Logo ROOT   6.12/07
Reference Guide
TGPack.cxx
Go to the documentation of this file.
1 // @(#)root/eve:$Id$
2 // Author: Matevz Tadel 2007
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2007, 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 #include "TGPack.h"
13 #include "TGSplitter.h"
14 #include "TMath.h"
15 
16 //______________________________________________________________________________
17 //
18 // Stack of frames in horizontal (default) or vertical stack.
19 // The splitters are placed between the neighbouring frames so that
20 // they can be resized by the user.
21 // When the whole pack is resized, frames are scaled proportionally to
22 // their previous size.
23 //
24 // When frames are left in pack at destruction time, they will be
25 // deleted via local-cleanup.
26 
28 
29 ////////////////////////////////////////////////////////////////////////////////
30 /// Constructor.
31 
32 TGPack::TGPack(const TGWindow *p, UInt_t w, UInt_t h, UInt_t options, Pixel_t back) :
33  TGCompositeFrame(p, w, h, options, back),
34  fVertical (kTRUE),
35  fUseSplitters (kTRUE),
36  fSplitterLen (4),
37  fDragOverflow (0),
38  fWeightSum(0),
39  fNVisible(0)
40 {
42 }
43 
44 ////////////////////////////////////////////////////////////////////////////////
45 /// Constructor.
46 
47 TGPack::TGPack(TGClient *c, Window_t id, const TGWindow *parent) :
48  TGCompositeFrame(c, id, parent),
49  fVertical (kTRUE),
51  fSplitterLen (4),
52  fDragOverflow (0),
53  fWeightSum (0.0),
54  fNVisible (0)
55 {
57 }
58 
59 ////////////////////////////////////////////////////////////////////////////////
60 /// Destructor.
61 
63 {
64 }
65 
66 //------------------------------------------------------------------------------
67 
68 ////////////////////////////////////////////////////////////////////////////////
69 /// Return length of entire frame without splitters.
70 
72 {
73  Int_t len = fVertical ? GetHeight() : GetWidth();
74  len -= fSplitterLen * (fNVisible - 1);
75 
76  return len;
77 }
78 
79 ////////////////////////////////////////////////////////////////////////////////
80 /// Set pack-wise length of frame f.
81 
83 {
84  if (fVertical)
85  f->Resize(GetWidth(), len);
86  else
87  f->Resize(len, GetHeight());
88 }
89 
90 ////////////////////////////////////////////////////////////////////////////////
91 /// Set pack-wise position of frame f.
92 
94 {
95  if (fVertical)
96  f->Move(0, pos);
97  else
98  f->Move(pos, 0);
99 }
100 
101 ////////////////////////////////////////////////////////////////////////////////
102 /// Check if splitter of first visible frame is hidden.
103 /// Check if the next following visible splitter is visible.
104 
106 {
107  TGFrameElementPack *el;
108  TIter next(fList);
109  Int_t rvf = 0;
110  while ((el = (TGFrameElementPack*) next()))
111  {
112  if (el->fState && el->fSplitFE)
113  {
114  if (rvf)
115  {
116  // unmap first slider if necessary
117  if ( el->fSplitFE->fState == 0 ) {
118  el->fSplitFE->fState = 1;
119  el->fSplitFE->fFrame->MapWindow();
120  }
121  }
122  else
123  {
124  // show slider in next visible frame
125  if (el->fSplitFE->fState) {
126  el->fSplitFE->fState = 0;
127  el->fSplitFE->fFrame->UnmapWindow();
128  }
129  }
130  ++rvf;
131  }
132  }
133 }
134 
135 ////////////////////////////////////////////////////////////////////////////////
136 /// Resize (shrink or expand) existing frames by amount in total.
137 
139 {
140  if (fList->IsEmpty())
141  return;
142 
143  // get unitsize
144  Int_t nflen = GetAvailableLength();
145  Float_t unit = Float_t(nflen)/fWeightSum;
146 
147  // set frame sizes
148  Int_t sumFrames = 0;
149  Int_t frameLength = 0;
150  {
151  TGFrameElementPack *el;
152  TIter next(fList);
153  while ((el = (TGFrameElementPack*) next()))
154  {
155  if (el->fState && el->fWeight)
156  {
157  frameLength = TMath::Nint( unit*(el->fWeight));
158  SetFrameLength(el->fFrame, frameLength);
159  sumFrames += frameLength;
160  }
161  }
162  }
163 
164  // redistribute the remain
165  {
166  // printf("available %d total %d \n", nflen, sumFrames);
167  Int_t remain = nflen-sumFrames;
168  Int_t step = TMath::Sign(1, remain);
169  TGFrameElementPack *el;
170  TIter next(fList);
171  while ((el = (TGFrameElementPack*) next()) && remain)
172  {
173  if (el->fState && el->fWeight)
174  {
175  Int_t l = GetFrameLength(el->fFrame) + step;
176  if (l > 0)
177  {
178  SetFrameLength(el->fFrame, l);
179  remain -= step;
180  }
181  }
182  }
183  }
185 }
186 
187 ////////////////////////////////////////////////////////////////////////////////
188 /// Refit existing frames to pack size.
189 
191 {
192  TGFrameElement *el;
193  TIter next(fList);
194 
195  while ((el = (TGFrameElement *) next()))
196  {
197  if (fVertical)
198  el->fFrame->Resize(GetWidth(), el->fFrame->GetHeight());
199  else
200  el->fFrame->Resize(el->fFrame->GetWidth(), GetHeight());
201  }
202 }
203 
204 ////////////////////////////////////////////////////////////////////////////////
205 /// Find frames around splitter and return them f0 (previous) and f1 (next).
206 
208 {
209  TGFrameElementPack *el;
210  TIter next(fList);
211 
212  while ((el = (TGFrameElementPack *) next()))
213  {
214  if ( ! (el->fState & kIsVisible) )
215  continue;
216 
217  if (el->fFrame == splitter)
218  break;
219  f0 = el;
220  }
221  f1 = (TGFrameElementPack *) next();
222 }
223 
224 
225 //------------------------------------------------------------------------------
226 
227 ////////////////////////////////////////////////////////////////////////////////
228 /// Add frame f at the end.
229 /// LayoutHints are ignored in TGPack.
230 
232 {
233  // add splitter
234  TGFrameElementPack *sf = 0;
235  if (fUseSplitters) {
236  TGSplitter* s = 0;
237  if (fVertical)
238  s = new TGHSplitter(this, GetWidth(), fSplitterLen, kTRUE);
239  else
240  s = new TGVSplitter(this, fSplitterLen, GetHeight(), kTRUE);
241  s->Connect("Moved(Int_t)", "TGPack", this, "HandleSplitterResize(Int_t)");
242  s->Connect("DragStarted()", "TGPack", this, "HandleSplitterStart()");
243 
244  sf = new TGFrameElementPack(s, l ? l : fgDefaultHints, 0);
245  fList->Add(sf);
246  // in case of recusive cleanup, propagate cleanup setting to all
247  // child composite frames
248  if (fMustCleanup == kDeepCleanup)
250  s->MapWindow();
251  }
252 
253  // instread TGCopositeFrame::AddFrame
254  TGFrameElementPack *el = new TGFrameElementPack(f, l ? l : fgDefaultHints, weight);
255  el->fSplitFE = sf;
256  fList->Add(el);
257 
258  // in case of recusive cleanup, propagate cleanup setting to all
259  // child composite frames
260  if (fMustCleanup == kDeepCleanup)
262  f->MapWindow();
263 
264  fNVisible ++;
265  fWeightSum += weight;
266 
269 }
270 
271 ////////////////////////////////////////////////////////////////////////////////
272 /// Add frame f at the end with given weight.
273 /// LayoutHints are ignored in TGPack.
274 
276 {
277  AddFrameInternal(f, l, weight);
278  Layout();
279 }
280 
281 ////////////////////////////////////////////////////////////////////////////////
282 /// Add frame f at the end with default weight.
283 /// LayoutHints are ignored in TGPack.
284 
286 {
287  AddFrameInternal(f, l, 1);
288  Layout();
289 }
290 
291 ////////////////////////////////////////////////////////////////////////////////
292 /// Remove frame f.
293 
295 {
297 
298  if (!el) return;
299 
300  if (fUseSplitters)
301  {
303  splitter->UnmapWindow();
305  // This is needed so that splitter window gets destroyed on server.
306  splitter->ReparentWindow(fClient->GetDefaultRoot());
307  delete splitter;
308  }
309  if (el->fState & kIsVisible)
310  {
311  f->UnmapWindow();
312  fWeightSum -= el->fWeight;
313  --fNVisible;
314  }
316 
319 }
320 
321 ////////////////////////////////////////////////////////////////////////////////
322 /// Remove frame f and refit existing frames to pack size.
323 /// Frame is deleted.
324 
326 {
328  delete f;
329  Layout();
330 }
331 
332 ////////////////////////////////////////////////////////////////////////////////
333 /// Remove frame f and refit existing frames to pack size.
334 /// Frame is not deleted.
335 
337 {
339  Layout();
340 }
341 
342 ////////////////////////////////////////////////////////////////////////////////
343 /// Print sub frame info.
344 
345 void TGPack::Dump() const
346 {
347  printf("--------------------------------------------------------------\n");
348  Int_t cnt = 0;
349  TGFrameElementPack *el;
350  TIter next(fList);
351  while ((el = (TGFrameElementPack *) next()))
352  {
353  printf("idx[%d] visible(%d) %s \n",cnt, el->fState, el->fFrame->GetName());
354  cnt++;
355  }
356  printf("--------------------------------------------------------------\n");
357 }
358 
359 ////////////////////////////////////////////////////////////////////////////////
360 /// Show sub frame.
361 /// Virtual from TGCompositeFrame.
362 
364 {
366  if (el)
367  {
368  //show
369  el->fState = 1;
370  el->fFrame->MapWindow();
371 
372  // show splitter
373  if (fUseSplitters)
374  {
375  el->fSplitFE->fFrame->MapWindow();
376  el->fSplitFE->fState = 1;
377  }
378 
379  // Dump();
380  fNVisible++;
381  fWeightSum += el->fWeight;
382 
385  Layout();
386  }
387 }
388 
389 ////////////////////////////////////////////////////////////////////////////////
390 /// Hide sub frame.
391 /// Virtual from TGCompositeFrame.
392 
394 {
396  if (el)
397  {
398  // hide real frame
399  el->fState = 0;
400  el->fFrame->UnmapWindow();
401 
402  // hide splitter
403  if (fUseSplitters)
404  {
405  el->fSplitFE->fFrame->UnmapWindow();
406  el->fSplitFE->fState = 0;
407  }
408 
409  // Dump();
410  fNVisible--;
411  fWeightSum -= el->fWeight;
412 
415  Layout();
416  }
417 }
418 
419 //------------------------------------------------------------------------------
420 
421 ////////////////////////////////////////////////////////////////////////////////
422 /// Virtual method of TGcompositeFrame.
423 /// Map all sub windows that are part of the composite frame.
424 
426 {
427  if (!fMapSubwindows) {
428  return;
429  }
430 
431  if (!fList) return;
432 
433  TGFrameElement *el;
434  TIter next(fList);
435 
436  while ((el = (TGFrameElement *) next())) {
437  if (el->fFrame && el->fState) {
438  el->fFrame->MapWindow();
439  el->fFrame->MapSubwindows();
441  if (fe) fe->fState |= kIsVisible;
442  }
443  }
444 }
445 
446 ////////////////////////////////////////////////////////////////////////////////
447 /// Resize the pack.
448 /// Contents is resized proportionally.
449 
451 {
452  if (w == fWidth && h == fHeight) return;
453 
454  fWidth = w;
455  fHeight = h;
457 
459 
460  Layout();
461 }
462 
463 ////////////////////////////////////////////////////////////////////////////////
464 /// Move and resize the pack.
465 
467 {
469  Resize(w, h);
470 }
471 
472 ////////////////////////////////////////////////////////////////////////////////
473 /// Reposition the frames so that they fit correctly.
474 /// LayoutHints are ignored.
475 
477 {
478  Int_t pos = 0;
479 
480  TGFrameElement *el;
481  TIter next(fList);
482 
483  while ((el = (TGFrameElement *) next()))
484  {
485  if (el->fState)
486  {
487  SetFramePosition(el->fFrame, pos);
488  pos += GetFrameLength(el->fFrame);
489  el->fFrame->Layout();
490  }
491  }
492 }
493 
494 ////////////////////////////////////////////////////////////////////////////////
495 /// Refit existing frames so that their lengths are equal.
496 
498 {
499  if (fList->IsEmpty())
500  return;
501 
502  fWeightSum = 0;
503  TGFrameElementPack *el;
504  TIter next(fList);
505  while ((el = (TGFrameElementPack *) next()))
506  {
507  el->fWeight = 1;
508  if (el->fState)
509  fWeightSum ++;
510  }
511 
513  Layout();
514 }
515 
516 ////////////////////////////////////////////////////////////////////////////////
517 /// Called when splitter drag starts.
518 
520 {
521  fDragOverflow = 0;
522 }
523 
524 ////////////////////////////////////////////////////////////////////////////////
525 /// Handle resize events from splitters.
526 
528 {
529  Int_t available = GetAvailableLength();
530  Int_t min_dec = - (available + fNVisible*2 -1);
531  if (delta < min_dec)
532  delta = min_dec;
533 
534  TGSplitter *s = dynamic_cast<TGSplitter*>((TGFrame*) gTQSender);
535 
536  TGFrameElementPack *f0=0, *f1=0;
537  FindFrames(s, f0, f1);
538 
539  if (fDragOverflow < 0)
540  {
541  fDragOverflow += delta;
542  if (fDragOverflow > 0) {
543  delta = fDragOverflow;
544  fDragOverflow = 0;
545  } else {
546  return;
547  }
548  }
549  else if (fDragOverflow > 0)
550  {
551  fDragOverflow += delta;
552  if (fDragOverflow < 0) {
553  delta = fDragOverflow;
554  fDragOverflow = 0;
555  } else {
556  return;
557  }
558  }
559 
560  Int_t l0 = GetFrameLength(f0->fFrame);
561  Int_t l1 = GetFrameLength(f1->fFrame);
562  if (delta < 0)
563  {
564  if (l0 - 1 < -delta)
565  {
566  fDragOverflow += delta + l0 - 1;
567  delta = -l0 + 1;
568  }
569  }
570  else
571  {
572  if (l1 - 1 < delta)
573  {
574  fDragOverflow += delta - l1 + 1;
575  delta = l1 - 1;
576  }
577  }
578  l0 += delta;
579  l1 -= delta;
580  SetFrameLength(f0->fFrame, l0);
581  SetFrameLength(f1->fFrame, l1);
582  Float_t weightDelta = Float_t(delta)/available;
583  weightDelta *= fWeightSum;
584  f0->fWeight += weightDelta;
585  f1->fWeight -= weightDelta;
586 
588  Layout();
589 }
590 
591 //------------------------------------------------------------------------------
592 
593 ////////////////////////////////////////////////////////////////////////////////
594 /// Sets the vertical flag and reformats the back to new stacking
595 /// direction.
596 
598 {
599  if (x == fVertical)
600  return;
601 
602  TList list;
603  while ( ! fList->IsEmpty())
604  {
605  TGFrameElement *el = (TGFrameElement*) fList->At(1);
606  TGFrame *f = el->fFrame;
607  if ( ! (el->fState & kIsVisible) )
608  f->SetBit(kTempFrame);
610  list.Add(f);
611  }
612  fVertical = x;
613  while ( ! list.IsEmpty())
614  {
615  TGFrame* f = (TGFrame*) list.First();
616  AddFrameInternal(f);
617  if (f->TestBit(kTempFrame)) {
618  f->ResetBit(kTempFrame);
619  HideFrame(f);
620  }
621  list.RemoveFirst();
622  }
623  Layout();
624 }
Float_t fWeightSum
Definition: TGPack.h:52
virtual void HideFrame(TGFrame *f)
Hide sub frame.
Definition: TGPack.cxx:393
virtual void Resize(UInt_t w=0, UInt_t h=0)
Resize the frame.
Definition: TGFrame.cxx:587
Int_t fSplitterLen
Definition: TGPack.h:48
virtual void MapSubwindows()
Definition: TGFrame.h:247
TGFrameElementPack * fSplitFE
Definition: TGPack.h:29
virtual void MoveResize(Int_t x, Int_t y, UInt_t w=0, UInt_t h=0)
Move and resize the pack.
Definition: TGPack.cxx:466
T1 Sign(T1 a, T2 b)
Definition: TMathBase.h:153
Int_t fDragOverflow
Definition: TGPack.h:50
float Float_t
Definition: RtypesCore.h:53
virtual void Dump() const
Print sub frame info.
Definition: TGPack.cxx:345
R__EXTERN void * gTQSender
Definition: TQObject.h:45
void CheckSplitterVisibility()
Check if splitter of first visible frame is hidden.
Definition: TGPack.cxx:105
void ResizeExistingFrames()
Resize (shrink or expand) existing frames by amount in total.
Definition: TGPack.cxx:138
REAL splitter
Definition: triangle.c:616
UInt_t GetHeight() const
Definition: TGFrame.h:272
TH1 * h
Definition: legend2.C:5
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
int Int_t
Definition: RtypesCore.h:41
virtual ~TGPack()
Destructor.
Definition: TGPack.cxx:62
bool Bool_t
Definition: RtypesCore.h:59
UInt_t GetWidth() const
Definition: TGFrame.h:271
Int_t fState
Definition: TGLayout.h:120
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
virtual void RemoveFrame(TGFrame *f)
Remove frame from composite frame.
Definition: TGFrame.cxx:1131
TGPack(const TGPack &)
Int_t GetFrameLength(const TGFrame *f) const
Definition: TGPack.h:55
void FindFrames(TGFrame *splitter, TGFrameElementPack *&f0, TGFrameElementPack *&f1) const
Find frames around splitter and return them f0 (previous) and f1 (next).
Definition: TGPack.cxx:207
Double_t x[n]
Definition: legend1.C:17
ULong_t Pixel_t
Definition: GuiTypes.h:39
void EqualizeFrames()
Refit existing frames so that their lengths are equal.
Definition: TGPack.cxx:497
Definition: TGPack.h:39
virtual void ReparentWindow(const TGWindow *p, Int_t x=0, Int_t y=0)
Reparent window, make p the new parent and position the window at position (x,y) in new parent...
Definition: TGFrame.h:249
virtual void Layout()
Definition: TGFrame.h:246
void HandleSplitterResize(Int_t delta)
Handle resize events from splitters.
Definition: TGPack.cxx:527
void SetVertical(Bool_t x)
Sets the vertical flag and reformats the back to new stacking direction.
Definition: TGPack.cxx:597
Bool_t fUseSplitters
Definition: TGPack.h:47
Bool_t fMapSubwindows
Definition: TGFrame.h:354
A doubly linked list.
Definition: TList.h:44
virtual void DeleteFrame(TGFrame *f)
Remove frame f and refit existing frames to pack size.
Definition: TGPack.cxx:325
Bool_t fVertical
Definition: TGPack.h:46
Bool_t Connect(const char *signal, const char *receiver_class, void *receiver, const char *slot)
Non-static method is used to connect from the signal of this object to the receiver slot...
Definition: TQObject.cxx:867
virtual void Resize(UInt_t w, UInt_t h)
Resize the window.
Definition: TGWindow.cxx:164
void RefitFramesToPack()
Refit existing frames to pack size.
Definition: TGPack.cxx:190
TList * fList
Definition: TGFrame.h:351
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:655
virtual void Resize(UInt_t w=0, UInt_t h=0)
Resize the pack.
Definition: TGPack.cxx:450
virtual const char * GetName() const
Return unique name, used in SavePrimitive methods.
Definition: TGWindow.cxx:221
static TGLayoutHints * fgDefaultHints
Definition: TGFrame.h:356
unsigned int UInt_t
Definition: RtypesCore.h:42
TGFrame * fFrame
Definition: TGLayout.h:119
virtual void RemoveFrame(TGFrame *f)
Remove frame f and refit existing frames to pack size.
Definition: TGPack.cxx:336
virtual TObject * At(Int_t idx) const
Returns the object at position idx. Returns 0 if idx is out of range.
Definition: TList.cxx:354
Int_t fMustCleanup
Definition: TGFrame.h:353
UInt_t fWidth
Definition: TGFrame.h:134
virtual void ShowFrame(TGFrame *f)
Show sub frame.
Definition: TGPack.cxx:363
virtual void Move(Int_t x, Int_t y)
Move frame.
Definition: TGFrame.cxx:575
virtual void Layout()
Reposition the frames so that they fit correctly.
Definition: TGPack.cxx:476
virtual void AddFrame(TGFrame *f, TGLayoutHints *l=0)
Add frame f at the end with default weight.
Definition: TGPack.cxx:285
virtual Bool_t IsEmpty() const
Definition: TCollection.h:184
void SetFramePosition(TGFrame *f, Int_t pos)
Set pack-wise position of frame f.
Definition: TGPack.cxx:93
#define ClassImp(name)
Definition: Rtypes.h:359
virtual void SetCleanup(Int_t mode=kLocalCleanup)
Turn on automatic cleanup of child frames in dtor.
Definition: TGFrame.cxx:1054
Double_t y[n]
Definition: legend1.C:17
static constexpr double s
virtual void SetCleanup(Int_t=kLocalCleanup)
Definition: TGFrame.h:264
UInt_t fHeight
Definition: TGFrame.h:135
Handle_t Window_t
Definition: GuiTypes.h:28
virtual void UnmapWindow()
Definition: TGFrame.h:253
virtual TGFrameElement * FindFrameElement(TGFrame *f) const
Find frame-element holding frame f.
Definition: TGFrame.cxx:1076
void AddFrameInternal(TGFrame *f, TGLayoutHints *l=0, Float_t weight=1)
Add frame f at the end.
Definition: TGPack.cxx:231
void HandleSplitterStart()
Called when splitter drag starts.
Definition: TGPack.cxx:519
virtual void Add(TObject *obj)
Definition: TList.h:87
auto * l
Definition: textangle.C:4
Float_t fWeight
Definition: TGPack.h:28
virtual void MapWindow()
Definition: TGFrame.h:251
TGClient * fClient
Definition: TGObject.h:37
void RemoveFrameInternal(TGFrame *f)
Remove frame f.
Definition: TGPack.cxx:294
virtual void MapSubwindows()
Virtual method of TGcompositeFrame.
Definition: TGPack.cxx:425
const TGWindow * GetDefaultRoot() const
Returns the root (i.e.
Definition: TGClient.cxx:232
TF1 * f1
Definition: legend1.C:11
TGFrameElement * GetFrameElement() const
Definition: TGFrame.h:282
virtual void AddFrameWithWeight(TGFrame *f, TGLayoutHints *l, Float_t w)
Add frame f at the end with given weight.
Definition: TGPack.cxx:275
void SetFrameLength(TGFrame *f, Int_t len)
Set pack-wise length of frame f.
Definition: TGPack.cxx:82
void ResetBit(UInt_t f)
Definition: TObject.h:171
Int_t fNVisible
Definition: TGPack.h:53
const Bool_t kTRUE
Definition: RtypesCore.h:87
Int_t Nint(T x)
Definition: TMath.h:606
const char * cnt
Definition: TXMLSetup.cxx:74
Int_t GetAvailableLength() const
Return length of entire frame without splitters.
Definition: TGPack.cxx:71
virtual void RemoveFirst()