Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
drag_and_drop.C
Go to the documentation of this file.
1/// \file
2/// \ingroup tutorial_gui
3/// This tutorial illustrates how to use drag and drop within ROOT.
4/// Select a list tree item with a mouse press, drag it (move the mouse while keeping the mouse button pressed)
5/// and release the mouse button in any pad inside the canvas or in the top list tree item ("Base").
6/// When the button is released, the selected data is "dropped" at that location,
7/// displaying the object in the canvas or adding (copying) it in the list tree.
8///
9/// \macro_code
10///
11/// \author Bertrand Bellenot
12
13#include "TROOT.h"
14#include "TApplication.h"
15#include "TSystem.h"
16#include "TGFrame.h"
17#include "TGButton.h"
18#include "TGLabel.h"
19#include "TGMenu.h"
20#include "TGFileDialog.h"
21#include "TBrowser.h"
22#include "TRootEmbeddedCanvas.h"
23#include "TRootHelpDialog.h"
24#include "TCanvas.h"
25#include "TH1F.h"
26#include "TH2F.h"
27#include "TF2.h"
28#include "TGraph.h"
29#include "TImage.h"
30#include "TRandom.h"
31#include "TGMsgBox.h"
32#include "TGPicture.h"
33#include "TGListTree.h"
34#include "TObjString.h"
35#include "TMessage.h"
36#include "TTimer.h"
37#include "TGDNDManager.h"
38#include <cmath>
39
40const char gHelpDND[] = "\
41 Drag & Drop (DnD)\n\
42Drag and Drop support is implemented on Linux via Xdnd, the\n\
43drag and drop protocol for X window system, and on Windows\n\
44via the Clipboard.\n\
45Users can selects something in ROOT with a mouse press, drags\n\
46it (moves the mouse while keeping the mouse button pressed) and\n\
47releases the mouse button somewhere else. When the button is\n\
48released the selected data is \"dropped\" at that location. This\n\
49way, a histogram from an opened ROOT file in the browser can be\n\
50dragged to any TCanvas. A script file from the browser can be\n\
51dropped to a TGTextView or TGTextEdit widget in TGTextEditor.\n\
52On Linux, it is possible to drag objects between ROOT and an\n\
53external application. For example to drag a macro file from the\n\
54ROOT browser to the Kate editor. On Windows, drag and drop works\n\
55only within a single ROOT application, but it is possible to drag\n\
56from the Windows Explorer to ROOT (e.g. a picture file to a canvas\n\
57or a text file to a text editor).\n\
58";
59
60const char gReadyMsg[] = "Ready. You can drag list tree items to any \
61pad in the canvas, or to the \"Base\" folder of the list tree itself...";
62
63//----------------------------------------------------------------------
64
65class DNDMainFrame : public TGMainFrame {
66
67protected:
68 TRootEmbeddedCanvas *fEc; // embedded canvas
69 TGTextButton *fButtonExit; // "Exit" text button
70 TGMenuBar *fMenuBar; // main menu bar
71 TGPopupMenu *fMenuFile; // "File" popup menu entry
72 TGPopupMenu *fMenuHelp; // "Help" popup menu entry
73 TCanvas *fCanvas; // canvas
74 TGListTree *fListTree; // left list tree
75 TGListTreeItem *fBaseLTI; // base (root) list tree item
76 TGLabel *fStatus; // label used to display status
77 TGraph *fGraph; // TGraph object
78 TH1F *fHist1D; // 1D histogram
79 TH2F *fHist2D; // 2D histogram
80
81public:
82 DNDMainFrame(const TGWindow *p, int w, int h);
83 virtual ~DNDMainFrame();
84
85 void DoCloseWindow();
86 void HandleMenu(Int_t);
87 TObject *GetObject(const char *obj);
88 void DataDropped(TGListTreeItem *item, TDNDData *data);
89 void ResetStatus();
90
91 // ClassDef(DNDMainFrame, 0); // Mainframe for Drag and Drop demo
92};
93
94enum EMyMessageTypes {
95 M_FILE_OPEN,
96 M_FILE_BROWSE,
97 M_FILE_NEWCANVAS,
98 M_FILE_CLOSEWIN,
99 M_FILE_EXIT,
100 M_HELP_ABOUT
101};
102
103const char *dnd_types[] = {"ROOT files", "*.root", "ROOT macros", "*.C", "All files", "*", 0, 0};
104
105static Atom_t gRootObj = kNone;
106
107//______________________________________________________________________________
108DNDMainFrame::DNDMainFrame(const TGWindow *p, int w, int h) : TGMainFrame(p, w, h), fGraph(0), fHist1D(0), fHist2D(0)
109
110{
111 // Constructor.
112
113 SetCleanup(kDeepCleanup);
114 const TGPicture *pic = 0;
115 TGListTreeItem *item;
116 fMenuBar = new TGMenuBar(this, 35, 50, kHorizontalFrame);
117
118 fMenuFile = new TGPopupMenu(gClient->GetRoot());
119 fMenuFile->AddEntry(" &Open...\tCtrl+O", M_FILE_OPEN, 0, gClient->GetPicture("bld_open.png"));
120 fMenuFile->AddEntry(" &Browse...\tCtrl+B", M_FILE_BROWSE);
121 fMenuFile->AddEntry(" &New Canvas\tCtrl+N", M_FILE_NEWCANVAS);
122 fMenuFile->AddEntry(" &Close Window\tCtrl+W", M_FILE_CLOSEWIN);
123 fMenuFile->AddSeparator();
124 fMenuFile->AddEntry(" E&xit\tCtrl+Q", M_FILE_EXIT, 0, gClient->GetPicture("bld_exit.png"));
125 fMenuFile->Connect("Activated(Int_t)", "DNDMainFrame", this, "HandleMenu(Int_t)");
126
127 fMenuHelp = new TGPopupMenu(gClient->GetRoot());
128 fMenuHelp->AddEntry(" &About...", M_HELP_ABOUT, 0, gClient->GetPicture("about.xpm"));
129 fMenuHelp->Connect("Activated(Int_t)", "DNDMainFrame", this, "HandleMenu(Int_t)");
130
131 fMenuBar->AddPopup("&File", fMenuFile, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 4, 0, 0));
132
133 fMenuBar->AddPopup("&Help", fMenuHelp, new TGLayoutHints(kLHintsTop | kLHintsRight));
134
135 AddFrame(fMenuBar, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 2, 2, 2, 5));
136
137 TGHorizontalFrame *hfrm = new TGHorizontalFrame(this, 10, 10);
138 TGCanvas *canvas = new TGCanvas(hfrm, 150, 100);
139 fListTree = new TGListTree(canvas, kHorizontalFrame);
140 fListTree->Associate(this);
141 fEc = new TRootEmbeddedCanvas("glec", hfrm, 550, 350);
142 hfrm->AddFrame(canvas, new TGLayoutHints(kLHintsLeft | kLHintsExpandY, 5, 5));
144 AddFrame(hfrm, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
145 fEc->SetDNDTarget(kTRUE);
146 fCanvas = fEc->GetCanvas();
147 fCanvas->Divide(3, 2);
148 fCanvas->SetBorderMode(0);
149 fBaseLTI = fListTree->AddItem(0, "Base");
150
151 TGHorizontalFrame *hf = new TGHorizontalFrame(this, 10, 10);
152
153 fStatus = new TGLabel(hf, new TGHotString(gReadyMsg));
154 fStatus->SetTextJustify(kTextLeft);
155 fStatus->SetTextColor(0x0000ff);
156 hf->AddFrame(fStatus, new TGLayoutHints(kLHintsExpandX | kLHintsCenterY, 10, 10, 10, 10));
157
158 fButtonExit = new TGTextButton(hf, " &Exit... ", 3);
159 fButtonExit->Resize(fButtonExit->GetDefaultSize());
160 fButtonExit->SetToolTipText("Exit Application (ROOT)");
161 fButtonExit->Connect("Clicked()", "TApplication", gApplication, "Terminate()");
162 hf->AddFrame(fButtonExit, new TGLayoutHints(kLHintsCenterY | kLHintsRight, 10, 10, 10, 10));
163
164 AddFrame(hf, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5));
165
166 gRootObj = gVirtualX->InternAtom("application/root", kFALSE);
167
168 TGraph *gr = (TGraph *)GetObject("Graph");
169 pic = gClient->GetPicture("f1_t.xpm");
170 item = fListTree->AddItem(fBaseLTI, gr->GetName(), gr, pic, pic);
171 fListTree->SetToolTipItem(item, "Simple Graph");
172 item->SetDNDSource(kTRUE);
173
174 TH1F *hpx = (TH1F *)GetObject("1D Hist");
175 pic = gClient->GetPicture("h1_t.xpm");
176 item = fListTree->AddItem(fBaseLTI, hpx->GetName(), hpx, pic, pic);
177 fListTree->SetToolTipItem(item, "1D Histogram");
178 item->SetDNDSource(kTRUE);
179
180 TH2F *h2 = (TH2F *)GetObject("2D Hist");
181 pic = gClient->GetPicture("h2_t.xpm");
182 item = fListTree->AddItem(fBaseLTI, h2->GetName(), h2, pic, pic);
183 fListTree->SetToolTipItem(item, "2D Histogram");
184 item->SetDNDSource(kTRUE);
185
186 TString rootsys(gSystem->UnixPathName(gSystem->Getenv("ROOTSYS")));
187#ifdef R__WIN32
188 // remove the drive letter (e.g. "C:/") from $ROOTSYS, if any
189 if (rootsys[1] == ':' && rootsys[2] == '/')
190 rootsys.Remove(0, 3);
191#endif
192 TString link = TString::Format("/%s/tutorials/visualisation/image/rose512.jpg", rootsys.Data());
194 TImage *img = TImage::Open(link.Data());
195 if (img) {
196 // create a 16x16 icon from the original picture
197 img->Scale(16, 16);
198 pic = gClient->GetPicturePool()->GetPicture("rose512", img->GetPixmap(), img->GetMask());
199 delete img;
200 } else
201 pic = gClient->GetPicture("psp_t.xpm");
202 link.Prepend("file://");
203 TObjString *ostr = new TObjString(link.Data());
204 item = fListTree->AddItem(fBaseLTI, "Rose", ostr, pic, pic);
205 fListTree->SetToolTipItem(item, link.Data());
206 item->SetDNDSource(kTRUE);
207 }
208
209 // open the base list tree item and allow to drop into it
210 fListTree->OpenItem(fBaseLTI);
211 fListTree->GetFirstItem()->SetDNDTarget(kTRUE);
212
213 // connect the DataDropped signal to be able to handle it
214 fListTree->Connect("DataDropped(TGListTreeItem*, TDNDData*)", "DNDMainFrame", this,
215 "DataDropped(TGListTreeItem*,TDNDData*)");
216
217 SetWindowName("ROOT DND Demo Application");
219 Resize(GetDefaultSize());
220 Connect("CloseWindow()", "DNDMainFrame", this, "DoCloseWindow()");
221 DontCallClose(); // to avoid double deletions.
222}
223
224//______________________________________________________________________________
225DNDMainFrame::~DNDMainFrame()
226{
227 // Destructor. Doesnt't do much here.
228}
229
230//______________________________________________________________________________
231void DNDMainFrame::DoCloseWindow()
232{
233 // Do some cleanup, disconnect signals and then really close the main window.
234
235 if (fGraph) {
236 delete fGraph;
237 fGraph = 0;
238 }
239 if (fHist1D) {
240 delete fHist1D;
241 fHist1D = 0;
242 }
243 if (fHist2D) {
244 delete fHist2D;
245 fHist2D = 0;
246 }
247 fMenuFile->Disconnect("Activated(Int_t)", this, "HandleMenu(Int_t)");
248 fMenuHelp->Disconnect("Activated(Int_t)", this, "HandleMenu(Int_t)");
249 fButtonExit->Disconnect("Clicked()", this, "CloseWindow()");
250 fListTree->Disconnect("DataDropped(TGListTreeItem*, TDNDData*)", this, "DataDropped(TGListTreeItem*,TDNDData*)");
251 delete fListTree;
252 CloseWindow();
253}
254
255//______________________________________________________________________________
256void DNDMainFrame::DataDropped(TGListTreeItem *, TDNDData *data)
257{
258 // Handle the drop event in the TGListTree. This will just create a new
259 // list tree item and copy the received data into it.
260
261 fStatus->SetTextColor(0xff0000);
262 fStatus->ChangeText("I received data!!!");
263 if (data) {
264 const TGPicture *pic = 0;
265 TGListTreeItem *itm = 0;
266 char tmp[1000];
267 if (data->fDataType == gRootObj) {
268 TBufferFile buf(TBuffer::kRead, data->fDataLength, (void *)data->fData);
269 buf.SetReadMode();
270 TObject *obj = (TObject *)buf.ReadObjectAny(TObject::Class());
271 sprintf(tmp, "Received DND data : Type = \"%s\"; Length = %d bytes;", obj->ClassName(), data->fDataLength);
272 if (obj->InheritsFrom("TGraph"))
273 pic = gClient->GetPicture("f1_t.xpm");
274 else if (obj->InheritsFrom("TH2F"))
275 pic = gClient->GetPicture("h2_t.xpm");
276 else if (obj->InheritsFrom("TH1F"))
277 pic = gClient->GetPicture("h1_t.xpm");
278 itm = fListTree->AddItem(fBaseLTI, obj->GetName(), obj, pic, pic);
279 fListTree->SetToolTipItem(itm, obj->GetName());
280 } else {
281 sprintf(tmp, "Received DND data: \"%s\"", (char *)data->fData);
282 TObjString *ostr = new TObjString((char *)data->fData);
283 TImage *img1 = TImage::Open("doc_t.xpm");
284 TImage *img2 = TImage::Open("slink_t.xpm");
285 if (img1 && img2) {
286 img1->Merge(img2);
287 pic = gClient->GetPicturePool()->GetPicture("doc_lnk", img1->GetPixmap(), img1->GetMask());
288 delete img2;
289 delete img1;
290 } else
291 pic = gClient->GetPicture("doc_t.xpm");
292 itm = fListTree->AddItem(fBaseLTI, "Link...", ostr, pic, pic);
293 fListTree->SetToolTipItem(itm, (const char *)data->fData);
294 }
295 if (itm)
296 itm->SetDNDSource(kTRUE);
297 fStatus->ChangeText(tmp);
298 }
299 TTimer::SingleShot(3000, "DNDMainFrame", this, "ResetStatus()");
300}
301
302//______________________________________________________________________________
303TObject *DNDMainFrame::GetObject(const char *obj)
304{
305 // Return the object specified in argument. If the object doesn't exist yet,
306 // it is firt created.
307
308 if (!strcmp(obj, "Graph")) {
309 if (fGraph == 0) {
310 const Int_t n = 20;
311 Double_t x[n], y[n];
312 for (Int_t i = 0; i < n; i++) {
313 x[i] = i * 0.1;
314 y[i] = 10 * sin(x[i] + 0.2);
315 }
316 fGraph = new TGraph(n, x, y);
317 }
318 return fGraph;
319 } else if (!strcmp(obj, "1D Hist")) {
320 if (fHist1D == 0) {
321 fHist1D = new TH1F("1D Hist", "This is the px distribution", 100, -4, 4);
322 Float_t px, py;
323 for (Int_t i = 0; i < 10000; i++) {
324 gRandom->Rannor(px, py);
325 fHist1D->Fill(px);
326 }
327 }
328 return fHist1D;
329 } else if (!strcmp(obj, "2D Hist")) {
330 if (fHist2D == 0) {
331 Double_t params[] = {130, -1.4, 1.8, 1.5, 1, 150, 2, 0.5, -2, 0.5, 3600, -2, 0.7, -3, 0.3};
332 TF2 *f2 = new TF2("f2", "xygaus + xygaus(5) + xylandau(10)", -4, 4, -4, 4);
333 f2->SetParameters(params);
334 fHist2D = new TH2F("2D Hist", "xygaus+xygaus(5)+xylandau(10)", 20, -4, 4, 20, -4, 4);
335 fHist2D->FillRandom("f2", 40000);
336 }
337 return fHist2D;
338 }
339 return 0;
340}
341
342//______________________________________________________________________________
343void DNDMainFrame::HandleMenu(Int_t menu_id)
344{
345 // Handle menu events.
346
347 TRootHelpDialog *hd;
348 static TString dir(".");
349 TGFileInfo fi;
350 fi.fFileTypes = dnd_types;
351 fi.SetIniDir(dir);
352
353 switch (menu_id) {
354 case M_FILE_EXIT:
355 // close the window and quit application
356 DoCloseWindow();
358 break;
359 case M_FILE_OPEN:
360 new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fi);
361 dir = fi.fIniDir;
362 // doesn't do much, but can be used to open a root file...
363 break;
364 case M_FILE_BROWSE:
365 // start a root object browser
366 new TBrowser();
367 break;
368 case M_FILE_NEWCANVAS:
369 // open a root canvas
370 gROOT->MakeDefCanvas();
371 break;
372 case M_FILE_CLOSEWIN: DoCloseWindow(); break;
373 case M_HELP_ABOUT:
374 hd = new TRootHelpDialog(this, "About Drag and Drop...", 550, 250);
375 hd->SetText(gHelpDND);
376 hd->Popup();
377 break;
378 }
379}
380
381//______________________________________________________________________________
382void DNDMainFrame::ResetStatus()
383{
384 // Restore the original text of the status label and its original color.
385
386 fStatus->SetTextColor(0x0000ff);
387 fStatus->ChangeText(gReadyMsg);
388}
389
390//------------------------------------------------------------------------------
391void drag_and_drop()
392{
393 // Main function (entry point)
394
395 DNDMainFrame *mainWindow = new DNDMainFrame(gClient->GetRoot(), 700, 400);
396 mainWindow->MapWindow();
397}
Handle_t Atom_t
WM token.
Definition GuiTypes.h:37
@ kHorizontalFrame
Definition GuiTypes.h:382
const Handle_t kNone
Definition GuiTypes.h:88
#define h(i)
Definition RSha256.hxx:106
int Int_t
Definition RtypesCore.h:45
float Float_t
Definition RtypesCore.h:57
constexpr Bool_t kFALSE
Definition RtypesCore.h:94
double Double_t
Definition RtypesCore.h:59
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
R__EXTERN TApplication * gApplication
#define gClient
Definition TGClient.h:157
@ kFDOpen
@ kDeepCleanup
Definition TGFrame.h:42
EMyMessageTypes
@ kLHintsRight
Definition TGLayout.h:26
@ kLHintsExpandY
Definition TGLayout.h:31
@ kLHintsLeft
Definition TGLayout.h:24
@ kLHintsCenterY
Definition TGLayout.h:28
@ kLHintsTop
Definition TGLayout.h:27
@ kLHintsExpandX
Definition TGLayout.h:30
@ kTextLeft
Definition TGWidget.h:23
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize MapSubwindows
#define gROOT
Definition TROOT.h:406
R__EXTERN TRandom * gRandom
Definition TRandom.h:62
@ kReadPermission
Definition TSystem.h:45
R__EXTERN TSystem * gSystem
Definition TSystem.h:561
#define gVirtualX
Definition TVirtualX.h:337
virtual void Terminate(Int_t status=0)
Terminate the application by call TSystem::Exit() unless application has been told to return from Run...
Using a TBrowser one can browse all ROOT objects.
Definition TBrowser.h:37
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket.
Definition TBufferFile.h:47
@ kRead
Definition TBuffer.h:73
The Canvas class.
Definition TCanvas.h:23
Drag and drop data container.
virtual void SetParameters(const Double_t *params)
Definition TF1.h:677
A 2-Dim function with parameters.
Definition TF2.h:29
A frame containing two scrollbars (a horizontal and a vertical) and a viewport.
Definition TGCanvas.h:192
virtual void AddFrame(TGFrame *f, TGLayoutHints *l=nullptr)
Add frame to the composite frame using the specified layout hints.
Definition TGFrame.cxx:1117
This class creates a file selection dialog.
const char ** fFileTypes
file types used to filter selectable files
char * fIniDir
on input: initial directory, on output: new directory
void SetIniDir(const char *inidir)
Set directory name.
A composite frame that layout their children in horizontal way.
Definition TGFrame.h:385
TGHotString is a string with a "hot" character underlined.
Definition TGString.h:42
This class handles GUI labels.
Definition TGLabel.h:24
This class describes layout hints used by the layout classes.
Definition TGLayout.h:50
void SetDNDSource(Bool_t onoff)
Definition TGListTree.h:108
A list tree is a widget that can contain a number of items arranged in a tree structure.
Definition TGListTree.h:195
Defines top level windows that interact with the system Window Manager.
Definition TGFrame.h:397
The TGMenu.h header contains all different menu classes.
Definition TGMenu.h:282
The TGPicture class implements pictures and icons used in the different GUI elements and widgets.
Definition TGPicture.h:25
Pixmap_t GetPicture() const
Definition TGPicture.h:54
This class creates a popup menu object.
Definition TGMenu.h:110
Yield an action as soon as it is clicked.
Definition TGButton.h:142
ROOT GUI Window base class.
Definition TGWindow.h:23
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:623
2-D histogram with a float per channel (see TH1 documentation)
Definition TH2.h:308
An abstract interface to image processing library.
Definition TImage.h:29
static TImage * Open(const char *file, EImageFileTypes type=kUnknown)
Open a specified image file.
Definition TImage.cxx:118
virtual void Scale(UInt_t, UInt_t)
Definition TImage.h:141
virtual void Merge(const TImage *, const char *="alphablend", Int_t=0, Int_t=0)
Definition TImage.h:172
virtual Pixmap_t GetPixmap()
Definition TImage.h:235
virtual Pixmap_t GetMask()
Definition TImage.h:236
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
Collectable string class.
Definition TObjString.h:28
Mother of all ROOT objects.
Definition TObject.h:41
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:456
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:225
static TClass * Class()
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:542
virtual void Rannor(Float_t &a, Float_t &b)
Return 2 numbers distributed following a gaussian with mean=0 and sigma=1.
Definition TRandom.cxx:507
This class creates a TGCanvas in which a TCanvas is created.
A TRootHelpDialog is used to display help text (or any text in a dialog window).
void SetText(const char *helpText)
Set help text from helpText buffer in TGTextView.
void Popup()
Show help dialog.
Basic string class.
Definition TString.h:139
const char * Data() const
Definition TString.h:376
TString & Prepend(const char *cs)
Definition TString.h:673
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:2378
virtual const char * Getenv(const char *env)
Get environment variable.
Definition TSystem.cxx:1665
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition TSystem.cxx:1296
virtual const char * UnixPathName(const char *unixpathname)
Convert from a local pathname to a Unix pathname.
Definition TSystem.cxx:1063
static void SingleShot(Int_t milliSec, const char *receiver_class, void *receiver, const char *method)
This static function calls a slot after a given time interval.
Definition TTimer.cxx:258
RVec< PromoteType< T > > sin(const RVec< T > &v)
Definition RVec.hxx:1851
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
TGraphErrors * gr
Definition legend1.C:25