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[] = {
104 "ROOT files", "*.root",
105 "ROOT macros", "*.C",
106 "All files", "*",
107 0, 0
108};
109
110static Atom_t gRootObj = kNone;
111
112//______________________________________________________________________________
113DNDMainFrame::DNDMainFrame(const TGWindow *p, int w, int h) :
114 TGMainFrame(p, w, h), fGraph(0), fHist1D(0), fHist2D(0)
115
116{
117 // Constructor.
118
119 SetCleanup(kDeepCleanup);
120 const TGPicture *pic = 0;
121 TGListTreeItem *item;
122 fMenuBar = new TGMenuBar(this, 35, 50, kHorizontalFrame);
123
124 fMenuFile = new TGPopupMenu(gClient->GetRoot());
125 fMenuFile->AddEntry(" &Open...\tCtrl+O", M_FILE_OPEN, 0,
126 gClient->GetPicture("bld_open.png"));
127 fMenuFile->AddEntry(" &Browse...\tCtrl+B", M_FILE_BROWSE);
128 fMenuFile->AddEntry(" &New Canvas\tCtrl+N", M_FILE_NEWCANVAS);
129 fMenuFile->AddEntry(" &Close Window\tCtrl+W", M_FILE_CLOSEWIN);
130 fMenuFile->AddSeparator();
131 fMenuFile->AddEntry(" E&xit\tCtrl+Q", M_FILE_EXIT, 0,
132 gClient->GetPicture("bld_exit.png"));
133 fMenuFile->Connect("Activated(Int_t)", "DNDMainFrame", this,
134 "HandleMenu(Int_t)");
135
136 fMenuHelp = new TGPopupMenu(gClient->GetRoot());
137 fMenuHelp->AddEntry(" &About...", M_HELP_ABOUT, 0,
138 gClient->GetPicture("about.xpm"));
139 fMenuHelp->Connect("Activated(Int_t)", "DNDMainFrame", this,
140 "HandleMenu(Int_t)");
141
142 fMenuBar->AddPopup("&File", fMenuFile, new TGLayoutHints(kLHintsTop|kLHintsLeft,
143 0, 4, 0, 0));
144
145 fMenuBar->AddPopup("&Help", fMenuHelp, new TGLayoutHints(kLHintsTop|kLHintsRight));
146
147 AddFrame(fMenuBar, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 2, 2, 2, 5));
148
149 TGHorizontalFrame *hfrm = new TGHorizontalFrame(this, 10, 10);
150 TGCanvas *canvas = new TGCanvas(hfrm, 150, 100);
151 fListTree = new TGListTree(canvas, kHorizontalFrame);
152 fListTree->Associate(this);
153 fEc = new TRootEmbeddedCanvas("glec", hfrm, 550, 350);
154 hfrm->AddFrame(canvas, new TGLayoutHints(kLHintsLeft | kLHintsExpandY, 5, 5));
156 AddFrame(hfrm, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
157 fEc->SetDNDTarget(kTRUE);
158 fCanvas = fEc->GetCanvas();
159 fCanvas->Divide(3, 2);
160 fCanvas->SetBorderMode(0);
161 fBaseLTI = fListTree->AddItem(0, "Base");
162
163 TGHorizontalFrame *hf = new TGHorizontalFrame(this, 10, 10);
164
165 fStatus = new TGLabel(hf, new TGHotString(gReadyMsg));
166 fStatus->SetTextJustify(kTextLeft);
167 fStatus->SetTextColor(0x0000ff);
169 10, 10, 10, 10));
170
171 fButtonExit = new TGTextButton(hf, " &Exit... ", 3);
172 fButtonExit->Resize(fButtonExit->GetDefaultSize());
173 fButtonExit->SetToolTipText("Exit Application (ROOT)");
174 fButtonExit->Connect("Clicked()" , "TApplication", gApplication,
175 "Terminate()");
176 hf->AddFrame(fButtonExit, new TGLayoutHints(kLHintsCenterY | kLHintsRight,
177 10, 10, 10, 10));
178
179 AddFrame(hf, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5));
180
181 gRootObj = gVirtualX->InternAtom("application/root", kFALSE);
182
183 TGraph *gr = (TGraph *)GetObject("Graph");
184 pic = gClient->GetPicture("f1_t.xpm");
185 item = fListTree->AddItem(fBaseLTI, gr->GetName(), gr, pic, pic);
186 fListTree->SetToolTipItem(item, "Simple Graph");
187 item->SetDNDSource(kTRUE);
188
189 TH1F *hpx = (TH1F *)GetObject("1D Hist");
190 pic = gClient->GetPicture("h1_t.xpm");
191 item = fListTree->AddItem(fBaseLTI, hpx->GetName(), hpx, pic, pic);
192 fListTree->SetToolTipItem(item, "1D Histogram");
193 item->SetDNDSource(kTRUE);
194
195 TH2F *h2 = (TH2F *)GetObject("2D Hist");
196 pic = gClient->GetPicture("h2_t.xpm");
197 item = fListTree->AddItem(fBaseLTI, h2->GetName(), h2, pic, pic);
198 fListTree->SetToolTipItem(item, "2D Histogram");
199 item->SetDNDSource(kTRUE);
200
201 TString rootsys(gSystem->UnixPathName(gSystem->Getenv("ROOTSYS")));
202#ifdef R__WIN32
203 // remove the drive letter (e.g. "C:/") from $ROOTSYS, if any
204 if (rootsys[1] == ':' && rootsys[2] == '/')
205 rootsys.Remove(0, 3);
206#endif
207 TString link = TString::Format("/%s/tutorials/image/rose512.jpg",
208 rootsys.Data());
210 TImage *img = TImage::Open(link.Data());
211 if (img) {
212 // create a 16x16 icon from the original picture
213 img->Scale(16, 16);
214 pic = gClient->GetPicturePool()->GetPicture("rose512", img->GetPixmap(),
215 img->GetMask());
216 delete img;
217 }
218 else pic = gClient->GetPicture("psp_t.xpm");
219 link.Prepend("file://");
220 TObjString *ostr = new TObjString(link.Data());
221 item = fListTree->AddItem(fBaseLTI, "Rose", ostr, pic, pic);
222 fListTree->SetToolTipItem(item, link.Data());
223 item->SetDNDSource(kTRUE);
224 }
225
226 // open the base list tree item and allow to drop into it
227 fListTree->OpenItem(fBaseLTI);
228 fListTree->GetFirstItem()->SetDNDTarget(kTRUE);
229
230 // connect the DataDropped signal to be able to handle it
231 fListTree->Connect("DataDropped(TGListTreeItem*, TDNDData*)", "DNDMainFrame",
232 this, "DataDropped(TGListTreeItem*,TDNDData*)");
233
234 SetWindowName("ROOT DND Demo Application");
236 Resize(GetDefaultSize());
237 Connect("CloseWindow()", "DNDMainFrame", this, "DoCloseWindow()");
238 DontCallClose(); // to avoid double deletions.
239}
240
241//______________________________________________________________________________
242DNDMainFrame::~DNDMainFrame()
243{
244 // Destructor. Doesnt't do much here.
245}
246
247//______________________________________________________________________________
248void DNDMainFrame::DoCloseWindow()
249{
250 // Do some cleanup, disconnect signals and then really close the main window.
251
252 if (fGraph) { delete fGraph; fGraph = 0; }
253 if (fHist1D) { delete fHist1D; fHist1D = 0; }
254 if (fHist2D) { delete fHist2D; fHist2D = 0; }
255 fMenuFile->Disconnect("Activated(Int_t)", this, "HandleMenu(Int_t)");
256 fMenuHelp->Disconnect("Activated(Int_t)", this, "HandleMenu(Int_t)");
257 fButtonExit->Disconnect("Clicked()" , this, "CloseWindow()");
258 fListTree->Disconnect("DataDropped(TGListTreeItem*, TDNDData*)", this,
259 "DataDropped(TGListTreeItem*,TDNDData*)");
260 delete fListTree;
261 CloseWindow();
262}
263
264//______________________________________________________________________________
265void DNDMainFrame::DataDropped(TGListTreeItem *, TDNDData *data)
266{
267 // Handle the drop event in the TGListTree. This will just create a new
268 // list tree item and copy the received data into it.
269
270 fStatus->SetTextColor(0xff0000);
271 fStatus->ChangeText("I received data!!!");
272 if (data) {
273 const TGPicture *pic = 0;
274 TGListTreeItem *itm = 0;
275 char tmp[1000];
276 if (data->fDataType == gRootObj) {
277 TBufferFile buf(TBuffer::kRead, data->fDataLength, (void *)data->fData);
278 buf.SetReadMode();
279 TObject *obj = (TObject *)buf.ReadObjectAny(TObject::Class());
280 sprintf(tmp, "Received DND data : Type = \"%s\"; Length = %d bytes;",
281 obj->ClassName(), data->fDataLength);
282 if (obj->InheritsFrom("TGraph"))
283 pic = gClient->GetPicture("f1_t.xpm");
284 else if (obj->InheritsFrom("TH2F"))
285 pic = gClient->GetPicture("h2_t.xpm");
286 else if (obj->InheritsFrom("TH1F"))
287 pic = gClient->GetPicture("h1_t.xpm");
288 itm = fListTree->AddItem(fBaseLTI, obj->GetName(), obj, pic, pic);
289 fListTree->SetToolTipItem(itm, obj->GetName());
290 }
291 else {
292 sprintf(tmp, "Received DND data: \"%s\"", (char *)data->fData);
293 TObjString *ostr = new TObjString((char *)data->fData);
294 TImage *img1 = TImage::Open("doc_t.xpm");
295 TImage *img2 = TImage::Open("slink_t.xpm");
296 if (img1 && img2) {
297 img1->Merge(img2);
298 pic = gClient->GetPicturePool()->GetPicture("doc_lnk", img1->GetPixmap(),
299 img1->GetMask());
300 delete img2;
301 delete img1;
302 }
303 else pic = gClient->GetPicture("doc_t.xpm");
304 itm = fListTree->AddItem(fBaseLTI, "Link...", ostr, pic, pic);
305 fListTree->SetToolTipItem(itm, (const char *)data->fData);
306 }
307 if (itm) itm->SetDNDSource(kTRUE);
308 fStatus->ChangeText(tmp);
309 }
310 TTimer::SingleShot(3000, "DNDMainFrame", this, "ResetStatus()");
311}
312
313//______________________________________________________________________________
314TObject *DNDMainFrame::GetObject(const char *obj)
315{
316 // Return the object specified in argument. If the object doesn't exist yet,
317 // it is firt created.
318
319 if (!strcmp(obj, "Graph")) {
320 if (fGraph == 0) {
321 const Int_t n = 20;
322 Double_t x[n], y[n];
323 for (Int_t i=0;i<n;i++) {
324 x[i] = i*0.1;
325 y[i] = 10*sin(x[i]+0.2);
326 }
327 fGraph = new TGraph(n, x, y);
328 }
329 return fGraph;
330 }
331 else if (!strcmp(obj, "1D Hist")) {
332 if (fHist1D == 0) {
333 fHist1D = new TH1F("1D Hist","This is the px distribution",100,-4,4);
334 Float_t px, py;
335 for ( Int_t i=0; i<10000; i++) {
336 gRandom->Rannor(px, py);
337 fHist1D->Fill(px);
338 }
339 }
340 return fHist1D;
341 }
342 else if (!strcmp(obj, "2D Hist")) {
343 if (fHist2D == 0) {
344 Double_t params[] = {
345 130,-1.4,1.8,1.5,1, 150,2,0.5,-2,0.5, 3600,-2,0.7,-3,0.3
346 };
347 TF2 *f2 = new TF2("f2","xygaus + xygaus(5) + xylandau(10)",
348 -4, 4, -4, 4);
349 f2->SetParameters(params);
350 fHist2D = new TH2F("2D Hist","xygaus+xygaus(5)+xylandau(10)",
351 20, -4, 4, 20, -4, 4);
352 fHist2D->FillRandom("f2",40000);
353 }
354 return fHist2D;
355 }
356 return 0;
357}
358
359//______________________________________________________________________________
360void DNDMainFrame::HandleMenu(Int_t menu_id)
361{
362 // Handle menu events.
363
364 TRootHelpDialog *hd;
365 static TString dir(".");
366 TGFileInfo fi;
367 fi.fFileTypes = dnd_types;
368 fi.SetIniDir(dir);
369
370 switch (menu_id) {
371 case M_FILE_EXIT:
372 // close the window and quit application
373 DoCloseWindow();
375 break;
376 case M_FILE_OPEN:
377 new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fi);
378 dir = fi.fIniDir;
379 // doesn't do much, but can be used to open a root file...
380 break;
381 case M_FILE_BROWSE:
382 // start a root object browser
383 new TBrowser();
384 break;
385 case M_FILE_NEWCANVAS:
386 // open a root canvas
387 gROOT->MakeDefCanvas();
388 break;
389 case M_FILE_CLOSEWIN:
390 DoCloseWindow();
391 break;
392 case M_HELP_ABOUT:
393 hd = new TRootHelpDialog(this, "About Drag and Drop...", 550, 250);
394 hd->SetText(gHelpDND);
395 hd->Popup();
396 break;
397 }
398}
399
400//______________________________________________________________________________
401void DNDMainFrame::ResetStatus()
402{
403 // Restore the original text of the status label and its original color.
404
405 fStatus->SetTextColor(0x0000ff);
406 fStatus->ChangeText(gReadyMsg);
407}
408
409//------------------------------------------------------------------------------
410void drag_and_drop()
411{
412 // Main function (entry point)
413
414 DNDMainFrame *mainWindow = new DNDMainFrame(gClient->GetRoot(), 700, 400);
415 mainWindow->MapWindow();
416}
417
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:101
double Double_t
Definition RtypesCore.h:59
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
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:407
R__EXTERN TRandom * gRandom
Definition TRandom.h:62
@ kReadPermission
Definition TSystem.h:47
R__EXTERN TSystem * gSystem
Definition TSystem.h:560
#define gVirtualX
Definition TVirtualX.h:338
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:650
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:577
2-D histogram with a float per channel (see TH1 documentation)}
Definition TH2.h:258
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:439
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:207
static TClass * Class()
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:525
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:500
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:380
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:2356
virtual const char * Getenv(const char *env)
Get environment variable.
Definition TSystem.cxx:1650
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:1283
virtual const char * UnixPathName(const char *unixpathname)
Convert from a local pathname to a Unix pathname.
Definition TSystem.cxx:1050
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:1814
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