Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGListBox.cxx
Go to the documentation of this file.
1 // @(#)root/gui:$Id$
2 // Author: Fons Rademakers 12/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 // TGListBox, TGLBContainer, TGLBEntry and TGTextLBEntry //
26 // //
27 // A listbox is a box, possibly with scrollbar, containing entries. //
28 // Currently entries are simple text strings (TGTextLBEntry). //
29 // A TGListBox looks a lot like a TGCanvas. It has a TGViewPort //
30 // containing a TGLBContainer which contains the entries and it also //
31 // has a vertical scrollbar which becomes visible if there are more //
32 // items than fit in the visible part of the container. //
33 // //
34 // The TGListBox is user callable. The other classes are service //
35 // classes of the listbox. //
36 // //
37 // Selecting an item in the listbox will generate the event: //
38 // kC_COMMAND, kCM_LISTBOX, listbox id, item id. //
39 // //
40 //////////////////////////////////////////////////////////////////////////
41 
42 #include "TGPicture.h"
43 #include "TGListBox.h"
44 #include "TGScrollBar.h"
45 #include "TGResourcePool.h"
46 #include "TSystem.h"
47 #include "Riostream.h"
48 #include "TMath.h"
49 #include <stdlib.h>
50 
51 
52 const TGFont *TGTextLBEntry::fgDefaultFont = 0;
53 TGGC *TGTextLBEntry::fgDefaultGC = 0;
54 
55 ClassImp(TGLBEntry);
56 ClassImp(TGTextLBEntry);
57 ClassImp(TGLineLBEntry);
58 ClassImp(TGLBContainer);
59 ClassImp(TGListBox);
60 
61 ////////////////////////////////////////////////////////////////////////////////
62 /// Base class entry constructor.
63 
64 TGLBEntry::TGLBEntry(const TGWindow *p, Int_t id, UInt_t options, Pixel_t back) :
65  TGFrame(p, 10, 10, options | kOwnBackground, back)
66 {
67  fActive = kFALSE;
68  fEntryId = id;
69  fBkcolor = back;
70  fEditDisabled = kEditDisable | kEditDisableGrab;
71 
72  SetWindowName();
73 }
74 
75 ////////////////////////////////////////////////////////////////////////////////
76 /// Toggle active state of listbox entry.
77 
78 void TGLBEntry::Activate(Bool_t a)
79 {
80  if (fActive == a) return;
81  fActive = a;
82  DoRedraw();
83 }
84 
85 ////////////////////////////////////////////////////////////////////////////////
86 /// Toggle active state of listbox entry.
87 
88 void TGLBEntry::Toggle()
89 {
90  fActive = !fActive;
91  DoRedraw();
92 }
93 
94 
95 //////////////////////////////////////////////////////////////////////////
96 // //
97 // TGTextLBEntry //
98 // //
99 // Text string listbox entries. //
100 // A TGTextLBEntry is for TGListBox internal use. //
101 // //
102 //////////////////////////////////////////////////////////////////////////
103 
104 ////////////////////////////////////////////////////////////////////////////////
105 /// Create a text listbox entry. The TGString is adopted.
106 
107 TGTextLBEntry::TGTextLBEntry(const TGWindow *p, TGString *s, Int_t id,
108  GContext_t norm, FontStruct_t font, UInt_t options, ULong_t back) :
109  TGLBEntry(p, id, options, back)
110 {
111  fText = s;
112  fTextChanged = kTRUE;
113  fFontStruct = font;
114  fNormGC = norm;
115  fTWidth = 0;
116 
117  int max_ascent, max_descent;
118 
119  if (fText) fTWidth = gVirtualX->TextWidth(fFontStruct, fText->GetString(), fText->GetLength());
120  gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
121  fTHeight = max_ascent + max_descent;
122  Resize(fTWidth, fTHeight + 1);
123  fEditDisabled = kEditDisable | kEditDisableGrab;
124  SetWindowName();
125 }
126 
127 ////////////////////////////////////////////////////////////////////////////////
128 /// Delete text listbox entry.
129 
130 TGTextLBEntry::~TGTextLBEntry()
131 {
132  if (fText) delete fText;
133 }
134 
135 ////////////////////////////////////////////////////////////////////////////////
136 /// Draw text listbox entry on window/pixmap.
137 
138 void TGTextLBEntry::DrawCopy(Handle_t id, Int_t x, Int_t y)
139 {
140  int max_ascent, max_descent;
141 
142  y += (fHeight - fTHeight) >> 1;
143 
144  gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
145 
146  if (fActive) {
147  gVirtualX->SetForeground(fNormGC, fgDefaultSelectedBackground );
148  gVirtualX->FillRectangle(id,fNormGC, x, y, fWidth, fHeight);
149  gVirtualX->SetForeground(fNormGC, fClient->GetResourcePool()->GetSelectedFgndColor());
150  fText->Draw(id, fNormGC, x + 3, y + max_ascent);
151  } else {
152  gVirtualX->SetForeground(fNormGC, fBkcolor);
153  gVirtualX->FillRectangle(id, fNormGC, x, y, fWidth, fHeight);
154  gVirtualX->SetForeground(fNormGC, GetForeground());
155  fText->Draw(id, fNormGC, x + 3, y + max_ascent);
156  }
157 }
158 
159 ////////////////////////////////////////////////////////////////////////////////
160 /// Redraw text listbox entry.
161 
162 void TGTextLBEntry::DoRedraw()
163 {
164  if (fId) DrawCopy(fId, 0, 0);
165 }
166 
167 ////////////////////////////////////////////////////////////////////////////////
168 /// Set or change text in text entry.
169 
170 void TGTextLBEntry::SetText(TGString *new_text)
171 {
172  if (fText) delete fText;
173  fText = new_text;
174  fTextChanged = kTRUE;
175 
176  int max_ascent, max_descent;
177  fTWidth = gVirtualX->TextWidth(fFontStruct, fText->GetString(), fText->GetLength());
178  gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
179  fTHeight = max_ascent + max_descent;
180 
181  Resize(fTWidth + 3, fTHeight + 1);
182 
183  DoRedraw();
184 }
185 
186 ////////////////////////////////////////////////////////////////////////////////
187 /// Return default font structure in use for a text listbox entry.
188 
189 FontStruct_t TGTextLBEntry::GetDefaultFontStruct()
190 {
191  if (!fgDefaultFont)
192  fgDefaultFont = gClient->GetResourcePool()->GetDefaultFont();
193  return fgDefaultFont->GetFontStruct();
194 }
195 
196 ////////////////////////////////////////////////////////////////////////////////
197 /// Return default graphics context in use for a text listbox entry.
198 
199 const TGGC &TGTextLBEntry::GetDefaultGC()
200 {
201  if (!fgDefaultGC)
202  fgDefaultGC = new TGGC(*gClient->GetResourcePool()->GetFrameGC());
203  return *fgDefaultGC;
204 }
205 
206 //////////////////////////////////////////////////////////////////////////
207 // //
208 // TGLineLBEntry //
209 // //
210 // Line style and width listbox entries. //
211 // //
212 //////////////////////////////////////////////////////////////////////////
213 
214 ////////////////////////////////////////////////////////////////////////////////
215 /// Create the line style listbox entry.
216 
217 TGLineLBEntry::TGLineLBEntry(const TGWindow *p, Int_t id, const char *str,
218  UInt_t w, Style_t style, UInt_t options, ULong_t back) :
219  TGTextLBEntry(p, new TGString(str), id, GetDefaultGC()(),
220  GetDefaultFontStruct(), options, back)
221 {
222  GCValues_t gcv;
223 
224  gcv.fMask = kGCLineStyle | kGCLineWidth | kGCFillStyle | kGCDashList;
225  fLineWidth = gcv.fLineWidth = w;
226  gcv.fFillStyle = kFillSolid;
227  gcv.fDashLen = 2;
228  gcv.fDashOffset = 0;
229  memcpy(gcv.fDashes, "\x5\x5", 3);
230  gcv.fLineStyle = kLineOnOffDash;
231  fLineGC = fClient->GetGC(&gcv, kTRUE);
232  SetLineStyle(style);
233 
234  int max_ascent, max_descent;
235 
236  fTWidth = gVirtualX->TextWidth(GetDefaultFontStruct(), "8", 1);
237  fTWidth += 15; // for drawing
238  gVirtualX->GetFontProperties(GetDefaultFontStruct(),
239  max_ascent, max_descent);
240  fTHeight = max_ascent + max_descent;
241  fLineLength = 0;
242 
243  Resize(fTWidth, fTHeight + 1);
244  fEditDisabled = kEditDisable | kEditDisableGrab;
245  SetWindowName();
246 }
247 
248 ////////////////////////////////////////////////////////////////////////////////
249 /// Delete line style listbox entry.
250 
251 TGLineLBEntry::~TGLineLBEntry()
252 {
253  fClient->FreeGC(fLineGC);
254 }
255 
256 ////////////////////////////////////////////////////////////////////////////////
257 /// Update line style listbox entry.
258 
259 void TGLineLBEntry::Update(TGLBEntry *e)
260 {
261  TGTextLBEntry::Update(e);
262 
263  fClient->FreeGC(fLineGC);
264  fLineGC = ((TGLineLBEntry *)e)->GetLineGC();
265  fLineGC->AddReference();
266 }
267 
268 ////////////////////////////////////////////////////////////////////////////////
269 /// Set the line style corresponding to the TPad line styles.
270 
271 void TGLineLBEntry::SetLineStyle(Style_t linestyle)
272 {
273  static const char* dashed = "\x3\x3";
274  static const char* dotted= "\x1\x2";
275  static const char* dasheddotted = "\x3\x4\x1\x4";
276  static const char* ls05 = "\x5\x3\x1\x3";
277  static const char* ls06 = "\x5\x3\x1\x3\x1\x3\x1\x3";
278  static const char* ls07 = "\x5\x5";
279  static const char* ls08 = "\x5\x3\x1\x3\x1\x3";
280  static const char* ls09 = "\x20\x5";
281  static const char* ls10 = "\x20\x10\x1\x10";
282 
283 
284  if (linestyle <= 1) {
285  fLineGC->SetLineStyle(kLineSolid);
286  } else {
287  switch (linestyle) {
288  case 2:
289  fLineGC->SetDashList(dashed, 2);
290  break;
291  case 3:
292  fLineGC->SetDashList(dotted, 2);
293  break;
294  case 4:
295  fLineGC->SetDashList(dasheddotted, 4);
296  break;
297  case 5:
298  fLineGC->SetDashList(ls05, 4);
299  break;
300  case 6:
301  fLineGC->SetDashList(ls06, 8);
302  break;
303  case 7:
304  fLineGC->SetDashList(ls07, 2);
305  break;
306  case 8:
307  fLineGC->SetDashList(ls08, 6);
308  break;
309  case 9:
310  fLineGC->SetDashList(ls09, 2);
311  break;
312  case 10:
313  fLineGC->SetDashList(ls10, 4);
314  break;
315  }
316  }
317  fLineGC->SetCapStyle(0); // flat cap
318  fLineStyle = linestyle;
319 }
320 
321 ////////////////////////////////////////////////////////////////////////////////
322 /// Set or change line witdh in an entry.
323 
324 void TGLineLBEntry::SetLineWidth(Int_t width)
325 {
326  fLineWidth = width;
327  fLineGC->SetLineWidth(fLineWidth);
328 }
329 
330 ////////////////////////////////////////////////////////////////////////////////
331 /// Draw copy on window/pixmap.
332 
333 void TGLineLBEntry::DrawCopy(Handle_t id, Int_t x, Int_t y)
334 {
335  TGTextLBEntry::DrawCopy(id, x, y);
336  if (!strcmp(TGTextLBEntry::GetTitle(),"None")) return;
337  if (fActive) {
338  gVirtualX->SetForeground(fLineGC->GetGC(),
339  fClient->GetResourcePool()->GetSelectedFgndColor());
340  } else {
341  gVirtualX->SetForeground(fLineGC->GetGC(),
342  fClient->GetResourcePool()->GetBlackColor());
343  }
344  gVirtualX->DrawLine(id, fLineGC->GetGC(), x + fTWidth + 5, y + fHeight/2,
345  x + fWidth - 5, y + fHeight/2);
346 }
347 
348 ////////////////////////////////////////////////////////////////////////////////
349 /// Redraw line style listbox entry.
350 
351 void TGLineLBEntry::DoRedraw()
352 {
353  if (fId) DrawCopy(fId, 0, 0);
354 }
355 
356 //////////////////////////////////////////////////////////////////////////
357 // //
358 // TGIconLBEntry //
359 // //
360 // Icon + text listbox entry. //
361 // //
362 //////////////////////////////////////////////////////////////////////////
363 
364 ////////////////////////////////////////////////////////////////////////////////
365 /// Create the icon & text listbox entry.
366 
367 TGIconLBEntry::TGIconLBEntry(const TGWindow *p, Int_t id, const char *str,
368  const TGPicture *pic,
369  UInt_t /*w*/, Style_t /*style*/, UInt_t options, ULong_t back) :
370  TGTextLBEntry(p, new TGString(str), id, GetDefaultGC()(),
371  GetDefaultFontStruct(), options, back)
372 {
373  int max_ascent, max_descent;
374 
375  fPicture = pic;
376  if (fPicture) {
377  fTWidth += fPicture->GetWidth() + 4;
378  ((TGPicture *)fPicture)->AddReference();
379  }
380  else
381  fTWidth += 20;
382  gVirtualX->GetFontProperties(GetDefaultFontStruct(),
383  max_ascent, max_descent);
384  fTHeight = max_ascent + max_descent;
385  if (fPicture && fPicture->GetHeight() > fTHeight)
386  fTHeight = fPicture->GetHeight();
387 
388  Resize(fTWidth, fTHeight + 1);
389  fEditDisabled = kEditDisable | kEditDisableGrab;
390  SetWindowName();
391 }
392 
393 ////////////////////////////////////////////////////////////////////////////////
394 /// Delete icon & text listbox entry.
395 
396 TGIconLBEntry::~TGIconLBEntry()
397 {
398  fClient->FreePicture(fPicture);
399 }
400 
401 ////////////////////////////////////////////////////////////////////////////////
402 /// Update icon & text listbox entry.
403 
404 void TGIconLBEntry::Update(TGLBEntry *e)
405 {
406  TGTextLBEntry::Update(e);
407 }
408 
409 ////////////////////////////////////////////////////////////////////////////////
410 /// Draw copy on window/pixmap.
411 
412 void TGIconLBEntry::DrawCopy(Handle_t id, Int_t x, Int_t y)
413 {
414  Int_t off_x = 0;
415  if (fPicture) {
416  fPicture->Draw(id, fNormGC, x + 2, y);
417  off_x = fPicture->GetWidth() + 4;
418  }
419  TGTextLBEntry::DrawCopy(id, x + off_x, y);
420 }
421 
422 ////////////////////////////////////////////////////////////////////////////////
423 /// Redraw icon & text listbox entry.
424 
425 void TGIconLBEntry::DoRedraw()
426 {
427  if (fId) DrawCopy(fId, 0, 0);
428 }
429 
430 ////////////////////////////////////////////////////////////////////////////////
431 /// Change the icon of listbox entry containing icon & text.
432 
433 void TGIconLBEntry::SetPicture(const TGPicture *pic)
434 {
435  fClient->FreePicture(fPicture);
436 
437  if (pic) ((TGPicture *)pic)->AddReference();
438 
439  fPicture = pic;
440 }
441 
442 /////////////////////////////////////////////////////////////////////////////////
443 class TGLBFrameElement : public TGFrameElement {
444 public:
445  TGLBFrameElement(TGFrame *f, TGLayoutHints *l) : TGFrameElement(f, l) {}
446  virtual ~TGLBFrameElement() {}
447 
448  Bool_t IsSortable() const { return kTRUE; }
449  Int_t Compare(const TObject *obj) const {
450  if (!fFrame->InheritsFrom(TGTextLBEntry::Class())) {
451  return 0;
452  }
453  TGTextLBEntry *f1 = (TGTextLBEntry*)fFrame;
454  TGTextLBEntry *f2 = (TGTextLBEntry *) ((TGFrameElement *) obj)->fFrame;
455 
456 
457  double d1, d2;
458  const char *t1 = f1->GetText()->Data();
459  const char *t2 = f2->GetText()->Data();
460 
461  if ((d1 = atof(t1)) && (d2 = atof(t2))) {
462  return (d1 > d2);
463  } else {
464  return strcmp(t1, t2);
465  }
466  return 0;
467  }
468 };
469 
470 //////////////////////////////////////////////////////////////////////////
471 // //
472 // TGLBContainer //
473 // //
474 // A Composite frame that contains a list of TGLBEnties. //
475 // A TGLBContainer is for TGListBox internal use. //
476 // //
477 //////////////////////////////////////////////////////////////////////////
478 
479 ////////////////////////////////////////////////////////////////////////////////
480 /// Create a listbox container.
481 
482 TGLBContainer::TGLBContainer(const TGWindow *p, UInt_t w, UInt_t h,
483  UInt_t options, ULong_t back) :
484  TGContainer(p, w, h, options, back)
485 {
486  fLastActive = 0;
487  fMsgWindow = p;
488  fMultiSelect = kFALSE;
489  fChangeStatus = kFALSE;
490  fListBox = 0;
491 
492  SetWindowName();
493  fEditDisabled = kEditDisableGrab | kEditDisableBtnEnable | kEditDisableKeyEnable;
494 }
495 
496 ////////////////////////////////////////////////////////////////////////////////
497 /// Delete the listbox container.
498 
499 TGLBContainer::~TGLBContainer()
500 {
501  Cleanup();
502 }
503 
504 ////////////////////////////////////////////////////////////////////////////////
505 /// Layout container
506 
507 void TGLBContainer::Layout()
508 {
509  TGContainer::Layout();
510  TGFrame::Resize(fListBox->GetViewPort()->GetWidth(), fHeight);
511 }
512 
513 ////////////////////////////////////////////////////////////////////////////////
514 /// redraw
515 
516 void TGLBContainer::DoRedraw()
517 {
518  return TGContainer::DoRedraw();
519 }
520 
521 ////////////////////////////////////////////////////////////////////////////////
522 /// Add listbox entry with hints to container. To show entry call
523 /// MapSubwindows() and Layout().
524 
525 void TGLBContainer::AddEntry(TGLBEntry *lbe, TGLayoutHints *lhints)
526 {
527  // DEPRECATED: the color should always be set in the TGLBEntry ctor
528  //lbe->SetBackgroundColor(fgWhitePixel);
529 
530  TGLBFrameElement *nw = new TGLBFrameElement(lbe, lhints ? lhints : fgDefaultHints);
531  fList->Add(nw);
532  ClearViewPort();
533 }
534 
535 ////////////////////////////////////////////////////////////////////////////////
536 /// Insert listbox entry after specified entry with id afterID. If afterID = -1
537 /// then add entry at head of list. To show entry call MapSubwindows() and
538 /// Layout().
539 
540 void TGLBContainer::InsertEntry(TGLBEntry *lbe, TGLayoutHints *lhints, Int_t afterID)
541 {
542  // DEPRECATED: the color should always be set in the TGLBEntry ctor
543  //lbe->SetBackgroundColor(fgWhitePixel);
544 
545  TGLBEntry *e;
546  TGFrameElement *el, *nw;
547  TIter next(fList);
548 
549  while ((el = (TGFrameElement *) next())) {
550  e = (TGLBEntry *) el->fFrame;
551  if (e->EntryId() == afterID) break;
552  }
553 
554  if (!el && afterID != -1) {
555  nw = new TGLBFrameElement(lbe, lhints ? lhints : fgDefaultHints);
556  fList->Add(nw);
557  } else {
558  nw = new TGLBFrameElement(lbe, lhints);
559  nw->fFrame = lbe;
560  nw->fLayout = lhints;
561  nw->fState = 1;
562  //lbe->SetFrameElement(nw);
563 
564  if (afterID == -1)
565  fList->AddFirst(nw);
566  else
567  fList->AddAfter(el, nw);
568  }
569  ClearViewPort();
570 }
571 
572 ////////////////////////////////////////////////////////////////////////////////
573 /// Insert listbox entry before the list box entry with a higher id.
574 /// To show entry call MapSubwindows() and Layout().
575 
576 void TGLBContainer::AddEntrySort(TGLBEntry *lbe, TGLayoutHints *lhints)
577 {
578  // DEPRECATED: the color should always be set in the TGLBEntry ctor
579  //lbe->SetBackgroundColor(fgWhitePixel);
580 
581  TGLBEntry *e;
582  TGFrameElement *el, *nw;
583  TIter next(fList);
584 
585  while ((el = (TGFrameElement *) next())) {
586  e = (TGLBEntry *) el->fFrame;
587  if (e->EntryId() > lbe->EntryId()) break;
588  }
589 
590  if (!el) {
591  nw = new TGLBFrameElement(lbe, lhints ? lhints : fgDefaultHints);
592  fList->Add(nw);
593  } else {
594  nw = new TGLBFrameElement(lbe, lhints);
595  nw->fFrame = lbe;
596  nw->fLayout = lhints;
597  nw->fState = 1;
598  //lbe->SetFrameElement(nw);
599 
600  fList->AddBefore(el, nw);
601  }
602  ClearViewPort();
603 }
604 
605 ////////////////////////////////////////////////////////////////////////////////
606 /// Remove the entry with specified id from the listbox container.
607 /// To update the listbox call Layout().
608 
609 void TGLBContainer::RemoveEntry(Int_t id)
610 {
611  TGLBEntry *e;
612  TGFrameElement *el;
613  TGLayoutHints *l;
614 
615  TIter next(fList);
616 
617  while ((el = (TGFrameElement *) next())) {
618  e = (TGLBEntry *) el->fFrame;
619  l = el->fLayout;
620  if (e->EntryId() == id) {
621  if (fLastActive == e) fLastActive = 0;
622  e->DestroyWindow();
623  fList->Remove(el); // avoid calling RemoveFrame(e)
624  delete el; // item
625  delete e;
626  delete l;
627  break;
628  }
629  }
630  ClearViewPort();
631 }
632 
633 ////////////////////////////////////////////////////////////////////////////////
634 /// Remove entries from from_ID to to_ID (including).
635 /// To update the listbox call Layout().
636 
637 void TGLBContainer::RemoveEntries(Int_t from_ID, Int_t to_ID)
638 {
639  TGLBEntry *e;
640  TGFrameElement *el;
641  TGLayoutHints *l;
642 
643  TIter next(fList);
644 
645  while ((el = (TGFrameElement *) next())) {
646  e = (TGLBEntry *) el->fFrame;
647  l = el->fLayout;
648  if ((e->EntryId() >= from_ID) && (e->EntryId() <= to_ID)) {
649  if (fLastActive == e) fLastActive = 0;
650  e->DestroyWindow();
651  fList->Remove(el); // avoid calling RemoveFrame(e)
652  delete el; // idem
653  delete e;
654  delete l;
655  }
656  }
657  ClearViewPort();
658 }
659 
660 ////////////////////////////////////////////////////////////////////////////////
661 /// Remove all entries in this container.
662 
663 void TGLBContainer::RemoveAll()
664 {
665  TGLBEntry *e;
666  TGFrameElement *el;
667  TGLayoutHints *l;
668 
669  TIter next(fList);
670 
671  while ((el = (TGFrameElement *) next())) {
672  e = (TGLBEntry *) el->fFrame;
673  l = el->fLayout;
674  if (fLastActive == e) fLastActive = 0;
675  e->DestroyWindow();
676  fList->Remove(el); // avoid calling RemoveFrame(e)
677  delete el; // item
678  delete e;
679  delete l;
680  }
681  ClearViewPort();
682 }
683 
684 ////////////////////////////////////////////////////////////////////////////////
685 /// Select the entry with the specified id.
686 /// Returns the selected TGLBEntry.
687 
688 TGLBEntry *TGLBContainer::Select(Int_t id)
689 {
690  return Select(id, kTRUE);
691 }
692 
693 ////////////////////////////////////////////////////////////////////////////////
694 /// Select / deselect the entry with the specified id.
695 /// Returns the selected TGLBEntry.
696 
697 TGLBEntry *TGLBContainer::Select(Int_t id, Bool_t sel)
698 {
699  TGLBEntry *f;
700  TGFrameElement *el;
701 
702  if (!fMultiSelect && fLastActive) {
703  fLastActive->Activate(kFALSE);
704  fLastActive = 0;
705  }
706 
707  TIter next(fList);
708  while ((el = (TGFrameElement *) next())) {
709  f = (TGLBEntry *) el->fFrame;
710  if (f->EntryId() == id) {
711  f->Activate(sel);
712  if (fMultiSelect == kFALSE && sel == kTRUE) {
713  fLastActive = f;
714  fLastActiveEl = el;
715  }
716  ClearViewPort();
717  return f;
718  }
719  }
720 
721  return 0;
722 }
723 
724 ////////////////////////////////////////////////////////////////////////////////
725 /// Returns id of selected entry. In case of no selected entry or
726 /// if multi selection is switched on returns -1.
727 
728 Int_t TGLBContainer::GetSelected() const
729 {
730  if (fLastActive == 0) return -1;
731  return fLastActive->EntryId();
732 }
733 
734 ////////////////////////////////////////////////////////////////////////////////
735 /// Returns kTrue if entry id is selected.
736 
737 Bool_t TGLBContainer::GetSelection(Int_t id)
738 {
739  TGLBEntry *f;
740  TGFrameElement *el;
741 
742  TIter next(fList);
743  while ((el = (TGFrameElement *) next())) {
744  f = (TGLBEntry *) el->fFrame;
745  if (f->EntryId() == id)
746  return f->IsActive();
747  }
748 
749  return kFALSE;
750 }
751 
752 ////////////////////////////////////////////////////////////////////////////////
753 /// Adds all selected entries (TGLBEntry) of the list box into
754 /// the list selected.
755 
756 void TGLBContainer::GetSelectedEntries(TList *selected)
757 {
758  TGLBEntry *f;
759  TGFrameElement *el;
760 
761  TIter next(fList);
762  while ((el = (TGFrameElement *) next())) {
763  f = (TGLBEntry *) el->fFrame;
764  if (f->IsActive()) {
765  selected->Add(f);
766  }
767  }
768 }
769 
770 ////////////////////////////////////////////////////////////////////////////////
771 /// Enables and disables multiple selections of entries.
772 
773 void TGLBContainer::SetMultipleSelections(Bool_t multi)
774 {
775  TGFrameElement *el;
776 
777  fMultiSelect = multi;
778  if (!fMultiSelect) {
779  // deselect all entries
780  TIter next(fList);
781  while ((el = (TGFrameElement *) next())) {
782  ((TGLBEntry *)(el->fFrame))->Activate(kFALSE);
783  }
784  }
785  fLastActive = 0;
786  fLastActiveEl = 0;
787  ClearViewPort();
788 }
789 
790 ////////////////////////////////////////////////////////////////////////////////
791 /// Return a pointer to vertical scroll bar.
792 
793 TGVScrollBar *TGLBContainer::GetVScrollbar() const
794 {
795  return fListBox ? fListBox->GetVScrollbar() : 0;
796 }
797 
798 ////////////////////////////////////////////////////////////////////////////////
799 /// Set new vertical scroll bar position.
800 
801 void TGLBContainer::SetVsbPosition(Int_t newPos)
802 {
803  TGVScrollBar *vb = GetVScrollbar();
804 
805  if (vb && vb->IsMapped()) {
806  vb->SetPosition(newPos);
807  }
808 }
809 
810 ////////////////////////////////////////////////////////////////////////////////
811 /// Handle mouse button event in the listbox container.
812 
813 Bool_t TGLBContainer::HandleButton(Event_t *event)
814 {
815  int xf0, yf0, xff, yff;
816 
817  TGLBEntry *f;
818  TGFrameElement *el;
819  TGLBEntry *last = fLastActive;
820 
821  TGPosition pos = GetPagePosition();
822  Int_t x = pos.fX + event->fX;
823  Int_t y = pos.fY + event->fY;
824  Bool_t activate = kFALSE;
825 
826  // do not handle "context menu button" during guibuilding
827  if (fClient->IsEditable() && (event->fCode == kButton3)) {
828  return kTRUE;
829  }
830 
831  TGVScrollBar *vb = GetVScrollbar();
832 
833  if ((event->fCode == kButton4) && vb){
834  // scroll 2 lines up (a button down is always followed by a button up)
835  Int_t newpos = vb->GetPosition() - 1;
836  if (newpos < 0) newpos = 0;
837  vb->SetPosition(newpos);
838  ClearViewPort();
839  return kTRUE;
840  }
841  if ((event->fCode == kButton5) && vb) {
842  // scroll 2 lines down (a button down is always followed by a button up)
843  Int_t newpos = vb->GetPosition() + 1;
844  vb->SetPosition(newpos);
845  ClearViewPort();
846  return kTRUE;
847  }
848 
849  gVirtualX->SetInputFocus(fId);
850 
851  if (fMultiSelect) {
852  if (event->fType == kButtonPress) {
853  TIter next(fList);
854  while ((el = (TGFrameElement *) next())) {
855  f = (TGLBEntry *) el->fFrame;
856  xf0 = f->GetX();
857  yf0 = f->GetY();
858  xff = xf0 + f->GetWidth();
859  yff = yf0 + f->GetHeight();
860 
861  activate = fMapSubwindows ? (f->GetId() == (Window_t)event->fUser[0]) :
862  (x > xf0) && (x < xff) && (y > yf0) && (y < yff);
863 
864  if (activate) {
865  fLastActive = f;
866  fLastActiveEl = el;
867  f->Toggle();
868  fChangeStatus = f->IsActive() ? 1 : 0;
869  SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_ITEMCLICK),
870  f->EntryId(), 0);
871  break;
872  }
873  }
874  } else {
875  fChangeStatus = -1;
876  }
877  } else {
878  if (event->fType == kButtonPress) {
879  if (fLastActive) {
880  fLastActive->Activate(kFALSE);
881  fLastActive = 0;
882  }
883  TIter next(fList);
884  while ((el = (TGFrameElement *) next())) {
885  f = (TGLBEntry *) el->fFrame;
886  xf0 = f->GetX();
887  yf0 = f->GetY();
888  xff = xf0 + f->GetWidth();
889  yff = yf0 + f->GetHeight();
890 
891  activate = fMapSubwindows ? (f->GetId() == (Window_t)event->fUser[0]) :
892  (x > xf0) && (x < xff) && (y > yf0) && (y < yff) && !f->IsActive();
893 
894  if (activate) {
895  f->Activate(kTRUE);
896  fLastActive = f;
897  fLastActiveEl = el;
898  } else {
899  f->Activate(kFALSE);
900  }
901  }
902  } else {
903  if (fLastActive) {
904  f = fLastActive;
905  SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_ITEMCLICK),
906  f->EntryId(), 0);
907  }
908  }
909  }
910  if (event->fType == kButtonRelease) {
911  fScrolling = kFALSE;
912  gSystem->RemoveTimer(fScrollTimer);
913  }
914  if (fChangeStatus || (last != fLastActive))
915  ClearViewPort();
916  // trick to avoid mouse move events between the mouse click
917  // and the unmapping...
918  if (fListBox->GetParent()->InheritsFrom("TGComboBoxPopup"))
919  fListBox->GetContainer()->RemoveInput(kPointerMotionMask);
920  return kTRUE;
921 }
922 
923 ////////////////////////////////////////////////////////////////////////////////
924 /// Handle double click mouse event in the listbox container.
925 
926 Bool_t TGLBContainer::HandleDoubleClick(Event_t *ev)
927 {
928  if (!fMultiSelect) {
929  if (fLastActive) {
930  TGLBEntry *f = fLastActive;
931  SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_ITEMDBLCLICK),
932  f->EntryId(), 0);
933  DoubleClicked(f, ev->fCode);
934  DoubleClicked(f, ev->fCode, ev->fXRoot, ev->fYRoot);
935  }
936  return kTRUE;
937  }
938  return TGContainer::HandleDoubleClick(ev);
939 }
940 
941 ////////////////////////////////////////////////////////////////////////////////
942 /// Handle mouse motion event in listbox container.
943 
944 Bool_t TGLBContainer::HandleMotion(Event_t *event)
945 {
946  int xf0, yf0, xff, yff;
947 
948  static Long64_t was = gSystem->Now();
949  Long64_t now = gSystem->Now();
950 
951  if ((now-was) < 50) return kFALSE;
952  was = now;
953 
954  TGLBEntry *f;
955  TGFrameElement *el;
956  TGPosition pos = GetPagePosition();
957  TGDimension dim = GetPageDimension();
958  Int_t x = pos.fX + event->fX;
959  Int_t y = pos.fY + event->fY;
960  Bool_t activate = kFALSE;
961  TGLBEntry *last = fLastActive;
962 
963  if (fMultiSelect) {
964 
965  if ((event->fY < 10) || (event->fY > Int_t(dim.fHeight) - 10)) {
966  if (!fScrolling) {
967  fScrollTimer->Reset();
968  gSystem->AddTimer(fScrollTimer);
969  }
970  fScrolling = kTRUE;
971  }
972  else if (fChangeStatus >= 0) {
973  TIter next(fList);
974  while ((el = (TGFrameElement *) next())) {
975  f = (TGLBEntry *) el->fFrame;
976  xf0 = f->GetX();
977  yf0 = f->GetY();
978  xff = xf0 + f->GetWidth();
979  yff = yf0 + f->GetHeight();
980  activate = fMapSubwindows ? (f->GetId() == (Window_t)event->fUser[0]) :
981  (x > xf0) && (x < xff) && (y > yf0) && (y < yff);
982 
983  if (activate) {
984  if (fChangeStatus != (f->IsActive() ? 1 : 0)) {
985  f->Toggle();
986  ClearViewPort();
987  SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_ITEMCLICK),
988  f->EntryId(), 0);
989  }
990  break;
991  }
992  }
993  }
994  } else if (fListBox->GetParent()->InheritsFrom("TGComboBoxPopup")) {
995  TIter next(fList);
996  while ((el = (TGFrameElement *) next())) {
997  f = (TGLBEntry *) el->fFrame;
998  xf0 = f->GetX();
999  yf0 = f->GetY();
1000  xff = xf0 + f->GetWidth();
1001  yff = yf0 + f->GetHeight();
1002 
1003  activate = fMapSubwindows ? (f->GetId() == (Window_t)event->fUser[0]) :
1004  (x > xf0) && (x < xff) && (y > yf0) && (y < yff) && !f->IsActive();
1005 
1006  if (activate) {
1007  f->Activate(kTRUE);
1008  fLastActive = f;
1009  fLastActiveEl = el;
1010  } else {
1011  f->Activate(kFALSE);
1012  }
1013  if (last != fLastActive) {
1014  ClearViewPort();
1015  }
1016  }
1017  }
1018  return kTRUE;
1019 }
1020 
1021 ////////////////////////////////////////////////////////////////////////////////
1022 /// Autoscroll while close to & beyond The Wall
1023 
1024 void TGLBContainer::OnAutoScroll()
1025 {
1026  TGFrameElement* el = 0;
1027  TGLBEntry *f = 0;
1028  Int_t yf0, yff;
1029  Bool_t changed = kFALSE;
1030 
1031  TGDimension dim = GetPageDimension();
1032  TGPosition pos = GetPagePosition();
1033 
1034  Window_t dum1, dum2;
1035  Event_t ev;
1036  ev.fType = kButtonPress;
1037  Int_t x, y;
1038 
1039  // Where's the cursor?
1040  gVirtualX->QueryPointer(fId,dum1,dum2,ev.fXRoot,ev.fYRoot,x,y,ev.fState);
1041  TGVScrollBar *vb = GetVScrollbar();
1042  if (vb && y > 0 && y < 10) {
1043  // scroll 1 line up
1044  Int_t newpos = vb->GetPosition() - 1;
1045  if (newpos < 0) newpos = 0;
1046  vb->SetPosition(newpos);
1047  changed = kTRUE;
1048  }
1049  else if (vb && y > (Int_t)dim.fHeight - 10 && y < (Int_t)dim.fHeight) {
1050  // scroll 1 line down
1051  Int_t newpos = vb->GetPosition() + 1;
1052  vb->SetPosition(newpos);
1053  changed = kTRUE;
1054  }
1055  if (changed && fChangeStatus >= 0) {
1056  pos = GetPagePosition();
1057  TIter next(fList);
1058  while ((el = (TGFrameElement *) next())) {
1059  f = (TGLBEntry *) el->fFrame;
1060  yf0 = f->GetY();
1061  yff = yf0 + f->GetHeight();
1062  if ((y + pos.fY > yf0) && (y + pos.fY < yff)) {
1063  if (fChangeStatus != (f->IsActive() ? 1 : 0)) {
1064  f->Toggle();
1065  ClearViewPort();
1066  SendMessage(fMsgWindow, MK_MSG(kC_CONTAINER, kCT_ITEMCLICK),
1067  f->EntryId(), 0);
1068  }
1069  break;
1070  }
1071  }
1072  }
1073 }
1074 
1075 ////////////////////////////////////////////////////////////////////////////////
1076 /// Activate item.
1077 
1078 void TGLBContainer::ActivateItem(TGFrameElement *el)
1079 {
1080  TGContainer::ActivateItem(el);
1081  fLastActive = (TGLBEntry *)el->fFrame;
1082 }
1083 
1084 ////////////////////////////////////////////////////////////////////////////////
1085 /// Returns the position in the list box of the entry id.
1086 /// The first position has position no 0. Returns -1 if entry id
1087 /// is not in the list of entries.
1088 
1089 Int_t TGLBContainer::GetPos(Int_t id)
1090 {
1091  Int_t pos = 0;
1092  TGLBEntry *f;
1093  TGFrameElement *el;
1094 
1095  TIter next(fList);
1096  while ((el = (TGFrameElement *) next())) {
1097  f = (TGLBEntry *) el->fFrame;
1098  if (f->EntryId() == id)
1099  return pos;
1100  pos++;
1101  }
1102 
1103  return -1;
1104 }
1105 
1106 
1107 //////////////////////////////////////////////////////////////////////////
1108 // //
1109 // TGListBox //
1110 // //
1111 // A listbox contains a container frame which is viewed through a //
1112 // viewport. If the container is larger than the viewport than a //
1113 // vertical scrollbar is added. //
1114 // //
1115 // Selecting an item in the listbox will generate the event: //
1116 // kC_COMMAND, kCM_LISTBOX, listbox id, item id. //
1117 // //
1118 //////////////////////////////////////////////////////////////////////////
1119 
1120 ////////////////////////////////////////////////////////////////////////////////
1121 /// Create a listbox.
1122 
1123 TGListBox::TGListBox(const TGWindow *p, Int_t id,
1124  UInt_t options, ULong_t back) :
1125  TGCompositeFrame(p, 10, 10, options, back)
1126 {
1127  fMsgWindow = p;
1128  fWidgetId = id;
1129 
1130  fItemVsize = 1;
1131  fIntegralHeight = kTRUE;
1132 
1133  InitListBox();
1134 }
1135 
1136 ////////////////////////////////////////////////////////////////////////////////
1137 /// Delete a listbox widget.
1138 
1139 TGListBox::~TGListBox()
1140 {
1141  if (!MustCleanup()) {
1142  delete fVScrollbar;
1143  delete fVport;
1144  delete fLbc;
1145  }
1146 }
1147 
1148 ////////////////////////////////////////////////////////////////////////////////
1149 /// Initiate the internal classes of a list box.
1150 
1151 void TGListBox::InitListBox()
1152 {
1153  fVport = new TGViewPort(this, 6, 6, kChildFrame | kOwnBackground, fgWhitePixel);
1154  fVScrollbar = new TGVScrollBar(this, kDefaultScrollBarWidth, 6);
1155  fLbc = new TGLBContainer(fVport, 10, 10, kVerticalFrame, fgWhitePixel);
1156  fLbc->fViewPort = fVport;
1157  fLbc->Associate(this);
1158  fLbc->SetListBox(this);
1159  SetContainer(fLbc);
1160 
1161  AddFrame(fVport, 0);
1162  AddFrame(fVScrollbar, 0);
1163 
1164  fVScrollbar->Associate(this);
1165 
1166  fVScrollbar->AddInput(kButtonPressMask | kButtonReleaseMask |
1167  kPointerMotionMask);
1168  fLbc->RemoveInput(kPointerMotionMask);
1169  fLbc->AddInput(kButtonPressMask | kButtonReleaseMask | kButtonMotionMask);
1170 
1171  fVport->SetEditDisabled(kEditDisable | kEditDisableGrab);
1172  fVScrollbar->SetEditDisabled(kEditDisable | kEditDisableGrab | kEditDisableBtnEnable);
1173  fLbc->SetEditDisabled(kEditDisableGrab | kEditDisableBtnEnable | kEditDisableKeyEnable);
1174  fEditDisabled = kEditDisableLayout;
1175 
1176  // layout manager is not used
1177  delete fLayoutManager;
1178  fLayoutManager = 0;
1179 }
1180 
1181 ////////////////////////////////////////////////////////////////////////////////
1182 /// Draw borders of the list box widget.
1183 
1184 void TGListBox::DrawBorder()
1185 {
1186  switch (fOptions & (kSunkenFrame | kRaisedFrame | kDoubleBorder)) {
1187 
1188  case kSunkenFrame | kDoubleBorder:
1189  gVirtualX->DrawLine(fId, GetShadowGC()(), 0, 0, fWidth-2, 0);
1190  gVirtualX->DrawLine(fId, GetShadowGC()(), 0, 0, 0, fHeight-2);
1191  gVirtualX->DrawLine(fId, GetBlackGC()(), 1, 1, fWidth-3, 1);
1192  gVirtualX->DrawLine(fId, GetBlackGC()(), 1, 1, 1, fHeight-3);
1193  if (gClient->GetStyle() > 1) break;
1194  gVirtualX->DrawLine(fId, GetHilightGC()(), 0, fHeight-1, fWidth-1, fHeight-1);
1195  gVirtualX->DrawLine(fId, GetHilightGC()(), fWidth-1, fHeight-1, fWidth-1, 0);
1196  gVirtualX->DrawLine(fId, GetBckgndGC()(), 1, fHeight-2, fWidth-2, fHeight-2);
1197  gVirtualX->DrawLine(fId, GetBckgndGC()(), fWidth-2, 1, fWidth-2, fHeight-2);
1198  break;
1199 
1200  default:
1201  TGCompositeFrame::DrawBorder();
1202  break;
1203  }
1204 }
1205 
1206 ////////////////////////////////////////////////////////////////////////////////
1207 /// Add entry with specified string and id to listbox. The id will be
1208 /// used in the event processing routine when the item is selected.
1209 /// The string will be adopted by the listbox.
1210 
1211 void TGListBox::AddEntry(TGString *s, Int_t id)
1212 {
1213  TGTextLBEntry *lbe;
1214  TGLayoutHints *lhints;
1215 
1216  lbe = new TGTextLBEntry(fLbc, s, id);
1217  lhints = new TGLayoutHints(kLHintsExpandX | kLHintsTop);
1218  fItemVsize = TMath::Max(fItemVsize, lbe->GetDefaultHeight());
1219  fLbc->AddEntry(lbe, lhints);
1220 }
1221 
1222 ////////////////////////////////////////////////////////////////////////////////
1223 /// Add entry with specified string and id to listbox. The id will be
1224 /// used in the event processing routine when the item is selected.
1225 
1226 void TGListBox::AddEntry(const char *s, Int_t id)
1227 {
1228  AddEntry(new TGString(s), id);
1229 }
1230 
1231 ////////////////////////////////////////////////////////////////////////////////
1232 /// Add specified TGLBEntry and TGLayoutHints to listbox. The
1233 /// entry and layout will be adopted and later deleted by the listbox.
1234 
1235 void TGListBox::AddEntry(TGLBEntry *lbe, TGLayoutHints *lhints)
1236 {
1237  fItemVsize = TMath::Max(fItemVsize, lbe->GetDefaultHeight());
1238  fLbc->AddEntry(lbe, lhints);
1239 }
1240 
1241 ////////////////////////////////////////////////////////////////////////////////
1242 /// Add entry with specified string and id to listbox sorted by increasing id.
1243 /// This sorting works proberly only if EntrySort functions are used to add
1244 /// entries without mixing them with other add or insert functions. The id will be
1245 /// used in the event processing routine when the item is selected.
1246 /// The string will be adopted by the listbox.
1247 
1248 void TGListBox::AddEntrySort(TGString *s, Int_t id)
1249 {
1250  TGTextLBEntry *lbe;
1251  TGLayoutHints *lhints;
1252 
1253  lbe = new TGTextLBEntry(fLbc, s, id);
1254  lhints = new TGLayoutHints(kLHintsExpandX | kLHintsTop);
1255  fItemVsize = TMath::Max(fItemVsize, lbe->GetDefaultHeight());
1256  fLbc->AddEntrySort(lbe, lhints);
1257 }
1258 
1259 ////////////////////////////////////////////////////////////////////////////////
1260 /// Add entry with specified string and id to listbox sorted by increasing id.
1261 /// This sorting works proberly only if EntrySort functions are used to add
1262 /// entries without mixing them with other add or insert functions. The id will be
1263 /// used in the event processing routine when the item is selected.
1264 
1265 void TGListBox::AddEntrySort(const char *s, Int_t id)
1266 {
1267  AddEntrySort(new TGString(s), id);
1268 }
1269 
1270 ////////////////////////////////////////////////////////////////////////////////
1271 /// Add specified TGLBEntry and TGLayoutHints to listbox sorted by increasing id.
1272 /// This sorting works proberly only if EntrySort functions are used to add
1273 /// entries without mixing them with other add or insert functions. The
1274 /// entry and layout will be adopted and later deleted by the listbox.
1275 
1276 void TGListBox::AddEntrySort(TGLBEntry *lbe, TGLayoutHints *lhints)
1277 {
1278  fItemVsize = TMath::Max(fItemVsize, lbe->GetDefaultHeight());
1279  fLbc->AddEntrySort(lbe, lhints);
1280 }
1281 
1282 ////////////////////////////////////////////////////////////////////////////////
1283 /// Insert entry with specified string and id behind the entry with afterID.
1284 /// The string will be adopted and later deleted by the listbox.
1285 
1286 void TGListBox::InsertEntry(TGString *s, Int_t id, Int_t afterID)
1287 {
1288  TGTextLBEntry *lbe;
1289  TGLayoutHints *lhints;
1290 
1291  lbe = new TGTextLBEntry(fLbc, s, id);
1292  lhints = new TGLayoutHints(kLHintsExpandX | kLHintsTop);
1293  fItemVsize = TMath::Max(fItemVsize, lbe->GetDefaultHeight());
1294  fLbc->InsertEntry(lbe, lhints, afterID);
1295 }
1296 
1297 ////////////////////////////////////////////////////////////////////////////////
1298 /// Insert entry with specified string and id behind the entry with afterID.
1299 
1300 void TGListBox::InsertEntry(const char *s, Int_t id, Int_t afterID)
1301 {
1302  InsertEntry(new TGString(s), id, afterID);
1303 }
1304 
1305 ////////////////////////////////////////////////////////////////////////////////
1306 /// method used to add entry via context menu
1307 
1308 void TGListBox::NewEntry(const char *s)
1309 {
1310  Int_t selected = fLbc->GetSelected();
1311 
1312  // no selected entry or the last entry
1313  if ((selected < 0) || (selected == GetNumberOfEntries())) {
1314  AddEntry(s, GetNumberOfEntries()+1);
1315  } else {
1316  InsertEntry(s, GetNumberOfEntries()+1, selected);
1317  }
1318  Layout();
1319 }
1320 
1321 ////////////////////////////////////////////////////////////////////////////////
1322 /// remove entry with id.
1323 /// If id = -1 - the selected entry/entries is/are removed.
1324 ///
1325 
1326 void TGListBox:: RemoveEntry(Int_t id)
1327 {
1328  if (id >= 0) {
1329  fLbc->RemoveEntry(id);
1330  Layout();
1331  return;
1332  }
1333  if (!fLbc->GetMultipleSelections()) {
1334  fLbc->RemoveEntry(fLbc->GetSelected());
1335  Layout();
1336  return;
1337  }
1338  TList li;
1339  fLbc->GetSelectedEntries(&li);
1340  TGLBEntry *e;
1341  TIter next(&li);
1342 
1343  while ((e = (TGLBEntry*)next())) {
1344  fLbc->RemoveEntry(e->EntryId());
1345  }
1346  Layout();
1347 }
1348 
1349 ////////////////////////////////////////////////////////////////////////////////
1350 /// Remove all entries.
1351 
1352 void TGListBox::RemoveAll()
1353 {
1354  fLbc->RemoveAll();
1355  Layout();
1356 }
1357 
1358 ////////////////////////////////////////////////////////////////////////////////
1359 /// Remove a range of entries defined by from_ID and to_ID.
1360 
1361 void TGListBox::RemoveEntries(Int_t from_ID, Int_t to_ID)
1362 {
1363  fLbc->RemoveEntries(from_ID, to_ID);
1364  Layout();
1365 }
1366 
1367 ////////////////////////////////////////////////////////////////////////////////
1368 /// Insert the specified TGLBEntry and layout hints behind afterID.
1369 /// The entry and layout will be adopted and later deleted by the listbox.
1370 
1371 void TGListBox::InsertEntry(TGLBEntry *lbe, TGLayoutHints *lhints, int afterID)
1372 {
1373  fItemVsize = TMath::Max(fItemVsize, lbe->GetDefaultHeight());
1374  fLbc->InsertEntry(lbe, lhints, afterID);
1375 }
1376 
1377 ////////////////////////////////////////////////////////////////////////////////
1378 /// Returns list box entry with specified id.
1379 
1380 TGLBEntry *TGListBox::GetEntry(Int_t id) const
1381 {
1382  TIter next(fLbc->GetList());
1383  TGFrameElement *el;
1384 
1385  while ((el = (TGFrameElement *)next())) {
1386  TGLBEntry *lbe = (TGLBEntry *)el->fFrame;
1387  if (lbe->EntryId() == id) return lbe;
1388  }
1389  return 0;
1390 }
1391 
1392 ////////////////////////////////////////////////////////////////////////////////
1393 /// Scroll the entry with id to the top of the listbox.
1394 
1395 void TGListBox::SetTopEntry(Int_t id)
1396 {
1397  Int_t idPos;
1398 
1399  idPos = fLbc->GetPos(id);
1400 
1401  // id not found in list of entries
1402  if (idPos < 0)
1403  return;
1404 
1405  // call layout to define the range of the scroll bars
1406  Layout();
1407 
1408  // SetPosition will send a message which will handled by
1409  // the function TGListBox::ProcessMessage. Now ProcessMessage will
1410  // set the viewport. SetPosition also will check that the idPos is
1411  // not out of range.
1412  fVScrollbar->SetPosition(idPos);
1413 }
1414 
1415 ////////////////////////////////////////////////////////////////////////////////
1416 /// Resize the listbox widget. If fIntegralHeight is true make the height
1417 /// an integral number of the maximum height of a single entry.
1418 
1419 void TGListBox::Resize(UInt_t w, UInt_t h)
1420 {
1421  if (fIntegralHeight)
1422  h = TMath::Max(fItemVsize, ((h - (fBorderWidth << 1)) / fItemVsize) * fItemVsize)
1423  + (fBorderWidth << 1);
1424 
1425  TGCompositeFrame::Resize(w, h);
1426  DoRedraw();
1427 }
1428 
1429 ////////////////////////////////////////////////////////////////////////////////
1430 /// Move and resize the listbox widget.
1431 
1432 void TGListBox::MoveResize(Int_t x, Int_t y, UInt_t w, UInt_t h)
1433 {
1434  if (fIntegralHeight)
1435  h = TMath::Max(fItemVsize, ((h - (fBorderWidth << 1)) / fItemVsize) * fItemVsize)
1436  + (fBorderWidth << 1);
1437  TGCompositeFrame::MoveResize(x, y, w, h);
1438  DoRedraw();
1439 }
1440 
1441 ////////////////////////////////////////////////////////////////////////////////
1442 /// Return default size of listbox widget.
1443 
1444 TGDimension TGListBox::GetDefaultSize() const
1445 {
1446  UInt_t h;
1447 
1448  if (fIntegralHeight)
1449  h = TMath::Max(fItemVsize, ((fHeight - (fBorderWidth << 1)) / fItemVsize) * fItemVsize)
1450  + (fBorderWidth << 1);
1451  else
1452  h = fHeight;
1453 
1454  return TGDimension(fWidth, h);
1455 }
1456 
1457 ////////////////////////////////////////////////////////////////////////////////
1458 /// Layout the listbox components.
1459 
1460 void TGListBox::Layout()
1461 {
1462  TGFrame *container;
1463  UInt_t cw, ch, tch;
1464  Bool_t need_vsb;
1465 
1466  need_vsb = kFALSE;
1467 
1468  container = fVport->GetContainer();
1469 
1470  // test whether we need vertical scrollbar or not
1471 
1472  cw = fWidth - (fBorderWidth << 1);
1473  ch = fHeight - (fBorderWidth << 1);
1474 
1475  container->SetWidth(cw);
1476  container->SetHeight(ch);
1477 
1478  if (container->GetDefaultHeight() > ch) {
1479  need_vsb = kTRUE;
1480  cw -= fVScrollbar->GetDefaultWidth();
1481  if ((Int_t) cw < 0) {
1482  Warning("Layout", "width would become too small, setting to 10");
1483  cw = 10;
1484  }
1485  container->SetWidth(cw);
1486  }
1487 
1488  fVport->MoveResize(fBorderWidth, fBorderWidth, cw, ch);
1489  container->Layout();
1490 
1491  tch = TMath::Max(container->GetDefaultHeight(), ch);
1492  container->SetHeight(0); // force a resize in TGFrame::Resize
1493  container->Resize(cw, tch);
1494  //fVport->SetPos(0, 0);
1495 
1496  if (need_vsb) {
1497  fVScrollbar->MoveResize(cw+fBorderWidth, fBorderWidth, fVScrollbar->GetDefaultWidth(), ch);
1498  fVScrollbar->MapWindow();
1499  } else {
1500  fVScrollbar->UnmapWindow();
1501  fVScrollbar->SetPosition(0);
1502  }
1503 
1504  fVScrollbar->SetRange((Int_t)TMath::Ceil((Double_t)container->GetHeight()/(Double_t)fItemVsize),
1505  fVport->GetHeight()/fItemVsize);
1506  //fClient->NeedRedraw(container);
1507  ((TGContainer *)container)->ClearViewPort();
1508 }
1509 
1510 ////////////////////////////////////////////////////////////////////////////////
1511 /// Sort entries by name
1512 
1513 void TGListBox::SortByName(Bool_t ascend)
1514 {
1515  fLbc->GetList()->Sort(ascend);
1516  Layout();
1517  fLbc->ClearViewPort();
1518 }
1519 
1520 ////////////////////////////////////////////////////////////////////////////////
1521 /// Return id of selected listbox item.
1522 
1523 Int_t TGListBox::GetSelected() const
1524 {
1525  TGLBContainer *ct = (TGLBContainer *) fVport->GetContainer();
1526  return ct->GetSelected();
1527 }
1528 
1529 ////////////////////////////////////////////////////////////////////////////////
1530 /// Adds all selected entries (TGLBEntry) of the list box into
1531 /// the list selected.
1532 
1533 void TGListBox::GetSelectedEntries(TList *selected)
1534 {
1535  fLbc->GetSelectedEntries(selected);
1536 }
1537 
1538 ////////////////////////////////////////////////////////////////////////////////
1539 /// Change background to all entries
1540 
1541 void TGListBox::ChangeBackground(Pixel_t back)
1542 {
1543  fBackground = back;
1544 
1545  TIter next(fLbc->GetList());
1546  TGFrameElement *el;
1547 
1548  while ((el = (TGFrameElement *)next())) {
1549  TGLBEntry *lbe = (TGLBEntry *)el->fFrame;
1550  lbe->SetBackgroundColor(back);
1551  }
1552  fLbc->ClearViewPort();
1553 }
1554 
1555 ////////////////////////////////////////////////////////////////////////////////
1556 /// Process messages generated by the listbox container and forward
1557 /// messages to the listbox message handling window.
1558 
1559 Bool_t TGListBox::ProcessMessage(Long_t msg, Long_t parm1, Long_t)
1560 {
1561  switch (GET_MSG(msg)) {
1562  case kC_VSCROLL:
1563  switch (GET_SUBMSG(msg)) {
1564  case kSB_SLIDERTRACK:
1565  case kSB_SLIDERPOS:
1566  fVport->SetVPos(Int_t(-parm1 * fItemVsize));
1567  break;
1568  }
1569  break;
1570 
1571  case kC_CONTAINER:
1572  switch (GET_SUBMSG(msg)) {
1573  case kCT_ITEMCLICK:
1574  {
1575  SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_LISTBOX),
1576  fWidgetId, parm1);
1577  if (GetMultipleSelections()) SelectionChanged();
1578  TGLBEntry *entry = GetSelectedEntry();
1579  if (entry) {
1580  if (entry->InheritsFrom(TGTextLBEntry::Class())) {
1581  const char *text;
1582  text = ((TGTextLBEntry*)entry)->GetText()->GetString();
1583  Selected(text);
1584  }
1585  Selected(fWidgetId, (Int_t) parm1);
1586  Selected((Int_t) parm1);
1587  }
1588  }
1589  break;
1590  case kCT_ITEMDBLCLICK:
1591  if (!GetMultipleSelections()) {
1592  TGLBEntry *entry = GetSelectedEntry();
1593  if (entry) {
1594  if (entry->InheritsFrom(TGTextLBEntry::Class())) {
1595  const char *text;
1596  text = ((TGTextLBEntry*)entry)->GetText()->GetString();
1597  DoubleClicked(text);
1598  }
1599  DoubleClicked(fWidgetId, (Int_t) parm1);
1600  DoubleClicked((Int_t) parm1);
1601  }
1602  }
1603  break;
1604  }
1605  break;
1606 
1607  default:
1608  break;
1609 
1610  }
1611  return kTRUE;
1612 }
1613 
1614 ////////////////////////////////////////////////////////////////////////////////
1615 /// Emit Selected signal with list box id and entry id.
1616 
1617 void TGListBox::Selected(Int_t widgetId, Int_t id)
1618 {
1619  Long_t args[2];
1620 
1621  args[0] = widgetId;
1622  args[1] = id;
1623 
1624  Emit("Selected(Int_t,Int_t)", args);
1625 }
1626 
1627 ////////////////////////////////////////////////////////////////////////////////
1628 /// Emit DoubleClicked signal with list box id and entry id.
1629 
1630 void TGListBox::DoubleClicked(Int_t widgetId, Int_t id)
1631 {
1632  Long_t args[2];
1633 
1634  args[0] = widgetId;
1635  args[1] = id;
1636 
1637  Emit("DoubleClicked(Int_t,Int_t)", args);
1638 }
1639 
1640 ////////////////////////////////////////////////////////////////////////////////
1641 /// Find entry by name.
1642 
1643 TGLBEntry *TGListBox::FindEntry(const char *name) const
1644 {
1645  TList *list = fLbc->GetList();
1646  TGFrameElement *el = (TGFrameElement *)list->First();
1647  while (el) {
1648  if (el->fFrame->GetTitle() == TString(name))
1649  return (TGLBEntry *)el->fFrame;
1650  el = (TGFrameElement *)list->After(el);
1651  }
1652  return 0;
1653 }
1654 
1655 ////////////////////////////////////////////////////////////////////////////////
1656 /// Save a list box widget as a C++ statement(s) on output stream out.
1657 
1658 void TGListBox::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
1659 {
1660  if (fBackground != GetWhitePixel()) SaveUserColor(out, option);
1661 
1662  out << std::endl << " // list box" << std::endl;
1663 
1664  out<<" TGListBox *";
1665  out << GetName() << " = new TGListBox(" << fParent->GetName();
1666 
1667  if (fBackground == GetWhitePixel()) {
1668  if (GetOptions() == (kSunkenFrame | kDoubleBorder)) {
1669  if (fWidgetId == -1) {
1670  out <<");" << std::endl;
1671  } else {
1672  out << "," << fWidgetId << ");" << std::endl;
1673  }
1674  } else {
1675  out << "," << fWidgetId << "," << GetOptionString() <<");" << std::endl;
1676  }
1677  } else {
1678  out << "," << fWidgetId << "," << GetOptionString() << ",ucolor);" << std::endl;
1679  }
1680  if (option && strstr(option, "keep_names"))
1681  out << " " << GetName() << "->SetName(\"" << GetName() << "\");" << std::endl;
1682 
1683  if (!fLbc->GetList()) return;
1684 
1685  TGFrameElement *el;
1686  TIter next(fLbc->GetList());
1687 
1688  while ((el = (TGFrameElement *) next())) {
1689  out << " " << GetName() << "->AddEntry(";
1690  el->fFrame->SavePrimitive(out, option);
1691  out << ");"<< std::endl;
1692  }
1693  out << " " << GetName() << "->Resize(" << GetWidth() << "," << GetHeight()
1694  << ");" << std::endl;
1695 }
1696 
1697 ////////////////////////////////////////////////////////////////////////////////
1698 /// Save a list box entry widget as a C++ statement(s) on output stream out.
1699 
1700 void TGTextLBEntry::SavePrimitive(std::ostream &out, Option_t * /*= ""*/)
1701 {
1702  TString content = GetText()->GetString();
1703  content.ReplaceAll('\\', "\\\\");
1704  content.ReplaceAll("\"", "\\\"");
1705  char quote = '"';
1706  out << quote << content << quote << "," << EntryId();
1707 }