ROOT logo

From $ROOTSYS/tutorials/gui/drag_and_drop.C

// 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
// Author: Bertrand Bellenot

#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 "TRootEmbeddedCanvas.h"
#include "TRootHelpDialog.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
};

enum EMyMessageTypes {
   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;
   TGListTreeItem *item;
   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));
   hfrm->AddFrame(fEc, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
   AddFrame(hfrm, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
   fEc->SetDNDTarget(kTRUE);
   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);
   hf->AddFrame(fStatus, new TGLayoutHints(kLHintsExpandX | kLHintsCenterY,
                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()");
   hf->AddFrame(fButtonExit, new TGLayoutHints(kLHintsCenterY | kLHintsRight,
                                               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");
   item->SetDNDSource(kTRUE);

   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");
   item->SetDNDSource(kTRUE);

   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");
   item->SetDNDSource(kTRUE);

   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());
   if (!gSystem->AccessPathName(link.Data(), kReadPermission)) {
      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());
      item->SetDNDSource(kTRUE);
   }

   // 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.

   TRootHelpDialog *hd;
   static TString dir(".");
   TGFileInfo fi;
   fi.fFileTypes = dnd_types;
   fi.fIniDir    = StrDup(dir);

   switch (menu_id) {
      case M_FILE_EXIT:
         // close the window and quit application
         DoCloseWindow();
         gApplication->Terminate(0);
         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();
}

 drag_and_drop.C:1
 drag_and_drop.C:2
 drag_and_drop.C:3
 drag_and_drop.C:4
 drag_and_drop.C:5
 drag_and_drop.C:6
 drag_and_drop.C:7
 drag_and_drop.C:8
 drag_and_drop.C:9
 drag_and_drop.C:10
 drag_and_drop.C:11
 drag_and_drop.C:12
 drag_and_drop.C:13
 drag_and_drop.C:14
 drag_and_drop.C:15
 drag_and_drop.C:16
 drag_and_drop.C:17
 drag_and_drop.C:18
 drag_and_drop.C:19
 drag_and_drop.C:20
 drag_and_drop.C:21
 drag_and_drop.C:22
 drag_and_drop.C:23
 drag_and_drop.C:24
 drag_and_drop.C:25
 drag_and_drop.C:26
 drag_and_drop.C:27
 drag_and_drop.C:28
 drag_and_drop.C:29
 drag_and_drop.C:30
 drag_and_drop.C:31
 drag_and_drop.C:32
 drag_and_drop.C:33
 drag_and_drop.C:34
 drag_and_drop.C:35
 drag_and_drop.C:36
 drag_and_drop.C:37
 drag_and_drop.C:38
 drag_and_drop.C:39
 drag_and_drop.C:40
 drag_and_drop.C:41
 drag_and_drop.C:42
 drag_and_drop.C:43
 drag_and_drop.C:44
 drag_and_drop.C:45
 drag_and_drop.C:46
 drag_and_drop.C:47
 drag_and_drop.C:48
 drag_and_drop.C:49
 drag_and_drop.C:50
 drag_and_drop.C:51
 drag_and_drop.C:52
 drag_and_drop.C:53
 drag_and_drop.C:54
 drag_and_drop.C:55
 drag_and_drop.C:56
 drag_and_drop.C:57
 drag_and_drop.C:58
 drag_and_drop.C:59
 drag_and_drop.C:60
 drag_and_drop.C:61
 drag_and_drop.C:62
 drag_and_drop.C:63
 drag_and_drop.C:64
 drag_and_drop.C:65
 drag_and_drop.C:66
 drag_and_drop.C:67
 drag_and_drop.C:68
 drag_and_drop.C:69
 drag_and_drop.C:70
 drag_and_drop.C:71
 drag_and_drop.C:72
 drag_and_drop.C:73
 drag_and_drop.C:74
 drag_and_drop.C:75
 drag_and_drop.C:76
 drag_and_drop.C:77
 drag_and_drop.C:78
 drag_and_drop.C:79
 drag_and_drop.C:80
 drag_and_drop.C:81
 drag_and_drop.C:82
 drag_and_drop.C:83
 drag_and_drop.C:84
 drag_and_drop.C:85
 drag_and_drop.C:86
 drag_and_drop.C:87
 drag_and_drop.C:88
 drag_and_drop.C:89
 drag_and_drop.C:90
 drag_and_drop.C:91
 drag_and_drop.C:92
 drag_and_drop.C:93
 drag_and_drop.C:94
 drag_and_drop.C:95
 drag_and_drop.C:96
 drag_and_drop.C:97
 drag_and_drop.C:98
 drag_and_drop.C:99
 drag_and_drop.C:100
 drag_and_drop.C:101
 drag_and_drop.C:102
 drag_and_drop.C:103
 drag_and_drop.C:104
 drag_and_drop.C:105
 drag_and_drop.C:106
 drag_and_drop.C:107
 drag_and_drop.C:108
 drag_and_drop.C:109
 drag_and_drop.C:110
 drag_and_drop.C:111
 drag_and_drop.C:112
 drag_and_drop.C:113
 drag_and_drop.C:114
 drag_and_drop.C:115
 drag_and_drop.C:116
 drag_and_drop.C:117
 drag_and_drop.C:118
 drag_and_drop.C:119
 drag_and_drop.C:120
 drag_and_drop.C:121
 drag_and_drop.C:122
 drag_and_drop.C:123
 drag_and_drop.C:124
 drag_and_drop.C:125
 drag_and_drop.C:126
 drag_and_drop.C:127
 drag_and_drop.C:128
 drag_and_drop.C:129
 drag_and_drop.C:130
 drag_and_drop.C:131
 drag_and_drop.C:132
 drag_and_drop.C:133
 drag_and_drop.C:134
 drag_and_drop.C:135
 drag_and_drop.C:136
 drag_and_drop.C:137
 drag_and_drop.C:138
 drag_and_drop.C:139
 drag_and_drop.C:140
 drag_and_drop.C:141
 drag_and_drop.C:142
 drag_and_drop.C:143
 drag_and_drop.C:144
 drag_and_drop.C:145
 drag_and_drop.C:146
 drag_and_drop.C:147
 drag_and_drop.C:148
 drag_and_drop.C:149
 drag_and_drop.C:150
 drag_and_drop.C:151
 drag_and_drop.C:152
 drag_and_drop.C:153
 drag_and_drop.C:154
 drag_and_drop.C:155
 drag_and_drop.C:156
 drag_and_drop.C:157
 drag_and_drop.C:158
 drag_and_drop.C:159
 drag_and_drop.C:160
 drag_and_drop.C:161
 drag_and_drop.C:162
 drag_and_drop.C:163
 drag_and_drop.C:164
 drag_and_drop.C:165
 drag_and_drop.C:166
 drag_and_drop.C:167
 drag_and_drop.C:168
 drag_and_drop.C:169
 drag_and_drop.C:170
 drag_and_drop.C:171
 drag_and_drop.C:172
 drag_and_drop.C:173
 drag_and_drop.C:174
 drag_and_drop.C:175
 drag_and_drop.C:176
 drag_and_drop.C:177
 drag_and_drop.C:178
 drag_and_drop.C:179
 drag_and_drop.C:180
 drag_and_drop.C:181
 drag_and_drop.C:182
 drag_and_drop.C:183
 drag_and_drop.C:184
 drag_and_drop.C:185
 drag_and_drop.C:186
 drag_and_drop.C:187
 drag_and_drop.C:188
 drag_and_drop.C:189
 drag_and_drop.C:190
 drag_and_drop.C:191
 drag_and_drop.C:192
 drag_and_drop.C:193
 drag_and_drop.C:194
 drag_and_drop.C:195
 drag_and_drop.C:196
 drag_and_drop.C:197
 drag_and_drop.C:198
 drag_and_drop.C:199
 drag_and_drop.C:200
 drag_and_drop.C:201
 drag_and_drop.C:202
 drag_and_drop.C:203
 drag_and_drop.C:204
 drag_and_drop.C:205
 drag_and_drop.C:206
 drag_and_drop.C:207
 drag_and_drop.C:208
 drag_and_drop.C:209
 drag_and_drop.C:210
 drag_and_drop.C:211
 drag_and_drop.C:212
 drag_and_drop.C:213
 drag_and_drop.C:214
 drag_and_drop.C:215
 drag_and_drop.C:216
 drag_and_drop.C:217
 drag_and_drop.C:218
 drag_and_drop.C:219
 drag_and_drop.C:220
 drag_and_drop.C:221
 drag_and_drop.C:222
 drag_and_drop.C:223
 drag_and_drop.C:224
 drag_and_drop.C:225
 drag_and_drop.C:226
 drag_and_drop.C:227
 drag_and_drop.C:228
 drag_and_drop.C:229
 drag_and_drop.C:230
 drag_and_drop.C:231
 drag_and_drop.C:232
 drag_and_drop.C:233
 drag_and_drop.C:234
 drag_and_drop.C:235
 drag_and_drop.C:236
 drag_and_drop.C:237
 drag_and_drop.C:238
 drag_and_drop.C:239
 drag_and_drop.C:240
 drag_and_drop.C:241
 drag_and_drop.C:242
 drag_and_drop.C:243
 drag_and_drop.C:244
 drag_and_drop.C:245
 drag_and_drop.C:246
 drag_and_drop.C:247
 drag_and_drop.C:248
 drag_and_drop.C:249
 drag_and_drop.C:250
 drag_and_drop.C:251
 drag_and_drop.C:252
 drag_and_drop.C:253
 drag_and_drop.C:254
 drag_and_drop.C:255
 drag_and_drop.C:256
 drag_and_drop.C:257
 drag_and_drop.C:258
 drag_and_drop.C:259
 drag_and_drop.C:260
 drag_and_drop.C:261
 drag_and_drop.C:262
 drag_and_drop.C:263
 drag_and_drop.C:264
 drag_and_drop.C:265
 drag_and_drop.C:266
 drag_and_drop.C:267
 drag_and_drop.C:268
 drag_and_drop.C:269
 drag_and_drop.C:270
 drag_and_drop.C:271
 drag_and_drop.C:272
 drag_and_drop.C:273
 drag_and_drop.C:274
 drag_and_drop.C:275
 drag_and_drop.C:276
 drag_and_drop.C:277
 drag_and_drop.C:278
 drag_and_drop.C:279
 drag_and_drop.C:280
 drag_and_drop.C:281
 drag_and_drop.C:282
 drag_and_drop.C:283
 drag_and_drop.C:284
 drag_and_drop.C:285
 drag_and_drop.C:286
 drag_and_drop.C:287
 drag_and_drop.C:288
 drag_and_drop.C:289
 drag_and_drop.C:290
 drag_and_drop.C:291
 drag_and_drop.C:292
 drag_and_drop.C:293
 drag_and_drop.C:294
 drag_and_drop.C:295
 drag_and_drop.C:296
 drag_and_drop.C:297
 drag_and_drop.C:298
 drag_and_drop.C:299
 drag_and_drop.C:300
 drag_and_drop.C:301
 drag_and_drop.C:302
 drag_and_drop.C:303
 drag_and_drop.C:304
 drag_and_drop.C:305
 drag_and_drop.C:306
 drag_and_drop.C:307
 drag_and_drop.C:308
 drag_and_drop.C:309
 drag_and_drop.C:310
 drag_and_drop.C:311
 drag_and_drop.C:312
 drag_and_drop.C:313
 drag_and_drop.C:314
 drag_and_drop.C:315
 drag_and_drop.C:316
 drag_and_drop.C:317
 drag_and_drop.C:318
 drag_and_drop.C:319
 drag_and_drop.C:320
 drag_and_drop.C:321
 drag_and_drop.C:322
 drag_and_drop.C:323
 drag_and_drop.C:324
 drag_and_drop.C:325
 drag_and_drop.C:326
 drag_and_drop.C:327
 drag_and_drop.C:328
 drag_and_drop.C:329
 drag_and_drop.C:330
 drag_and_drop.C:331
 drag_and_drop.C:332
 drag_and_drop.C:333
 drag_and_drop.C:334
 drag_and_drop.C:335
 drag_and_drop.C:336
 drag_and_drop.C:337
 drag_and_drop.C:338
 drag_and_drop.C:339
 drag_and_drop.C:340
 drag_and_drop.C:341
 drag_and_drop.C:342
 drag_and_drop.C:343
 drag_and_drop.C:344
 drag_and_drop.C:345
 drag_and_drop.C:346
 drag_and_drop.C:347
 drag_and_drop.C:348
 drag_and_drop.C:349
 drag_and_drop.C:350
 drag_and_drop.C:351
 drag_and_drop.C:352
 drag_and_drop.C:353
 drag_and_drop.C:354
 drag_and_drop.C:355
 drag_and_drop.C:356
 drag_and_drop.C:357
 drag_and_drop.C:358
 drag_and_drop.C:359
 drag_and_drop.C:360
 drag_and_drop.C:361
 drag_and_drop.C:362
 drag_and_drop.C:363
 drag_and_drop.C:364
 drag_and_drop.C:365
 drag_and_drop.C:366
 drag_and_drop.C:367
 drag_and_drop.C:368
 drag_and_drop.C:369
 drag_and_drop.C:370
 drag_and_drop.C:371
 drag_and_drop.C:372
 drag_and_drop.C:373
 drag_and_drop.C:374
 drag_and_drop.C:375
 drag_and_drop.C:376
 drag_and_drop.C:377
 drag_and_drop.C:378
 drag_and_drop.C:379
 drag_and_drop.C:380
 drag_and_drop.C:381
 drag_and_drop.C:382
 drag_and_drop.C:383
 drag_and_drop.C:384
 drag_and_drop.C:385
 drag_and_drop.C:386
 drag_and_drop.C:387
 drag_and_drop.C:388
 drag_and_drop.C:389
 drag_and_drop.C:390
 drag_and_drop.C:391
 drag_and_drop.C:392
 drag_and_drop.C:393
 drag_and_drop.C:394
 drag_and_drop.C:395
 drag_and_drop.C:396
 drag_and_drop.C:397
 drag_and_drop.C:398
 drag_and_drop.C:399
 drag_and_drop.C:400
 drag_and_drop.C:401
 drag_and_drop.C:402
 drag_and_drop.C:403
 drag_and_drop.C:404
 drag_and_drop.C:405
 drag_and_drop.C:406
 drag_and_drop.C:407
 drag_and_drop.C:408
 drag_and_drop.C:409
 drag_and_drop.C:410
 drag_and_drop.C:411
 drag_and_drop.C:412
 drag_and_drop.C:413
 drag_and_drop.C:414
 drag_and_drop.C:415
thumb