// @(#)root/gui:$Name: $:$Id: TGColorDialog.cxx,v 1.8 2003/03/17 16:38:03 rdm Exp $
// Author: Bertrand Bellenot + Fons Rademakers 22/08/02
/*************************************************************************
* Copyright (C) 1995-2002, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
/**************************************************************************
This file is part of xclass.
Copyright (C) 2000, 2001, Hector Peraza.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**************************************************************************/
//////////////////////////////////////////////////////////////////////////
// //
// TGColorPalette, TGColorPick and TGColorDialog. //
// //
// The TGColorPalette is a widget showing an matrix of color cells. The //
// colors can be set and selected. //
// //
// The TGColorPick is a widget which allows a color to be picked from //
// HLS space. It consists of two elements: a color map window from //
// where the user can select the hue and saturation level of a color, //
// and a slider to select color's lightness. //
// //
// Selecting a color in these two widgets will generate the event: //
// kC_COLORSEL, kCOL_CLICK, widget id, 0. //
// and the signal: //
// ColorSelected(ULong_t pixel) //
// //
// The TGColorDialog presents a full featured color selection dialog. //
// It uses 2 TGColorPalette's and the TGColorPick widgets. //
// //
//////////////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include "TGLabel.h"
#include "TGMsgBox.h" // for ID_OK, ID_CANCEL
#include "TGLayout.h"
#include "TGGC.h"
#include "KeySymbols.h"
#include "TGColorDialog.h"
#include "TGTextEntry.h"
#include "TGButton.h"
#include "TColor.h"
ClassImp(TGColorPalette)
ClassImp(TGColorPick)
ClassImp(TGColorDialog)
// TODO:
// - implement "custom" colors.
// - optimize the code, specially the one handling the fColormap image
// and dithering in pseudo-color modes; remove duplicated code.
// - improve the color allocation routine.
// - use a buffering pixmap for the fColormap image.
enum {
kCDLG_OK = 100,
kCDLG_CANCEL,
kCDLG_ADD,
kCDLG_SPALETTE = 200,
kCDLG_CPALETTE,
kCDLG_COLORPICK,
kCDLG_HTE = 300,
kCDLG_LTE,
kCDLG_STE,
kCDLG_RTE,
kCDLG_GTE,
kCDLG_BTE
};
enum {
kCLICK_NONE,
kCLICK_HS,
kCLICK_L
};
enum {
kIMG_HS,
kIMG_L
};
// "Basic" colors:
static UChar_t bcolor[48][3] = {
{ 0xff, 0x80, 0x80 }, { 0xff, 0xff, 0x80 },
{ 0x80, 0xff, 0x80 }, { 0x00, 0xff, 0x80 },
{ 0x80, 0xff, 0xff }, { 0x00, 0x80, 0xff },
{ 0xff, 0x80, 0xc0 }, { 0xff, 0x80, 0xff },
{ 0xff, 0x00, 0x00 }, { 0xff, 0xff, 0x00 },
{ 0x80, 0xff, 0x00 }, { 0x00, 0xff, 0x40 },
{ 0x00, 0xff, 0xff }, { 0x00, 0x80, 0xc0 },
{ 0x80, 0x80, 0xc0 }, { 0xff, 0x00, 0xff },
{ 0x80, 0x40, 0x40 }, { 0xff, 0x80, 0x40 },
{ 0x00, 0xff, 0x00 }, { 0x00, 0x80, 0x80 },
{ 0x00, 0x40, 0x80 }, { 0x80, 0x80, 0xff },
{ 0x80, 0x00, 0x40 }, { 0xff, 0x00, 0x80 },
{ 0x80, 0x00, 0x00 }, { 0xff, 0x80, 0x00 },
{ 0x00, 0x80, 0x00 }, { 0x00, 0x80, 0x40 },
{ 0x00, 0x00, 0xff }, { 0x00, 0x00, 0xa0 },
{ 0x80, 0x00, 0x80 }, { 0x80, 0x00, 0xff },
{ 0x40, 0x00, 0x00 }, { 0x80, 0x40, 0x00 },
{ 0x00, 0x40, 0x00 }, { 0x00, 0x40, 0x40 },
{ 0x00, 0x00, 0x80 }, { 0x00, 0x00, 0x40 },
{ 0x40, 0x00, 0x40 }, { 0x40, 0x00, 0x80 },
{ 0x00, 0x00, 0x00 }, { 0x80, 0x80, 0x00 },
{ 0x80, 0x80, 0x40 }, { 0x80, 0x80, 0x80 },
{ 0x40, 0x80, 0x80 }, { 0xc0, 0xc0, 0xc0 },
{ 0x40, 0x00, 0x40 }, { 0xff, 0xff, 0xff }
};
// "User" defined colors
static ULong_t ucolor[24] = { 0xff000000 };
//________________________________________________________________________________
TGColorPalette::TGColorPalette(const TGWindow *p, Int_t cols, Int_t rows, Int_t id) :
TGFrame(p, 10, 10, kChildFrame), fDrawGC(TGButton::GetDefaultGC())
{
// TGColorPalette widget: this is just a grid of color cells of the
// specified size. Colors can be selected by clicking on them or by
// using the arrow keys.
fWidgetId = id;
fWidgetFlags = kWidgetIsEnabled;
fMsgWindow = p;
fCw = 20;
fCh = 17;
fRows = rows;
fCols = cols;
fCx = fCy = 0;
fPixels = new ULong_t[fRows * fCols];
for (Int_t i = 0; i < fRows * fCols; ++i) {
fPixels[i] = TColor::RGB2Pixel(255, 255, 255);
}
gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
kButtonPressMask | kButtonReleaseMask |
#ifndef GDK_WIN32
kPointerMotionMask, kNone, kNone);
#else
kButtonMotionMask, kNone, kNone);
#endif
AddInput(kKeyPressMask | kEnterWindowMask | kLeaveWindowMask |
kFocusChangeMask | kStructureNotifyMask);
}
//________________________________________________________________________________
TGColorPalette::~TGColorPalette()
{
delete [] fPixels;
}
//________________________________________________________________________________
Bool_t TGColorPalette::HandleButton(Event_t *event)
{
if (event->fCode != kButton1)
return kFALSE;
if ((event->fType == kButtonPress) && HasFocus())
WantFocus();
Int_t cx = event->fX / (fCw + 5);
Int_t cy = event->fY / (fCh + 5);
if (cx >= 0 && cx < fCols && cy >= 0 && cy < fRows) {
DrawFocusHilite(kFALSE);
fCx = cx;
fCy = cy;
DrawFocusHilite(kTRUE);
SendMessage(fMsgWindow, MK_MSG(kC_COLORSEL, kCOL_CLICK), fWidgetId, 0);
ColorSelected();
}
return kTRUE;
}
//________________________________________________________________________________
Bool_t TGColorPalette::HandleMotion(Event_t *event)
{
if (!IsEnabled())
return kTRUE;
Int_t cx = event->fX / (fCw + 5);
Int_t cy = event->fY / (fCh + 5);
if (cx >= 0 && cx < fCols && cy >= 0 && cy < fRows) {
DrawFocusHilite(kFALSE);
fCx = cx;
fCy = cy;
DrawFocusHilite(kTRUE);
SendMessage(fMsgWindow, MK_MSG(kC_COLORSEL, kCOL_CLICK), fWidgetId, 0);
ColorSelected();
}
return kTRUE;
}
//________________________________________________________________________________
Bool_t TGColorPalette::HandleKey(Event_t *event)
{
Char_t input[10];
UInt_t keysym;
if (event->fType == kGKeyPress) {
gVirtualX->LookupString(event, input, sizeof(input), keysym);
Int_t cx = fCx;
Int_t cy = fCy;
switch ((EKeySym)keysym) {
case kKey_Left:
if (cx > 0) --cx;
break;
case kKey_Right:
if (cx < fCols - 1) ++cx;
break;
case kKey_Up:
if (cy > 0) --cy;
break;
case kKey_Down:
if (cy < fRows - 1) ++cy;
break;
case kKey_Home:
cx = cy = 0;
break;
case kKey_End:
cx = fCols - 1;
cy = fRows - 1;
break;
default:
break;
}
if (cx != fCx || cy != fCy) {
DrawFocusHilite(kFALSE);
fCx = cx;
fCy = cy;
DrawFocusHilite(kTRUE);
SendMessage(fMsgWindow, MK_MSG(kC_COLORSEL, kCOL_CLICK), fWidgetId, 0);
ColorSelected();
}
}
return kTRUE;
}
//________________________________________________________________________________
void TGColorPalette::SetColors(ULong_t colors[])
{
for (Int_t i = 0; i < fRows * fCols; ++i)
SetColor(i, colors[i]);
gClient->NeedRedraw(this);
}
//________________________________________________________________________________
void TGColorPalette::SetColor(Int_t ix, ULong_t color)
{
fPixels[ix] = color;
gClient->NeedRedraw(this);
}
//________________________________________________________________________________
void TGColorPalette::SetCurrentCellColor(ULong_t color)
{
SetColor(fCy * fCols + fCx, color);
}
//________________________________________________________________________________
void TGColorPalette::SetCellSize(Int_t w, Int_t h)
{
fCw = w;
fCh = h;
gClient->NeedRedraw(this);
}
//________________________________________________________________________________
ULong_t TGColorPalette::GetCurrentColor() const
{
if (fCx >= 0 && fCy >= 0)
return GetColorByIndex(fCy * fCols + fCx);
else
return TColor::RGB2Pixel(0, 0, 0);
}
//________________________________________________________________________________
void TGColorPalette::DoRedraw()
{
Int_t i, j, k, x, y;
k = 0;
y = 2;
for (i = 0; i < fRows; ++i) {
x = 2;
for (j = 0; j < fCols; ++j) {
Draw3dRectangle(kSunkenFrame | kDoubleBorder, x, y, fCw, fCh);
fDrawGC.SetForeground(fPixels[k++]);
gVirtualX->FillRectangle(fId, fDrawGC(), x + 2, y + 2, fCw - 4, fCh - 4);
x += fCw + 5;
}
y += fCh + 5;
}
DrawFocusHilite(kTRUE);
}
//________________________________________________________________________________
void TGColorPalette::GotFocus()
{
AddInput(kKeyPressMask | kKeyReleaseMask);
}
//________________________________________________________________________________
void TGColorPalette::LostFocus()
{
RemoveInput(kKeyPressMask | kKeyReleaseMask);
gClient->NeedRedraw(this);
}
//________________________________________________________________________________
void TGColorPalette::DrawFocusHilite(Int_t onoff)
{
if (fCx >= 0 && fCy >= 0) {
GContext_t gc = onoff ? GetShadowGC()() : GetBckgndGC()();
gVirtualX->DrawRectangle(fId, gc, fCx * (fCw + 5) + 0, fCy * (fCh + 5) + 0,
fCw + 3, fCh + 3);
}
}
//________________________________________________________________________________
TGColorPick::TGColorPick(const TGWindow *p, Int_t w, Int_t h, Int_t id) :
TGFrame(p, w, h, kChildFrame), fCursorGC(GetBlackGC())
{
UInt_t iw, ih;
fWidgetId = id;
fWidgetFlags = kWidgetIsEnabled;
fMsgWindow = p;
fColormapRect.fX = 1;
fColormapRect.fY = 1;
fColormapRect.fWidth = w - 33 - 2;
fColormapRect.fHeight = h - 2;
fSliderRect.fX = w - 18 - 2;
fSliderRect.fY = 1;
fSliderRect.fWidth = 10;
fSliderRect.fHeight = h - 2;
fNColors = 0;
CreateImages();
gVirtualX->GetImageSize(fLimage, iw, ih);
fCx = 0;
fCy = 0;
fCz = (Int_t)ih / 2;
fClick = kCLICK_NONE;
UpdateCurrentColor();
InitImages();
gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
kButtonPressMask | kButtonReleaseMask |
kPointerMotionMask, kNone, kNone);
AddInput(kKeyPressMask | kEnterWindowMask | kLeaveWindowMask |
kFocusChangeMask | kStructureNotifyMask);
}
//________________________________________________________________________________
TGColorPick::~TGColorPick()
{
gVirtualX->DeleteImage(fHSimage);
gVirtualX->DeleteImage(fLimage);
FreeColors();
}
//________________________________________________________________________________
Bool_t TGColorPick::HandleButton(Event_t *event)
{
if (event->fCode != kButton1) return kFALSE;
if (event->fType == kButtonPress) {
if ((event->fX > fColormapRect.fX) && (event->fX < fColormapRect.fX + fColormapRect.fWidth) &&
(event->fY > fColormapRect.fY) && (event->fY < fColormapRect.fY + fColormapRect.fHeight)) {
fClick = kCLICK_HS;
SetHScursor(event->fX - fColormapRect.fX, event->fY - fColormapRect.fY);
} else if (event->fX > fSliderRect.fX) {
fClick = kCLICK_L;
SetLcursor(event->fY - fSliderRect.fY);
}
} else { // ButtonRelease
fClick = kCLICK_NONE;
}
UpdateCurrentColor();
if (fClick == kCLICK_HS) SetSliderColor();
SendMessage(fMsgWindow, MK_MSG(kC_COLORSEL, kCOL_CLICK), fWidgetId, kFALSE);
ColorSelected();
return kTRUE;
}
//________________________________________________________________________________
Bool_t TGColorPick::HandleMotion(Event_t *event)
{
if (!IsEnabled())
return kTRUE;
if (fClick == kCLICK_HS) {
SetHScursor(event->fX - fColormapRect.fX, event->fY - fColormapRect.fY);
} else if (fClick == kCLICK_L) {
SetLcursor(event->fY - fSliderRect.fY);
} else {
return kTRUE;
}
UpdateCurrentColor();
if (fClick == kCLICK_HS) SetSliderColor();
SendMessage(fMsgWindow, MK_MSG(kC_COLORSEL, kCOL_CLICK), fWidgetId, kFALSE);
ColorSelected();
return kTRUE;
}
//________________________________________________________________________________
void TGColorPick::CreateImages()
{
UInt_t width, height;
width = fColormapRect.fWidth;
height = fColormapRect.fHeight;
fHSimage = gVirtualX->CreateImage(width, height);
width = fSliderRect.fWidth;
height = fSliderRect.fHeight;
fLimage = gVirtualX->CreateImage(width, height);
}
//________________________________________________________________________________
void TGColorPick::AllocColors()
{
// Try to allocate first a palette of 64 colors. Used by the dithered
// version of the color maps.
ColorStruct_t color;
Int_t i;
for (i = 0; i < 64; ++i) {
Int_t cc[4] = { 0, 21845, 43691, 65535 };
color.fPixel = 0;
color.fRed = cc[i & 0x3];
color.fGreen = cc[(i >> 2) & 0x3];
color.fBlue = cc[(i >> 4) & 0x3];
if (gVirtualX->AllocColor(gVirtualX->GetColormap(), color) == 0)
break;
fColormap[i][0] = color.fRed / 256;
fColormap[i][1] = color.fGreen / 256;
fColormap[i][2] = color.fBlue / 256;
fPixel[i] = color.fPixel;
}
fNColors = i;
if (fNColors == 64) return; // success
// Failed, try a simpler 27-color.
FreeColors();
for (i = 0; i < 27; ++i) {
Int_t cc[3] = { 0, 32768, 65535 };
color.fPixel = 0;
color.fRed = cc[i % 3];
color.fGreen = cc[(i / 3) % 3];
color.fBlue = cc[(i / 9) % 3];
if (gVirtualX->AllocColor(gVirtualX->GetColormap(), color) == 0)
break;
fColormap[i][0] = color.fRed / 256;
fColormap[i][1] = color.fGreen / 256;
fColormap[i][2] = color.fBlue / 256;
fPixel[i] = color.fPixel;
}
fNColors = i;
if (fNColors == 27) return; // success
// Failed, try then a much simpler 8-color.
FreeColors();
for (i = 0; i < 8; ++i) {
color.fPixel = 0;
color.fRed = (i & 1) * 65535;
color.fGreen = ((i >> 1) & 1) * 65535;
color.fBlue = ((i >> 2) & 1) * 65535;
if (gVirtualX->AllocColor(gVirtualX->GetColormap(), color) == 0)
break;
fColormap[i][0] = color.fRed / 256;
fColormap[i][1] = color.fGreen / 256;
fColormap[i][2] = color.fBlue / 256;
fPixel[i] = color.fPixel;
}
fNColors = i;
if (fNColors == 8) return; // success
// Failed, try to get at least 8 closest colors...
// (TODO: search for closest colors in the colormap, right now we just
// get as many as exact colors we can for the 8-color palette)
FreeColors();
for (i = 0; i < 8; ++i) {
color.fPixel = 0;
color.fRed = (i & 1) * 65535;
color.fGreen = ((i >> 1) & 1) * 65535;
color.fBlue = ((i >> 2) & 1) * 65535;
if (gVirtualX->AllocColor(gVirtualX->GetColormap(), color) != 0) {
fColormap[fNColors][0] = color.fRed / 256;
fColormap[fNColors][1] = color.fGreen / 256;
fColormap[fNColors][2] = color.fBlue / 256;
fPixel[fNColors++] = color.fPixel;
}
}
// continue with what we got...
}
//________________________________________________________________________________
void TGColorPick::FreeColors()
{
for (Int_t i = 0; i < fNColors; i++)
gVirtualX->FreeColor(gVirtualX->GetColormap(), fPixel[i]);
fNColors = 0;
}
//________________________________________________________________________________
void TGColorPick::CreateDitheredImage(Pixmap_t image, Int_t which)
{
// Create a dithered version of the color map and lightness images for
// display modes with reduced number of colors. The Floyd-Steinberg error
// diffusion dithering algorithm is used.
// This routine is called in PseudoColor modes only.
const Int_t kWidth = 20;
ColorStruct_t line[kWidth];
struct { Int_t r, g, b; } ed[kWidth], ef;
Int_t x, y, c, v, e[4], nc = 0;
Int_t r, g, b;
Int_t h, l, s;
Long_t dist, sdist;
Int_t iw, ih;
gVirtualX->GetImageSize(image, (UInt_t&) iw, (UInt_t&) ih);
for (x = 0; x < iw; ++x) {
ed[x].r = ed[x].g = ed[x].b = 0;
}
if (fNColors == 0) AllocColors();
for (y = 0; y < ih; ++y) {
if (which == kIMG_HS) {
for (x = 0; x < iw; ++x) {
h = x * 255 / iw;
l = 128;
s = (ih - y) * 255 / ih;
TColor::HLS2RGB(h, l, s, r, g, b);
line[x].fRed = r;
line[x].fGreen = g;
line[x].fBlue = b;
}
} else if (which == kIMG_L) {
TColor::Pixel2RGB(fCurrentColor, r, g, b);
TColor::RGB2HLS(r, g, b, h, l, s);
Int_t l = (ih - y) * 255 / ih;
TColor::HLS2RGB(h, l, s, r, g, b);
for (Int_t x = 0; x < iw; ++x) {
line[x].fRed = r;
line[x].fGreen = g;
line[x].fBlue = b;
}
} else {
return;
}
ef.r = ef.g = ef.b = 0; // no forward error for first pixel
for (x = 0; x < iw; ++x) {
// add errors from previous line
v = line[x].fRed + ed[x].r;
if (v < 0) v = 0; else if (v > 255) v = 255;
line[x].fRed = v;
v = line[x].fGreen + ed[x].g;
if (v < 0) v = 0; else if (v > 255) v = 255;
line[x].fGreen = v;
v = line[x].fBlue + ed[x].b;
if (v < 0) v = 0; else if (v > 255) v = 255;
line[x].fBlue = v;
}
for (x = 0; x < iw; ++x) {
// add forward errors
v = line[x].fRed + ef.r;
if (v < 0) v = 0; else if (v > 255) v = 255;
line[x].fRed = v;
v = line[x].fGreen + ef.g;
if (v < 0) v = 0; else if (v > 255) v = 255;
line[x].fGreen = v;
v = line[x].fBlue + ef.b;
if (v < 0) v = 0; else if (v > 255) v = 255;
line[x].fBlue = v;
// find the nearest color in colormap[]
sdist = 255L * 255L * 255L;
for (c = 0; c < fNColors; ++c) {
Int_t dr = line[x].fRed - fColormap[c][0];
Int_t dg = line[x].fGreen - fColormap[c][1];
Int_t db = line[x].fBlue - fColormap[c][2];
dist = dr * dr + dg * dg + db * db;
if (dist < sdist) {
nc = c;
sdist = dist;
}
}
gVirtualX->PutPixel(image, x, y, fPixel[nc]);
#define FILTER(v) \
e[0] = (7 * v) >> 4; \
e[1] = v >> 4; \
e[2] = (5 * v) >> 4; \
e[3] = (3 * v) >> 4;
v = line[x].fRed - fColormap[nc][0];
FILTER(v)
ef.r = e[0];
if (x < iw-1) ed[x+1].r = e[1];
if (x == 0) ed[x].r = e[2]; else ed[x].r += e[2];
if (x > 0) ed[x-1].r += e[3];
v = line[x].fGreen - fColormap[nc][1];
FILTER(v)
ef.g = e[0];
if (x < iw-1) ed[x+1].g = e[1];
if (x == 0) ed[x].g = e[2]; else ed[x].g += e[2];
if (x > 0) ed[x-1].g += e[3];
v = line[x].fBlue - fColormap[nc][2];
FILTER(v)
ef.b = e[0];
if (x < iw-1) ed[x+1].b = e[1];
if (x == 0) ed[x].b = e[2]; else ed[x].b += e[2];
if (x > 0) ed[x-1].b += e[3];
}
}
}
//________________________________________________________________________________
void TGColorPick::InitImages()
{
Int_t width, height;
Int_t h, l, s;
Int_t r, g, b;
gVirtualX->GetImageSize(fHSimage, (UInt_t&) width, (UInt_t&) height);
// initialize fHSimage
Int_t ncolors = gVirtualX->GetDepth();
if (ncolors > 8) {
for (Int_t y = 0; y < height; ++y) {
for (Int_t x = 0; x < width; ++x) {
r = g = b = 0;
h = x * 255 / width;
l = 128;
s = (height - y) * 255 / height;
TColor::HLS2RGB(h, l, s, r, g, b);
ULong_t pixel = TColor::RGB2Pixel(r, g, b);
gVirtualX->PutPixel(fHSimage, x, y, pixel);
}
}
} else {
CreateDitheredImage(fHSimage, kIMG_HS);
}
// initialize fLimage
SetSliderColor();
}
//________________________________________________________________________________
void TGColorPick::SetSliderColor()
{
Int_t width, height;
Int_t h, l, s;
Int_t r, g, b;
gVirtualX->GetImageSize(fLimage, (UInt_t&) width, (UInt_t&) height);
Int_t ncolors = gVirtualX->GetDepth();
if (ncolors > 8) {
for (Int_t y = 0; y < height; ++y) {
TColor::Pixel2RGB(fCurrentColor, r, g, b);
TColor::RGB2HLS(r, g, b, h, l, s);
l = (height - y) * 255 / height;
TColor::HLS2RGB(h, l, s, r, g, b);
ULong_t pixel = TColor::RGB2Pixel(r, g, b);
for (Int_t x = 0; x < width; ++x) {
gVirtualX->PutPixel(fLimage, x, y, pixel);
}
}
} else {
CreateDitheredImage(fLimage, kIMG_L);
}
gClient->NeedRedraw(this);
}
//________________________________________________________________________________
void TGColorPick::SetColor(ULong_t color)
{
UInt_t width, height;
Int_t h, l, s;
Int_t r, g, b;
gVirtualX->GetImageSize(fHSimage, width, height);
fCurrentColor = color;
TColor::Pixel2RGB(fCurrentColor, r, g, b);
TColor::RGB2HLS(r, g, b, h, l, s);
SetHScursor(h * (Int_t)width / 256, (255 - s) * (Int_t)height / 256);
gVirtualX->GetImageSize(fLimage, width, height);
SetLcursor((255 - l) * (Int_t)height / 256);
SetSliderColor();
}
//________________________________________________________________________________
void TGColorPick::UpdateCurrentColor()
{
UInt_t lwidth, lheight;
UInt_t swidth, sheight;
Int_t r, g, b;
Int_t h, l, s;
gVirtualX->GetImageSize(fLimage, lwidth, lheight);
gVirtualX->GetImageSize(fHSimage, swidth, sheight);
h = Int_t(fCx * 255 / swidth);
l = Int_t((lheight - fCz) * 255 / lheight);
s = Int_t((sheight - fCy) * 255 / sheight);
TColor::HLS2RGB(h, l, s, r, g, b);
fCurrentColor = TColor::RGB2Pixel(r, g, b);
}
//________________________________________________________________________________
void TGColorPick::DoRedraw()
{
UInt_t lwidth, lheight;
UInt_t swidth, sheight;
gVirtualX->GetImageSize(fLimage, lwidth, lheight);
gVirtualX->GetImageSize(fHSimage, swidth, sheight);
DrawBorder();
Draw3dRectangle(kSunkenFrame, fColormapRect.fX - 1, fColormapRect.fY - 1,
fColormapRect.fWidth + 2, fColormapRect.fHeight + 2);
gVirtualX->PutImage(fId, GetBckgndGC()(), fHSimage,
fColormapRect.fX, fColormapRect.fY, 0, 0, swidth, sheight);
Draw3dRectangle(kSunkenFrame, fSliderRect.fX - 1, fSliderRect.fY - 1,
fSliderRect.fWidth + 2, fSliderRect.fHeight + 2);
gVirtualX->PutImage(fId, GetBckgndGC()(), fLimage,
fSliderRect.fX, fSliderRect.fY, 0, 0, lwidth, lheight);
DrawHScursor(kTRUE);
DrawLcursor(kTRUE);
}
//________________________________________________________________________________
void TGColorPick::SetHScursor(Int_t x, Int_t y)
{
UInt_t width, height;
gVirtualX->GetImageSize(fHSimage, width, height);
DrawHScursor(kFALSE);
fCx = x;
fCy = y;
if (fCx < 0)
fCx = 0;
else if (fCx >= (Int_t)width)
fCx = (Int_t)width - 1;
if (fCy < 0)
fCy = 0;
else if (fCy >= (Int_t)height)
fCy = (Int_t)height - 1;
DrawHScursor(kTRUE);
}
//________________________________________________________________________________
void TGColorPick::SetLcursor(Int_t z)
{
UInt_t width, height;
gVirtualX->GetImageSize(fLimage, width, height);
DrawLcursor(kFALSE);
fCz = z - fSliderRect.fY;
if (fCz < 0)
fCz = 0;
else if (fCz >= (Int_t)height)
fCz = (Int_t)height - 1;
DrawLcursor(kTRUE);
}
//________________________________________________________________________________
void TGColorPick::DrawHScursor(Int_t onoff)
{
UInt_t width, height;
gVirtualX->GetImageSize(fHSimage, width, height);
if (onoff) {
Int_t x, y;
Rectangle_t rect;
x = fCx + fColormapRect.fX;
y = fCy + fColormapRect.fY;
rect.fX = fColormapRect.fX;
rect.fY = fColormapRect.fX;
rect.fWidth = fColormapRect.fWidth;
rect.fHeight = fColormapRect.fHeight;
gVirtualX->SetClipRectangles(fCursorGC(), 0, 0, &rect, 1);
gVirtualX->FillRectangle(fId, fCursorGC(), x - 9, y - 1, 5, 3);
gVirtualX->FillRectangle(fId, fCursorGC(), x - 1, y - 9, 3, 5);
gVirtualX->FillRectangle(fId, fCursorGC(), x + 5, y - 1, 5, 3);
gVirtualX->FillRectangle(fId, fCursorGC(), x - 1, y + 5, 3, 5);
} else {
Int_t x, y;
UInt_t w, h;
x = fCx - 9; w = 19;
y = fCy - 9; h = 19;
if (x < 0) { w += x; x = 0; }
if (y < 0) { h += y; y = 0; }
if (x + w > width) w = width - x;
if (y + h > width) h = height - y;
gVirtualX->PutImage(fId, GetBckgndGC()(), fHSimage, x, y,
fColormapRect.fX + x, fColormapRect.fY + y, w, h);
}
}
//________________________________________________________________________________
void TGColorPick::DrawLcursor(Int_t onoff)
{
Int_t l = fSliderRect.fX + fSliderRect.fWidth + 3;
Int_t r = l + 5;
Int_t t = fCz - 5 + fSliderRect.fY;
Int_t b = t + 10;
Point_t points[3];
Int_t m = (t + b) >> 1;
points[0].fX = r;
points[0].fY = t;
points[1].fX = r;
points[1].fY = b;
points[2].fX = l;
points[2].fY = m;
GContext_t gc = onoff ? GetShadowGC()() : GetBckgndGC()();
gVirtualX->FillPolygon(fId, gc, points, 3);
}
//________________________________________________________________________________
TGColorDialog::TGColorDialog(const TGWindow *p, const TGWindow *m,
Int_t *retc, ULong_t *color) :
TGTransientFrame(p, m, 200, 150, kHorizontalFrame)
{
const Int_t kC_X = 175; // Win95: 177
const Int_t kC_Y = 180; // Win95: 189
Int_t ax, ay, i;
fRetc = retc;
fRetColor = color;
if (fRetc) *fRetc = kMBCancel;
TGVerticalFrame *vf1 = new TGVerticalFrame(this, 20, 20);
TGVerticalFrame *vf2 = new TGVerticalFrame(this, 20, 20);
AddFrame(vf1, new TGLayoutHints(kLHintsLeft | kLHintsExpandY));
AddFrame(vf2, new TGLayoutHints(kLHintsLeft | kLHintsExpandY));
//----------------------------------------- Left panel
// basic colors
vf1->AddFrame(new TGLabel(vf1, new TGHotString("&Basic colors:")),
new TGLayoutHints(kLHintsNormal, 5, 0, 7, 2));
fPalette = new TGColorPalette(vf1, 8, 6, kCDLG_SPALETTE);
vf1->AddFrame(fPalette, new TGLayoutHints(kLHintsNormal, 5, 5, 0, 0));
fPalette->Associate(this);
for (i = 0; i < 48; ++i)
fPalette->SetColor(i, TColor::RGB2Pixel(bcolor[i][0], bcolor[i][1], bcolor[i][2]));
// custom colors
vf1->AddFrame(new TGLabel(vf1, new TGHotString("&Custom colors:")),
new TGLayoutHints(kLHintsNormal, 5, 0, 15, 2));
fCpalette = new TGColorPalette(vf1, 8, 3, kCDLG_CPALETTE);
vf1->AddFrame(fCpalette, new TGLayoutHints(kLHintsNormal, 5, 5, 0, 0));
fCpalette->Associate(this);
if (ucolor[0] == 0xff000000) {
for (i = 0; i < 24; i++)
ucolor[i] = TColor::RGB2Pixel(255, 255, 255);
}
fCpalette->SetColors(ucolor);
// button frame
TGHorizontalFrame *hf = new TGHorizontalFrame(vf1, 10, 10, kFixedWidth);
vf1->AddFrame(hf, new TGLayoutHints(kLHintsBottom | kLHintsLeft, 5, 5, 10, 5));
TGTextButton *ok = new TGTextButton(hf, new TGHotString("OK"), kCDLG_OK);
TGTextButton *cancel = new TGTextButton(hf, new TGHotString("Cancel"), kCDLG_CANCEL);
hf->AddFrame(ok, new TGLayoutHints(kLHintsBottom | kLHintsExpandX, 0, 5, 0, 0));
hf->AddFrame(cancel, new TGLayoutHints(kLHintsBottom | kLHintsExpandX));
UInt_t w = ok->GetDefaultWidth();
w = TMath::Max(w, cancel->GetDefaultWidth());
hf->Resize(2 * (w + 20), hf->GetDefaultHeight());
ok->Associate(this);
cancel->Associate(this);
//----------------------------------------- Right panel
// fColormap frame
fColors = new TGColorPick(vf2, kC_X + 33, kC_Y, kCDLG_COLORPICK);
vf2->AddFrame(fColors, new TGLayoutHints(kLHintsLeft | kLHintsTop, 5, 5, 15, 5));
fColors->Associate(this);
if (color)
fColors->SetColor(*color);
// color sample frame
TGHorizontalFrame *hf3 = new TGHorizontalFrame(vf2, 10, 10);
vf2->AddFrame(hf3, new TGLayoutHints(kLHintsLeft | kLHintsTop, 5, 5, 2, 5));
TGVerticalFrame *vf3 = new TGVerticalFrame(hf3, 10, 10);
hf3->AddFrame(vf3, new TGLayoutHints(kLHintsLeft | kLHintsTop));
fSample = new TGFrame(vf3, 60, 42, kSunkenFrame | kOwnBackground);
vf3->AddFrame(fSample, new TGLayoutHints(kLHintsLeft | kLHintsTop));
vf3->AddFrame(new TGLabel(vf3, new TGString("Color")),
new TGLayoutHints(kLHintsCenterX | kLHintsTop, 0, 0, 2, 0));
if (color)
fCurrentColor = *color;
else
gClient->GetColorByName("red", fCurrentColor);
fSample->SetBackgroundColor(fCurrentColor);
TGCompositeFrame *cf = new TGCompositeFrame(hf3, 10, 10);
hf3->AddFrame(cf, new TGLayoutHints(kLHintsLeft | kLHintsTop, 10, 0, 0, 0));
cf->SetLayoutManager(new TGMatrixLayout(cf, 0, 2, 4));
cf->AddFrame(new TGLabel(cf, new TGHotString("Hu&e:")), 0);
cf->AddFrame(fHte = new TGTextEntry(cf, fHtb = new TGTextBuffer(5), kCDLG_HTE), 0);
fHte->Resize(35, fHte->GetDefaultHeight());
cf->AddFrame(new TGLabel(cf, new TGHotString("&Sat:")), 0);
cf->AddFrame(fSte = new TGTextEntry(cf, fStb = new TGTextBuffer(5), kCDLG_STE), 0);
fSte->Resize(35, fSte->GetDefaultHeight());
cf->AddFrame(new TGLabel(cf, new TGHotString("&Lum:")), 0);
cf->AddFrame(fLte = new TGTextEntry(cf, fLtb = new TGTextBuffer(5), kCDLG_LTE), 0);
fLte->Resize(35, fLte->GetDefaultHeight());
cf = new TGCompositeFrame(hf3, 10, 10);
hf3->AddFrame(cf, new TGLayoutHints(kLHintsLeft | kLHintsTop, 5, 0, 0, 0));
cf->SetLayoutManager(new TGMatrixLayout(cf, 0, 2, 4));
cf->AddFrame(new TGLabel(cf, new TGHotString("&Red:")), 0);
cf->AddFrame(fRte = new TGTextEntry(cf, fRtb = new TGTextBuffer(5), kCDLG_RTE), 0);
fRte->Resize(35, fRte->GetDefaultHeight());
cf->AddFrame(new TGLabel(cf, new TGHotString("&Green:")), 0);
cf->AddFrame(fGte = new TGTextEntry(cf, fGtb = new TGTextBuffer(5), kCDLG_GTE), 0);
fGte->Resize(35, fGte->GetDefaultHeight());
cf->AddFrame(new TGLabel(cf, new TGHotString("Bl&ue:")), 0);
cf->AddFrame(fBte = new TGTextEntry(cf, fBtb = new TGTextBuffer(5), kCDLG_BTE), 0);
fBte->Resize(35, fBte->GetDefaultHeight());
fHte->Associate(this);
fLte->Associate(this);
fSte->Associate(this);
fRte->Associate(this);
fGte->Associate(this);
fBte->Associate(this);
if (color) {
UpdateRGBentries(color);
UpdateHLSentries(color);
}
TGTextButton *add = new TGTextButton(vf2, new TGHotString("&Add to Custom Colors"),
kCDLG_ADD);
vf2->AddFrame(add, new TGLayoutHints(kLHintsBottom | kLHintsExpandX,
5, 5, 0, 5));
add->Associate(this);
MapSubwindows();
Resize(GetDefaultSize());
//---- position relative to the parent's window
if (m) {
Window_t wdum;
gVirtualX->TranslateCoordinates(m->GetId(), GetParent()->GetId(),
(Int_t)(((TGFrame *) m)->GetWidth() - fWidth) >> 1,
(Int_t)(((TGFrame *) m)->GetHeight() - fHeight) >> 1,
ax, ay, wdum);
} else {
UInt_t root_w, root_h;
gVirtualX->GetWindowSize(gClient->GetRoot()->GetId(), ax, ay, root_w, root_h);
ax = (root_w - fWidth) >> 1;
ay = (root_h - fHeight) >> 1;
}
Move(ax, ay);
SetWMPosition(ax, ay);
//---- make the message box non-resizable
SetWMSize(fWidth, fHeight);
SetWMSizeHints(fWidth, fHeight, fWidth, fHeight, 0, 0);
SetWindowName("Color Selector");
SetIconName("Color Selector");
SetClassHints("ColorSelector", "ColorSelector");
SetMWMHints(kMWMDecorAll | kMWMDecorResizeH | kMWMDecorMaximize |
kMWMDecorMinimize | kMWMDecorMenu,
kMWMFuncAll | kMWMFuncResize | kMWMFuncMaximize |
kMWMFuncMinimize,
kMWMInputModeless);
MapWindow();
fClient->WaitFor(this);
}
//________________________________________________________________________________
TGColorDialog::~TGColorDialog()
{
Cleanup();
}
//________________________________________________________________________________
void TGColorDialog::CloseWindow()
{
// Called when window is closed via window manager.
// save user set colors
for (Int_t i = 0; i < 24; ++i)
ucolor[i] = fCpalette->GetColorByIndex(i);
DeleteWindow();
}
//________________________________________________________________________________
void TGColorDialog::UpdateRGBentries(ULong_t *c)
{
Char_t tmp[20];
Int_t r, g, b;
TColor::Pixel2RGB(*c, r, g, b);
sprintf(tmp, "%d", r);
fRtb->Clear();
fRtb->AddText(0, tmp);
gClient->NeedRedraw(fRte);
sprintf(tmp, "%d", g);
fGtb->Clear();
fGtb->AddText(0, tmp);
gClient->NeedRedraw(fGte);
sprintf(tmp, "%d", b);
fBtb->Clear();
fBtb->AddText(0, tmp);
gClient->NeedRedraw(fBte);
}
//________________________________________________________________________________
void TGColorDialog::UpdateHLSentries(ULong_t *c)
{
Char_t tmp[20];
Int_t h, l, s;
Int_t r, g, b;
TColor::Pixel2RGB(*c, r, g, b);
TColor::RGB2HLS(r, g, b, h, l, s);
sprintf(tmp, "%d", h);
fHtb->Clear();
fHtb->AddText(0, tmp);
gClient->NeedRedraw(fHte);
sprintf(tmp, "%d", l);
fLtb->Clear();
fLtb->AddText(0, tmp);
gClient->NeedRedraw(fLte);
sprintf(tmp, "%d", s);
fStb->Clear();
fStb->AddText(0, tmp);
gClient->NeedRedraw(fSte);
}
//________________________________________________________________________________
Bool_t TGColorDialog::ProcessMessage(Long_t msg, Long_t parm1, Long_t /*parm2*/)
{
ULong_t color;
Int_t h, l, s;
Int_t r, g, b;
switch (GET_MSG(msg)) {
case kC_COMMAND:
switch (GET_SUBMSG(msg)) {
case kCM_BUTTON:
switch(parm1) {
case kCDLG_ADD:
fCpalette->SetCurrentCellColor(fCurrentColor);
break;
case kCDLG_OK:
*fRetc = kMBOk;
*fRetColor = TColor::RGB2Pixel(atoi(fRtb->GetString()),
atoi(fGtb->GetString()),
atoi(fBtb->GetString()));
// fall through
case kCDLG_CANCEL:
CloseWindow();
break;
}
break;
}
break;
case kC_COLORSEL:
switch (GET_SUBMSG(msg)) {
case kCOL_CLICK:
switch (parm1) {
case kCDLG_SPALETTE:
color = fPalette->GetCurrentColor();
fSample->SetBackgroundColor(color);
gClient->NeedRedraw(fSample);
fCurrentColor = color;
fColors->SetColor(color);
UpdateRGBentries(&color);
UpdateHLSentries(&color);
break;
case kCDLG_CPALETTE:
color = fCpalette->GetCurrentColor();
fSample->SetBackgroundColor(color);
gClient->NeedRedraw(fSample);
fCurrentColor = color;
fColors->SetColor(color);
UpdateRGBentries(&color);
UpdateHLSentries(&color);
break;
case kCDLG_COLORPICK:
color = fColors->GetCurrentColor();
fSample->SetBackgroundColor(color);
gClient->NeedRedraw(fSample);
fCurrentColor = color;
UpdateRGBentries(&color);
UpdateHLSentries(&color);
break;
}
break;
}
break;
case kC_TEXTENTRY:
switch (GET_SUBMSG(msg)) {
case kTE_TEXTCHANGED:
switch (parm1) {
case kCDLG_HTE:
case kCDLG_LTE:
case kCDLG_STE:
h = atoi(fHtb->GetString());
l = atoi(fLtb->GetString());
s = atoi(fStb->GetString());
TColor::HLS2RGB(h, l, s, r, g, b);
color = TColor::RGB2Pixel(r, g, b);
fSample->SetBackgroundColor(color);
gClient->NeedRedraw(fSample);
fCurrentColor = color;
fColors->SetColor(color);
UpdateRGBentries(&color);
break;
case kCDLG_RTE:
case kCDLG_GTE:
case kCDLG_BTE:
color = TColor::RGB2Pixel(atoi(fRtb->GetString()),
atoi(fGtb->GetString()),
atoi(fBtb->GetString()));
fSample->SetBackgroundColor(color);
gClient->NeedRedraw(fSample);
fCurrentColor = color;
fColors->SetColor(color);
UpdateHLSentries(&color);
break;
}
break;
}
break;
}
return kTRUE;
}
ROOT page - Class index - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.