Logo ROOT  
Reference Guide
drag_and_drop.C File Reference

Detailed Description

This tutorial illustrates how to use drag and drop within ROOT. Select a list tree item with a mouse press, drag it (move the mouse while keeping the mouse button pressed) and release the mouse button in any pad inside the canvas or in the top list tree item ("Base"). When the button is released, the selected data is "dropped" at that location, displaying the object in the canvas or adding (copying) it in the list tree.

#include "TROOT.h"
#include "TApplication.h"
#include "TSystem.h"
#include "TGFrame.h"
#include "TGButton.h"
#include "TGLabel.h"
#include "TGMenu.h"
#include "TGFileDialog.h"
#include "TBrowser.h"
#include "TCanvas.h"
#include "TH1F.h"
#include "TH2F.h"
#include "TF2.h"
#include "TGraph.h"
#include "TImage.h"
#include "TRandom.h"
#include "TGMsgBox.h"
#include "TGPicture.h"
#include "TGListTree.h"
#include "TObjString.h"
#include "TMessage.h"
#include "TTimer.h"
#include "TGDNDManager.h"
#include <cmath>
const char gHelpDND[] = "\
Drag & Drop (DnD)\n\
Drag and Drop support is implemented on Linux via Xdnd, the\n\
drag and drop protocol for X window system, and on Windows\n\
via the Clipboard.\n\
Users can selects something in ROOT with a mouse press, drags\n\
it (moves the mouse while keeping the mouse button pressed) and\n\
releases the mouse button somewhere else. When the button is\n\
released the selected data is \"dropped\" at that location. This\n\
way, a histogram from an opened ROOT file in the browser can be\n\
dragged to any TCanvas. A script file from the browser can be\n\
dropped to a TGTextView or TGTextEdit widget in TGTextEditor.\n\
On Linux, it is possible to drag objects between ROOT and an\n\
external application. For example to drag a macro file from the\n\
ROOT browser to the Kate editor. On Windows, drag and drop works\n\
only within a single ROOT application, but it is possible to drag\n\
from the Windows Explorer to ROOT (e.g. a picture file to a canvas\n\
or a text file to a text editor).\n\
";
const char gReadyMsg[] = "Ready. You can drag list tree items to any \
pad in the canvas, or to the \"Base\" folder of the list tree itself...";
//----------------------------------------------------------------------
class DNDMainFrame : public TGMainFrame {
protected:
TRootEmbeddedCanvas *fEc; // embedded canvas
TGTextButton *fButtonExit; // "Exit" text button
TGMenuBar *fMenuBar; // main menu bar
TGPopupMenu *fMenuFile; // "File" popup menu entry
TGPopupMenu *fMenuHelp; // "Help" popup menu entry
TCanvas *fCanvas; // canvas
TGListTree *fListTree; // left list tree
TGListTreeItem *fBaseLTI; // base (root) list tree item
TGLabel *fStatus; // label used to display status
TGraph *fGraph; // TGraph object
TH1F *fHist1D; // 1D histogram
TH2F *fHist2D; // 2D histogram
public:
DNDMainFrame(const TGWindow *p, int w, int h);
virtual ~DNDMainFrame();
void DoCloseWindow();
void HandleMenu(Int_t);
TObject *GetObject(const char *obj);
void DataDropped(TGListTreeItem* item, TDNDData* data);
void ResetStatus();
//ClassDef(DNDMainFrame, 0); // Mainframe for Drag and Drop demo
};
M_FILE_OPEN,
M_FILE_BROWSE,
M_FILE_NEWCANVAS,
M_FILE_CLOSEWIN,
M_FILE_EXIT,
M_HELP_ABOUT
};
const char *dnd_types[] = {
"ROOT files", "*.root",
"ROOT macros", "*.C",
"All files", "*",
0, 0
};
static Atom_t gRootObj = kNone;
//______________________________________________________________________________
DNDMainFrame::DNDMainFrame(const TGWindow *p, int w, int h) :
TGMainFrame(p, w, h), fGraph(0), fHist1D(0), fHist2D(0)
{
// Constructor.
SetCleanup(kDeepCleanup);
const TGPicture *pic = 0;
fMenuBar = new TGMenuBar(this, 35, 50, kHorizontalFrame);
fMenuFile = new TGPopupMenu(gClient->GetRoot());
fMenuFile->AddEntry(" &Open...\tCtrl+O", M_FILE_OPEN, 0,
gClient->GetPicture("bld_open.png"));
fMenuFile->AddEntry(" &Browse...\tCtrl+B", M_FILE_BROWSE);
fMenuFile->AddEntry(" &New Canvas\tCtrl+N", M_FILE_NEWCANVAS);
fMenuFile->AddEntry(" &Close Window\tCtrl+W", M_FILE_CLOSEWIN);
fMenuFile->AddSeparator();
fMenuFile->AddEntry(" E&xit\tCtrl+Q", M_FILE_EXIT, 0,
gClient->GetPicture("bld_exit.png"));
fMenuFile->Connect("Activated(Int_t)", "DNDMainFrame", this,
"HandleMenu(Int_t)");
fMenuHelp = new TGPopupMenu(gClient->GetRoot());
fMenuHelp->AddEntry(" &About...", M_HELP_ABOUT, 0,
gClient->GetPicture("about.xpm"));
fMenuHelp->Connect("Activated(Int_t)", "DNDMainFrame", this,
"HandleMenu(Int_t)");
fMenuBar->AddPopup("&File", fMenuFile, new TGLayoutHints(kLHintsTop|kLHintsLeft,
0, 4, 0, 0));
fMenuBar->AddPopup("&Help", fMenuHelp, new TGLayoutHints(kLHintsTop|kLHintsRight));
AddFrame(fMenuBar, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 2, 2, 2, 5));
TGHorizontalFrame *hfrm = new TGHorizontalFrame(this, 10, 10);
TGCanvas *canvas = new TGCanvas(hfrm, 150, 100);
fListTree = new TGListTree(canvas, kHorizontalFrame);
fListTree->Associate(this);
fEc = new TRootEmbeddedCanvas("glec", hfrm, 550, 350);
hfrm->AddFrame(canvas, new TGLayoutHints(kLHintsLeft | kLHintsExpandY, 5, 5));
fCanvas = fEc->GetCanvas();
fCanvas->Divide(3, 2);
fCanvas->SetBorderMode(0);
fBaseLTI = fListTree->AddItem(0, "Base");
TGHorizontalFrame *hf = new TGHorizontalFrame(this, 10, 10);
fStatus = new TGLabel(hf, new TGHotString(gReadyMsg));
fStatus->SetTextJustify(kTextLeft);
fStatus->SetTextColor(0x0000ff);
10, 10, 10, 10));
fButtonExit = new TGTextButton(hf, " &Exit... ", 3);
fButtonExit->Resize(fButtonExit->GetDefaultSize());
fButtonExit->SetToolTipText("Exit Application (ROOT)");
fButtonExit->Connect("Clicked()" , "TApplication", gApplication,
"Terminate()");
10, 10, 10, 10));
AddFrame(hf, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5));
gRootObj = gVirtualX->InternAtom("application/root", kFALSE);
TGraph *gr = (TGraph *)GetObject("Graph");
pic = gClient->GetPicture("f1_t.xpm");
item = fListTree->AddItem(fBaseLTI, gr->GetName(), gr, pic, pic);
fListTree->SetToolTipItem(item, "Simple Graph");
TH1F *hpx = (TH1F *)GetObject("1D Hist");
pic = gClient->GetPicture("h1_t.xpm");
item = fListTree->AddItem(fBaseLTI, hpx->GetName(), hpx, pic, pic);
fListTree->SetToolTipItem(item, "1D Histogram");
TH2F *h2 = (TH2F *)GetObject("2D Hist");
pic = gClient->GetPicture("h2_t.xpm");
item = fListTree->AddItem(fBaseLTI, h2->GetName(), h2, pic, pic);
fListTree->SetToolTipItem(item, "2D Histogram");
TString rootsys(gSystem->UnixPathName(gSystem->Getenv("ROOTSYS")));
#ifdef G__WIN32
// remove the drive letter (e.g. "C:/") from $ROOTSYS, if any
if (rootsys[1] == ':' && rootsys[2] == '/')
rootsys.Remove(0, 3);
#endif
TString link = TString::Format("/%s/tutorials/image/rose512.jpg",
rootsys.Data());
TImage *img = TImage::Open(link.Data());
if (img) {
// create a 16x16 icon from the original picture
img->Scale(16, 16);
pic = gClient->GetPicturePool()->GetPicture("rose512", img->GetPixmap(),
img->GetMask());
delete img;
}
else pic = gClient->GetPicture("psp_t.xpm");
link.Prepend("file://");
TObjString *ostr = new TObjString(link.Data());
item = fListTree->AddItem(fBaseLTI, "Rose", ostr, pic, pic);
fListTree->SetToolTipItem(item, link.Data());
}
// open the base list tree item and allow to drop into it
fListTree->OpenItem(fBaseLTI);
fListTree->GetFirstItem()->SetDNDTarget(kTRUE);
// connect the DataDropped signal to be able to handle it
fListTree->Connect("DataDropped(TGListTreeItem*, TDNDData*)", "DNDMainFrame",
this, "DataDropped(TGListTreeItem*,TDNDData*)");
SetWindowName("ROOT DND Demo Application");
MapSubwindows();
Resize(GetDefaultSize());
Connect("CloseWindow()", "DNDMainFrame", this, "DoCloseWindow()");
DontCallClose(); // to avoid double deletions.
}
//______________________________________________________________________________
DNDMainFrame::~DNDMainFrame()
{
// Destructor. Doesnt't do much here.
}
//______________________________________________________________________________
void DNDMainFrame::DoCloseWindow()
{
// Do some cleanup, disconnect signals and then really close the main window.
if (fGraph) { delete fGraph; fGraph = 0; }
if (fHist1D) { delete fHist1D; fHist1D = 0; }
if (fHist2D) { delete fHist2D; fHist2D = 0; }
fMenuFile->Disconnect("Activated(Int_t)", this, "HandleMenu(Int_t)");
fMenuHelp->Disconnect("Activated(Int_t)", this, "HandleMenu(Int_t)");
fButtonExit->Disconnect("Clicked()" , this, "CloseWindow()");
fListTree->Disconnect("DataDropped(TGListTreeItem*, TDNDData*)", this,
"DataDropped(TGListTreeItem*,TDNDData*)");
delete fListTree;
CloseWindow();
}
//______________________________________________________________________________
void DNDMainFrame::DataDropped(TGListTreeItem *, TDNDData *data)
{
// Handle the drop event in the TGListTree. This will just create a new
// list tree item and copy the received data into it.
fStatus->SetTextColor(0xff0000);
fStatus->ChangeText("I received data!!!");
if (data) {
const TGPicture *pic = 0;
TGListTreeItem *itm = 0;
char tmp[1000];
if (data->fDataType == gRootObj) {
TBufferFile buf(TBuffer::kRead, data->fDataLength, (void *)data->fData);
buf.SetReadMode();
TObject *obj = (TObject *)buf.ReadObjectAny(TObject::Class());
sprintf(tmp, "Received DND data : Type = \"%s\"; Length = %d bytes;",
obj->ClassName(), data->fDataLength);
if (obj->InheritsFrom("TGraph"))
pic = gClient->GetPicture("f1_t.xpm");
else if (obj->InheritsFrom("TH2F"))
pic = gClient->GetPicture("h2_t.xpm");
else if (obj->InheritsFrom("TH1F"))
pic = gClient->GetPicture("h1_t.xpm");
itm = fListTree->AddItem(fBaseLTI, obj->GetName(), obj, pic, pic);
fListTree->SetToolTipItem(itm, obj->GetName());
}
else {
sprintf(tmp, "Received DND data: \"%s\"", (char *)data->fData);
TObjString *ostr = new TObjString((char *)data->fData);
TImage *img1 = TImage::Open("doc_t.xpm");
TImage *img2 = TImage::Open("slink_t.xpm");
if (img1 && img2) {
img1->Merge(img2);
pic = gClient->GetPicturePool()->GetPicture("doc_lnk", img1->GetPixmap(),
img1->GetMask());
delete img2;
delete img1;
}
else pic = gClient->GetPicture("doc_t.xpm");
itm = fListTree->AddItem(fBaseLTI, "Link...", ostr, pic, pic);
fListTree->SetToolTipItem(itm, (const char *)data->fData);
}
if (itm) itm->SetDNDSource(kTRUE);
fStatus->ChangeText(tmp);
}
TTimer::SingleShot(3000, "DNDMainFrame", this, "ResetStatus()");
}
//______________________________________________________________________________
TObject *DNDMainFrame::GetObject(const char *obj)
{
// Return the object specified in argument. If the object doesn't exist yet,
// it is firt created.
if (!strcmp(obj, "Graph")) {
if (fGraph == 0) {
const Int_t n = 20;
Double_t x[n], y[n];
for (Int_t i=0;i<n;i++) {
x[i] = i*0.1;
y[i] = 10*sin(x[i]+0.2);
}
fGraph = new TGraph(n, x, y);
}
return fGraph;
}
else if (!strcmp(obj, "1D Hist")) {
if (fHist1D == 0) {
fHist1D = new TH1F("1D Hist","This is the px distribution",100,-4,4);
Float_t px, py;
for ( Int_t i=0; i<10000; i++) {
gRandom->Rannor(px, py);
fHist1D->Fill(px);
}
}
return fHist1D;
}
else if (!strcmp(obj, "2D Hist")) {
if (fHist2D == 0) {
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
};
TF2 *f2 = new TF2("f2","xygaus + xygaus(5) + xylandau(10)",
-4, 4, -4, 4);
f2->SetParameters(params);
fHist2D = new TH2F("2D Hist","xygaus+xygaus(5)+xylandau(10)",
20, -4, 4, 20, -4, 4);
fHist2D->FillRandom("f2",40000);
}
return fHist2D;
}
return 0;
}
//______________________________________________________________________________
void DNDMainFrame::HandleMenu(Int_t menu_id)
{
// Handle menu events.
static TString dir(".");
fi.fFileTypes = dnd_types;
fi.SetIniDir(dir);
switch (menu_id) {
case M_FILE_EXIT:
// close the window and quit application
DoCloseWindow();
break;
case M_FILE_OPEN:
new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fi);
dir = fi.fIniDir;
// doesn't do much, but can be used to open a root file...
break;
case M_FILE_BROWSE:
// start a root object browser
new TBrowser();
break;
case M_FILE_NEWCANVAS:
// open a root canvas
gROOT->MakeDefCanvas();
break;
case M_FILE_CLOSEWIN:
DoCloseWindow();
break;
case M_HELP_ABOUT:
hd = new TRootHelpDialog(this, "About Drag and Drop...", 550, 250);
hd->SetText(gHelpDND);
hd->Popup();
break;
}
}
//______________________________________________________________________________
void DNDMainFrame::ResetStatus()
{
// Restore the original text of the status label and its original color.
fStatus->SetTextColor(0x0000ff);
fStatus->ChangeText(gReadyMsg);
}
//------------------------------------------------------------------------------
void drag_and_drop()
{
// Main function (entry point)
DNDMainFrame *mainWindow = new DNDMainFrame(gClient->GetRoot(), 700, 400);
mainWindow->MapWindow();
}
Author
Bertrand Bellenot

