51 #include "RConfigure.h"
55 kToggleListStart = 2000,
56 kUserFunctionStart = 3000
60 ClassImp(TRootContextMenu);
65 TRootContextMenu::TRootContextMenu(TContextMenu *c,
const char *)
66 : TGPopupMenu(gClient->GetDefaultRoot()), TContextMenuImp(c)
71 AddInput(kButtonPressMask | kButtonReleaseMask);
72 gROOT->GetListOfCleanups()->Add(
this);
80 TRootContextMenu::~TRootContextMenu()
82 gROOT->GetListOfCleanups()->Remove(
this);
84 if (fTrash) fTrash->Delete();
91 void TRootContextMenu::DisplayPopup(Int_t x, Int_t y)
93 if (fClient->IsEditable())
return;
96 if (fEntryList) fEntryList->Delete();
98 if (fTrash) fTrash->Delete();
109 CreateMenu(fContextMenu->GetSelectedObject());
111 int xx, yy, topx = 0, topy = 0;
114 if (fContextMenu->GetSelectedCanvas())
115 gVirtualX->GetGeometry(fContextMenu->GetSelectedCanvas()->GetCanvasID(),
126 TGWindow *parent = 0;
127 if (TVirtualPad *pad = fContextMenu->GetSelectedCanvas())
128 parent = dynamic_cast<TGWindow *>(pad->GetCanvasImp());
129 else if ((pad = fContextMenu->GetSelectedPad()) && pad->GetCanvasImp())
130 parent = dynamic_cast<TGWindow *>(pad->GetCanvasImp());
131 else if (TBrowser *
const browser = fContextMenu->GetBrowser())
132 parent = dynamic_cast<TGWindow *>(browser->GetBrowserImp());
135 gVirtualX->SetWMTransientHint(GetId(), parent->GetId());
138 PlaceMenu(xx, yy, kTRUE, kTRUE);
141 Resize(GetDefaultWidth()+5, GetDefaultHeight());
149 TGPopupMenu * TRootContextMenu::FindHierarchy(
const char *commentstring, TString & last_component)
151 TString cmd(commentstring);
154 TGPopupMenu *currentMenu = 0;
159 if ((opt_ptr=cmd.Index(
"*MENU={")) != kNPOS ||
160 (opt_ptr=cmd.Index(
"*SUBMENU={"))!= kNPOS ||
161 (opt_ptr=cmd.Index(
"*TOGGLE={")) != kNPOS ) {
163 Ssiz_t start = cmd.Index(
"{",opt_ptr) + 1;
164 Ssiz_t end = cmd.Index(
"}",start);
165 option = cmd(start,end - start);
168 TObjArray * array = option.Tokenize(
";");
171 while((obj = iter())) {
172 TString token(obj->GetName());
173 if (token.Index(
"Hierarchy=\"") != kNPOS) {
174 Ssiz_t tstart = token.Index(
"\"") + 1;
175 Ssiz_t tend = token.Index(
"\"",tstart+1);
176 if (tend == kNPOS)
continue;
177 hierarchy = token(tstart,tend - tstart);
185 TObjArray * array = hierarchy.Tokenize(
"/");
187 TObject *obj = iter();
189 last_component = obj->GetName();
193 TIter next(currentMenu->GetListOfEntries());
195 while ((ptr = (TGMenuEntry *) next()) &&
196 (ptr->GetType() != kMenuPopup ||
197 last_component.CompareTo(ptr->GetName()))) { }
199 currentMenu = ptr->GetPopup();
201 TGPopupMenu *r =
new TGPopupMenu(gClient->GetDefaultRoot());
204 TIter next2(currentMenu->GetListOfEntries());
206 while ((ptr2 = (TGMenuEntry *) next2()) &&
207 (ptr2->GetType() != kMenuPopup ||
208 last_component.CompareTo(ptr2->GetName()) > 0 )) { }
210 currentMenu->AddPopup(last_component, r,ptr2);
213 last_component = obj->GetName();
225 void TRootContextMenu::AddEntrySorted(TGPopupMenu *currentMenu,
const char *s, Int_t
id,
void *ud,
226 const TGPicture *p , Bool_t sorted)
228 TGMenuEntry *ptr2 = 0;
230 TIter next(currentMenu->GetListOfEntries());
232 while ((ptr2 = (TGMenuEntry *) next()) &&
233 (ptr2->GetType() != kMenuEntry ||
234 strcmp(ptr2->GetName(), s)<0 )) { }
236 currentMenu->AddEntry(s,
id,ud,p,ptr2);
242 void TRootContextMenu::CreateMenu(TObject *
object)
244 if (!
object || fClient->IsEditable())
return;
246 int entry = 0, toggle = kToggleStart, togglelist = kToggleListStart;
247 int userfunction = kUserFunctionStart;
250 AddLabel(fContextMenu->CreatePopupTitle(
object));
254 TList *menuItemList =
object->IsA()->GetMenuList();
256 TClassMenuItem *menuItem;
257 TIter nextItem(menuItemList);
259 while ((menuItem = (TClassMenuItem*) nextItem())) {
260 switch (menuItem->GetType()) {
261 case TClassMenuItem::kPopupSeparator:
263 TGMenuEntry *last = (TGMenuEntry *)GetListOfEntries()->Last();
264 if (last && last->GetType() != kMenuSeparator)
268 case TClassMenuItem::kPopupStandardList:
273 TList *methodList =
new TList;
274 object->IsA()->GetMenuItems(methodList);
277 TClass *classPtr = 0;
278 TIter next(methodList);
279 Bool_t needSep = kFALSE;
281 while ((method = (TMethod*) next())) {
282 if (classPtr != method->GetClass()) {
284 classPtr = method->GetClass();
288 EMenuItemKind menuKind = method->IsMenuItem();
289 TGPopupMenu *currentMenu = 0;
290 TString last_component;
295 currentMenu = FindHierarchy(method->GetCommentString(),last_component);
296 if (needSep && currentMenu ==
this) {
300 AddEntrySorted(currentMenu,last_component.Length() ? last_component.Data() : method->GetName(), entry++, method,0,currentMenu !=
this);
303 if ((m = method->FindDataMember())) {
306 currentMenu = FindHierarchy(method->GetCommentString(),last_component);
308 if (m->GetterMethod()) {
309 TGPopupMenu *r =
new TGPopupMenu(gClient->GetDefaultRoot());
310 if (needSep && currentMenu ==
this) {
314 if (last_component.Length()) {
315 currentMenu->AddPopup(last_component, r);
317 currentMenu->AddPopup(method->GetName(), r);
320 TIter nxt(m->GetOptions());
322 while ((it = (TOptionListItem*) nxt())) {
323 const char *name = it->fOptName;
324 Long_t val = it->fValue;
326 TToggle *t =
new TToggle;
327 t->SetToggledObject(
object, method);
331 r->AddEntry(name, togglelist++, t);
333 r->CheckEntry(togglelist-1);
336 if (needSep && currentMenu ==
this) {
340 AddEntrySorted(currentMenu,last_component.Length() ? last_component.Data() : method->GetName(), entry++, method,0,currentMenu !=
this);
347 TToggle *t =
new TToggle;
348 t->SetToggledObject(
object, method);
352 currentMenu = FindHierarchy(method->GetCommentString(),last_component);
353 if (needSep && currentMenu ==
this) {
357 AddEntrySorted(currentMenu,last_component.Length() ? last_component.Data() : method->GetName(), toggle++, t,0,currentMenu !=
this);
358 if (t->GetState()) currentMenu->CheckEntry(toggle-1);
369 case TClassMenuItem::kPopupUserFunction:
371 const char* menuItemTitle = menuItem->GetTitle();
372 if (menuItem->IsToggle()) {
374 object->IsA()->GetMethodWithPrototype(menuItem->GetFunctionName(),menuItem->GetArgs());
376 TToggle *t =
new TToggle;
377 t->SetToggledObject(
object, method);
381 if (strlen(menuItemTitle)==0) menuItemTitle = method->GetName();
382 AddEntry(menuItemTitle, toggle++, t);
383 if (t->GetState()) CheckEntry(toggle-1);
386 if (strlen(menuItemTitle)==0) menuItemTitle = menuItem->GetFunctionName();
387 AddEntry(menuItemTitle,userfunction++,menuItem);
401 void TRootContextMenu::Dialog(TObject *
object, TMethod *method)
403 Dialog(
object,(TFunction*)method);
411 void TRootContextMenu::Dialog(TObject *
object, TFunction *
function)
415 if (!
function)
return;
418 if (fContextMenu->GetSelectedMenuItem())
419 selfobjpos = fContextMenu->GetSelectedMenuItem()->GetSelfObjectPos();
420 else selfobjpos = -1;
423 if (fContextMenu->GetSelectedCanvas()) {
424 TCanvas *c = (TCanvas *) fContextMenu->GetSelectedCanvas();
428 if (c->GetCanvasImp()->IsA()->InheritsFrom(TGFrame::Class())) {
429 w = fClient->GetWindowById(gVirtualX->GetWindowID(c->GetCanvasID()));
430 if (!w) w = (TRootCanvas *) c->GetCanvasImp();
432 w = gClient->GetDefaultRoot();
434 }
else if (fContextMenu->GetBrowser()) {
435 TBrowser *b = (TBrowser *) fContextMenu->GetBrowser();
436 w = (TRootBrowser *) b->GetBrowserImp();
438 w = gClient->GetDefaultRoot();
440 fDialog =
new TRootDialog(
this, w, fContextMenu->CreateDialogTitle(
object,
function));
444 TMethodArg *argument = 0;
446 TIter next(function->GetListOfMethodArgs());
449 while ((argument = (TMethodArg *) next())) {
451 if (selfobjpos != argpos) {
452 const char *argname = fContextMenu->CreateArgumentTitle(argument);
453 const char *type = argument->GetTypeName();
454 TDataType *datatype = gROOT->GetType(type);
455 const char *charstar =
"char*";
459 strlcpy(basictype, datatype->GetTypeName(), 32);
461 TClass *cl = TClass::GetClass(type);
462 if (strncmp(type,
"enum", 4) && (cl && !(cl->Property() & kIsEnum)))
463 Warning(
"Dialog",
"data type is not basic type, assuming (int)");
464 strlcpy(basictype,
"int", 32);
467 if (strchr(argname,
'*')) {
468 strlcat(basictype,
"*",32);
469 if (!strncmp(type,
"char", 4) || !strncmp(type,
"Option_t", 8))
471 else if (strstr(argname,
"[default:")) {
479 TDataMember *m = argument->GetDataMember();
480 if (m &&
object && m->GetterMethod(object->IsA())) {
486 if (!strncmp(basictype,
"char*", 5)) {
488 m->GetterMethod()->Execute(
object,
"", &tdefval);
489 strlcpy(val, tdefval,
sizeof(val));
490 }
else if (!strncmp(basictype,
"float", 5) ||
491 !strncmp(basictype,
"double", 6)) {
493 m->GetterMethod()->Execute(
object,
"", ddefval);
494 snprintf(val,256,
"%g", ddefval);
495 }
else if (!strncmp(basictype,
"char", 4) ||
496 !strncmp(basictype,
"bool", 4) ||
497 !strncmp(basictype,
"int", 3) ||
498 !strncmp(basictype,
"long", 4) ||
499 !strncmp(basictype,
"short", 5)) {
501 m->GetterMethod()->Execute(
object,
"", ldefval);
502 snprintf(val,256,
"%li", ldefval);
509 if ((opt = m->GetOptions())) {
510 Warning(
"Dialog",
"option menu not yet implemented");
512 TMotifOptionMenu *o=
new TMotifOptionMenu(argname);
514 TOptionListItem *it = 0;
515 while ((it = (TOptionListItem*) nextopt())) {
516 char *name = it->fOptName;
517 char *label = it->fOptLabel;
518 Long_t value = it->fValue;
519 if (value != -9999) {
521 snprintf(val,256,
"%li", value);
522 o->AddItem(name, val);
524 o->AddItem(name, label);
531 fDialog->Add(argname, val, type);
536 const char *tval = argument->GetDefault();
537 if (tval && strlen(tval)) {
539 strlcpy(val, tval + (tval[0] ==
'"' ? 1 : 0),
sizeof(val));
540 if (val[strlen(val)-1] ==
'"')
541 val[strlen(val)-1]= 0;
543 fDialog->Add(argname, val, type);
555 void TRootContextMenu::DrawEntry(TGMenuEntry *entry)
558 static int max_ascent = 0, max_descent = 0;
560 TGPopupMenu::DrawEntry(entry);
562 if (entry->GetType() == kMenuEntry && (entry->GetStatus() & kMenuActiveMask)) {
563 if (max_ascent == 0) {
564 gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
566 offset = (entry->GetEh() - (max_ascent + max_descent)) / 2;
567 ty = entry->GetEy() + max_ascent + offset - 1;
569 s.Draw(fId, fSelGC, fMenuWidth-12, ty);
576 Bool_t TRootContextMenu::HandleButton(Event_t *event)
581 if ((event->fType == kButtonRelease) && (event->fX >= (Int_t)(fMenuWidth-15)) &&
582 (event->fX <= (Int_t)fMenuWidth)) {
584 if (fHasGrab) gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
587 TFunction *
function = 0;
588 if (
id < kToggleStart) {
589 TMethod *m = (TMethod *)ud;
590 function = (TFunction *)m;
591 }
else if (
id >= kToggleStart &&
id < kUserFunctionStart) {
592 TToggle *t = (TToggle *)ud;
593 TMethodCall *mc = (TMethodCall *)t->GetSetter();
594 function = (TFunction *)mc->GetMethod();
596 TClassMenuItem *mi = (TClassMenuItem *)ud;
597 function = gROOT->GetGlobalFunctionWithPrototype(mi->GetFunctionName());
600 fContextMenu->SetMethod(
function);
605 return TGPopupMenu::HandleButton(event);
611 Bool_t TRootContextMenu::HandleCrossing(Event_t *event)
613 if (event->fType == kLeaveNotify) {
617 return TGPopupMenu::HandleCrossing(event);
623 Bool_t TRootContextMenu::HandleMotion(Event_t *event)
625 static int toggle = 0;
626 static Cursor_t handCur = kNone, rightCur = kNone;
627 static UInt_t mask = kButtonPressMask | kButtonReleaseMask | kPointerMotionMask;
629 if (handCur == kNone)
630 handCur = gVirtualX->CreateCursor(kHand);
631 if (rightCur == kNone)
632 rightCur = gVirtualX->CreateCursor(kArrowRight);
634 if (event->fType == kLeaveNotify) {
635 gVirtualX->ChangeActivePointerGrab(fId, mask, rightCur);
640 if ((event->fX >= (Int_t)(fMenuWidth-15)) && (event->fX <= (Int_t)fMenuWidth) &&
641 fCurrent && (fCurrent->GetType() == kMenuEntry)) {
643 gVirtualX->ChangeActivePointerGrab(fId, mask, handCur);
649 gVirtualX->ChangeActivePointerGrab(fId, mask, rightCur);
653 return TGPopupMenu::HandleMotion(event);
659 void TRootContextMenu::OnlineHelp()
663 TString url = gEnv->GetValue(
"Browser.StartUrl",
"http://root.cern.ch/root/html/");
664 if (url.EndsWith(
".html", TString::kIgnoreCase)) {
665 if (url.Last(
'/') != kNPOS)
666 url.Remove(url.Last(
'/'));
668 if (!url.EndsWith(
"/")) {
671 TObject *obj = fContextMenu->GetSelectedObject();
673 clname = obj->ClassName();
674 if (fContextMenu->GetSelectedMethod()) {
675 TString smeth = fContextMenu->GetSelectedMethod()->GetName();
676 TMethod *method = obj->IsA()->GetMethodAllAny(smeth.Data());
677 if (method) clname = method->GetClass()->GetName();
689 if (fDialog)
delete fDialog;
691 cmd = TString::Format(
"new TGHtmlBrowser(\"%s\", 0, 900, 300);", url.Data());
692 gROOT->ProcessLine(cmd.Data());
699 Bool_t TRootContextMenu::ProcessMessage(Long_t msg, Long_t parm1, Long_t parm2)
702 if (GetContextMenu()->GetSelectedPad()) {
703 savedPad.SetObject(gPad);
704 gPad = GetContextMenu()->GetSelectedPad();
707 switch (GET_MSG(msg)) {
711 switch (GET_SUBMSG(msg)) {
715 if (parm1 < kToggleStart) {
716 TMethod *m = (TMethod *) parm2;
717 GetContextMenu()->Action(m);
718 }
else if (parm1 >= kToggleStart && parm1 < kToggleListStart) {
719 TToggle *t = (TToggle *) parm2;
720 GetContextMenu()->Action(t);
721 }
else if (parm1 >= kToggleListStart && parm1<kUserFunctionStart) {
722 TToggle *t = (TToggle *) parm2;
723 if (t->GetState() == 0)
726 TClassMenuItem *mi = (TClassMenuItem*)parm2;
727 GetContextMenu()->Action(mi);
733 const char *args = fDialog->GetParameters();
734 GetContextMenu()->Execute((
char *)args);
739 const char *args = fDialog->GetParameters();
740 GetContextMenu()->Execute((
char *)args);
758 switch (GET_SUBMSG(msg)) {
762 const char *args = fDialog->GetParameters();
763 GetContextMenu()->Execute((
char *)args);
778 if (savedPad.GetObject()) gPad = (TVirtualPad*) savedPad.GetObject();
787 void TRootContextMenu::RecursiveRemove(TObject *obj)
790 if (obj == fContextMenu->GetSelectedCanvas())
791 fContextMenu->SetCanvas(0);
792 if (obj == fContextMenu->GetSelectedPad())
793 fContextMenu->SetPad(0);
794 if (obj == fContextMenu->GetSelectedObject()) {
797 fContextMenu->SetObject(0);
799 gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);