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 <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...";
protected:
public:
DNDMainFrame(
const TGWindow *p,
int w,
int h);
virtual ~DNDMainFrame();
void DoCloseWindow();
TObject *GetObject(
const char *obj);
void ResetStatus();
};
M_FILE_BROWSE,
M_FILE_NEWCANVAS,
M_FILE_CLOSEWIN,
};
const char *dnd_types[] = {
"ROOT files", "*.root",
"ROOT macros", "*.C",
"All files", "*",
0, 0
};
DNDMainFrame::DNDMainFrame(
const TGWindow *p,
int w,
int h) :
TGMainFrame(p, w, h), fGraph(0), fHist1D(0), fHist2D(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();
gClient->GetPicture(
"bld_exit.png"));
fMenuFile->Connect("Activated(Int_t)", "DNDMainFrame", this,
"HandleMenu(Int_t)");
fMenuHelp->
AddEntry(
" &About...", M_HELP_ABOUT, 0,
fMenuHelp->Connect("Activated(Int_t)", "DNDMainFrame", this,
"HandleMenu(Int_t)");
0, 4, 0, 0));
fListTree->Associate(this);
fCanvas->SetBorderMode(0);
fBaseLTI = fListTree->AddItem(0, "Base");
fStatus->SetTextColor(0x0000ff);
10, 10, 10, 10));
fButtonExit->Resize(fButtonExit->GetDefaultSize());
fButtonExit->SetToolTipText("Exit Application (ROOT)");
fButtonExit->Connect(
"Clicked()" ,
"TApplication",
gApplication,
"Terminate()");
10, 10, 10, 10));
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");
#ifdef G__WIN32
if (rootsys[1] == ':' && rootsys[2] == '/')
rootsys.Remove(0, 3);
#endif
rootsys.Data());
if (img) {
delete img;
}
else pic =
gClient->GetPicture(
"psp_t.xpm");
item = fListTree->AddItem(fBaseLTI, "Rose", ostr, pic, pic);
fListTree->SetToolTipItem(item, link.
Data());
item->SetDNDSource(
kTRUE);
}
fListTree->OpenItem(fBaseLTI);
fListTree->GetFirstItem()->SetDNDTarget(
kTRUE);
fListTree->Connect("DataDropped(TGListTreeItem*, TDNDData*)", "DNDMainFrame",
this, "DataDropped(TGListTreeItem*,TDNDData*)");
SetWindowName("ROOT DND Demo Application");
MapSubwindows();
Resize(GetDefaultSize());
Connect("CloseWindow()", "DNDMainFrame", this, "DoCloseWindow()");
DontCallClose();
}
DNDMainFrame::~DNDMainFrame()
{
}
void DNDMainFrame::DoCloseWindow()
{
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();
}
{
fStatus->SetTextColor(0xff0000);
fStatus->ChangeText("I received data!!!");
if (data) {
char tmp[1000];
buf.SetReadMode();
sprintf(tmp, "Received DND data : Type = \"%s\"; Length = %d bytes;",
pic =
gClient->GetPicture(
"f1_t.xpm");
pic =
gClient->GetPicture(
"h2_t.xpm");
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);
if (img1 && img2) {
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);
}
fStatus->ChangeText(tmp);
}
}
TObject *DNDMainFrame::GetObject(
const char *obj)
{
if (!strcmp(obj, "Graph")) {
if (fGraph == 0) {
x[i] = i*0.1;
}
}
return fGraph;
}
else if (!strcmp(obj, "1D Hist")) {
if (fHist1D == 0) {
fHist1D =
new TH1F(
"1D Hist",
"This is the px distribution",100,-4,4);
for (
Int_t i=0; i<10000; i++) {
fHist1D->Fill(px);
}
}
return fHist1D;
}
else if (!strcmp(obj, "2D Hist")) {
if (fHist2D == 0) {
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);
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)
{
switch (menu_id) {
DoCloseWindow();
break;
break;
case M_FILE_BROWSE:
break;
case M_FILE_NEWCANVAS:
break;
case M_FILE_CLOSEWIN:
DoCloseWindow();
break;
break;
}
}
void DNDMainFrame::ResetStatus()
{
fStatus->SetTextColor(0x0000ff);
fStatus->ChangeText(gReadyMsg);
}
void drag_and_drop()
{
DNDMainFrame *mainWindow =
new DNDMainFrame(
gClient->GetRoot(), 700, 400);
mainWindow->MapWindow();
}