Definition in file drag_and_drop.C.

TRootHelpDialog::Popup
void Popup()
Show help dialog.
Definition: TRootHelpDialog.cxx:68
n
const Int_t n
Definition: legend1.C:16
TBrowser
Definition: TBrowser.h:37
TGWindow
Definition: TGWindow.h:31
kTRUE
const Bool_t kTRUE
Definition: RtypesCore.h:91
TH1F.h
TGMainFrame
Definition: TGFrame.h:444
TDNDData::fDataLength
Int_t fDataLength
Definition: TGDNDManager.h:78
TGPicture
Definition: TGPicture.h:36
TImage::Merge
virtual void Merge(const TImage *, const char *="alphablend", Int_t=0, Int_t=0)
Definition: TImage.h:172
TBuffer::kRead
@ kRead
Definition: TBuffer.h:73
TString::Prepend
TString & Prepend(const char *cs)
Definition: TString.h:661
gVirtualX
#define gVirtualX
Definition: TVirtualX.h:338
TH2F
2-D histogram with a float per channel (see TH1 documentation)}
Definition: TH2.h:251
TString::Data
const char * Data() const
Definition: TString.h:369
kLHintsTop
@ kLHintsTop
Definition: TGLayout.h:40
TObjString.h
TGPicture.h
TGraph.h
TGHotString
Definition: TGString.h:52
kLHintsLeft
@ kLHintsLeft
Definition: TGLayout.h:37
TGLabel
Definition: TGLabel.h:32
TRandom.h
Float_t
float Float_t
Definition: RtypesCore.h:57
TGTextButton
Definition: TGButton.h:142
Int_t
int Int_t
Definition: RtypesCore.h:45
TGFileInfo::SetIniDir
void SetIniDir(const char *inidir)
Set directory name.
Definition: TGFileDialog.cxx:115
TBrowser.h
TGListTree
Definition: TGListTree.h:210
TImage
Definition: TImage.h:29
sin
double sin(double)
x
Double_t x[n]
Definition: legend1.C:17
TPad::Divide
virtual void Divide(Int_t nx=1, Int_t ny=1, Float_t xmargin=0.01, Float_t ymargin=0.01, Int_t color=0)
Automatic pad generation by division.
Definition: TPad.cxx:1166
TMessage.h
TGHorizontalFrame
Definition: TGFrame.h:423
TRootHelpDialog::SetText
void SetText(const char *helpText)
Set help text from helpText buffer in TGTextView.
Definition: TRootHelpDialog.cxx:76
TTimer.h
TString::Format
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:2311
TCanvas.h
TImage::Open
static TImage * Open(const char *file, EImageFileTypes type=kUnknown)
Open a specified image file.
Definition: TImage.cxx:118
TGDNDManager.h
TString
Definition: TString.h:136
TSystem::AccessPathName
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:1294
TObject::InheritsFrom
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:445
TGFileDialog.h
TImage.h
TROOT.h
TF1::SetParameters
virtual void SetParameters(const Double_t *params)
Definition: TF1.h:640
TRandom::Rannor
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:489
TObjString
Definition: TObjString.h:28
gClient
#define gClient
Definition: TGClient.h:166
kTextLeft
@ kTextLeft
Definition: TGWidget.h:40
TDNDData::fDataType
Atom_t fDataType
Definition: TGDNDManager.h:75
TApplication.h
TObject::GetName
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:359
kNone
const Handle_t kNone
Definition: GuiTypes.h:87
TF2.h
TDNDData::fData
void * fData
Definition: TGDNDManager.h:77
TSystem.h
kLHintsCenterY
@ kLHintsCenterY
Definition: TGLayout.h:41
h
#define h(i)
Definition: RSha256.hxx:124
TImage::Scale
virtual void Scale(UInt_t, UInt_t)
Definition: TImage.h:141
gr
TGraphErrors * gr
Definition: legend1.C:25
Atom_t
Handle_t Atom_t
Definition: GuiTypes.h:36
kFALSE
const Bool_t kFALSE
Definition: RtypesCore.h:92
TImage::GetMask
virtual Pixmap_t GetMask()
Definition: TImage.h:236
TGFrame.h
kLHintsRight
@ kLHintsRight
Definition: TGLayout.h:39
TGListTreeItem::SetDNDSource
void SetDNDSource(Bool_t onoff)
Definition: TGListTree.h:123
TGFileInfo
Definition: TGFileDialog.h:54
TGLayoutHints
Definition: TGLayout.h:57
TRootHelpDialog.h
gRandom
R__EXTERN TRandom * gRandom
Definition: TRandom.h:62
gApplication
R__EXTERN TApplication * gApplication
Definition: TApplication.h:166
TTimer::SingleShot
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:256
y
Double_t y[n]
Definition: legend1.C:17
TApplication::Terminate
virtual void Terminate(Int_t status=0)
kLHintsExpandY
@ kLHintsExpandY
Definition: TGLayout.h:44
TDNDData
Definition: TGDNDManager.h:65
TH2F.h
TF2
Definition: TF2.h:29
TRootEmbeddedCanvas.h
kHorizontalFrame
@ kHorizontalFrame
Definition: GuiTypes.h:382
gSystem
R__EXTERN TSystem * gSystem
Definition: TSystem.h:559
TGLabel.h
TSystem::Getenv
virtual const char * Getenv(const char *env)
Get environment variable.
Definition: TSystem.cxx:1661
TGFileInfo::fIniDir
char * fIniDir
Definition: TGFileDialog.h:62
TGFileInfo::fFileTypes
const char ** fFileTypes
Definition: TGFileDialog.h:63
EMyMessageTypes
EMyMessageTypes
Definition: TGHtmlBrowser.cxx:50
Double_t
double Double_t
Definition: RtypesCore.h:59
TGraph
Definition: TGraph.h:41
TCanvas
Definition: TCanvas.h:23
TSystem::UnixPathName
virtual const char * UnixPathName(const char *unixpathname)
Convert from a local pathname to a Unix pathname.
Definition: TSystem.cxx:1061
TGMsgBox.h
TH1F
1-D histogram with a float per channel (see TH1 documentation)}
Definition: TH1.h:572
TObject
Definition: TObject.h:37
TGButton.h
TGListTree.h
TGPopupMenu
Definition: TGMenu.h:123
TGFrame::SetDNDTarget
void SetDNDTarget(Bool_t onoff)
Definition: TGFrame.h:295
TImage::GetPixmap
virtual Pixmap_t GetPixmap()
Definition: TImage.h:235
kDeepCleanup
@ kDeepCleanup
Definition: TGFrame.h:51
TRootEmbeddedCanvas::GetCanvas
TCanvas * GetCanvas() const
Definition: TRootEmbeddedCanvas.h:63
kLHintsExpandX
@ kLHintsExpandX
Definition: TGLayout.h:43
TNamed::GetName
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:53
TGMenuBar
Definition: TGMenu.h:304
Class
void Class()
Definition: Class.C:29
kReadPermission
@ kReadPermission
Definition: TSystem.h:47
TGCanvas
Definition: TGCanvas.h:202
TGListTreeItem
Definition: TGListTree.h:43
TObject::ClassName
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:130
TGCompositeFrame::AddFrame
virtual void AddFrame(TGFrame *f, TGLayoutHints *l=0)
Add frame to the composite frame using the specified layout hints.
Definition: TGFrame.cxx:1102
TGMenu.h
TBufferFile
Definition: TBufferFile.h:47
TRootEmbeddedCanvas
Definition: TRootEmbeddedCanvas.h:32
TRootHelpDialog
Definition: TRootHelpDialog.h:31
gROOT
#define gROOT
Definition: TROOT.h:406
TGFileDialog
Definition: TGFileDialog.h:80
kFDOpen
@ kFDOpen
Definition: TGFileDialog.h:44