Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TGtk4ContextMenu.cxx
Go to the documentation of this file.
1// Author: Sergey Linev 13/08/2026
2
3/*************************************************************************
4 * Copyright (C) 1995-2026, Rene Brun and Fons Rademakers. *
5 * All rights reserved. *
6 * *
7 * For the licensing terms see $ROOTSYS/LICENSE. *
8 * For the list of contributors see $ROOTSYS/README/CREDITS. *
9 *************************************************************************/
10
11
12/** \class TGtk4ContextMenu
13 \ingroup gtk4canvas
14
15This class provides an interface to context-sensitive popup menus.
16These menus pop up when the user hits the right mouse button, and
17are destroyed when the menu pops downs.
18*/
19
20
21#include "TGtk4ContextMenu.h"
22
23#include "TROOT.h"
24#include "TContextMenu.h"
25#include "TCanvas.h"
26#include "TColor.h"
27#include "TMethod.h"
28#include "TDataMember.h"
29#include "TToggle.h"
30#include "TClassMenuItem.h"
31#include "TAttText.h"
32#include "TAttMarker.h"
33
34#include "TGtk4Canvas.h"
35#include "Gtk4DrawArea.h"
36#include "Gtk4MethodDialog.h"
37
38#include <iostream>
39
41 kToggleStart = 1000, // first id of toggle menu items
42 kToggleListStart = 2000, // first id of toggle list menu items
43 kUserFunctionStart = 3000 // first id of user added functions/methods, etc...
44};
45
46////////////////////////////////////////////////////////////////////////////////
47/// Create context menu.
48
51{
52 gROOT->GetListOfCleanups()->Add(this);
53}
54
55////////////////////////////////////////////////////////////////////////////////
56/// Delete a context menu.
57
59{
60 gROOT->GetListOfCleanups()->Remove(this);
61 fTrash.Delete();
62}
63
64////////////////////////////////////////////////////////////////////////////////
65/// Display context popup menu for currently selected object.
66
68{
69 // add menu items to popup menu
70 // CreateMenu(fContextMenu->GetSelectedObject());
71
72 auto object = fContextMenu->GetSelectedObject();
73 if (!object)
74 return;
75
76 fCustomArg.clear();
77 fTrash.Delete();
78
79
80 auto canv = dynamic_cast<TCanvas *>(fContextMenu->GetSelectedCanvas());
81 auto canvimp = dynamic_cast<ROOT::Experimental::TGtk4Canvas *>(canv->GetCanvasImp());
82 auto widget = canvimp->GetDrawArea();
83
84// QPoint screenPos = widget->mapToGlobal(widget->rect().topLeft());
85
86// QMenu menu;
87// QSignalMapper map;
88
89// QObject::connect(&map, &QSignalMapper::mappedInt,
90// this, &TGtk4ContextMenu::executeMenu);
91
92 auto action_group = Gio::SimpleActionGroup::create();
93
94 action_group->add_action_with_parameter(
95 "action",
96 Glib::VariantType("i"), // Expected parameter type (int32)
97 [this](const Glib::VariantBase& parameter) {
98 if (auto var = Glib::VariantBase::cast_dynamic<Glib::Variant<int>>(parameter)) {
99 int value = var.get();
100 std::cout << "Action triggered with integer value: " << value << std::endl;
102 }
103 }
104 );
105
106 auto menu_model = Gio::Menu::create();
107
108 auto current_section = Gio::Menu::create();
109
110
111 auto addSeparator = [&menu_model, &current_section]() {
112 menu_model->append_section(current_section);
113 current_section = Gio::Menu::create();
114 };
115
116 auto addMenuAction = [&current_section, &action_group, this](const TString &text, int id, void *arg = nullptr, int checked = 0) {
117 bool enabled = true;
118 if ((text == "DrawClone") || (text == "DrawClass") || (text == "Inspect") ||
119 (text == "SetShowProjectionX") || (text == "SetShowProjectionY") ||
120 (text == "DrawPanel") || (text == "FitPanel"))
121 enabled = false;
122
123
124 if (checked != 0) {
125 TString action_name = TString::Format("toggle-item-%d", id);
126 auto action = Gio::SimpleAction::create_bool(action_name.Data(), checked > 0);
127 action->signal_activate().connect([action,this, id](const Glib::VariantBase &) {
128 bool current;
129 action->get_state(current);
130 action->set_state(Glib::Variant<bool>::create(!current));
131 std::cout << "Action triggered with integer value: " << id << std::endl;
132 executeMenu(id);
133 });
134 action->set_enabled(enabled);
135 action_group->add_action(action);
136
137 action_name.Prepend("context.");
138 auto item = Gio::MenuItem::create(text.Data(), action_name.Data());
139 current_section->append_item(item);
140 } else if (enabled) {
141 auto item = Gio::MenuItem::create(text.Data(), "");
142 item->set_action_and_target("context.action", Glib::Variant<int>::create(id));
143 current_section->append_item(item);
144 } else {
145 // just refer to non-existing action
146 current_section->append(text.Data(), "context.dummy");
147 }
148
149 fCustomArg[id] = arg;
150 };
151
152 TString title = fContextMenu->CreatePopupTitle(object);
153
154 bool last_separ = true;
155 int entry = 0, toggle = kToggleStart, togglelist = kToggleListStart;
156 int userfunction = kUserFunctionStart;
157
158 // Get list of menu items from the selected object's class
159 TList *menuItemList = object->IsA()->GetMenuList();
160
161 TIter nextItem(menuItemList);
162
163 while (auto menuItem = (TClassMenuItem*) nextItem()) {
164 switch (menuItem->GetType()) {
166 if (!last_separ)
167 addSeparator();
168 last_separ = true;
169 break;
170 }
172 // Standard list of class methods. Rebuild from scratch.
173 // Get linked list of objects menu items (i.e. member functions
174 // with the token *MENU in their comment fields.
175 TList *methodList = new TList;
176 object->IsA()->GetMenuItems(methodList);
177
178 TMethod *method;
179 TClass *classPtr = nullptr;
180 TIter next(methodList);
181 Bool_t needSep = kFALSE;
182
183 while ((method = (TMethod*) next())) {
184 if (classPtr != method->GetClass()) {
185 needSep = kTRUE;
186 classPtr = method->GetClass();
187 }
188
189 EMenuItemKind menuKind = method->IsMenuItem();
190 TString last_component;
191
192 switch (menuKind) {
193 case kMenuDialog:
194 // search for arguments to the MENU statement
195 if (needSep) {
196 addSeparator();
197 needSep = kFALSE;
198 }
199 addMenuAction(method->GetName(), entry++, method);
200 break;
201 case kMenuSubMenu:
202 if (auto m = method->FindDataMember()) {
203 if (needSep) {
204 addSeparator();
205 needSep = kFALSE;
206 }
207
208 // TODO: implement selection menu
209 if (m->GetterMethod()) {
210 // QMenu *r = menu.addMenu(method->GetName());
211 TIter nxt(m->GetOptions());
212 while (auto it = (TOptionListItem*) nxt()) {
213 TToggle *t = new TToggle;
214 t->SetToggledObject(object, method);
215 t->SetOnValue(it->fValue);
216 fTrash.Add(t);
217
218 // TODO: implement checked state
219 addMenuAction(it->fOptName.Data(), togglelist++, t, t->GetState() ? 1 : -1);
220 }
221 } else {
222 addMenuAction(method->GetName(), entry++, method);
223 }
224 }
225 break;
226
227 case kMenuToggle: {
228 if (needSep) {
229 addSeparator();
230 needSep = kFALSE;
231 }
232
233 TToggle *t = new TToggle;
234 t->SetToggledObject(object, method);
235 t->SetOnValue(1);
236 fTrash.Add(t);
237
238 addMenuAction(method->GetName(), toggle++, t, t->GetState() ? 1 : -1);
239 break;
240 }
241 default:
242 break;
243 }
244 }
245 delete methodList;
246 }
247 break;
249 const char* menuItemTitle = menuItem->GetTitle();
250 if (menuItem->IsToggle()) {
251 TMethod* method = object->IsA()->GetMethodWithPrototype(menuItem->GetFunctionName(),menuItem->GetArgs());
252 if (method) {
253 TToggle *t = new TToggle;
254 t->SetToggledObject(object, method);
255 t->SetOnValue(1);
256 fTrash.Add(t);
257
258 if (strlen(menuItemTitle)==0)
259 menuItemTitle = method->GetName();
260 addMenuAction(menuItemTitle, toggle++, t, t->GetState() ? 1 : -1);
261 }
262 } else {
263 if (strlen(menuItemTitle)==0)
264 menuItemTitle = menuItem->GetFunctionName();
265 addMenuAction(menuItemTitle, userfunction++, menuItem);
266 }
267 break;
268 }
269
270 default:
271 break;
272 }
273 }
274
275 widget->insert_action_group("context", action_group);
276
277 widget->ShowContextMenu(menu_model, title.Data(), x, y);
278}
279
280////////////////////////////////////////////////////////////////////////////////
281/// Create dialog object with OK and Cancel buttons. This dialog
282/// prompts for the arguments of "method".
283
285{
286 Dialog(object, (TFunction *)method);
287}
288
289////////////////////////////////////////////////////////////////////////////////
290/// Create dialog object with OK and Cancel buttons. This dialog
291/// prompts for the arguments of "function".
292/// function may be a global function or a method
293
295{
296 auto widget = new Gtk4MethodDialog(300, 300);
297
298 widget->methodDialog(fContextMenu, object, func);
299}
300
301////////////////////////////////////////////////////////////////////////////////
302/// Handle remove of some ROOT objects
303
305{
306 if (obj == fContextMenu->GetSelectedCanvas())
307 fContextMenu->SetCanvas(nullptr);
308 if (obj == fContextMenu->GetSelectedPad())
309 fContextMenu->SetPad(nullptr);
310 if (obj == fContextMenu->GetSelectedObject()) {
311 // if the object being deleted is the one selected,
312 // ungrab the mouse pointer and terminate (close) the menu
313 fContextMenu->SetObject(nullptr);
314 }
315}
316
317
318////////////////////////////////////////////////////////////////////////////////
319/// Execute specified menu item
320
322{
323 if (id < 0)
324 return;
325 void *ud = fCustomArg[id];
326
327 if (ud) {
328 // retrieve the highlighted function
329 TFunction *function = nullptr;
330 if (id < kToggleStart) {
331 TMethod *m = (TMethod *)ud;
332 function = (TFunction *)m;
333 } else if (id >= kToggleStart && id < kUserFunctionStart) {
334 TToggle *t = (TToggle *)ud;
335 TMethodCall *mc = (TMethodCall *)t->GetSetter();
336 function = (TFunction *)mc->GetMethod();
337 } else {
338 TClassMenuItem *mi = (TClassMenuItem *)ud;
339 function = gROOT->GetGlobalFunctionWithPrototype(mi->GetFunctionName());
340 }
341 if (function)
342 fContextMenu->SetMethod(function);
343 }
344
345 if (id < kToggleStart) {
346 auto m = (TMethod *) ud;
347
348 /*
349 if (!strcmp(m->GetName(), "SetLineAttributes")) {
350 auto attline = dynamic_cast<TAttLine *>(fContextMenu->GetSelectedObject());
351 if (attline) {
352 auto widget = new Gtk4MethodDialog(300, 300);
353 widget->attLineDialog(attline);
354 }
355 } else if (!strcmp(m->GetName(), "SetFillAttributes")) {
356 auto attfill = dynamic_cast<TAttFill *>(fContextMenu->GetSelectedObject());
357 if (attfill) {
358 auto widget = new Gtk4MethodDialog(300, 300);
359 widget->attFillDialog(attfill);
360 }
361 } else if (!strcmp(m->GetName(), "SetTextAttributes")) {
362 auto atttext = dynamic_cast<TAttText *>(fContextMenu->GetSelectedObject());
363 if (atttext) {
364 auto widget = new Gtk4MethodDialog(300, 300);
365 widget->attTextDialog(atttext);
366 }
367 } else if (!strcmp(m->GetName(), "SetMarkerAttributes")) {
368 auto attmark = dynamic_cast<TAttMarker *>(fContextMenu->GetSelectedObject());
369 if (attmark) {
370 auto widget = new Gtk4MethodDialog(300, 300);
371 widget->attMarkerDialog(attmark);
372 }
373 } else {
374 */
376
377 } else if (id >= kToggleStart && id < kToggleListStart) {
378 TToggle *t = (TToggle *) ud;
380 } else if (id >= kToggleListStart && id < kUserFunctionStart) {
381 TToggle *t = (TToggle *) ud;
382 if (t->GetState() == 0)
383 t->SetState(1);
384 } else {
386 fContextMenu->Action(mi);
387 }
388}
#define c(i)
Definition RSha256.hxx:101
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char text
@ kToggleStart
@ kToggleListStart
@ kUserFunctionStart
EMenuItemKind
Definition TMethod.h:31
@ kMenuSubMenu
Definition TMethod.h:35
@ kMenuDialog
Definition TMethod.h:33
@ kMenuToggle
Definition TMethod.h:34
#define gROOT
Definition TROOT.h:417
Specialized dialog to enter arguments for method exection.
Gtk4DrawArea * GetDrawArea() const
Definition TGtk4Canvas.h:43
The Canvas class.
Definition TCanvas.h:23
Describes one element of the context menu associated to a class The menu item may describe.
virtual const char * GetFunctionName() const
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
TList * GetMenuList() const
Return the list of menu items associated with the class.
Definition TClass.cxx:4462
TMethod * GetMethodWithPrototype(const char *method, const char *proto, Bool_t objectIsConst=kFALSE, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch)
Find the method with a given prototype.
Definition TClass.cxx:4577
void GetMenuItems(TList *listitems)
Returns list of methods accessible by context menu.
Definition TClass.cxx:3937
This class provides an interface to GUI independent context sensitive popup menus.
TContextMenu * fContextMenu
This class provides an interface to context sensitive popup menus.
virtual void SetCanvas(TVirtualPad *c)
virtual TVirtualPad * GetSelectedCanvas()
virtual void Action(TObject *object, TMethod *method)
Action to be performed when this menu item is selected.
virtual TVirtualPad * GetSelectedPad()
virtual void SetPad(TVirtualPad *p)
virtual void SetMethod(TFunction *m)
virtual void SetObject(TObject *o)
virtual TObject * GetSelectedObject()
virtual const char * CreatePopupTitle(TObject *object)
Create title for popup menu.
Global functions class (global functions are obtained from CINT).
Definition TFunction.h:30
TGtk4ContextMenu(TContextMenu *c=nullptr, const char *name="ROOT Context Menu")
Create context menu.
~TGtk4ContextMenu() override
Delete a context menu.
void DisplayPopup(Int_t x, Int_t y) override
Display context popup menu for currently selected object.
void executeMenu(int id)
Execute specified menu item.
std::map< int, void * > fCustomArg
void RecursiveRemove(TObject *obj) override
Handle remove of some ROOT objects.
void Dialog(TObject *object, TMethod *method) override
Create dialog object with OK and Cancel buttons.
A doubly linked list.
Definition TList.h:38
void Add(TObject *obj) override
Definition TList.h:81
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:600
TClass * IsA() const override
Definition TList.h:115
Method or function calling interface.
Definition TMethodCall.h:37
TFunction * GetMethod()
Returns the TMethod describing the method to be executed.
Each ROOT class (see TClass) has a linked list of methods.
Definition TMethod.h:38
virtual TDataMember * FindDataMember()
Tries to guess DataMember from comment string and Method's name <==(only if 1 Argument!...
Definition TMethod.cxx:132
TClass * GetClass() const
Definition TMethod.h:55
EMenuItemKind IsMenuItem() const
Definition TMethod.h:56
TClass * IsA() const override
Definition TMethod.h:68
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
Mother of all ROOT objects.
Definition TObject.h:42
virtual const char * GetTitle() const
Returns title of object.
Definition TObject.cxx:506
Basic string class.
Definition TString.h:137
const char * Data() const
Definition TString.h:385
TString & Prepend(const char *cs)
Definition TString.h:683
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2460
This class defines toggling facility for both - object's method or variables.
Definition TToggle.h:49
virtual void SetOnValue(Long_t lon)
Definition TToggle.h:82
TMethodCall * GetSetter() const
return setter method request new for the TDataMember while it can be recreated at any time
Definition TToggle.cxx:167
virtual void SetToggledObject(TObject *obj, TMethod *anymethod)
Initializes it to toggle an object's datamember using this object's method.
Definition TToggle.cxx:116
virtual void SetState(Bool_t state)
Sets the value of toggle to fOnValue or fOffValue according to passed argument.
Definition TToggle.cxx:73
virtual Bool_t GetState()
Returns the state of Toggle according to its current value and fOnValue, returns true if they match.
Definition TToggle.cxx:60
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
TMarker m
Definition textangle.C:8