Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGColorDialog.cxx
Go to the documentation of this file.
1 // @(#)root/gui:$Id: c1ecfb3a4b91442ae3b6fe3059ae838e463f2f56 $
2 // Author: Bertrand Bellenot + Fons Rademakers 22/08/02
3 // Author: Ilka Antcheva (color wheel support) 16/03/07
4 
5 /*************************************************************************
6  * Copyright (C) 1995-2002, Rene Brun and Fons Rademakers. *
7  * All rights reserved. *
8  * *
9  * For the licensing terms see $ROOTSYS/LICENSE. *
10  * For the list of contributors see $ROOTSYS/README/CREDITS. *
11  *************************************************************************/
12 /**************************************************************************
13 
14  This source is based on Xclass95, a Win95-looking GUI toolkit.
15  Copyright (C) 1996, 1997 David Barth, Ricky Ralston, Hector Peraza.
16 
17  Xclass95 is free software; you can redistribute it and/or
18  modify it under the terms of the GNU Library General Public
19  License as published by the Free Software Foundation; either
20  version 2 of the License, or (at your option) any later version.
21 
22 **************************************************************************/
23 
24 //////////////////////////////////////////////////////////////////////////
25 // //
26 // TGColorPalette, TGColorPick and TGColorDialog. //
27 // //
28 // The TGColorPalette is a widget showing an matrix of color cells. The //
29 // colors can be set and selected. //
30 // //
31 // The TGColorPick is a widget which allows a color to be picked from //
32 // HLS space. It consists of two elements: a color map window from //
33 // where the user can select the hue and saturation level of a color, //
34 // and a slider to select color's lightness. //
35 // //
36 // Selecting a color in these two widgets will generate the event: //
37 // kC_COLORSEL, kCOL_CLICK, widget id, 0. //
38 // and the signal: //
39 // ColorSelected(Pixel_t color) //
40 // //
41 // The TGColorDialog presents a full featured color selection dialog. //
42 // It uses 2 TGColorPalette's and the TGColorPick widgets. //
43 // //
44 //////////////////////////////////////////////////////////////////////////
45 
46 #include <stdlib.h>
47 
48 #include "TGLabel.h"
49 #include "TGMsgBox.h" // for ID_OK, ID_CANCEL
50 #include "TGLayout.h"
51 #include "TGGC.h"
52 #include "KeySymbols.h"
53 #include "TGColorDialog.h"
54 #include "TGTextEntry.h"
55 #include "TGButton.h"
56 #include "TGResourcePool.h"
57 #include "TColor.h"
58 #include "TColorWheel.h"
59 #include "TGColorSelect.h"
60 #include "TGTab.h"
61 #include "TRootEmbeddedCanvas.h"
62 #include "TCanvas.h"
63 #include "TROOT.h"
64 #include "TMath.h"
65 
66 ClassImp(TGColorPalette);
67 ClassImp(TGColorPick);
68 ClassImp(TGColorDialog);
69 
70 
71 // TODO:
72 // - implement "custom" colors.
73 // - optimize the code, specially the one handling the fColormap image
74 // and dithering in pseudo-color modes; remove duplicated code.
75 // - improve the color allocation routine.
76 // - use a buffering pixmap for the fColormap image.
77 
78 enum EColorDialog {
79  kCDLG_OK = 100,
80  kCDLG_CANCEL,
81  kCDLG_PREVIEW,
82  kCDLG_ADD,
83 
84  kCDLG_SPALETTE = 200,
85  kCDLG_CPALETTE,
86  kCDLG_COLORPICK,
87 
88  kCDLG_HTE = 300,
89  kCDLG_LTE,
90  kCDLG_STE,
91  kCDLG_RTE,
92  kCDLG_GTE,
93  kCDLG_BTE,
94  kCDLG_ALE
95 };
96 
97 enum EColorPick {
98  kCLICK_NONE,
99  kCLICK_HS,
100  kCLICK_L
101 };
102 
103 enum EColorImage {
104  kIMG_HS,
105  kIMG_L
106 };
107 
108 // "User" defined colors
109 
110 static ULong_t gUcolor[24] = { 0xff000000 };
111 
112 
113 ////////////////////////////////////////////////////////////////////////////////
114 /// TGColorPalette widget: this is just a grid of color cells of the
115 /// specified size. Colors can be selected by clicking on them or by
116 /// using the arrow keys.
117 
118 TGColorPalette::TGColorPalette(const TGWindow *p, Int_t cols, Int_t rows, Int_t id) :
119  TGFrame(p, 10, 10, kChildFrame)
120 {
121  fWidgetId = id;
122  fWidgetFlags = kWidgetIsEnabled;
123  fMsgWindow = p;
124  fDrawGC = *fClient->GetResourcePool()->GetFrameGC();
125 
126  fCw = 20;
127  fCh = 17;
128 
129  fRows = rows;
130  fCols = cols;
131 
132  fCx = fCy = 0;
133 
134  fPixels = new ULong_t[fRows * fCols];
135 
136  for (Int_t i = 0; i < fRows * fCols; ++i) {
137  fPixels[i] = TColor::RGB2Pixel(255, 255, 255);
138  }
139 
140  gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
141  kButtonPressMask | kButtonReleaseMask |
142  kPointerMotionMask, kNone, kNone);
143 
144  AddInput(kKeyPressMask | kEnterWindowMask | kLeaveWindowMask |
145  kFocusChangeMask | kStructureNotifyMask);
146  fEditDisabled = kEditDisable;
147 }
148 
149 ////////////////////////////////////////////////////////////////////////////////
150 /// Destructor.
151 
152 TGColorPalette::~TGColorPalette()
153 {
154  delete [] fPixels;
155 }
156 
157 ////////////////////////////////////////////////////////////////////////////////
158 /// Handle button events in color palette
159 
160 Bool_t TGColorPalette::HandleButton(Event_t *event)
161 {
162  if (event->fCode != kButton1)
163  return kFALSE;
164 
165  if ((event->fType == kButtonPress) && HasFocus())
166  WantFocus();
167 
168  Int_t cx = event->fX / (fCw + 5);
169  Int_t cy = event->fY / (fCh + 5);
170 
171  if (cx >= 0 && cx < fCols && cy >= 0 && cy < fRows) {
172 
173  DrawFocusHilite(kFALSE);
174 
175  fCx = cx;
176  fCy = cy;
177 
178  DrawFocusHilite(kTRUE);
179 
180  SendMessage(fMsgWindow, MK_MSG(kC_COLORSEL, kCOL_CLICK), fWidgetId, 0);
181  ColorSelected();
182  }
183 
184  return kTRUE;
185 }
186 
187 ////////////////////////////////////////////////////////////////////////////////
188 /// Handle mouse motion events in color palette.
189 
190 Bool_t TGColorPalette::HandleMotion(Event_t *event)
191 {
192  if (!IsEnabled())
193  return kTRUE;
194 
195  Int_t cx = event->fX / (fCw + 5);
196  Int_t cy = event->fY / (fCh + 5);
197 
198  if (cx >= 0 && cx < fCols && cy >= 0 && cy < fRows) {
199 
200  DrawFocusHilite(kFALSE);
201 
202  fCx = cx;
203  fCy = cy;
204 
205  DrawFocusHilite(kTRUE);
206 
207  SendMessage(fMsgWindow, MK_MSG(kC_COLORSEL, kCOL_CLICK), fWidgetId, 0);
208  ColorSelected();
209  }
210 
211  return kTRUE;
212 }
213 
214 ////////////////////////////////////////////////////////////////////////////////
215 /// Handle keyboard events in color palette.
216 
217 Bool_t TGColorPalette::HandleKey(Event_t *event)
218 {
219  Char_t input[10];
220  UInt_t keysym;
221 
222  if (event->fType == kGKeyPress) {
223 
224  gVirtualX->LookupString(event, input, sizeof(input), keysym);
225 
226  Int_t cx = fCx;
227  Int_t cy = fCy;
228 
229  switch ((EKeySym)keysym) {
230  case kKey_Left:
231  if (cx > 0) --cx;
232  break;
233 
234  case kKey_Right:
235  if (cx < fCols - 1) ++cx;
236  break;
237 
238  case kKey_Up:
239  if (cy > 0) --cy;
240  break;
241 
242  case kKey_Down:
243  if (cy < fRows - 1) ++cy;
244  break;
245 
246  case kKey_Home:
247  cx = cy = 0;
248  break;
249 
250  case kKey_End:
251  cx = fCols - 1;
252  cy = fRows - 1;
253  break;
254 
255  default:
256  break;
257  }
258 
259  if (cx != fCx || cy != fCy) {
260 
261  DrawFocusHilite(kFALSE);
262 
263  fCx = cx;
264  fCy = cy;
265 
266  DrawFocusHilite(kTRUE);
267 
268  SendMessage(fMsgWindow, MK_MSG(kC_COLORSEL, kCOL_CLICK), fWidgetId, 0);
269  ColorSelected();
270  }
271  }
272 
273  return kTRUE;
274 }
275 
276 ////////////////////////////////////////////////////////////////////////////////
277 /// Set color entries in color samples.
278 
279 void TGColorPalette::SetColors(ULong_t colors[])
280 {
281  for (Int_t i = 0; i < fRows * fCols; ++i)
282  SetColor(i, colors[i]);
283  gClient->NeedRedraw(this);
284 }
285 
286 ////////////////////////////////////////////////////////////////////////////////
287 /// Set color at index ix of color entries.
288 
289 void TGColorPalette::SetColor(Int_t ix, ULong_t color)
290 {
291  fPixels[ix] = color;
292  gClient->NeedRedraw(this);
293 }
294 
295 ////////////////////////////////////////////////////////////////////////////////
296 /// Set current cell color.
297 
298 void TGColorPalette::SetCurrentCellColor(ULong_t color)
299 {
300  SetColor(fCy * fCols + fCx, color);
301 }
302 
303 ////////////////////////////////////////////////////////////////////////////////
304 /// Set color cell size.
305 
306 void TGColorPalette::SetCellSize(Int_t w, Int_t h)
307 {
308  fCw = w;
309  fCh = h;
310  gClient->NeedRedraw(this);
311 }
312 
313 ////////////////////////////////////////////////////////////////////////////////
314 /// Return currently selected color value.
315 
316 ULong_t TGColorPalette::GetCurrentColor() const
317 {
318  if (fCx >= 0 && fCy >= 0)
319  return GetColorByIndex(fCy * fCols + fCx);
320  else
321  return TColor::RGB2Pixel(0, 0, 0);
322 }
323 
324 ////////////////////////////////////////////////////////////////////////////////
325 /// Redraw color palette.
326 
327 void TGColorPalette::DoRedraw()
328 {
329  Int_t i, j, k, x, y;
330 
331  k = 0;
332  y = 2;
333  for (i = 0; i < fRows; ++i) {
334  x = 2;
335  for (j = 0; j < fCols; ++j) {
336  Draw3dRectangle(kSunkenFrame | kDoubleBorder, x, y, fCw, fCh);
337  fDrawGC.SetForeground(fPixels[k++]);
338  gVirtualX->FillRectangle(fId, fDrawGC(), x + 2, y + 2, fCw - 4, fCh - 4);
339  x += fCw + 5;
340  }
341  y += fCh + 5;
342  }
343 
344  DrawFocusHilite(kTRUE);
345 }
346 
347 ////////////////////////////////////////////////////////////////////////////////
348 /// Add keyboard input.
349 
350 void TGColorPalette::GotFocus()
351 {
352  AddInput(kKeyPressMask | kKeyReleaseMask);
353 }
354 
355 ////////////////////////////////////////////////////////////////////////////////
356 /// Remove keyboard input.
357 
358 void TGColorPalette::LostFocus()
359 {
360  RemoveInput(kKeyPressMask | kKeyReleaseMask);
361  gClient->NeedRedraw(this);
362 }
363 
364 ////////////////////////////////////////////////////////////////////////////////
365 /// Draw a highlight rectangle around cell obtaining focus.
366 
367 void TGColorPalette::DrawFocusHilite(Int_t onoff)
368 {
369  if (fCx >= 0 && fCy >= 0) {
370  GContext_t gc = onoff ? GetShadowGC()() : GetBckgndGC()();
371  gVirtualX->DrawRectangle(fId, gc, fCx * (fCw + 5) + 0, fCy * (fCh + 5) + 0,
372  fCw + 3, fCh + 3);
373  }
374 }
375 
376 
377 ////////////////////////////////////////////////////////////////////////////////
378 /// TGColorPick constructor.
379 /// TGColorPick is a widget which allows a color to be picked from HLS space.
380 /// It consists of two elements: a color map window from where the user can
381 /// select the hue and saturation level of a color, and a slider to select
382 /// color's lightness.
383 
384 TGColorPick::TGColorPick(const TGWindow *p, Int_t w, Int_t h, Int_t id) :
385  TGFrame(p, w, h, kChildFrame), fCursorGC(GetBlackGC())
386 {
387  UInt_t iw, ih;
388 
389  fWidgetId = id;
390  fWidgetFlags = kWidgetIsEnabled;
391  fMsgWindow = p;
392 
393  fColormapRect.fX = 1;
394  fColormapRect.fY = 1;
395  fColormapRect.fWidth = w - 33 - 2;
396  fColormapRect.fHeight = h - 2;
397  fSliderRect.fX = w - 18 - 2;
398  fSliderRect.fY = 1;
399  fSliderRect.fWidth = 10;
400  fSliderRect.fHeight = h - 2;
401 
402  fNColors = 0;
403 
404  if (!p) {
405  MakeZombie();
406  // coverity[uninit_member]
407  return;
408  }
409  CreateImages();
410  gVirtualX->GetImageSize(fLimage, iw, ih);
411 
412  fCx = 0;
413  fCy = 0;
414  fCz = (Int_t)ih / 2;
415 
416  fClick = kCLICK_NONE;
417 
418  UpdateCurrentColor();
419  InitImages();
420 
421  gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
422  kButtonPressMask | kButtonReleaseMask |
423  kPointerMotionMask, kNone, kNone);
424 
425  AddInput(kKeyPressMask | kEnterWindowMask | kLeaveWindowMask |
426  kFocusChangeMask | kStructureNotifyMask);
427  fEditDisabled = kEditDisable;
428 }
429 
430 ////////////////////////////////////////////////////////////////////////////////
431 /// TGColorPick destructor.
432 
433 TGColorPick::~TGColorPick()
434 {
435  if (IsZombie()) return;
436  gVirtualX->DeleteImage(fHSimage);
437  gVirtualX->DeleteImage(fLimage);
438  FreeColors();
439 }
440 
441 ////////////////////////////////////////////////////////////////////////////////
442 /// Handle mouse button events in color pick widget.
443 
444 Bool_t TGColorPick::HandleButton(Event_t *event)
445 {
446  if (event->fCode != kButton1) return kFALSE;
447 
448  if (event->fType == kButtonPress) {
449  if ((event->fX > fColormapRect.fX) && (event->fX < fColormapRect.fX + fColormapRect.fWidth) &&
450  (event->fY > fColormapRect.fY) && (event->fY < fColormapRect.fY + fColormapRect.fHeight)) {
451 
452  fClick = kCLICK_HS;
453  SetHScursor(event->fX - fColormapRect.fX, event->fY - fColormapRect.fY);
454 
455  } else if (event->fX > fSliderRect.fX) {
456 
457  fClick = kCLICK_L;
458  SetLcursor(event->fY - fSliderRect.fY);
459 
460  }
461  } else { // ButtonRelease
462 
463  fClick = kCLICK_NONE;
464 
465  }
466 
467  UpdateCurrentColor();
468  if (fClick == kCLICK_HS) SetSliderColor();
469 
470  SendMessage(fMsgWindow, MK_MSG(kC_COLORSEL, kCOL_CLICK), fWidgetId, kFALSE);
471  ColorSelected();
472 
473  return kTRUE;
474 }
475 
476 ////////////////////////////////////////////////////////////////////////////////
477 /// Handle mouse motion events in color pick widget.
478 
479 Bool_t TGColorPick::HandleMotion(Event_t *event)
480 {
481  if (!IsEnabled())
482  return kTRUE;
483 
484  if (fClick == kCLICK_HS) {
485 
486  SetHScursor(event->fX - fColormapRect.fX, event->fY - fColormapRect.fY);
487 
488  } else if (fClick == kCLICK_L) {
489 
490  SetLcursor(event->fY - fSliderRect.fY);
491 
492  } else {
493 
494  return kTRUE;
495 
496  }
497 
498  UpdateCurrentColor();
499  if (fClick == kCLICK_HS) SetSliderColor();
500 
501  SendMessage(fMsgWindow, MK_MSG(kC_COLORSEL, kCOL_CLICK), fWidgetId, kFALSE);
502  ColorSelected();
503 
504  return kTRUE;
505 }
506 
507 ////////////////////////////////////////////////////////////////////////////////
508 /// Create colormap and color slider images.
509 
510 void TGColorPick::CreateImages()
511 {
512  UInt_t width, height;
513 
514  width = fColormapRect.fWidth;
515  height = fColormapRect.fHeight;
516  fHSimage = gVirtualX->CreateImage(width, height);
517  width = fSliderRect.fWidth;
518  height = fSliderRect.fHeight;
519  fLimage = gVirtualX->CreateImage(width, height);
520 }
521 
522 ////////////////////////////////////////////////////////////////////////////////
523 /// Try to allocate first a palette of 64 colors. Used by the dithered
524 /// version of the color maps.
525 
526 void TGColorPick::AllocColors()
527 {
528  ColorStruct_t color;
529  Int_t i;
530 
531  for (i = 0; i < 64; ++i) {
532  Int_t cc[4] = { 0, 21845, 43691, 65535 };
533  color.fPixel = 0;
534  color.fRed = cc[i & 0x3];
535  color.fGreen = cc[(i >> 2) & 0x3];
536  color.fBlue = cc[(i >> 4) & 0x3];
537  if (gVirtualX->AllocColor(gVirtualX->GetColormap(), color) == 0)
538  break;
539  fColormap[i][0] = color.fRed / 256;
540  fColormap[i][1] = color.fGreen / 256;
541  fColormap[i][2] = color.fBlue / 256;
542  fPixel[i] = color.fPixel;
543  }
544 
545  fNColors = i;
546  if (fNColors == 64) return; // success
547 
548  // Failed, try a simpler 27-color.
549 
550  FreeColors();
551 
552  for (i = 0; i < 27; ++i) {
553  Int_t cc[3] = { 0, 32768, 65535 };
554  color.fPixel = 0;
555  color.fRed = cc[i % 3];
556  color.fGreen = cc[(i / 3) % 3];
557  color.fBlue = cc[(i / 9) % 3];
558  if (gVirtualX->AllocColor(gVirtualX->GetColormap(), color) == 0)
559  break;
560  fColormap[i][0] = color.fRed / 256;
561  fColormap[i][1] = color.fGreen / 256;
562  fColormap[i][2] = color.fBlue / 256;
563  fPixel[i] = color.fPixel;
564  }
565 
566  fNColors = i;
567  if (fNColors == 27) return; // success
568 
569  // Failed, try then a much simpler 8-color.
570 
571  FreeColors();
572 
573  for (i = 0; i < 8; ++i) {
574  color.fPixel = 0;
575  color.fRed = (i & 1) * 65535;
576  color.fGreen = ((i >> 1) & 1) * 65535;
577  color.fBlue = ((i >> 2) & 1) * 65535;
578  if (gVirtualX->AllocColor(gVirtualX->GetColormap(), color) == 0)
579  break;
580  fColormap[i][0] = color.fRed / 256;
581  fColormap[i][1] = color.fGreen / 256;
582  fColormap[i][2] = color.fBlue / 256;
583  fPixel[i] = color.fPixel;
584  }
585 
586  fNColors = i;
587  if (fNColors == 8) return; // success
588 
589  // Failed, try to get at least 8 closest colors...
590  // (TODO: search for closest colors in the colormap, right now we just
591  // get as many as exact colors we can for the 8-color palette)
592 
593  FreeColors();
594 
595  for (i = 0; i < 8; ++i) {
596  color.fPixel = 0;
597  color.fRed = (i & 1) * 65535;
598  color.fGreen = ((i >> 1) & 1) * 65535;
599  color.fBlue = ((i >> 2) & 1) * 65535;
600  if (gVirtualX->AllocColor(gVirtualX->GetColormap(), color) != 0) {
601  fColormap[fNColors][0] = color.fRed / 256;
602  fColormap[fNColors][1] = color.fGreen / 256;
603  fColormap[fNColors][2] = color.fBlue / 256;
604  fPixel[fNColors++] = color.fPixel;
605  }
606  }
607 
608  // continue with what we got...
609 }
610 
611 ////////////////////////////////////////////////////////////////////////////////
612 /// Free allocated colors.
613 
614 void TGColorPick::FreeColors()
615 {
616  for (Int_t i = 0; i < fNColors; i++)
617  gVirtualX->FreeColor(gVirtualX->GetColormap(), fPixel[i]);
618  fNColors = 0;
619 }
620 
621 ////////////////////////////////////////////////////////////////////////////////
622 /// Create a dithered version of the color map and lightness images for
623 /// display modes with reduced number of colors. The Floyd-Steinberg error
624 /// diffusion dithering algorithm is used.
625 /// This routine is called in PseudoColor modes only.
626 
627 void TGColorPick::CreateDitheredImage(Pixmap_t image, Int_t which)
628 {
629  const Int_t kWidth = 20;
630 
631  ColorStruct_t line[kWidth];
632  struct { Int_t r, g, b; } ed[kWidth], ef;
633  Int_t x, y, c, v, e[4], nc = 0;
634  Int_t r, g, b;
635  Int_t h, l, s;
636  Long_t dist, sdist;
637  Int_t iw, ih;
638 
639  gVirtualX->GetImageSize(image, (UInt_t&) iw, (UInt_t&) ih);
640 
641  for (x = 0; x < iw; ++x) {
642  ed[x].r = ed[x].g = ed[x].b = 0;
643  }
644 
645  if (fNColors == 0) AllocColors();
646 
647  for (y = 0; y < ih; ++y) {
648 
649  if (which == kIMG_HS) {
650 
651  for (x = 0; x < iw; ++x) {
652 
653  h = x * 255 / iw;
654  l = 128;
655  s = (ih - y) * 255 / ih;
656 
657  TColor::HLS2RGB(h, l, s, r, g, b);
658 
659  line[x].fRed = r;
660  line[x].fGreen = g;
661  line[x].fBlue = b;
662  }
663 
664  } else if (which == kIMG_L) {
665 
666  TColor::Pixel2RGB(fCurrentColor, r, g, b);
667  TColor::RGB2HLS(r, g, b, h, l, s);
668 
669  Int_t ll = (ih - y) * 255 / ih;
670 
671  TColor::HLS2RGB(h, ll, s, r, g, b);
672 
673  for (x = 0; x < iw; ++x) {
674  line[x].fRed = r;
675  line[x].fGreen = g;
676  line[x].fBlue = b;
677  }
678 
679  } else {
680 
681  return;
682 
683  }
684 
685  ef.r = ef.g = ef.b = 0; // no forward error for first pixel
686 
687  for (x = 0; x < iw; ++x) {
688 
689  // add errors from previous line
690 
691  v = line[x].fRed + ed[x].r;
692  if (v < 0) v = 0; else if (v > 255) v = 255;
693  line[x].fRed = v;
694 
695  v = line[x].fGreen + ed[x].g;
696  if (v < 0) v = 0; else if (v > 255) v = 255;
697  line[x].fGreen = v;
698 
699  v = line[x].fBlue + ed[x].b;
700  if (v < 0) v = 0; else if (v > 255) v = 255;
701  line[x].fBlue = v;
702 
703  }
704 
705  for (x = 0; x < iw; ++x) {
706 
707  // add forward errors
708 
709  v = line[x].fRed + ef.r;
710  if (v < 0) v = 0; else if (v > 255) v = 255;
711  line[x].fRed = v;
712 
713  v = line[x].fGreen + ef.g;
714  if (v < 0) v = 0; else if (v > 255) v = 255;
715  line[x].fGreen = v;
716 
717  v = line[x].fBlue + ef.b;
718  if (v < 0) v = 0; else if (v > 255) v = 255;
719  line[x].fBlue = v;
720 
721  // find the nearest color in colormap[]
722 
723  sdist = 255L * 255L * 255L;
724  for (c = 0; c < fNColors; ++c) {
725 
726  Int_t dr = line[x].fRed - fColormap[c][0];
727  Int_t dg = line[x].fGreen - fColormap[c][1];
728  Int_t db = line[x].fBlue - fColormap[c][2];
729 
730  dist = dr * dr + dg * dg + db * db;
731  if (dist < sdist) {
732  nc = c;
733  sdist = dist;
734  }
735  }
736 
737  gVirtualX->PutPixel(image, x, y, fPixel[nc]);
738 
739 #define FILTER(v) \
740  e[0] = (7 * v) >> 4; \
741  e[1] = v >> 4; \
742  e[2] = (5 * v) >> 4; \
743  e[3] = (3 * v) >> 4;
744 
745  v = line[x].fRed - fColormap[nc][0];
746  FILTER(v)
747 
748  ef.r = e[0];
749  if (x < iw-1) ed[x+1].r = e[1];
750  if (x == 0) ed[x].r = e[2]; else ed[x].r += e[2];
751  if (x > 0) ed[x-1].r += e[3];
752 
753  v = line[x].fGreen - fColormap[nc][1];
754  FILTER(v)
755 
756  ef.g = e[0];
757  if (x < iw-1) ed[x+1].g = e[1];
758  if (x == 0) ed[x].g = e[2]; else ed[x].g += e[2];
759  if (x > 0) ed[x-1].g += e[3];
760 
761  v = line[x].fBlue - fColormap[nc][2];
762  FILTER(v)
763 
764  ef.b = e[0];
765  if (x < iw-1) ed[x+1].b = e[1];
766  if (x == 0) ed[x].b = e[2]; else ed[x].b += e[2];
767  if (x > 0) ed[x-1].b += e[3];
768 
769  }
770  }
771 }
772 
773 ////////////////////////////////////////////////////////////////////////////////
774 /// Initialize color palette and slider images.
775 
776 void TGColorPick::InitImages()
777 {
778  Int_t width, height;
779  Int_t h, l, s;
780  Int_t r, g, b;
781 
782  gVirtualX->GetImageSize(fHSimage, (UInt_t&) width, (UInt_t&) height);
783 
784  // initialize fHSimage
785 
786  Int_t ncolors = gVirtualX->GetDepth();
787 
788  if (ncolors > 8) {
789  for (Int_t y = 0; y < height; ++y) {
790  for (Int_t x = 0; x < width; ++x) {
791 
792  r = g = b = 0;
793  h = x * 255 / width;
794  l = 128;
795  s = (height - y) * 255 / height;
796 
797  TColor::HLS2RGB(h, l, s, r, g, b);
798 
799  ULong_t pixel = TColor::RGB2Pixel(r, g, b);
800  gVirtualX->PutPixel(fHSimage, x, y, pixel);
801  }
802  }
803  } else {
804  CreateDitheredImage(fHSimage, kIMG_HS);
805  }
806 
807  // initialize fLimage
808 
809  SetSliderColor();
810 }
811 
812 ////////////////////////////////////////////////////////////////////////////////
813 /// Set slider colors.
814 
815 void TGColorPick::SetSliderColor()
816 {
817  Int_t width, height;
818  Int_t h, l, s;
819  Int_t r, g, b;
820 
821  gVirtualX->GetImageSize(fLimage, (UInt_t&) width, (UInt_t&) height);
822 
823  Int_t ncolors = gVirtualX->GetDepth();
824 
825  if (ncolors > 8) {
826 
827  for (Int_t y = 0; y < height; ++y) {
828 
829  TColor::Pixel2RGB(fCurrentColor, r, g, b);
830  TColor::RGB2HLS(r, g, b, h, l, s);
831 
832  l = (height - y) * 255 / height;
833 
834  TColor::HLS2RGB(h, l, s, r, g, b);
835 
836  ULong_t pixel = TColor::RGB2Pixel(r, g, b);
837 
838  for (Int_t x = 0; x < width; ++x) {
839  gVirtualX->PutPixel(fLimage, x, y, pixel);
840  }
841  }
842  } else {
843  CreateDitheredImage(fLimage, kIMG_L);
844  }
845 
846  gClient->NeedRedraw(this);
847 }
848 
849 ////////////////////////////////////////////////////////////////////////////////
850 /// Position the slider cursor on right color position.
851 
852 void TGColorPick::SetColor(ULong_t color)
853 {
854  UInt_t width, height;
855  Int_t h, l, s;
856  Int_t r, g, b;
857 
858  gVirtualX->GetImageSize(fHSimage, width, height);
859 
860  fCurrentColor = color;
861 
862  TColor::Pixel2RGB(fCurrentColor, r, g, b);
863  TColor::RGB2HLS(r, g, b, h, l, s);
864 
865  SetHScursor(h * (Int_t)width / 256, (255 - s) * (Int_t)height / 256);
866 
867  gVirtualX->GetImageSize(fLimage, width, height);
868 
869  SetLcursor((255 - l) * (Int_t)height / 256);
870 
871  SetSliderColor();
872 }
873 
874 ////////////////////////////////////////////////////////////////////////////////
875 /// Assign the current cursor position as currently selected color.
876 
877 void TGColorPick::UpdateCurrentColor()
878 {
879  UInt_t lwidth, lheight;
880  UInt_t swidth, sheight;
881  Int_t r, g, b;
882  Int_t h, l, s;
883 
884  gVirtualX->GetImageSize(fLimage, lwidth, lheight);
885  gVirtualX->GetImageSize(fHSimage, swidth, sheight);
886 
887  h = Int_t(fCx * 255 / swidth);
888  l = Int_t((lheight - fCz) * 255 / lheight);
889  s = Int_t((sheight - fCy) * 255 / sheight);
890 
891  TColor::HLS2RGB(h, l, s, r, g, b);
892  fCurrentColor = TColor::RGB2Pixel(r, g, b);
893 }
894 
895 ////////////////////////////////////////////////////////////////////////////////
896 /// Redraw the color pick widget.
897 
898 void TGColorPick::DoRedraw()
899 {
900  UInt_t lwidth, lheight;
901  UInt_t swidth, sheight;
902 
903  gVirtualX->GetImageSize(fLimage, lwidth, lheight);
904  gVirtualX->GetImageSize(fHSimage, swidth, sheight);
905 
906  DrawBorder();
907 
908  Draw3dRectangle(kSunkenFrame, fColormapRect.fX - 1, fColormapRect.fY - 1,
909  fColormapRect.fWidth + 2, fColormapRect.fHeight + 2);
910  gVirtualX->PutImage(fId, GetBckgndGC()(), fHSimage,
911  fColormapRect.fX, fColormapRect.fY, 0, 0, swidth, sheight);
912 
913  Draw3dRectangle(kSunkenFrame, fSliderRect.fX - 1, fSliderRect.fY - 1,
914  fSliderRect.fWidth + 2, fSliderRect.fHeight + 2);
915  gVirtualX->PutImage(fId, GetBckgndGC()(), fLimage,
916  fSliderRect.fX, fSliderRect.fY, 0, 0, lwidth, lheight);
917 
918  DrawHScursor(kTRUE);
919  DrawLcursor(kTRUE);
920 }
921 
922 ////////////////////////////////////////////////////////////////////////////////
923 /// Set hue / saturation cursor position.
924 
925 void TGColorPick::SetHScursor(Int_t x, Int_t y)
926 {
927  UInt_t width, height;
928 
929  gVirtualX->GetImageSize(fHSimage, width, height);
930 
931  DrawHScursor(kFALSE);
932 
933  fCx = x;
934  fCy = y;
935 
936  if (fCx < 0)
937  fCx = 0;
938  else if (fCx >= (Int_t)width)
939  fCx = (Int_t)width - 1;
940 
941  if (fCy < 0)
942  fCy = 0;
943  else if (fCy >= (Int_t)height)
944  fCy = (Int_t)height - 1;
945 
946  DrawHScursor(kTRUE);
947 }
948 
949 ////////////////////////////////////////////////////////////////////////////////
950 /// Set lightness slider cursor position.
951 
952 void TGColorPick::SetLcursor(Int_t z)
953 {
954  UInt_t width, height;
955 
956  gVirtualX->GetImageSize(fLimage, width, height);
957 
958  DrawLcursor(kFALSE);
959 
960  fCz = z - fSliderRect.fY;
961 
962  if (fCz < 0)
963  fCz = 0;
964  else if (fCz >= (Int_t)height)
965  fCz = (Int_t)height - 1;
966 
967  DrawLcursor(kTRUE);
968 }
969 
970 ////////////////////////////////////////////////////////////////////////////////
971 /// Draw hue / saturation cursor
972 
973 void TGColorPick::DrawHScursor(Int_t onoff)
974 {
975  UInt_t width, height;
976 
977  gVirtualX->GetImageSize(fHSimage, width, height);
978 
979  if (onoff) {
980  Int_t x, y;
981  Rectangle_t rect;
982 
983  x = fCx + fColormapRect.fX;
984  y = fCy + fColormapRect.fY;
985 
986  rect.fX = fColormapRect.fX;
987  rect.fY = fColormapRect.fX;
988  rect.fWidth = fColormapRect.fWidth;
989  rect.fHeight = fColormapRect.fHeight;
990  gVirtualX->SetClipRectangles(fCursorGC(), 0, 0, &rect, 1);
991 
992  gVirtualX->FillRectangle(fId, fCursorGC(), x - 9, y - 1, 5, 3);
993  gVirtualX->FillRectangle(fId, fCursorGC(), x - 1, y - 9, 3, 5);
994  gVirtualX->FillRectangle(fId, fCursorGC(), x + 5, y - 1, 5, 3);
995  gVirtualX->FillRectangle(fId, fCursorGC(), x - 1, y + 5, 3, 5);
996 
997  } else {
998  Int_t x, y;
999  UInt_t w, h;
1000 
1001  x = fCx - 9; w = 19;
1002  y = fCy - 9; h = 19;
1003 
1004  if (x < 0) { w += x; x = 0; }
1005  if (y < 0) { h += y; y = 0; }
1006 
1007  if (x + w > width) w = width - x;
1008  if (y + h > height) h = height - y;
1009 
1010  gVirtualX->PutImage(fId, GetBckgndGC()(), fHSimage, x, y,
1011  fColormapRect.fX + x, fColormapRect.fY + y, w, h);
1012  }
1013 }
1014 
1015 ////////////////////////////////////////////////////////////////////////////////
1016 /// Draw lightness slider cursor
1017 
1018 void TGColorPick::DrawLcursor(Int_t onoff)
1019 {
1020  Int_t l = fSliderRect.fX + fSliderRect.fWidth + 3;
1021  Int_t r = l + 5;
1022  Int_t t = fCz - 5 + fSliderRect.fY;
1023  Int_t b = t + 10;
1024 
1025  Point_t points[3];
1026 
1027  Int_t m = (t + b) >> 1;
1028 
1029  points[0].fX = r;
1030  points[0].fY = t;
1031  points[1].fX = r;
1032  points[1].fY = b;
1033  points[2].fX = l;
1034  points[2].fY = m;
1035 
1036  GContext_t gc = onoff ? GetShadowGC()() : GetBckgndGC()();
1037 
1038  gVirtualX->FillPolygon(fId, gc, points, 3);
1039 }
1040 
1041 
1042 ////////////////////////////////////////////////////////////////////////////////
1043 /// Color selection dialog constructor.
1044 /// The TGColorDialog presents a full featured color selection dialog.
1045 /// It uses 2 TGColorPalette's and the TGColorPick widgets.
1046 
1047 TGColorDialog::TGColorDialog(const TGWindow *p, const TGWindow *m,
1048  Int_t *retc, ULong_t *color, Bool_t wait) :
1049  TGTransientFrame(p, m, 200, 150)
1050 {
1051  const Int_t kC_X = 175; // Win95: 177
1052  const Int_t kC_Y = 180; // Win95: 189
1053 
1054  Int_t i;
1055 
1056  fRetc = retc;
1057  fRetColor = 0;
1058  fRetTColor = 0;
1059  fInitColor = 0;
1060  if (color) {
1061  fRetColor = color;
1062  fRetTColor = gROOT->GetColor(TColor::GetColor(*color));
1063  fInitColor = *fRetColor;
1064  }
1065  fWaitFor = wait;
1066 
1067  if (fRetc) *fRetc = kMBCancel;
1068 
1069  TGHorizontalFrame *hftop = new TGHorizontalFrame(this, 10, 10);
1070  hftop->SetCleanup();
1071  AddFrame(hftop, new TGLayoutHints(kLHintsTop | kLHintsLeft, 5, 5, 10, 5));
1072 
1073  fTab = new TGTab(hftop, 300, 300);
1074  hftop->AddFrame(fTab);
1075 
1076  TGCompositeFrame *cf = new TGCompositeFrame(hftop, 10, 10);
1077  cf->SetCleanup();
1078  hftop->AddFrame(cf, new TGLayoutHints(kLHintsLeft | kLHintsTop, 5, 0, 30, 0));
1079 
1080  TGCompositeFrame *cf1 = new TGCompositeFrame(cf, 10, 10);
1081  cf1->SetCleanup();
1082  cf->AddFrame(cf1, new TGLayoutHints(kLHintsLeft | kLHintsTop, 5, 0, 30, 0));
1083  cf1->SetLayoutManager(new TGMatrixLayout(cf1, 0, 2, 4));
1084 
1085  cf1->AddFrame(new TGLabel(cf1, new TGHotString("Red:")));
1086  cf1->AddFrame(fRte = new TGTextEntry(cf1, fRtb = new TGTextBuffer(5), kCDLG_RTE),0);
1087  fRte->Resize(50, fRte->GetDefaultHeight());
1088  cf1->AddFrame(new TGLabel(cf1, new TGHotString("Green:")),0);
1089  cf1->AddFrame(fGte = new TGTextEntry(cf1, fGtb = new TGTextBuffer(5), kCDLG_GTE),0);
1090  fGte->Resize(50, fGte->GetDefaultHeight());
1091  cf1->AddFrame(new TGLabel(cf1, new TGHotString("Blue:")));
1092  cf1->AddFrame(fBte = new TGTextEntry(cf1, fBtb = new TGTextBuffer(5), kCDLG_BTE),0);
1093  fBte->Resize(50, fBte->GetDefaultHeight());
1094  cf1->AddFrame(new TGLabel(cf1, new TGHotString("Opacity:")),0);
1095  cf1->AddFrame(fAle = new TGTextEntry(cf1, fAlb = new TGTextBuffer(5), kCDLG_ALE),0);
1096  fAle->Resize(50, fAle->GetDefaultHeight());
1097 
1098  if (!TCanvas::SupportAlpha()) {
1099  fAle->SetEnabled(kFALSE);
1100  }
1101 
1102  TGCompositeFrame *cf2 = new TGCompositeFrame(cf, 10, 10);
1103  cf2->SetCleanup();
1104  cf->AddFrame(cf2, new TGLayoutHints(kLHintsLeft | kLHintsTop, 5, 0, 30, 0));
1105  cf2->SetLayoutManager(new TGMatrixLayout(cf2, 0, 2, 4));
1106  cf2->AddFrame(new TGLabel(cf2, new TGHotString("Hue:")),0);
1107  cf2->AddFrame(fHte = new TGTextEntry(cf2, fHtb = new TGTextBuffer(5), kCDLG_HTE),0);
1108  fHte->Resize(50, fHte->GetDefaultHeight());
1109  cf2->AddFrame(new TGLabel(cf2, new TGHotString("Sat:")),0);
1110  cf2->AddFrame(fSte = new TGTextEntry(cf2, fStb = new TGTextBuffer(5), kCDLG_STE),0);
1111  fSte->Resize(50, fSte->GetDefaultHeight());
1112  cf2->AddFrame(new TGLabel(cf2, new TGHotString("Lum:")),0);
1113  cf2->AddFrame(fLte = new TGTextEntry(cf2, fLtb = new TGTextBuffer(5), kCDLG_LTE),0);
1114  fLte->Resize(50, fLte->GetDefaultHeight());
1115 
1116  fHte->Associate(this);
1117  fLte->Associate(this);
1118  fSte->Associate(this);
1119  fRte->Associate(this);
1120  fGte->Associate(this);
1121  fBte->Associate(this);
1122  fAle->Associate(this);
1123 
1124  if (color) {
1125  UpdateRGBentries(color);
1126  UpdateHLSentries(color);
1127  UpdateAlpha(color);
1128  fCurrentColor = *color;
1129  } else {
1130  gClient->GetColorByName("red", fCurrentColor);
1131  }
1132 
1133  // color sample
1134  TGCompositeFrame *cf3 = new TGCompositeFrame(cf, 10, 10);
1135  cf3->SetCleanup();
1136  cf3->SetLayoutManager(new TGMatrixLayout(cf3, 0, 1, 0));
1137  cf3->AddFrame(fColorInfo = new TGLabel(cf3, new TGString("New: not set ")),0);
1138  fColorInfo->SetTextJustify(kTextLeft);
1139  cf3->AddFrame(fSample = new TGFrame(cf3, 50, 25, kOwnBackground),0);
1140  cf3->AddFrame(fSampleOld = new TGFrame(cf3, 50, 25, kOwnBackground),0);
1141  cf3->AddFrame(new TGLabel(cf3, new TGString("Current")),0);
1142  cf->AddFrame(cf3, new TGLayoutHints(kLHintsLeft | kLHintsTop, 5, 5, 20, 0));
1143  fSample->SetBackgroundColor(fCurrentColor);
1144  fSampleOld->SetBackgroundColor(fCurrentColor);
1145 
1146  TGCompositeFrame *tf = fTab->AddTab("Color Wheel");
1147  TGCompositeFrame *tf1 = new TGCompositeFrame(tf, 60, 20, kHorizontalFrame);
1148  tf->AddFrame(tf1);
1149  fEcanvas = new TRootEmbeddedCanvas("wheel", tf1, 360, 360);
1150  tf1->AddFrame(fEcanvas);
1151  TCanvas *wcan = fEcanvas->GetCanvas();
1152  wcan->SetBit(kNoContextMenu);
1153  fColorWheel = new TColorWheel();
1154  fColorWheel->SetCanvas(wcan);
1155  fColorWheel->Draw();
1156  wcan->Update();
1157  wcan->Connect("ProcessedEvent(Int_t,Int_t,Int_t,TObject*)","TGColorDialog",this,
1158  "SetColorInfo(Int_t,Int_t,Int_t,TObject*)");
1159 
1160  tf = fTab->AddTab("Basic Colors");
1161  TGCompositeFrame *tf2 = new TGCompositeFrame(tf, 60, 20, kHorizontalFrame);
1162  tf->AddFrame(tf2);
1163 
1164  TGVerticalFrame *vf1 = new TGVerticalFrame(tf2, 20, 20);
1165  vf1->SetCleanup();
1166  TGVerticalFrame *vf2 = new TGVerticalFrame(tf2, 20, 20);
1167  vf2->SetCleanup();
1168 
1169  tf2->AddFrame(vf1, new TGLayoutHints(kLHintsLeft | kLHintsExpandY));
1170  tf2->AddFrame(vf2, new TGLayoutHints(kLHintsLeft | kLHintsExpandY));
1171 
1172  //----------------------------------------- Left panel
1173 
1174  // basic colors
1175 
1176  fPalette = new TGColorPalette(vf1, 6, 8, kCDLG_SPALETTE);
1177  vf1->AddFrame(fPalette, new TGLayoutHints(kLHintsNormal, 5, 5, 15, 0));
1178  fPalette->Associate(this);
1179 
1180  for (i = 0; i < 48; ++i)
1181  fPalette->SetColor(i, TColor::Number2Pixel(i+10)); // root colors
1182  // the basic colors were set via bcolor
1183  //fPalette->SetColor(i, TColor::GetPixel(bcolor[i][0], bcolor[i][1], bcolor[i][2]));
1184 
1185  // add some default colors
1186  fPalette->SetColor(47, TGFrame::GetDefaultFrameBackground());
1187 
1188  Float_t r, g, b;
1189 
1190  r = 232./255;
1191  g = 232./255;
1192  b = 222./255;
1193 
1194  // Gui Builder background
1195  Pixel_t pixel = TColor::RGB2Pixel(r, g, b);
1196  fPalette->SetColor(46, pixel);
1197 
1198  r = 230./255;
1199  g = 230./255;
1200  b = 230./255;
1201 
1202  // a la MAC background
1203  pixel = TColor::RGB2Pixel(r, g, b);
1204  fPalette->SetColor(45, pixel);
1205 
1206  r = 172./255;
1207  g = 174./255;
1208  b = 205./255;
1209 
1210  // a la CDE background
1211  pixel = TColor::RGB2Pixel(r, g, b);
1212  fPalette->SetColor(44, pixel);
1213 
1214  r = 205./255;
1215  g = 195./255;
1216  b = 175./255;
1217 
1218  // a la FOX background
1219  pixel = TColor::RGB2Pixel(r, g, b);
1220  fPalette->SetColor(43, pixel);
1221 
1222  // custom colors
1223 
1224  vf1->AddFrame(new TGLabel(vf1, new TGHotString("&Custom Colors:")),
1225  new TGLayoutHints(kLHintsNormal, 5, 0, 15, 2));
1226 
1227  fCpalette = new TGColorPalette(vf1, 6, 4, kCDLG_CPALETTE);
1228  vf1->AddFrame(fCpalette, new TGLayoutHints(kLHintsNormal, 5, 5, 5, 0));
1229  fCpalette->Associate(this);
1230 
1231  if (gUcolor[0] == 0xff000000) {
1232  for (i = 0; i < 24; i++)
1233  gUcolor[i] = TColor::RGB2Pixel(255, 255, 255);
1234  }
1235  fCpalette->SetColors(gUcolor);
1236 
1237  // button frame - OK, Cancel
1238  TGHorizontalFrame *hf = new TGHorizontalFrame(this, 10, 10, kFixedWidth);
1239  hf->SetCleanup();
1240  AddFrame(hf, new TGLayoutHints(kLHintsBottom | kLHintsRight, 5, 5, 10, 5));
1241 
1242  TGTextButton *ok = new TGTextButton(hf, new TGHotString("OK"), kCDLG_OK);
1243  TGTextButton *cancel = new TGTextButton(hf, new TGHotString("Cancel"), kCDLG_CANCEL);
1244  fPreview = new TGTextButton(hf, new TGHotString("&Preview"), kCDLG_PREVIEW);
1245  fPreview->Connect("Clicked()", "TGColorDialog", this, "DoPreview()");
1246 
1247  hf->AddFrame(ok, new TGLayoutHints(kLHintsBottom | kLHintsExpandX, 0, 3, 0, 0));
1248  hf->AddFrame(cancel, new TGLayoutHints(kLHintsBottom | kLHintsExpandX,3, 0, 0, 0));
1249  hf->AddFrame(fPreview, new TGLayoutHints(kLHintsBottom | kLHintsExpandX,3, 0, 0, 0));
1250 
1251  UInt_t w = ok->GetDefaultWidth();
1252  w = TMath::Max(w, cancel->GetDefaultWidth());
1253  hf->Resize(3 * (w + 30), hf->GetDefaultHeight());
1254 
1255  ok->Associate(this);
1256  cancel->Associate(this);
1257 
1258  //----------------------------------------- Right panel
1259 
1260  // fColormap frame
1261 
1262  fColors = new TGColorPick(vf2, kC_X + 23, kC_Y, kCDLG_COLORPICK);
1263  vf2->AddFrame(fColors, new TGLayoutHints(kLHintsLeft | kLHintsTop, 5, 0, 15, 5));
1264  fColors->Associate(this);
1265 
1266  if (color)
1267  fColors->SetColor(*color);
1268 
1269  TGTextButton *add = new TGTextButton(vf2, new TGHotString("&Add to Custom Colors"),
1270  kCDLG_ADD);
1271  vf2->AddFrame(add, new TGLayoutHints(kLHintsBottom | kLHintsExpandX,
1272  5, 10, 0, 5));
1273  add->Associate(this);
1274 
1275  MapSubwindows();
1276  Resize(GetDefaultSize());
1277  SetEditDisabled(kEditDisable);
1278 
1279  //---- make the message box non-resizable
1280 
1281  SetWMSize(fWidth, fHeight);
1282  SetWMSizeHints(fWidth, fHeight, fWidth, fHeight, 0, 0);
1283 
1284  SetWindowName("Color Selector");
1285  SetIconName("Color Selector");
1286  SetClassHints("ROOT", "ColorSelector");
1287 
1288  SetMWMHints(kMWMDecorAll | kMWMDecorResizeH | kMWMDecorMaximize |
1289  kMWMDecorMinimize | kMWMDecorMenu,
1290  kMWMFuncAll | kMWMFuncResize | kMWMFuncMaximize |
1291  kMWMFuncMinimize,
1292  kMWMInputModeless);
1293 
1294 
1295  //---- position relative to the parent's window
1296 
1297  if (fClient->IsEditable()) {
1298  const TGWindow *main = fMain;
1299  fMain = fClient->GetRoot();
1300  CenterOnParent(kTRUE, TGTransientFrame::kRight);
1301  fMain = main;
1302  } else {
1303  CenterOnParent();
1304  }
1305 
1306  if (fWaitFor) {
1307  MapWindow();
1308  fClient->WaitForUnmap(this);
1309  DeleteWindow();
1310  }
1311 }
1312 
1313 ////////////////////////////////////////////////////////////////////////////////
1314 /// TGColorDialog destructor.
1315 
1316 TGColorDialog::~TGColorDialog()
1317 {
1318  fEcanvas->GetCanvas()->Disconnect("ProcessedEvent(Int_t,Int_t,Int_t,TObject*)");
1319  delete fEcanvas;
1320  Cleanup();
1321 }
1322 
1323 ////////////////////////////////////////////////////////////////////////////////
1324 /// Change current color.
1325 
1326 void TGColorDialog::SetCurrentColor(Pixel_t col)
1327 {
1328  if (fCurrentColor == col) {
1329  return;
1330  }
1331  fInitColor = *fRetColor = col;
1332  if((fRetTColor = gROOT->GetColor(TColor::GetColor(col)))) {};
1333  fCurrentColor = col;
1334  fColors->SetColor(col);
1335  fSample->SetBackgroundColor(col);
1336  ColorSelected(col);
1337 }
1338 
1339 ////////////////////////////////////////////////////////////////////////////////
1340 /// Emit signal about selected color.
1341 
1342 void TGColorDialog::ColorSelected(Pixel_t color)
1343 {
1344  Emit("ColorSelected(Pixel_t)", color);
1345 }
1346 
1347 ////////////////////////////////////////////////////////////////////////////////
1348 /// Emit signal about selected alpha and color.
1349 
1350 void TGColorDialog::AlphaColorSelected(ULong_t color)
1351 {
1352  Emit("AlphaColorSelected(ULong_t)", color);
1353 }
1354 
1355 ////////////////////////////////////////////////////////////////////////////////
1356 /// Called when window is closed via window manager.
1357 
1358 void TGColorDialog::CloseWindow()
1359 {
1360  // save user set colors
1361  for (Int_t i = 0; i < 24; ++i)
1362  gUcolor[i] = fCpalette->GetColorByIndex(i);
1363 
1364  if (*fRetc != kMBOk) {
1365  ColorSelected(fInitColor);
1366  ULong_t ptr;
1367  if((ptr = (ULong_t)gROOT->GetColor(TColor::GetColor(fInitColor)))) AlphaColorSelected(ptr);
1368  } else {
1369  ColorSelected(*fRetColor);
1370  AlphaColorSelected((ULong_t)fRetTColor);
1371  }
1372  // don't call DeleteWindow() here since that will cause access
1373  // to the deleted dialog in the WaitFor() method (see ctor)
1374 
1375  //OpenGL + XQuartz on Mac: gl context and related resources
1376  //must be deleted _before_ UnmapWindow.
1377  if (gVirtualX->InheritsFrom("TGX11") && fEcanvas->GetCanvas()->UseGL())
1378  fEcanvas->GetCanvas()->DeleteCanvasPainter();
1379 
1380  UnmapWindow();
1381 }
1382 
1383 ////////////////////////////////////////////////////////////////////////////////
1384 /// Upadate Opacity text entry with alpha value of color c.
1385 
1386 void TGColorDialog::UpdateAlpha(ULong_t *c)
1387 {
1388  Char_t tmp[20];
1389  Double_t alpha;
1390 
1391  if (TColor *color = gROOT->GetColor(TColor::GetColor(*c))) {
1392  alpha = color->GetAlpha();
1393  snprintf(tmp, 20, "%.1f", alpha);
1394  fAlb->Clear();
1395  fAlb->AddText(0,tmp);
1396  gClient->NeedRedraw(fAle);
1397  }
1398 }
1399 
1400 
1401 ////////////////////////////////////////////////////////////////////////////////
1402 /// Update RGB text entries with RGB values of color c.
1403 
1404 void TGColorDialog::UpdateRGBentries(ULong_t *c)
1405 {
1406  Char_t tmp[20];
1407 
1408  Int_t r, g, b;
1409  TColor::Pixel2RGB(*c, r, g, b);
1410 
1411  snprintf(tmp, 20, "%d", r);
1412  fRtb->Clear();
1413  fRtb->AddText(0, tmp);
1414  gClient->NeedRedraw(fRte);
1415 
1416  snprintf(tmp, 20, "%d", g);
1417  fGtb->Clear();
1418  fGtb->AddText(0, tmp);
1419  gClient->NeedRedraw(fGte);
1420 
1421  snprintf(tmp, 20, "%d", b);
1422  fBtb->Clear();
1423  fBtb->AddText(0, tmp);
1424  gClient->NeedRedraw(fBte);
1425 }
1426 
1427 ////////////////////////////////////////////////////////////////////////////////
1428 /// Update HLS text entries with HLS values of color c.
1429 
1430 void TGColorDialog::UpdateHLSentries(ULong_t *c)
1431 {
1432  Char_t tmp[20];
1433 
1434  Int_t h, l, s;
1435  Int_t r, g, b;
1436 
1437  TColor::Pixel2RGB(*c, r, g, b);
1438  TColor::RGB2HLS(r, g, b, h, l, s);
1439 
1440  snprintf(tmp, 20, "%d", h);
1441  fHtb->Clear();
1442  fHtb->AddText(0, tmp);
1443  gClient->NeedRedraw(fHte);
1444 
1445  snprintf(tmp, 20, "%d", l);
1446  fLtb->Clear();
1447  fLtb->AddText(0, tmp);
1448  gClient->NeedRedraw(fLte);
1449 
1450  snprintf(tmp, 20, "%d", s);
1451  fStb->Clear();
1452  fStb->AddText(0, tmp);
1453  gClient->NeedRedraw(fSte);
1454 }
1455 
1456 ////////////////////////////////////////////////////////////////////////////////
1457 /// Process messages for the color selection dialog.
1458 
1459 Bool_t TGColorDialog::ProcessMessage(Long_t msg, Long_t parm1, Long_t /*parm2*/)
1460 {
1461  ULong_t color;
1462  Int_t h, l, s;
1463  Int_t r, g, b;
1464 
1465  switch (GET_MSG(msg)) {
1466  case kC_COMMAND:
1467  switch (GET_SUBMSG(msg)) {
1468  case kCM_BUTTON:
1469  switch(parm1) {
1470  case kCDLG_ADD:
1471  fCpalette->SetCurrentCellColor(fCurrentColor);
1472  break;
1473 
1474  case kCDLG_OK:
1475  *fRetc = kMBOk;
1476  *fRetColor = TColor::RGB2Pixel(atoi(fRtb->GetString()),
1477  atoi(fGtb->GetString()),
1478  atoi(fBtb->GetString()));
1479  if ((fRetTColor = gROOT->GetColor(TColor::GetColor(*fRetColor)))) {
1480  fRetTColor->SetAlpha(TMath::Max((Double_t)0, TMath::Min((Double_t)1,
1481  atof(fAlb->GetString()))));
1482  }
1483  CloseWindow();
1484  break;
1485  case kCDLG_CANCEL:
1486  if (!fClient->IsEditable()) {
1487  TGColorPopup *p = (TGColorPopup *)GetMain();
1488  if (p && p->InheritsFrom("TGColorPopup"))
1489  p->PreviewColor(fSampleOld->GetBackground());
1490  }
1491  CloseWindow();
1492  break;
1493  }
1494  break;
1495  }
1496  break;
1497  case kC_COLORSEL:
1498  switch (GET_SUBMSG(msg)) {
1499  case kCOL_CLICK:
1500  switch (parm1) {
1501  case kCDLG_SPALETTE:
1502  color = fPalette->GetCurrentColor();
1503  fSample->SetBackgroundColor(color);
1504  ColorSelected(color);
1505  gClient->NeedRedraw(fSample);
1506  fCurrentColor = color;
1507  fColors->SetColor(color);
1508  UpdateRGBentries(&color);
1509  UpdateHLSentries(&color);
1510  UpdateAlpha(&color);
1511  break;
1512 
1513  case kCDLG_CPALETTE:
1514  color = fCpalette->GetCurrentColor();
1515  fSample->SetBackgroundColor(color);
1516  ColorSelected(color);
1517  gClient->NeedRedraw(fSample);
1518  fCurrentColor = color;
1519  fColors->SetColor(color);
1520  UpdateRGBentries(&color);
1521  UpdateHLSentries(&color);
1522  UpdateAlpha(&color);
1523  break;
1524 
1525  case kCDLG_COLORPICK:
1526  color = fColors->GetCurrentColor();
1527  fSample->SetBackgroundColor(color);
1528  ColorSelected(color);
1529  gClient->NeedRedraw(fSample);
1530  fCurrentColor = color;
1531  UpdateRGBentries(&color);
1532  UpdateHLSentries(&color);
1533  UpdateAlpha(&color);
1534  break;
1535 
1536  }
1537  break;
1538  }
1539  break;
1540 
1541  case kC_TEXTENTRY:
1542  switch (GET_SUBMSG(msg)) {
1543  case kTE_TEXTCHANGED:
1544  switch (parm1) {
1545  case kCDLG_HTE:
1546  case kCDLG_LTE:
1547  case kCDLG_STE:
1548 
1549  h = atoi(fHtb->GetString());
1550  l = atoi(fLtb->GetString());
1551  s = atoi(fStb->GetString());
1552  TColor::HLS2RGB(h, l, s, r, g, b);
1553 
1554  color = TColor::RGB2Pixel(r, g, b);
1555  fSample->SetBackgroundColor(color);
1556  ColorSelected(color);
1557  gClient->NeedRedraw(fSample);
1558  fCurrentColor = color;
1559  fColors->SetColor(color);
1560  UpdateRGBentries(&color);
1561  break;
1562 
1563  case kCDLG_RTE:
1564  case kCDLG_GTE:
1565  case kCDLG_BTE:
1566  color = TColor::RGB2Pixel(atoi(fRtb->GetString()),
1567  atoi(fGtb->GetString()),
1568  atoi(fBtb->GetString()));
1569  fSample->SetBackgroundColor(color);
1570  ColorSelected(color);
1571  gClient->NeedRedraw(fSample);
1572  fCurrentColor = color;
1573  fColors->SetColor(color);
1574  UpdateHLSentries(&color);
1575  break;
1576 
1577  }
1578  break;
1579  }
1580  break;
1581  }
1582 
1583  return kTRUE;
1584 }
1585 
1586 ////////////////////////////////////////////////////////////////////////////////
1587 /// Set the color info in RGB and HLS parts
1588 
1589 void TGColorDialog::SetColorInfo(Int_t event, Int_t px, Int_t py, TObject *object)
1590 {
1591  if (object == fColorWheel) {
1592  Int_t n = fColorWheel->GetColor(px,py);
1593  if (n < 0) return;
1594  TColor *color = gROOT->GetColor(n);
1595  if (!color) return;
1596  ULong_t pcolor = color->GetPixel();
1597  if (event == kButton1Down) {
1598  UpdateRGBentries(&pcolor);
1599  UpdateHLSentries(&pcolor);
1600  UpdateAlpha(&pcolor);
1601  fSample->SetBackgroundColor(pcolor);
1602  fColorInfo->SetText(Form("New: %s",color->GetName()));
1603  gClient->NeedRedraw(fSample);
1604  gClient->NeedRedraw(fColorInfo);
1605  fCurrentColor = pcolor;
1606  fColors->SetColor(pcolor);
1607  ColorSelected(pcolor);
1608  }
1609  }
1610 }
1611 
1612 ////////////////////////////////////////////////////////////////////////////////
1613 /// Slot method called when Preview button is clicked.
1614 
1615 void TGColorDialog::DoPreview()
1616 {
1617  TColor *tcolor;
1618  if ((tcolor = gROOT->GetColor(TColor::GetColor(fSample->GetBackground())))) {
1619  tcolor->SetAlpha(TMath::Max((Double_t)0, TMath::Min((Double_t)1, atof(fAlb->GetString()))));
1620  }
1621 
1622  if (fClient->IsEditable()) {
1623  ColorSelected(fSample->GetBackground());
1624  AlphaColorSelected((ULong_t)tcolor);
1625  return;
1626  }
1627  TGColorPopup *p = (TGColorPopup *)GetMain();
1628  if (p && p->InheritsFrom("TGColorPopup")) {
1629  if (tcolor) p->PreviewAlphaColor((ULong_t)tcolor);
1630  else p->PreviewColor(fSample->GetBackground());
1631  }
1632 }