TGPopupMenu->Connect(... ) issues

Hello,

I would like to make a simple context menu for entries in a TGListTree object. The idea being when you right click on an object, it gives you a list of options related to that object… standard context menu.

Looking through the gui examples, I found many TGPopupMenu objects, but no standalone ones, only those added to MenuBars.

All of them use the ->Connect(“Activated(Int_t)”…) method to handle the user clicking on a menu. So I tried doing that with my standalone popup menu, created with the gClient->GetDefaultRoot() window as its parent, and instructed the TGListTree to handle a Clicked(Int_t) event with button = 3 (right click) to call a method which pops up the TGPopupMenu, which is a member object of the main frame. (I tried it as a heap object as well, same behavior).

Basically what I observe is that connecting the Highlighted signal produces expected behavior (the function it connects to is called with the right parameter), but that the PoppedUp and Clicked signals don’t connect properly (or I’ve not linked the signals correctly). They don’t do anything as far as I can tell, in this context.

Perhaps someone could tell me what I’m doing wrong in the code below that’s causing it not to work as I expect?

Also, am I correct that there is no gui tutorial that demonstrates this, a context menu with signals connected not as part of a menu bar? (customContextMenu.C is related to this, however it just modifies a context list connected elsewhere, rather than connecting its own items). Perhaps such a tutorial could be added? Or is there a reason there is no example for this?

I’m sure there is the answer somewhere deep in the source for the context menus we see all over the place but I haven’t been able to find what I’m looking for. Basically, the example would create an widget, create a popupmenu, link right clicking the widget to popping open the menu, connecting clicking the menu to handling the click, and finally closing the menu when done…

Thanks,
Joe

[code]#include <TApplication.h>
#include <TGClient.h>
#include <TGListTree.h>
#include <TGMenu.h>

class MyMainFrame : public TGMainFrame {

private:
TGListTree fLT;
TGPopupMenu
fContext;

public:
MyMainFrame (const TGWindow p, int w, int h);
virtual ~MyMainFrame();
void DoExit();
void DoSelect();
void HandleMenu(Int_t);
void HandleHighlight(Int_t);
void HandlePopup();
void ListClicked(TGListTreeItem
, Int_t,Int_t x, Int_t y);
void PrintSelected();

ClassDef(MyMainFrame, 0)

};

void MyMainFrame::DoSelect() {
cout << “slot DoSelect()\n”;
}

void MyMainFrame::DoExit() {
gApplication->Terminate(0);
}

MyMainFrame::MyMainFrame(const TGWindow *p, int w, int h) : TGMainFrame(p,w,h) {

TGCanvas* canvas = new TGCanvas (this,100,200);
fLT = new TGListTree(canvas,kHorizontalFrame);
//fLT->Associate(this);
TGListTreeItem* item = fLT->AddItem(0,"hi",NULL);
AddFrame(canvas);
fLT->Connect("Clicked(TGListTreeItem*, Int_t, Int_t, Int_t)","MyMainFrame",this,"ListClicked(TGListTreeItem*, Int_t, Int_t, Int_t)");

MapSubwindows();

MapWindow();

}

MyMainFrame::~MyMainFrame() {
if(fButton) delete fButton;
}
void popuptest() {

}

void MyMainFrame::ListClicked(TGListTreeItem* item, Int_t button, Int_t x, Int_t y) {
cout << "ListClicked, item " << item << " button " << button << " coords " << x << ", " << y << endl;
if(button !=3) return;
if(button==3) cout << “Rightclick.” << endl;
//TGPopupMenu* fContext = new TGPopupMenu(gClient->GetDefaultRoot(),20,20);
fContext = new TGPopupMenu(gClient->GetDefaultRoot(),20,20);
//fContext = new TGPopupMenu(this,20,20);
//TGPopupMenu* fContext = new TGPopupMenu(this,20,20);
//fContext->Associate(this);
fContext->AddEntry(“choice 1”,1);
fContext->AddEntry(“choice 2”,2);
fContext->Connect(“Activated(Int_t)”,“MyMainFrame”,this,“HandleMenu(Int_t)”);
fContext->Connect(“PoppedUp()”,“MyMainFrame”,this,“HandlePopup()”);
fContext->Connect(“Highlighted(Int_t)”,“MyMainFrame”,this,“HandleHighlight(Int_t)”);

fContext->PlaceMenu(x,y,kFALSE,kFALSE);
//fContext->Activate(1);

}

void MyMainFrame::HandlePopup(Int_t index) {
cout << “HandlePopup entered” << endl;
}

void MyMainFrame::HandleHighlight(Int_t index) {
cout << "HandleHighlight entered with id " << index << endl;
}

void MyMainFrame::HandleMenu(Int_t index) {
cout << "HandleMenu entered with index " << index << endl;
}

void popuptest() {
new MyMainFrame(gClient->GetRoot(), 200,200);
}[/code]

A quick update… (how often does this happen to you guys, that you discover the answer to your question 3 hours after coming across the issue, but 1 minute after asking someone else about it?)

It seems that the GrabPointer parameter to the PlaceMenu function is important, and when it’s false, you can only Highlight.

So if in my code one changes:

to

then a reasonable behavior results (right click opens the menu, dragging right click over an entry emits Highlighted, releasing rightclick over an entry emits Activated. (For the record, I was very confused by the description of this parameter in the online documentation).

I still don’t see PoppedUp or Down, however.

I was searching roottalk again to see if the capacity to easily add a context menu to TGListTreeItem’s was ever added into root, and didn’t see anything about it (only some requests for it).

Is there anything new on this? There is a way to do it which is a workaround (but does work), if anyone would like to know it I’ll put together a small example and attach it here (and perhaps some kind of small tutorial could be added into the gui tutorials section?).

The way to do it involves having a global TGPopupMenu which has its entries deleted/created when a TGListTreeItem is right-clicked, then popped up on the x/y location of the right click.

Joe

Hi,

You should use TGListTree::Clicked() signal. See for example how it is implemented in TGFileBrowser.cxx

[code]…
fListTree->Connect(“Clicked(TGListTreeItem *, Int_t, Int_t, Int_t)”,
“TGFileBrowser”, this, “Clicked(TGListTreeItem *, Int_t, Int_t, Int_t)”);

//______________________________________________________________________________
void TGFileBrowser::Clicked(TGListTreeItem *item, Int_t btn, Int_t x, Int_t y)
{

if (btn == kButton3)
fContextMenu->Popup(x, y, obj, fBrowser);
…[/code]
Cheers, Bertrand.

Thanks for that; I hadn’t been able to find that before.

Joe