40 const char gHelpDND[] =
"\
42 Drag and Drop support is implemented on Linux via Xdnd, the\n\
43 drag and drop protocol for X window system, and on Windows\n\
45 Users can selects something in ROOT with a mouse press, drags\n\
46 it (moves the mouse while keeping the mouse button pressed) and\n\
47 releases the mouse button somewhere else. When the button is\n\
48 released the selected data is \"dropped\" at that location. This\n\
49 way, a histogram from an opened ROOT file in the browser can be\n\
50 dragged to any TCanvas. A script file from the browser can be\n\
51 dropped to a TGTextView or TGTextEdit widget in TGTextEditor.\n\
52 On Linux, it is possible to drag objects between ROOT and an\n\
53 external application. For example to drag a macro file from the\n\
54 ROOT browser to the Kate editor. On Windows, drag and drop works\n\
55 only within a single ROOT application, but it is possible to drag\n\
56 from the Windows Explorer to ROOT (e.g. a picture file to a canvas\n\
57 or a text file to a text editor).\n\
60 const char gReadyMsg[] =
"Ready. You can drag list tree items to any \
61 pad in the canvas, or to the \"Base\" folder of the list tree itself...";
65 class DNDMainFrame :
public TGMainFrame {
68 TRootEmbeddedCanvas *fEc;
69 TGTextButton *fButtonExit;
71 TGPopupMenu *fMenuFile;
72 TGPopupMenu *fMenuHelp;
74 TGListTree *fListTree;
75 TGListTreeItem *fBaseLTI;
82 DNDMainFrame(
const TGWindow *p,
int w,
int h);
83 virtual ~DNDMainFrame();
86 void HandleMenu(Int_t);
87 TObject *GetObject(
const char *obj);
88 void DataDropped(TGListTreeItem* item, TDNDData* data);
94 enum EMyMessageTypes {
103 const char *dnd_types[] = {
104 "ROOT files",
"*.root",
105 "ROOT macros",
"*.C",
110 static Atom_t gRootObj = kNone;
113 DNDMainFrame::DNDMainFrame(
const TGWindow *p,
int w,
int h) :
114 TGMainFrame(p, w, h), fGraph(0), fHist1D(0), fHist2D(0)
119 SetCleanup(kDeepCleanup);
120 const TGPicture *pic = 0;
121 TGListTreeItem *item;
122 fMenuBar =
new TGMenuBar(
this, 35, 50, kHorizontalFrame);
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)");
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)");
142 fMenuBar->AddPopup(
"&File", fMenuFile,
new TGLayoutHints(kLHintsTop|kLHintsLeft,
145 fMenuBar->AddPopup(
"&Help", fMenuHelp,
new TGLayoutHints(kLHintsTop|kLHintsRight));
147 AddFrame(fMenuBar,
new TGLayoutHints(kLHintsTop | kLHintsExpandX, 2, 2, 2, 5));
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));
155 hfrm->AddFrame(fEc,
new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
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");
163 TGHorizontalFrame *hf =
new TGHorizontalFrame(
this, 10, 10);
165 fStatus =
new TGLabel(hf,
new TGHotString(gReadyMsg));
166 fStatus->SetTextJustify(kTextLeft);
167 fStatus->SetTextColor(0x0000ff);
168 hf->AddFrame(fStatus,
new TGLayoutHints(kLHintsExpandX | kLHintsCenterY,
171 fButtonExit =
new TGTextButton(hf,
" &Exit... ", 3);
172 fButtonExit->Resize(fButtonExit->GetDefaultSize());
173 fButtonExit->SetToolTipText(
"Exit Application (ROOT)");
174 fButtonExit->Connect(
"Clicked()" ,
"TApplication", gApplication,
176 hf->AddFrame(fButtonExit,
new TGLayoutHints(kLHintsCenterY | kLHintsRight,
179 AddFrame(hf,
new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5));
181 gRootObj = gVirtualX->InternAtom(
"application/root", kFALSE);
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);
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);
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);
201 TString rootsys(gSystem->UnixPathName(gSystem->Getenv(
"ROOTSYS")));
204 if (rootsys[1] ==
':' && rootsys[2] ==
'/')
205 rootsys.Remove(0, 3);
207 TString link = TString::Format(
"/%s/tutorials/image/rose512.jpg",
209 if (!gSystem->AccessPathName(link.Data(), kReadPermission)) {
210 TImage *img = TImage::Open(link.Data());
214 pic = gClient->GetPicturePool()->GetPicture(
"rose512", img->GetPixmap(),
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);
227 fListTree->OpenItem(fBaseLTI);
228 fListTree->GetFirstItem()->SetDNDTarget(kTRUE);
231 fListTree->Connect(
"DataDropped(TGListTreeItem*, TDNDData*)",
"DNDMainFrame",
232 this,
"DataDropped(TGListTreeItem*,TDNDData*)");
234 SetWindowName(
"ROOT DND Demo Application");
236 Resize(GetDefaultSize());
237 Connect(
"CloseWindow()",
"DNDMainFrame",
this,
"DoCloseWindow()");
242 DNDMainFrame::~DNDMainFrame()
248 void DNDMainFrame::DoCloseWindow()
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*)");
265 void DNDMainFrame::DataDropped(TGListTreeItem *, TDNDData *data)
270 fStatus->SetTextColor(0xff0000);
271 fStatus->ChangeText(
"I received data!!!");
273 const TGPicture *pic = 0;
274 TGListTreeItem *itm = 0;
276 if (data->fDataType == gRootObj) {
277 TBufferFile buf(TBuffer::kRead, data->fDataLength, (
void *)data->fData);
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());
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");
298 pic = gClient->GetPicturePool()->GetPicture(
"doc_lnk", img1->GetPixmap(),
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);
307 if (itm) itm->SetDNDSource(kTRUE);
308 fStatus->ChangeText(tmp);
310 TTimer::SingleShot(3000,
"DNDMainFrame",
this,
"ResetStatus()");
314 TObject *DNDMainFrame::GetObject(
const char *obj)
319 if (!strcmp(obj,
"Graph")) {
323 for (Int_t i=0;i<n;i++) {
325 y[i] = 10*sin(x[i]+0.2);
327 fGraph =
new TGraph(n, x, y);
331 else if (!strcmp(obj,
"1D Hist")) {
333 fHist1D =
new TH1F(
"1D Hist",
"This is the px distribution",100,-4,4);
335 for ( Int_t i=0; i<10000; i++) {
336 gRandom->Rannor(px, py);
342 else if (!strcmp(obj,
"2D Hist")) {
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
347 TF2 *f2 =
new TF2(
"f2",
"xygaus + xygaus(5) + xylandau(10)",
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);
360 void DNDMainFrame::HandleMenu(Int_t menu_id)
365 static TString dir(
".");
367 fi.fFileTypes = dnd_types;
368 fi.fIniDir = StrDup(dir);
374 gApplication->Terminate(0);
377 new TGFileDialog(gClient->GetRoot(),
this, kFDOpen, &fi);
385 case M_FILE_NEWCANVAS:
387 gROOT->MakeDefCanvas();
389 case M_FILE_CLOSEWIN:
393 hd =
new TRootHelpDialog(
this,
"About Drag and Drop...", 550, 250);
394 hd->SetText(gHelpDND);
401 void DNDMainFrame::ResetStatus()
405 fStatus->SetTextColor(0x0000ff);
406 fStatus->ChangeText(gReadyMsg);
414 DNDMainFrame *mainWindow =
new DNDMainFrame(gClient->GetRoot(), 700, 400);
415 mainWindow->MapWindow();