00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "TROOT.h"
00011 #include "TApplication.h"
00012 #include "TSystem.h"
00013 #include "TGFrame.h"
00014 #include "TGButton.h"
00015 #include "TGLabel.h"
00016 #include "TGMenu.h"
00017 #include "TGFileDialog.h"
00018 #include "TBrowser.h"
00019 #include "TRootEmbeddedCanvas.h"
00020 #include "TRootHelpDialog.h"
00021 #include "TCanvas.h"
00022 #include "TH1F.h"
00023 #include "TH2F.h"
00024 #include "TF2.h"
00025 #include "TGraph.h"
00026 #include "TImage.h"
00027 #include "TRandom.h"
00028 #include "TGMsgBox.h"
00029 #include "TGPicture.h"
00030 #include "TGListTree.h"
00031 #include "TObjString.h"
00032 #include "TMessage.h"
00033 #include "TTimer.h"
00034 #include "TGDNDManager.h"
00035 #include <cmath>
00036
00037 const char gHelpDND[] = "\
00038 Drag & Drop (DnD)\n\
00039 Drag and Drop support is implemented on Linux via Xdnd, the\n\
00040 drag and drop protocol for X window system, and on Windows\n\
00041 via the Clipboard.\n\
00042 Users can selects something in ROOT with a mouse press, drags\n\
00043 it (moves the mouse while keeping the mouse button pressed) and\n\
00044 releases the mouse button somewhere else. When the button is\n\
00045 released the selected data is \"dropped\" at that location. This\n\
00046 way, a histogram from an opened ROOT file in the browser can be\n\
00047 dragged to any TCanvas. A script file from the browser can be\n\
00048 dropped to a TGTextView or TGTextEdit widget in TGTextEditor.\n\
00049 On Linux, it is possible to drag objects between ROOT and an\n\
00050 external application. For example to drag a macro file from the\n\
00051 ROOT browser to the Kate editor. On Windows, drag and drop works\n\
00052 only within a single ROOT application, but it is possible to drag\n\
00053 from the Windows Explorer to ROOT (e.g. a picture file to a canvas\n\
00054 or a text file to a text editor).\n\
00055 ";
00056
00057 const char gReadyMsg[] = "Ready. You can drag list tree items to any \
00058 pad in the canvas, or to the \"Base\" folder of the list tree itself...";
00059
00060
00061
00062 class DNDMainFrame : public TGMainFrame {
00063
00064 protected:
00065 TRootEmbeddedCanvas *fEc;
00066 TGTextButton *fButtonExit;
00067 TGMenuBar *fMenuBar;
00068 TGPopupMenu *fMenuFile;
00069 TGPopupMenu *fMenuHelp;
00070 TCanvas *fCanvas;
00071 TGListTree *fListTree;
00072 TGListTreeItem *fBaseLTI;
00073 TGLabel *fStatus;
00074 TGraph *fGraph;
00075 TH1F *fHist1D;
00076 TH2F *fHist2D;
00077
00078 public:
00079 DNDMainFrame(const TGWindow *p, int w, int h);
00080 virtual ~DNDMainFrame();
00081
00082 void DoCloseWindow();
00083 void HandleMenu(Int_t);
00084 TObject *GetObject(const char *obj);
00085 void DataDropped(TGListTreeItem* item, TDNDData* data);
00086 void ResetStatus();
00087
00088
00089 };
00090
00091 enum EMyMessageTypes {
00092 M_FILE_OPEN,
00093 M_FILE_BROWSE,
00094 M_FILE_NEWCANVAS,
00095 M_FILE_CLOSEWIN,
00096 M_FILE_EXIT,
00097 M_HELP_ABOUT
00098 };
00099
00100 const char *dnd_types[] = {
00101 "ROOT files", "*.root",
00102 "ROOT macros", "*.C",
00103 "All files", "*",
00104 0, 0
00105 };
00106
00107 static Atom_t gRootObj = kNone;
00108
00109
00110 DNDMainFrame::DNDMainFrame(const TGWindow *p, int w, int h) :
00111 TGMainFrame(p, w, h), fGraph(0), fHist1D(0), fHist2D(0)
00112
00113 {
00114
00115
00116 SetCleanup(kDeepCleanup);
00117 const TGPicture *pic = 0;
00118 TGListTreeItem *item;
00119 fMenuBar = new TGMenuBar(this, 35, 50, kHorizontalFrame);
00120
00121 fMenuFile = new TGPopupMenu(gClient->GetRoot());
00122 fMenuFile->AddEntry(" &Open...\tCtrl+O", M_FILE_OPEN, 0,
00123 gClient->GetPicture("bld_open.png"));
00124 fMenuFile->AddEntry(" &Browse...\tCtrl+B", M_FILE_BROWSE);
00125 fMenuFile->AddEntry(" &New Canvas\tCtrl+N", M_FILE_NEWCANVAS);
00126 fMenuFile->AddEntry(" &Close Window\tCtrl+W", M_FILE_CLOSEWIN);
00127 fMenuFile->AddSeparator();
00128 fMenuFile->AddEntry(" E&xit\tCtrl+Q", M_FILE_EXIT, 0,
00129 gClient->GetPicture("bld_exit.png"));
00130 fMenuFile->Connect("Activated(Int_t)", "DNDMainFrame", this,
00131 "HandleMenu(Int_t)");
00132
00133 fMenuHelp = new TGPopupMenu(gClient->GetRoot());
00134 fMenuHelp->AddEntry(" &About...", M_HELP_ABOUT, 0,
00135 gClient->GetPicture("about.xpm"));
00136 fMenuHelp->Connect("Activated(Int_t)", "DNDMainFrame", this,
00137 "HandleMenu(Int_t)");
00138
00139 fMenuBar->AddPopup("&File", fMenuFile, new TGLayoutHints(kLHintsTop|kLHintsLeft,
00140 0, 4, 0, 0));
00141
00142 fMenuBar->AddPopup("&Help", fMenuHelp, new TGLayoutHints(kLHintsTop|kLHintsRight));
00143
00144 AddFrame(fMenuBar, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 2, 2, 2, 5));
00145
00146 TGHorizontalFrame *hfrm = new TGHorizontalFrame(this, 10, 10);
00147 TGCanvas *canvas = new TGCanvas(hfrm, 150, 100);
00148 fListTree = new TGListTree(canvas, kHorizontalFrame);
00149 fListTree->Associate(this);
00150 fEc = new TRootEmbeddedCanvas("glec", hfrm, 550, 350);
00151 hfrm->AddFrame(canvas, new TGLayoutHints(kLHintsLeft | kLHintsExpandY, 5, 5));
00152 hfrm->AddFrame(fEc, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
00153 AddFrame(hfrm, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
00154 fEc->SetDNDTarget(kTRUE);
00155 fCanvas = fEc->GetCanvas();
00156 fCanvas->Divide(3, 2);
00157 fCanvas->SetBorderMode(0);
00158 fBaseLTI = fListTree->AddItem(0, "Base");
00159
00160 TGHorizontalFrame *hf = new TGHorizontalFrame(this, 10, 10);
00161
00162 fStatus = new TGLabel(hf, new TGHotString(gReadyMsg));
00163 fStatus->SetTextJustify(kTextLeft);
00164 fStatus->SetTextColor(0x0000ff);
00165 hf->AddFrame(fStatus, new TGLayoutHints(kLHintsExpandX | kLHintsCenterY,
00166 10, 10, 10, 10));
00167
00168 fButtonExit = new TGTextButton(hf, " &Exit... ", 3);
00169 fButtonExit->Resize(fButtonExit->GetDefaultSize());
00170 fButtonExit->SetToolTipText("Exit Application (ROOT)");
00171 fButtonExit->Connect("Clicked()" , "TApplication", gApplication,
00172 "Terminate()");
00173 hf->AddFrame(fButtonExit, new TGLayoutHints(kLHintsCenterY | kLHintsRight,
00174 10, 10, 10, 10));
00175
00176 AddFrame(hf, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5));
00177
00178 gRootObj = gVirtualX->InternAtom("application/root", kFALSE);
00179
00180 TGraph *gr = (TGraph *)GetObject("Graph");
00181 pic = gClient->GetPicture("f1_t.xpm");
00182 item = fListTree->AddItem(fBaseLTI, gr->GetName(), gr, pic, pic);
00183 fListTree->SetToolTipItem(item, "Simple Graph");
00184 item->SetDNDSource(kTRUE);
00185
00186 TH1F *hpx = (TH1F *)GetObject("1D Hist");
00187 pic = gClient->GetPicture("h1_t.xpm");
00188 item = fListTree->AddItem(fBaseLTI, hpx->GetName(), hpx, pic, pic);
00189 fListTree->SetToolTipItem(item, "1D Histogram");
00190 item->SetDNDSource(kTRUE);
00191
00192 TH2F *h2 = (TH2F *)GetObject("2D Hist");
00193 pic = gClient->GetPicture("h2_t.xpm");
00194 item = fListTree->AddItem(fBaseLTI, h2->GetName(), h2, pic, pic);
00195 fListTree->SetToolTipItem(item, "2D Histogram");
00196 item->SetDNDSource(kTRUE);
00197
00198 TString rootsys(gSystem->UnixPathName(gSystem->Getenv("ROOTSYS")));
00199 #ifdef G__WIN32
00200
00201 if (rootsys[1] == ':' && rootsys[2] == '/')
00202 rootsys.Remove(0, 3);
00203 #endif
00204 TString link = TString::Format("/%s/tutorials/image/rose512.jpg",
00205 rootsys.Data());
00206 if (!gSystem->AccessPathName(link.Data(), kReadPermission)) {
00207 TImage *img = TImage::Open(link.Data());
00208 if (img) {
00209
00210 img->Scale(16, 16);
00211 pic = gClient->GetPicturePool()->GetPicture("rose512", img->GetPixmap(),
00212 img->GetMask());
00213 delete img;
00214 }
00215 else pic = gClient->GetPicture("psp_t.xpm");
00216 link.Prepend("file://");
00217 TObjString *ostr = new TObjString(link.Data());
00218 item = fListTree->AddItem(fBaseLTI, "Rose", ostr, pic, pic);
00219 fListTree->SetToolTipItem(item, link.Data());
00220 item->SetDNDSource(kTRUE);
00221 }
00222
00223
00224 fListTree->OpenItem(fBaseLTI);
00225 fListTree->GetFirstItem()->SetDNDTarget(kTRUE);
00226
00227
00228 fListTree->Connect("DataDropped(TGListTreeItem*, TDNDData*)", "DNDMainFrame",
00229 this, "DataDropped(TGListTreeItem*,TDNDData*)");
00230
00231 SetWindowName("ROOT DND Demo Application");
00232 MapSubwindows();
00233 Resize(GetDefaultSize());
00234 Connect("CloseWindow()", "DNDMainFrame", this, "DoCloseWindow()");
00235 DontCallClose();
00236 }
00237
00238
00239 DNDMainFrame::~DNDMainFrame()
00240 {
00241
00242 }
00243
00244
00245 void DNDMainFrame::DoCloseWindow()
00246 {
00247
00248
00249 if (fGraph) { delete fGraph; fGraph = 0; }
00250 if (fHist1D) { delete fHist1D; fHist1D = 0; }
00251 if (fHist2D) { delete fHist2D; fHist2D = 0; }
00252 fMenuFile->Disconnect("Activated(Int_t)", this, "HandleMenu(Int_t)");
00253 fMenuHelp->Disconnect("Activated(Int_t)", this, "HandleMenu(Int_t)");
00254 fButtonExit->Disconnect("Clicked()" , this, "CloseWindow()");
00255 fListTree->Disconnect("DataDropped(TGListTreeItem*, TDNDData*)", this,
00256 "DataDropped(TGListTreeItem*,TDNDData*)");
00257 delete fListTree;
00258 CloseWindow();
00259 }
00260
00261
00262 void DNDMainFrame::DataDropped(TGListTreeItem *, TDNDData *data)
00263 {
00264
00265
00266
00267 fStatus->SetTextColor(0xff0000);
00268 fStatus->ChangeText("I received data!!!");
00269 if (data) {
00270 const TGPicture *pic = 0;
00271 TGListTreeItem *itm = 0;
00272 char tmp[1000];
00273 if (data->fDataType == gRootObj) {
00274 TBufferFile buf(TBuffer::kRead, data->fDataLength, (void *)data->fData);
00275 buf.SetReadMode();
00276 TObject *obj = (TObject *)buf.ReadObjectAny(TObject::Class());
00277 sprintf(tmp, "Received DND data : Type = \"%s\"; Length = %d bytes;",
00278 obj->ClassName(), data->fDataLength);
00279 if (obj->InheritsFrom("TGraph"))
00280 pic = gClient->GetPicture("f1_t.xpm");
00281 else if (obj->InheritsFrom("TH2F"))
00282 pic = gClient->GetPicture("h2_t.xpm");
00283 else if (obj->InheritsFrom("TH1F"))
00284 pic = gClient->GetPicture("h1_t.xpm");
00285 itm = fListTree->AddItem(fBaseLTI, obj->GetName(), obj, pic, pic);
00286 fListTree->SetToolTipItem(itm, obj->GetName());
00287 }
00288 else {
00289 sprintf(tmp, "Received DND data: \"%s\"", (char *)data->fData);
00290 TObjString *ostr = new TObjString((char *)data->fData);
00291 TImage *img1 = TImage::Open("doc_t.xpm");
00292 TImage *img2 = TImage::Open("slink_t.xpm");
00293 if (img1 && img2) {
00294 img1->Merge(img2);
00295 pic = gClient->GetPicturePool()->GetPicture("doc_lnk", img1->GetPixmap(),
00296 img1->GetMask());
00297 delete img2;
00298 delete img1;
00299 }
00300 else pic = gClient->GetPicture("doc_t.xpm");
00301 itm = fListTree->AddItem(fBaseLTI, "Link...", ostr, pic, pic);
00302 fListTree->SetToolTipItem(itm, (const char *)data->fData);
00303 }
00304 if (itm) itm->SetDNDSource(kTRUE);
00305 fStatus->ChangeText(tmp);
00306 }
00307 TTimer::SingleShot(3000, "DNDMainFrame", this, "ResetStatus()");
00308 }
00309
00310
00311 TObject *DNDMainFrame::GetObject(const char *obj)
00312 {
00313
00314
00315
00316 if (!strcmp(obj, "Graph")) {
00317 if (fGraph == 0) {
00318 const Int_t n = 20;
00319 Double_t x[n], y[n];
00320 for (Int_t i=0;i<n;i++) {
00321 x[i] = i*0.1;
00322 y[i] = 10*sin(x[i]+0.2);
00323 }
00324 fGraph = new TGraph(n, x, y);
00325 }
00326 return fGraph;
00327 }
00328 else if (!strcmp(obj, "1D Hist")) {
00329 if (fHist1D == 0) {
00330 fHist1D = new TH1F("1D Hist","This is the px distribution",100,-4,4);
00331 Float_t px, py;
00332 for ( Int_t i=0; i<10000; i++) {
00333 gRandom->Rannor(px, py);
00334 fHist1D->Fill(px);
00335 }
00336 }
00337 return fHist1D;
00338 }
00339 else if (!strcmp(obj, "2D Hist")) {
00340 if (fHist2D == 0) {
00341 Double_t params[] = {
00342 130,-1.4,1.8,1.5,1, 150,2,0.5,-2,0.5, 3600,-2,0.7,-3,0.3
00343 };
00344 TF2 *f2 = new TF2("f2","xygaus + xygaus(5) + xylandau(10)",
00345 -4, 4, -4, 4);
00346 f2->SetParameters(params);
00347 fHist2D = new TH2F("2D Hist","xygaus+xygaus(5)+xylandau(10)",
00348 20, -4, 4, 20, -4, 4);
00349 fHist2D->FillRandom("f2",40000);
00350 }
00351 return fHist2D;
00352 }
00353 return 0;
00354 }
00355
00356
00357 void DNDMainFrame::HandleMenu(Int_t menu_id)
00358 {
00359
00360
00361 TRootHelpDialog *hd;
00362 static TString dir(".");
00363 TGFileInfo fi;
00364 fi.fFileTypes = dnd_types;
00365 fi.fIniDir = StrDup(dir);
00366
00367 switch (menu_id) {
00368 case M_FILE_EXIT:
00369
00370 DoCloseWindow();
00371 gApplication->Terminate(0);
00372 break;
00373 case M_FILE_OPEN:
00374 new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fi);
00375 dir = fi.fIniDir;
00376
00377 break;
00378 case M_FILE_BROWSE:
00379
00380 new TBrowser();
00381 break;
00382 case M_FILE_NEWCANVAS:
00383
00384 gROOT->MakeDefCanvas();
00385 break;
00386 case M_FILE_CLOSEWIN:
00387 DoCloseWindow();
00388 break;
00389 case M_HELP_ABOUT:
00390 hd = new TRootHelpDialog(this, "About Drag and Drop...", 550, 250);
00391 hd->SetText(gHelpDND);
00392 hd->Popup();
00393 break;
00394 }
00395 }
00396
00397
00398 void DNDMainFrame::ResetStatus()
00399 {
00400
00401
00402 fStatus->SetTextColor(0x0000ff);
00403 fStatus->ChangeText(gReadyMsg);
00404 }
00405
00406
00407 void drag_and_drop()
00408 {
00409
00410
00411 DNDMainFrame *mainWindow = new DNDMainFrame(gClient->GetRoot(), 700, 400);
00412 mainWindow->MapWindow();
00413 }
00414