Logo ROOT  
Reference Guide
TGuiBldDragManager.cxx
Go to the documentation of this file.
1 // @(#)root/guibuilder:$Id: 99541fed972db7e4279fadcd4c0a0f0ae28a0a4d $
2 // Author: Valeriy Onuchin 12/09/04
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 
13 #include "TGuiBldDragManager.h"
14 #include "TGuiBldEditor.h"
15 #include "TRootGuiBuilder.h"
16 
17 #include "TTimer.h"
18 #include "TList.h"
19 #include "TClass.h"
20 #include "TSystem.h"
21 #include "TROOT.h"
22 #include "TColor.h"
23 #include "TImage.h"
24 
25 #include "TError.h"
26 #include "TClassMenuItem.h"
27 #include "TMethod.h"
28 #include "TMethodCall.h"
29 #include "TBaseClass.h"
30 #include "TDataMember.h"
31 #include "TMethodArg.h"
32 #include "TToggle.h"
33 #include "TDataType.h"
34 #include "TObjString.h"
35 #include "TInterpreter.h"
36 
37 #include "KeySymbols.h"
38 #include "TGResourcePool.h"
39 #include "TGMenu.h"
40 #include "TGFileDialog.h"
41 #include "TGMsgBox.h"
42 #include "TRandom.h"
43 #include "TGButton.h"
44 #include "TGMdi.h"
45 #include "TGTextEntry.h"
46 #include "TGDockableFrame.h"
47 #include "TGColorDialog.h"
48 #include "TGFontDialog.h"
49 #include "TGComboBox.h"
50 #include "TGCanvas.h"
51 #include "TGLabel.h"
52 #include "TGProgressBar.h"
53 #include "TGScrollBar.h"
54 #include "TVirtualX.h"
55 #include "strlcpy.h"
56 #include "snprintf.h"
57 
58 #undef DEBUG_LOCAL
59 
60 //_____________________________________________________________________________
61 //
62 // TGuiBldDragManager
63 //
64 // Drag and drop manager used by the ROOT GUI Builder.
65 //_____________________________________________________________________________
66 
68 
69 static UInt_t gGridStep = 8;
73 
74 static const char *gSaveMacroTypes[] = {
75  "Macro files", "*.C",
76  "All files", "*",
77  0, 0
78 };
79 
80 static const char *gImageTypes[] = {
81  "All files", "*",
82  "XPM", "*.xpm",
83  "GIF", "*.gif",
84  "PNG", "*.png",
85  "JPEG", "*.jpg",
86  "TARGA", "*.tga",
87  "BMP", "*.bmp",
88  "ICO", "*.ico",
89  "XCF", "*.xcf",
90  "CURSORS", "*.cur",
91  "PPM", "*.ppm",
92  "PNM", "*.pnm",
93  "XBM", "*.xbm",
94  "TIFF", "*.tiff",
95  "Enacapsulated PostScript", "*.eps",
96  "PostScript", "*.ps",
97  "PDF", "*.pdf",
98  "ASImage XML","*.xml",
99  0, 0
100 };
101 
102 
103 ////////////////////////////////////////////////////////////////////////////////
104 
105 
106 class TGuiBldMenuDialog : public TGTransientFrame {
107 
108 friend class TGuiBldDragManager;
109 
110 public:
111  TGButton *fOK; // OK button
112  //TGButton *fApply; // apply button
113  TGButton *fCancel; // cancel button
114  TObject *fObject; // selected object/frame
115  TMethod *fMethod; // method to be applied
116  TGLayoutHints *fL1; // internally used layout hints
117  TGLayoutHints *fL2; // internally used layout hints
118  TList *fWidgets; // list of widgets
119 
120 public:
121  virtual ~TGuiBldMenuDialog();
122  TGuiBldMenuDialog(const TGWindow *main, TObject *obj, TMethod *method);
123 
124  const char *GetParameters();
125  void CloseWindow();
126  void ConnectButtonSignals();
127  void Build();
128  void Popup();
129  void ApplyMethod();
130  void Add(const char *argname, const char *value, const char *type);
131 
132 };
133 
135 
136 
137 ////////////////////////////////////////////////////////////////////////////////
138 /// ctor.
139 
140 TGuiBldMenuDialog::TGuiBldMenuDialog(const TGWindow *main, TObject *obj, TMethod *method) :
141  TGTransientFrame(gClient->GetDefaultRoot(), main, 200, 100)
142 {
143  fObject = obj;
144  fMethod = method;
145  if (!obj) return; // zombie
146 
147  fWidgets = new TList();
148 
149  fL1 = new TGLayoutHints(kLHintsTop | kLHintsCenterX, 0, 0, 5, 0);
150  fL2 = new TGLayoutHints(kLHintsTop | kLHintsLeft, 5, 5, 5, 5);
151 
152  TString title = obj->ClassName();
153  title += "::";
154  title += method->GetName();
155 
156  Build();
157  ConnectButtonSignals();
158 
159  SetWindowName(title);
160  SetIconName(title);
162 
163  //TRootGuiBuilder::PropagateBgndColor(this, TRootGuiBuilder::GetBgnd());
164 }
165 
166 ////////////////////////////////////////////////////////////////////////////////
167 /// dtor.
168 
169 TGuiBldMenuDialog::~TGuiBldMenuDialog()
170 {
171  fWidgets->Delete();
172  delete fWidgets;
173  delete fL1;
174  delete fL2;
175 }
176 
177 ////////////////////////////////////////////////////////////////////////////////
178 /// Connect buttons signals
179 
180 void TGuiBldMenuDialog::ConnectButtonSignals()
181 {
182  fOK->Connect("Pressed()", "TGuiBldDragManager", gGuiBldDragManager, "DoDialogOK()");
183  //fApply->Connect("Pressed()", "TGuiBldDragManager", gGuiBldDragManager, "DoDialogApply()");
184  fCancel->Connect("Pressed()", "TGuiBldDragManager", gGuiBldDragManager, "DoDialogCancel()");
185 }
186 
187 ////////////////////////////////////////////////////////////////////////////////
188 /// execute method for obejct with input args
189 
190 void TGuiBldMenuDialog::ApplyMethod()
191 {
192  const char *params = GetParameters();
193  fObject->Execute(fMethod->GetName(), params);
194 }
195 
196 ////////////////////////////////////////////////////////////////////////////////
197 /// Return input parameters as single string.
198 
200 {
201  static char params[1024];
202  char param[256];
203 
204  TObjString *str;
205  TObject *obj;
206 
207  Int_t selfobjpos;
208 // if (fMenu->GetContextMenu()->GetSelectedMenuItem())
209 // selfobjpos = fMenu->GetContextMenu()->GetSelectedMenuItem()->GetSelfObjectPos();
210 // else
211  selfobjpos = -1;
212 
213  params[0] = 0;
214  TIter next(fWidgets);
215  Int_t nparam = 0;
216 
217  while ((obj = next())) { // first element is label, skip...
218  if (obj->IsA() != TGLabel::Class()) break;
219  obj = next(); // get either TGTextEntry or TGComboBox
220  str = (TObjString *) next(); // get type string
221 
222  nparam++;
223 
224  const char *type = str->GetString().Data();
225  const char *data = 0;
226 
227  if (obj->IsA() == TGTextEntry::Class())
228  data = ((TGTextEntry *) obj)->GetBuffer()->GetString();
229 
230  // TODO: Combobox...
231 
232  // if necessary, replace the selected object by it's address
233  if (selfobjpos == nparam-1) {
234  if (params[0]) strlcat(params, ",", 1024-strlen(params));
235  snprintf(param, 255, "(TObject*)0x%lx", (Long_t)fObject);
236  strlcat(params, param, 1024-strlen(params));
237  }
238 
239  if (params[0]) strlcat(params, ",", 1024-strlen(params));
240  if (data) {
241  if (!strncmp(type, "char*", 5))
242  snprintf(param, 255, "\"%s\"", data);
243  else
244  strlcpy(param, data, sizeof(param));
245  } else
246  strlcpy(param, "0", sizeof(param));
247 
248  strlcat(params, param, 1024-strlen(params));
249  }
250 
251  // if selected object is the last argument, have to insert it here
252  if (selfobjpos == nparam) {
253  if (params[0]) strlcat(params, ",", 1024-strlen(params));
254  snprintf(param, 255, "(TObject*)0x%lx", (Long_t)fObject);
255  strlcat(params, param, 1024-strlen(params));
256  }
257 
258  return params;
259 }
260 
261 ////////////////////////////////////////////////////////////////////////////////
262 /// Create a string describing method argument.
263 
265 {
266  static TString ret;
267 
268  if (argument) {
269  ret.Form("(%s) %s", argument->GetTitle(), argument->GetName());
270  if (argument->GetDefault() && *(argument->GetDefault())) {
271  ret += " [default: ";
272  ret += argument->GetDefault();
273  ret += "]";
274  }
275  }
276 
277  return ret;
278 }
279 
280 ////////////////////////////////////////////////////////////////////////////////
281 /// Add a label and text input field.
282 
283 void TGuiBldMenuDialog::Add(const char *argname, const char *value, const char *type)
284 {
285  TGLabel *l = new TGLabel(this, argname);
286  TGTextBuffer *b = new TGTextBuffer(20);
287  b->AddText(0, value);
288  TGTextEntry *t = new TGTextEntry(this, b);
289 
290  t->Connect("ReturnPressed()", "TGuiBldDragManager", gGuiBldDragManager, "DoDialogOK()");
291  t->Resize(260, t->GetDefaultHeight());
292  AddFrame(l, fL1);
293  AddFrame(t, fL2);
294 
295  fWidgets->Add(l);
296  fWidgets->Add(t);
297  fWidgets->Add(new TObjString(type));
298 }
299 
300 ////////////////////////////////////////////////////////////////////////////////
301 /// Close window
302 
303 void TGuiBldMenuDialog::CloseWindow()
304 {
306 }
307 
308 ////////////////////////////////////////////////////////////////////////////////
309 /// Build dialog
310 
311 void TGuiBldMenuDialog::Build()
312 {
313  TMethodArg *argument = 0;
314  Int_t selfobjpos = -1;
315 
316  TIter next(fMethod->GetListOfMethodArgs());
317  Int_t argpos = 0;
318 
319  while ((argument = (TMethodArg *) next())) {
320  // Do not input argument for self object
321  if (selfobjpos != argpos) {
322  TString arg_name = CreateArgumentTitle(argument);
323  const char *argname = arg_name.Data();
324  const char *type = argument->GetTypeName();
325  TDataType *datatype = gROOT->GetType(type);
326  const char *charstar = "char*";
327  char basictype[32];
328 
329  if (datatype) {
330  strlcpy(basictype, datatype->GetTypeName(), sizeof(basictype));
331  } else {
333  if (strncmp(type, "enum", 4) && (cl && !(cl->Property() & kIsEnum)))
334  Warning("Dialog", "data type is not basic type, assuming (int)");
335  strlcpy(basictype, "int", sizeof(basictype));
336  }
337 
338  if (strchr(argname, '*')) {
339  strlcat(basictype, "*", 32-strlen(basictype));
340  type = charstar;
341  }
342 
343  TDataMember *m = argument->GetDataMember();
344  if (m && m->GetterMethod(fObject->IsA())) {
345 
346  // Get the current value and form it as a text:
347  char val[256];
348 
349  if (!strncmp(basictype, "char*", 5)) {
350  char *tdefval = 0;
351  m->GetterMethod()->Execute(fObject, "", &tdefval);
352  if (tdefval && strlen(tdefval))
353  strlcpy(val, tdefval, sizeof(val));
354  } else if (!strncmp(basictype, "float", 5) ||
355  !strncmp(basictype, "double", 6)) {
356  Double_t ddefval = 0.0;
357  m->GetterMethod()->Execute(fObject, "", ddefval);
358  snprintf(val, 255, "%g", ddefval);
359  } else if (!strncmp(basictype, "char", 4) ||
360  !strncmp(basictype, "bool", 4) ||
361  !strncmp(basictype, "int", 3) ||
362  !strncmp(basictype, "long", 4) ||
363  !strncmp(basictype, "short", 5)) {
364  Long_t ldefval = 0L;
365  m->GetterMethod()->Execute(fObject, "", ldefval);
366  snprintf(val, 255, "%li", ldefval);
367  }
368 
369  // Find out whether we have options ...
370 
371  TList *opt;
372  // coverity[returned_pointer]: keep for later use
373  if ((opt = m->GetOptions())) {
374  Warning("Dialog", "option menu not yet implemented");
375 
376  } else {
377  // we haven't got options - textfield ...
378  Add(argname, val, type);
379  }
380  } else { // if m not found ...
381 
382  char val[256] = "";
383  const char *tval = argument->GetDefault();
384  if (tval) strlcpy(val, tval, sizeof(val));
385  Add(argname, val, type);
386  }
387  }
388  argpos++;
389  }
390 
391  // add OK, Apply, Cancel buttons
392  TGHorizontalFrame *hf = new TGHorizontalFrame(this, 60, 20, kFixedWidth);
393  TGLayoutHints *l1 = new TGLayoutHints(kLHintsCenterY | kLHintsExpandX, 5, 5, 0, 0);
394  UInt_t width = 0, height = 0;
395 
396  fWidgets->Add(l1);
397 
398  fOK = new TGTextButton(hf, "&OK", 1);
399  hf->AddFrame(fOK, l1);
400  fWidgets->Add(fOK);
401  height = fOK->GetDefaultHeight();
402  width = TMath::Max(width, fOK->GetDefaultWidth());
403 
404 /*
405  fApply = new TGTextButton(hf, "&Apply", 2);
406  hf->AddFrame(fApply, l1);
407  fWidgets->Add(fApply);
408  height = fApply->GetDefaultHeight();
409  width = TMath::Max(width, fApply->GetDefaultWidth());
410 */
411 
412  fCancel = new TGTextButton(hf, "&Cancel", 3);
413  hf->AddFrame(fCancel, l1);
414  fWidgets->Add(fCancel);
415  height = fCancel->GetDefaultHeight();
416  width = TMath::Max(width, fCancel->GetDefaultWidth());
417 
418  // place buttons at the bottom
419  l1 = new TGLayoutHints(kLHintsBottom | kLHintsCenterX, 0, 0, 5, 5);
420  AddFrame(hf, l1);
421  fWidgets->Add(l1);
422  fWidgets->Add(hf);
423 
424  hf->Resize((width + 20) * 3, height);
425 
426  // map all widgets and calculate size of dialog
427  MapSubwindows();
428 }
429 
430 ////////////////////////////////////////////////////////////////////////////////
431 /// Popup dialog.
432 
433 void TGuiBldMenuDialog::Popup()
434 {
436  UInt_t height = GetDefaultHeight();
437 
438  Resize(width, height);
439 
440  Window_t wdummy;
441  Int_t x = (Int_t)((TGFrame*)fMain)->GetWidth();
442  Int_t y = (Int_t)((TGFrame*)fMain)->GetHeight();
443  gVirtualX->TranslateCoordinates(fMain->GetId(), fClient->GetDefaultRoot()->GetId(),
444  x, y, x, y, wdummy);
445 
446  x += 10;
447  y += 10;
448 
449  // make the message box non-resizable
450  SetWMSize(width, height);
451  SetWMSizeHints(width, height, width, height, 0, 0);
452 
458 
459  Move(x, y);
460  SetWMPosition(x, y);
461  MapRaised();
462  fClient->WaitFor(this);
463 }
464 
465 
466 ///////////////////////// auxilary static functions ///////////////////////////
467 ////////////////////////////////////////////////////////////////////////////////
468 /// Helper. Return a window located at point x,y (in screen coordinates)
469 
471 {
472  Window_t src, dst, child;
473  Window_t ret = 0;
474  Int_t xx = x;
475  Int_t yy = y;
476 
478  !gClient->IsEditable()) return 0;
479 
480  dst = src = child = gVirtualX->GetDefaultRootWindow();
481 
482  while (child && dst) {
483  src = dst;
484  dst = child;
485  gVirtualX->TranslateCoordinates(src, dst, xx, yy, xx, yy, child);
486  ret = dst;
487  }
488  return ret;
489 }
490 
491 ////////////////////////////////////////////////////////////////////////////////
492 /// Helper to layout
493 
494 static void layoutFrame(TGFrame *frame)
495 {
496  if (!frame || !frame->InheritsFrom(TGCompositeFrame::Class())) {
497  return;
498  }
499 
500  TGCompositeFrame *comp = (TGCompositeFrame*)frame;
501 
502  if (comp->GetLayoutManager()) {
503  comp->GetLayoutManager()->Layout();
504  } else {
505  comp->Layout();
506  }
507  gClient->NeedRedraw(comp);
508 
509  TIter next(comp->GetList());
510  TGFrameElement *fe;
511 
512  while ((fe = (TGFrameElement*)next())) {
513  layoutFrame(fe->fFrame);
514  gClient->NeedRedraw(fe->fFrame);
515  }
516 }
517 
518 ////////////////////////////////////////////////////////////////////////////////
519 /// Our own error handler (not used yet)
520 
521 static void GuiBldErrorHandler(Int_t /*level*/, Bool_t /*abort*/,
522  const char * /*location*/, const char * /*msg*/)
523 {
524 }
525 
526 ////////////////////////////////////////////////////////////////////////////////
527 class TGuiBldDragManagerGrid {
528 
529 public:
530  static UInt_t fgStep;
531  static ULong_t fgPixel;
532  static TGGC *fgBgnd;
533 
534  Pixmap_t fPixmap;
535  TGWindow *fWindow;
536  Int_t fWinId;
537 
538  TGuiBldDragManagerGrid();
539  ~TGuiBldDragManagerGrid();
540  void Draw();
541  void SetStep(UInt_t step);
542  void InitPixmap();
543  void InitBgnd();
544 };
545 
546 UInt_t TGuiBldDragManagerGrid::fgStep = gGridStep;
547 ULong_t TGuiBldDragManagerGrid::fgPixel = 0;
548 TGGC *TGuiBldDragManagerGrid::fgBgnd = 0;
549 
550 ////////////////////////////////////////////////////////////////////////////////
551 /// Create a grid background for the selected window
552 
553 TGuiBldDragManagerGrid::TGuiBldDragManagerGrid()
554 {
555  fPixmap = 0;
556  fWindow = 0;
557  fWinId = 0;
558 
559  if (!fgBgnd) {
560  InitBgnd();
561  }
562  SetStep(fgStep);
563 }
564 
565 ////////////////////////////////////////////////////////////////////////////////
566 /// ctor.
567 
568 TGuiBldDragManagerGrid::~TGuiBldDragManagerGrid()
569 {
570  fWindow = gClient->GetWindowById(fWinId);
571 
572  if (fWindow) {
573  fWindow->SetBackgroundPixmap(0);
574  fWindow->SetBackgroundColor(((TGFrame*)fWindow)->GetBackground());
575  gClient->NeedRedraw(fWindow, kTRUE);
576  }
577  if (fPixmap) {
578  gVirtualX->DeletePixmap(fPixmap);
579  }
580 
581  fPixmap = 0;
582  fWindow = 0;
583  fWinId = 0;
584 }
585 
586 ////////////////////////////////////////////////////////////////////////////////
587 /// Set the grid step
588 
589 void TGuiBldDragManagerGrid::SetStep(UInt_t step)
590 {
591  if (!gClient || !gClient->IsEditable()) {
592  return;
593  }
594 
595  fWindow = (TGWindow*)gClient->GetRoot();
596  fWinId = fWindow->GetId();
597  fgStep = step;
598  InitPixmap();
599 
600 }
601 
602 ////////////////////////////////////////////////////////////////////////////////
603 /// Create grid background.
604 
605 void TGuiBldDragManagerGrid::InitBgnd()
606 {
607  if (fgBgnd) {
608  return;
609  }
610 
611  fgBgnd = new TGGC(TGFrame::GetBckgndGC());
612 
613  Float_t r, g, b;
614 
615  r = 232./255;
616  g = 232./255;
617  b = 226./255;
618 
619  fgPixel = TColor::RGB2Pixel(r, g, b);
620  fgBgnd->SetForeground(fgPixel);
621 }
622 
623 ////////////////////////////////////////////////////////////////////////////////
624 /// Create grid background pixmap
625 
626 void TGuiBldDragManagerGrid::InitPixmap()
627 {
628  if (fPixmap) {
629  gVirtualX->DeletePixmap(fPixmap);
630  }
631 
632  fPixmap = gVirtualX->CreatePixmap(gClient->GetDefaultRoot()->GetId(), fgStep, fgStep);
633  gVirtualX->FillRectangle(fPixmap, fgBgnd->GetGC(), 0, 0, fgStep, fgStep);
634 
635  if(fgStep > 2) {
636  gVirtualX->FillRectangle(fPixmap, TGFrame::GetShadowGC()(),
637  fgStep - 1, fgStep - 1, 1, 1);
638  }
639 }
640 
641 ////////////////////////////////////////////////////////////////////////////////
642 /// Draw grid over editted frame.
643 
645 {
646  if (!gClient || !gClient->IsEditable()) {
647  return;
648  }
649 
650  fWindow = gClient->GetWindowById(fWinId);
651 
652  if (fWindow && (fWindow != gClient->GetRoot())) {
653  fWindow->SetBackgroundPixmap(0);
654  fWindow->SetBackgroundColor(((TGFrame*)fWindow)->GetBackground());
655  gClient->NeedRedraw(fWindow);
656  }
657 
658  if (!fPixmap) {
659  InitPixmap();
660  }
661 
662  fWindow = (TGWindow*)gClient->GetRoot();
663  fWinId = fWindow->GetId();
664  fWindow->SetBackgroundPixmap(fPixmap);
665 
666  gClient->NeedRedraw(fWindow);
667 }
668 
669 
670 ////////////////////////////////////////////////////////////////////////////////
671 class TGuiBldDragManagerRepeatTimer : public TTimer {
672 
673 private:
674  TGuiBldDragManager *fManager; // back pointer
675 
676 public:
677  TGuiBldDragManagerRepeatTimer(TGuiBldDragManager *m, Long_t ms) :
678  TTimer(ms, kTRUE) { fManager = m; }
679  Bool_t Notify() { fManager->HandleTimer(this); Reset(); return kFALSE; }
680 };
681 
682 
683 ////////////////////////////////////////////////////////////////////////////////
684 class TGGrabRect : public TGFrame {
685 
686 private:
687  Pixmap_t fPixmap;
688  ECursor fType;
689 
690 public:
691  TGGrabRect(Int_t type);
692  ~TGGrabRect() {}
693 
695  ECursor GetType() const { return fType; }
696 };
697 
698 ////////////////////////////////////////////////////////////////////////////////
699 /// ctor.
700 
701 TGGrabRect::TGGrabRect(Int_t type) :
702  TGFrame(gClient->GetDefaultRoot(), 8, 8, kTempFrame)
703 {
704  fType = kTopLeft;
705 
706  switch (type) {
707  case 0:
708  fType = kTopLeft;
709  break;
710  case 1:
711  fType = kTopSide;
712  break;
713  case 2:
714  fType = kTopRight;
715  break;
716  case 3:
717  fType = kBottomLeft;
718  break;
719  case 4:
720  fType = kLeftSide;
721  break;
722  case 5:
723  fType = kRightSide;
724  break;
725  case 6:
726  fType = kBottomSide;
727  break;
728  case 7:
729  fType = kBottomRight;
730  break;
731  }
732 
735  attr.fOverrideRedirect = kTRUE;
736  attr.fSaveUnder = kTRUE;
737 
738  gVirtualX->ChangeWindowAttributes(fId, &attr);
739 
740  fPixmap = gVirtualX->CreatePixmap(gVirtualX->GetDefaultRootWindow(), 8, 8);
741  const TGGC *bgc = TRootGuiBuilder::GetPopupHlghtGC();
742 //fClient->GetResourcePool()->GetSelectedBckgndGC();
743  TGGC *gc = new TGGC(TGFrame::GetBckgndGC());
744 
745  Pixel_t back;
746  fClient->GetColorByName("black", back);
747  gc->SetBackground(back);
748  gc->SetForeground(back);
749 
750  gVirtualX->FillRectangle(fPixmap, bgc->GetGC(), 0, 0, 7, 7);
751  gVirtualX->DrawRectangle(fPixmap, gc->GetGC(), 0, 0, 7, 7);
752 // gVirtualX->DrawRectangle(fPixmap, fClient->GetResourcePool()->GetSelectedBckgndGC()->GetGC(), 1, 1, 5, 5);
753 
754  AddInput(kButtonPressMask);
755  SetBackgroundPixmap(fPixmap);
756 
757  gVirtualX->SetCursor(fId, gVirtualX->CreateCursor(fType));
758 }
759 
760 ////////////////////////////////////////////////////////////////////////////////
761 /// Handle button press event.
762 
763 Bool_t TGGrabRect::HandleButton(Event_t *ev)
764 {
766  return kTRUE;
767 }
768 
769 ////////////////////////////////////////////////////////////////////////////////
770 class TGAroundFrame : public TGFrame {
771 
772 public:
773  TGAroundFrame();
774  ~TGAroundFrame() {}
775 };
776 
777 ////////////////////////////////////////////////////////////////////////////////
778 /// ctor.
779 
780 TGAroundFrame::TGAroundFrame() : TGFrame(gClient->GetDefaultRoot(), 1, 1,
782 {
785  attr.fOverrideRedirect = kTRUE;
786  attr.fSaveUnder = kTRUE;
787 
788  gVirtualX->ChangeWindowAttributes(fId, &attr);
789  ULong_t blue;
790  fClient->GetColorByName("blue", blue);
791  SetBackgroundColor(blue);
792 }
793 
794 
795 ////////////////////////////////////////////////////////////////////////////////
796 class TGuiBldDragManagerPimpl {
797 
798 friend class TGuiBldDragManager;
799 
800 private:
801  TGuiBldDragManager *fManager; // drag and drop manager
802  TTimer *fRepeatTimer; // repeat rate timer (when mouse stays pressed)
803  TGFrame *fGrab; // grabbed/selected frame
804  TGLayoutHints *fGrabLayout; // layout of grabbed frame
805  TGFrame *fSaveGrab; // used during context menu handling
806  TGFrame *fClickFrame; // last clicked frame
807  TGuiBldDragManagerGrid *fGrid; //
808  ECursor fResizeType; // defines resize type
809  Int_t fX0, fY0; // initial drag position in pixels
810  Int_t fX, fY; // current drag position in pixels
811  Int_t fXf, fYf; // offset of inititial position inside frame
812  Int_t fGrabX, fGrabY; //
813  const TGWindow *fGrabParent; // parent of the grabbed/seleceted frame
814  Int_t fLastPopupAction;//
815  Bool_t fReplaceOn;
816  TGGrabRect *fGrabRect[8]; // small rectangles drawn over grabbed/selected frame
817  TGFrame *fAroundFrame[4]; // red lines drawn over layouted frame
818  Bool_t fGrabRectHidden;
819  TGFrameElement *fGrabListPosition;
820  Bool_t fButtonPressed; //
821  Bool_t fCompacted; //
822  TGFrame *fPlane; // highlighted plain composite frame when mose is moving
823  TGFrame *fSpacePressedFrame; // frame which was grabbed via spacebar pressed
824  Bool_t fPlacePopup; // kTRUE is menu fo frame was placed
825  TList *fFrameMenuTrash; // trash list
826  TGFrame *fMenuObject; // object/frame for which context menu is created
827 
828 public:
829  TGuiBldDragManagerPimpl(TGuiBldDragManager *m) {
830  fManager = m;
831  fRepeatTimer = new TGuiBldDragManagerRepeatTimer(m, 100);
832 
833  int i = 0;
834  for (i = 0; i <8; i++) {
835  fGrabRect[i] = new TGGrabRect(i);
836  }
837  for (i = 0; i <4; i++) {
838  fAroundFrame[i] = new TGAroundFrame();
839  }
840 
841  fFrameMenuTrash = new TList();
842 
843  ResetParams();
844  }
845  void ResetParams() {
846  fGrab = 0;
847  fSaveGrab = 0;
848  fClickFrame = 0;
849  fGrid = 0;
850  fX0 = fY0 = fX = fY = fXf = fYf = fGrabX = fGrabY = 0;
851  fGrabParent = 0;
852  fResizeType = kPointer;
853  fLastPopupAction = kNoneAct;
854  fReplaceOn = kFALSE;
855  fGrabLayout = 0;
856  fGrabRectHidden = kFALSE;
857  fGrabListPosition = 0;
858  fButtonPressed = kFALSE;
859  fCompacted = kFALSE;
860  fPlane = 0;
861  fSpacePressedFrame = 0;
862  fPlacePopup = kFALSE;
863  fFrameMenuTrash->Delete();
864  fMenuObject = 0;
865  }
866 
867  ~TGuiBldDragManagerPimpl() {
868  int i;
869  for (i = 0; i <8; i++) {
870  delete fGrabRect[i];
871  }
872  for (i = 0; i <4; i++) {
873  delete fAroundFrame[i];
874  }
875 
876  delete fRepeatTimer;
877  delete fGrab;
878  fFrameMenuTrash->Delete();
879  delete fFrameMenuTrash;
880 
881  if (fPlane) {
882  fPlane->ChangeOptions(fPlane->GetOptions() & ~kRaisedFrame);
883  gClient->NeedRedraw(fPlane, kTRUE);
884  fPlane = 0;
885  }
886  }
887 };
888 
889 
890 ////////////////////////////////////////////////////////////////////////////////
892  TGFrame(gClient->GetDefaultRoot(), 1, 1)
893 {
894  // Constructor. Create "fantom window".
895 
898  attr.fOverrideRedirect = kTRUE;
899  attr.fSaveUnder = kTRUE;
900 
901  gVirtualX->ChangeWindowAttributes(fId, &attr);
902 
903  gGuiBldDragManager = this;
904  fPimpl = new TGuiBldDragManagerPimpl(this);
905 
907  fFrameMenu = 0;
908  fLassoMenu = 0;
909  fEditor = 0;
910  fBuilder = 0;
913  fStop = kTRUE;
914  fSelected = 0;
915  fListOfDialogs = 0;
916 
917  Reset1();
919 
920  TString tmpfile = gSystem->TempDirectory();
921  char *s = gSystem->ConcatFileName(tmpfile.Data(),
922  TString::Format("RootGuiBldClipboard%d.C", gSystem->GetPid()));
923  fPasteFileName = s;
924  delete [] s;
925 
926  s = gSystem->ConcatFileName(tmpfile.Data(),
927  TString::Format("RootGuiBldTmpFile%d.C", gSystem->GetPid()));
928  fTmpBuildFile = s;
929  delete [] s;
930 
931  fName = "Gui Builder Drag Manager";
933 
934  // let's try to solve the problems by myself
936 
937  fClient->UnregisterWindow(this);
938 }
939 
940 ////////////////////////////////////////////////////////////////////////////////
941 /// Destructor
942 
944 {
946 
947  delete fPimpl;
948 
949  delete fBuilder;
950  fBuilder = 0;
951 
952 // delete fEditor;
953 // fEditor = 0;
954 
955  delete fFrameMenu;
956  fFrameMenu =0;
957 
958  delete fLassoMenu;
959  fLassoMenu = 0;
960 
963  }
964 
965  delete fListOfDialogs;
966 
967  gGuiBldDragManager = 0;
968 }
969 
970 ////////////////////////////////////////////////////////////////////////////////
971 /// Reset some parameters
972 
974 {
976  fTargetId = 0;
977  fPimpl->fPlacePopup = kFALSE;
979 }
980 
981 ////////////////////////////////////////////////////////////////////////////////
982 /// Create a list of dialog methods
983 
985 {
986  fListOfDialogs = new TList();
987 
988  TList *methodList = IsA()->GetListOfMethods();
989  TIter next(methodList);
990  TString str;
991  TMethod *method;
992 
993  while ((method = (TMethod*) next())) {
994  str = method->GetCommentString();
995  if (str.Contains("*DIALOG")) {
996  fListOfDialogs->Add(method);
997  }
998  }
999 }
1000 
1001 ////////////////////////////////////////////////////////////////////////////////
1002 /// Draw grid on editable frame and restore background on previuosly editted one
1003 
1005 {
1006  if (fStop) {
1007  return;
1008  }
1009 
1010  delete fPimpl->fGrid;
1011 
1012  fPimpl->fGrid = new TGuiBldDragManagerGrid();
1013  fPimpl->fGrid->Draw();
1014 }
1015 
1016 ////////////////////////////////////////////////////////////////////////////////
1017 /// Return the grid step
1018 
1020 {
1021  return fPimpl->fGrid ? fPimpl->fGrid->fgStep : 1;
1022 }
1023 
1024 ////////////////////////////////////////////////////////////////////////////////
1025 /// Set the grid step
1026 
1028 {
1029  fPimpl->fGrid->SetStep(step);
1030 }
1031 
1032 ////////////////////////////////////////////////////////////////////////////////
1033 /// Return kTRUE if event is rejected for processing by drag manager
1034 
1036 {
1037  if (fStop || !fClient || !fClient->IsEditable()) return kTRUE;
1038  if (event->fType == kClientMessage) return kFALSE;
1039  if (event->fType == kDestroyNotify) return kFALSE;
1040 
1041  TGWindow *w = fClient->GetWindowById(event->fWindow);
1042 
1043  if (w) {
1044  if (IsEditDisabled(w)) {
1045  w = GetEditableParent((TGFrame*)w);
1046  return !w;
1047  }
1048  } else {
1049  return kTRUE;
1050  }
1051  return kFALSE;
1052 }
1053 
1054 ////////////////////////////////////////////////////////////////////////////////
1055 /// Return a pointer to the parent window (which is being editted)
1056 
1058 {
1059  if (fStop || !id) {
1060  return 0;
1061  }
1062 
1063  Window_t preparent = id;
1064  Window_t parent = (Window_t)gVirtualX->GetParent(id);
1065 
1066  while (!parent || (parent != fClient->GetDefaultRoot()->GetId())) {
1067  if (parent == fClient->GetRoot()->GetId()) {
1068  TGWindow *w = fClient->GetWindowById(preparent);
1069  return (w ? (TGFrame*)w : 0);
1070  }
1071  preparent = parent;
1072  parent = gVirtualX->GetParent(parent);
1073  }
1074  return 0;
1075 }
1076 
1077 ////////////////////////////////////////////////////////////////////////////////
1078 /// Find the first composite parent of window
1079 
1081 {
1082  if (fStop || !id) {
1083  return 0;
1084  }
1085 
1086  Window_t parent = id;
1087 
1088  while (!parent || (parent != fClient->GetDefaultRoot()->GetId())) {
1089  TGWindow *w = fClient->GetWindowById(parent);
1090  if (w) {
1092  return (TGCompositeFrame*)w;
1093  }
1094  }
1095  parent = gVirtualX->GetParent(parent);
1096  }
1097  return 0;
1098 }
1099 
1100 ////////////////////////////////////////////////////////////////////////////////
1101 /// Set cursor for selcted/grabbed frame.
1102 
1104 {
1105  if (fStop) {
1106  return;
1107  }
1108 
1109  static UInt_t gid = 0;
1110  static UInt_t rid = 0;
1111 
1112  if (fPimpl->fGrab && (gid != fPimpl->fGrab->GetId())) {
1113  gVirtualX->SetCursor(fPimpl->fGrab->GetId(),
1114  gVirtualX->CreateCursor((ECursor)cur));
1115  gid = fPimpl->fGrab->GetId();
1116  }
1117  if (fClient->IsEditable() && (rid != fClient->GetRoot()->GetId())) {
1118  gVirtualX->SetCursor(fClient->GetRoot()->GetId(),
1119  gVirtualX->CreateCursor((ECursor)cur));
1120  rid = fClient->GetRoot()->GetId();
1121  }
1122 }
1123 
1124 ////////////////////////////////////////////////////////////////////////////////
1125 /// Check resize type event.
1126 
1128 {
1129  if (fStop) {
1130  return kFALSE;
1131  }
1132 
1133  Bool_t ret = kFALSE;
1134  fPimpl->fResizeType = kPointer;
1135 
1136  for (int i = 0; i < 8; i++) {
1137  if (fPimpl->fGrabRect[i]->GetId() == event->fWindow) {
1138  fPimpl->fResizeType = fPimpl->fGrabRect[i]->GetType();
1139  ret = kTRUE;
1140  }
1141  }
1142 
1143  if ((event->fType == kButtonPress) && (fPimpl->fResizeType != kPointer)) {
1145  ret = kTRUE;
1146  }
1147 
1148  SetCursorType(ret ? fPimpl->fResizeType : kPointer);
1149  return ret;
1150 }
1151 
1152 ////////////////////////////////////////////////////////////////////////////////
1153 /// Redraw the editted window
1154 
1156 {
1157  if (fStop || !fClient || !fClient->IsEditable()) {
1158  return;
1159  }
1160 
1161  TGWindow *root = (TGWindow*)fClient->GetRoot();
1162 
1163  fClient->NeedRedraw(root, kTRUE);
1164 
1165  if (fBuilder) {
1167  }
1168 }
1169 
1170 ////////////////////////////////////////////////////////////////////////////////
1171 /// Switch editable
1172 
1174 {
1175  if (fStop || !frame) {
1176  return;
1177  }
1178 
1179  TGCompositeFrame *comp = 0;
1180 
1181  if (frame->InheritsFrom(TGCompositeFrame::Class()) && CanChangeLayout(frame)) {
1182  comp = (TGCompositeFrame *)frame;
1183  } else if (frame->GetParent()->InheritsFrom(TGCompositeFrame::Class())) {
1184  comp = (TGCompositeFrame *)frame->GetParent();
1185  }
1186 
1187  if (!comp) {
1188  return;
1189  }
1190 
1191  TString str = comp->ClassName();
1192  str += "::";
1193  str += comp->GetName();
1194 
1195  if (IsEditDisabled(comp)) {
1196  if (fBuilder) {
1197  str += " cannot be editted.";
1198  fBuilder->UpdateStatusBar(str.Data());
1199  }
1200  return;
1201  }
1202 
1203  if (frame != comp) {
1204  SelectFrame(frame);
1205  }
1206 
1207  if (comp->IsEditable()) {
1208  return;
1209  }
1210 
1211  RaiseMdiFrame(comp);
1212  comp->SetEditable(kTRUE);
1213 }
1214 
1215 ////////////////////////////////////////////////////////////////////////////////
1216 /// Grab/Select frame
1217 
1219 {
1220  if (fStop || !frame || (frame->GetParent() == fClient->GetDefaultRoot()) ||
1221  !fClient->IsEditable()) {
1222  return;
1223  }
1224 
1225  TString str = frame->ClassName();
1226  str += "::";
1227  str += frame->GetName();
1228 
1229  if (IsGrabDisabled(frame)) {
1230  if (fBuilder) {
1231  str += "can not be selected";
1232  fBuilder->UpdateStatusBar(str.Data());
1233  }
1234  return;
1235  }
1236 
1237  // do not grab mdi frames (quick hack)
1238  if (fBuilder && frame->InheritsFrom(TGMdiFrame::Class())) {
1239  return;
1240  }
1241 
1242 
1243  static Int_t x, x0, y, y0, xx, yy;
1244  Window_t c;
1245 
1246  RaiseMdiFrame(FindMdiFrame(frame));
1247  frame->MapRaised();
1248 
1249  if (!add) {
1250 
1252 
1253  gVirtualX->TranslateCoordinates(frame->GetId(),
1255  0, 0, x0, y0, c);
1256 
1257  x = x0 + frame->GetWidth();
1258  y = y0 + frame->GetHeight();
1259 
1260  if (fBuilder) {
1261  str += " selected";
1262  str += (IsEditDisabled(frame) || IsFixedLayout(frame) ? ". This frame cannot be editted." :
1263  " ");
1264  str += " Press SpaceBar to unselect the frame.";
1265  if (IsFixedSize(frame)) str += " This frame cannot be resized.";
1266 
1267  fBuilder->UpdateStatusBar(str.Data());
1268  }
1269 
1270  } else { //shift mask is on
1271 
1272  gVirtualX->TranslateCoordinates(frame->GetId(),
1274  0, 0, xx, yy, c);
1275 
1277  fPimpl->fX0 = x0 = TMath::Min(x0, xx);
1278  fPimpl->fX = x = TMath::Max(x, xx + (Int_t)frame->GetWidth());
1279  fPimpl->fY0 = y0 = TMath::Min(y0, yy);
1280  fPimpl->fY = y = TMath::Max(y, yy + (Int_t)frame->GetHeight());
1281 
1282  DrawLasso();
1283  }
1284 
1285  fFrameUnder = fPimpl->fGrab = frame;
1286  fPimpl->fGrab->RequestFocus();
1287 
1288  // quick hack. the special case for TGCanvases
1289  if (frame->InheritsFrom(TGCanvas::Class())) {
1290  fSelected = ((TGCanvas*)frame)->GetContainer();
1291 
1292  if (!IsEditDisabled(fSelected)) {
1294  if (fBuilder && fBuilder->GetAction()) {
1296  }
1297  }
1298  } else {
1299  fSelected = fPimpl->fGrab;
1300  }
1301  ChangeSelected(fPimpl->fGrab);
1302 
1304 
1306  DrawGrabRectangles(fPimpl->fGrab);
1307 }
1308 
1309 ////////////////////////////////////////////////////////////////////////////////
1310 /// Inform outside wold that selected frame was changed
1311 
1313 {
1314  if (fStop) {
1315  return;
1316  }
1317 
1318  TGFrame *sel = fr;
1319 
1320  if (fBuilder && (sel == fBuilder->GetMdiMain()->GetCurrent())) {
1321  sel = 0;
1322  }
1323 
1324  if (!fr) {
1325  UngrabFrame();
1326  }
1327 
1328  if (fEditor) {
1329  fEditor->ChangeSelected(sel);
1330  }
1331 
1332  if (fBuilder) {
1333  fBuilder->ChangeSelected(sel);
1334  //fBuilder->Update();
1335  }
1336 }
1337 
1338 ////////////////////////////////////////////////////////////////////////////////
1339 /// grab frame (see SelectFrame)
1340 
1342 {
1343  if (fStop || !frame || !fClient->IsEditable()) {
1344  return;
1345  }
1346 
1347  fPimpl->fGrabParent = frame->GetParent();
1348  fPimpl->fGrabX = frame->GetX();
1349  fPimpl->fGrabY = frame->GetY();
1350 
1351  Window_t c;
1352 
1353  gVirtualX->TranslateCoordinates(frame->GetId(),
1355  0, 0, fPimpl->fX0, fPimpl->fY0, c);
1356 
1357  fPimpl->fX = fPimpl->fX0;
1358  fPimpl->fY = fPimpl->fY0;
1359 
1360  if (frame->GetFrameElement() && frame->GetFrameElement()->fLayout) {
1361  fPimpl->fGrabLayout = frame->GetFrameElement()->fLayout;
1362  }
1363 
1364  if (fPimpl->fGrabParent && frame->GetFrameElement() &&
1365  fPimpl->fGrabParent->InheritsFrom(TGCompositeFrame::Class())) {
1366  TList *li = ((TGCompositeFrame*)fPimpl->fGrabParent)->GetList();
1367  fPimpl->fGrabListPosition = (TGFrameElement*)li->Before(frame->GetFrameElement());
1368  ((TGCompositeFrame*)fPimpl->fGrabParent)->RemoveFrame(frame);
1369  }
1370 
1371  SetWindowAttributes_t attr;
1373  attr.fOverrideRedirect = kTRUE;
1374  attr.fSaveUnder = kTRUE;
1375 
1376  gVirtualX->ChangeWindowAttributes(frame->GetId(), &attr);
1377 
1378  frame->UnmapWindow();
1379  frame->ReparentWindow(fClient->GetDefaultRoot(), fPimpl->fX0, fPimpl->fY0);
1380  gVirtualX->Update(1);
1381  frame->Move(fPimpl->fX0, fPimpl->fY0);
1382  frame->MapRaised();
1383 
1384  if (fBuilder) {
1385  //fBuilder->Update();
1386  TString str = frame->ClassName();
1387  str += "::";
1388  str += frame->GetName();
1389  str += " is grabbed";
1390 
1391  fBuilder->UpdateStatusBar(str.Data());
1392  }
1393 }
1394 
1395 ////////////////////////////////////////////////////////////////////////////////
1396 /// Ungrab/Unselect selected/grabbed frame.
1397 
1399 {
1400  if (fStop || !fPimpl->fGrab) {
1401  return;
1402  }
1403 
1406 
1407  DoRedraw();
1408 
1409  if (fBuilder) {
1410  //fBuilder->Update();
1411  TString str = fPimpl->fGrab->ClassName();
1412  str += "::";
1413  str += fPimpl->fGrab->GetName();
1414  str += " ungrabbed";
1415  fBuilder->UpdateStatusBar(str.Data());
1416  }
1417  fSelected = fPimpl->fGrab = 0;
1418 }
1419 
1420 ////////////////////////////////////////////////////////////////////////////////
1421 /// Helper for IsPointVisible
1422 
1423 static Bool_t IsParentOfGrab(Window_t id, const TGWindow *grab)
1424 {
1425  const TGWindow *parent = grab;
1426 
1427  while (parent && (parent != gClient->GetDefaultRoot())) {
1428  if (parent->GetId() == id) {
1429  return kTRUE;
1430  }
1431  parent = parent->GetParent();
1432  }
1433 
1434  return kFALSE;
1435 }
1436 
1437 ////////////////////////////////////////////////////////////////////////////////
1438 /// Helper function for IsSelectedWindow method
1439 
1441 {
1442  Window_t w = gVirtualX->GetDefaultRootWindow();
1443  Window_t src, dst, child;
1444  Int_t x = xi;
1445  Int_t y = yi;
1446  Bool_t ret = kFALSE;
1447 
1448  gVirtualX->TranslateCoordinates(fPimpl->fGrab->GetId(), w, x, y, x, y, child);
1449 
1450  dst = src = child = w;
1451 
1452  while (child) {
1453  src = dst;
1454  dst = child;
1455  gVirtualX->TranslateCoordinates(src, dst, x, y, x, y, child);
1456 
1457  if (IsParentOfGrab(child, fPimpl->fGrab)) {
1458  return kTRUE;
1459  }
1460  }
1461 
1462  return ret;
1463 }
1464 
1465 ////////////////////////////////////////////////////////////////////////////////
1466 /// Return kTRUE if grabbed/selected frame is not overlapped by other windows.
1467 
1469 {
1470  if (fStop || !fPimpl->fGrab || !fClient->IsEditable()) {
1471  return kFALSE;
1472  }
1473 
1474  if (fBuilder) {
1476  if (mdi && (mdi != fBuilder->GetMdiMain()->GetCurrent())) {
1477  return kFALSE;
1478  }
1479  }
1480 
1481  // popup menu was placed
1482  if (fPimpl->fPlacePopup) {
1483  return kTRUE;
1484  }
1485 
1486  static Long64_t was = gSystem->Now();
1487  static Bool_t visible = kFALSE;
1488 
1489  Long64_t now = gSystem->Now();
1490 
1491  if (now-was < 100) {
1492  return visible;
1493  }
1494  was = now;
1495 
1496  visible = kFALSE;
1497 
1498  if (!IsPointVisible(2, 2)) {
1499  return visible;
1500  }
1501 
1502  if (!IsPointVisible(2, fPimpl->fGrab->GetHeight()-2)) {
1503  return visible;
1504  }
1505 
1506  if (!IsPointVisible(fPimpl->fGrab->GetWidth()-2, 2)) {
1507  return visible;
1508  }
1509 
1510  if (!IsPointVisible(fPimpl->fGrab->GetWidth()-2,
1511  fPimpl->fGrab->GetHeight()-2)) {
1512  return visible;
1513  }
1514 
1515  visible = kTRUE;
1516 
1517  return visible;
1518 }
1519 
1520 ////////////////////////////////////////////////////////////////////////////////
1521 /// Draw small grab rectangles around grabbed/selected/frame
1522 
1524 {
1525  if (fStop) {
1526  return;
1527  }
1528 
1529  TGFrame *frame = win ? (TGFrame *)win : fPimpl->fGrab;
1530 
1531  if (!frame || !fClient->IsEditable() || fPimpl->fPlacePopup) {
1532  return;
1533  }
1534 
1535  Window_t w = gVirtualX->GetDefaultRootWindow();
1536  Window_t c; Int_t x, y;
1537 
1538  gVirtualX->TranslateCoordinates(frame->GetId(), w, 0, 0, x, y, c);
1539 
1540  if (frame->InheritsFrom(TGCompositeFrame::Class()) &&
1541  CanChangeLayout(frame) && !frame->IsLayoutBroken()) {
1542  fPimpl->fAroundFrame[0]->MoveResize(x-3, y-3, frame->GetWidth()+6, 2);
1543  fPimpl->fAroundFrame[0]->MapRaised();
1544  fPimpl->fAroundFrame[1]->MoveResize(x+frame->GetWidth()+3, y-3, 2, frame->GetHeight()+6);
1545  fPimpl->fAroundFrame[1]->MapRaised();
1546  fPimpl->fAroundFrame[2]->MoveResize(x-3, y+frame->GetHeight()+2, frame->GetWidth()+6, 2);
1547  fPimpl->fAroundFrame[2]->MapRaised();
1548  fPimpl->fAroundFrame[3]->MoveResize(x-3, y-3, 2, frame->GetHeight()+6);
1549  fPimpl->fAroundFrame[3]->MapRaised();
1550  } else {
1551  for (int i = 0; i < 4; i++) fPimpl->fAroundFrame[i]->UnmapWindow();
1552  }
1553 
1554  // draw rectangles
1555  DrawGrabRect(0, x - 6, y - 6);
1556  DrawGrabRect(1, x + frame->GetWidth()/2 - 3, y - 6);
1557  DrawGrabRect(2, x + frame->GetWidth(), y - 6);
1558  DrawGrabRect(3, x - 6, y + frame->GetHeight());
1559  DrawGrabRect(4, x - 6, y + frame->GetHeight()/2 - 3);
1560  DrawGrabRect(5, x + frame->GetWidth(), y + frame->GetHeight()/2 - 3);
1561  DrawGrabRect(6, x + frame->GetWidth()/2 - 3, y + frame->GetHeight());
1562  DrawGrabRect(7, x + frame->GetWidth(), y + frame->GetHeight());
1563 
1564  fPimpl->fGrabRectHidden = kFALSE;
1565 }
1566 
1567 ////////////////////////////////////////////////////////////////////////////////
1568 /// Helper method to draw grab rectangle at position x,y
1569 
1571 {
1572  if (fStop) {
1573  return;
1574  }
1575 
1576  fPimpl->fGrabRect[i]->Move(x, y);
1577  fPimpl->fGrabRect[i]->MapRaised();
1578 }
1579 
1580 ////////////////////////////////////////////////////////////////////////////////
1581 /// Raise composite frame when mouse is moving over it.
1582 /// That allows to highlight position of "plain" composite frames.
1583 
1585 {
1586  static Window_t gw = 0;
1587 
1588  if (fStop || !win || (win == gw)) {
1589  return;
1590  }
1591 
1592  TGWindow *w = fClient->GetWindowById(win);
1593 
1594  if (!w || (w == fPimpl->fPlane) || w->GetEditDisabled() || w->IsEditable() ||
1596  return;
1597  }
1598 
1599  TGFrame *frame = (TGFrame*)w;
1600  UInt_t opt = frame->GetOptions();
1601 
1602  if ((opt & kRaisedFrame) || (opt & kSunkenFrame)) {
1603  return;
1604  }
1605 
1606  gw = win;
1607  if (fPimpl->fPlane) {
1608  fPimpl->fPlane->ChangeOptions(fPimpl->fPlane->GetOptions() & ~kRaisedFrame);
1609  fClient->NeedRedraw(fPimpl->fPlane, kTRUE);
1610  }
1611  fPimpl->fPlane = frame;
1612  fPimpl->fPlane->ChangeOptions(opt | kRaisedFrame);
1613  fClient->NeedRedraw(fPimpl->fPlane, kTRUE);
1614 
1615  if (fBuilder) {
1616  TString str = frame->ClassName();
1617  str += "::";
1618  str += frame->GetName();
1619  fBuilder->UpdateStatusBar(str.Data());
1620  }
1621 }
1622 
1623 ////////////////////////////////////////////////////////////////////////////////
1624 /// The main event loop is originated here
1625 /// It repeadeatly queries pointer state and position on the screen.
1626 /// From this info an Event_t structure is built.
1627 
1629 {
1630  return HandleTimerEvent(0, t);
1631 }
1632 
1633 ////////////////////////////////////////////////////////////////////////////////
1634 /// Handle timer events or events coming from the recorder.
1635 
1637 {
1638  static Int_t gy = 0;
1639  static Int_t gx = 0;
1640  static UInt_t gstate = 0;
1641  static Window_t gw = 0;
1642 
1643  Bool_t ret = kTRUE;
1644 
1645  // if nothing is editted stop timer and reset everything
1646  if (!fClient || !fClient->IsEditable()) {
1648  return kFALSE;
1649  }
1650  if (!IsSelectedVisible()) {
1652  }
1653  if (e) {
1654  if (fPimpl->fRepeatTimer) {
1655  // we are replaying events from the recorder...
1656  fPimpl->fRepeatTimer->Reset();
1657  fPimpl->fRepeatTimer->Remove();
1658  }
1659  if (e->fType == kButtonPress)
1660  return HandleButtonPress(e);
1661  else if (e->fType == kButtonRelease)
1662  return HandleButtonRelease(e);
1663  else if (e->fState & kButton1Mask)
1664  return HandleMotion(e);
1665  return kTRUE;
1666  }
1667  Window_t dum;
1668  Event_t ev;
1669  ev.fCode = kButton1;
1670  ev.fType = kMotionNotify;
1671  ev.fState = 0;
1672 
1673  gVirtualX->QueryPointer(gVirtualX->GetDefaultRootWindow(), dum, dum,
1674  ev.fXRoot, ev.fYRoot, ev.fX, ev.fY, ev.fState);
1675 
1676  ev.fWindow = GetWindowFromPoint(ev.fXRoot, ev.fYRoot);
1677 
1678  if (ev.fWindow && (gw == ev.fWindow) && (gstate == ev.fState) &&
1679  (ev.fYRoot == gy) && (ev.fXRoot == gx)) {
1680  return kFALSE;
1681  }
1682 
1683  gw = ev.fWindow;
1684  gstate = ev.fState;
1685  ev.fState &= ~16; // ignore "num lock" pressed
1686  ev.fState &= ~2; // ignore "caps lock" pressed
1687 
1688  if (!fDragging && !fMoveWaiting && !fPimpl->fButtonPressed &&
1689  ((ev.fState == kButton1Mask) || (ev.fState == kButton3Mask) ||
1690  (ev.fState == (kButton1Mask | kKeyShiftMask)) ||
1691  (ev.fState == (kButton1Mask | kKeyControlMask)))) {
1692 
1693  if (ev.fState & kButton1Mask) ev.fCode = kButton1;
1694  if (ev.fState & kButton3Mask) ev.fCode = kButton3;
1695 
1696  ev.fType = kButtonPress;
1697  t->SetTime(40);
1698 
1699  if (fPimpl->fPlane && fClient->GetWindowById(fPimpl->fPlane->GetId())) {
1700  fPimpl->fPlane->ChangeOptions(fPimpl->fPlane->GetOptions() & ~kRaisedFrame);
1701  fClient->NeedRedraw(fPimpl->fPlane, kTRUE);
1702  } else {
1703  fPimpl->fPlane = 0;
1704  }
1705 
1706  ret = HandleButtonPress(&ev);
1707  TimerEvent(&ev);
1708  return ret;
1709  }
1710 
1711  if ((fDragging || fMoveWaiting) && (!ev.fState || (ev.fState == kKeyShiftMask)) &&
1712  fPimpl->fButtonPressed) {
1713 
1714  ev.fType = kButtonRelease;
1715  t->SetTime(100);
1716 
1717  ret = HandleButtonRelease(&ev);
1718  TimerEvent(&ev);
1719  return ret;
1720  }
1721 
1722  fPimpl->fButtonPressed = (ev.fState & kButton1Mask) ||
1723  (ev.fState & kButton2Mask) ||
1724  (ev.fState & kButton3Mask);
1725 
1726  if ((ev.fYRoot == gy) && (ev.fXRoot == gx)) return kFALSE;
1727 
1728  gy = ev.fYRoot;
1729  gx = ev.fXRoot;
1730 
1731  if (!fMoveWaiting && !fDragging && !ev.fState) {
1732  if (!CheckDragResize(&ev) && fClient->GetWindowById(ev.fWindow)) {
1734  }
1735  } else if (ev.fState & kButton1Mask) {
1736  HandleMotion(&ev);
1737  TimerEvent(&ev);
1738  }
1739  return ret;
1740 }
1741 
1742 ////////////////////////////////////////////////////////////////////////////////
1743 /// Recognize what was done when mouse button pressed
1744 
1746 {
1747  if (fStop) {
1748  return kFALSE;
1749  }
1750 
1751  if (((event->fCode != kButton1) && (event->fCode != kButton3)) ||
1752  !frame || !fClient->IsEditable()) {
1753  return kFALSE;
1754  }
1755 
1756  TGFrame *context_fr = 0;
1757  Bool_t mdi = kFALSE;
1758 
1759  // hack for editable mdi frames
1760  if (frame->IsEditable() && frame->InheritsFrom(TGMdiFrame::Class())) {
1761  context_fr = frame;
1762  mdi = kTRUE;
1763  }
1764 
1765  // handle context menu
1766  if (event->fCode == kButton3) {
1767  if (!fPimpl->fSpacePressedFrame) {
1768  if (!mdi) {
1769  SelectFrame(frame);
1770  context_fr = fSelected;
1771  }
1772  } else {
1773  context_fr = fPimpl->fSpacePressedFrame;
1774  }
1775 
1776  HandleButon3Pressed(event, context_fr);
1777  return kTRUE;
1778  }
1779 
1780  fDragType = kDragNone;
1781 
1782  if (!fSelectionIsOn) {
1783  fPimpl->fX0 = event->fXRoot;
1784  fPimpl->fY0 = event->fYRoot;
1785  }
1786 
1787  //HideGrabRectangles();
1788  fPimpl->fClickFrame = frame;
1789 
1790  if (fBuilder && fBuilder->IsExecutable() &&
1792  UngrabFrame();
1793  frame->SetEditable(kTRUE);
1794  fSource = 0;
1796  goto out;
1797  }
1798 
1799  if (event->fState & kKeyShiftMask) {
1800  // drag grabbed frame with shift key pressed should create a copy of grabbed frame
1801  // move a copy of editable and selected frame
1802  if (frame == fPimpl->fGrab) {
1803  fSource = frame;
1804  fDragType = kDragCopy;
1805  gVirtualX->SetCursor(frame->GetId(), gVirtualX->CreateCursor(kMove));
1806  goto out;
1807  }
1808 
1809  // otherwise do lasso selection
1810  if (!fSelectionIsOn) {
1812  } else {
1813  fPimpl->fX = event->fXRoot;
1814  fPimpl->fY = event->fYRoot;
1816  DrawLasso();
1817  return kTRUE;
1818  }
1819  }
1820 
1821  CheckDragResize(event);
1822 
1823  if (frame->IsEditable()) {
1824  fSource = 0;
1825 
1826  if (fDragType != kDragResize) {
1827 
1828  // move editable and selected frame
1829  if (frame == fPimpl->fGrab) {
1830  fSource = frame;
1831  fDragType = kDragMove;
1832  gVirtualX->SetCursor(frame->GetId(), gVirtualX->CreateCursor(kMove));
1833  goto out;
1834  }
1835 
1837  }
1838  } else if ((fDragType != kDragResize) && !fPimpl->fSpacePressedFrame) {
1839 
1840  // special case of TGCanvas
1841  if (!fPimpl->fGrab && frame->InheritsFrom(TGCanvas::Class())) {
1842  TGFrame *cont = ((TGCanvas*)frame)->GetContainer();
1843 
1844  if (!cont->IsEditable()) {
1845  cont->SetEditable(kTRUE);
1847  goto out;
1848  }
1849  }
1850 
1851  fSource = frame;
1852  SelectFrame(frame, event->fState & kKeyShiftMask);
1853  }
1854 
1855  if ((fDragType == kDragNone) && !fPimpl->fSpacePressedFrame) {
1856  SwitchEditable(frame);
1857  fSource = 0;
1858 
1859  // try again
1860  CheckDragResize(event);
1861 
1862  if (fDragType == kDragNone) {
1863  return kFALSE;
1864  }
1865  }
1866 
1867 out:
1868  Window_t c;
1869 
1870  gVirtualX->TranslateCoordinates(fClient->GetDefaultRoot()->GetId(),
1871  frame->GetId(),
1872  event->fXRoot, event->fYRoot,
1873  fPimpl->fXf, fPimpl->fYf, c);
1874  fPimpl->fX = event->fXRoot;
1875  fPimpl->fY = event->fYRoot;
1876 
1877  fMoveWaiting = kTRUE;
1878  DoRedraw();
1879 
1880  return kTRUE;
1881 }
1882 
1883 ////////////////////////////////////////////////////////////////////////////////
1884 /// Handle 3d mouse pressed (popup context menu)
1885 
1887 {
1888  if (fStop || !frame) {
1889  return;
1890  }
1891 
1892  if (fClient->GetWaitForEvent() == kUnmapNotify) {
1893  return;
1894  }
1895 
1896  if (frame == fSelected) {
1897  Menu4Frame(frame, event->fXRoot, event->fYRoot);
1898  } else if (frame->IsEditable()) {
1899  if (fLassoDrawn) {
1900  Menu4Lasso(event->fXRoot, event->fYRoot);
1901  } else {
1902  Menu4Frame(frame, event->fXRoot, event->fYRoot);
1903  }
1904  } else {
1905  TGFrame *base = InEditable(frame->GetId());
1906  if (base) {
1907  //SelectFrame(base);
1908  Menu4Frame(base, event->fXRoot, event->fYRoot);
1909  } else {
1910  Menu4Frame(frame, event->fXRoot, event->fYRoot);
1911  }
1912  }
1913 }
1914 
1915 ////////////////////////////////////////////////////////////////////////////////
1916 /// Handle button event occured in some ROOT frame
1917 
1919 {
1920  if (fStop) {
1921  return kFALSE;
1922  }
1923 
1924  if (event->fCode != kButton3) {
1925  CloseMenus();
1926  }
1927 
1928  if (event->fType == kButtonPress) {
1929  return HandleButtonPress(event);
1930  } else {
1931  return HandleButtonRelease(event);
1932  }
1933 }
1934 
1935 ////////////////////////////////////////////////////////////////////////////////
1936 /// Resize events
1937 
1939 {
1940  if (fStop) {
1941  return kFALSE;
1942  }
1943 
1944  TGWindow *w = fClient->GetWindowById(event->fWindow);
1945 
1946  if (!w) {
1947  return kFALSE;
1948  }
1949 
1950  fPimpl->fCompacted = kFALSE;
1951  return kFALSE;
1952 }
1953 
1954 ////////////////////////////////////////////////////////////////////////////////
1955 /// Handle repaint event
1956 
1958 {
1959  if (fStop) {
1960  return kFALSE;
1961  }
1962 
1963  static Long64_t was = gSystem->Now();
1964  static Window_t win = 0;
1965  Long64_t now = gSystem->Now();
1966 
1967  if (event->fCount || (win == event->fWindow) || (now-was < 50) || fDragging) {
1968  if (fDragging) {
1970  }
1971  return kFALSE;
1972  }
1973 
1974  if (gMenuDialog) {
1976  gMenuDialog->RaiseWindow();
1977  return kFALSE;
1978  }
1979 
1980  if (fLassoDrawn) {
1981  DrawLasso();
1982  } else {
1983  if (IsSelectedVisible()) {
1985  }
1986  }
1987 
1988  win = event->fWindow;
1989  was = now;
1990 
1991  return kFALSE;
1992 }
1993 
1994 ////////////////////////////////////////////////////////////////////////////////
1995 /// Handle all events.
1996 
1998 {
1999  if (fStop) {
2000  return kFALSE;
2001  }
2002 
2003  if (IgnoreEvent(event)) {
2004  return kFALSE;
2005  }
2006 
2007  switch (event->fType) {
2008 
2009  case kExpose:
2010  return HandleExpose(event);
2011 
2012  case kConfigureNotify:
2013  while (gVirtualX->CheckEvent(fId, kConfigureNotify, *event))
2014  ;
2015  return HandleConfigureNotify(event);
2016 
2017  case kGKeyPress:
2018  case kKeyRelease:
2019  return HandleKey(event);
2020 
2021  case kFocusIn:
2022  case kFocusOut:
2023  //HandleFocusChange(event);
2024  break;
2025 
2026  case kButtonPress:
2027  {
2028  Int_t dbl_clk = kFALSE;
2029 
2030  static Window_t gDbw = 0;
2031  static Long_t gLastClick = 0;
2032  static UInt_t gLastButton = 0;
2033  static Int_t gDbx = 0;
2034  static Int_t gDby = 0;
2035 
2036  if ((event->fTime - gLastClick < 350) &&
2037  (event->fCode == gLastButton) &&
2038  (TMath::Abs(event->fXRoot - gDbx) < 6) &&
2039  (TMath::Abs(event->fYRoot - gDby) < 6) &&
2040  (event->fWindow == gDbw)) {
2041  dbl_clk = kTRUE;
2042  }
2043 
2044  if (dbl_clk) {
2045  if (event->fState & kKeyControlMask) {
2047  return kTRUE;
2048  } else if (!(event->fState & 0xFF)) {
2049  TGFrame *w = (TGFrame*)fClient->GetWindowById(event->fWindow);
2050 
2051  if (w && (w->GetEditDisabled() & kEditDisableBtnEnable)) {
2052  return w->HandleDoubleClick(event);
2053  }
2054  if (SaveFrame(fTmpBuildFile.Data())) {
2055  gROOT->Macro(fTmpBuildFile.Data());
2056  }
2057  // an easy way to start editting
2059  return kTRUE;
2060  }
2061  } else {
2062  gDbw = event->fWindow;
2063  gLastClick = event->fTime;
2064  gLastButton = event->fCode;
2065  gDbx = event->fXRoot;
2066  gDby = event->fYRoot;
2067 
2068  Bool_t ret = HandleButtonPress(event);
2069  return ret;
2070  }
2071 
2072  return kFALSE;
2073  }
2074 
2075  case kButtonRelease:
2076  return HandleButtonRelease(event);
2077 
2078  case kEnterNotify:
2079  case kLeaveNotify:
2080  //HandleCrossing(event);
2081  break;
2082 
2083  case kMotionNotify:
2084  while (gVirtualX->CheckEvent(fId, kMotionNotify, *event))
2085  ;
2086  return HandleMotion(event);
2087 
2088  case kClientMessage:
2089  return HandleClientMessage(event);
2090 
2091  case kDestroyNotify:
2092  return HandleDestroyNotify(event);
2093 
2094  case kSelectionNotify:
2095  //HandleSelection(event);
2096  break;
2097 
2098  case kSelectionRequest:
2099  //HandleSelectionRequest(event);
2100  break;
2101 
2102  case kSelectionClear:
2103  //HandleSelectionClear(event);
2104  break;
2105 
2106  case kColormapNotify:
2107  //HandleColormapChange(event);
2108  break;
2109 
2110  default:
2111  //Warning("HandleEvent", "unknown event (%#x) for (%#x)", event->fType, fId);
2112  break;
2113  }
2114 
2115  return kFALSE;
2116 }
2117 
2118 ////////////////////////////////////////////////////////////////////////////////
2119 /// Mouse double click handler (never should happen)
2120 
2122 {
2123  if (fStop) {
2124  return kFALSE;
2125  }
2126 
2127  return kFALSE;
2128 }
2129 
2130 ////////////////////////////////////////////////////////////////////////////////
2131 /// Return a parent which can handle button evevents.
2132 
2134 {
2135  TGWindow *parent = fr;
2136 
2137  while (parent && (parent != fClient->GetDefaultRoot())) {
2138  if (parent->GetEditDisabled() & kEditDisableBtnEnable) {
2139  return (TGFrame*)parent;
2140  }
2141  parent = (TGWindow*)parent->GetParent();
2142  }
2143  return 0;
2144 }
2145 
2146 ////////////////////////////////////////////////////////////////////////////////
2147 /// Unmap all popups
2148 
2150 {
2151  TList *li = fClient->GetListOfPopups();
2152  if (!li->GetEntries()) {
2153  return;
2154  }
2155 
2156  TGPopupMenu *pup;
2157  TIter next(li);
2158 
2159  while ((pup = (TGPopupMenu*)next())) {
2160  pup->UnmapWindow();
2161  fClient->ResetWaitFor(pup);
2162  }
2163  gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
2164 }
2165 
2166 ////////////////////////////////////////////////////////////////////////////////
2167 /// Handle button press event
2168 
2170 {
2171  if (fStop) {
2172  return kFALSE;
2173  }
2174 
2175  fPimpl->fButtonPressed = kTRUE;
2176  fPimpl->fPlacePopup = kFALSE;
2177 
2178  if (fPimpl->fPlane) {
2179  fPimpl->fPlane->ChangeOptions(fPimpl->fPlane->GetOptions() & ~kRaisedFrame);
2180  fClient->NeedRedraw(fPimpl->fPlane, kTRUE);
2181  }
2182 
2183  if (gMenuDialog) { // keep editor on the top
2184  gMenuDialog->RaiseWindow();
2185  }
2186 
2187  // keep undocked toolbar on the top
2188  //(but under win32 key handling will be broken : todo)
2189  if (gVirtualX->InheritsFrom("TGX11") && fBuilder &&
2192  }
2193 
2194  // keep color dialog on the top
2197  return kFALSE;
2198  }
2199 
2200  if ( ((event->fCode != kButton1) && (event->fCode != kButton3)) ||
2201  (event->fType != kButtonPress) || IgnoreEvent(event)) {
2202  return kFALSE;
2203  }
2204 
2205  Reset1();
2206  //HideGrabRectangles();
2207 
2208  Window_t w = GetWindowFromPoint(event->fXRoot, event->fYRoot);
2209  TGFrame *fr = 0;
2210 
2211  if (w) {
2212  fr = (TGFrame*)fClient->GetWindowById(w);
2213  if (!fr) {
2214  return kFALSE;
2215  }
2216 
2217  //fr->HandleButton(event);
2218  if (!IsEventsDisabled(fr)) {
2219  TGFrame *btnframe = GetBtnEnableParent(fr);
2220  if (btnframe) {
2221  event->fUser[0] = fr->GetId();
2222  btnframe->HandleButton(event);
2223  }
2224  }
2225 
2226  if (IsGrabDisabled(fr)) {
2227  fr = GetEditableParent(fr);
2228  }
2229 
2230  if (!fr) {
2231  return kFALSE;
2232  }
2233  } else {
2234  return kFALSE;
2235  }
2236 
2237  return RecognizeGesture(event, fr);
2238 }
2239 
2240 ////////////////////////////////////////////////////////////////////////////////
2241 /// Handle button release event
2242 
2244 {
2245  if (fStop) {
2246  return kFALSE;
2247  }
2248 
2249  // unmap all waiting popups
2250  if (fClient->GetWaitForEvent() == kUnmapNotify) {
2251  UnmapAllPopups();
2252  }
2253 
2254  TGWindow *w = fClient->GetWindowById(event->fWindow);
2255 
2256  if (w && !IsEventsDisabled(w)) {
2257  TGFrame *btnframe = GetBtnEnableParent((TGFrame*)w);
2258  if (btnframe) {
2259  event->fUser[0] = w->GetId();
2260  btnframe->HandleButton(event);
2261  }
2262  }
2263 
2264  fPimpl->fButtonPressed = kFALSE;
2265  gVirtualX->SetCursor(fClient->GetRoot()->GetId(), gVirtualX->CreateCursor(kPointer));
2266  EndDrag();
2267  fSelectionIsOn &= (event->fState & kKeyShiftMask);
2268 
2269  if (fLassoDrawn) {
2270  DrawLasso();
2271  return kTRUE;
2272  }
2273 
2274  if (fPimpl->fClickFrame && !fSelectionIsOn) {
2275 
2276  // make editable the clicked frame if no lasso was drawn
2277  if ((fPimpl->fClickFrame == fPimpl->fGrab) && (fSelected == fPimpl->fGrab) &&
2278  !fPimpl->fGrab->IsEditable()) {
2279  SwitchEditable(fPimpl->fClickFrame);
2280  return kTRUE;
2281 
2282  // select/grab clicked frame if there was no grab frame
2283  } else if (!fPimpl->fGrab || ((fPimpl->fClickFrame != fPimpl->fGrab) &&
2284  (fPimpl->fClickFrame != fSelected))) {
2285  SelectFrame(fPimpl->fClickFrame);
2286  return kTRUE;
2287  }
2288 
2289  }
2290 
2291  SelectFrame(fPimpl->fGrab);
2292 
2293  return kTRUE;
2294 }
2295 
2296 ////////////////////////////////////////////////////////////////////////////////
2297 /// Handle key event
2298 
2300 {
2301  if (fStop) {
2302  return kFALSE;
2303  }
2304 
2305  char tmp[10];
2306  UInt_t keysym;
2307  Bool_t ret = kFALSE;
2308  TGFileInfo fi;
2309  static TString dir(".");
2310  static Bool_t overwr = kFALSE;
2311  TString fname;
2312 
2314 
2315  if (!w || !fPimpl) {
2316  return kFALSE;
2317  }
2318 
2320  return ((TGFrame*)w)->HandleKey(event);
2321  }
2322 
2323  if (event->fType != kGKeyPress) {
2324  return kFALSE;
2325  }
2326 
2327  if (IsEditDisabled(w)) {
2328  TGFrame *parent = GetEditableParent((TGFrame*)w);
2329  if (parent) {
2330  event->fWindow = parent->GetId();
2331  parent->HandleKey(event);
2332  } else {
2333  return ((TGFrame*)w)->HandleKey(event);
2334  }
2335  }
2336 
2337  fPimpl->fSpacePressedFrame = 0;
2338 
2339  if (fPimpl->fPlane) {
2340  fPimpl->fPlane->ChangeOptions(fPimpl->fPlane->GetOptions() & ~kRaisedFrame);
2341  fClient->NeedRedraw(fPimpl->fPlane, kTRUE);
2342  }
2343 
2344  CloseMenus();
2345 
2347  fi.SetIniDir(dir);
2348  fi.fOverwrite = overwr;
2349 
2350  gVirtualX->LookupString(event, tmp, sizeof(tmp), keysym);
2351 
2352  if (event->fState & kKeyControlMask) {
2353 
2354  switch ((EKeySym)keysym & ~0x20) {
2355  case kKey_Return:
2356  case kKey_Enter:
2358  ret = kTRUE;
2359  break;
2360  case kKey_X:
2361  HandleCut();
2362  ret = kTRUE;
2363  break;
2364  case kKey_C:
2365  HandleCopy();
2366  ret = kTRUE;
2367  break;
2368  case kKey_V:
2369  if (fPimpl->fClickFrame && !fPimpl->fClickFrame->IsEditable()) {
2370  fPimpl->fClickFrame->SetEditable(kTRUE);
2371  }
2372  HandlePaste();
2373  ret = kTRUE;
2374  break;
2375  case kKey_B:
2376  {
2377  if (fPimpl->fGrab ) {
2378  BreakLayout();
2379  }
2380  ret = kTRUE;
2381  break;
2382  }
2383  case kKey_L:
2384  {
2385  if (fPimpl->fGrab && (fPimpl->fClickFrame != fClient->GetRoot())) {
2386  Compact(kFALSE);
2387  } else {
2388  Compact(kTRUE);
2389  }
2390  ret = kTRUE;
2391  break;
2392  }
2393  case kKey_R:
2394  HandleReplace();
2395  ret = kTRUE;
2396  break;
2397  case kKey_S:
2398  Save();
2399  ret = kTRUE;
2400  break;
2401  case kKey_G:
2402  HandleGrid();
2403  ret = kTRUE;
2404  break;
2405  case kKey_H:
2406  SwitchLayout();
2407  ret = kTRUE;
2408  break;
2409  case kKey_N:
2410  if (fBuilder) {
2411  fBuilder->NewProject();
2412  } else {
2413  TGMainFrame *main = new TGMainFrame(fClient->GetDefaultRoot(), 300, 300);
2414  main->MapRaised();
2415  main->SetEditable(kTRUE);
2416  }
2417  ret = kTRUE;
2418  break;
2419  case kKey_O:
2420  if (fBuilder) {
2421  fBuilder->NewProject();
2422  } else {
2423  TGMainFrame *main = new TGMainFrame(fClient->GetDefaultRoot(), 300, 300);
2424  main->MapRaised();
2425  main->SetEditable(kTRUE);
2426  }
2427  new TGFileDialog(fClient->GetDefaultRoot(), this, kFDSave, &fi);
2428 
2429  if (!fi.fFilename) return kTRUE;
2430  dir = fi.fIniDir;
2431  overwr = fi.fOverwrite;
2433 
2434  if (fname.EndsWith(".C")) {
2435  gROOT->Macro(fname.Data());
2436  } else {
2437  Int_t retval;
2438  new TGMsgBox(fClient->GetDefaultRoot(), this, "Error...",
2439  TString::Format("file (%s) must have extension .C", fname.Data()),
2440  kMBIconExclamation, kMBRetry | kMBCancel, &retval);
2441  if (retval == kMBRetry) {
2442  HandleKey(event);
2443  }
2444  }
2445  ret = kTRUE;
2446  break;
2447  default:
2448  break;
2449  }
2450  } else {
2451  switch ((EKeySym)keysym) {
2452  case kKey_Delete:
2453  case kKey_Backspace:
2454  HandleDelete(event->fState & kKeyShiftMask);
2455  ret = kTRUE;
2456  break;
2457  case kKey_Return:
2458  case kKey_Enter:
2459  //UnmapAllPopups();
2461  ret = kTRUE;
2462  break;
2463  case kKey_Left:
2464  case kKey_Right:
2465  case kKey_Up:
2466  case kKey_Down:
2467  if (fLassoDrawn) {
2468  HandleAlignment(keysym, event->fState & kKeyShiftMask);
2469  } else if (fPimpl->fGrab) {
2470  HandleLayoutOrder((keysym == kKey_Right) || (keysym == kKey_Down));
2471  }
2472  ret = kTRUE;
2473  break;
2474  case kKey_Space:
2475  //UnmapAllPopups();
2476  if (fPimpl->fGrab) {
2477  SwitchEditable(fPimpl->fGrab);
2478 
2479  TGFrame *p = (TGFrame*)GetEditableParent(fPimpl->fGrab);
2480 
2481  if (p) {
2482  if (p == fBuilder->GetMdiMain()->GetCurrent()) {
2483  UngrabFrame();
2484  } else {
2485  SelectFrame(p);
2486  fSource = fPimpl->fSpacePressedFrame = p;
2487  }
2488  }
2489  }
2490  ret = kTRUE;
2491  break;
2492  default:
2493  break;
2494  }
2495  }
2496  if (fBuilder) {
2497  fBuilder->SetAction(0);
2498  //fBuilder->Update();
2499  }
2500 
2501  if (fLassoDrawn) {
2502  DrawLasso();
2503  }
2504 
2505  return ret;
2506 }
2507 
2508 ////////////////////////////////////////////////////////////////////////////////
2509 /// Reparent frames
2510 
2512 {
2513  if (fStop || !fClient->IsEditable() || (newfr == fClient->GetDefaultRoot())) {
2514  return;
2515  }
2516 
2517  Int_t x0, y0, xx, yy;
2518  Window_t c;
2519  static TGLayoutHints *hints = new TGLayoutHints(kLHintsNormal, 2, 2, 2, 2);
2520 
2521  if (!newfr || !newfr->GetId() || !oldfr || !oldfr->GetId()) return;
2522 
2523  gVirtualX->TranslateCoordinates(newfr->GetId(), oldfr->GetId(),
2524  0, 0, x0, y0, c);
2525 
2526  x0 = x0 < 0 ? 0 : x0;
2527  y0 = y0 < 0 ? 0 : y0;
2528  Int_t x = x0 + newfr->GetWidth();
2529  Int_t y = y0 + newfr->GetHeight();
2530 
2531  TGCompositeFrame *comp = 0;
2532 
2533  if (newfr->InheritsFrom(TGCompositeFrame::Class())) {
2534  comp = (TGCompositeFrame*)newfr;
2535  comp->SetLayoutBroken();
2536  }
2537 
2538  TIter next(oldfr->GetList());
2539  TGFrameElement *el;
2540 
2541  while ((el = (TGFrameElement*)next())) {
2542  TGFrame *frame = el->fFrame;
2543 
2544  if ((frame->GetX() >= x0) && (frame->GetY() >= y0) &&
2545  (frame->GetX() + (Int_t)frame->GetWidth() <= x) &&
2546  (frame->GetY() + (Int_t)frame->GetHeight() <= y)) {
2547 
2548  if (frame == fPimpl->fGrab) {
2549  UngrabFrame();
2550  }
2551 
2552  oldfr->RemoveFrame(frame);
2553 
2554  gVirtualX->TranslateCoordinates(oldfr->GetId(), newfr->GetId(),
2555  frame->GetX(), frame->GetY(), xx, yy, c);
2556 
2557  frame->ReparentWindow(newfr, xx, yy);
2558 
2559  if (comp) {
2560  comp->AddFrame(frame, hints); // el->fLayout);
2561  }
2562  }
2563  }
2564 }
2565 
2566 ////////////////////////////////////////////////////////////////////////////////
2567 /// Return the list of frames inside of some area
2568 
2570 {
2571  if (fStop) {
2572  return 0;
2573  }
2574 
2575  Int_t xx, yy;
2576 
2578  return 0;
2579  }
2580 
2581  TList *list = new TList();
2582 
2583  xx = x0; yy = y0;
2584  x0 = TMath::Min(xx, x); x = TMath::Max(xx, x);
2585  y0 = TMath::Min(yy, y); y = TMath::Max(yy, y);
2586 
2587  TIter next(((TGCompositeFrame*)fClient->GetRoot())->GetList());
2588  TGFrameElement *el;
2589 
2590  while ((el = (TGFrameElement*)next())) {
2591  if ((el->fFrame->GetX() >= x0) && (el->fFrame->GetY() >= y0) &&
2592  (el->fFrame->GetX() + (Int_t)el->fFrame->GetWidth() <= x) &&
2593  (el->fFrame->GetY() + (Int_t)el->fFrame->GetHeight() <= y)) {
2594  list->Add(el->fFrame);
2595  }
2596  }
2597  if (list->IsEmpty()) {
2598  delete list;
2599  return 0;
2600  }
2601  return list;
2602 }
2603 
2604 ////////////////////////////////////////////////////////////////////////////////
2605 /// Drop canvas container
2606 
2608 {
2609  if (fStop) {
2610  return;
2611  }
2612 
2613  TGCompositeFrame *comp = (TGCompositeFrame*)canvas->GetParent();
2614  comp->SetEditable(kTRUE);
2615 
2616  TGCompositeFrame *cont = (TGCompositeFrame*)canvas->GetContainer();
2617  Int_t x = canvas->GetX();
2618  Int_t y = canvas->GetY();
2619 
2621  cont->ReparentWindow(comp, x, y);
2622  canvas->SetContainer(0);
2623  comp->AddFrame(cont);
2624  DeleteFrame(canvas);
2625 
2626  if (fBuilder) {
2627  TString str = cont->ClassName();
2628  str += "::";
2629  str += cont->GetName();
2630  str += " dropped.";
2631  fBuilder->UpdateStatusBar(str.Data());
2632  }
2633  SelectFrame(cont);
2634 }
2635 
2636 ////////////////////////////////////////////////////////////////////////////////
2637 /// Create a new TGCanvas and place container into it
2638 
2640 {
2641  if (fStop || !cont) {
2642  return;
2643  }
2644 
2645  TGCompositeFrame *comp = (TGCompositeFrame*)cont->GetParent();
2646  comp->SetEditable(kTRUE);
2647 
2648  UInt_t w = cont->GetWidth()/2;
2649  UInt_t h = cont->GetHeight()/2;
2650 
2651  w = w < 100 ? 100 : w;
2652  h = h < 100 ? 100 : h;
2653 
2654  TGCanvas *canvas = new TGCanvas(comp, w, h);
2655  canvas->Move(cont->GetX(), cont->GetY());
2656  comp->RemoveFrame(cont);
2657  comp->AddFrame(canvas);
2658  cont->ReparentWindow(canvas->GetViewPort());
2659  canvas->SetContainer(cont);
2660  cont->SetCleanup(kDeepCleanup);
2661  canvas->MapSubwindows();
2662  canvas->MapWindow();
2663  SelectFrame(canvas);
2664 
2665  if (fBuilder) {
2666  fBuilder->UpdateStatusBar("Grab action performed. Presss Cntrl-Return to Drop grabbed frame.");
2667  }
2668 }
2669 
2670 ////////////////////////////////////////////////////////////////////////////////
2671 /// Handling of return/enter key pressing
2672 ///
2673 /// If on is kFALSE:
2674 /// If Return or Enter key was pressed - Grab Act
2675 /// If lasso is drawn - new composite frame is created and
2676 /// all frames inside lasso adopted as childrens.
2677 /// If lasso is not drawn and selected frame is composite one,
2678 /// - new TGCanvas widget is created and selcted frmae became
2679 /// container for this canvas.
2680 ///
2681 /// If on is kTRUE:
2682 /// If Return or Enter key was pressed with Control Key - Drop Act,
2683 /// The opposite action to the Grab Act.
2684 /// If selected/grabbed frame is not a TGCanvas widget -
2685 /// all frames inside the grabbed/selected frame are "dropped" into
2686 /// the underlying frame and the grabbed frame is deleted.
2687 ///
2688 /// If selected/grabbed frame is a TGCanvas widget -
2689 /// container frame "dropped" to editable frame
2690 
2692 {
2693  if (fStop) {
2694  return;
2695  }
2696 
2697  Int_t x0, y0, x, y, xx, yy;
2698  Window_t c;
2699  TGCompositeFrame *parent = 0;
2700  TList *li = 0;
2701 
2703  !fClient->IsEditable()) {
2704  return;
2705  }
2706 
2707  // if grabbed frame is editable - we need to switch edit to parent
2708  if (fPimpl->fGrab && fPimpl->fGrab->IsEditable()) {
2709  ((TGFrame*)fPimpl->fGrab->GetParent())->SetEditable(kTRUE);
2710  }
2711 
2712  if (fPimpl->fGrab && !fLassoDrawn) {
2713  if (!on) {
2714  if (fPimpl->fGrab->InheritsFrom(TGCompositeFrame::Class()) &&
2715  !fPimpl->fGrab->InheritsFrom(TGCanvas::Class()) &&
2716  !fPimpl->fGrab->InheritsFrom(TGContainer::Class()) &&
2717  CanChangeLayout(fPimpl->fGrab) &&
2718  CanChangeLayout((TGWindow*)fPimpl->fGrab->GetParent())) {
2720  return;
2721  }
2722  } else {
2723 
2724  if ((fPimpl->fGrab->IsA() == TGCanvas::Class()) &&
2725  !((TGCanvas*)fPimpl->fGrab)->GetContainer()->InheritsFrom(TGContainer::Class()) &&
2726  CanChangeLayout((TGWindow*)fPimpl->fGrab->GetParent())) {
2727  DropCanvas((TGCanvas*)fPimpl->fGrab);
2728  return;
2729  }
2730  }
2731  }
2732 
2734 
2735  if (fLassoDrawn) {
2736 
2737  gVirtualX->TranslateCoordinates(fClient->GetDefaultRoot()->GetId(),
2738  fClient->GetRoot()->GetId(),
2739  fPimpl->fX, fPimpl->fY, x, y, c);
2740  gVirtualX->TranslateCoordinates(fClient->GetDefaultRoot()->GetId(),
2741  fClient->GetRoot()->GetId(),
2742  fPimpl->fX0, fPimpl->fY0, x0, y0, c);
2743 
2744  xx = x0; yy = y0;
2745  x0 = TMath::Min(xx, x); x = TMath::Max(xx, x);
2746  y0 = TMath::Min(yy, y); y = TMath::Max(yy, y);
2747 
2748  li = GetFramesInside(x0, y0, x, y);
2749 
2750  if (!on && li) {
2751  parent = new TGCompositeFrame(comp, x - x0, y - y0);
2752  parent->MoveResize(x0, y0, x - x0, y - y0);
2753  ReparentFrames(parent, comp);
2754 
2755  comp->AddFrame(parent);
2756  parent->MapWindow();
2758  SelectFrame(parent);
2759 
2760  if (fBuilder) {
2761  TString str = "Grab action performed.";
2762  str += " Press Cntrl-Return to Drop grabbed frames.";
2763  str += " Presss Return for TCanvas Grab";
2764  fBuilder->UpdateStatusBar(str.Data());
2765  }
2766  }
2767  } else if (on && fPimpl->fGrab) {
2768 
2769  // check if it is forbidden
2770  if (!CanChangeLayout(fPimpl->fGrab) ||
2771  !CanChangeLayout((TGWindow*)fPimpl->fGrab->GetParent())) {
2772  if (fBuilder) {
2773  fBuilder->UpdateStatusBar("Drop action disabled");
2774  }
2775  return;
2776  }
2777 
2778  if (fPimpl->fGrab->InheritsFrom(TGCompositeFrame::Class())) {
2779  parent = (TGCompositeFrame*)fPimpl->fGrab;
2780  } else {
2781  //parent = (TGCompositeFrame*)fPimpl->fGrab->GetParent();
2782  }
2783  if (parent) {
2784  ReparentFrames(comp, parent);
2785  DeleteFrame(fPimpl->fGrab);
2786  UngrabFrame();
2787  ChangeSelected(0); //update editors
2788 
2789  if (fBuilder) {
2790  fBuilder->UpdateStatusBar("Drop action performed");
2791  }
2792  }
2793  }
2794  delete li;
2795 }
2796 
2797 ////////////////////////////////////////////////////////////////////////////////
2798 /// Align frames located inside lasso area.
2799 
2801 {
2802  if (fStop) {
2803  return;
2804  }
2805 
2806  Int_t x0, y0, x, y, xx, yy;
2807  Window_t c;
2808  TGCompositeFrame *comp = 0;
2809 
2811  !fClient->IsEditable()) {
2812  return;
2813  }
2814 
2815  if (fLassoDrawn) {
2816  gVirtualX->TranslateCoordinates(fClient->GetDefaultRoot()->GetId(),
2817  fClient->GetRoot()->GetId(),
2818  fPimpl->fX, fPimpl->fY, x, y, c);
2819  gVirtualX->TranslateCoordinates(fClient->GetDefaultRoot()->GetId(),
2820  fClient->GetRoot()->GetId(),
2821  fPimpl->fX0, fPimpl->fY0, x0, y0, c);
2822 
2823  xx = x0; yy = y0;
2824  x0 = TMath::Min(xx, x); x = TMath::Max(xx, x);
2825  y0 = TMath::Min(yy, y); y = TMath::Max(yy, y);
2826 
2827  comp = (TGCompositeFrame*)fClient->GetRoot();
2828 
2829  ToGrid(x, y);
2830  ToGrid(x0, y0);
2831 
2832  TIter next(comp->GetList());
2833  TGFrameElement *el;
2834  TGFrame *prev = 0;
2835 
2836  while ((el = (TGFrameElement*)next())) {
2837  TGFrame *fr = el->fFrame;
2838 
2839  if ((fr->GetX() >= x0) && (fr->GetY() >= y0) &&
2840  (fr->GetX() + (Int_t)fr->GetWidth() <= x) &&
2841  (fr->GetY() + (Int_t)fr->GetHeight() <= y)) {
2842 
2843  switch ((EKeySym)to) {
2844  case kKey_Left:
2845  fr->Move(x0, fr->GetY());
2846  if (lineup) {
2847  // coverity[dead_error_line]
2848  if (prev) fr->Move(fr->GetX(), prev->GetY() + prev->GetHeight());
2849  else fr->Move(x0, y0);
2850  }
2851  break;
2852  case kKey_Right:
2853  fr->Move(x - fr->GetWidth(), fr->GetY());
2854  if (lineup) {
2855  if (prev) fr->Move(fr->GetX(), prev->GetY() + prev->GetHeight());
2856  else fr->Move(x - fr->GetWidth(), y0);
2857  }
2858  break;
2859  case kKey_Up:
2860  fr->Move(fr->GetX(), y0);
2861  if (lineup) {
2862  if (prev) fr->Move(prev->GetX() + prev->GetWidth(), fr->GetY());
2863  else fr->Move(x0, y0);
2864  }
2865  break;
2866  case kKey_Down:
2867  fr->Move(fr->GetX(), y - fr->GetHeight());
2868  if (lineup) {
2869  if (prev) fr->Move(prev->GetX() + prev->GetWidth(), fr->GetY());
2870  else fr->Move(x0, y - fr->GetHeight());
2871  }
2872  break;
2873  default:
2874  break;
2875  }
2876  prev = fr;
2877  }
2878  }
2879  }
2880  if (fLassoDrawn) {
2881  DrawLasso();
2882  }
2883 }
2884 
2885 ////////////////////////////////////////////////////////////////////////////////
2886 /// Handle delete or crop action
2887 ///
2888 /// crop is kFALSE - delete action
2889 /// - if lasso is drawn -> all frames inside lasso area are deleted
2890 /// - if frame is grabbed/selected -> the frame is deleted
2891 /// crop is kTRUE - crop action
2892 /// - if lasso is drawn -> all frames outside of lasso area are deleted
2893 /// - if frame is grabbed/selected -> all frames except the grabbed frame are deleted
2894 /// In both cases the main frame is shrinked to the size of crop area.
2895 
2897 {
2898  if (fStop) {
2899  return;
2900  }
2901 
2902  Int_t x0, y0, x, y, xx, yy, w, h;
2903  Window_t c;
2904 
2906  !fClient->IsEditable()) {
2907  return;
2908  }
2909 
2910  TGCompositeFrame *comp = 0;
2911  Bool_t fromGrab = kFALSE;
2912  TGFrame *frame = fPimpl->fGrab;
2913 
2914  if (fBuilder && crop) {
2916  } else {
2917  comp = (TGCompositeFrame*)fClient->GetRoot();
2918  }
2919 
2920  if (frame && !CanChangeLayout((TGWindow*)frame->GetParent())) {
2921  frame = GetMovableParent(frame);
2922 
2923  if (!frame) {
2924  TString str = fPimpl->fGrab->ClassName();
2925  str += "::";
2926  str += fPimpl->fGrab->GetName();
2927  str += " cannot be deleted";
2928 
2929  if (fBuilder) {
2930  fBuilder->UpdateStatusBar(str.Data());
2931  }
2932  return;
2933  }
2934  }
2935 
2936  // prepare to crop grabbed frame
2937  if (frame && !fLassoDrawn && crop) {
2938  gVirtualX->TranslateCoordinates(frame->GetId(),
2940  -2, -2,
2941  fPimpl->fX0, fPimpl->fY0, c);
2942 
2943  fPimpl->fX = fPimpl->fX0 + frame->GetWidth()+4;
2944  fPimpl->fY = fPimpl->fY0 + frame->GetHeight()+4;
2945  fromGrab = kTRUE;
2946  }
2947 
2948  x0 = fPimpl->fX0; y0 = fPimpl->fY0;
2949  x = fPimpl->fX; y = fPimpl->fY;
2950  if (comp) {
2951  gVirtualX->TranslateCoordinates(fClient->GetDefaultRoot()->GetId(),
2952  comp->GetId(),
2953  fPimpl->fX, fPimpl->fY, x, y, c);
2954  gVirtualX->TranslateCoordinates(fClient->GetDefaultRoot()->GetId(),
2955  comp->GetId(),
2956  fPimpl->fX0, fPimpl->fY0, x0, y0, c);
2957  }
2958 
2959  xx = x0; yy = y0;
2960  x0 = TMath::Min(xx, x); x = TMath::Max(xx, x);
2961  y0 = TMath::Min(yy, y); y = TMath::Max(yy, y);
2962  w = x - x0;
2963  h = y - y0;
2964 
2965  if (fLassoDrawn || fromGrab) {
2966  if (comp) {
2967  TIter next(comp->GetList());
2968  TGFrameElement *el;
2969 
2970  while ((el = (TGFrameElement*)next())) {
2971  TGFrame *fr = el->fFrame;
2972 
2973  if ((fr->GetX() >= x0) && (fr->GetY() >= y0) &&
2974  (fr->GetX() + (Int_t)fr->GetWidth() <= x) &&
2975  (fr->GetY() + (Int_t)fr->GetHeight() <= y)) {
2976  if (!crop) {
2977  DeleteFrame(fr);
2978  } else {
2979  fr->Move(fr->GetX() - x0, fr->GetY() - y0);
2980  }
2981  } else {
2982  if (crop) {
2983  DeleteFrame(fr);
2984  }
2985  }
2986  }
2987  if (crop && comp) {
2988  gVirtualX->TranslateCoordinates(comp->GetId(), comp->GetParent()->GetId(),
2989  x0, y0, xx, yy, c);
2990 
2991  comp->MoveResize(xx, yy, w, h);
2992 
2993  if (comp->GetParent()->InheritsFrom(TGMdiDecorFrame::Class())) {
2994  TGMdiDecorFrame *decor = (TGMdiDecorFrame *)comp->GetParent();
2995 
2996  gVirtualX->TranslateCoordinates(decor->GetId(), decor->GetParent()->GetId(),
2997  xx, yy, xx, yy, c);
2998 
2999  Int_t b = 2 * decor->GetBorderWidth();
3000  decor->MoveResize(xx, yy, comp->GetWidth() + b,
3001  comp->GetHeight() + b + decor->GetTitleBar()->GetDefaultHeight());
3002  }
3003  }
3004  }
3005  } else { // no lasso drawn -> delete selected frame
3006  if (frame)
3007  DeleteFrame(frame);
3008  UngrabFrame();
3009  ChangeSelected(0); //update editors
3010  }
3012 
3013  if (fBuilder) {
3014  //fBuilder->Update();
3015  fBuilder->UpdateStatusBar(crop ? "Crop action performed" : "Delete action performed");
3016  }
3017 }
3018 
3019 ////////////////////////////////////////////////////////////////////////////////
3020 /// Delete frame
3021 
3023 {
3024  if (fStop || !frame) {
3025  return;
3026  }
3027 
3028  // remove the frame from the list tree and reset the editor...
3029  fEditor->RemoveFrame(frame);
3030 
3031  frame->UnmapWindow();
3032 
3033  TGCompositeFrame *comp = 0;
3034 
3035  if (frame->GetParent()->InheritsFrom(TGCompositeFrame::Class())) {
3036  comp = (TGCompositeFrame*)frame->GetParent();
3037  }
3038 
3039  if (comp) {
3040  comp->RemoveFrame(frame);
3041  }
3042 
3043  if (frame == fPimpl->fGrab) {
3044  UngrabFrame();
3045  }
3046 
3047  fClient->UnregisterWindow(frame);
3048 
3049  // mem.leak paid for robustness (with possibility "undelete")
3051 }
3052 
3053 ////////////////////////////////////////////////////////////////////////////////
3054 /// Handle cut action
3055 
3057 {
3058  if (fStop || !fPimpl->fGrab) {
3059  return;
3060  }
3061 
3062  //
3063  fPimpl->fGrab = GetMovableParent(fPimpl->fGrab);
3064  HandleCopy();
3065  DeleteFrame(fPimpl->fGrab);
3066  ChangeSelected(0); //update editors
3067 }
3068 
3069 ////////////////////////////////////////////////////////////////////////////////
3070 /// Handle copy. This method is also used by SaveFrame method.
3071 /// In later case brk_layout == kFALSE
3072 
3074 {
3075  if (fStop || !fPimpl->fGrab) {
3076  return;
3077  }
3078 
3080  fPimpl->fGrab->GetWidth(),
3081  fPimpl->fGrab->GetHeight());
3082 
3083  // save coordinates
3084  Int_t x0 = fPimpl->fGrab->GetX();
3085  Int_t y0 = fPimpl->fGrab->GetY();
3086 
3087  // save parent name
3088  TString name = fPimpl->fGrab->GetParent()->GetName();
3089 
3090  ((TGWindow*)fPimpl->fGrab->GetParent())->SetName(tmp->GetName());
3091 
3092  fPimpl->fGrab->SetX(0);
3093  fPimpl->fGrab->SetY(0);
3094 
3095  TGFrameElement *fe = fPimpl->fGrab->GetFrameElement();
3096 
3097  if (fe) {
3098  tmp->GetList()->Add(fe);
3099  }
3100 
3101  tmp->SetLayoutBroken(brk_layout);
3102 
3103  if (!brk_layout) { //save frame
3105  tmp->SetWMSize(tmp->GetWidth(), tmp->GetHeight());
3106  tmp->SetWMSizeHints(tmp->GetDefaultWidth(), tmp->GetDefaultHeight(), 10000, 10000, 0, 0);
3107  const char *short_name = gSystem->BaseName(fPasteFileName.Data());
3108  tmp->SetWindowName(short_name);
3109  tmp->SetIconName(short_name);
3110  tmp->SetClassHints(short_name, short_name);
3111  // some problems here under win32
3112  if (gVirtualX->InheritsFrom("TGX11")) tmp->SetIconPixmap("bld_rgb.xpm");
3113  }
3114  Bool_t quite = brk_layout || (fPasteFileName == fTmpBuildFile);
3115  tmp->SaveSource(fPasteFileName.Data(), quite ? "keep_names quiet" : "keep_names");
3116  tmp->GetList()->Remove(fe);
3117 
3118  fPimpl->fGrab->SetX(x0);
3119  fPimpl->fGrab->SetY(y0);
3120 
3121  ((TGWindow*)fPimpl->fGrab->GetParent())->SetName(name.Data());
3122 
3123  if (fBuilder) {
3124  TString str = fPimpl->fGrab->ClassName();
3125  str += "::";
3126  str += fPimpl->fGrab->GetName();
3127  str += " copied to clipboard";
3128  fBuilder->UpdateStatusBar(str.Data());
3129  }
3130 
3131  delete tmp;
3132 }
3133 
3134 ////////////////////////////////////////////////////////////////////////////////
3135 /// Handle paste action.
3136 
3138 {
3139  if (fStop) {
3140  return;
3141  }
3142 
3143  Int_t xp = 0;
3144  Int_t yp = 0;
3145 
3147  return;
3148  }
3149 
3150  fPasting = kTRUE;
3151  gROOT->Macro(fPasteFileName.Data());
3152 
3153  Window_t c;
3154  TGFrame *root = (TGFrame*)fClient->GetRoot();
3155 
3156  if (!fPimpl->fReplaceOn) {
3157  gVirtualX->TranslateCoordinates(fClient->GetDefaultRoot()->GetId(),
3158  root->GetId(),
3159  fPimpl->fX0, fPimpl->fY0, xp, yp, c);
3160  ToGrid(xp, yp);
3161 
3162  // fPasteFrame is defined in TVirtualDragManager.h
3163  // fPasteFrame is a TGMainFrame consisting "the frame to paste"
3164  // into the editable frame (aka fClient->GetRoot())
3165 
3166  if (fPasteFrame) {
3168  TGFrame *paste = ((TGFrameElement*)main->GetList()->First())->fFrame;
3169 
3170  UInt_t w = paste->GetWidth();
3171  UInt_t h = paste->GetHeight();
3172 
3173  if (xp + w > root->GetWidth()) {
3174  w = root->GetWidth() - xp -1;
3175  }
3176  if (yp + h > root->GetHeight()) {
3177  h = root->GetHeight() - yp -1;
3178  }
3179 
3180  paste->Resize(w, h);
3181  fPasteFrame->Move(xp, yp);
3182  fPimpl->fGrab = fPasteFrame;
3183  HandleReturn(1); // drop
3184  }
3185  }
3186 
3187  fPasting = kFALSE;
3188 
3189  if (fBuilder) {
3190  fBuilder->UpdateStatusBar("Paste action performed");
3191  }
3192 }
3193 
3194 ////////////////////////////////////////////////////////////////////////////////
3195 /// Replace frame (doesn't work yet properly)
3196 
3198 {
3199  if (fStop || !frame || !fPimpl->fGrab || !fPimpl->fReplaceOn) {
3200  return;
3201  }
3202 
3203  Int_t w = fPimpl->fGrab->GetWidth();
3204  Int_t h = fPimpl->fGrab->GetHeight();
3205  Int_t x = fPimpl->fGrab->GetX();
3206  Int_t y = fPimpl->fGrab->GetY();
3207 
3208  if (fBuilder) {
3209  TString str = fPimpl->fGrab->ClassName();
3210  str += "::";
3211  str += fPimpl->fGrab->GetName();
3212  str += " replaced by ";
3213  str += frame->ClassName();
3214  str += "::";
3215  str += frame->GetName();
3216  fBuilder->UpdateStatusBar(str.Data());
3217  }
3218 
3219  TGFrameElement *fe = fPimpl->fGrab->GetFrameElement();
3220 
3221  if (fe) {
3222  fe->fFrame = 0;
3223  fPimpl->fGrab->DestroyWindow();
3224  delete fPimpl->fGrab;
3225  fPimpl->fGrab = 0;
3226 
3227  fe->fFrame = frame;
3228  frame->MoveResize(x, y, w, h);
3229  frame->MapRaised();
3230  frame->SetFrameElement(fe);
3231  }
3232 
3233  SelectFrame(frame);
3234  fPimpl->fReplaceOn = kFALSE;
3235 
3236  TGWindow *root = (TGWindow *)fClient->GetRoot();
3237  root->SetEditable(kFALSE);
3238  DoRedraw();
3239  root->SetEditable(kTRUE);
3240 }
3241 
3242 ////////////////////////////////////////////////////////////////////////////////
3243 /// Handle replace
3244 
3246 {
3247  if (fStop || !fPimpl->fGrab) {
3248  return;
3249  }
3250 
3251  fPimpl->fReplaceOn = kTRUE;
3252  TGFrame *frame = 0;
3253 
3254  if (fBuilder && fBuilder->IsExecutable()) {
3255  frame = (TGFrame *)fBuilder->ExecuteAction();
3256  } else {
3257  HandlePaste();
3258  frame = fPasteFrame;
3259  }
3260  DoReplace(frame);
3261  fPimpl->fReplaceOn = kFALSE;
3262 }
3263 
3264 ////////////////////////////////////////////////////////////////////////////////
3265 /// Create a frame which is the same as currently editted frame
3266 
3268 {
3269  if (fStop) {
3270  return;
3271  }
3272 
3273  TString tmpfile = gSystem->TempDirectory();
3274  char *s = gSystem->ConcatFileName(tmpfile.Data(), TString::Format("tmp%d.C",
3275  gRandom->Integer(100)));
3276  Save(s);
3277  gROOT->Macro(s);
3278  gSystem->Unlink(s);
3279  delete [] s;
3280 
3282  TGFrame *f = (TGFrame *)fClient->GetRoot();
3283  f->Resize(f->GetWidth() + 10, f->GetHeight() + 10);
3284  }
3285 }
3286 
3287 ////////////////////////////////////////////////////////////////////////////////
3288 /// Save an editted frame to the file
3289 
3291 {
3292  if (fStop || !fClient->GetRoot() || !fClient->IsEditable()) {
3293  return kFALSE;
3294  }
3295 
3297  TGWindow *root = (TGWindow*)fClient->GetRoot();
3298  TString fname = file;
3299 
3300  root->SetEditable(kFALSE);
3301 
3302  static TImage *img = 0;
3303 
3304  if (!img) {
3305  img = TImage::Create();
3306  }
3307  img->FromWindow(main->GetId());
3308 
3309  if (!file || !file[0]) {
3310  static TString dir(".");
3311  static Bool_t overwr = kFALSE;
3312  TGFileInfo fi;
3313 
3315  fi.SetIniDir(dir);
3316  fi.fOverwrite = overwr;
3317  new TGFileDialog(fClient->GetDefaultRoot(), this, kFDSave, &fi);
3318 
3319  if (!fi.fFilename) goto out;
3320  dir = fi.fIniDir;
3321  overwr = fi.fOverwrite;
3323  }
3324 
3325  if (fname.EndsWith(".C")) {
3327  main->SetWMSize(main->GetWidth(), main->GetHeight());
3328  main->SetWMSizeHints(main->GetDefaultWidth(), main->GetDefaultHeight(), 10000, 10000, 0, 0);
3329  main->SetWindowName(fname.Data());
3330  main->SetIconName(fname.Data());
3331  main->SetClassHints(fname.Data(), fname.Data());
3332  // some problems here under win32
3333  if (gVirtualX->InheritsFrom("TGX11")) main->SetIconPixmap("bld_rgb.xpm");
3334  main->SaveSource(fname.Data(), file ? "keep_names quiet" : "keep_names");
3335 
3336  fBuilder->AddMacro(fname.Data(), img);
3337 
3338  } else {
3339  Int_t retval;
3340  TString msg = TString::Format("file (%s) must have extension .C", fname.Data());
3341 
3342  new TGMsgBox(fClient->GetDefaultRoot(), main, "Error...", msg.Data(),
3343  kMBIconExclamation, kMBRetry | kMBCancel, &retval);
3344 
3345  if (retval == kMBRetry) {
3346  return Save();
3347  }
3348  }
3349 
3350 out:
3351  main->RaiseWindow();
3352  return kTRUE;
3353 }
3354 
3355 ////////////////////////////////////////////////////////////////////////////////
3356 /// Save composite frame as macro
3357 
3359 {
3360  if (fStop || !fClient->GetRoot() || !fClient->IsEditable() ||
3361  !fPimpl->fGrab || !fPimpl->fGrab->InheritsFrom(TGCompositeFrame::Class())) {
3362  return kFALSE;
3363  }
3364 
3365  TString fname = file;
3366 
3367  TGFrame *frame = fPimpl->fGrab;
3369 
3370  static TImage *img = 0;
3371 
3372  if (!img) {
3373  img = TImage::Create();
3374  }
3375  img->FromWindow(frame->GetId());
3376 
3377  static TString dir(".");
3378  static Bool_t overwr = kFALSE;
3379 
3380  TString sav = fPasteFileName;
3381 
3382  if (!file) {
3383  TGFileInfo fi;
3384 
3386  fi.SetIniDir(dir);
3387  fi.fOverwrite = overwr;
3388  new TGFileDialog(fClient->GetDefaultRoot(), frame, kFDSave, &fi);
3389 
3390  if (!fi.fFilename) {
3391  goto out;
3392  }
3393 
3394  dir = fi.fIniDir;
3395  overwr = fi.fOverwrite;
3397  }
3398 
3399  if (fname.EndsWith(".C")) {
3400  fPasteFileName = fname;
3401  fPimpl->fGrab = frame;
3402  fStop = kFALSE;
3403  TGFrameElement *fe = frame->GetFrameElement();
3404 
3405  if (!fe) { // should never happen
3406  fe = new TGFrameElement();
3407  fe->fFrame = frame;
3408  fe->fState = kIsMapped;
3409  frame->SetFrameElement(fe);
3410  TGCompositeFrame *comp = (TGCompositeFrame*)frame->GetParent();
3411  comp->GetList()->Add(fe);
3412  }
3413  delete fe->fLayout;
3415 
3416  HandleCopy(kFALSE);
3417  fStop = kTRUE;
3418 
3419  fBuilder->AddMacro(fname.Data(), img);
3420  } else {
3421  Int_t retval;
3422  TString msg = TString::Format("file (%s) must have extension .C", fname.Data());
3423 
3424  new TGMsgBox(fClient->GetDefaultRoot(), frame, "Error...", msg.Data(),
3425  kMBIconExclamation, kMBRetry | kMBCancel, &retval);
3426 
3427  if (retval == kMBRetry) {
3428  return SaveFrame();
3429  }
3430  }
3431 
3432 out:
3433  fPasteFileName = sav;
3434  return kTRUE;
3435 }
3436 /*
3437 ////////////////////////////////////////////////////////////////////////////////
3438 /// Not used yet. Return 0 if all child frames are inside area x,y, w,h
3439 
3440 static Int_t canResize(TGFrame *frame, Int_t x, Int_t y, UInt_t &w, UInt_t &h)
3441 {
3442  if (frame->InheritsFrom(TGCompositeFrame::Class())) return 0;
3443 
3444  TGCompositeFrame *comp = (TGCompositeFrame*)frame;
3445 
3446  TIter next(comp->GetList());
3447  TGFrameElement *fe;
3448  Int_t d = gGuiBldDragManager->GetGridStep();
3449  Int_t ret = 0;
3450 
3451  while ((fe = (TGFrameElement*)next())) {
3452  if (x + fe->fFrame->GetX() + fe->fFrame->GetWidth() > w) {
3453  w = fe->fFrame->GetX() + x + fe->fFrame->GetWidth();
3454  ret |= 4;
3455  }
3456  if (y + fe->fFrame->GetY() + fe->fFrame->GetHeight() > h) {
3457  h = fe->fFrame->GetY() + y + fe->fFrame->GetHeight();
3458  ret |= 8;
3459  }
3460  }
3461  return ret;
3462 }
3463 */
3464 
3465 ////////////////////////////////////////////////////////////////////////////////
3466 /// handle resize
3467 
3469 {
3470  if (fStop || !fClient->IsEditable()) {
3471  return;
3472  }
3473 
3474  TGFrame *fr = fPimpl->fGrab;
3475 
3476  if (!fr || IsFixedSize(fr) ||
3477  IsFixedLayout((TGWindow*)fr->GetParent())) {
3478 
3479  fr = (TGFrame*)GetResizableParent(fr);
3480 
3481  if (!fr ) {
3482  return;
3483  }
3484  }
3485 
3486  TGCompositeFrame *comp = 0;
3487 
3489  comp = (TGCompositeFrame*)fr;
3490  }
3491 
3492  Window_t c;
3493  Int_t x = fPimpl->fX;
3494  Int_t y = fPimpl->fY;
3495  UInt_t w = 0;
3496  UInt_t h = 0;
3497  UInt_t wp = ((TGFrame*)fr->GetParent())->GetWidth() - 2;
3498  UInt_t hp = ((TGFrame*)fr->GetParent())->GetHeight() - 2;
3499 
3500  gVirtualX->TranslateCoordinates(fClient->GetDefaultRoot()->GetId(),
3501  fr->GetId(), x, y, x, y, c);
3502 
3503  ToGrid(x, y);
3505 
3506  switch (fPimpl->fResizeType) {
3507  case kTopLeft:
3508  if ((((int)fr->GetWidth() > x) || (x < 0)) &&
3509  (((int)fr->GetHeight() > y) || (y < 0))) {
3510 
3511  if (fr->GetY() + y < 2) {
3512  y = 2 - fr->GetY();
3513  }
3514  if (fr->GetX() + x < 2) {
3515  x = 2 - fr->GetX();
3516  }
3517  h = fr->GetHeight() - y;
3518  w = fr->GetWidth() - x;
3519  x = fr->GetX() + x;
3520  y = fr->GetY() + y;
3521 
3522  if (!IsFixedH(fr) && !IsFixedW(fr)) {
3523  fr->MoveResize(x, y, w, h);
3524  break;
3525  }
3526  if (IsFixedH(fr)) {
3527  fr->MoveResize(x, fr->GetY(), w, fr->GetDefaultHeight());
3528  break;
3529  }
3530  if (IsFixedW(fr)) {
3531  fr->MoveResize(fr->GetX(), y, fr->GetDefaultWidth(), h);
3532  break;
3533  }
3534  }
3535  break;
3536  case kTopRight:
3537  if ((x > 0) && (((int)fr->GetHeight() > y) || (y < 0))) {
3538 
3539  if (fr->GetY() + y < 2) {
3540  y = 2 - fr->GetY();
3541  }
3542  h = fr->GetHeight() - y;
3543 
3544  if (IsFixedW(fr)) {
3545  w = fr->GetDefaultWidth();
3546  } else {
3547  w = fr->GetX() + x > Int_t(wp) ? wp - fr->GetX() : UInt_t(x);
3548  }
3549  x = fr->GetX();
3550  y = fr->GetY() + y;
3551 
3552  if (!IsFixedH(fr)) {
3553  fr->MoveResize(x, y, w, h);
3554  } else {
3555  fr->Resize(x, fr->GetDefaultHeight());
3556  }
3557  }
3558  break;
3559  case kTopSide:
3560  if (((int)fr->GetHeight() > y) || (y < 0)) {
3561  if (IsFixedH(fr)) {
3562  break;
3563  }
3564 
3565  if (fr->GetY() + y < 2) {
3566  y = 2 - fr->GetY();
3567  }
3568  h = fr->GetHeight() - y;
3569  w = fr->GetWidth();
3570  x = fr->GetX();
3571  y = fr->GetY() + y;
3572 
3573  fr->MoveResize(x, y, w, h);
3574  }
3575  break;
3576  case kBottomLeft:
3577  if ((((int)fr->GetWidth() > x) || (x < 0)) && (y > 0)) {
3578 
3579  if (fr->GetX() + x < 2) {
3580  x = 2 - fr->GetX();
3581  }
3582  h = fr->GetY() + y > Int_t(hp) ? hp - fr->GetY() : UInt_t(y);
3583  w = fr->GetWidth() - x;
3584  x = fr->GetX() + x;
3585 
3586  if (!IsFixedH(fr) && !IsFixedW(fr)) {
3587  fr->MoveResize(x, fr->GetY(), w, h);
3588  break;
3589  }
3590  if (IsFixedH(fr)) {
3591  fr->MoveResize(x, fr->GetY(), w, fr->GetDefaultHeight());
3592  break;
3593  }
3594  if (IsFixedW(fr)) {
3595  fr->MoveResize(fr->GetX(), fr->GetY(),
3596  fr->GetDefaultWidth(), h);
3597  break;
3598  }
3599  }
3600  break;
3601  case kBottomRight:
3602  if ((x > 0) && (y > 0)) {
3603  w = !IsFixedW(fr) ? UInt_t(x) : fr->GetDefaultWidth();
3604  h = !IsFixedH(fr) ? UInt_t(y) : fr->GetDefaultHeight();
3605 
3606  h = fr->GetY() + h > hp ? hp - fr->GetY() : h;
3607  w = fr->GetX() + w > wp ? wp - fr->GetX() : w;
3608 
3609  //canResize(comp, 0, 0, w, h);
3610  fr->Resize(w, h);
3611  }
3612  break;
3613  case kBottomSide:
3614  if (y > 0) {
3615  if (IsFixedH(fr)) {
3616  break;
3617  }
3618 
3619  w = fr->GetWidth();
3620  h = fr->GetY() + y > (Int_t)hp ? hp - fr->GetY() : UInt_t(y);
3621 
3622  //canResize(comp, 0, 0, w, h);
3623  fr->Resize(w, h);
3624  }
3625  break;
3626  case kLeftSide:
3627  if ((int)fr->GetWidth() > x ) {
3628  if (IsFixedW(fr)) {
3629  break;
3630  }
3631 
3632  if (fr->GetX() + x < 2) {
3633  x = 2 - fr->GetX();
3634  }
3635  w = fr->GetWidth() - x;
3636  h = fr->GetHeight();
3637  y = fr->GetY();
3638  x = fr->GetX() + x;
3639 
3640  //canResize(comp, x, y, w, h);
3641  fr->MoveResize(x, y, w, h);
3642  }
3643  break;
3644  case kRightSide:
3645  if (x > 0) {
3646  if (IsFixedW(fr)) {
3647  break;
3648  }
3649 
3650  h = fr->GetHeight();
3651  w = fr->GetX() + x > (Int_t)wp ? wp - fr->GetX() : UInt_t(x);
3652  //canResize(comp, 0, 0, w, h);
3653  fr->Resize(w, h);
3654  }
3655  break;
3656  default:
3657  break;
3658  }
3659  if (comp && (!comp->IsLayoutBroken() || IsFixedLayout(comp))) {
3660  layoutFrame(comp);
3661  }
3662 
3663  gVirtualX->SetCursor(fClient->GetRoot()->GetId(),
3664  gVirtualX->CreateCursor(fPimpl->fResizeType));
3665  w = fr->GetWidth();
3666  h = fr->GetHeight();
3667 
3668  if (fBuilder) {
3669  TString str = fr->ClassName();
3670  str += "::";
3671  str += fr->GetName();
3672  str += " resized ";
3673  str += TString::Format("(%d x %d)", w, h);
3674  fBuilder->UpdateStatusBar(str.Data());
3675  }
3676 
3677  fClient->NeedRedraw(fr, kTRUE);
3678  DoRedraw();
3679  fEditor->ChangeSelected(fr); //to update the geometry frame after drag resize
3680 }
3681 
3682 ////////////////////////////////////////////////////////////////////////////////
3683 /// Handle move
3684 
3686 {
3687  if (fStop || !fPimpl->fGrab || !fClient->IsEditable()) {
3688  return;
3689  }
3690 
3691  TGWindow *parent = (TGWindow*)fPimpl->fGrab->GetParent();
3692 
3693  // do not remove frame from fixed layout or non-editable parent
3694  if (IsFixedLayout(parent) || IsEditDisabled(parent)) {
3695  return;
3696  }
3697 
3698  Int_t x = fPimpl->fX - fPimpl->fXf;
3699  Int_t y = fPimpl->fY - fPimpl->fYf;
3700 
3701  static Int_t qq;
3702  static UInt_t w = 0;
3703  static UInt_t h = 0;
3704 
3705  if (w == 0) {
3706  gVirtualX->GetWindowSize(gVirtualX->GetDefaultRootWindow(), qq, qq, w, h);
3707  }
3708 
3709  //
3710  Bool_t move = (x > 0) && (y > 0) && ((x + fPimpl->fGrab->GetWidth()) < (w - 0)) &&
3711  ((y + fPimpl->fGrab->GetHeight()) < (h - 30));
3712 
3713 
3714  // we are out of "win32 world"
3715  if (!move && !gVirtualX->InheritsFrom("TGX11")) {
3716  EndDrag();
3717  return;
3718  }
3719 
3720  fPimpl->fGrab->Move(x, y);
3721 
3722  if (fBuilder) {
3723  //fBuilder->Update();
3724  TString str = fPimpl->fGrab->ClassName();
3725  str += "::";
3726  str += fPimpl->fGrab->GetName();
3727  str += " is moved to absolute position ";
3728  str += TString::Format("(%d , %d)", x, y);
3729  fBuilder->UpdateStatusBar(str.Data());
3730  }
3731 
3733 }
3734 
3735 ////////////////////////////////////////////////////////////////////////////////
3736 /// Return a pointer to the parent mdi frame
3737 
3739 {
3740  if (fStop || !in) {
3741  return 0;
3742  }
3743 
3744  TGFrame *p = in;
3745 
3746  while (p && (p != fClient->GetDefaultRoot()) &&
3748  if (p->InheritsFrom(TGMdiFrame::Class())) {
3749  return p;
3750  }
3751  p = (TGFrame*)p->GetParent();
3752  }
3753  return 0;
3754 }
3755 
3756 ////////////////////////////////////////////////////////////////////////////////
3757 /// Raise guibuilder's mdi frame.
3758 
3760 {
3761  if (fStop || !comp) {
3762  return;
3763  }
3764 
3765  if (comp && comp->InheritsFrom(TGMdiFrame::Class()) && fBuilder) {
3766  TGFrame *mdi = fBuilder->FindEditableMdiFrame(comp);
3767  if (mdi) {
3768  // dragged frame is taken from some main frame
3769  //if (fPimpl->fGrab && fClient->GetRoot()->InheritsFrom(TGMainFrame::Class())) {
3770  // fBuilder->MapRaised();
3771  //}
3772  }
3773  if (fBuilder->GetMdiMain()->GetCurrent() != comp) {
3775  }
3776  }
3777 }
3778 
3779 ////////////////////////////////////////////////////////////////////////////////
3780 /// Look for the drop target under grabbed/selected frame while moving
3781 
3783 {
3784  if (fStop || !fPimpl->fGrab ) {
3785  return;
3786  }
3787 
3788  Int_t x = fPimpl->fGrab->GetX();
3789  Int_t y = fPimpl->fGrab->GetY();
3790  UInt_t w = fPimpl->fGrab->GetWidth();
3791  UInt_t h = fPimpl->fGrab->GetHeight();
3792 
3793  Bool_t ok = CheckTargetAtPoint(x - 1, y - 1);
3794 
3795  if (!ok) {
3796  ok = CheckTargetAtPoint(x + w + 1, y + h + 1);
3797  }
3798 
3799  if (!ok) {
3800  ok = CheckTargetAtPoint(x + w + 1, y - 1);
3801  }
3802 
3803  if (!ok) {
3804  ok = CheckTargetAtPoint(x - 1, y + h + 1);
3805  }
3806 }
3807 
3808 ////////////////////////////////////////////////////////////////////////////////
3809 /// Helper. Look for the drop target under grabbed/selected frame while moving.
3810 
3812 {
3813  if (fStop || !fPimpl->fGrab) {
3814  return kFALSE;
3815  }
3816 
3817  UInt_t ww = fPimpl->fGrab->GetWidth();
3818  UInt_t hh = fPimpl->fGrab->GetHeight();
3819  Bool_t ret = kFALSE;
3820  Window_t c;
3821  TGWindow *win = 0;
3822 
3824 
3825  if (w && (w != gVirtualX->GetDefaultRootWindow())) {
3826  win = fClient->GetWindowById(w);
3827  TGCompositeFrame *comp = 0;
3828 
3829  if (!win) {
3830  goto out;
3831  }
3832 
3833  if (win->InheritsFrom(TGCompositeFrame::Class())) {
3834  comp = (TGCompositeFrame *)win;
3835  } else if (win->GetParent() != fClient->GetDefaultRoot()) {
3836  comp = (TGCompositeFrame *)win->GetParent();
3837  }
3838 
3839  if (comp) {
3840  gVirtualX->TranslateCoordinates(fClient->GetDefaultRoot()->GetId(),
3841  comp->GetId(), x, y, x, y, c);
3842 
3843  RaiseMdiFrame(comp);
3844 
3845  if ((comp != fPimpl->fGrab) && (x >= 0) && (y >= 0) &&
3846  (x + ww <= comp->GetWidth()) &&
3847  (y + hh <= comp->GetHeight())) {
3848 
3849  if (comp != fTarget) {
3850  comp->HandleDragEnter(fPimpl->fGrab);
3851 
3852  if (fTarget) fTarget->HandleDragLeave(fPimpl->fGrab);
3853 
3854  else Snap2Grid();
3855  } else {
3856  if (fTarget) {
3857  fTarget->HandleDragMotion(fPimpl->fGrab);
3858  }
3859  }
3860 
3861  fTarget = comp;
3862  fTargetId = comp->GetId();
3863  ret = kTRUE;
3864  return ret;
3865 
3866  } else {
3867  if (fTarget) {
3868  fTarget->HandleDragLeave(fPimpl->fGrab);
3869  }
3870  fTarget = 0;
3871  fTargetId = 0;
3872  }
3873  }
3874  }
3875 
3876 out:
3877  if (fTarget) {
3878  fTarget->HandleDragLeave(fPimpl->fGrab);
3879  }
3880 
3881  if (!w || !win) {
3882  fTarget = 0;
3883  fTargetId = 0;
3884  }
3885  return ret;
3886 }
3887 
3888 ////////////////////////////////////////////////////////////////////////////////
3889 /// Handle motion event
3890 
3892 {
3893  if (fStop) {
3894  return kFALSE;
3895  }
3896 
3897  static Long64_t was = gSystem->Now();
3898  static Int_t gy = event->fYRoot;
3899  static Int_t gx = event->fXRoot;
3900 
3901  Long64_t now = gSystem->Now();
3902 
3903  if ((now-was < 100) || !(event->fState & kButton1Mask) ||
3904  ((event->fYRoot == gy) && (event->fXRoot == gx))) {
3905  return kFALSE;
3906  }
3907 
3908  was = now;
3909  gy = event->fYRoot;
3910  gx = event->fXRoot;
3911 
3912  if (!fDragging) {
3913  if (fMoveWaiting && ((TMath::Abs(fPimpl->fX - event->fXRoot) > 10) ||
3914  (TMath::Abs(fPimpl->fY - event->fYRoot) > 10))) {
3915 
3916  return StartDrag(fSource, event->fXRoot, event->fYRoot);
3917  }
3918  } else {
3919  fPimpl->fX = event->fXRoot;
3920  fPimpl->fY = event->fYRoot;
3921 
3922  switch (fDragType) {
3923  case kDragLasso:
3924  DrawLasso();
3925  fSelectionIsOn = event->fState & kKeyShiftMask;
3926  break;
3927  case kDragMove:
3928  case kDragCopy:
3929  case kDragLink:
3930  DoMove();
3931  break;
3932  case kDragResize:
3933  DoResize();
3934  break;
3935  default:
3936  break;
3937  }
3938  }
3940  return kTRUE;
3941 }
3942 
3943 ////////////////////////////////////////////////////////////////////////////////
3944 /// Put created frame at position of the last mouse click
3945 
3947 {
3948  Int_t x0, y0, x, y;
3949  Window_t c;
3950 
3951  if (fStop || !frame || !fClient->IsEditable()) {
3952  return;
3953  }
3954 
3955  frame->MapSubwindows();
3956  TGFrame *root = (TGFrame*)fClient->GetRoot();
3957 
3958  gVirtualX->TranslateCoordinates(fClient->GetDefaultRoot()->GetId(),
3959  root->GetId(),
3960  fPimpl->fX0 , fPimpl->fY0, x0, y0, c);
3961  gVirtualX->TranslateCoordinates(fClient->GetDefaultRoot()->GetId(),
3962  root->GetId(),
3963  fPimpl->fX , fPimpl->fY, x, y, c);
3964 
3965  ToGrid(x, y);
3966  ToGrid(x0, y0);
3967 
3968  UInt_t w = TMath::Abs(x - x0);
3969  UInt_t h = TMath::Abs(y - y0);
3970  x = x > x0 ? x0 : x;
3971  y = y > y0 ? y0 : y;
3972 
3973  // do not create frame with size smaller when default size
3974  w = w < frame->GetDefaultWidth() + 2 ? frame->GetDefaultWidth() + 2 : w;
3975  h = h < frame->GetDefaultHeight() + 2 ? frame->GetDefaultHeight() + 2 : h;
3976 
3977  // do not create frame out of editable space
3978  x = x + w > root->GetWidth() ? Int_t(root->GetWidth() - w) : x;
3979  y = y + h > root->GetHeight() ? Int_t(root->GetHeight() - h) : y;
3980 
3981  frame->Move(x, y);
3982 
3983  UInt_t grid = GetGridStep();
3984 
3985  if (IsFixedW(frame) || IsFixedH(frame) || IsFixedSize(frame)) {
3986  w = IsFixedW(frame) ? frame->GetDefaultWidth() : w;
3987  h = IsFixedH(frame) ? frame->GetDefaultHeight() : h;
3988  frame->Resize(w < grid ? grid : w, h < grid ? grid : h);
3989  } else {
3990  if (frame->InheritsFrom(TGVerticalFrame::Class())) {
3991  frame->Resize(w < grid ? 15*grid : w, h < grid ? 30*grid : h);
3992  } else if (frame->InheritsFrom(TGHorizontalFrame::Class())) {
3993  frame->Resize(w < grid ? 30*grid : w, h < grid ? 15*grid : h);
3994  }
3995  else frame->Resize(w < 2*grid ? 2*grid : w, h < 2*grid ? 2*grid : h);
3996  }
3997 
3998  frame->MapRaised();
3999  frame->SetCleanup(kDeepCleanup);
4000  frame->AddInput(kButtonPressMask);
4001 
4004  edit->SetCleanup(kDeepCleanup);
4005  ReparentFrames(frame, edit);
4006  frame->MapRaised();
4007  //edit->SetLayoutBroken();
4008  UInt_t g = 2;
4009  // temporary hack for status bar
4010  if (frame->InheritsFrom("TGStatusBar")) {
4011  edit->AddFrame(frame, new TGLayoutHints(kLHintsBottom | kLHintsExpandX));
4012  }
4013  else {
4014  edit->AddFrame(frame, hints ? hints : new TGLayoutHints(kLHintsNormal, g, g, g, g));
4015  }
4016 
4017  if (hints && !edit->IsLayoutBroken()) {
4018  edit->GetLayoutManager()->Layout();
4019  } else {
4020  edit->Layout();
4021  }
4022  }
4023  if (fBuilder) {
4024  TString str = frame->ClassName();
4025  str += "::";
4026  str += frame->GetName();
4027  str += " created";
4028  fBuilder->UpdateStatusBar(str.Data());
4029  }
4030 
4031  if (frame->InheritsFrom(TGCanvas::Class())) {
4032  frame = ((TGCanvas*)frame)->GetContainer();
4033  }
4034 
4035  SelectFrame(frame);
4036 
4037 }
4038 ////////////////////////////////////////////////////////////////////////////////
4039 /// Draw lasso for allocation new object
4040 
4042 {
4043  if (fStop || !fClient->IsEditable()) {
4044  return;
4045  }
4046 
4047  UngrabFrame();
4048 
4049  Int_t x0, y0, x, y;
4050  Window_t c;
4051  TGFrame *root = (TGFrame*)fClient->GetRoot();
4052 
4053  gVirtualX->TranslateCoordinates(fClient->GetDefaultRoot()->GetId(), root->GetId(),
4054  fPimpl->fX0 , fPimpl->fY0, x0, y0, c);
4055  gVirtualX->TranslateCoordinates(fClient->GetDefaultRoot()->GetId(), root->GetId(),
4056  fPimpl->fX , fPimpl->fY, x, y, c);
4057 
4058  UInt_t w, h;
4059  Bool_t xswap = kFALSE;
4060  Bool_t yswap = kFALSE;
4061 
4062  // check limits
4063 
4064  if ((x == x0) || ( y==y0 )) return; //lasso is not rectangle -> do not draw it
4065 
4066  if (x > x0) {
4067  x0 = x0 < 0 ? 0 : x0;
4068  w = x - x0;
4069  } else {
4070  x = x < 0 ? 0 : x;
4071  w = x0 - x;
4072  x0 = x;
4073  xswap = kTRUE;
4074  }
4075 
4076  if (y > y0) {
4077  y0 = y0 < 0 ? 0 : y0;
4078  h = y - y0;
4079  } else {
4080  y = y < 0 ? 0 : y;
4081  h = y0 - y;
4082  y0 = y;
4083  yswap = kTRUE;
4084  }
4085 
4086  w = x0 + w > root->GetWidth() ? root->GetWidth() - x0 : w;
4087  h = y0 + h > root->GetHeight() ? root->GetHeight() - y0 : h;
4088  x = x0 + w;
4089  y = y0 + h;
4090 
4091  ToGrid(x, y);
4092  ToGrid(x0, y0);
4093 
4094  // correct fPimpl->fX0 , fPimpl->fY0 , fPimpl->fX , fPimpl->fY
4095  gVirtualX->TranslateCoordinates(root->GetId(), fClient->GetDefaultRoot()->GetId(),
4096  xswap ? x : x0, yswap ? y : y0,
4097  fPimpl->fX0 , fPimpl->fY0, c);
4098  gVirtualX->TranslateCoordinates(root->GetId(), fClient->GetDefaultRoot()->GetId(),
4099  xswap ? x0 : x, yswap ? y0 : y,
4100  fPimpl->fX , fPimpl->fY, c);
4101  DoRedraw();
4102 
4103  gVirtualX->DrawRectangle(fClient->GetRoot()->GetId(),
4104  GetBlackGC()(), x0, y0, w, h);
4105  gVirtualX->DrawRectangle(fClient->GetRoot()->GetId(),
4106  GetBlackGC()(), x0+1, y0+1, w-2, h-2);
4107 
4108  gVirtualX->SetCursor(fId, gVirtualX->CreateCursor(kCross));
4109  gVirtualX->SetCursor(fClient->GetRoot()->GetId(), gVirtualX->CreateCursor(kCross));
4110 
4112  root->RequestFocus();
4113 
4114  if (fBuilder) {
4115  TString str = "Lasso drawn. Align frames inside or presss Return key to grab frames.";
4116  fBuilder->UpdateStatusBar(str.Data());
4117  }
4118 }
4119 
4120 ////////////////////////////////////////////////////////////////////////////////
4121 /// Handle client message
4122 
4124 {
4125  if (fStop) {
4126  return kFALSE;
4127  }
4128 
4129  if ((event->fFormat == 32) && ((Atom_t)event->fUser[0] == gWM_DELETE_WINDOW) &&
4130  (event->fHandle != gROOT_MESSAGE)) {
4131 
4132  if (fPimpl->fPlane && (fPimpl->fPlane->GetId() == event->fWindow)) {
4133  fPimpl->fPlane = 0;
4134  }
4135 
4136  TGWindow *root = (TGWindow*)fClient->GetRoot();
4137  if (!root || (root == fClient->GetDefaultRoot())) {
4139  return kTRUE;
4140  }
4142 
4143  if (event->fWindow == main->GetId()) {
4144  if (main != fBuilder) {
4145  if (fEditor && !fEditor->IsEmbedded()) {
4146  delete fEditor;
4147  fEditor = 0;
4148  }
4149 
4151  return kTRUE;
4152  }
4153 
4154  delete fFrameMenu;
4155  fFrameMenu =0;
4156 
4157  delete fLassoMenu;
4158  fLassoMenu = 0;
4159 
4160  delete fPimpl->fGrid;
4161  fPimpl->fGrid = 0;
4162  Reset1();
4163 
4164  } else if (fBuilder && (event->fWindow == fBuilder->GetId())) {
4165  fBuilder->CloseWindow();
4166 
4167  } else if (fEditor && (event->fWindow == fEditor->GetMainFrame()->GetId())) {
4169  fEditor = 0;
4170  }
4171 
4172  // to avoid segv. stop editting
4174  }
4175 
4176  return kFALSE;
4177 }
4178 
4179 ////////////////////////////////////////////////////////////////////////////////
4180 /// Handle destroy notify
4181 
4183 {
4184  if (fPimpl->fPlane && (fPimpl->fPlane->GetId() == event->fWindow)) {
4185  fPimpl->fPlane = 0;
4186  }
4187 
4188  return kFALSE;
4189 }
4190 
4191 
4192 ////////////////////////////////////////////////////////////////////////////////
4193 /// not used yet.
4194 
4196 {
4197  if (fStop) {
4198  return kFALSE;
4199  }
4200 
4201  return kFALSE;
4202 }
4203 
4204 ////////////////////////////////////////////////////////////////////////////////
4205 /// not used yet.
4206 
4208 {
4209  if (fStop) {
4210  return kFALSE;
4211  }
4212 
4213  return kFALSE;
4214 }
4215 
4216 ////////////////////////////////////////////////////////////////////////////////
4217 /// Find parent frame which can be dragged
4218 
4220 {
4221  if (fStop) {
4222  return 0;
4223  }
4224 
4225  TGFrame *ret = (TGFrame*)p;
4226  TGWindow *parent = (TGWindow*)ret->GetParent();
4227 
4228  while (parent && (parent != fClient->GetDefaultRoot())) {
4229  if (!IsFixedLayout(parent) && !IsEditDisabled(parent)) {
4230  return ret;
4231  }
4232  ret = (TGFrame*)parent;
4233  parent = (TGWindow*)ret->GetParent();
4234  }
4235 
4236  return 0;
4237 }
4238 
4239 ////////////////////////////////////////////////////////////////////////////////
4240 /// Find parent frame which can be resized
4241 
4243 {
4244  if (fStop) {
4245  return 0;
4246  }
4247 
4248  TGWindow *parent = p;
4249 
4250  while (parent && (parent != fClient->GetDefaultRoot())) {
4251  if (!IsFixedSize(parent) &&
4252  !IsFixedLayout((TGWindow*)parent->GetParent()) &&
4253  !IsEditDisabled((TGWindow*)parent->GetParent())) {
4254  return parent;
4255  }
4256  parent = (TGWindow*)parent->GetParent();
4257  }
4258 
4259  return 0;
4260 }
4261 
4262 ////////////////////////////////////////////////////////////////////////////////
4263 /// Start dragging.
4264 
4266 {
4267  if (fStop || fDragging) {
4268  return kFALSE;
4269  }
4270 
4271  TGFrame *mov = src;
4272 
4273  // special case when frame was grabbed via spacebar pressing
4274  if (fPimpl->fSpacePressedFrame) {
4275  if (fDragType == kDragNone) {
4276  fDragType = kDragMove;
4277  mov = fPimpl->fSpacePressedFrame;
4278  } else {
4279  fPimpl->fSpacePressedFrame = 0;
4280  }
4281  }
4282 
4283  TGWindow *parent = (TGWindow*)(mov ? mov->GetParent() : 0);
4284 
4285  // do not remove frame from fixed layout or non-editable parent
4286  // try to drag "draggable parent"
4287  if (parent && (IsFixedLayout(parent) || IsEditDisabled(parent))) {
4288  mov = GetMovableParent(parent);
4289  if (!mov) {
4290  return kFALSE;
4291  }
4292  }
4293 
4294  SetEditable(kTRUE); // grab server
4295 
4296  fPimpl->fX = x;
4297  fPimpl->fY = y;
4299 
4300  fPimpl->fRepeatTimer->Reset();
4301  gSystem->AddTimer(fPimpl->fRepeatTimer);
4302 
4303  fMoveWaiting = kFALSE;
4304  fDragging = kTRUE;
4305  if (src) gVirtualX->SetCursor(src->GetId(), gVirtualX->CreateCursor(kMove));
4306 
4307  switch (fDragType) {
4308  case kDragCopy:
4309  HandleCopy();
4310  HandlePaste();
4311  GrabFrame(fPimpl->fGrab);
4312  break;
4313  case kDragMove:
4314  fPimpl->fGrab = mov;
4315  GrabFrame(fPimpl->fGrab);
4316  break;
4317  default:
4318  //fPimpl->fGrab = 0;
4319  break;
4320  }
4321 
4322  return kTRUE;
4323 }
4324 
4325 ////////////////////////////////////////////////////////////////////////////////
4326 /// End dragging.
4327 
4329 {
4330  TGFrame *frame = 0;
4331  Bool_t ret = kFALSE;
4332 
4333  if (fStop) {
4334  return kFALSE;
4335  }
4336 
4337  fMoveWaiting = kFALSE; // for sanity check
4338 
4339  if (fPimpl->fGrab && (fDragType >= kDragMove) && (fDragType <= kDragLink)) {
4340 
4341  ret = Drop();
4342 
4343  } else if (fBuilder && fBuilder->IsExecutable() &&
4344  (fDragType == kDragLasso) && !fSelectionIsOn) {
4345 
4346  frame = (TGFrame*)fBuilder->ExecuteAction();
4347  PlaceFrame(frame, fBuilder->GetAction()->fHints);
4349  ret = kTRUE;
4350  //return ret;
4351  } else if ((fDragType == kDragLasso) && fSelectionIsOn) {
4352 
4354  ret = kTRUE;
4355  }
4356 
4357  if (!fLassoDrawn) {
4358  DoRedraw();
4359  }
4360 
4361  Reset1();
4362  fPimpl->fSpacePressedFrame = 0;
4363 
4364  if (fBuilder) {
4365  fBuilder->SetAction(0);
4366  }
4367 
4368  return ret;
4369 }
4370 
4371 ////////////////////////////////////////////////////////////////////////////////
4372 /// Do cancel action.
4373 
4375 {
4376  if (fStop) {
4377  return kFALSE;
4378  }
4379 
4380  fTarget = 0;
4381  EndDrag();
4382  return kTRUE;
4383 }
4384 
4385 ////////////////////////////////////////////////////////////////////////////////
4386 /// Drop grabbed frame
4387 
4389 {
4390  if (fStop || !fDragging || !fPimpl->fGrab ||
4391  !((fDragType >= kDragMove) && (fDragType <= kDragLink))) {
4392  return kFALSE;
4393  }
4394 
4395  fDropStatus = kFALSE;
4396  TGFrame *frame = 0;
4397  TGFrame *parent = 0;
4398  Int_t x, y;
4399  Window_t c;
4400 
4401  switch (fDragType) {
4402  case kDragCopy:
4403  case kDragMove:
4404  frame = (TGFrame*)fPimpl->fGrab;
4405  break;
4406  default:
4407  break;
4408  }
4409 
4411 
4412  if (fTarget && fPimpl->fGrab && (w == fTarget) && w &&
4413  (w != fClient->GetDefaultRoot())) {
4414  parent = fTarget;
4415 
4416  gVirtualX->TranslateCoordinates(fClient->GetDefaultRoot()->GetId(),
4417  fTarget->GetId(),
4418  fPimpl->fGrab->GetX(),
4419  fPimpl->fGrab->GetY(), x, y, c);
4420  fTarget->HandleDragLeave(fPimpl->fGrab);
4421  } else {
4422  parent = (TGFrame*)fPimpl->fGrabParent;
4423  x = fPimpl->fGrabX;
4424  y = fPimpl->fGrabY;
4425  }
4426 
4427  //reject move if layout is on
4428  if (parent && !parent->IsLayoutBroken() && (parent == fPimpl->fGrabParent) ) {
4429  fDropStatus = 0;
4430  } else if (parent && frame && (parent != fClient->GetDefaultRoot()) ) {
4431  ToGrid(x, y);
4432  fDropStatus = parent->HandleDragDrop(frame, x, y, fPimpl->fGrabLayout);
4433 
4434  // drop was rejected
4435  if (!fDropStatus) {
4436  if (fDragType == kDragMove) { // return dragged frame to initial position
4437  parent = (TGFrame*)fPimpl->fGrabParent;
4438  x = fPimpl->fGrabX;
4439  y = fPimpl->fGrabY;
4440  frame = fPimpl->fGrab;
4441 
4442  if (parent && frame && (parent != fClient->GetDefaultRoot())) {
4443  fDropStatus = parent->HandleDragDrop(frame, x, y, fPimpl->fGrabLayout);
4444  }
4445  } else { // (fDragType == kDragCopy) - delete it
4446  DeleteFrame(frame);
4447  }
4448  }
4449  }
4450 
4451  if (fDropStatus) {
4452  //do not break layout of the new parent if layout there is enabled
4453  if (parent && !parent->IsLayoutBroken()) {
4454  parent->Layout();
4455  }
4456 
4457  if (fBuilder) {
4458  TString str = frame->ClassName();
4459  str += "::";
4460  str += frame->GetName();
4461  str += " dropped into ";
4462  str += parent->ClassName();
4463  str += "::";
4464  str += parent->GetName();
4465  str += " at position ";
4466  str += TString::Format("(%d , %d)", x, y);
4467  fBuilder->UpdateStatusBar(str.Data());
4468  }
4469  fTarget = 0;
4470  fTargetId = 0;
4471 
4472  if (parent && (parent == fPimpl->fGrabParent) && fPimpl->fGrabListPosition &&
4473  frame && parent->InheritsFrom(TGCompositeFrame::Class())) {
4474 
4475  TList *li = ((TGCompositeFrame*)parent)->GetList();
4476  li->Remove(frame->GetFrameElement());
4477  li->AddAfter(fPimpl->fGrabListPosition, frame->GetFrameElement());
4478  }
4479  } else { // grab frame cannot be dropped
4480 // if (fDragType == kDragCopy) { // dosn't work (point is not reached ???)
4481 // HandleDelete(kFALSE);
4482 // }
4483 
4484  if (fPimpl->fGrab && fPimpl->fGrabParent) {
4485  fPimpl->fGrab->ReparentWindow(fPimpl->fGrabParent, fPimpl->fGrabX, fPimpl->fGrabY);
4486  ((TGCompositeFrame*)fPimpl->fGrabParent)->AddFrame(fPimpl->fGrab);
4487  }
4488  }
4489 
4490  fPimpl->fGrabParent = 0;
4491  fPimpl->fGrabX = 0;
4492  fPimpl->fGrabY = 0;
4493  fPimpl->fGrabListPosition = 0;
4494 
4495  return fDropStatus;
4496 }
4497 
4498 ////////////////////////////////////////////////////////////////////////////////
4499 /// Waits for either the mouse move from the given initial ButtonPress location
4500 /// or for the mouse button to be released. If mouse moves away from the initial
4501 /// ButtonPress location before the mouse button is released "IsMoveWaiting"
4502 /// returns kTRUE. If the mouse button released before the mose moved from the
4503 /// initial ButtonPress location, "IsMoveWaiting" returns kFALSE.
4504 
4506 {
4507  return fMoveWaiting;
4508 }
4509 
4510 ////////////////////////////////////////////////////////////////////////////////
4511 /// Layout and Resize frame.
4512 /// If global is kFALSE - compact selected frame
4513 /// If global is kFALSE - compact main frame of selected frame
4514 
4516 {
4517  TGCompositeFrame *comp = 0;
4518  TGFrameElement *fe;
4519 
4520  if (fStop || !fClient || !fClient->IsEditable() || !fPimpl->fGrab) {
4521  return;
4522  }
4523 
4524  TGWindow *parent = (TGWindow*)fPimpl->fGrab->GetParent();
4525 
4526  if (global) {
4527  if (!fBuilder) {
4529  } else {
4531  if (!comp) {
4533  }
4534  }
4535  } else {
4536  if (fPimpl->fGrab &&
4537  fPimpl->fGrab->InheritsFrom(TGCompositeFrame::Class())) {
4538  comp = (TGCompositeFrame*)fPimpl->fGrab;
4539  } else {
4540  comp = (TGCompositeFrame*)parent;
4541  }
4542  }
4543 
4544  if (!comp || IsFixedLayout(comp) || IsFixedLayout(parent) ||
4545  IsFixedSize(comp) || IsFixedH(comp) || IsFixedW(comp)) return;
4546 
4547  comp->SetLayoutBroken(kFALSE);
4548 
4549  TIter next(comp->GetList());
4550 
4551  TGFrame *root = (TGFrame *)fClient->GetRoot();
4552  root->SetEditable(kFALSE);
4553 
4554  TGDimension d;
4555 
4556  if (global) {
4557  while ((fe = (TGFrameElement*)next())) {
4558  if (IsFixedLayout(fe->fFrame) || IsFixedSize(fe->fFrame) ||
4559  IsFixedH(fe->fFrame) || IsFixedW(fe->fFrame)) continue;
4560 
4562  d = fe->fFrame->GetDefaultSize();
4563 
4564  // avoid "to point" resizing
4565  if ((d.fWidth > 10) && (d.fHeight > 10)) {
4566  fe->fFrame->Resize();
4567  } else if (d.fWidth > 10) {
4568  fe->fFrame->Resize(d.fWidth, 10);
4569  } else if (d.fHeight > 10) {
4570  fe->fFrame->Resize(10, d.fHeight);
4571  } else {
4572  fe->fFrame->Resize(10, 10);
4573  }
4574  fClient->NeedRedraw(fe->fFrame);
4575  }
4576  if (!IsFixedLayout(root)) {
4577  root->SetLayoutBroken(kFALSE);
4578  }
4579  fPimpl->fCompacted = kTRUE;
4580  }
4581 
4582  if (!IsFixedLayout(comp)) {
4583  comp->SetLayoutBroken(kFALSE);
4584  d = comp->GetDefaultSize();
4585 
4586  // avoid "to point" resizing
4587  if ((d.fWidth > 10) && (d.fHeight > 10)) {
4588  comp->Resize();
4589  } else if (d.fWidth > 10) {
4590  comp->Resize(d.fWidth, 10);
4591  } else if (d.fHeight > 10) {
4592  comp->Resize(10, d.fHeight);
4593  } else {
4594  comp->Resize(10, 10);
4595  }
4596  layoutFrame(comp);
4597  }
4598 
4599  if (comp->GetParent()->InheritsFrom(TGMdiDecorFrame::Class())) {
4600  TGMdiDecorFrame *decor = (TGMdiDecorFrame *)comp->GetParent();
4601  Int_t b = 2 * decor->GetBorderWidth();
4602  decor->MoveResize(decor->GetX(), decor->GetY(), comp->GetDefaultWidth() + b,
4603  comp->GetDefaultHeight() + b + decor->GetTitleBar()->GetDefaultHeight());
4604  }
4605 
4606  root->SetEditable(kTRUE);
4607 
4608  fClient->NeedRedraw(comp);
4609  SelectFrame(comp);
4610  DoRedraw();
4611 }
4612 
4613 ////////////////////////////////////////////////////////////////////////////////
4614 /// Grab server.
4615 
4617 {
4618  static Bool_t gon = kFALSE;
4619  static const TGWindow *gw = 0;
4620 
4621  if ((gon == on) && (fClient->GetRoot() == gw)) {
4622  return;
4623  }
4624 
4625  gon = on; gw = fClient->GetRoot();
4626 
4627  if (on) {
4628  fStop = kFALSE;
4629 
4630  if (fPimpl->fRepeatTimer) {
4631  fPimpl->fRepeatTimer->Reset();
4632  } else {
4633  fPimpl->fRepeatTimer = new TGuiBldDragManagerRepeatTimer(this, 100);
4634  }
4635  gSystem->AddTimer(fPimpl->fRepeatTimer);
4637 
4638  Snap2Grid();
4639  } else {
4641 
4642  if (fPimpl->fRepeatTimer) {
4643  fPimpl->fRepeatTimer->Remove();
4644  }
4645 
4646  fSelected = fPimpl->fGrab = 0;
4647 
4648  delete fPimpl->fGrid;
4649  fPimpl->fGrid = 0;
4650 
4651  fPimpl->ResetParams();
4652 
4653  TGWindow *root = (TGWindow*)fClient->GetRoot();
4654  if (root) {
4655  fClient->SetRoot(0);
4656  }
4657 
4660  }
4661 
4664  }
4665 
4666  if (fBuilder) {
4667  fBuilder->Update();
4668  }
4669  //CloseMenus();
4670 
4671  fStop = kTRUE;
4672  }
4673 
4674  if (on && fClient->IsEditable()) {
4675  gVirtualX->SetCursor(fClient->GetRoot()->GetId(),
4676  gVirtualX->CreateCursor(kPointer));
4677  }
4678 }
4679 
4680 ////////////////////////////////////////////////////////////////////////////////
4681 /// Return grid coordinates which are close to given
4682 
4684 {
4685  UInt_t step = GetGridStep();
4686  x = x - x%step;
4687  y = y - y%step;
4688 }
4689 
4690 ////////////////////////////////////////////////////////////////////////////////
4691 /// Main handler of actions
4692 
4694 {
4695  fPimpl->fLastPopupAction = act;
4696 
4697  switch ((EActionType)act) {
4698  case kPropertyAct:
4700  break;
4701  case kEditableAct:
4702  if (fPimpl->fSaveGrab) fPimpl->fSaveGrab->SetEditable(kTRUE);
4703  if (fBuilder) {
4705  }
4706  break;
4707  case kCutAct:
4708  HandleCut();
4709  break;
4710  case kCopyAct:
4711  HandleCopy();
4712  break;
4713  case kPasteAct:
4714  HandlePaste();
4715  break;
4716  case kCropAct:
4718  break;
4719  case kCompactAct:
4720  Compact(kFALSE);
4721  break;
4722  case kCompactGlobalAct:
4723  Compact(kTRUE);
4724  break;
4725  case kDropAct:
4727  break;
4728  case kLayUpAct:
4730  break;
4731  case kLayDownAct:
4733  break;
4734  case kCloneAct:
4735  CloneEditable();
4736  break;
4737  case kGrabAct:
4739  break;
4740  case kDeleteAct:
4742  break;
4743  case kLeftAct:
4745  break;
4746  case kRightAct:
4748  break;
4749  case kUpAct:
4751  break;
4752  case kDownAct:
4754  break;
4755  case kEndEditAct:
4756  if (fBuilder) {
4758  }
4760  break;
4761  case kReplaceAct:
4762  HandleReplace();
4763  break;
4764  case kGridAct:
4765  HandleGrid();
4766  break;
4767  case kBreakLayoutAct:
4768  BreakLayout();
4769  break;
4770  case kSwitchLayoutAct:
4771  case kLayoutVAct:
4772  case kLayoutHAct:
4773  SwitchLayout();
4774  break;
4775  case kNewAct:
4776  if (fBuilder) {
4777  fBuilder->NewProject();
4778  } else {
4779  TGMainFrame *main = new TGMainFrame(fClient->GetDefaultRoot(), 300, 300);
4780  main->MapRaised();
4781  main->SetEditable(kTRUE);
4782  }
4783  break;
4784  case kOpenAct:
4785  if (fBuilder) {
4786  fBuilder->OpenProject();
4787  } else {
4788  TGMainFrame *main = new TGMainFrame(fClient->GetDefaultRoot(), 300, 300);
4789  main->MapRaised();
4790  main->SetEditable(kTRUE);
4791  }
4792  break;
4793  case kSaveAct:
4794  if (fBuilder) {
4796  (!fClient->IsEditable() && fBuilder->GetMdiMain()->GetCurrent())) {
4797  fBuilder->SaveProject();
4798  } else {
4799  Save();
4800  }
4801  } else {
4802  Save();
4803  }
4804  break;
4805  case kSaveFrameAct:
4806  SaveFrame();
4807  break;
4808  default:
4809  break;
4810  }
4811 
4812  fPimpl->fPlacePopup = kFALSE;
4813 
4814  if (fBuilder) {
4815  fBuilder->SetAction(0);
4816  //fBuilder->Update();
4817  }
4818 
4819  if (fPimpl->fSaveGrab) {
4820  fClient->NeedRedraw(fPimpl->fSaveGrab, kTRUE);
4821  }
4822 
4823  DoRedraw();
4824 }
4825 
4826 ////////////////////////////////////////////////////////////////////////////////
4827 /// kTRUE - if it's possible to switch disable/enable layout
4828 
4830 {
4831  return (!(w->GetEditDisabled() & kEditDisable) &&
4833 }
4834 
4835 ////////////////////////////////////////////////////////////////////////////////
4836 /// kTRUE - if it's possible to change layout order in the parent's layout of window w
4837 
4839 {
4840  return (w->GetParent()->InheritsFrom(TGCompositeFrame::Class()) &&
4841  !((TGCompositeFrame*)w->GetParent())->IsLayoutBroken() &&
4842  !IsFixedLayout((TGWindow*)w->GetParent()));
4843 }
4844 
4845 ////////////////////////////////////////////////////////////////////////////////
4846 /// kTRUE is frame could be compacted/"layouted"
4847 
4849 {
4850  return CanChangeLayout(w);
4851 /*
4852  return (!IsFixedLayout(w) &&
4853  w->InheritsFrom(TGCompositeFrame::Class()) &&
4854  ((TGCompositeFrame*)w)->IsLayoutBroken() &&
4855  !IsEditDisabled((TGWindow*)w->GetParent()) &&
4856  !IsFixedLayout((TGWindow*)w->GetParent()));
4857 */
4858 }
4859 
4860 ////////////////////////////////////////////////////////////////////////////////
4861 /// Create widget property editor (it could be located outside of guibuilder)
4862 
4864 {
4865 // if (!fPimpl->fClickFrame) return;
4866 
4867  TGWindow *root = (TGWindow*)fClient->GetRoot();
4868  root->SetEditable(kFALSE);
4869 
4871 
4872  fBuilder->Move(fPimpl->fX0, fPimpl->fY0);
4873  fBuilder->SetWMPosition(fPimpl->fX0, fPimpl->fY0);
4875 
4876  root->SetEditable(kTRUE);
4877 }
4878 
4879 ////////////////////////////////////////////////////////////////////////////////
4880 /// Helper method
4881 
4883 {
4884  fEditor = e;
4885 
4886  if (!fEditor) {
4887  return;
4888  }
4889 
4890  ChangeSelected(fPimpl->fClickFrame);
4891  fEditor->Connect("UpdateSelected(TGFrame*)", "TGuiBldDragManager", this,
4892  "HandleUpdateSelected(TGFrame*)");
4893 }
4894 
4895 ////////////////////////////////////////////////////////////////////////////////
4896 /// Change layout order
4897 
4899 {
4900  if (fStop || !fPimpl->fGrab || !fPimpl->fGrab->GetFrameElement() ||
4901  !CanChangeLayoutOrder(fPimpl->fGrab)) {
4902  return;
4903  }
4904 
4905  TGCompositeFrame *comp = (TGCompositeFrame*)fPimpl->fGrab->GetParent();
4906  TList *li = comp->GetList();
4907  TGFrameElement *fe = fPimpl->fGrab->GetFrameElement();
4908 
4909  if (!fe) { // sanity check
4910  return;
4911  }
4912 
4913  TGFrame *frame;
4914  TGFrameElement *el;
4915 
4916  if (forward) {
4917  el = (TGFrameElement *)li->After(fe);
4918  if (!el) return;
4919  frame = el->fFrame;
4920 
4921  el->fFrame = fPimpl->fGrab;
4922  fPimpl->fGrab->SetFrameElement(el);
4923  fe->fFrame = frame;
4924  frame->SetFrameElement(fe);
4925  } else {
4926  el = (TGFrameElement *)li->Before(fe);
4927 
4928  if (!el) {
4929  return;
4930  }
4931  frame = el->fFrame;
4932 
4933  el->fFrame = fPimpl->fGrab;
4934  fPimpl->fGrab->SetFrameElement(el);
4935  fe->fFrame = frame;
4936  frame->SetFrameElement(fe);
4937  }
4938 
4939  Bool_t sav = comp->IsLayoutBroken();
4940  comp->SetLayoutBroken(kFALSE);
4941  TGWindow *root = (TGWindow *)fClient->GetRoot();
4942  root->SetEditable(kFALSE);
4943  comp->Layout();
4944  DoRedraw();
4945  root->SetEditable(kTRUE);
4946 
4947  if (sav) {
4948  comp->SetLayoutBroken(kTRUE);
4949  }
4950  SelectFrame(el->fFrame);
4951 }
4952 
4953 ////////////////////////////////////////////////////////////////////////////////
4954 /// Switch on/of grid drawn.
4955 
4957 {
4958  if (fStop) {
4959  return;
4960  }
4961 
4962  TGWindow *root = (TGWindow*)fClient->GetRoot();
4963 
4964  if (!root || (root == fClient->GetDefaultRoot())) {
4965  return;
4966  }
4967 
4968  if (fPimpl->fGrid->fgStep > 1) {
4969  fPimpl->fGrid->SetStep(1);
4970  if (fBuilder) {
4971  fBuilder->UpdateStatusBar("Grid switched OFF");
4972  }
4973  } else {
4974  fPimpl->fGrid->SetStep(gGridStep);
4975 
4976  if (fBuilder) {
4977  fBuilder->UpdateStatusBar("Grid switched ON");
4978  }
4979 
4980  if (root->InheritsFrom(TGCompositeFrame::Class())) {
4981  TGCompositeFrame *comp = (TGCompositeFrame*)root;
4982  TIter next(comp->GetList());
4983  TGFrameElement *fe;
4984  Int_t x, y, w, h;
4985 
4986  while ((fe = (TGFrameElement*)next())) {
4987  x = fe->fFrame->GetX();
4988  y = fe->fFrame->GetY();
4989  w = fe->fFrame->GetWidth();
4990  h = fe->fFrame->GetHeight();
4991  ToGrid(x, y);
4992  ToGrid(w, h);
4993  fe->fFrame->MoveResize(x, y, w, h);
4994  }
4995  }
4996  }
4997 
4998  Snap2Grid();
5000 }
5001 
5002 ////////////////////////////////////////////////////////////////////////////////
5003 /// Helper to find a frame which can be layouted
5004 
5006 {
5007  if (fStop || !f) {
5008  return 0;
5009  }
5010 
5011  const TGWindow *parent = f->GetParent();
5012  TGCompositeFrame *ret = 0;
5013 
5014  while (parent && (parent != fClient->GetDefaultRoot())) {
5015  ret = (TGCompositeFrame*)parent;
5016  if (parent->InheritsFrom(TGMdiFrame::Class())) return ret;
5017  parent = parent->GetParent();
5018  }
5019  return ret;
5020 }
5021 
5022 ////////////////////////////////////////////////////////////////////////////////
5023 /// When selected frame was changed by guibuilder editor -> update its appearence
5024 
5026 {
5027  if (fStop || !f) {
5028  return;
5029  }
5030 
5031  TGCompositeFrame *parent = 0;
5032  if (f->GetParent() &&
5033  f->GetParent()->InheritsFrom(TGCompositeFrame::Class())) {
5034  parent = (TGCompositeFrame*)f->GetParent();
5035  }
5036 
5037  if (!parent || !CanChangeLayout(parent)) {
5038  return;
5039  }
5040 
5041  Bool_t sav = parent->IsLayoutBroken();
5042  parent->SetLayoutBroken(kFALSE);
5043 
5044  if ((parent->GetWidth() < parent->GetDefaultWidth()) ||
5045  (parent->GetHeight() < parent->GetDefaultHeight())) {
5046  parent->Resize(parent->GetDefaultSize());
5047  } else {
5048  parent->Layout();
5049  if (f->InheritsFrom(TGCompositeFrame::Class())) {
5050  layoutFrame(f);
5051  }
5052  }
5053  fClient->NeedRedraw(parent, kTRUE);
5054  fClient->NeedRedraw(f);
5055 
5056  if (sav) parent->SetLayoutBroken(kTRUE);
5057 
5058  SelectFrame(f);
5059 }
5060 
5061 ////////////////////////////////////////////////////////////////////////////////
5062 /// Hide/Unmap grab rectangles.
5063 
5065 {
5066  static Bool_t first = kFALSE;
5067 
5068  if (fPimpl->fGrabRectHidden) {
5069  return;
5070  }
5071  // skip very first event
5072  if (!first) {
5073  first = kTRUE;
5074  return;
5075  }
5076  int i = 0;
5077  for (i = 0; i < 8; i++) fPimpl->fGrabRect[i]->UnmapWindow();
5078  for (i = 0; i < 4; i++) fPimpl->fAroundFrame[i]->UnmapWindow();
5079  fPimpl->fGrabRectHidden = kTRUE;
5080 }
5081 
5082 ////////////////////////////////////////////////////////////////////////////////
5083 /// Delete widget property editor.
5084 
5086 {
5087  if (fStop || !fEditor) {
5088  return;
5089  }
5090 
5092 
5093  delete fEditor;
5094  fEditor = 0;
5095 }
5096 
5097 ////////////////////////////////////////////////////////////////////////////////
5098 /// Return the X coordinate where drag started
5099 
5101 {
5102  return fPimpl->fX0;
5103 }
5104 
5105 ////////////////////////////////////////////////////////////////////////////////
5106 /// Return the Y coordinate where drag started
5107 
5109 {
5110  return fPimpl->fY0;
5111 }
5112 
5113 ////////////////////////////////////////////////////////////////////////////////
5114 /// Return the current X coordinate of the dragged frame
5115 
5117 {
5118  return fPimpl->fY;
5119 }
5120 
5121 ////////////////////////////////////////////////////////////////////////////////
5122 /// Returns the current Y coordinate of the dragged frame
5123 
5125 {
5126  return fPimpl->fY;
5127 }
5128 
5129 ////////////////////////////////////////////////////////////////////////////////
5130 /// Disable/Enable layout for selected/grabbed composite frame.
5131 
5133 {
5134  if (fStop) {
5135  return;
5136  }
5137 
5138  TGFrame *frame = fSelected;
5139 
5140  if (!frame) {
5141  return;
5142  }
5143 
5144  TString str = frame->ClassName();
5145  str += "::";
5146  str += frame->GetName();
5147 
5148  if (IsFixedLayout(frame)) {
5149  if (fBuilder) {
5150  str += " layout cannot be broken";
5151  fBuilder->UpdateStatusBar(str.Data());
5152  }
5153  return;
5154  }
5155 
5156  frame->SetLayoutBroken(!frame->IsLayoutBroken());
5158 
5159  if (fBuilder) {
5160  str += (frame->IsLayoutBroken() ? " Disable Layout" : " Enable Layout");
5161  fBuilder->UpdateStatusBar(str.Data());
5162  }
5163  if (fPimpl->fGrab && (fPimpl->fGrab->IsA() == TGCanvas::Class())) {
5164  fPimpl->fGrab->Layout();
5165  }
5166 }
5167 
5168 ////////////////////////////////////////////////////////////////////////////////
5169