Logo ROOT   6.16/01
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
32TGPack::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
48 TGCompositeFrame(c, id, parent),
49 fVertical (kTRUE),
50 fUseSplitters (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{
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;
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 {
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);
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{
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
249 s->SetCleanup(kDeepCleanup);
250 s->MapWindow();
251 }
252
253 // instread TGCopositeFrame::AddFrame
255 el->fSplitFE = sf;
256 fList->Add(el);
257
258 // in case of recusive cleanup, propagate cleanup setting to all
259 // child composite frames
261 f->SetCleanup(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
345void TGPack::Dump() const
346{
347 printf("--------------------------------------------------------------\n");
348 Int_t cnt = 0;
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 {
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;
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 {
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();
617 if (f->TestBit(kTempFrame)) {
618 f->ResetBit(kTempFrame);
619 HideFrame(f);
620 }
621 list.RemoveFirst();
622 }
623 Layout();
624}
ULong_t Pixel_t
Definition: GuiTypes.h:39
Handle_t Window_t
Definition: GuiTypes.h:28
#define f(i)
Definition: RSha256.hxx:104
#define c(i)
Definition: RSha256.hxx:101
#define h(i)
Definition: RSha256.hxx:106
int Int_t
Definition: RtypesCore.h:41
unsigned int UInt_t
Definition: RtypesCore.h:42
bool Bool_t
Definition: RtypesCore.h:59
float Float_t
Definition: RtypesCore.h:53
const Bool_t kTRUE
Definition: RtypesCore.h:87
#define ClassImp(name)
Definition: Rtypes.h:363
@ kLocalCleanup
Definition: TGFrame.h:50
@ kDeepCleanup
Definition: TGFrame.h:51
@ kIsVisible
Definition: TGFrame.h:42
@ kTempFrame
Definition: TGFrame.h:71
R__EXTERN void * gTQSender
Definition: TQObject.h:45
virtual Bool_t IsEmpty() const
Definition: TCollection.h:186
const TGWindow * GetDefaultRoot() const
Returns the root (i.e.
Definition: TGClient.cxx:234
virtual TGFrameElement * FindFrameElement(TGFrame *f) const
Find frame-element holding frame f.
Definition: TGFrame.cxx:1076
Int_t fMustCleanup
Definition: TGFrame.h:353
virtual void SetCleanup(Int_t mode=kLocalCleanup)
Turn on automatic cleanup of child frames in dtor.
Definition: TGFrame.cxx:1054
Bool_t fMapSubwindows
Definition: TGFrame.h:354
TList * fList
Definition: TGFrame.h:351
virtual void RemoveFrame(TGFrame *f)
Remove frame from composite frame.
Definition: TGFrame.cxx:1131
static TGLayoutHints * fgDefaultHints
Definition: TGFrame.h:356
Float_t fWeight
Definition: TGPack.h:28
TGFrameElementPack * fSplitFE
Definition: TGPack.h:29
Int_t fState
Definition: TGLayout.h:120
TGFrame * fFrame
Definition: TGLayout.h:119
UInt_t fHeight
Definition: TGFrame.h:135
TGFrameElement * GetFrameElement() const
Definition: TGFrame.h:282
virtual void Move(Int_t x, Int_t y)
Move frame.
Definition: TGFrame.cxx:575
virtual void Resize(UInt_t w=0, UInt_t h=0)
Resize the frame.
Definition: TGFrame.cxx:587
UInt_t fWidth
Definition: TGFrame.h:134
UInt_t GetHeight() const
Definition: TGFrame.h:272
virtual void Layout()
Definition: TGFrame.h:246
virtual void MapWindow()
Definition: TGFrame.h:251
UInt_t GetWidth() const
Definition: TGFrame.h:271
virtual void MapSubwindows()
Definition: TGFrame.h:247
virtual void UnmapWindow()
Definition: TGFrame.h:253
TGClient * fClient
Definition: TGObject.h:37
Definition: TGPack.h:40
Bool_t fVertical
Definition: TGPack.h:46
virtual void RemoveFrame(TGFrame *f)
Remove frame f and refit existing frames to pack size.
Definition: TGPack.cxx:336
void RemoveFrameInternal(TGFrame *f)
Remove frame f.
Definition: TGPack.cxx:294
virtual ~TGPack()
Destructor.
Definition: TGPack.cxx:62
void ResizeExistingFrames()
Resize (shrink or expand) existing frames by amount in total.
Definition: TGPack.cxx:138
virtual void Resize(UInt_t w=0, UInt_t h=0)
Resize the pack.
Definition: TGPack.cxx:450
Int_t GetAvailableLength() const
Return length of entire frame without splitters.
Definition: TGPack.cxx:71
TGPack(const TGPack &)
Int_t fSplitterLen
Definition: TGPack.h:48
virtual void DeleteFrame(TGFrame *f)
Remove frame f and refit existing frames to pack size.
Definition: TGPack.cxx:325
Int_t GetFrameLength(const TGFrame *f) const
Definition: TGPack.h:55
virtual void AddFrameWithWeight(TGFrame *f, TGLayoutHints *l, Float_t w)
Add frame f at the end with given weight.
Definition: TGPack.cxx:275
virtual void ShowFrame(TGFrame *f)
Show sub frame.
Definition: TGPack.cxx:363
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
void RefitFramesToPack()
Refit existing frames to pack size.
Definition: TGPack.cxx:190
void AddFrameInternal(TGFrame *f, TGLayoutHints *l=0, Float_t weight=1)
Add frame f at the end.
Definition: TGPack.cxx:231
virtual void HideFrame(TGFrame *f)
Hide sub frame.
Definition: TGPack.cxx:393
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
void EqualizeFrames()
Refit existing frames so that their lengths are equal.
Definition: TGPack.cxx:497
void HandleSplitterStart()
Called when splitter drag starts.
Definition: TGPack.cxx:519
Float_t fWeightSum
Definition: TGPack.h:52
virtual void MapSubwindows()
Virtual method of TGcompositeFrame.
Definition: TGPack.cxx:425
Bool_t fUseSplitters
Definition: TGPack.h:47
void SetVertical(Bool_t x)
Sets the vertical flag and reformats the back to new stacking direction.
Definition: TGPack.cxx:597
void HandleSplitterResize(Int_t delta)
Handle resize events from splitters.
Definition: TGPack.cxx:527
void SetFrameLength(TGFrame *f, Int_t len)
Set pack-wise length of frame f.
Definition: TGPack.cxx:82
void SetFramePosition(TGFrame *f, Int_t pos)
Set pack-wise position of frame f.
Definition: TGPack.cxx:93
void CheckSplitterVisibility()
Check if splitter of first visible frame is hidden.
Definition: TGPack.cxx:105
Int_t fNVisible
Definition: TGPack.h:53
Int_t fDragOverflow
Definition: TGPack.h:50
virtual void Dump() const
Print sub frame info.
Definition: TGPack.cxx:345
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
virtual const char * GetName() const
Return unique name, used in SavePrimitive methods.
Definition: TGWindow.cxx:221
virtual void Resize(UInt_t w, UInt_t h)
Resize the window.
Definition: TGWindow.cxx:164
A doubly linked list.
Definition: TList.h:44
virtual void Add(TObject *obj)
Definition: TList.h:87
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
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:655
virtual void RemoveFirst()
Double_t y[n]
Definition: legend1.C:17
Double_t x[n]
Definition: legend1.C:17
TF1 * f1
Definition: legend1.C:11
static constexpr double s
Int_t Nint(T x)
Round to nearest integer. Rounds half integers to the nearest even integer.
Definition: TMath.h:701
T1 Sign(T1 a, T2 b)
Definition: TMathBase.h:165
const char * cnt
Definition: TXMLSetup.cxx:74
auto * l
Definition: textangle.C:4
REAL splitter
Definition: triangle.c:616