Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGScrollBar.cxx
Go to the documentation of this file.
1 // @(#)root/gui:$Id$
2 // Author: Fons Rademakers 10/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 // TGScrollBar and TGScrollBarElement //
26 // //
27 // The classes in this file implement scrollbars. Scrollbars can be //
28 // either placed horizontal or vertical. A scrollbar contains three //
29 // TGScrollBarElements: The "head", "tail" and "slider". The head and //
30 // tail are fixed at either end and have the typical arrows in them. //
31 // //
32 // The TGHScrollBar will generate the following event messages: //
33 // kC_HSCROLL, kSB_SLIDERPOS, position, 0 //
34 // kC_HSCROLL, kSB_SLIDERTRACK, position, 0 //
35 // //
36 // The TGVScrollBar will generate the following event messages: //
37 // kC_VSCROLL, kSB_SLIDERPOS, position, 0 //
38 // kC_VSCROLL, kSB_SLIDERTRACK, position, 0 //
39 // //
40 //////////////////////////////////////////////////////////////////////////
41 
42 #include "TGScrollBar.h"
43 #include "TGResourcePool.h"
44 #include "TGPicture.h"
45 #include "TImage.h"
46 #include "TSystem.h"
47 #include "TTimer.h"
48 #include "TEnv.h"
49 #include "Riostream.h"
50 
51 
52 Pixmap_t TGScrollBar::fgBckgndPixmap = 0;
53 Int_t TGScrollBar::fgScrollBarWidth = kDefaultScrollBarWidth;
54 
55 ClassImp(TGScrollBarElement);
56 ClassImp(TGScrollBar);
57 ClassImp(TGHScrollBar);
58 ClassImp(TGVScrollBar);
59 
60 
61 ////////////////////////////////////////////////////////////////////////////////
62 
63 class TSBRepeatTimer : public TTimer {
64 private:
65  TGScrollBar *fScrollBar; // scroll bar
66  Int_t fSmallInc; // step
67 public:
68  TSBRepeatTimer(TGScrollBar *s, Long_t ms, Int_t inc) : TTimer(ms, kTRUE)
69  { fScrollBar = s; fSmallInc = inc; }
70 
71  Bool_t Notify();
72  Int_t GetSmallInc() const { return fSmallInc; }
73 };
74 
75 ////////////////////////////////////////////////////////////////////////////////
76 /// Notify when timer times out and reset the timer.
77 
78 Bool_t TSBRepeatTimer::Notify()
79 {
80  fScrollBar->HandleTimer(this);
81  Reset();
82  return kFALSE;
83 }
84 
85 ////////////////////////////////////////////////////////////////////////////////
86 /// Constructor.
87 
88 TGScrollBarElement::TGScrollBarElement(const TGWindow *p, const TGPicture *pic,
89  UInt_t w, UInt_t h, UInt_t options, Pixel_t back) :
90  TGFrame(p, w, h, options | kOwnBackground, back)
91 {
92  fPic = fPicN = pic;
93  fState = kButtonUp;
94  fPicD = 0;
95  fStyle = 0;
96  if ((gClient->GetStyle() > 1) || (p && p->InheritsFrom("TGScrollBar")))
97  fStyle = gClient->GetStyle();
98 
99  fBgndColor = fBackground;
100  fHighColor = gClient->GetResourcePool()->GetHighLightColor();
101  AddInput(kEnterWindowMask | kLeaveWindowMask);
102 }
103 
104 ////////////////////////////////////////////////////////////////////////////////
105 /// destructor
106 
107 TGScrollBarElement::~TGScrollBarElement()
108 {
109  if (fPicD) {
110  fClient->FreePicture(fPicD);
111  }
112 }
113 
114 ////////////////////////////////////////////////////////////////////////////////
115 /// Change state of scrollbar element (either up or down).
116 
117 void TGScrollBarElement::SetState(Int_t state)
118 {
119  if (state != fState) {
120  switch (state) {
121  case kButtonDown:
122  fOptions &= ~kRaisedFrame;
123  fOptions |= kSunkenFrame;
124  break;
125  case kButtonUp:
126  case kButtonDisabled:
127  fOptions &= ~kSunkenFrame;
128  fOptions |= kRaisedFrame;
129  break;
130  }
131  fState = state;
132  fClient->NeedRedraw(this);
133  }
134 }
135 
136 ////////////////////////////////////////////////////////////////////////////////
137 /// Enable/Disable scroll bar button chaging the state.
138 
139 void TGScrollBarElement::SetEnabled(Bool_t on)
140 {
141  if (on) {
142  if (fState == kButtonUp) {
143  return;
144  }
145  SetState(kButtonUp);
146  fPic = fPicN;
147  } else {
148  if (fState == kButtonDisabled) {
149  return;
150  }
151  SetState(kButtonDisabled);
152 
153  if (!fPicD) {
154  TImage *img = TImage::Create();
155  if (!img) return;
156  TImage *img2 = TImage::Create();
157  if (!img2) {
158  if (img) delete img;
159  return;
160  }
161  TString back = gEnv->GetValue("Gui.BackgroundColor", "#c0c0c0");
162  img2->FillRectangle(back.Data(), 0, 0, fPic->GetWidth(), fPic->GetHeight());
163  img->SetImage(fPicN->GetPicture(), fPicN->GetMask());
164  Pixmap_t mask = img->GetMask();
165  img2->Merge(img, "overlay");
166 
167  TString name = "disbl_";
168  name += fPic->GetName();
169  fPicD = fClient->GetPicturePool()->GetPicture(name.Data(), img2->GetPixmap(),
170  mask);
171  delete img;
172  delete img2;
173  }
174  fPic = fPicD;
175  }
176  fClient->NeedRedraw(this);
177 }
178 
179 ////////////////////////////////////////////////////////////////////////////////
180 /// Draw border around scollbar element.
181 
182 void TGScrollBarElement::DrawBorder()
183 {
184  switch (fOptions & (kSunkenFrame | kRaisedFrame)) {
185  case kSunkenFrame: // pressed
186  gVirtualX->DrawLine(fId, GetBlackGC()(), 0, 0, fWidth-2, 0);
187  gVirtualX->DrawLine(fId, GetBlackGC()(), 0, 0, 0, fHeight-2);
188  gVirtualX->DrawLine(fId, GetShadowGC()(), 1, 1, fWidth-3, 1);
189  gVirtualX->DrawLine(fId, GetShadowGC()(), 1, 1, 1, fHeight-3);
190 
191  gVirtualX->DrawLine(fId, GetWhiteGC()(), 0, fHeight-1, fWidth-1, fHeight-1);
192  gVirtualX->DrawLine(fId, GetWhiteGC()(), fWidth-1, fHeight-1, fWidth-1, 1);
193  gVirtualX->DrawLine(fId, GetBckgndGC()(), 1, fHeight-2, fWidth-2, fHeight-2);
194  gVirtualX->DrawLine(fId, GetBckgndGC()(), fWidth-2, fHeight-2, fWidth-2, 2);
195 
196  if (fPic) {
197  int x = (fWidth - fPic->GetWidth()) >> 1;
198  int y = (fHeight - fPic->GetHeight()) >> 1;
199  fPic->Draw(fId, GetBckgndGC()(), x+1, y+1); // 3, 3
200  }
201  break;
202 
203  case kRaisedFrame: // normal
204  case kButtonDisabled:
205  if (fStyle > 0) {
206  // new modern (flat) version
207  if (fBackground == fHighColor) {
208  gVirtualX->DrawRectangle(fId, GetShadowGC()(), 0, 0, fWidth-1, fHeight-1);
209  }
210  else {
211  if (fPic == 0)
212  gVirtualX->DrawRectangle(fId, GetShadowGC()(), 0, 0, fWidth-1, fHeight-1);
213  else
214  gVirtualX->DrawRectangle(fId, GetBckgndGC()(), 0, 0, fWidth-1, fHeight-1);
215  }
216  if (fParent && fParent->InheritsFrom("TGHScrollBar")) {
217  if (fWidth > 20) {
218  gVirtualX->DrawLine(fId, GetShadowGC()(), (fWidth/2)-3, 4, (fWidth/2)-3, fHeight-5);
219  gVirtualX->DrawLine(fId, GetShadowGC()(), (fWidth/2), 4, (fWidth/2), fHeight-5);
220  gVirtualX->DrawLine(fId, GetShadowGC()(), (fWidth/2)+3, 4, (fWidth/2)+3, fHeight-5);
221  }
222  }
223  else if (fParent && fParent->InheritsFrom("TGVScrollBar")) {
224  if (fHeight > 20) {
225  gVirtualX->DrawLine(fId, GetShadowGC()(), 4, (fHeight/2)-3, fWidth-5, (fHeight/2)-3);
226  gVirtualX->DrawLine(fId, GetShadowGC()(), 4, (fHeight/2) , fWidth-5, (fHeight/2));
227  gVirtualX->DrawLine(fId, GetShadowGC()(), 4, (fHeight/2)+3, fWidth-5, (fHeight/2)+3);
228  }
229  }
230  else { // not used in a scroll bar (e.g. in a combo box)
231  gVirtualX->DrawRectangle(fId, GetShadowGC()(), 0, 0, fWidth-1, fHeight-1);
232  }
233  }
234  else {
235  gVirtualX->DrawLine(fId, GetBckgndGC()(), 0, 0, fWidth-2, 0);
236  gVirtualX->DrawLine(fId, GetBckgndGC()(), 0, 0, 0, fHeight-2);
237  gVirtualX->DrawLine(fId, GetHilightGC()(), 1, 1, fWidth-3, 1);
238  gVirtualX->DrawLine(fId, GetHilightGC()(), 1, 1, 1, fHeight-3);
239 
240  gVirtualX->DrawLine(fId, GetShadowGC()(), 1, fHeight-2, fWidth-2, fHeight-2);
241  gVirtualX->DrawLine(fId, GetShadowGC()(), fWidth-2, fHeight-2, fWidth-2, 1);
242  gVirtualX->DrawLine(fId, GetBlackGC()(), 0, fHeight-1, fWidth-1, fHeight-1);
243  gVirtualX->DrawLine(fId, GetBlackGC()(), fWidth-1, fHeight-1, fWidth-1, 0);
244  }
245  if (fPic) {
246  int x = (fWidth - fPic->GetWidth()) >> 1;
247  int y = (fHeight - fPic->GetHeight()) >> 1;
248  fPic->Draw(fId, GetBckgndGC()(), x, y); // 2, 2
249  }
250  break;
251 
252  default:
253  break;
254  }
255 }
256 
257 ////////////////////////////////////////////////////////////////////////////////
258 /// Handle mouse crossing event.
259 
260 Bool_t TGScrollBarElement::HandleCrossing(Event_t *event)
261 {
262  if (fStyle > 0) {
263  TGScrollBarElement *el = 0;
264  TGScrollBar *bar = 0;
265  if ((event->fType == kEnterNotify) && (fState != kButtonDisabled)) {
266  fBgndColor = fHighColor;
267  } else {
268  fBgndColor = fBackground;
269  }
270  if (event->fType == kLeaveNotify) {
271  fBgndColor = fBackground;
272  }
273  gVirtualX->SetWindowBackground(fId, fBgndColor);
274  TGFrame::DoRedraw();
275  DrawBorder();
276  if (fParent && fParent->InheritsFrom("TGScrollBar")) {
277  bar = (TGScrollBar *)fParent;
278  if ((el = bar->GetHead()) != this) {
279  el->ChangeBackground(fBgndColor);
280  el->DrawBorder();
281  }
282  if ((el = bar->GetTail()) != this) {
283  el->ChangeBackground(fBgndColor);
284  el->DrawBorder();
285  }
286  if ((el = bar->GetSlider()) != this) {
287  el->ChangeBackground(fBgndColor);
288  el->DrawBorder();
289  }
290  }
291  }
292  return kTRUE;
293 }
294 
295 ////////////////////////////////////////////////////////////////////////////////
296 /// Constructor.
297 
298 TGScrollBar::TGScrollBar(const TGWindow *p, UInt_t w, UInt_t h,
299  UInt_t options, Pixel_t back) :
300  TGFrame(p, w, h, options | kOwnBackground, back),
301  fX0(0), fY0(0), fXp(0), fYp(0), fDragging(kFALSE), fGrabPointer(kTRUE),
302  fRange(0), fPsize(0), fPos(0), fSliderSize(0), fSliderRange(0),
303  fSmallInc(1), fHead(0), fTail(0), fSlider(0), fHeadPic(0),
304  fTailPic(0), fRepeat(0), fSubw()
305 {
306  fAccelerated = kFALSE;
307 
308  fBgndColor = fBackground;
309  fHighColor = gClient->GetResourcePool()->GetHighLightColor();
310 
311  fMsgWindow = p;
312  if (gClient->GetStyle() == 0)
313  SetBackgroundPixmap(GetBckgndPixmap());
314  SetWindowName();
315  AddInput(kEnterWindowMask | kLeaveWindowMask);
316 }
317 
318 ////////////////////////////////////////////////////////////////////////////////
319 /// Delete a scrollbar (either horizontal or vertical).
320 
321 TGScrollBar::~TGScrollBar()
322 {
323  delete fHead;
324  delete fTail;
325  delete fSlider;
326  if (fHeadPic) fClient->FreePicture(fHeadPic);
327  if (fTailPic) fClient->FreePicture(fTailPic);
328  if (fRepeat) { delete fRepeat; fRepeat = 0; }
329 }
330 
331 ////////////////////////////////////////////////////////////////////////////////
332 /// Handle mouse crossing event.
333 
334 Bool_t TGScrollBar::HandleCrossing(Event_t *event)
335 {
336  if (gClient->GetStyle() > 0) {
337  if (event->fType == kEnterNotify) {
338  fBgndColor = fHighColor;
339  } else {
340  fBgndColor = fBackground;
341  }
342  if (event->fType == kLeaveNotify) {
343  fBgndColor = fBackground;
344  }
345  fHead->ChangeBackground(fBgndColor);
346  fTail->ChangeBackground(fBgndColor);
347  fSlider->ChangeBackground(fBgndColor);
348  fHead->DrawBorder();
349  fTail->DrawBorder();
350  fSlider->DrawBorder();
351  }
352  return kTRUE;
353 }
354 
355 ////////////////////////////////////////////////////////////////////////////////
356 /// Handle repeat timer for horizontal or vertical scrollbar. Every time
357 /// timer times out we move slider.
358 
359 Bool_t TGScrollBar::HandleTimer(TTimer *t)
360 {
361  // shorten time out time to 50 milli seconds
362  t->SetTime(50);
363 
364  Window_t dum1, dum2;
365  Event_t ev;
366 
367  ev.fCode = kButton1;
368  ev.fType = kButtonPress;
369  ev.fUser[0] = fSubw;
370 
371  if (IsAccelerated()) {
372  ++fSmallInc;
373  if (fSmallInc > 100) fSmallInc = 100;
374  }
375 
376  gVirtualX->QueryPointer(fId, dum1, dum2, ev.fXRoot, ev.fYRoot, ev.fX, ev.fY,
377  ev.fState);
378 
379  HandleButton(&ev);
380 
381  return kTRUE;
382 }
383 
384 ////////////////////////////////////////////////////////////////////////////////
385 /// Static method returning scrollbar background pixmap.
386 
387 Pixmap_t TGScrollBar::GetBckgndPixmap()
388 {
389  static Bool_t init = kFALSE;
390  if (!init) {
391  fgBckgndPixmap = gClient->GetResourcePool()->GetCheckeredPixmap();
392  init = kTRUE;
393  }
394  return fgBckgndPixmap;
395 }
396 
397 ////////////////////////////////////////////////////////////////////////////////
398 /// Static method returning the scrollbar width.
399 
400 Int_t TGScrollBar::GetScrollBarWidth()
401 {
402  return fgScrollBarWidth;
403 }
404 
405 ////////////////////////////////////////////////////////////////////////////////
406 /// Change background color
407 
408 void TGScrollBar::ChangeBackground(Pixel_t back)
409 {
410  TGFrame::ChangeBackground(back);
411  fHead->ChangeBackground(back);
412  fTail->ChangeBackground(back);
413  fSlider->ChangeBackground(back);
414 }
415 
416 ////////////////////////////////////////////////////////////////////////////////
417 /// Create a horizontal scrollbar widget.
418 
419 TGHScrollBar::TGHScrollBar(const TGWindow *p, UInt_t w, UInt_t h,
420  UInt_t options, ULong_t back) :
421  TGScrollBar(p, w, h, options, back)
422 {
423  fHeadPic = fClient->GetPicture("arrow_left.xpm");
424  fTailPic = fClient->GetPicture("arrow_right.xpm");
425 
426  if (!fHeadPic || !fTailPic) {
427  Error("TGHScrollBar", "arrow_*.xpm not found");
428  return;
429  }
430  fHead = new TGScrollBarElement(this, fHeadPic, fgScrollBarWidth, fgScrollBarWidth,
431  kRaisedFrame);
432  fTail = new TGScrollBarElement(this, fTailPic, fgScrollBarWidth, fgScrollBarWidth,
433  kRaisedFrame);
434  fSlider = new TGScrollBarElement(this, 0, fgScrollBarWidth, 50,
435  kRaisedFrame);
436 
437  gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier, kButtonPressMask |
438  kButtonReleaseMask | kPointerMotionMask, kNone, kNone);
439 
440  fDragging = kFALSE;
441  fX0 = fY0 = (fgScrollBarWidth = TMath::Max(fgScrollBarWidth, 5));
442  fPos = 0;
443 
444  fRange = TMath::Max((Int_t) w - (fgScrollBarWidth << 1), 1);
445  fPsize = fRange >> 1;
446 
447  fSliderSize = 50;
448  fSliderRange = 1;
449 
450  fHead->SetEditDisabled(kEditDisable | kEditDisableGrab);
451  fTail->SetEditDisabled(kEditDisable | kEditDisableGrab);
452  fSlider->SetEditDisabled(kEditDisable | kEditDisableGrab);
453  fEditDisabled = kEditDisableLayout | kEditDisableHeight | kEditDisableBtnEnable;
454 }
455 
456 ////////////////////////////////////////////////////////////////////////////////
457 /// Layout and move horizontal scrollbar components.
458 
459 void TGHScrollBar::Layout()
460 {
461  // Should also recalculate the slider size and range, etc.
462  fHead->Move(0, 0);
463  fHead->Resize(fgScrollBarWidth, fgScrollBarWidth);
464  fTail->Move(fWidth-fgScrollBarWidth, 0);
465  fTail->Resize(fgScrollBarWidth, fgScrollBarWidth);
466 
467  if (fSlider->GetX() != fX0) {
468  fSlider->Move(fX0, 0);
469  fSlider->Resize(50, fgScrollBarWidth);
470  fClient->NeedRedraw(fSlider);
471  }
472 }
473 
474 ////////////////////////////////////////////////////////////////////////////////
475 /// Handle a mouse button event in a horizontal scrolbar.
476 
477 Bool_t TGHScrollBar::HandleButton(Event_t *event)
478 {
479  Int_t newpos;
480 
481  if (event->fCode == kButton4) {
482  if (!fHead->IsEnabled()) {
483  return kFALSE;
484  }
485  //scroll left
486  newpos = fPos - fPsize;
487  if (newpos<0) newpos = 0;
488  SetPosition(newpos);
489  return kTRUE;
490  }
491  if (event->fCode == kButton5) {
492  if (!fTail->IsEnabled()) {
493  return kFALSE;
494  }
495  // scroll right
496  newpos = fPos + fPsize;
497  SetPosition(newpos);
498  return kTRUE;
499  }
500 
501  if (event->fType == kButtonPress) {
502  if (event->fCode == kButton3) {
503  fX0 = event->fX - fSliderSize/2;
504  fX0 = TMath::Max(fX0, fgScrollBarWidth);
505  fX0 = TMath::Min(fX0, fgScrollBarWidth + fSliderRange);
506  ULong_t pos = (ULong_t)(fX0 - fgScrollBarWidth) * (ULong_t)(fRange-fPsize) / (ULong_t)fSliderRange;
507  fPos = (Int_t)pos;
508 
509  fPos = TMath::Max(fPos, 0);
510  fPos = TMath::Min(fPos, fRange-fPsize);
511  fSlider->Move(fX0, 0);
512 
513  SendMessage(fMsgWindow, MK_MSG(kC_HSCROLL, kSB_SLIDERTRACK), fPos, 0);
514  PositionChanged(fPos);
515  return kTRUE;
516  }
517 
518  // fUser[0] contains the subwindow (child) in which the event occured
519  // (see GX11Gui.cxx)
520  Window_t subw = (Window_t)event->fUser[0];
521 
522  if (subw == fSlider->GetId()) {
523  fXp = event->fX - fX0;
524  fYp = event->fY - fY0;
525  fDragging = kTRUE;
526 
527  } else {
528 
529  if (!fRepeat)
530  fRepeat = new TSBRepeatTimer(this, 400, fSmallInc); // 500
531  fRepeat->Reset();
532  gSystem->AddTimer(fRepeat);
533  fSubw = subw;
534 
535  if (subw == fHead->GetId()) {
536  //if (!fHead->IsEnabled()) {
537  // return kFALSE;
538  //}
539  fHead->SetState(kButtonDown);
540  fPos -= fSmallInc;
541  } else if (subw == fTail->GetId()) {
542  //if (!fTail->IsEnabled()) {
543  // return kFALSE;
544  // }
545  fTail->SetState(kButtonDown);
546  fPos += fSmallInc;
547  } else if (event->fX > fgScrollBarWidth && event->fX < fX0)
548  fPos -= fPsize;
549  else if (event->fX > fX0+fSliderSize && event->fX < (Int_t)fWidth-fgScrollBarWidth)
550  fPos += fPsize;
551 
552  fPos = TMath::Max(fPos, 0);
553  fPos = TMath::Min(fPos, fRange-fPsize);
554 
555  fX0 = fgScrollBarWidth + fPos * fSliderRange / TMath::Max(fRange-fPsize, 1);
556 
557  fX0 = TMath::Max(fX0, fgScrollBarWidth);
558  fX0 = TMath::Min(fX0, fgScrollBarWidth + fSliderRange);
559 
560  fSlider->Move(fX0, 0);
561 
562  SendMessage(fMsgWindow, MK_MSG(kC_HSCROLL, kSB_SLIDERTRACK), fPos, 0);
563  PositionChanged(fPos);
564  }
565 
566  // last argument kFALSE forces all specified events to this window
567  if (fGrabPointer && !fClient->IsEditable())
568  gVirtualX->GrabPointer(fId, kButtonPressMask | kButtonReleaseMask |
569  kPointerMotionMask, kNone, kNone,
570  kTRUE, kFALSE);
571  } else {
572  fHead->SetState(kButtonUp);
573  fTail->SetState(kButtonUp);
574 
575  if (fRepeat) {
576  fRepeat->Remove();
577  fRepeat->SetTime(400); // might have been shortened in HandleTimer()
578  fSmallInc = ((TSBRepeatTimer*)fRepeat)->GetSmallInc();
579  }
580 
581  fDragging = kFALSE;
582 
583  fPos = TMath::Max(fPos, 0);
584  fPos = TMath::Min(fPos, fRange-fPsize);
585 
586  SendMessage(fMsgWindow, MK_MSG(kC_HSCROLL, kSB_SLIDERPOS), fPos, 0);
587  PositionChanged(fPos);
588 
589  if (fGrabPointer)
590  gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE); // ungrab pointer
591  }
592  return kTRUE;
593 }
594 
595 ////////////////////////////////////////////////////////////////////////////////
596 /// Handle mouse motion event in a horizontal scrollbar.
597 
598 Bool_t TGHScrollBar::HandleMotion(Event_t *event)
599 {
600  if (fDragging) {
601  fX0 = event->fX - fXp;
602  fY0 = event->fY - fYp;
603 
604  fX0 = TMath::Max(fX0, fgScrollBarWidth);
605  fX0 = TMath::Min(fX0, fgScrollBarWidth + fSliderRange);
606  fSlider->Move(fX0, 0);
607  ULong_t pos = (ULong_t)(fX0 - fgScrollBarWidth) * (ULong_t)(fRange-fPsize) / (ULong_t)fSliderRange;
608  fPos = (Int_t)pos;
609 
610  fPos = TMath::Max(fPos, 0);
611  fPos = TMath::Min(fPos, fRange-fPsize);
612 
613  SendMessage(fMsgWindow, MK_MSG(kC_HSCROLL, kSB_SLIDERTRACK), fPos, 0);
614  PositionChanged(fPos);
615  }
616  return kTRUE;
617 }
618 
619 ////////////////////////////////////////////////////////////////////////////////
620 /// Set range of horizontal scrollbar.
621 
622 void TGHScrollBar::SetRange(Int_t range, Int_t page_size)
623 {
624  fRange = TMath::Max(range, 1);
625  fPsize = TMath::Max(page_size, 0);
626  fPos = TMath::Max(fPos, 0);
627  fPos = TMath::Min(fPos, fRange-fPsize);
628 
629  fSliderSize = TMath::Max(fPsize * (fWidth - (fgScrollBarWidth << 1)) /
630  fRange, (UInt_t) 6);
631  fSliderSize = TMath::Min((UInt_t)fSliderSize, fWidth - (fgScrollBarWidth << 1));
632 
633  fSliderRange = TMath::Max(fWidth - (fgScrollBarWidth << 1) - fSliderSize,
634  (UInt_t) 1);
635 
636  fX0 = fgScrollBarWidth + fPos * fSliderRange / TMath::Max(fRange-fPsize, 1);
637  fX0 = TMath::Max(fX0, fgScrollBarWidth);
638  fX0 = TMath::Min(fX0, fgScrollBarWidth + fSliderRange);
639 
640  fSlider->Move(fX0, 0);
641  fSlider->Resize(fSliderSize, fgScrollBarWidth);
642  fClient->NeedRedraw(fSlider);
643 
644  // fPos = (fX0 - fgScrollBarWidth) * (fRange-fPsize) / fSliderRange;
645 
646  SendMessage(fMsgWindow, MK_MSG(kC_HSCROLL, kSB_SLIDERPOS), fPos, 0);
647  PositionChanged(fPos);
648  RangeChanged(fRange);
649  PageSizeChanged(fPsize);
650 }
651 
652 ////////////////////////////////////////////////////////////////////////////////
653 /// Set logical slider position of horizontal scrollbar.
654 
655 void TGHScrollBar::SetPosition(Int_t pos)
656 {
657  fPos = TMath::Max(pos, 0);
658  fPos = TMath::Min(pos, fRange-fPsize);
659 
660  fX0 = fgScrollBarWidth + fPos * fSliderRange / TMath::Max(fRange-fPsize, 1);
661  fX0 = TMath::Max(fX0, fgScrollBarWidth);
662  fX0 = TMath::Min(fX0, fgScrollBarWidth + fSliderRange);
663 
664  fSlider->Move(fX0, 0);
665  fSlider->Resize(fSliderSize, fgScrollBarWidth);
666  fClient->NeedRedraw(fSlider);
667 
668  SendMessage(fMsgWindow, MK_MSG(kC_HSCROLL, kSB_SLIDERPOS), fPos, 0);
669  PositionChanged(fPos);
670 }
671 
672 
673 ////////////////////////////////////////////////////////////////////////////////
674 /// Create a vertical scrollbar.
675 
676 TGVScrollBar::TGVScrollBar(const TGWindow *p, UInt_t w, UInt_t h,
677  UInt_t options, ULong_t back) :
678  TGScrollBar(p, w, h, options, back)
679 {
680  fHeadPic = fClient->GetPicture("arrow_up.xpm");
681  fTailPic = fClient->GetPicture("arrow_down.xpm");
682 
683  if (!fHeadPic || !fTailPic) {
684  Error("TGVScrollBar", "arrow_*.xpm not found");
685  return;
686  }
687  fHead = new TGScrollBarElement(this, fHeadPic, fgScrollBarWidth, fgScrollBarWidth,
688  kRaisedFrame);
689  fTail = new TGScrollBarElement(this, fTailPic, fgScrollBarWidth, fgScrollBarWidth,
690  kRaisedFrame);
691  fSlider = new TGScrollBarElement(this, 0, fgScrollBarWidth, 50,
692  kRaisedFrame);
693 
694  gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier, kButtonPressMask |
695  kButtonReleaseMask | kPointerMotionMask, kNone, kNone);
696 
697  fDragging = kFALSE;
698  fX0 = fY0 = (fgScrollBarWidth = TMath::Max(fgScrollBarWidth, 5));
699  fPos = 0;
700 
701  fRange = TMath::Max((Int_t) h - (fgScrollBarWidth << 1), 1);
702  fPsize = fRange >> 1;
703 
704  fSliderSize = 50;
705  fSliderRange = 1;
706 
707  fHead->SetEditDisabled(kEditDisable | kEditDisableGrab);
708  fTail->SetEditDisabled(kEditDisable | kEditDisableGrab);
709  fSlider->SetEditDisabled(kEditDisable | kEditDisableGrab);
710  fEditDisabled = kEditDisableLayout | kEditDisableWidth | kEditDisableBtnEnable;
711 }
712 
713 ////////////////////////////////////////////////////////////////////////////////
714 /// Layout and move vertical scrollbar components.
715 
716 void TGVScrollBar::Layout()
717 {
718  // Should recalculate fSliderSize, fSliderRange, fX0, fY0, etc. too...
719  fHead->Move(0, 0);
720  fHead->Resize(fgScrollBarWidth, fgScrollBarWidth);
721  fTail->Move(0, fHeight-fgScrollBarWidth);
722  fTail->Resize(fgScrollBarWidth, fgScrollBarWidth);
723 
724  if (fSlider->GetY() != fY0) {
725  fSlider->Move(0, fY0);
726  fSlider->Resize(fgScrollBarWidth, 50);
727  fClient->NeedRedraw(fSlider);
728  }
729 }
730 
731 ////////////////////////////////////////////////////////////////////////////////
732 /// Handle mouse button event in vertical scrollbar.
733 
734 Bool_t TGVScrollBar::HandleButton(Event_t *event)
735 {
736  Int_t newpos;
737 
738  if (event->fCode == kButton4) {
739  if (!fHead->IsEnabled()) {
740  return kFALSE;
741  }
742  //scroll up
743  newpos = fPos - fPsize;
744  if (newpos<0) newpos = 0;
745  SetPosition(newpos);
746  return kTRUE;
747  }
748  if (event->fCode == kButton5) {
749  if (!fTail->IsEnabled()) {
750  return kFALSE;
751  }
752 
753  // scroll down
754  newpos = fPos + fPsize;
755  SetPosition(newpos);
756  return kTRUE;
757  }
758 
759  if (event->fType == kButtonPress) {
760  if (event->fCode == kButton3) {
761  fY0 = event->fY - fSliderSize/2;
762  fY0 = TMath::Max(fY0, fgScrollBarWidth);
763  fY0 = TMath::Min(fY0, fgScrollBarWidth + fSliderRange);
764  ULong_t pos = (ULong_t)(fY0 - fgScrollBarWidth) * (ULong_t)(fRange-fPsize) / (ULong_t)fSliderRange;
765  fPos = (Int_t)pos;
766 
767  fPos = TMath::Max(fPos, 0);
768  fPos = TMath::Min(fPos, fRange-fPsize);
769  fSlider->Move(0, fY0);
770 
771  SendMessage(fMsgWindow, MK_MSG(kC_VSCROLL, kSB_SLIDERTRACK), fPos, 0);
772  PositionChanged(fPos);
773  return kTRUE;
774  }
775 
776  // fUser[0] contains the subwindow (child) in which the event occured
777  // (see GX11Gui.cxx)
778  Window_t subw = (Window_t)event->fUser[0];
779 
780  if (subw == fSlider->GetId()) {
781  fXp = event->fX - fX0;
782  fYp = event->fY - fY0;
783  fDragging = kTRUE;
784 
785  } else {
786 
787  if (!fRepeat)
788  fRepeat = new TSBRepeatTimer(this, 400, fSmallInc); // 500
789  fRepeat->Reset();
790  gSystem->AddTimer(fRepeat);
791  fSubw = subw;
792 
793  if (subw == fHead->GetId()) {
794  //if (!fHead->IsEnabled()) {
795  // return kFALSE;
796  // }
797  fHead->SetState(kButtonDown);
798  fPos -= fSmallInc;
799  } else if (subw == fTail->GetId()) {
800  //if (!fTail->IsEnabled()) {
801  // return kFALSE;
802  //}
803  fTail->SetState(kButtonDown);
804  fPos += fSmallInc;
805  } else if (event->fY > fgScrollBarWidth && event->fY < fY0)
806  fPos -= fPsize;
807  else if (event->fY > fY0+fSliderSize && event->fY < (Int_t)fHeight-fgScrollBarWidth)
808  fPos += fPsize;
809 
810  fPos = TMath::Max(fPos, 0);
811  fPos = TMath::Min(fPos, fRange-fPsize);
812 
813  ULong_t y0 = (ULong_t)fgScrollBarWidth + (ULong_t)fPos * (ULong_t)fSliderRange / (ULong_t)TMath::Max(fRange-fPsize, 1);
814  fY0 = (Int_t)y0;
815 
816  fY0 = TMath::Max(fY0, fgScrollBarWidth);
817  fY0 = TMath::Min(fY0, fgScrollBarWidth + fSliderRange);
818 
819  fSlider->Move(0, fY0);
820 
821  SendMessage(fMsgWindow, MK_MSG(kC_VSCROLL, kSB_SLIDERTRACK), fPos, 0);
822  PositionChanged(fPos);
823  }
824 
825  // last argument kFALSE forces all specified events to this window
826  if (fGrabPointer && !fClient->IsEditable())
827  gVirtualX->GrabPointer(fId, kButtonPressMask | kButtonReleaseMask |
828  kPointerMotionMask, kNone, kNone,
829  kTRUE, kFALSE);
830  } else {
831  fHead->SetState(kButtonUp);
832  fTail->SetState(kButtonUp);
833 
834  if (fRepeat) {
835  fRepeat->Remove();
836  fRepeat->SetTime(400); // might have been shortened in HandleTimer()
837  fSmallInc = ((TSBRepeatTimer*)fRepeat)->GetSmallInc();
838  }
839 
840  fDragging = kFALSE;
841 
842  fPos = TMath::Max(fPos, 0);
843  fPos = TMath::Min(fPos, fRange-fPsize);
844 
845  SendMessage(fMsgWindow, MK_MSG(kC_VSCROLL, kSB_SLIDERPOS), fPos, 0);
846  PositionChanged(fPos);
847 
848  if (fGrabPointer) {
849  gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE); // ungrab pointer
850  }
851  }
852  return kTRUE;
853 }
854 
855 ////////////////////////////////////////////////////////////////////////////////
856 /// Handle mouse motion in a vertical scrollbar.
857 
858 Bool_t TGVScrollBar::HandleMotion(Event_t *event)
859 {
860  if (fDragging) {
861  fX0 = event->fX - fXp;
862  fY0 = event->fY - fYp;
863 
864  fY0 = TMath::Max(fY0, fgScrollBarWidth);
865  fY0 = TMath::Min(fY0, fgScrollBarWidth + fSliderRange);
866  fSlider->Move(0, fY0);
867  ULong_t pos = (ULong_t)(fY0 - fgScrollBarWidth) * (ULong_t)(fRange-fPsize) / fSliderRange;
868  fPos = (Int_t)pos;
869 
870  fPos = TMath::Max(fPos, 0);
871  fPos = TMath::Min(fPos, fRange-fPsize);
872 
873  SendMessage(fMsgWindow, MK_MSG(kC_VSCROLL, kSB_SLIDERTRACK), fPos, 0);
874  PositionChanged(fPos);
875  }
876  return kTRUE;
877 }
878 
879 ////////////////////////////////////////////////////////////////////////////////
880 /// Set range of vertical scrollbar.
881 
882 void TGVScrollBar::SetRange(Int_t range, Int_t page_size)
883 {
884  fRange = TMath::Max(range, 1);
885  fPsize = TMath::Max(page_size, 0);
886  fPos = TMath::Max(fPos, 0);
887  fPos = TMath::Min(fPos, fRange-fPsize);
888 
889  fSliderSize = TMath::Max(fPsize * (fHeight - (fgScrollBarWidth << 1)) /
890  fRange, (UInt_t) 6);
891  fSliderSize = TMath::Min((UInt_t)fSliderSize, fHeight - (fgScrollBarWidth << 1));
892 
893  fSliderRange = TMath::Max(fHeight - (fgScrollBarWidth << 1) - fSliderSize,
894  (UInt_t)1);
895 
896  ULong_t y0 = (ULong_t)fgScrollBarWidth + (ULong_t)fPos * (ULong_t)fSliderRange / (ULong_t)TMath::Max(fRange-fPsize, 1);
897  fY0 = (Int_t)y0;
898  fY0 = TMath::Max(fY0, fgScrollBarWidth);
899  fY0 = TMath::Min(fY0, fgScrollBarWidth + fSliderRange);
900 
901  fSlider->Move(0, fY0);
902  fSlider->Resize(fgScrollBarWidth, fSliderSize);
903  fClient->NeedRedraw(fSlider);
904 
905  // fPos = (fY0 - fgScrollBarWidth) * (fRange-fPsize) / fSliderRange;
906 
907 
908  SendMessage(fMsgWindow, MK_MSG(kC_VSCROLL, kSB_SLIDERPOS), fPos, 0);
909  PositionChanged(fPos);
910  RangeChanged(fRange);
911  PageSizeChanged(fPsize);
912 }
913 
914 ////////////////////////////////////////////////////////////////////////////////
915 /// Set logical slider position of vertical scrollbar.
916 
917 void TGVScrollBar::SetPosition(Int_t pos)
918 {
919  fPos = TMath::Max(pos, 0);
920  fPos = TMath::Min(pos, fRange-fPsize);
921 
922  ULong_t y0 = (ULong_t)fgScrollBarWidth + (ULong_t)fPos * (ULong_t)fSliderRange / (ULong_t)TMath::Max(fRange-fPsize, 1);
923  fY0 = (Int_t)y0;
924  fY0 = TMath::Max(fY0, fgScrollBarWidth);
925  fY0 = TMath::Min(fY0, fgScrollBarWidth + fSliderRange);
926 
927  fSlider->Move(0, fY0);
928  fSlider->Resize(fgScrollBarWidth, fSliderSize);
929  fClient->NeedRedraw(fSlider);
930 
931  SendMessage(fMsgWindow, MK_MSG(kC_VSCROLL, kSB_SLIDERPOS), fPos, 0);
932  PositionChanged(fPos);
933 }
934 
935 ////////////////////////////////////////////////////////////////////////////////
936 /// Save an horizontal scrollbar as a C++ statement(s) on output stream out.
937 
938 void TGHScrollBar::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
939 {
940  if (fBackground != GetDefaultFrameBackground()) SaveUserColor(out, option);
941 
942  out <<" TGHScrollBar *";
943  out << GetName() << " = new TGHScrollBar(" << fParent->GetName()
944  << "," << GetWidth() << "," << GetHeight();
945 
946  if (fBackground == GetDefaultFrameBackground()) {
947  if (!GetOptions()) {
948  out <<");" << std::endl;
949  } else {
950  out << "," << GetOptionString() <<");" << std::endl;
951  }
952  } else {
953  out << "," << GetOptionString() << ",ucolor);" << std::endl;
954  }
955  if (option && strstr(option, "keep_names"))
956  out << " " << GetName() << "->SetName(\"" << GetName() << "\");" << std::endl;
957 
958  out << " " << GetName() <<"->SetRange(" << GetRange() << "," << GetPageSize() << ");" << std::endl;
959  out << " " << GetName() <<"->SetPosition(" << GetPosition() << ");" << std::endl;
960 }
961 
962 ////////////////////////////////////////////////////////////////////////////////
963 /// Save an vertical scrollbar as a C++ statement(s) on output stream out.
964 
965 void TGVScrollBar::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
966 {
967  if (fBackground != GetDefaultFrameBackground()) SaveUserColor(out, option);
968 
969  out<<" TGVScrollBar *";
970  out << GetName() <<" = new TGVScrollBar("<< fParent->GetName()
971  << "," << GetWidth() << "," << GetHeight();
972 
973  if (fBackground == GetDefaultFrameBackground()) {
974 
975  if (!GetOptions()) {
976  out <<");" << std::endl;
977  } else {
978  out << "," << GetOptionString() <<");" << std::endl;
979  }
980  } else {
981  out << "," << GetOptionString() << ",ucolor);" << std::endl;
982  }
983  if (option && strstr(option, "keep_names"))
984  out << " " << GetName() << "->SetName(\"" << GetName() << "\");" << std::endl;
985 
986  out << " " << GetName() <<"->SetRange(" << GetRange() << "," << GetPageSize() << ");" << std::endl;
987  out << " " << GetName() <<"->SetPosition(" << GetPosition() << ");" << std::endl;
988 }