Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGCanvas.cxx
Go to the documentation of this file.
1 // @(#)root/gui:$Id$
2 // Author: Fons Rademakers 11/01/98
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, 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  This source is based on Xclass95, a Win95-looking GUI toolkit.
14  Copyright (C) 1996, 1997 David Barth, Ricky Ralston, Hector Peraza.
15 
16  Xclass95 is free software; you can redistribute it and/or
17  modify it under the terms of the GNU Library General Public
18  License as published by the Free Software Foundation; either
19  version 2 of the License, or (at your option) any later version.
20 
21 **************************************************************************/
22 
23 //////////////////////////////////////////////////////////////////////////
24 // //
25 // TGCanvas and TGViewPort and TGContainer //
26 // //
27 // A TGCanvas is a frame containing two scrollbars (a horizontal and //
28 // a vertical) and a viewport. The viewport acts as the window through //
29 // which we look at the contents of the container frame. //
30 // //
31 // A TGContainer frame manages a content area. It can display and //
32 // control a hierarchy of multi-column items, and provides the ability //
33 // to add new items at any time. By default it doesn't map subwindows //
34 // which are items of the container. In this case subwindow must //
35 // provide DrawCopy method, see for example TGLVEntry class. //
36 // It is also possible to use option which allow to map subwindows. //
37 // This option has much slower drawing speed in case of more than 1000 //
38 // items placed in container. To activate this option the fMapSubwindows//
39 // data member must be set to kTRUE (for example TTVLVContainer class) //
40 // //
41 // The TGContainer class can handle the keys: //
42 // //
43 // o F7, Ctnrl-F - activate search dialog //
44 // o F3, Ctnrl-G - continue search //
45 // o End - go to the last item in container //
46 // o Home - go to the first item in container //
47 // o PageUp,PageDown,arrow keys - navigate inside container //
48 // o Return/Enter - equivalent to double click of the mouse button //
49 // o Contrl-A - select/activate all items. //
50 // o Space - invert selection. //
51 // //
52 //////////////////////////////////////////////////////////////////////////
53 
54 #include "TGCanvas.h"
55 #include "TGListView.h"
56 #include "TGScrollBar.h"
57 #include "TTimer.h"
58 #include "KeySymbols.h"
59 #include "TSystem.h"
60 #include "TGTextEditDialogs.h"
61 #include "TGMsgBox.h"
62 #include "TGResourcePool.h"
63 #include "TList.h"
64 #include "TClass.h"
65 #include "TGListView.h"
66 #include "TGMimeTypes.h"
67 #include "TKey.h"
68 #include "TKeyMapFile.h"
69 #include "TGDNDManager.h"
70 #include "Riostream.h"
71 #include "RConfigure.h"
72 #include <stdlib.h>
73 
74 
75 TGGC *TGContainer::fgLineGC = 0;
76 
77 const Int_t kAutoScrollFudge = 10;
78 const Int_t kAcceleration[kAutoScrollFudge+1] = {1,1,1,2,3,4,6,7,8,16,32};
79 const Int_t kKeyboardTime = 700;
80 
81 ClassImp(TGCanvas);
82 ClassImp(TGViewPort);
83 ClassImp(TGContainer);
84 
85 
86 ////////////////////////////////////////////////////////////////////////////////
87 
88 class TGContainerKeyboardTimer : public TTimer {
89 private:
90  TGContainer *fContainer;
91 public:
92  TGContainerKeyboardTimer(TGContainer *t) : TTimer(kKeyboardTime) { fContainer = t; }
93  Bool_t Notify();
94 };
95 
96 ////////////////////////////////////////////////////////////////////////////////
97 /// single shot timer
98 
99 Bool_t TGContainerKeyboardTimer::Notify()
100 {
101  fContainer->SearchPattern();
102  Reset();
103  if (gSystem) gSystem->RemoveTimer(this);
104  return kFALSE;
105 }
106 
107 ////////////////////////////////////////////////////////////////////////////////
108 
109 class TGContainerScrollTimer : public TTimer {
110 private:
111  TGContainer *fContainer;
112 public:
113  TGContainerScrollTimer(TGContainer *t) : TTimer(50) { fContainer = t; }
114  Bool_t Notify();
115 };
116 
117 ////////////////////////////////////////////////////////////////////////////////
118 /// on-timeout
119 
120 Bool_t TGContainerScrollTimer::Notify()
121 {
122  fContainer->OnAutoScroll();
123  Reset();
124  return kFALSE;
125 }
126 
127 
128 ////////////////////////////////////////////////////////////////////////////////
129 /// Create a viewport object.
130 
131 TGViewPort::TGViewPort(const TGWindow *p, UInt_t w, UInt_t h,
132  UInt_t options, ULong_t back) :
133  TGCompositeFrame(p, w, h, options, back)
134 {
135  fContainer = 0;
136  fX0 = fY0 = 0;
137 
138  AddInput(kStructureNotifyMask);
139  SetWindowName();
140  fEditDisabled = kEditDisable | kEditDisableGrab;
141 }
142 
143 ////////////////////////////////////////////////////////////////////////////////
144 /// Add container frame to the viewport. We must make sure that the added
145 /// container is at least a TGCompositeFrame (TGCanvas::AddFrame depends
146 /// on it).
147 
148 void TGViewPort::SetContainer(TGFrame *f)
149 {
150  if (!f) {
151  RemoveFrame(fContainer);
152  fContainer = 0;
153  return;
154  }
155 
156  if (!fContainer) {
157  fContainer = f;
158  AddFrame(f, 0);
159  fContainer->SetEditDisabled(fContainer->GetEditDisabled() | kEditDisableGrab);
160 
161  if (fContainer->InheritsFrom(TGContainer::Class())) {
162  ((TGContainer*)fContainer)->fViewPort = this;
163  if (fParent->InheritsFrom(TGCanvas::Class())) {
164  ((TGContainer*)fContainer)->fCanvas = (TGCanvas*)fParent;
165  }
166  }
167  }
168 }
169 
170 ////////////////////////////////////////////////////////////////////////////////
171 /// Moves content of container frame in horizontal direction.
172 
173 void TGViewPort::SetHPos(Int_t xpos)
174 {
175  Int_t diff;
176 
177  if (!fContainer) return;
178 
179  if (!fContainer->InheritsFrom(TGContainer::Class())) {
180  fContainer->Move(fX0 = xpos, fY0);
181  return;
182  } else {
183  if (((TGContainer*)fContainer)->fMapSubwindows) {
184  fContainer->Move(fX0 = xpos, fY0);
185  return;
186  }
187  }
188 
189  if (-xpos < 0) return;
190  else diff = xpos - fX0;
191 
192  if (!diff) return;
193 
194  fX0 = xpos;
195 
196 #if defined(R__HAS_COCOA)
197  //In the current version of cocoa back-end, it's very expensive
198  //to read window's pixels, skip "optimization".
199  ((TGContainer*)fContainer)->DrawRegion(0, 0, fWidth, fHeight);
200 #else
201  UInt_t adiff = TMath::Abs(diff);
202 
203  if (adiff < fWidth) {
204  if (diff < 0) {
205  gVirtualX->CopyArea(fContainer->GetId(), fContainer->GetId(), GetWhiteGC()(),
206  adiff, 0, fWidth - adiff, fHeight, 0, 0);
207  adiff += 20; // draw larger region
208  ((TGContainer*)fContainer)->DrawRegion(fWidth - adiff, 0, adiff, fHeight);
209  } else {
210  gVirtualX->CopyArea(fContainer->GetId(), fContainer->GetId(), GetWhiteGC()(),
211  0, 0, fWidth - adiff, fHeight, adiff, 0);
212  adiff += 20; // draw larger region
213  ((TGContainer*)fContainer)->DrawRegion(0, 0, adiff, fHeight);
214  }
215  } else {
216  ((TGContainer*)fContainer)->DrawRegion(0, 0, fWidth, fHeight);
217  }
218 #endif
219 }
220 
221 ////////////////////////////////////////////////////////////////////////////////
222 /// Moves content of container frame in vertical direction.
223 
224 void TGViewPort::SetVPos(Int_t ypos)
225 {
226  Int_t diff;
227 
228  if (!fContainer) return;
229 
230  // for backward comatibility
231  if (!fContainer->InheritsFrom(TGContainer::Class())) {
232  fContainer->Move(fX0, fY0 = ypos);
233  return;
234  } else {
235  if (((TGContainer*)fContainer)->fMapSubwindows) {
236  fContainer->Move(fX0, fY0 = ypos);
237  return;
238  }
239  }
240 
241  if (-ypos < 0) return;
242  else diff = ypos - fY0;
243 
244  if (!diff) return;
245 
246  fY0 = ypos;
247 
248 #if defined(R__HAS_COCOA)
249  //In the current version of cocoa back-end, it's very expensive
250  //to read window's pixels, skip "optimization".
251  ((TGContainer*)fContainer)->DrawRegion(0, 0, fWidth, fHeight);
252 #else
253  UInt_t adiff = TMath::Abs(diff);
254 
255  if (adiff < fHeight) {
256  if (diff < 0) {
257  gVirtualX->CopyArea(fContainer->GetId(), fContainer->GetId(), GetWhiteGC()(),
258  0, adiff, fWidth, fHeight - adiff, 0, 0);
259  adiff += 20; // draw larger region
260  ((TGContainer*)fContainer)->DrawRegion(0, fHeight - adiff, fWidth, adiff);
261  } else {
262  gVirtualX->CopyArea(fContainer->GetId(), fContainer->GetId(), GetWhiteGC()(),
263  0, 0, fWidth, fHeight - adiff, 0, adiff);
264  adiff += 20; // draw larger region
265  ((TGContainer*)fContainer)->DrawRegion(0, 0, fWidth, adiff);
266  }
267  } else {
268  ((TGContainer*)fContainer)->DrawRegion(0, 0, fWidth, fHeight);
269  }
270 #endif
271 }
272 
273 ////////////////////////////////////////////////////////////////////////////////
274 /// Goto new position.
275 
276 void TGViewPort::SetPos(Int_t xpos, Int_t ypos)
277 {
278  if (!fContainer) return;
279 
280  SetHPos(fX0 = xpos);
281  SetVPos(fY0 = ypos);
282 }
283 
284 ////////////////////////////////////////////////////////////////////////////////
285 /// Handle resize events.
286 
287 Bool_t TGViewPort::HandleConfigureNotify(Event_t *event)
288 {
289  if (!fContainer->InheritsFrom(TGContainer::Class())) {
290  TGFrame::HandleConfigureNotify(event);
291  return kTRUE;
292  }
293 
294  TGContainer *cont = (TGContainer*)fContainer;
295 
296  // protection
297  if ((event->fWidth > 32768) || (event->fHeight > 32768)) {
298  return kFALSE;
299  }
300 
301  cont->DrawRegion(event->fX, event->fY, event->fWidth, event->fHeight);
302 
303  return kTRUE;
304 }
305 
306 ////////////////////////////////////////////////////////////////////////////////
307 /// Create a canvas container. This is the (large) frame that contains
308 /// all the list items. It will be shown through a TGViewPort (which is
309 /// created by the TGCanvas).
310 
311 TGContainer::TGContainer(const TGWindow *p, UInt_t w, UInt_t h,
312  UInt_t options, ULong_t back) :
313  TGCompositeFrame(p, w, h, options, back)
314 {
315  fXp = fYp = fX0 = fY0 = fXf = fYf = fXDND = fYDND = 0;
316  fViewPort = 0;
317  fBdown = kFALSE;
318  fMsgWindow = p;
319  fDragging = kFALSE;
320  fTotal = fSelected = 0;
321  fMapSubwindows = kFALSE;
322  fOnMouseOver = kFALSE;
323  fLastActiveEl = 0;
324  fLastDir = kTRUE;
325  fLastCase = kTRUE;
326  fLastSubstring = kFALSE;
327  fLastName = "";
328  fKeyTimer = new TGContainerKeyboardTimer(this);
329  fScrollTimer = new TGContainerScrollTimer(this);
330  fKeyTimerActive = kFALSE;
331  fScrolling = kFALSE;
332  fCanvas = 0;
333  fExposedRegion.Empty();
334 
335  gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
336  kButtonPressMask | kButtonReleaseMask |
337  kPointerMotionMask, kNone, kNone);
338 
339  AddInput(kKeyPressMask | kPointerMotionMask);
340  SetWindowName();
341 
342  SetWindowAttributes_t wattr;
343  wattr.fMask = kWAWinGravity | kWABitGravity;
344  wattr.fBitGravity = 1; // NorthWestGravity
345  wattr.fWinGravity = 1;
346  gVirtualX->ChangeWindowAttributes(fId, &wattr);
347 
348  fEditDisabled = kEditDisableGrab | kEditDisableBtnEnable;
349 }
350 
351 ////////////////////////////////////////////////////////////////////////////////
352 /// Create a canvas container. This is the (large) frame that contains
353 /// all the list items. It will be shown through a TGViewPort (which is
354 /// created by the TGCanvas).
355 
356 TGContainer::TGContainer(TGCanvas *p, UInt_t options, ULong_t back) :
357  TGCompositeFrame(p->GetViewPort(), p->GetWidth(), p->GetHeight(), options, back)
358 {
359  fXp = fYp = fX0 = fY0 = fXf = fYf = fXDND = fYDND = 0;
360  fViewPort = 0;
361  fBdown = kFALSE;
362  fMsgWindow = p->GetViewPort();
363  fCanvas = p;
364  fCanvas->GetViewPort()->SetContainer(this);
365  p->GetViewPort()->SetBackgroundColor(back);
366 
367  fDragging = kFALSE;
368  fTotal = fSelected = 0;
369  fMapSubwindows = kFALSE;
370  fOnMouseOver = kFALSE;
371  fLastActiveEl = 0;
372  fLastDir = kTRUE;
373  fLastCase = kTRUE;
374  fLastSubstring = kFALSE;
375  fLastName = "";
376  fKeyTimer = new TGContainerKeyboardTimer(this);
377  fScrollTimer = new TGContainerScrollTimer(this);
378  fKeyTimerActive = kFALSE;
379  fScrolling = kFALSE;
380  fExposedRegion.Empty();
381 
382  gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
383  kButtonPressMask | kButtonReleaseMask |
384  kPointerMotionMask, kNone, kNone);
385 
386  AddInput(kKeyPressMask | kPointerMotionMask);
387  SetWindowName();
388 
389  SetWindowAttributes_t wattr;
390  wattr.fMask = kWAWinGravity | kWABitGravity;
391  wattr.fBitGravity = 1; // NorthWestGravity
392  wattr.fWinGravity = 1;
393  gVirtualX->ChangeWindowAttributes(fId, &wattr);
394 
395  fEditDisabled = kEditDisableGrab | kEditDisableBtnEnable;
396 }
397 
398 ////////////////////////////////////////////////////////////////////////////////
399 /// Delete canvas container.
400 
401 TGContainer::~TGContainer()
402 {
403  if (TGSearchDialog::SearchDialog()) {
404  TQObject::Disconnect(TGSearchDialog::SearchDialog(), 0, this);
405  }
406 
407  delete fScrollTimer;
408  fScrollTimer = 0;
409 
410  delete fKeyTimer;
411  fKeyTimer = 0;
412 }
413 
414 ////////////////////////////////////////////////////////////////////////////////
415 /// Layout container entries.
416 
417 void TGContainer::Layout()
418 {
419  TGCompositeFrame::Layout();
420  TGLayoutManager *lm = GetLayoutManager();
421 
422  // clear content if positions of subframes changed after layout
423  if (lm && lm->IsModified()) ClearViewPort();
424 }
425 
426 ////////////////////////////////////////////////////////////////////////////////
427 /// Emit signal when current position changed.
428 
429 void TGContainer::CurrentChanged(Int_t x, Int_t y)
430 {
431  Long_t args[2];
432 
433  args[0] = x;
434  args[1] = y;
435 
436  Emit("CurrentChanged(Int_t,Int_t)",args);
437 }
438 
439 ////////////////////////////////////////////////////////////////////////////////
440 /// Emit signal when current selected frame changed.
441 
442 void TGContainer::CurrentChanged(TGFrame* f)
443 {
444  Emit("CurrentChanged(TGFrame*)", (Long_t)f);
445 }
446 
447 ////////////////////////////////////////////////////////////////////////////////
448 /// Signal emitted when keyboard key pressed
449 ///
450 /// frame - activated frame
451 /// keysym - defined in "KeySymbols.h"
452 /// mask - modifier key mask, defined in "GuiTypes.h"
453 ///
454 /// const Mask_t kKeyShiftMask = BIT(0);
455 /// const Mask_t kKeyLockMask = BIT(1);
456 /// const Mask_t kKeyControlMask = BIT(2);
457 /// const Mask_t kKeyMod1Mask = BIT(3); // typically the Alt key
458 /// const Mask_t kButton1Mask = BIT(8);
459 /// const Mask_t kButton2Mask = BIT(9);
460 /// const Mask_t kButton3Mask = BIT(10);
461 /// const Mask_t kButton4Mask = BIT(11);
462 /// const Mask_t kButton5Mask = BIT(12);
463 /// const Mask_t kAnyModifier = BIT(15);
464 
465 void TGContainer::KeyPressed(TGFrame *frame, UInt_t keysym, UInt_t mask)
466 {
467  Long_t args[3];
468  args[0] = (Long_t)frame;
469  args[1] = (Long_t)keysym;
470  args[2] = (Long_t)mask;
471  Emit("KeyPressed(TGFrame*,UInt_t,UInt_t)", args);
472  SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_KEY), keysym, mask);
473 }
474 
475 ////////////////////////////////////////////////////////////////////////////////
476 /// Signal emitted when Return/Enter key pressed.
477 /// It's equivalent to "double click" of mouse button.
478 
479 void TGContainer::ReturnPressed(TGFrame* f)
480 {
481  Emit("ReturnPressed(TGFrame*)", (Long_t)f);
482 }
483 
484 ////////////////////////////////////////////////////////////////////////////////
485 /// Signal emitted when space key pressed.
486 /// Pressing space key inverts selection.
487 
488 void TGContainer::SpacePressed(TGFrame* f)
489 {
490  Emit("SpacePressed(TGFrame*)", (Long_t)f);
491 }
492 
493 ////////////////////////////////////////////////////////////////////////////////
494 /// Signal emitted when pointer is over entry.
495 
496 void TGContainer::OnMouseOver(TGFrame* f)
497 {
498  if (!fOnMouseOver) Emit("OnMouseOver(TGFrame*)", (Long_t)f);
499  fOnMouseOver = kTRUE;
500 }
501 
502 ////////////////////////////////////////////////////////////////////////////////
503 /// Emit Clicked() signal.
504 
505 void TGContainer::Clicked(TGFrame *entry, Int_t btn)
506 {
507  Long_t args[2];
508 
509  args[0] = (Long_t)entry;
510  args[1] = btn;
511 
512  Emit("Clicked(TGFrame*,Int_t)", args);
513 }
514 
515 ////////////////////////////////////////////////////////////////////////////////
516 /// Emit Clicked() signal.
517 
518 void TGContainer::Clicked(TGFrame *entry, Int_t btn, Int_t x, Int_t y)
519 {
520  Long_t args[4];
521 
522  args[0] = (Long_t)entry;
523  args[1] = btn;
524  args[2] = x;
525  args[3] = y;
526 
527  Emit("Clicked(TGFrame*,Int_t,Int_t,Int_t)", args);
528 }
529 
530 ////////////////////////////////////////////////////////////////////////////////
531 /// Emit DoubleClicked() signal.
532 
533 void TGContainer::DoubleClicked(TGFrame *entry, Int_t btn)
534 {
535  Long_t args[2];
536 
537  args[0] = (Long_t)entry;
538  args[1] = btn;
539 
540  Emit("DoubleClicked(TGFrame*,Int_t)", args);
541 }
542 
543 ////////////////////////////////////////////////////////////////////////////////
544 /// Emit DoubleClicked() signal.
545 
546 void TGContainer::DoubleClicked(TGFrame *entry, Int_t btn, Int_t x, Int_t y)
547 {
548  Long_t args[4];
549 
550  args[0] = (Long_t)entry;
551  args[1] = btn;
552  args[2] = x;
553  args[3] = y;
554 
555  Emit("DoubleClicked(TGFrame*,Int_t,Int_t,Int_t)", args);
556 }
557 
558 ////////////////////////////////////////////////////////////////////////////////
559 /// Select all items in the container.
560 /// SelectAll() signal emitted.
561 
562 void TGContainer::SelectAll()
563 {
564  TIter next(fList);
565  TGFrameElement *el;
566  TGFrame *fr;
567 
568  while ((el = (TGFrameElement *) next())) {
569  fr = el->fFrame;
570  if (!fr->IsActive()) {
571  ActivateItem(el);
572  }
573  }
574  fSelected = fTotal;
575  SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_SELCHANGED),
576  fTotal, fSelected);
577 
578  Emit("SelectAll()");
579 }
580 
581 ////////////////////////////////////////////////////////////////////////////////
582 /// Unselect all items in the container.
583 
584 void TGContainer::UnSelectAll()
585 {
586  TIter next(fList);
587  TGFrameElement *el;
588  TGFrame *fr;
589 
590  while ((el = (TGFrameElement *) next())) {
591  fr = el->fFrame;
592  if (fr->IsActive()) {
593  DeActivateItem(el);
594  }
595  }
596  fLastActiveEl = 0;
597  fSelected = 0;
598 
599  SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_SELCHANGED),
600  fTotal, fSelected);
601 
602  Emit("UnSelectAll()");
603 }
604 
605 ////////////////////////////////////////////////////////////////////////////////
606 /// Invert the selection, all selected items become unselected and
607 /// vice versa.
608 
609 void TGContainer::InvertSelection()
610 {
611  int selected = 0;
612 
613  TIter next(fList);
614  TGFrameElement *el;
615 
616  while ((el = (TGFrameElement *) next())) {
617  if (!el->fFrame->IsActive()) {
618  ActivateItem(el);
619  ++selected;
620  } else {
621  DeActivateItem(el);
622  }
623  }
624  ClearViewPort(); // full redraw
625  fSelected = selected;
626 
627  SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_SELCHANGED),
628  fTotal, fSelected);
629 
630  Emit("InvertSelection()");
631 }
632 
633 ////////////////////////////////////////////////////////////////////////////////
634 /// Remove all items from the container.
635 
636 void TGContainer::RemoveAll()
637 {
638  TGFrameElement *el;
639  TIter next(fList);
640 
641  while ((el = (TGFrameElement *) next())) {
642  el->fFrame->DestroyWindow();
643  delete el->fFrame;
644  fList->Remove(el);
645  delete el;
646  }
647  fLastActiveEl = 0;
648  fSelected = fTotal = 0;
649  ClearViewPort(); // full redraw
650 }
651 
652 ////////////////////////////////////////////////////////////////////////////////
653 /// Remove item from container.
654 
655 void TGContainer::RemoveItem(TGFrame *item)
656 {
657  TGFrameElement *el;
658  TIter next(fList);
659  while ((el = (TGFrameElement *) next())) {
660  if (item == el->fFrame) {
661  if (fLastActiveEl && item == fLastActiveEl->fFrame) fLastActiveEl = 0;
662  item->DestroyWindow();
663  delete item;
664  fList->Remove(el);
665  delete el;
666  break;
667  }
668  }
669  ClearViewPort(); // fill redraw
670 }
671 
672 ////////////////////////////////////////////////////////////////////////////////
673 /// Return the next selected item. If the "current" pointer is 0, the first
674 /// selected item will be returned.
675 
676 const TGFrame *TGContainer::GetNextSelected(void **current)
677 {
678  TGFrame *f;
679  TObjLink *lnk = (TObjLink *) *current;
680 
681  lnk = (lnk == 0) ? fList->FirstLink() : lnk->Next();
682  while (lnk) {
683  f = (TGFrame *) ((TGFrameElement *) lnk->GetObject())->fFrame;
684  if (f->IsActive()) {
685  *current = (void *) lnk;
686  return f;
687  }
688  lnk = lnk->Next();
689  }
690  return 0;
691 }
692 
693 ////////////////////////////////////////////////////////////////////////////////
694 /// Activate item.
695 
696 void TGContainer::ActivateItem(TGFrameElement *el)
697 {
698  TGFrame *fr = el->fFrame;
699  fr->Activate(kTRUE);
700 
701  if (fLastActiveEl != el) {
702  fLastActiveEl = el;
703  CurrentChanged(fLastActiveEl->fFrame->GetX(), fLastActiveEl->fFrame->GetY());
704  CurrentChanged(fLastActiveEl->fFrame);
705  fSelected++;
706  }
707 
708  if (!fSelected) fSelected = 1;
709 
710  SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_SELCHANGED), fTotal, fSelected);
711 
712  TGPosition pos = GetPagePosition();
713  DrawRegion(fr->GetX() - pos.fX, fr->GetY() - pos.fY, fr->GetWidth(), fr->GetHeight());
714 }
715 
716 ////////////////////////////////////////////////////////////////////////////////
717 /// DeActivate item.
718 
719 void TGContainer::DeActivateItem(TGFrameElement *el)
720 {
721  TGFrame *fr = el->fFrame;
722  fr->Activate(kFALSE);
723  SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_SELCHANGED), fTotal, fSelected);
724 
725  TGPosition pos = GetPagePosition();
726  DrawRegion(fr->GetX() - pos.fX, fr->GetY() - pos.fY, fr->GetWidth(), fr->GetHeight());
727 }
728 
729 ////////////////////////////////////////////////////////////////////////////////
730 /// Returns page position.
731 
732 TGPosition TGContainer::GetPagePosition() const
733 {
734  TGPosition ret;
735  if (!fViewPort) return ret;
736 
737  ret.fX = -fViewPort->GetHPos();
738  ret.fY = -fViewPort->GetVPos();
739 
740  return ret;
741 }
742 
743 ////////////////////////////////////////////////////////////////////////////////
744 /// Returns page dimension.
745 
746 TGDimension TGContainer::GetPageDimension() const
747 {
748  TGDimension ret;
749  if (!fViewPort) return ret;
750 
751  ret.fWidth = fViewPort->GetWidth();
752  ret.fHeight = fViewPort->GetHeight();
753  return ret;
754 }
755 
756 ////////////////////////////////////////////////////////////////////////////////
757 /// Set page position.
758 
759 void TGContainer::SetPagePosition(const TGPosition& pos)
760 {
761  if (!fViewPort) return;
762  fViewPort->SetPos(pos.fX, pos.fY);
763 }
764 
765 ////////////////////////////////////////////////////////////////////////////////
766 /// Set page position.
767 
768 void TGContainer::SetPagePosition(Int_t x, Int_t y)
769 {
770  if (!fViewPort) return;
771  fViewPort->SetPos(x, y);
772 }
773 
774 ////////////////////////////////////////////////////////////////////////////////
775 /// Set page dimension.
776 
777 void TGContainer::SetPageDimension(const TGDimension& dim)
778 {
779  if (!fViewPort) return;
780  fViewPort->Resize(dim);
781 }
782 
783 ////////////////////////////////////////////////////////////////////////////////
784 /// Set page dimension.
785 
786 void TGContainer::SetPageDimension(UInt_t w, UInt_t h)
787 {
788  if (!fViewPort) return;
789  fViewPort->Resize(w, h);
790 }
791 
792 ////////////////////////////////////////////////////////////////////////////////
793 /// Redraw content of container in the viewport region.
794 
795 void TGContainer::DoRedraw()
796 {
797 #ifdef R__HAS_COCOA
798  DrawRegion(0, 0, GetWidth(), GetHeight());
799 #else
800  if (!fExposedRegion.IsEmpty()) {
801  DrawRegion(fExposedRegion.fX, fExposedRegion.fY,
802  fExposedRegion.fW, fExposedRegion.fH);
803 
804  fExposedRegion.Empty();
805  }
806 #endif
807 }
808 
809 ////////////////////////////////////////////////////////////////////////////////
810 /// Draw a region of container in viewport.
811 /// x, y, w, h are position and dimension of area to be
812 /// redrawn in viewport coordinates.
813 
814 void TGContainer::DrawRegion(Int_t x, Int_t y, UInt_t w, UInt_t h)
815 {
816  static GContext_t gcBg = 0;
817  Pixmap_t pixmap = 0;
818 
819  if (!fViewPort) return;
820  // sanity checks
821  if ((x > (Int_t)fViewPort->GetWidth()) || (y > (Int_t)fViewPort->GetHeight())) {
822  return;
823  }
824  x = x < 0 ? 0 : x;
825  y = y < 0 ? 0 : y;
826 
827  w = x + w > fViewPort->GetWidth() ? fViewPort->GetWidth() - x : w;
828  h = y + h > fViewPort->GetHeight() ? fViewPort->GetHeight() - y : h;
829 
830  if (((Int_t)w < 1) || ((Int_t)h < 1)) {
831  return;
832  }
833 
834  if (!fMapSubwindows) {
835  pixmap = gVirtualX->CreatePixmap(fId, w, h);
836 
837  if (!gcBg) {
838  GCValues_t gcValues;
839  gcValues.fForeground = fBackground;
840  gcValues.fBackground = fBackground;
841  gcValues.fGraphicsExposures = kTRUE;
842  gcValues.fMask = kGCForeground | kGCBackground | kGCGraphicsExposures;
843  gcBg = gVirtualX->CreateGC(fId, &gcValues);
844  }
845 
846  gVirtualX->SetForeground(gcBg, fBackground);
847  gVirtualX->FillRectangle(pixmap, gcBg, 0, 0, w, h);
848  }
849 
850  TGPosition pos = GetPagePosition();
851 
852  // translate coordinates in viewport into coordinates in container
853  Int_t xx = pos.fX + x;
854  Int_t yy = pos.fY + y;
855 
856  TIter next(fList);
857  TGFrameElement *el;
858 
859  while ((el = (TGFrameElement *) next())) {
860  if ((Int_t(el->fFrame->GetY()) > yy - (Int_t)el->fFrame->GetHeight()) &&
861  (Int_t(el->fFrame->GetX()) > xx - (Int_t)el->fFrame->GetWidth()) &&
862  (Int_t(el->fFrame->GetY()) < yy + Int_t(h + el->fFrame->GetHeight())) &&
863  (Int_t(el->fFrame->GetX()) < xx + Int_t(w + el->fFrame->GetWidth()))) {
864 
865  // draw either in container window or in double-buffer
866  if (!fMapSubwindows) {
867  Int_t fx = el->fFrame->GetX() - xx;
868  Int_t fy = el->fFrame->GetY() - yy;
869  el->fFrame->DrawCopy(pixmap, fx, fy);
870  } else {
871  fClient->NeedRedraw(el->fFrame);
872  }
873  }
874  }
875 
876  if (fMapSubwindows) return;
877 
878  gVirtualX->CopyArea(pixmap, fId, gcBg, 0, 0, w, h, x, y);
879  gVirtualX->DeletePixmap(pixmap);
880  gVirtualX->Update(kFALSE);
881 }
882 
883 ////////////////////////////////////////////////////////////////////////////////
884 /// Clear view port and redraw full content
885 
886 void TGContainer::ClearViewPort()
887 {
888  if (!fViewPort) return;
889  fExposedRegion.fW = fViewPort->GetWidth();
890  fExposedRegion.fH = fViewPort->GetHeight();
891  fExposedRegion.fX = fExposedRegion.fY = 0;
892  fClient->NeedRedraw(this);
893 }
894 
895 ////////////////////////////////////////////////////////////////////////////////
896 /// Handle expose events. Do not use double buffer.
897 
898 Bool_t TGContainer::HandleExpose(Event_t *event)
899 {
900  if (fMapSubwindows) return TGCompositeFrame::HandleExpose(event);
901 
902  if (event->fWindow == GetId()) {
903  TGPosition pos(event->fX, event->fY);
904  TGDimension dim(event->fWidth, event->fHeight);
905  TGRectangle rect(pos, dim);
906 
907  if (fExposedRegion.IsEmpty()) {
908  fExposedRegion = rect;
909  } else {
910  fExposedRegion.Merge(rect);
911  }
912 
913  fClient->NeedRedraw(this);
914  } else {
915  TGCompositeFrame::HandleExpose(event);
916  }
917 
918  return kTRUE;
919 }
920 
921 ////////////////////////////////////////////////////////////////////////////////
922 /// Handle mouse button event in container.
923 
924 Bool_t TGContainer::HandleButton(Event_t *event)
925 {
926  Int_t total, selected, page = 0;
927 
928  TGPosition pos = GetPagePosition();
929  TGDimension dim = GetPageDimension();
930  Int_t newpos;
931  page = dim.fHeight/4;
932 
933  if (event->fCode == kButton4) {
934  //scroll up
935  newpos = pos.fY - page;
936  if (newpos < 0) newpos = 0;
937  fCanvas->SetVsbPosition(newpos);
938  return kTRUE;
939  }
940  if (event->fCode == kButton5) {
941  // scroll down
942  newpos = fCanvas->GetVsbPosition() + page;
943  fCanvas->SetVsbPosition(newpos);
944  return kTRUE;
945  }
946 
947  Int_t xx = pos.fX + event->fX; // translate coordinates
948  Int_t yy = pos.fY + event->fY;
949 
950  if (event->fType == kButtonPress) {
951  gVirtualX->SetInputFocus(fId);
952 
953  fXp = pos.fX + event->fX;
954  fYp = pos.fY + event->fY;
955 
956  fXDND = event->fX;
957  fYDND = event->fY;
958  fBdown = kTRUE;
959 
960  UnSelectAll();
961  total = selected = 0;
962 
963  TGFrameElement *el;
964  TIter next(fList);
965  Bool_t select_frame = kFALSE;
966 
967  while ((el = (TGFrameElement *) next())) {
968  select_frame = kFALSE;
969 
970  if (!fMapSubwindows) {
971  if ((Int_t(el->fFrame->GetY()) + (Int_t)el->fFrame->GetHeight() > yy ) &&
972  (Int_t(el->fFrame->GetX()) + (Int_t)el->fFrame->GetWidth() > xx ) &&
973  (Int_t(el->fFrame->GetY()) < yy) &&
974  (Int_t(el->fFrame->GetX()) < xx)) {
975  select_frame = kTRUE;
976  }
977  } else {
978  if (el->fFrame->GetId() == (Window_t)event->fUser[0]) {
979  select_frame = kTRUE;
980  }
981  }
982 
983  if (select_frame) {
984  selected++;
985  ActivateItem(el);
986  Clicked(el->fFrame, event->fCode);
987  Clicked(el->fFrame, event->fCode, event->fXRoot, event->fYRoot);
988  }
989  total++;
990  }
991 
992  if (fTotal != total || fSelected != selected) {
993  fTotal = total;
994  fSelected = selected;
995  SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_SELCHANGED),
996  fTotal, fSelected);
997  }
998 
999  if ( selected == 0 ) {
1000  fDragging = kTRUE;
1001  fX0 = fXf = fXp;
1002  fY0 = fYf = fYp;
1003  gVirtualX->DrawRectangle(fId, GetLineGC()(), fX0-pos.fX, fY0-pos.fY,
1004  fXf-fX0, fYf-fY0);
1005  }
1006  }
1007 
1008  if (event->fType == kButtonRelease) {
1009  gVirtualX->SetInputFocus(fId);
1010 
1011  fBdown = kFALSE;
1012  if (fDragging) {
1013  fDragging = kFALSE;
1014  fScrolling = kFALSE;
1015 
1016  if (gSystem) gSystem->RemoveTimer(fScrollTimer);
1017  gVirtualX->DrawRectangle(fId, GetLineGC()(), fX0-pos.fX, fY0-pos.fY,
1018  fXf-fX0, fYf-fY0);
1019  ClearViewPort();
1020 
1021  } else {
1022  SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_ITEMCLICK),
1023  event->fCode, (event->fYRoot << 16) | event->fXRoot);
1024  }
1025  }
1026  DoRedraw();
1027  return kTRUE;
1028 }
1029 
1030 ////////////////////////////////////////////////////////////////////////////////
1031 /// Retrieve icons associated with class "name". Association is made
1032 /// via the user's ~/.root.mimes file or via $ROOTSYS/etc/root.mimes.
1033 
1034 const TGPicture *TGContainer::GetObjPicture(TGFrame *f)
1035 {
1036  TObject *obj = 0;
1037  TClass *cl;
1038  const TGPicture *pic=0;
1039  const char *iconname = 0;
1040 
1041  if (f->InheritsFrom("TGLVEntry")) {
1042  obj = (TObject *)((TGLVEntry *)f)->GetUserData();
1043  if (obj) {
1044  if (obj->IsA() == TKey::Class()) {
1045  cl = TClass::GetClass(((TKey *)obj)->GetClassName());
1046  } else if (obj->IsA() == TKeyMapFile::Class()) {
1047  cl = TClass::GetClass(((TKeyMapFile *)obj)->GetTitle());
1048  } else {
1049  cl = obj->IsA();
1050  }
1051  const char *name = obj->GetIconName();
1052  if (((name == 0) || (!name[0])) && (cl != 0))
1053  name = cl->GetName();
1054  iconname = ((name != 0) && (strlen(name) > 0)) ? name : obj->GetName();
1055 
1056  if (obj->IsA()->InheritsFrom("TGeoVolume")) {
1057  iconname = obj->GetIconName() ? obj->GetIconName() : obj->IsA()->GetName();
1058  }
1059  pic = fClient->GetMimeTypeList()->GetIcon(iconname, kFALSE);
1060  }
1061  }
1062  if (pic == 0) {
1063  if (obj && obj->IsFolder()) {
1064  pic = fClient->GetPicture("folder_s.xpm");
1065  } else {
1066  pic = fClient->GetPicture("doc_s.xpm");
1067  }
1068  }
1069  return pic;
1070 }
1071 
1072 ////////////////////////////////////////////////////////////////////////////////
1073 /// Set drag window pixmaps and hotpoint.
1074 
1075 void TGContainer::SetDragPixmap(const TGPicture *p)
1076 {
1077  Pixmap_t pic, mask;
1078  TGPicture *selpic = new TGSelectedPicture(gClient, p);
1079  pic = selpic->GetPicture();
1080  mask = selpic->GetMask();
1081 
1082  if (gDNDManager) {
1083  gDNDManager->SetDragPixmap(pic, mask, p->GetWidth()/2, 2+p->GetHeight()/2);
1084  } else {
1085  gVirtualX->DeletePixmap(pic);
1086  gVirtualX->DeletePixmap(mask);
1087  }
1088 }
1089 
1090 ////////////////////////////////////////////////////////////////////////////////
1091 /// Handle double click mouse event.
1092 
1093 Bool_t TGContainer::HandleDoubleClick(Event_t *event)
1094 {
1095  TGFrameElement *el;
1096  TIter next(fList);
1097 
1098  TGPosition pos = GetPagePosition();
1099 
1100  Int_t xx = pos.fX + event->fX; // translate coordinates
1101  Int_t yy = pos.fY + event->fY;
1102 
1103  Bool_t select_frame = kFALSE;
1104 
1105  while ((el = (TGFrameElement *) next())) {
1106  select_frame = kFALSE;
1107 
1108  if (!fMapSubwindows) {
1109  if ((Int_t(el->fFrame->GetY()) + (Int_t)el->fFrame->GetHeight() > yy) &&
1110  (Int_t(el->fFrame->GetX()) + (Int_t)el->fFrame->GetWidth() > xx) &&
1111  (Int_t(el->fFrame->GetY()) < yy) &&
1112  (Int_t(el->fFrame->GetX()) < xx)) {
1113  select_frame = kTRUE;
1114  }
1115  } else {
1116  if (el->fFrame->GetId() == (Window_t)event->fUser[0]) {
1117  select_frame = kTRUE;
1118  }
1119  }
1120 
1121  if (select_frame) {
1122  SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_ITEMDBLCLICK),
1123  event->fCode, (event->fYRoot << 16) | event->fXRoot);
1124 
1125  DoubleClicked(el->fFrame, event->fCode);
1126  DoubleClicked(el->fFrame, event->fCode, event->fXRoot, event->fYRoot);
1127  return kTRUE;
1128  }
1129  }
1130  return kTRUE;
1131 }
1132 
1133 ////////////////////////////////////////////////////////////////////////////////
1134 /// Handle mouse motion events.
1135 
1136 Bool_t TGContainer::HandleMotion(Event_t *event)
1137 {
1138  int xf0, yf0, xff, yff, total, selected;
1139 
1140  TGPosition pos = GetPagePosition();
1141  TGDimension dim = GetPageDimension();
1142  Int_t x = pos.fX + event->fX;
1143  Int_t y = pos.fY + event->fY;
1144  TGFrameElement *el = 0;
1145  TGFrame *f = 0;
1146  fOnMouseOver = kFALSE;
1147 
1148  Bool_t wasScrolling = fScrolling;
1149 
1150  if (gDNDManager->IsDragging()) {
1151  gDNDManager->Drag(event->fXRoot, event->fYRoot,
1152  TGDNDManager::GetDNDActionCopy(), event->fTime);
1153  }
1154  else if (fDragging) {
1155 
1156  gVirtualX->DrawRectangle(fId, GetLineGC()(), fX0-pos.fX, fY0-pos.fY,
1157  fXf-fX0, fYf-fY0);
1158  fX0 = TMath::Min(fXp,x);
1159  fY0 = TMath::Min(fYp,y);
1160  fXf = TMath::Max(fXp,x);
1161  fYf = TMath::Max(fYp,y);
1162 
1163  total = selected = 0;
1164 
1165  if (event->fX > Int_t(dim.fWidth) - kAutoScrollFudge) {
1166  //fCanvas->SetHsbPosition(x - dim.fWidth);
1167  fScrolling = kTRUE;
1168  } else if (event->fX < kAutoScrollFudge) {
1169  //fCanvas->SetHsbPosition(x);
1170  fScrolling = kTRUE;
1171  } else if (event->fY > Int_t(dim.fHeight) - kAutoScrollFudge) {
1172  //fCanvas->SetVsbPosition(y - dim.fHeight);
1173  fScrolling = kTRUE;
1174  } else if (event->fY < kAutoScrollFudge) {
1175  //fCanvas->SetVsbPosition(y);
1176  fScrolling = kTRUE;
1177  }
1178  else {
1179  fScrolling = kFALSE;
1180  }
1181 
1182  TIter next(fList);
1183 
1184  while ((el = (TGFrameElement *) next())) {
1185  f = el->fFrame;
1186  ++total;
1187  xf0 = f->GetX() + (f->GetWidth() >> 3);
1188  yf0 = f->GetY() + (f->GetHeight() >> 3);
1189  xff = xf0 + f->GetWidth() - (f->GetWidth() >> 2);
1190  yff = yf0 + f->GetHeight() - (f->GetHeight() >> 2);
1191 
1192  if (((xf0 > fX0 && xf0 < fXf) ||
1193  (xff > fX0 && xff < fXf)) &&
1194  ((yf0 > fY0 && yf0 < fYf) ||
1195  (yff > fY0 && yff < fYf))) {
1196  if (!el->fFrame->IsActive())
1197  ActivateItem(el);
1198  gVirtualX->SetCursor(fId, gVirtualX->CreateCursor(kHand));
1199  OnMouseOver(f);
1200  ++selected;
1201  } else {
1202  if (el->fFrame->IsActive())
1203  DeActivateItem(el);
1204  }
1205  }
1206 
1207  if (fTotal != total || fSelected != selected) {
1208  fTotal = total;
1209  fSelected = selected;
1210  SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_SELCHANGED),
1211  fTotal, fSelected);
1212  }
1213  gVirtualX->DrawRectangle(fId, GetLineGC()(), fX0-pos.fX, fY0-pos.fY,
1214  fXf-fX0, fYf-fY0);
1215  }
1216  else {
1217  TGFrame *over_frame = 0;
1218 
1219  TIter next(fList);
1220 
1221  while ((el = (TGFrameElement *) next())) {
1222  if (!fMapSubwindows) {
1223  if ((Int_t(el->fFrame->GetY()) + (Int_t)el->fFrame->GetHeight() > y) &&
1224  (Int_t(el->fFrame->GetX()) + (Int_t)el->fFrame->GetWidth() > x) &&
1225  (Int_t(el->fFrame->GetY()) < y) &&
1226  (Int_t(el->fFrame->GetX()) < x)) {
1227  over_frame = el->fFrame;
1228  break;
1229  }
1230  } else {
1231  if (el->fFrame->GetId() == (Window_t)event->fUser[0]) {
1232  over_frame = el->fFrame;
1233  break;
1234  }
1235  }
1236  }
1237  if (over_frame) {
1238  if (!gDNDManager->IsDragging()) {
1239  if (fBdown && ((abs(event->fX - fXDND) > 2) || (abs(event->fY - fYDND) > 2))) {
1240  if (gDNDManager && over_frame->IsDNDSource()) {
1241  const TGPicture *drag_pic = GetObjPicture(over_frame);
1242  if (drag_pic) SetDragPixmap(drag_pic);
1243  gDNDManager->StartDrag(over_frame, event->fXRoot, event->fYRoot);
1244  }
1245  }
1246  }
1247  if (gDNDManager->IsDragging()) {
1248  gDNDManager->Drag(event->fXRoot, event->fYRoot,
1249  TGDNDManager::GetDNDActionCopy(), event->fTime);
1250  } else {
1251  OnMouseOver(over_frame);
1252  gVirtualX->SetCursor(fId, gVirtualX->CreateCursor(kHand));
1253  }
1254  } else {
1255  gVirtualX->SetCursor(fId, gVirtualX->CreateCursor(kPointer));
1256  }
1257  }
1258 
1259  if (!wasScrolling && fScrolling) {
1260  if (gSystem) {
1261  fScrollTimer->Reset();
1262  gSystem->AddTimer(fScrollTimer);
1263  }
1264  }
1265 
1266  return kTRUE;
1267 }
1268 
1269 ////////////////////////////////////////////////////////////////////////////////
1270 /// The key press event handler converts a key press to some line editor
1271 /// action.
1272 
1273 Bool_t TGContainer::HandleKey(Event_t *event)
1274 {
1275  char input[10];
1276  Int_t n;
1277  UInt_t keysym;
1278 
1279  if (event->fType == kGKeyPress) {
1280  gVirtualX->LookupString(event, input, sizeof(input), keysym);
1281  n = strlen(input);
1282 
1283  KeyPressed(fLastActiveEl?fLastActiveEl->fFrame:0, keysym, event->fState);
1284 
1285  switch ((EKeySym)keysym) {
1286  case kKey_Enter:
1287  case kKey_Return:
1288  // treat 'Enter' and 'Return' as a double click
1289  SendMessage(GetMessageWindow(), MK_MSG(kC_CONTAINER, kCT_ITEMDBLCLICK),
1290  kButton1, (event->fYRoot << 16) | event->fXRoot);
1291  if (fLastActiveEl) ReturnPressed(fLastActiveEl->fFrame);
1292  break;
1293  case kKey_Shift:
1294  case kKey_Control:
1295  case kKey_Meta:
1296  case kKey_Alt:
1297  case kKey_CapsLock:
1298  case kKey_NumLock:
1299  case kKey_ScrollLock:
1300  return kTRUE;
1301  case kKey_Space:
1302  if (fLastActiveEl) {
1303  fLastActiveEl->fFrame->Activate(!fLastActiveEl->fFrame->IsActive());
1304  SpacePressed(fLastActiveEl->fFrame);
1305  }
1306  break;
1307  default:
1308  break;
1309  }
1310 
1311  if (event->fState & kKeyControlMask) { // Cntrl key modifier pressed
1312  switch((EKeySym)keysym & ~0x20) { // treat upper and lower the same
1313  case kKey_A:
1314  SelectAll();
1315  break;
1316  case kKey_B:
1317  LineLeft();
1318  break;
1319  case kKey_C:
1320  return kTRUE;
1321  case kKey_D:
1322  break;
1323  case kKey_E:
1324  End();
1325  break;
1326  case kKey_F:
1327  Search();
1328  break;
1329  case kKey_G:
1330  RepeatSearch();
1331  break;
1332  case kKey_H:
1333  LineLeft();
1334  break;
1335  case kKey_K:
1336  End();
1337  break;
1338  case kKey_U:
1339  Home();
1340  break;
1341  case kKey_V:
1342  case kKey_Y:
1343  return kTRUE;
1344  case kKey_X:
1345  return kTRUE;
1346  default:
1347  return kTRUE;
1348  }
1349  }
1350  if (n && keysym >= 32 && keysym < 127 && // printable keys
1351  !(event->fState & kKeyControlMask) &&
1352  (EKeySym)keysym != kKey_Delete &&
1353  (EKeySym)keysym != kKey_Backspace) {
1354 
1355  if (fKeyTimerActive) {
1356  fKeyInput += input;
1357  } else {
1358  fKeyInput = input;
1359  fKeyTimerActive = kTRUE;
1360  fKeyTimer->Reset();
1361  if (gSystem) gSystem->AddTimer(fKeyTimer);
1362  }
1363  } else {
1364 
1365  switch ((EKeySym)keysym) {
1366  case kKey_F3:
1367  RepeatSearch();
1368  break;
1369  case kKey_F5:
1370  Layout();
1371  break;
1372  case kKey_F7:
1373  Search();
1374  break;
1375  case kKey_Left:
1376  LineLeft(event->fState & kKeyShiftMask);
1377  break;
1378  case kKey_Right:
1379  LineRight(event->fState & kKeyShiftMask);
1380  break;
1381  case kKey_Up:
1382  LineUp(event->fState & kKeyShiftMask);
1383  break;
1384  case kKey_Down:
1385  LineDown(event->fState & kKeyShiftMask);
1386  break;
1387  case kKey_PageUp:
1388  PageUp(event->fState & kKeyShiftMask);
1389  break;
1390  case kKey_PageDown:
1391  PageDown(event->fState & kKeyShiftMask);
1392  break;
1393  case kKey_Home:
1394  Home(event->fState & kKeyShiftMask);
1395  break;
1396  case kKey_End:
1397  End(event->fState & kKeyShiftMask);
1398  break;
1399  default:
1400  break;
1401  }
1402  }
1403  }
1404  DoRedraw();
1405  return kTRUE;
1406 }
1407 
1408 ////////////////////////////////////////////////////////////////////////////////
1409 /// Find frame by name.
1410 
1411 TGFrame *TGContainer::FindFrameByName(const char *name)
1412 {
1413  if (!IsMapped()) return 0;
1414 
1415  Bool_t direction = kTRUE;
1416  Bool_t caseSensitive = kFALSE;
1417  Bool_t subString = kFALSE;
1418 
1419  if (gTQSender && (gTQSender == TGSearchDialog::SearchDialog())) {
1420  caseSensitive = TGSearchDialog::SearchDialog()->GetType()->fCaseSensitive;
1421  direction = TGSearchDialog::SearchDialog()->GetType()->fDirection;
1422  }
1423  TString sname(name);
1424  if (sname.Contains("*")) {
1425  subString = kTRUE;
1426  sname.ReplaceAll("*", "");
1427  }
1428 
1429  TGFrameElement *fe = (TGFrameElement*)FindItem(sname.Data(), direction,
1430  caseSensitive, subString);
1431  if (!fe) { // find again
1432  if (fLastActiveEl) DeActivateItem(fLastActiveEl);
1433  fLastActiveEl = 0;
1434  fe = (TGFrameElement*)FindItem(fLastName, fLastDir, fLastCase, fLastSubstring);
1435 
1436  if (!fe) {
1437  if (gTQSender && (gTQSender == TGSearchDialog::SearchDialog())) {
1438  TString msg = "Couldn't find \"" + fLastName + '\"';
1439  gVirtualX->Bell(20);
1440  new TGMsgBox(fClient->GetDefaultRoot(), fCanvas, "Container", msg.Data(),
1441  kMBIconExclamation, kMBOk, 0);
1442  }
1443  return 0;
1444  } else {
1445  if (fLastActiveEl) DeActivateItem(fLastActiveEl);
1446  ActivateItem(fe);
1447  AdjustPosition();
1448  return fe->fFrame;
1449  }
1450  } else {
1451  if (fLastActiveEl) DeActivateItem(fLastActiveEl);
1452  ActivateItem(fe);
1453  AdjustPosition();
1454  return fe->fFrame;
1455  }
1456  return 0;
1457 }
1458 
1459 ////////////////////////////////////////////////////////////////////////////////
1460 /// Invokes search dialog. Looks for item with the entered name.
1461 
1462 void TGContainer::Search(Bool_t close)
1463 {
1464  static TGSearchType *srch = 0;
1465  Int_t ret = 0;
1466 
1467  if (!srch) srch = new TGSearchType;
1468  srch->fClose = close;
1469  srch->fBuffer = 0;
1470 
1471  if (!close) {
1472  if (!TGSearchDialog::SearchDialog()) {
1473  TGSearchDialog::SearchDialog() = new TGSearchDialog(fClient->GetDefaultRoot(),
1474  fCanvas, 400, 150, srch, &ret);
1475  }
1476  TGSearchDialog::SearchDialog()->Connect("TextEntered(char *)", "TGContainer", this,
1477  "FindFrameByName(char *)");
1478  TGSearchDialog::SearchDialog()->MapRaised();
1479  } else {
1480  new TGSearchDialog(fClient->GetDefaultRoot(), fCanvas, 400, 150, srch, &ret);
1481  if (ret) {
1482  FindFrameByName(srch->fBuffer);
1483  }
1484  }
1485 }
1486 
1487 ////////////////////////////////////////////////////////////////////////////////
1488 /// Autoscroll while close to & beyond The Wall
1489 
1490 void TGContainer::OnAutoScroll()
1491 {
1492  TGFrameElement *el = 0;
1493  TGFrame *f = 0;
1494  int xf0, yf0, xff, yff, total, selected;
1495 
1496  TGDimension dim = GetPageDimension();
1497  TGPosition pos = GetPagePosition();
1498 
1499  Window_t dum1, dum2;
1500  Event_t ev;
1501  ev.fType = kButtonPress;
1502  Int_t x,y;
1503 
1504  // Autoscroll while close to the wall
1505  Int_t dx = 0;
1506  Int_t dy = 0;
1507 
1508  // Where's the cursor?
1509  gVirtualX->QueryPointer(fId,dum1,dum2,ev.fXRoot,ev.fYRoot,x,y,ev.fState);
1510 
1511  // Figure scroll amount x
1512  if (x < kAutoScrollFudge)
1513  dx = kAutoScrollFudge - x;
1514  else if ((Int_t)dim.fWidth-kAutoScrollFudge <= x)
1515  dx = dim.fWidth - kAutoScrollFudge - x;
1516 
1517  // Figure scroll amount y
1518  if (y < kAutoScrollFudge)
1519  dy = kAutoScrollFudge - y;
1520  else if ((Int_t)dim.fHeight - kAutoScrollFudge <= y)
1521  dy = dim.fHeight - kAutoScrollFudge - y;
1522 
1523  if (dx || dy) {
1524  if (dx) dx /= 5;
1525  if (dy) dy /= 5;
1526  Int_t adx = TMath::Abs(dx);
1527  Int_t ady = TMath::Abs(dy);
1528  if (adx > kAutoScrollFudge) adx = kAutoScrollFudge;
1529  if (ady > kAutoScrollFudge) ady = kAutoScrollFudge;
1530 
1531  dx *= kAcceleration[adx];
1532  dy *= kAcceleration[ady];
1533 
1534  Int_t nx = pos.fX-dx;
1535  Int_t ny = pos.fY-dy;
1536 
1537  fCanvas->SetHsbPosition(nx);
1538  fCanvas->SetVsbPosition(ny);
1539 
1540  // position inside container
1541  x += pos.fX;
1542  y += pos.fY;
1543 
1544  fX0 = TMath::Min(fXp, x);
1545  fY0 = TMath::Min(fYp, y);
1546  fXf = TMath::Max(fXp, x);
1547  fYf = TMath::Max(fYp ,y);
1548 
1549  total = selected = 0;
1550 
1551  TIter next(fList);
1552 
1553  while ((el = (TGFrameElement *) next())) {
1554  f = el->fFrame;
1555  ++total;
1556  xf0 = f->GetX() + (f->GetWidth() >> 3);
1557  yf0 = f->GetY() + (f->GetHeight() >> 3);
1558  xff = xf0 + f->GetWidth() - (f->GetWidth() >> 2);
1559  yff = yf0 + f->GetHeight() - (f->GetHeight() >> 2);
1560 
1561  if (((xf0 > fX0 && xf0 < fXf) ||
1562  (xff > fX0 && xff < fXf)) &&
1563  ((yf0 > fY0 && yf0 < fYf) ||
1564  (yff > fY0 && yff < fYf))) {
1565  if (!el->fFrame->IsActive())
1566  ActivateItem(el);
1567  ++selected;
1568  } else {
1569  if (el->fFrame->IsActive())
1570  DeActivateItem(el);
1571  }
1572  }
1573  gVirtualX->DrawRectangle(fId, GetLineGC()(), fX0-pos.fX, fY0-pos.fY,
1574  fXf-fX0, fYf-fY0);
1575 
1576  if (fTotal != total || fSelected != selected) {
1577  fTotal = total;
1578  fSelected = selected;
1579  SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_SELCHANGED),
1580  fTotal, fSelected);
1581  }
1582  ClearViewPort();
1583  DoRedraw();
1584  gVirtualX->DrawRectangle(fId, GetLineGC()(), fX0-pos.fX, fY0-pos.fY,
1585  fXf-fX0, fYf-fY0);
1586  }
1587 }
1588 
1589 ////////////////////////////////////////////////////////////////////////////////
1590 /// Search for entry which name begins with pattern.
1591 
1592 void TGContainer::SearchPattern()
1593 {
1594  TGFrameElement *fe = 0;
1595  TIter next(fList);
1596  TString str;
1597 
1598  while ((fe=( TGFrameElement*)next())) {
1599  str = fe->fFrame->GetTitle();
1600 
1601  if (str.BeginsWith(fKeyInput,TString::kIgnoreCase)) {
1602  if (fLastActiveEl && (fLastActiveEl!=fe) ) {
1603  fLastActiveEl->fFrame->Activate(kFALSE);
1604  }
1605  ActivateItem(fe);
1606  AdjustPosition();
1607  break;
1608  }
1609  }
1610 
1611  fKeyInput = ""; //clear
1612  fKeyTimerActive = kFALSE;
1613 }
1614 
1615 ////////////////////////////////////////////////////////////////////////////////
1616 /// Repeats search.
1617 
1618 void TGContainer::RepeatSearch()
1619 {
1620  TGFrameElement *fe = 0;
1621 
1622  if (fLastName == "")
1623  return Search();
1624 
1625  fe = (TGFrameElement*)FindItem(fLastName, fLastDir, fLastCase, fLastSubstring);
1626 
1627  if (!fe) {
1628  if (fLastActiveEl) DeActivateItem(fLastActiveEl);
1629  fLastActiveEl = 0;
1630  fe = (TGFrameElement*)FindItem(fLastName, fLastDir, fLastCase, fLastSubstring);
1631 
1632  if (!fe) {
1633  TString msg = "Couldn't find \"" + fLastName + '\"';
1634  gVirtualX->Bell(50);
1635  new TGMsgBox(fClient->GetDefaultRoot(), fCanvas, "Container", msg.Data(),
1636  kMBIconExclamation, kMBOk, 0);
1637  } else {
1638  if (fLastActiveEl) DeActivateItem(fLastActiveEl);
1639  ActivateItem(fe);
1640  AdjustPosition();
1641  }
1642  } else {
1643  if (fLastActiveEl) DeActivateItem(fLastActiveEl);
1644  ActivateItem(fe);
1645  AdjustPosition();
1646  }
1647 }
1648 
1649 ////////////////////////////////////////////////////////////////////////////////
1650 /// Find frame located int container at position x,y.
1651 
1652 TGFrameElement *TGContainer::FindFrame(Int_t x, Int_t y, Bool_t exclude)
1653 {
1654  TIter next(fList);
1655  TGFrameElement *el;
1656  TGFrameElement *ret = 0;
1657  Int_t dx = 0;
1658  Int_t dy = 0;
1659  Int_t d = 0;
1660  Int_t dd;
1661 
1662  el = (TGFrameElement *) next();
1663  if (!el) return 0;
1664 
1665  dx = TMath::Abs(el->fFrame->GetX()-x);
1666  dy = TMath::Abs(el->fFrame->GetY()-y);
1667  d = dx + dy;
1668 
1669  while ((el = (TGFrameElement *) next())) {
1670  if (exclude && (el==fLastActiveEl) ) continue;
1671  dx = TMath::Abs(el->fFrame->GetX()-x);
1672  dy = TMath::Abs(el->fFrame->GetY()-y);
1673  dd = dx+dy;
1674 
1675  if (dd<d) {
1676  d = dd;
1677  ret = el;
1678  }
1679  }
1680  return ret;
1681 }
1682 
1683 ////////////////////////////////////////////////////////////////////////////////
1684 
1685 void *TGContainer::FindItem(const TString& name, Bool_t direction,
1686  Bool_t caseSensitive, Bool_t subString)
1687 {
1688  // Find a frame which assosiated object has a name containing a "name"
1689  // string.
1690 
1691  if (name.IsNull()) return 0;
1692  int idx = kNPOS;
1693 
1694  TGFrameElement *el = 0;
1695  TString str;
1696  TString::ECaseCompare cmp = caseSensitive ? TString::kExact : TString::kIgnoreCase;
1697 
1698  fLastDir = direction;
1699  fLastCase = caseSensitive;
1700  fLastName = name;
1701  fLastSubstring = subString;
1702 
1703  if (fLastActiveEl) {
1704  el = fLastActiveEl;
1705 
1706  if (direction) {
1707  el = (TGFrameElement *)fList->After(el);
1708  } else {
1709  el = (TGFrameElement *)fList->Before(el);
1710  }
1711  } else {
1712  if (direction) el = (TGFrameElement *)fList->First();
1713  else el = (TGFrameElement *)fList->Last();
1714  }
1715 
1716  while (el) {
1717  str = el->fFrame->GetTitle();
1718  idx = str.Index(name, 0, cmp);
1719 
1720  if (idx != kNPOS) {
1721  if (subString) {
1722  return el;
1723  } else {
1724  if (str.Length() == name.Length()) return el;
1725  }
1726  }
1727 
1728  if (direction) {
1729  el = (TGFrameElement *)fList->After(el);
1730  } else {
1731  el = (TGFrameElement *)fList->Before(el);
1732  }
1733  }
1734  return 0;
1735 }
1736 
1737 ////////////////////////////////////////////////////////////////////////////////
1738 /// returns pointer to hor. scroll bar
1739 
1740 TGHScrollBar *TGContainer::GetHScrollbar() const
1741 {
1742  return fCanvas ? fCanvas->GetHScrollbar() : 0;
1743 }
1744 
1745 ////////////////////////////////////////////////////////////////////////////////
1746 /// returns pointer to vert. scroll bar
1747 
1748 TGVScrollBar *TGContainer::GetVScrollbar() const
1749 {
1750  return fCanvas ? fCanvas->GetVScrollbar() : 0;
1751 }
1752 
1753 ////////////////////////////////////////////////////////////////////////////////
1754 /// Set position of vertical scrollbar.
1755 
1756 void TGContainer::SetVsbPosition(Int_t newPos)
1757 {
1758  if (!fViewPort) return;
1759  TGVScrollBar *vb = GetVScrollbar();
1760 
1761  if (vb && vb->IsMapped()) {
1762  vb->SetRange((Int_t)GetHeight(), (Int_t)fViewPort->GetHeight());
1763  vb->SetPosition(newPos);
1764  } else {
1765  fViewPort->SetVPos(0);
1766  }
1767 }
1768 
1769 ////////////////////////////////////////////////////////////////////////////////
1770 /// set new hor. position
1771 
1772 void TGContainer::SetHsbPosition(Int_t newPos)
1773 {
1774  if (!fViewPort) return;
1775  TGHScrollBar *hb = GetHScrollbar();
1776 
1777  if (hb && hb->IsMapped()) {
1778  hb->SetRange((Int_t)GetWidth(), (Int_t)fViewPort->GetWidth());
1779  hb->SetPosition(newPos);
1780  } else {
1781  fViewPort->SetHPos(0);
1782  }
1783 }
1784 
1785 ////////////////////////////////////////////////////////////////////////////////
1786 /// Move content to position of highlighted/activated frame.
1787 
1788 void TGContainer::AdjustPosition()
1789 {
1790  if (!fViewPort) return;
1791  if (!fLastActiveEl) return;
1792  TGFrame *f = fLastActiveEl->fFrame;
1793 
1794  Int_t vh = 0;
1795  Int_t v = 0;
1796 
1797  TGHScrollBar *hb = GetHScrollbar();
1798  TGVScrollBar *vb = GetVScrollbar();
1799  Int_t pos = GetPagePosition().fY;
1800  Int_t pg;
1801 
1802 
1803  if (vb && vb->IsMapped()) {
1804  pg = (vb->GetPageSize()*GetHeight())/fViewPort->GetHeight();
1805  vh = pos + (Int_t)fViewPort->GetHeight();
1806 
1807  if (f->GetY() < pos) {
1808  v = TMath::Max(0, f->GetY() - (Int_t)fViewPort->GetHeight()/2);
1809  v = (v*pg)/GetHeight();
1810 
1811  SetVsbPosition(v);
1812  } else if (f->GetY() + (Int_t)f->GetHeight() > vh) {
1813  v = TMath::Min((Int_t)GetHeight() - (Int_t)fViewPort->GetHeight(),
1814  f->GetY() + (Int_t)f->GetHeight() - (Int_t)fViewPort->GetHeight()/2);
1815  v = (v*pg)/GetHeight();
1816  SetVsbPosition(v);
1817  }
1818  }
1819 
1820  Int_t hw = 0;
1821  Int_t h = 0;
1822 
1823  if (hb && hb->IsMapped() && (!vb || (vb && !vb->IsMapped()))) {
1824  pg = (hb->GetPageSize()*GetWidth())/fViewPort->GetWidth();
1825  pos =GetPagePosition().fX;
1826  hw = pos + (Int_t)fViewPort->GetWidth();
1827 
1828  if (f->GetX() < pos) {
1829  h = TMath::Max(0, f->GetX() - (Int_t)fViewPort->GetWidth()/2);
1830  h = (h*pg)/GetWidth();
1831 
1832  SetHsbPosition(h);
1833  } else if (f->GetX() + (Int_t)f->GetWidth() > hw) {
1834  h = TMath::Min((Int_t)GetWidth() - (Int_t)fViewPort->GetWidth(),
1835  f->GetX() + (Int_t)f->GetWidth() - (Int_t)fViewPort->GetWidth()/2);
1836  h = (h*pg)/GetWidth();
1837 
1838  SetHsbPosition(h);
1839  }
1840  }
1841 }
1842 
1843 ////////////////////////////////////////////////////////////////////////////////
1844 /// Move current position one column left.
1845 
1846 void TGContainer::LineLeft(Bool_t select)
1847 {
1848  TGPosition pos = GetPagePosition();
1849  TGDimension dim = GetPageDimension();
1850 
1851  TGFrameElement *fe = (TGFrameElement*)fList->First();
1852  if (!fe) return; // empty list
1853 
1854  TGFrameElement *old = fLastActiveEl;
1855 
1856  if (old) DeActivateItem(old); //
1857  else fLastActiveEl = fe;
1858 
1859  TGFrameElement *la = fLastActiveEl;
1860  Int_t dx = la->fLayout->GetPadLeft() + la->fLayout->GetPadRight();
1861  Int_t dy = la->fLayout->GetPadTop() + la->fLayout->GetPadBottom();
1862  Int_t y = la->fFrame->GetY();
1863  Int_t x = la->fFrame->GetX() - dx;
1864 
1865  Int_t hw = pos.fX + dim.fWidth;
1866 
1867  TGHScrollBar *hb = GetHScrollbar();
1868  if (x<=0 && (hb && !hb->IsMapped())) { // move to previous line
1869  x = hw;
1870  y = y - la->fFrame->GetDefaultHeight() - dy;
1871  }
1872 
1873  fe = FindFrame(x, y);
1874  if (!fe) fe = (TGFrameElement*)fList->First();
1875 
1876  if (!select) fSelected=1;
1877 
1878  ActivateItem(fe);
1879  AdjustPosition();
1880 }
1881 
1882 ////////////////////////////////////////////////////////////////////////////////
1883 /// Move current position one column right.
1884 
1885 void TGContainer::LineRight(Bool_t select)
1886 {
1887  TGPosition pos = GetPagePosition();
1888  TGDimension dim = GetPageDimension();
1889 
1890  TGFrameElement *fe = (TGFrameElement*)fList->Last();
1891  if (!fe) return;
1892 
1893  TGFrameElement *old = fLastActiveEl;
1894 
1895  if (old) DeActivateItem(old);
1896  else fLastActiveEl = (TGFrameElement*)fList->First();
1897 
1898  Int_t dx = fLastActiveEl->fLayout->GetPadLeft() + fLastActiveEl->fLayout->GetPadRight();
1899  Int_t dy = fLastActiveEl->fLayout->GetPadTop() + fLastActiveEl->fLayout->GetPadBottom();
1900  Int_t y = fLastActiveEl->fFrame->GetY();
1901  Int_t x = fLastActiveEl->fFrame->GetX() + fLastActiveEl->fFrame->GetDefaultWidth() + dx;
1902 
1903  Int_t hw = pos.fX + dim.fWidth - dx;
1904 
1905  TGHScrollBar *hb = GetHScrollbar();
1906  if (x >= hw && (hb && !hb->IsMapped())) { // move one line down
1907  x = 0;
1908  y = y + fLastActiveEl->fFrame->GetDefaultHeight() + dy;
1909  }
1910 
1911  fe = FindFrame(x, y);
1912  if (!fe) fe = (TGFrameElement*)fList->Last();
1913  if (!select) fSelected = 1;
1914 
1915  ActivateItem(fe);
1916  AdjustPosition();
1917 }
1918 
1919 ////////////////////////////////////////////////////////////////////////////////
1920 /// Make current position first line in window by scrolling up.
1921 
1922 void TGContainer::LineUp(Bool_t select)
1923 {
1924  TGFrameElement *fe = (TGFrameElement*)fList->First();
1925  if (!fe) return;
1926 
1927  TGFrameElement *old = fLastActiveEl;
1928 
1929  if (old) {
1930  DeActivateItem(old);
1931  } else {
1932  fLastActiveEl = (TGFrameElement*)fList->First();
1933  }
1934 
1935  Int_t dy = fLastActiveEl->fLayout->GetPadTop() + fLastActiveEl->fLayout->GetPadBottom();
1936  Int_t y = fLastActiveEl->fFrame->GetY() - dy;
1937  Int_t x = fLastActiveEl->fFrame->GetX();
1938 
1939  fe = FindFrame(x, y);
1940  if (!fe) fe = (TGFrameElement*)fList->First();
1941  if (fe->fFrame->GetY() > fLastActiveEl->fFrame->GetY()) fe = fLastActiveEl;
1942  if (!select) fSelected = 1;
1943 
1944  ActivateItem(fe);
1945  AdjustPosition();
1946 }
1947 
1948 ////////////////////////////////////////////////////////////////////////////////
1949 /// Move one line down.
1950 
1951 void TGContainer::LineDown(Bool_t select)
1952 {
1953  TGFrameElement *fe = (TGFrameElement*)fList->Last();
1954  if (!fe) return;
1955 
1956  TGFrameElement* old = fLastActiveEl;
1957 
1958  if (old) DeActivateItem(old);
1959  else fLastActiveEl = (TGFrameElement*)fList->First();
1960 
1961  Int_t dy = fLastActiveEl->fLayout->GetPadTop() + fLastActiveEl->fLayout->GetPadBottom();
1962  Int_t y = fLastActiveEl->fFrame->GetY() +
1963  fLastActiveEl->fFrame->GetHeight() + dy;
1964  Int_t x = fLastActiveEl->fFrame->GetX();
1965 
1966  fe = FindFrame(x, y);
1967  if (!fe) fe = (TGFrameElement*)fList->Last();
1968  if (fe->fFrame->GetY() < fLastActiveEl->fFrame->GetY()) fe = fLastActiveEl;
1969  if (!select) fSelected = 1;
1970 
1971  ActivateItem(fe);
1972  AdjustPosition();
1973 }
1974 
1975 ////////////////////////////////////////////////////////////////////////////////
1976 /// Move position one page up.
1977 
1978 void TGContainer::PageUp(Bool_t select)
1979 {
1980  TGDimension dim = GetPageDimension();
1981 
1982  TGFrameElement *fe = (TGFrameElement*)fList->First();
1983  if (!fe) return;
1984 
1985  TGFrameElement* old = fLastActiveEl;
1986 
1987  if (old) DeActivateItem(old);
1988  else fLastActiveEl = (TGFrameElement*)fList->First();
1989 
1990  Int_t y = fLastActiveEl->fFrame->GetY();
1991  Int_t x = fLastActiveEl->fFrame->GetX();
1992 
1993  TGVScrollBar *vb = GetVScrollbar();
1994  TGHScrollBar *hb = GetHScrollbar();
1995 
1996  if (vb && vb->IsMapped()) {
1997  y -= dim.fHeight;
1998  } else {
1999  if (hb && hb->IsMapped()) {
2000  x -= dim.fWidth;
2001  } else {
2002  Home();
2003  return;
2004  }
2005  }
2006 
2007  fe = FindFrame(x, y);
2008 
2009  if (!fe || fe->fFrame->GetY()>fLastActiveEl->fFrame->GetY()) {
2010  fe = (TGFrameElement*)fList->First();
2011  }
2012 
2013  if (!select) fSelected = 1;
2014 
2015  ActivateItem(fe);
2016  AdjustPosition();
2017 }
2018 
2019 ////////////////////////////////////////////////////////////////////////////////
2020 /// Move position one page down.
2021 
2022 void TGContainer::PageDown(Bool_t select)
2023 {
2024  TGDimension dim = GetPageDimension();
2025 
2026  TList *li = GetList();
2027  TGFrameElement *fe = (TGFrameElement*)fList->Last();
2028  if (!fe) return;
2029 
2030  TGFrameElement *old = fLastActiveEl;
2031 
2032  if (old) DeActivateItem(old);
2033  else fLastActiveEl = (TGFrameElement*)fList->First();
2034 
2035  Int_t y = fLastActiveEl->fFrame->GetY();
2036  Int_t x = fLastActiveEl->fFrame->GetX();
2037 
2038  TGVScrollBar *vb = GetVScrollbar();
2039  TGHScrollBar *hb = GetHScrollbar();
2040 
2041  if (vb && vb->IsMapped()) {
2042  y += dim.fHeight;
2043  } else {
2044  if (hb && hb->IsMapped()) {
2045  x += dim.fWidth;
2046  } else {
2047  End();
2048  return;
2049  }
2050  }
2051 
2052  fe = FindFrame(x, y);
2053  if (!fe || fe->fFrame->GetY()<fLastActiveEl->fFrame->GetY() ) {
2054  fe = (TGFrameElement*)li->Last();
2055  }
2056 
2057  if (!select) fSelected = 1;
2058 
2059  ActivateItem(fe);
2060  AdjustPosition();
2061 }
2062 
2063 ////////////////////////////////////////////////////////////////////////////////
2064 /// Move to upper-left corner of container.
2065 
2066 void TGContainer::Home(Bool_t select)
2067 {
2068  TGFrameElement *fe = (TGFrameElement*)fList->First();
2069  if (!fe) return;
2070 
2071  TGFrameElement *old = fLastActiveEl;
2072  if (old) DeActivateItem(old);
2073 
2074  if (!select) fSelected = 1;
2075 
2076  ActivateItem(fe);
2077  AdjustPosition();
2078 }
2079 
2080 ////////////////////////////////////////////////////////////////////////////////
2081 /// Move to the bottom-right corner of container.
2082 
2083 void TGContainer::End(Bool_t select)
2084 {
2085  TGFrameElement *fe = (TGFrameElement*)fList->Last();
2086  if (!fe) return;
2087 
2088  TGFrameElement *old = fLastActiveEl;
2089  if (old) DeActivateItem(old);
2090 
2091  if (!select) fSelected = 1;
2092 
2093  ActivateItem(fe);
2094  AdjustPosition();
2095 }
2096 
2097 ////////////////////////////////////////////////////////////////////////////////
2098 /// Get graphics context for line drawing.
2099 
2100 const TGGC &TGContainer::GetLineGC()
2101 {
2102  if (!fgLineGC) {
2103  GCValues_t gval;
2104  gval.fMask = kGCForeground | kGCBackground | kGCFunction | kGCFillStyle |
2105  kGCLineWidth | kGCLineStyle | kGCSubwindowMode |
2106  kGCGraphicsExposures;
2107  gval.fForeground = fgWhitePixel ^ fgBlackPixel;
2108  gval.fBackground = fgWhitePixel;
2109  gval.fFunction = kGXxor;
2110  gval.fLineWidth = 0;
2111  gval.fLineStyle = kLineOnOffDash;
2112  gval.fFillStyle = kFillSolid;
2113  gval.fSubwindowMode = kIncludeInferiors;
2114  gval.fGraphicsExposures = kFALSE;
2115  fgLineGC = gClient->GetGC(&gval, kTRUE);
2116  fgLineGC->SetDashOffset(0);
2117  fgLineGC->SetDashList("\x1\x1", 2);
2118  }
2119  return *fgLineGC;
2120 }
2121 
2122 ////////////////////////////////////////////////////////////////////////////////
2123 /// Create a canvas object.
2124 
2125 TGCanvas::TGCanvas(const TGWindow *p, UInt_t w, UInt_t h,
2126  UInt_t options, ULong_t back) :
2127  TGFrame(p, w, h, options, back)
2128 {
2129  fVport = new TGViewPort(this, w-4, h-4, kChildFrame | kOwnBackground,
2130  fgWhitePixel);
2131  fHScrollbar = new TGHScrollBar(this, w-4, kDefaultScrollBarWidth);
2132  fVScrollbar = new TGVScrollBar(this, kDefaultScrollBarWidth, h-4);
2133 
2134  fScrolling = kCanvasScrollBoth;
2135 
2136  fHScrollbar->Associate(this);
2137  fVScrollbar->Associate(this);
2138 
2139  fVport->Move(fBorderWidth, fBorderWidth);
2140 
2141  SetWindowName();
2142 
2143  fVScrollbar->SetEditDisabled(kEditDisable | kEditDisableGrab | kEditDisableBtnEnable);
2144  fHScrollbar->SetEditDisabled(kEditDisable | kEditDisableGrab | kEditDisableBtnEnable);
2145 }
2146 
2147 ////////////////////////////////////////////////////////////////////////////////
2148 /// Delete canvas.
2149 
2150 TGCanvas::~TGCanvas()
2151 {
2152  delete fHScrollbar;
2153  delete fVScrollbar;
2154  delete fVport;
2155 }
2156 
2157 ////////////////////////////////////////////////////////////////////////////////
2158 /// Map all canvas sub windows.
2159 
2160 void TGCanvas::MapSubwindows()
2161 {
2162  if (fHScrollbar) fHScrollbar->MapSubwindows();
2163  if (fVScrollbar) fVScrollbar->MapSubwindows();
2164 
2165  if (fVport) {
2166  TGFrame *container = fVport->GetContainer();
2167  if (!container) {
2168  Error("MapSubwindows", "no canvas container set yet");
2169  return;
2170  }
2171  container->MapSubwindows();
2172  fVport->MapSubwindows();
2173  fVport->MapWindow();
2174  }
2175  Layout();
2176 }
2177 
2178 ////////////////////////////////////////////////////////////////////////////////
2179 /// Adding a frame to a canvas is actually adding the frame to the
2180 /// viewport container. The viewport container must be at least a
2181 /// TGCompositeFrame for this method to succeed.
2182 
2183 void TGCanvas::AddFrame(TGFrame *f, TGLayoutHints *l)
2184 {
2185  TGFrame *container = fVport->GetContainer();
2186  if (!container) {
2187  Error("AddFrame", "no canvas container set yet");
2188  return;
2189  }
2190  if (container->InheritsFrom(TGCompositeFrame::Class()))
2191  ((TGCompositeFrame*)container)->AddFrame(f, l);
2192  else
2193  Error("AddFrame", "canvas container must inherit from TGCompositeFrame");
2194 }
2195 
2196 ////////////////////////////////////////////////////////////////////////////////
2197 /// Draw canvas border.
2198 
2199 void TGCanvas::DrawBorder()
2200 {
2201  switch (fOptions & (kSunkenFrame | kRaisedFrame | kDoubleBorder)) {
2202  case kSunkenFrame | kDoubleBorder:
2203  gVirtualX->DrawLine(fId, GetShadowGC()(), 0, 0, fWidth-2, 0);
2204  gVirtualX->DrawLine(fId, GetShadowGC()(), 0, 0, 0, fHeight-2);
2205  gVirtualX->DrawLine(fId, GetBlackGC()(), 1, 1, fWidth-3, 1);
2206  gVirtualX->DrawLine(fId, GetBlackGC()(), 1, 1, 1, fHeight-3);
2207  if (gClient->GetStyle() > 1) break;
2208  gVirtualX->DrawLine(fId, GetHilightGC()(), 0, fHeight-1, fWidth-1, fHeight-1);
2209  gVirtualX->DrawLine(fId, GetHilightGC()(), fWidth-1, fHeight-1, fWidth-1, 0);
2210  gVirtualX->DrawLine(fId, GetBckgndGC()(), 1, fHeight-2, fWidth-2, fHeight-2);
2211  gVirtualX->DrawLine(fId, GetBckgndGC()(), fWidth-2, 1, fWidth-2, fHeight-2);
2212  break;
2213 
2214  default:
2215  TGFrame::DrawBorder();
2216  break;
2217  }
2218 }
2219 
2220 ////////////////////////////////////////////////////////////////////////////////
2221 /// Create layout for canvas. Depending on the size of the container
2222 /// we need to add the scrollbars.
2223 
2224 void TGCanvas::Layout()
2225 {
2226  Bool_t need_vsb, need_hsb;
2227  UInt_t cw, ch, tcw, tch;
2228 
2229  need_vsb = need_hsb = kFALSE;
2230 
2231  TGFrame *container = fVport->GetContainer();
2232  if (!container) {
2233  Error("Layout", "no canvas container set yet");
2234  return;
2235  }
2236 
2237  Bool_t fixedw = container->IsLayoutBroken() || (container->GetOptions() & kFixedWidth) ?
2238  kTRUE : kFALSE;
2239  Bool_t fixedh = container->IsLayoutBroken() || (container->GetOptions() & kFixedHeight) ?
2240  kTRUE : kFALSE;
2241 
2242  // test whether we need scrollbars
2243  cw = fWidth - UInt_t(fBorderWidth << 1);
2244  ch = fHeight - UInt_t(fBorderWidth << 1);
2245 
2246  if (!fixedw) container->SetWidth(cw);
2247  if (!fixedh) container->SetHeight(ch);
2248 
2249  if (container->GetDefaultWidth() > cw) {
2250  if ((fScrolling & kCanvasScrollHorizontal) && fHScrollbar) {
2251  need_hsb = kTRUE;
2252  ch -= fHScrollbar->GetDefaultHeight();
2253  if ((Int_t) ch < 0) {
2254  //Warning("Layout", "height would become too small, setting to 10");
2255  ch = 10;
2256  }
2257  if (!fixedh) container->SetHeight(ch);
2258  }
2259  }
2260 
2261  if (container->GetDefaultHeight() > ch) {
2262  if ((fScrolling & kCanvasScrollVertical) && fVScrollbar) {
2263  need_vsb = kTRUE;
2264  cw -= fVScrollbar->GetDefaultWidth();
2265  if ((Int_t) cw < 0) {
2266  //Warning("Layout", "width would become too small, setting to 10");
2267  cw = 10;
2268  }
2269  if (!fixedw) container->SetWidth(cw);
2270  }
2271  }
2272 
2273  // re-check again (putting the vertical scrollbar could have changed things)
2274 
2275  if (container->GetDefaultWidth() > cw) {
2276  if (!need_hsb) {
2277  if ((fScrolling & kCanvasScrollHorizontal) && fHScrollbar) {
2278  need_hsb = kTRUE;
2279  ch -= fHScrollbar->GetDefaultHeight();
2280  if ((Int_t) ch < 0) {
2281  //Warning("Layout", "height would become too small, setting to 10");
2282  ch = 10;
2283  }
2284  if (!fixedh) container->SetHeight(ch);
2285  }
2286  }
2287  }
2288 
2289  fVport->MoveResize(fBorderWidth, fBorderWidth, cw, ch);
2290 
2291  tcw = TMath::Max(container->GetDefaultWidth(), cw);
2292  tch = TMath::Max(container->GetDefaultHeight(), ch);
2293  UInt_t curw = container->GetDefaultWidth();
2294 
2295  container->SetWidth(0); // force a resize in TGFrame::Resize
2296 
2297  if (fixedw && fixedh) {
2298  container->Resize(curw, container->GetDefaultHeight());
2299  } else if (fixedw) {
2300  container->Resize(curw, tch);
2301  } else if (fixedh) {
2302  container->Resize(tcw, container->GetDefaultHeight());
2303  } else {
2304  container->Resize(tcw, tch);
2305  }
2306 
2307  if (fHScrollbar) {
2308  if (need_hsb) {
2309  fHScrollbar->MoveResize(fBorderWidth, ch+fBorderWidth, cw, fHScrollbar->GetDefaultHeight());
2310  fHScrollbar->SetRange((Int_t)container->GetWidth(), (Int_t)fVport->GetWidth());
2311  fHScrollbar->MapWindow();
2312  } else {
2313  fHScrollbar->UnmapWindow();
2314  fHScrollbar->SetPosition(0);
2315  if (container->IsLayoutBroken()) {
2316  container->Resize(fVport->GetWidth(), container->GetHeight());
2317  }
2318  }
2319  }
2320 
2321  if (fVScrollbar) {
2322  if (need_vsb) {
2323  fVScrollbar->MoveResize(cw+fBorderWidth, fBorderWidth, fVScrollbar->GetDefaultWidth(), ch);
2324  fVScrollbar->SetRange((Int_t)container->GetHeight(), (Int_t)fVport->GetHeight());
2325  fVScrollbar->MapWindow();
2326  } else {
2327  fVScrollbar->UnmapWindow();
2328  fVScrollbar->SetPosition(0);
2329  if (container->IsLayoutBroken()) {
2330  container->Resize(container->GetWidth(), fVport->GetHeight());
2331  }
2332  }
2333  }
2334 }
2335 
2336 ////////////////////////////////////////////////////////////////////////////////
2337 /// Handle message generated by the canvas scrollbars.
2338 
2339 Bool_t TGCanvas::ProcessMessage(Long_t msg, Long_t parm1, Long_t)
2340 {
2341  switch (GET_MSG(msg)) {
2342  case kC_HSCROLL:
2343  switch (GET_SUBMSG(msg)) {
2344  case kSB_SLIDERTRACK:
2345  case kSB_SLIDERPOS:
2346  fVport->SetHPos((Int_t)-parm1);
2347  break;
2348  }
2349  break;
2350 
2351  case kC_VSCROLL:
2352  switch (GET_SUBMSG(msg)) {
2353  case kSB_SLIDERTRACK:
2354  case kSB_SLIDERPOS:
2355  fVport->SetVPos((Int_t)-parm1);
2356  break;
2357  }
2358  break;
2359 
2360  default:
2361  break;
2362  }
2363  return kTRUE;
2364 }
2365 
2366 ////////////////////////////////////////////////////////////////////////////////
2367 /// Get position of horizontal scrollbar.
2368 
2369 Int_t TGCanvas::GetHsbPosition() const
2370 {
2371  if (fHScrollbar && fHScrollbar->IsMapped())
2372  return fHScrollbar->GetPosition();
2373  return 0;
2374 }
2375 
2376 ////////////////////////////////////////////////////////////////////////////////
2377 /// Get position of vertical scrollbar.
2378 
2379 Int_t TGCanvas::GetVsbPosition() const
2380 {
2381  if (fVScrollbar && fVScrollbar->IsMapped())
2382  return fVScrollbar->GetPosition();
2383  return 0;
2384 }
2385 
2386 ////////////////////////////////////////////////////////////////////////////////
2387 /// Set position of horizontal scrollbar.
2388 
2389 void TGCanvas::SetHsbPosition(Int_t newPos)
2390 {
2391  if (fHScrollbar && fHScrollbar->IsMapped()) {
2392  TGFrame *container = fVport->GetContainer();
2393  fHScrollbar->SetRange((Int_t)container->GetWidth(), (Int_t)fVport->GetWidth());
2394  fHScrollbar->SetPosition(newPos);
2395  } else {
2396  fVport->SetHPos(0);
2397  }
2398 }
2399 
2400 ////////////////////////////////////////////////////////////////////////////////
2401 /// Set position of vertical scrollbar.
2402 
2403 void TGCanvas::SetVsbPosition(Int_t newPos)
2404 {
2405  if (fVScrollbar && fVScrollbar->IsMapped()) {
2406  TGFrame *container = fVport->GetContainer();
2407  fVScrollbar->SetRange((Int_t)container->GetHeight(), (Int_t)fVport->GetHeight());
2408  fVScrollbar->SetPosition(newPos);
2409  } else {
2410  fVport->SetVPos(0);
2411  }
2412 }
2413 
2414 ////////////////////////////////////////////////////////////////////////////////
2415 /// Set scrolling policy. Use values defined by the enum: kCanvasNoScroll,
2416 /// kCanvasScrollHorizontal, kCanvasScrollVertical, kCanvasScrollBoth.
2417 
2418 void TGCanvas::SetScrolling(Int_t scrolling)
2419 {
2420  if (scrolling != fScrolling) {
2421  fScrolling = scrolling;
2422  Layout();
2423  }
2424 }
2425 
2426 ////////////////////////////////////////////////////////////////////////////////
2427 /// Clear view port and redraw content.
2428 
2429 void TGCanvas::ClearViewPort()
2430 {
2431  TGFrame *cont = GetContainer();
2432  if (!cont) return;
2433 
2434  gVirtualX->ClearArea(cont->GetId(), 0, 0, fVport->GetWidth(), fVport->GetHeight());
2435  fClient->NeedRedraw(cont);
2436 }
2437 
2438 ////////////////////////////////////////////////////////////////////////////////
2439 /// Save a canvas widget as a C++ statement(s) on output stream out.
2440 
2441 void TGCanvas::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
2442 {
2443  if (fBackground != GetDefaultFrameBackground()) SaveUserColor(out, option);
2444 
2445  out << std::endl << " // canvas widget" << std::endl;
2446 
2447  out << " TGCanvas *";
2448  out << GetName() << " = new TGCanvas("<< fParent->GetName()
2449  << "," << GetWidth() << "," << GetHeight();
2450 
2451  if (fBackground == GetDefaultFrameBackground()) {
2452  if (GetOptions() == (kSunkenFrame | kDoubleBorder)) {
2453  out << ");" << std::endl;
2454  } else {
2455  out << "," << GetOptionString() << ");" << std::endl;
2456  }
2457  } else {
2458  out << "," << GetOptionString() << ",ucolor);" << std::endl;
2459  }
2460  if (option && strstr(option, "keep_names"))
2461  out << " " << GetName() << "->SetName(\"" << GetName() << "\");" << std::endl;
2462 
2463  TGViewPort *vp = GetViewPort();
2464  out << std::endl << " // canvas viewport" << std::endl;
2465  out << " TGViewPort *" << vp->GetName() << " = " << GetName()
2466  << "->GetViewPort();" << std::endl;
2467 
2468  TGContainer *cont = (TGContainer*)GetContainer();
2469  cont->SavePrimitive(out, option);
2470 
2471  out << " " << vp->GetName() << "->AddFrame(" << cont->GetName()
2472  << ");" << std::endl;
2473 
2474  out << " " << cont->GetName() << "->SetLayoutManager(";
2475  cont->GetLayoutManager()->SavePrimitive(out, option);
2476  out << ");"<< std::endl;
2477 
2478  out << " " << cont->GetName() << "->MapSubwindows();" << std::endl;
2479 
2480  out << " " << GetName() << "->SetContainer(" << cont->GetName()
2481  << ");" << std::endl;
2482 
2483  out << " " << GetName() << "->MapSubwindows();" << std::endl;
2484 
2485  if (fHScrollbar && fHScrollbar->IsMapped())
2486  out << " " << GetName() << "->SetHsbPosition(" << GetHsbPosition()
2487  << ");" << std::endl;
2488 
2489 
2490  if (fVScrollbar && fVScrollbar->IsMapped())
2491  out << " " << GetName() << "->SetVsbPosition(" << GetVsbPosition()
2492  << ");" << std::endl;
2493 
2494 }
2495 
2496 ////////////////////////////////////////////////////////////////////////////////
2497 /// Save a canvas container as a C++ statement(s) on output stream out.
2498 
2499 void TGContainer::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
2500 {
2501  if (fBackground != GetDefaultFrameBackground()) SaveUserColor(out, option);
2502 
2503  out << std::endl << " // canvas container" << std::endl;
2504 
2505  if ((fParent->GetParent())->InheritsFrom(TGCanvas::Class())) {
2506  out << GetName() << " = new TGContainer(" << GetCanvas()->GetName();
2507  } else {
2508  out << GetName() << " = new TGContainer(" << fParent->GetName();
2509  out << "," << GetWidth() << "," << GetHeight();
2510  }
2511 
2512  if (fBackground == GetDefaultFrameBackground()) {
2513  if (GetOptions() == (kSunkenFrame | kDoubleBorder)) {
2514  out <<");" << std::endl;
2515  } else {
2516  out << "," << GetOptionString() <<");" << std::endl;
2517  }
2518  } else {
2519  out << "," << GetOptionString() << ",ucolor);" << std::endl;
2520  }
2521  if (option && strstr(option, "keep_names"))
2522  out << " " << GetName() << "->SetName(\"" << GetName() << "\");" << std::endl;
2523 }