Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGSplitter.cxx
Go to the documentation of this file.
1 // @(#)root/gui:$Id$
2 // Author: Fons Rademakers 6/09/2000
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 // //
14 // TGSplitter, TGVSplitter and TGHSplitter //
15 // //
16 // A splitter allows the frames left and right or above and below of //
17 // it to be resized. The frame to be resized must have the kFixedWidth //
18 // or kFixedHeight property set. //
19 // //
20 //////////////////////////////////////////////////////////////////////////
21 
22 #include "TGSplitter.h"
23 #include "TGPicture.h"
24 #include "Riostream.h"
25 
26 
27 ClassImp(TGSplitter);
28 ClassImp(TGVSplitter);
29 ClassImp(TGHSplitter);
30 ClassImp(TGVFileSplitter);
31 
32 
33 ////////////////////////////////////////////////////////////////////////////////
34 /// Create a splitter.
35 
36 TGSplitter::TGSplitter(const TGWindow *p, UInt_t w, UInt_t h,
37  UInt_t options, ULong_t back) :
38  TGFrame(p, w, h, options, back),
39  fDragging (kFALSE),
40  fExternalHandler (kFALSE),
41  fSplitterPic (0)
42 {
43  fSplitCursor = kNone;
44  fEditDisabled = kTRUE;
45 }
46 
47 ////////////////////////////////////////////////////////////////////////////////
48 /// Emit DragStarted signal.
49 
50 void TGSplitter::DragStarted()
51 {
52  Emit("DragStarted()");
53 }
54 
55 ////////////////////////////////////////////////////////////////////////////////
56 /// Emit Moved signal.
57 
58 void TGSplitter::Moved(Int_t delta)
59 {
60  Emit("Moved(Int_t)", delta);
61 }
62 
63 ////////////////////////////////////////////////////////////////////////////////
64 /// Create a vertical splitter.
65 
66 TGVSplitter::TGVSplitter(const TGWindow *p, UInt_t w, UInt_t h,
67  UInt_t options, ULong_t back) : TGSplitter(p, w, h, options, back)
68 {
69  fSplitCursor = kNone;
70  fSplitterPic = fClient->GetPicture("splitterv.xpm");
71  fFrameHeight = h;
72  fFrameWidth = w;
73  fLeft = kTRUE;
74  fMax = fMin = 0;
75  fStartX = 0;
76  fFrame = 0;
77 
78  if (!fSplitterPic)
79  Error("TGVSplitter", "splitterv.xpm not found");
80 
81  if (p && !p->InheritsFrom(TGCompositeFrame::Class())) {
82  Error("TGVSplitter", "parent must inherit from a TGCompositeFrame");
83  return;
84  }
85  if (p && !(((TGCompositeFrame*)p)->GetOptions() & kHorizontalFrame)) {
86  Error("TGVSplitter", "parent must have a horizontal layout manager");
87  return;
88  }
89 
90  fSplitCursor = gVirtualX->CreateCursor(kArrowHor);
91 
92  gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
93  kButtonPressMask | kButtonReleaseMask |
94  kPointerMotionMask, kNone, kNone);
95 
96  AddInput(kEnterWindowMask | kLeaveWindowMask);
97 }
98 
99 ////////////////////////////////////////////////////////////////////////////////
100 /// Create a vertical splitter.
101 
102 TGVSplitter::TGVSplitter(const TGWindow *p, UInt_t w, UInt_t h, Bool_t external) :
103  TGSplitter(p, w, h, kChildFrame, GetDefaultFrameBackground())
104 {
105  fExternalHandler = external;
106 
107  fSplitCursor = kNone;
108  fSplitterPic = fClient->GetPicture("splitterv.xpm");
109 
110  if (!fSplitterPic)
111  Error("TGVSplitter", "splitterv.xpm not found");
112 
113  fSplitCursor = gVirtualX->CreateCursor(kArrowHor);
114  fFrame = 0;
115  fFrameHeight = h;
116  fFrameWidth = w;
117  fLeft = kTRUE;
118  fMax = fMin = 0;
119  fStartX = 0;
120 
121  gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
122  kButtonPressMask | kButtonReleaseMask |
123  kPointerMotionMask, kNone, kNone);
124 
125  AddInput(kEnterWindowMask | kLeaveWindowMask);
126 }
127 
128 ////////////////////////////////////////////////////////////////////////////////
129 /// Delete vertical splitter widget.
130 
131 TGVSplitter::~TGVSplitter()
132 {
133  if (fSplitterPic) fClient->FreePicture(fSplitterPic);
134 }
135 
136 ////////////////////////////////////////////////////////////////////////////////
137 /// Set frame to be resized. If frame is on the left of the splitter
138 /// set left to true.
139 
140 void TGVSplitter::SetFrame(TGFrame *frame, Bool_t left)
141 {
142  fFrame = frame;
143  fLeft = left;
144 
145  if (!fExternalHandler && !(fFrame->GetOptions() & kFixedWidth))
146  Error("SetFrame", "resize frame must have kFixedWidth option set");
147 }
148 
149 ////////////////////////////////////////////////////////////////////////////////
150 /// Handle mouse button event in vertical splitter.
151 
152 Bool_t TGVSplitter::HandleButton(Event_t *event)
153 {
154  if (fSplitCursor == kNone) return kTRUE;
155 
156  if (!fExternalHandler && !fFrame) {
157  Error("HandleButton", "frame to be resized not set");
158  return kTRUE;
159  }
160 
161  if (event->fType == kButtonPress) {
162  fStartX = event->fXRoot;
163  fDragging = kTRUE;
164 
165  if (fExternalHandler) {
166  fMin = 0;
167  fMax = 99999;
168  DragStarted();
169  } else {
170  Int_t x, y;
171  gVirtualX->GetWindowSize(fFrame->GetId(), x, y, fFrameWidth, fFrameHeight);
172 
173  // get fMin and fMax in root coordinates
174  Int_t xroot, yroot;
175  UInt_t w, h;
176  Window_t wdum;
177  gVirtualX->GetWindowSize(fParent->GetId(), x, y, w, h);
178  gVirtualX->TranslateCoordinates(fParent->GetParent()->GetId(),
179  fClient->GetDefaultRoot()->GetId(),
180  x, y, xroot, yroot, wdum);
181  fMin = xroot;
182  fMax = xroot + w - 2;
183  }
184 
185  // last argument kFALSE forces all specified events to this window
186  gVirtualX->GrabPointer(fId, kButtonPressMask | kButtonReleaseMask |
187  kPointerMotionMask, kNone, fSplitCursor,
188  kTRUE, kFALSE);
189  } else {
190  fDragging = kFALSE;
191  gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE); // ungrab pointer
192  }
193  return kTRUE;
194 }
195 
196 ////////////////////////////////////////////////////////////////////////////////
197 /// Handle mouse motion event in vertical splitter.
198 
199 Bool_t TGVSplitter::HandleMotion(Event_t *event)
200 {
201  if (fDragging) {
202  Int_t xr = event->fXRoot;
203  if (xr > fMax) xr = fMax;
204  if (xr < fMin) xr = fMin;
205  Int_t delta = xr - fStartX;
206  if (fExternalHandler) {
207  if (delta != 0) {
208  Moved(delta);
209  fStartX = xr;
210  }
211  } else {
212  Int_t w = (Int_t) fFrameWidth;
213  if (fLeft)
214  w += delta;
215  else
216  w -= delta;
217  if (w < 0) w = 0;
218  fStartX = xr;
219 
220  if (delta != 0) {
221  fFrameWidth = w;
222  fFrame->Resize(fFrameWidth, fFrameHeight);
223 
224  TGCompositeFrame *p = (TGCompositeFrame *) GetParent();
225  p->Layout();
226  }
227  }
228  }
229  return kTRUE;
230 }
231 
232 ////////////////////////////////////////////////////////////////////////////////
233 /// Handle mouse motion event in vertical splitter.
234 
235 Bool_t TGVSplitter::HandleCrossing(Event_t *event)
236 {
237  if (event->fType == kEnterNotify)
238  gVirtualX->SetCursor(fId, fSplitCursor);
239  else
240  gVirtualX->SetCursor(fId, kNone);
241 
242  return kTRUE;
243 }
244 
245 ////////////////////////////////////////////////////////////////////////////////
246 /// Draw vertical splitter.
247 
248 void TGVSplitter::DrawBorder()
249 {
250  if (fSplitterPic) {
251  Int_t posx = (fWidth/2)-(fSplitterPic->GetWidth()/2);
252  Int_t posy = (fHeight/2)-(fSplitterPic->GetHeight()/2);
253  fSplitterPic->Draw(fId, GetBckgndGC()(), posx, posy);
254  }
255 }
256 
257 
258 ////////////////////////////////////////////////////////////////////////////////
259 /// Create a horizontal splitter.
260 
261 TGHSplitter::TGHSplitter(const TGWindow *p, UInt_t w, UInt_t h,
262  UInt_t options, ULong_t back) : TGSplitter(p, w, h, options, back)
263 {
264  fSplitCursor = kNone;
265  fSplitterPic = 0;
266  fSplitCursor = 0;
267  fFrame = 0;
268  fFrameHeight = h;
269  fFrameWidth = w;
270  fAbove = kTRUE;
271  fMax = fMin = 0;
272  fStartY = 0;
273 
274  if (p && !p->InheritsFrom(TGCompositeFrame::Class())) {
275  Error("TGHSplitter", "parent must inherit from a TGCompositeFrame");
276  return;
277  }
278  if (p && !(((TGCompositeFrame*)p)->GetOptions() & kVerticalFrame)) {
279  Error("TGHSplitter", "parent must have a vertical layout manager");
280  return;
281  }
282 
283  fSplitterPic = fClient->GetPicture("splitterh.xpm");
284 
285  if (!fSplitterPic)
286  Error("TGHSplitter", "splitterh.xpm not found");
287 
288  fSplitCursor = gVirtualX->CreateCursor(kArrowVer);
289 
290  gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
291  kButtonPressMask | kButtonReleaseMask |
292  kPointerMotionMask, kNone, kNone);
293 
294  AddInput(kEnterWindowMask | kLeaveWindowMask);
295 }
296 
297 ////////////////////////////////////////////////////////////////////////////////
298 /// Create a horizontal splitter.
299 
300 TGHSplitter::TGHSplitter(const TGWindow *p, UInt_t w, UInt_t h, Bool_t external) :
301  TGSplitter(p, w, h, kChildFrame, GetDefaultFrameBackground())
302 {
303  fExternalHandler = external;
304 
305  fSplitCursor = kNone;
306 
307  fSplitterPic = fClient->GetPicture("splitterh.xpm");
308 
309  if (!fSplitterPic)
310  Error("TGHSplitter", "splitterh.xpm not found");
311 
312  fSplitCursor = gVirtualX->CreateCursor(kArrowVer);
313  fFrame = 0;
314  fFrameHeight = h;
315  fFrameWidth = w;
316  fAbove = kTRUE;
317  fMax = fMin = 0;
318  fStartY = 0;
319 
320  gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
321  kButtonPressMask | kButtonReleaseMask |
322  kPointerMotionMask, kNone, kNone);
323 
324  AddInput(kEnterWindowMask | kLeaveWindowMask);
325 }
326 
327 ////////////////////////////////////////////////////////////////////////////////
328 /// Delete horizontal splitter widget.
329 
330 TGHSplitter::~TGHSplitter()
331 {
332  if (fSplitterPic) fClient->FreePicture(fSplitterPic);
333 }
334 
335 ////////////////////////////////////////////////////////////////////////////////
336 /// Set frame to be resized. If frame is above the splitter
337 /// set above to true.
338 
339 void TGHSplitter::SetFrame(TGFrame *frame, Bool_t above)
340 {
341  fFrame = frame;
342  fAbove = above;
343 
344  if (!fExternalHandler && !(fFrame->GetOptions() & kFixedHeight))
345  Error("SetFrame", "resize frame must have kFixedHeight option set");
346 }
347 
348 ////////////////////////////////////////////////////////////////////////////////
349 /// Handle mouse button event in horizontal splitter.
350 
351 Bool_t TGHSplitter::HandleButton(Event_t *event)
352 {
353  if (fSplitCursor == kNone) return kTRUE;
354 
355  if (!fExternalHandler && !fFrame) {
356  Error("HandleButton", "frame to be resized not set");
357  return kTRUE;
358  }
359 
360  if (event->fType == kButtonPress) {
361  fStartY = event->fYRoot;
362  fDragging = kTRUE;
363 
364  if (fExternalHandler) {
365  fMin = 0;
366  fMax = 99999;
367  DragStarted();
368  } else {
369  Int_t x, y;
370  gVirtualX->GetWindowSize(fFrame->GetId(), x, y, fFrameWidth, fFrameHeight);
371 
372  // get fMin and fMax in root coordinates
373  Int_t xroot, yroot;
374  UInt_t w, h;
375  Window_t wdum;
376  gVirtualX->GetWindowSize(fParent->GetId(), x, y, w, h);
377  gVirtualX->TranslateCoordinates(fParent->GetParent()->GetId(),
378  fClient->GetDefaultRoot()->GetId(),
379  x, y, xroot, yroot, wdum);
380  fMin = yroot;
381  fMax = yroot + h - 2;
382  }
383 
384  // last argument kFALSE forces all specified events to this window
385  gVirtualX->GrabPointer(fId, kButtonPressMask | kButtonReleaseMask |
386  kPointerMotionMask, kNone, fSplitCursor,
387  kTRUE, kFALSE);
388  } else {
389  fDragging = kFALSE;
390  gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE); // ungrab pointer
391  }
392  return kTRUE;
393 }
394 
395 ////////////////////////////////////////////////////////////////////////////////
396 /// Handle mouse motion event in horizontal splitter.
397 
398 Bool_t TGHSplitter::HandleMotion(Event_t *event)
399 {
400  if (fDragging) {
401  Int_t yr = event->fYRoot;
402  if (yr > fMax) yr = fMax;
403  if (yr < fMin) yr = fMin;
404  Int_t delta = yr - fStartY;
405  if (fExternalHandler) {
406  if (delta != 0) {
407  Moved(delta);
408  fStartY = yr;
409  }
410  } else {
411  Int_t h = (Int_t) fFrameHeight;
412  if (fAbove)
413  h += delta;
414  else
415  h -= delta;
416  if (h < 0) h = 0;
417  fStartY = yr;
418 
419  if (delta != 0) {
420  fFrameHeight = h;
421  fFrame->Resize(fFrameWidth, fFrameHeight);
422 
423  TGCompositeFrame *p = (TGCompositeFrame *) GetParent();
424  p->Layout();
425  }
426  }
427  }
428  return kTRUE;
429 }
430 
431 ////////////////////////////////////////////////////////////////////////////////
432 /// Handle mouse motion event in horizontal splitter.
433 
434 Bool_t TGHSplitter::HandleCrossing(Event_t *event)
435 {
436  if (event->fType == kEnterNotify)
437  gVirtualX->SetCursor(fId, fSplitCursor);
438  else
439  gVirtualX->SetCursor(fId, kNone);
440 
441  return kTRUE;
442 }
443 
444 ////////////////////////////////////////////////////////////////////////////////
445 /// Draw horizontal splitter.
446 
447 void TGHSplitter::DrawBorder()
448 {
449  if (fSplitterPic) {
450  Int_t posx = (fWidth/2)-(fSplitterPic->GetWidth()/2);
451  Int_t posy = (fHeight/2)-(fSplitterPic->GetHeight()/2);
452  fSplitterPic->Draw(fId, GetBckgndGC()(), posx, posy);
453  }
454 }
455 
456 ////////////////////////////////////////////////////////////////////////////////
457 /// fSplitterPic = fClient->GetPicture("filesplitterv.xpm");
458 
459 TGVFileSplitter::TGVFileSplitter(const TGWindow *p, UInt_t w, UInt_t h,
460  UInt_t options, Pixel_t back):
461  TGVSplitter(p, w, h, options, back)
462 {
463 // if (!fSplitterPic)
464 // Error("TGVFileSplitter", "filesplitterv.xpm not found");
465 }
466 
467 ////////////////////////////////////////////////////////////////////////////////
468 /// if (fSplitterPic) fClient->FreePicture(fSplitterPic);
469 
470 TGVFileSplitter::~TGVFileSplitter()
471 {
472 }
473 
474 ////////////////////////////////////////////////////////////////////////////////
475 /// Handle mouse motion event in vertical splitter.
476 
477 Bool_t TGVFileSplitter::HandleMotion(Event_t *event)
478 {
479  fMin = 30;
480 
481  if (fDragging) {
482  Int_t xr = event->fXRoot;
483  if (xr > fMax) xr = fMax;
484  if (xr < fMin) xr = fMin;
485  Int_t delta = xr - fStartX;
486  Int_t w = (Int_t) fFrameWidth;
487  if (fLeft)
488  w += delta;
489  else
490  w -= delta;
491 
492  if (w < 0) w = 0;
493  fStartX = xr;
494 
495  if (delta != 0) {
496  delta = w - fFrameWidth;
497  fFrameWidth = w;
498 
499  TGCompositeFrame *p = (TGCompositeFrame *) GetParent();
500  p->Resize( p->GetWidth() + delta, p->GetHeight() );
501 
502  fFrame->Resize(fFrameWidth, fFrameHeight);
503 
504  p->Layout();
505  LayoutHeader((TGFrame *)fFrame);
506  }
507  }
508  return kTRUE;
509 }
510 
511 ////////////////////////////////////////////////////////////////////////////////
512 /// Handle mouse button event in vertical splitter.
513 
514 Bool_t TGVFileSplitter::HandleButton(Event_t *event)
515 {
516  if ( event->fType == kButtonPress) {
517  ButtonPressed();
518  } else if ( event->fType == kButtonRelease) {
519  LayoutHeader(0);
520  LayoutListView();
521  ButtonReleased();
522  } else if ( event->fType == kButtonDoubleClick ) {
523  DoubleClicked(this);
524  }
525  return TGVSplitter::HandleButton(event);
526 }
527 
528 ////////////////////////////////////////////////////////////////////////////////
529 /// Emit LayoutFeader() signal.
530 
531 void TGVFileSplitter::LayoutHeader(TGFrame *f)
532 {
533  Emit("LayoutHeader(TGFrame*)", (Long_t)f);
534 }
535 
536 ////////////////////////////////////////////////////////////////////////////////
537 /// Emit LayoutListView() signal.
538 
539 void TGVFileSplitter::LayoutListView()
540 {
541  Emit("LayoutListView()");
542 }
543 
544 ////////////////////////////////////////////////////////////////////////////////
545 /// Emit ButtonPressed() signal.
546 
547 void TGVFileSplitter::ButtonPressed()
548 {
549  Emit("ButtonPressed()");
550 }
551 
552 ////////////////////////////////////////////////////////////////////////////////
553 /// Emit ButtonReleased() signal.
554 
555 void TGVFileSplitter::ButtonReleased()
556 {
557  Emit("ButtonReleased()");
558 }
559 
560 ////////////////////////////////////////////////////////////////////////////////
561 /// Emit DoubleClicked() signal.
562 
563 void TGVFileSplitter::DoubleClicked(TGVFileSplitter* splitter)
564 {
565  Emit("DoubleClicked(TGVFileSplitter*)", (Long_t) splitter);
566 }
567 
568 ////////////////////////////////////////////////////////////////////////////////
569 /// Handle double click mouse event in splitter.
570 
571 Bool_t TGVFileSplitter::HandleDoubleClick(Event_t *)
572 {
573  DoubleClicked(this);
574  return kTRUE;
575 }
576 
577 ////////////////////////////////////////////////////////////////////////////////
578 /// Save a splitter widget as a C++ statement(s) on output stream out.
579 
580 void TGVSplitter::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
581 {
582  if (fBackground != GetDefaultFrameBackground()) SaveUserColor(out, option);
583 
584  out << " TGVSplitter *";
585  out << GetName() <<" = new TGVSplitter("<< fParent->GetName()
586  << "," << GetWidth() << "," << GetHeight();
587 
588  if (fBackground == GetDefaultFrameBackground()) {
589  if (!GetOptions()) {
590  out <<");" << std::endl;
591  } else {
592  out << "," << GetOptionString() <<");" << std::endl;
593  }
594  } else {
595  out << "," << GetOptionString() << ",ucolor);" << std::endl;
596  }
597  if (option && strstr(option, "keep_names"))
598  out << " " << GetName() << "->SetName(\"" << GetName() << "\");" << std::endl;
599  // TGVSplitter->SetFrame( theframe ) can only be saved here
600  // if fFrame is the frame on the left (since the frame on the
601  // right will only be saved afterwards)... The other case is
602  // handled in TGCompositeFrame::SavePrimitiveSubframes()
603  if (GetLeft()) {
604  out << " " << GetName() << "->SetFrame(" << GetFrame()->GetName();
605  if (GetLeft()) out << ",kTRUE);" << std::endl;
606  else out << ",kFALSE);"<< std::endl;
607  }
608 }
609 
610 ////////////////////////////////////////////////////////////////////////////////
611 /// Save a splitter widget as a C++ statement(s) on output stream out.
612 
613 void TGHSplitter::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
614 {
615  if (fBackground != GetDefaultFrameBackground()) SaveUserColor(out, option);
616 
617  out << " TGHSplitter *";
618  out << GetName() <<" = new TGHSplitter("<< fParent->GetName()
619  << "," << GetWidth() << "," << GetHeight();
620 
621  if (fBackground == GetDefaultFrameBackground()) {
622  if (!GetOptions()) {
623  out <<");" << std::endl;
624  } else {
625  out << "," << GetOptionString() <<");" << std::endl;
626  }
627  } else {
628  out << "," << GetOptionString() << ",ucolor);" << std::endl;
629  }
630  if (option && strstr(option, "keep_names"))
631  out << " " << GetName() << "->SetName(\"" << GetName() << "\");" << std::endl;
632  // TGHSplitter->SetFrame( theframe ) can only be saved here
633  // if fFrame is the frame above (since the frame below will
634  // only be saved afterwards)... The other case is handled in
635  // TGCompositeFrame::SavePrimitiveSubframes()
636  if (GetAbove()) {
637  out << " " << GetName() << "->SetFrame(" << GetFrame()->GetName();
638  if (GetAbove()) out << ",kTRUE);" << std::endl;
639  else out << ",kFALSE);"<< std::endl;
640  }
641 }
642 
643 ////////////////////////////////////////////////////////////////////////////////
644 /// Save a splitter widget as a C++ statement(s) on output stream out.
645 
646 void TGVFileSplitter::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
647 {
648  if (fBackground != GetDefaultFrameBackground()) SaveUserColor(out, option);
649 
650  out << " TGVFileSplitter *";
651  out << GetName() <<" = new TGVFileSplitter("<< fParent->GetName()
652  << "," << GetWidth() << "," << GetHeight();
653 
654  if (fBackground == GetDefaultFrameBackground()) {
655  if (!GetOptions()) {
656  out <<");" << std::endl;
657  } else {
658  out << "," << GetOptionString() <<");" << std::endl;
659  }
660  } else {
661  out << "," << GetOptionString() << ",ucolor);" << std::endl;
662  }
663  if (option && strstr(option, "keep_names"))
664  out << " " << GetName() << "->SetName(\"" << GetName() << "\");" << std::endl;
665 
666  out << " " << GetName() << "->SetFrame(" << GetFrame()->GetName();
667  if (GetLeft()) out << ",kTRUE);" << std::endl;
668  else out << ",kFALSE);"<< std::endl;
669 }
670