wmaker: removed unused macro DBLCLICK_TIME
[wmaker-crm.git] / WINGs / wcolorpanel.c
blobf23c91d25584a6bec97f976a59ab924962858bb8
1 /*
2 * ColorPanel for WINGs
4 * by ]d : Original idea and basic initial code
5 * Pascal Hofstee : Code for wheeldrawing and calculating
6 * colors from it.
7 * Primary coder of this Color Panel.
8 * Alban Hertroys : Optimizations for algorithms for color-
9 * wheel. Also custom ColorPalettes and
10 * magnifying glass. Secondary coder ;)
11 * Alfredo K. Kojima : For pointing out memory-allocation
12 * problems and similair code-issues
13 * Marco van Hylckama-Vlieg : For once again doing the artwork ;-)
17 /* TODO:
18 * - Look at further optimization of colorWheel matrix calculation.
19 * It appears to be rather symmetric in angles of 60 degrees,
20 * while it is optimized in angles of 90 degrees.
21 * - Custom color-lists and custom colors in custom color-lists.
22 * - Stored colors
23 * - Resizing
26 #include "wconfig.h"
27 #include "WINGsP.h"
28 #include "rgb.h"
30 #include <errno.h>
31 #include <math.h>
32 #include <unistd.h>
33 #include <ctype.h>
34 #include <fcntl.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <dirent.h>
40 /* BUG There's something fishy with shaped windows */
41 /* Whithout shape extension the magnified image is completely broken -Dan */
43 #ifdef USE_XSHAPE
44 # include <X11/extensions/shape.h>
45 #endif
47 char *WMColorPanelColorChangedNotification = "WMColorPanelColorChangedNotification";
50 * Bitmaps for magnifying glass cursor
53 /* Cursor */
54 #define Cursor_x_hot 11
55 #define Cursor_y_hot 11
56 #define Cursor_width 32
57 #define Cursor_height 32
58 static unsigned char Cursor_bits[] = {
59 0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
60 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
61 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
62 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
63 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
64 0x00, 0x08, 0x00, 0x50, 0x00, 0x10, 0x00, 0x88, 0x00, 0x20, 0x00, 0x5c, 0x01, 0xc0, 0x81,
65 0x3b, 0x02, 0x00, 0x7e, 0x70, 0x05, 0x00, 0x00, 0xe0, 0x08, 0x00, 0x00, 0xc0, 0x15, 0x00,
66 0x00, 0x80, 0x23, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x5c,
67 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x70
70 /* Cursor shape-mask */
71 #define Cursor_shape_width 32
72 #define Cursor_shape_height 32
73 static unsigned char Cursor_shape_bits[] = {
74 0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
75 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
76 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
77 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
78 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
79 0x00, 0x08, 0x00, 0x70, 0x00, 0x10, 0x00, 0xf8, 0x00, 0x20, 0x00, 0xfc, 0x01, 0xc0, 0x81,
80 0xfb, 0x03, 0x00, 0x7e, 0xf0, 0x07, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xc0, 0x1f, 0x00,
81 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xfc,
82 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x70
85 /* Clip-mask for magnified pixels */
86 #define Cursor_mask_width 24
87 #define Cursor_mask_height 24
88 static unsigned char Cursor_mask_bits[] = {
89 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0xff, 0x07,
90 0xf0, 0xff, 0x0f, 0xf8, 0xff, 0x1f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f,
91 0xfc, 0xff, 0x3f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f,
92 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfc, 0xff, 0x3f,
93 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xf8, 0xff, 0x1f, 0xf0, 0xff, 0x0f,
94 0xe0, 0xff, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00
97 typedef struct MovingView {
98 WMView *view; /* The view this is all about */
99 XImage *image; /* What's under the view */
100 XImage *dirtyRect; /* Storage of overlapped image area */
101 Pixmap magPix; /* Magnified part of pixmap */
102 RColor color; /* Color of a pixel in the image */
103 int x, y; /* Position of view */
104 } MovingView;
106 typedef struct CPColor {
107 RColor rgb; /* The RGB values of the color */
108 RHSVColor hsv; /* The HSV values of the color */
109 enum { /* Which one was last set ? */
110 cpNone,
111 cpRGB,
112 cpHSV
113 } set;
114 } CPColor;
116 typedef struct WheelMatrix {
117 unsigned int width, height; /* Size of the colorwheel */
118 unsigned char *data[3]; /* Wheel data (R,G,B) */
119 unsigned char values[256]; /* Precalculated values R,G & B = 0-255 */
120 } wheelMatrix;
122 typedef struct W_ColorPanel {
123 WMWindow *win;
124 WMFont *font8;
125 WMFont *font12;
126 void *clientData;
127 WMAction2 *action;
129 /* Common Stuff */
130 WMColorWell *colorWell;
131 WMButton *magnifyBtn;
132 WMButton *wheelBtn;
133 WMButton *slidersBtn;
134 WMButton *customPaletteBtn;
135 WMButton *colorListBtn;
137 /* Magnifying Glass */
138 MovingView *magnifyGlass;
140 /* ColorWheel Panel */
141 WMFrame *wheelFrm;
142 WMSlider *wheelBrightnessS;
143 WMView *wheelView;
145 /* Slider Panels */
146 WMFrame *slidersFrm;
147 WMFrame *seperatorFrm;
148 WMButton *grayBtn;
149 WMButton *rgbBtn;
150 WMButton *cmykBtn;
151 WMButton *hsbBtn;
152 /* Gray Scale Panel */
153 WMFrame *grayFrm;
154 WMLabel *grayMinL;
155 WMLabel *grayMaxL;
156 WMSlider *grayBrightnessS;
157 WMTextField *grayBrightnessT;
158 WMButton *grayPresetBtn[7];
160 /* RGB Panel */
161 WMButton *rgbDecB;
162 WMButton *rgbHexB;
163 WMFrame *rgbFrm;
164 WMLabel *rgbMinL;
165 WMLabel *rgbMaxL;
166 WMSlider *rgbRedS;
167 WMSlider *rgbGreenS;
168 WMSlider *rgbBlueS;
169 WMTextField *rgbRedT;
170 WMTextField *rgbGreenT;
171 WMTextField *rgbBlueT;
172 enum {
173 RGBdec,
174 RGBhex
175 } rgbState;
177 /* CMYK Panel */
178 WMFrame *cmykFrm;
179 WMLabel *cmykMinL;
180 WMLabel *cmykMaxL;
181 WMSlider *cmykCyanS;
182 WMSlider *cmykMagentaS;
183 WMSlider *cmykYellowS;
184 WMSlider *cmykBlackS;
185 WMTextField *cmykCyanT;
186 WMTextField *cmykMagentaT;
187 WMTextField *cmykYellowT;
188 WMTextField *cmykBlackT;
190 /* HSB Panel */
191 WMFrame *hsbFrm;
192 WMSlider *hsbHueS;
193 WMSlider *hsbSaturationS;
194 WMSlider *hsbBrightnessS;
195 WMTextField *hsbHueT;
196 WMTextField *hsbSaturationT;
197 WMTextField *hsbBrightnessT;
199 /* Custom Palette Panel */
200 WMFrame *customPaletteFrm;
201 WMPopUpButton *customPaletteHistoryBtn;
202 WMFrame *customPaletteContentFrm;
203 WMPopUpButton *customPaletteMenuBtn;
204 WMView *customPaletteContentView;
206 /* Color List Panel */
207 WMFrame *colorListFrm;
208 WMPopUpButton *colorListHistoryBtn;
209 WMList *colorListContentLst;
210 WMPopUpButton *colorListColorMenuBtn;
211 WMPopUpButton *colorListListMenuBtn;
213 /* Look-Up Tables and Images */
214 wheelMatrix *wheelMtrx;
215 Pixmap wheelImg;
216 Pixmap selectionImg;
217 Pixmap selectionBackImg;
218 RImage *customPaletteImg;
219 char *lastBrowseDir;
221 /* Common Data Fields */
222 CPColor color; /* Current color */
223 WMColorPanelMode mode; /* Current color selection mode */
224 WMColorPanelMode slidersmode; /* Current color sel. mode sliders panel */
225 WMColorPanelMode lastChanged; /* Panel that last changed the color */
226 int colx, coly; /* (x,y) of sel.-marker in WheelMode */
227 int palx, paly; /* (x,y) of sel.-marker in
228 CustomPaletteMode */
229 double palXRatio, palYRatio; /* Ratios in x & y between
230 original and scaled
231 palettesize */
232 int currentPalette;
233 char *configurationPath;
235 struct {
236 unsigned int continuous:1;
237 unsigned int dragging:1;
238 } flags;
239 } W_ColorPanel;
241 enum {
242 CPmenuNewFromFile,
243 CPmenuRename,
244 CPmenuRemove,
245 CPmenuCopy,
246 CPmenuNewFromClipboard
247 } customPaletteMenuItem;
249 enum {
250 CLmenuAdd,
251 CLmenuRename,
252 CLmenuRemove
253 } colorListMenuItem;
255 #define PWIDTH 194
256 #define PHEIGHT 266
257 #define colorWheelSize 150
258 #define customPaletteWidth 182
259 #define customPaletteHeight 106
260 #define knobThickness 8
262 #define SPECTRUM_WIDTH 511
263 #define SPECTRUM_HEIGHT 360
265 #define COLORWHEEL_PART 1
266 #define CUSTOMPALETTE_PART 2
269 static char *generateNewFilename(const char *curName);
270 static void convertCPColor(CPColor * color);
271 static RColor ulongToRColor(WMScreen * scr, unsigned long value);
272 static unsigned char getShift(unsigned char value);
274 static void modeButtonCallback(WMWidget * w, void *data);
275 static int getPickerPart(W_ColorPanel * panel, int x, int y);
276 static void readConfiguration(W_ColorPanel * panel);
277 static void readXColors(W_ColorPanel * panel);
279 static void closeWindowCallback(WMWidget * w, void *data);
281 static Cursor magnifyGrabPointer(W_ColorPanel * panel);
282 static WMPoint magnifyInitialize(W_ColorPanel * panel);
283 static void magnifyPutCursor(WMWidget * w, void *data);
284 static Pixmap magnifyCreatePixmap(WMColorPanel * panel);
285 static void magnifyGetImageStored(W_ColorPanel * panel, int x1, int y1, int x2, int y2);
286 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h);
288 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height);
289 static void wheelDestroyMatrix(wheelMatrix * matrix);
290 static void wheelInitMatrix(W_ColorPanel * panel);
291 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue);
292 static void wheelRender(W_ColorPanel * panel);
293 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs);
294 static void wheelPaint(W_ColorPanel * panel);
296 static void wheelHandleEvents(XEvent * event, void *data);
297 static void wheelHandleActionEvents(XEvent * event, void *data);
298 static void wheelBrightnessSliderCallback(WMWidget * w, void *data);
299 static void wheelUpdateSelection(W_ColorPanel * panel);
300 static void wheelUndrawSelection(W_ColorPanel * panel);
302 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y);
303 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
304 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel);
305 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor);
307 static void grayBrightnessSliderCallback(WMWidget * w, void *data);
308 static void grayPresetButtonCallback(WMWidget * w, void *data);
309 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification);
311 static void rgbSliderCallback(WMWidget * w, void *data);
312 static void rgbTextFieldCallback(void *observerData, WMNotification * notification);
313 static void rgbDecToHex(WMWidget *w, void *data);
315 static void cmykSliderCallback(WMWidget * w, void *data);
316 static void cmykTextFieldCallback(void *observerData, WMNotification * notification);
318 static void hsbSliderCallback(WMWidget * w, void *data);
319 static void hsbTextFieldCallback(void *observerData, WMNotification * notification);
320 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel);
321 static void hsbUpdateSaturationGradient(W_ColorPanel * panel);
322 static void hsbUpdateHueGradient(W_ColorPanel * panel);
324 static void customRenderSpectrum(W_ColorPanel * panel);
325 static void customSetPalette(W_ColorPanel * panel);
326 static void customPaletteHandleEvents(XEvent * event, void *data);
327 static void customPaletteHandleActionEvents(XEvent * event, void *data);
328 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y);
329 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
330 static void customPaletteMenuCallback(WMWidget * w, void *data);
331 static void customPaletteHistoryCallback(WMWidget * w, void *data);
333 static void customPaletteMenuNewFromFile(W_ColorPanel * panel);
334 static void customPaletteMenuRename(W_ColorPanel * panel);
335 static void customPaletteMenuRemove(W_ColorPanel * panel);
337 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect);
338 static void colorListSelect(WMWidget * w, void *data);
339 static void colorListColorMenuCallback(WMWidget * w, void *data);
340 static void colorListListMenuCallback(WMWidget * w, void *data);
342 static void wheelInit(W_ColorPanel * panel);
343 static void grayInit(W_ColorPanel * panel);
344 static void rgbInit(W_ColorPanel * panel);
345 static void cmykInit(W_ColorPanel * panel);
346 static void hsbInit(W_ColorPanel * panel);
349 static inline int get_textfield_as_integer(WMTextField *widget)
351 char *str;
352 int value;
354 str = WMGetTextFieldText(widget);
355 value = atoi(str);
356 wfree(str);
357 return value;
360 void WMSetColorPanelAction(WMColorPanel * panel, WMAction2 * action, void *data)
362 panel->action = action;
363 panel->clientData = data;
366 static WMColorPanel *makeColorPanel(WMScreen * scrPtr, const char *name)
368 WMColorPanel *panel;
369 RImage *image;
370 WMPixmap *pixmap;
371 RColor from;
372 RColor to;
373 WMColor *textcolor, *graybuttoncolor;
374 int i;
375 GC bgc = WMColorGC(scrPtr->black);
376 GC wgc = WMColorGC(scrPtr->white);
378 panel = wmalloc(sizeof(WMColorPanel));
379 panel->color.rgb.red = 0;
380 panel->color.rgb.green = 0;
381 panel->color.rgb.blue = 0;
382 panel->color.hsv.hue = 0;
383 panel->color.hsv.saturation = 0;
384 panel->color.hsv.value = 0;
385 panel->color.set = cpNone; /* Color has not been set yet */
387 panel->font8 = WMSystemFontOfSize(scrPtr, 8);
388 panel->font12 = WMSystemFontOfSize(scrPtr, 12);
390 panel->win = WMCreateWindowWithStyle(scrPtr, name,
391 WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
392 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
393 WMSetWindowTitle(panel->win, _("Colors"));
394 WMSetWindowCloseAction(panel->win, closeWindowCallback, panel);
396 /* Set Default ColorPanel Mode(s) */
397 panel->mode = WMWheelModeColorPanel;
398 panel->lastChanged = 0;
399 panel->slidersmode = WMRGBModeColorPanel;
400 panel->configurationPath = wstrconcat(wusergnusteppath(), "/Library/Colors/");
402 /* Some General Purpose Widgets */
403 panel->colorWell = WMCreateColorWell(panel->win);
404 WMResizeWidget(panel->colorWell, 134, 36);
405 WSetColorWellBordered(panel->colorWell, False);
406 WMMoveWidget(panel->colorWell, 56, 4);
408 panel->magnifyBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
409 WMResizeWidget(panel->magnifyBtn, 46, 36);
410 WMMoveWidget(panel->magnifyBtn, 6, 4);
411 WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
412 WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
413 WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
415 panel->wheelBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
416 WMResizeWidget(panel->wheelBtn, 46, 32);
417 WMMoveWidget(panel->wheelBtn, 6, 44);
418 WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
419 WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
420 WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
422 panel->slidersBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
423 WMResizeWidget(panel->slidersBtn, 46, 32);
424 WMMoveWidget(panel->slidersBtn, 52, 44);
425 WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
426 WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
427 WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
429 panel->customPaletteBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
430 WMResizeWidget(panel->customPaletteBtn, 46, 32);
431 WMMoveWidget(panel->customPaletteBtn, 98, 44);
432 WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
433 WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
434 WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
436 panel->colorListBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
437 WMResizeWidget(panel->colorListBtn, 46, 32);
438 WMMoveWidget(panel->colorListBtn, 144, 44);
439 WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
440 WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
441 WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
443 /* Let's Group some of them together */
444 WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
445 WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
446 WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
448 /* Widgets for the ColorWheel Panel */
449 panel->wheelFrm = WMCreateFrame(panel->win);
450 WMSetFrameRelief(panel->wheelFrm, WRFlat);
451 WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
452 WMMoveWidget(panel->wheelFrm, 5, 80);
454 panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
455 /* XXX Can we create a view ? */
456 W_ResizeView(panel->wheelView, colorWheelSize + 4, colorWheelSize + 4);
457 W_MoveView(panel->wheelView, 0, 0);
459 /* Create an event handler to handle expose/click events in ColorWheel */
460 WMCreateEventHandler(panel->wheelView,
461 ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
462 LeaveWindowMask | ButtonMotionMask, wheelHandleActionEvents, panel);
464 WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents, panel);
466 panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
467 WMResizeWidget(panel->wheelBrightnessS, 16, 153);
468 WMMoveWidget(panel->wheelBrightnessS, 5 + colorWheelSize + 14, 1);
469 WMSetSliderMinValue(panel->wheelBrightnessS, 0);
470 WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
471 WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback, panel);
472 WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
474 panel->wheelMtrx = wheelCreateMatrix(colorWheelSize + 4, colorWheelSize + 4);
475 wheelInitMatrix(panel);
477 /* Widgets for the Slider Panels */
478 panel->slidersFrm = WMCreateFrame(panel->win);
479 WMSetFrameRelief(panel->slidersFrm, WRFlat);
480 WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
481 WMMoveWidget(panel->slidersFrm, 4, 80);
483 panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
484 WMSetFrameRelief(panel->seperatorFrm, WRPushed);
485 WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
486 WMMoveWidget(panel->seperatorFrm, 0, 1);
488 panel->grayBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
489 WMResizeWidget(panel->grayBtn, 46, 24);
490 WMMoveWidget(panel->grayBtn, 1, 8);
491 WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
492 WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
493 WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
495 panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
496 WMResizeWidget(panel->rgbBtn, 46, 24);
497 WMMoveWidget(panel->rgbBtn, 47, 8);
498 WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
499 WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
500 WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
502 panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
503 WMResizeWidget(panel->cmykBtn, 46, 24);
504 WMMoveWidget(panel->cmykBtn, 93, 8);
505 WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
506 WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
507 WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
509 panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
510 WMResizeWidget(panel->hsbBtn, 46, 24);
511 WMMoveWidget(panel->hsbBtn, 139, 8);
512 WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
513 WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
514 WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
516 /* Let's Group the Slider Panel Buttons Together */
517 WMGroupButtons(panel->grayBtn, panel->rgbBtn);
518 WMGroupButtons(panel->grayBtn, panel->cmykBtn);
519 WMGroupButtons(panel->grayBtn, panel->hsbBtn);
521 textcolor = WMDarkGrayColor(scrPtr);
523 /* Widgets for GrayScale Panel */
524 panel->grayFrm = WMCreateFrame(panel->slidersFrm);
525 WMSetFrameRelief(panel->grayFrm, WRFlat);
526 WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
527 WMMoveWidget(panel->grayFrm, 0, 34);
529 panel->grayMinL = WMCreateLabel(panel->grayFrm);
530 WMResizeWidget(panel->grayMinL, 20, 10);
531 WMMoveWidget(panel->grayMinL, 2, 2);
532 WMSetLabelText(panel->grayMinL, "0");
533 WMSetLabelTextAlignment(panel->grayMinL, WALeft);
534 WMSetLabelTextColor(panel->grayMinL, textcolor);
535 WMSetLabelFont(panel->grayMinL, panel->font8);
537 panel->grayMaxL = WMCreateLabel(panel->grayFrm);
538 WMResizeWidget(panel->grayMaxL, 40, 10);
539 WMMoveWidget(panel->grayMaxL, 104, 2);
540 WMSetLabelText(panel->grayMaxL, "100");
541 WMSetLabelTextAlignment(panel->grayMaxL, WARight);
542 WMSetLabelTextColor(panel->grayMaxL, textcolor);
543 WMSetLabelFont(panel->grayMaxL, panel->font8);
545 panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
546 WMResizeWidget(panel->grayBrightnessS, 141, 16);
547 WMMoveWidget(panel->grayBrightnessS, 2, 14);
548 WMSetSliderMinValue(panel->grayBrightnessS, 0);
549 WMSetSliderMaxValue(panel->grayBrightnessS, 100);
550 WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
551 WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback, panel);
553 from.red = 0;
554 from.green = 0;
555 from.blue = 0;
557 to.red = 255;
558 to.green = 255;
559 to.blue = 255;
561 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
562 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
563 RReleaseImage(image);
565 if (pixmap)
566 W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap,
567 panel->font12, 2, 0, 100, WALeft, scrPtr->white,
568 False, _("Brightness"), strlen(_("Brightness")));
569 else
570 wwarning(_("Color Panel: Could not allocate memory"));
572 WMSetSliderImage(panel->grayBrightnessS, pixmap);
573 WMReleasePixmap(pixmap);
575 panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
576 WMResizeWidget(panel->grayBrightnessT, 40, 18);
577 WMMoveWidget(panel->grayBrightnessT, 146, 13);
578 WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
579 WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel,
580 WMTextDidEndEditingNotification, panel->grayBrightnessT);
582 for (i = 0; i < 7; i++) {
583 pixmap = WMCreatePixmap(scrPtr, 13, 13, scrPtr->depth, False);
585 graybuttoncolor = WMCreateRGBColor(scrPtr, (255 / 6) * i << 8,
586 (255 / 6) * i << 8, (255 / 6) * i << 8, True);
587 WMPaintColorSwatch(graybuttoncolor, pixmap->pixmap, 0, 0, 15, 15);
588 WMReleaseColor(graybuttoncolor);
590 panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
591 WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
592 WMMoveWidget(panel->grayPresetBtn[i], 2 + (i * 20), 34);
593 WMSetButtonAction(panel->grayPresetBtn[i], grayPresetButtonCallback, panel);
594 WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
595 WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
596 WMReleasePixmap(pixmap);
600 /* End of GrayScale Panel */
602 /* Widgets for RGB Panel */
603 panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
604 WMSetFrameRelief(panel->rgbFrm, WRFlat);
605 WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
606 WMMoveWidget(panel->rgbFrm, 0, 34);
608 panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
609 WMResizeWidget(panel->rgbMinL, 20, 10);
610 WMMoveWidget(panel->rgbMinL, 2, 2);
611 WMSetLabelText(panel->rgbMinL, "0");
612 WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
613 WMSetLabelTextColor(panel->rgbMinL, textcolor);
614 WMSetLabelFont(panel->rgbMinL, panel->font8);
616 panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
617 WMResizeWidget(panel->rgbMaxL, 40, 10);
618 WMMoveWidget(panel->rgbMaxL, 104, 2);
619 WMSetLabelText(panel->rgbMaxL, "255");
620 WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
621 WMSetLabelTextColor(panel->rgbMaxL, textcolor);
622 WMSetLabelFont(panel->rgbMaxL, panel->font8);
624 panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
625 WMResizeWidget(panel->rgbRedS, 141, 16);
626 WMMoveWidget(panel->rgbRedS, 2, 14);
627 WMSetSliderMinValue(panel->rgbRedS, 0);
628 WMSetSliderMaxValue(panel->rgbRedS, 255);
629 WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
630 WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
632 to.red = 255;
633 to.green = 0;
634 to.blue = 0;
636 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
637 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
638 RReleaseImage(image);
640 if (pixmap)
641 W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12,
642 2, 0, 100, WALeft, scrPtr->white, False, _("Red"), strlen(_("Red")));
643 else
644 wwarning(_("Color Panel: Could not allocate memory"));
646 WMSetSliderImage(panel->rgbRedS, pixmap);
647 WMReleasePixmap(pixmap);
649 panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
650 WMResizeWidget(panel->rgbRedT, 40, 18);
651 WMMoveWidget(panel->rgbRedT, 146, 13);
652 WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
653 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbRedT);
655 panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
656 WMResizeWidget(panel->rgbGreenS, 141, 16);
657 WMMoveWidget(panel->rgbGreenS, 2, 36);
658 WMSetSliderMinValue(panel->rgbGreenS, 0);
659 WMSetSliderMaxValue(panel->rgbGreenS, 255);
660 WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
661 WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
663 to.red = 0;
664 to.green = 255;
665 to.blue = 0;
667 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
668 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
669 RReleaseImage(image);
671 if (pixmap)
672 W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12,
673 2, 0, 100, WALeft, scrPtr->white, False, _("Green"), strlen(_("Green")));
674 else
675 wwarning(_("Color Panel: Could not allocate memory"));
677 WMSetSliderImage(panel->rgbGreenS, pixmap);
678 WMReleasePixmap(pixmap);
680 panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
681 WMResizeWidget(panel->rgbGreenT, 40, 18);
682 WMMoveWidget(panel->rgbGreenT, 146, 35);
683 WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
684 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbGreenT);
686 panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
687 WMResizeWidget(panel->rgbBlueS, 141, 16);
688 WMMoveWidget(panel->rgbBlueS, 2, 58);
689 WMSetSliderMinValue(panel->rgbBlueS, 0);
690 WMSetSliderMaxValue(panel->rgbBlueS, 255);
691 WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
692 WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
694 to.red = 0;
695 to.green = 0;
696 to.blue = 255;
698 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
699 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
700 RReleaseImage(image);
702 if (pixmap)
703 W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12,
704 2, 0, 100, WALeft, scrPtr->white, False, _("Blue"), strlen(_("Blue")));
705 else
706 wwarning(_("Color Panel: Could not allocate memory"));
708 WMSetSliderImage(panel->rgbBlueS, pixmap);
709 WMReleasePixmap(pixmap);
711 panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
712 WMResizeWidget(panel->rgbBlueT, 40, 18);
713 WMMoveWidget(panel->rgbBlueT, 146, 57);
714 WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
715 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbBlueT);
717 panel->rgbDecB = WMCreateButton(panel->rgbFrm, WBTRadio);
718 WMSetButtonText(panel->rgbDecB, _("Decimal"));
719 WMSetButtonSelected(panel->rgbDecB, 1);
720 panel->rgbState = RGBdec;
721 WMSetButtonAction(panel->rgbDecB, rgbDecToHex, panel);
722 WMResizeWidget(panel->rgbDecB, PWIDTH - 8, 23);
723 WMMoveWidget(panel->rgbDecB, 2, 81);
725 panel->rgbHexB = WMCreateButton(panel->rgbFrm, WBTRadio);
726 WMSetButtonText(panel->rgbHexB, _("Hexadecimal"));
727 WMSetButtonAction(panel->rgbHexB, rgbDecToHex, panel);
728 WMResizeWidget(panel->rgbHexB, PWIDTH - 8, 23);
729 WMMoveWidget(panel->rgbHexB, 2, 104);
731 WMGroupButtons(panel->rgbDecB, panel->rgbHexB);
733 /* End of RGB Panel */
735 /* Widgets for CMYK Panel */
736 panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
737 WMSetFrameRelief(panel->cmykFrm, WRFlat);
738 WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
739 WMMoveWidget(panel->cmykFrm, 0, 34);
741 panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
742 WMResizeWidget(panel->cmykMinL, 20, 10);
743 WMMoveWidget(panel->cmykMinL, 2, 2);
744 WMSetLabelText(panel->cmykMinL, "0");
745 WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
746 WMSetLabelTextColor(panel->cmykMinL, textcolor);
747 WMSetLabelFont(panel->cmykMinL, panel->font8);
749 panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
750 WMResizeWidget(panel->cmykMaxL, 40, 10);
751 WMMoveWidget(panel->cmykMaxL, 104, 2);
752 WMSetLabelText(panel->cmykMaxL, "100");
753 WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
754 WMSetLabelTextColor(panel->cmykMaxL, textcolor);
755 WMSetLabelFont(panel->cmykMaxL, panel->font8);
757 panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
758 WMResizeWidget(panel->cmykCyanS, 141, 16);
759 WMMoveWidget(panel->cmykCyanS, 2, 14);
760 WMSetSliderMinValue(panel->cmykCyanS, 0);
761 WMSetSliderMaxValue(panel->cmykCyanS, 100);
762 WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
763 WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
765 from.red = 255;
766 from.green = 255;
767 from.blue = 255;
769 to.red = 0;
770 to.green = 255;
771 to.blue = 255;
773 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
774 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
775 RReleaseImage(image);
777 if (pixmap)
778 W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12,
779 2, 0, 100, WALeft, scrPtr->black, False, _("Cyan"), strlen(_("Cyan")));
780 else
781 wwarning(_("Color Panel: Could not allocate memory"));
783 WMSetSliderImage(panel->cmykCyanS, pixmap);
784 WMReleasePixmap(pixmap);
786 panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
787 WMResizeWidget(panel->cmykCyanT, 40, 18);
788 WMMoveWidget(panel->cmykCyanT, 146, 13);
789 WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
790 WMAddNotificationObserver(cmykTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->cmykCyanT);
792 panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
793 WMResizeWidget(panel->cmykMagentaS, 141, 16);
794 WMMoveWidget(panel->cmykMagentaS, 2, 36);
795 WMSetSliderMinValue(panel->cmykMagentaS, 0);
796 WMSetSliderMaxValue(panel->cmykMagentaS, 100);
797 WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
798 WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
800 to.red = 255;
801 to.green = 0;
802 to.blue = 255;
804 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
805 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
806 RReleaseImage(image);
808 if (pixmap)
809 W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12,
810 2, 0, 100, WALeft, scrPtr->black, False, _("Magenta"), strlen(_("Magenta")));
811 else
812 wwarning(_("Color Panel: Could not allocate memory"));
814 WMSetSliderImage(panel->cmykMagentaS, pixmap);
815 WMReleasePixmap(pixmap);
817 panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
818 WMResizeWidget(panel->cmykMagentaT, 40, 18);
819 WMMoveWidget(panel->cmykMagentaT, 146, 35);
820 WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
821 WMAddNotificationObserver(cmykTextFieldCallback, panel,
822 WMTextDidEndEditingNotification, panel->cmykMagentaT);
824 panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
825 WMResizeWidget(panel->cmykYellowS, 141, 16);
826 WMMoveWidget(panel->cmykYellowS, 2, 58);
827 WMSetSliderMinValue(panel->cmykYellowS, 0);
828 WMSetSliderMaxValue(panel->cmykYellowS, 100);
829 WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
830 WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
832 to.red = 255;
833 to.green = 255;
834 to.blue = 0;
836 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
837 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
838 RReleaseImage(image);
840 if (pixmap)
841 W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12,
842 2, 0, 100, WALeft, scrPtr->black, False, _("Yellow"), strlen(_("Yellow")));
843 else
844 wwarning(_("Color Panel: Could not allocate memory"));
846 WMSetSliderImage(panel->cmykYellowS, pixmap);
847 WMReleasePixmap(pixmap);
849 panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
850 WMResizeWidget(panel->cmykYellowT, 40, 18);
851 WMMoveWidget(panel->cmykYellowT, 146, 57);
852 WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
853 WMAddNotificationObserver(cmykTextFieldCallback, panel,
854 WMTextDidEndEditingNotification, panel->cmykYellowT);
856 panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
857 WMResizeWidget(panel->cmykBlackS, 141, 16);
858 WMMoveWidget(panel->cmykBlackS, 2, 80);
859 WMSetSliderMinValue(panel->cmykBlackS, 0);
860 WMSetSliderMaxValue(panel->cmykBlackS, 100);
861 WMSetSliderValue(panel->cmykBlackS, 0);
862 WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
863 WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
865 to.red = 0;
866 to.green = 0;
867 to.blue = 0;
869 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
870 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
871 RReleaseImage(image);
873 if (pixmap)
874 W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12,
875 2, 0, 100, WALeft, scrPtr->black, False, _("Black"), strlen(_("Black")));
876 else
877 wwarning(_("Color Panel: Could not allocate memory"));
879 WMSetSliderImage(panel->cmykBlackS, pixmap);
880 WMReleasePixmap(pixmap);
882 panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
883 WMResizeWidget(panel->cmykBlackT, 40, 18);
884 WMMoveWidget(panel->cmykBlackT, 146, 79);
885 WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
886 WMAddNotificationObserver(cmykTextFieldCallback, panel,
887 WMTextDidEndEditingNotification, panel->cmykBlackT);
888 /* End of CMYK Panel */
890 /* Widgets for HSB Panel */
891 panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
892 WMSetFrameRelief(panel->hsbFrm, WRFlat);
893 WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
894 WMMoveWidget(panel->hsbFrm, 0, 34);
896 panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
897 WMResizeWidget(panel->hsbHueS, 141, 16);
898 WMMoveWidget(panel->hsbHueS, 2, 14);
899 WMSetSliderMinValue(panel->hsbHueS, 0);
900 WMSetSliderMaxValue(panel->hsbHueS, 359);
901 WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
902 WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
904 panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
905 WMResizeWidget(panel->hsbHueT, 40, 18);
906 WMMoveWidget(panel->hsbHueT, 146, 13);
907 WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
908 WMAddNotificationObserver(hsbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->hsbHueT);
910 panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
911 WMResizeWidget(panel->hsbSaturationS, 141, 16);
912 WMMoveWidget(panel->hsbSaturationS, 2, 36);
913 WMSetSliderMinValue(panel->hsbSaturationS, 0);
914 WMSetSliderMaxValue(panel->hsbSaturationS, 100);
915 WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
916 WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
918 panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
919 WMResizeWidget(panel->hsbSaturationT, 40, 18);
920 WMMoveWidget(panel->hsbSaturationT, 146, 35);
921 WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
922 WMAddNotificationObserver(hsbTextFieldCallback, panel,
923 WMTextDidEndEditingNotification, panel->hsbSaturationT);
925 panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
926 WMResizeWidget(panel->hsbBrightnessS, 141, 16);
927 WMMoveWidget(panel->hsbBrightnessS, 2, 58);
928 WMSetSliderMinValue(panel->hsbBrightnessS, 0);
929 WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
930 WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
931 WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
933 panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
934 WMResizeWidget(panel->hsbBrightnessT, 40, 18);
935 WMMoveWidget(panel->hsbBrightnessT, 146, 57);
936 WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
937 WMAddNotificationObserver(hsbTextFieldCallback, panel,
938 WMTextDidEndEditingNotification, panel->hsbBrightnessT);
939 /* End of HSB Panel */
941 WMReleaseColor(textcolor);
943 /* Widgets for the CustomPalette Panel */
944 panel->customPaletteFrm = WMCreateFrame(panel->win);
945 WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
946 WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
947 WMMoveWidget(panel->customPaletteFrm, 5, 80);
949 panel->customPaletteHistoryBtn = WMCreatePopUpButton(panel->customPaletteFrm);
950 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, _("Spectrum"));
951 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
952 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1);
953 WMSetPopUpButtonAction(panel->customPaletteHistoryBtn, customPaletteHistoryCallback, panel);
954 WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
955 WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
957 panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
958 WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
959 WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
960 WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
962 panel->customPaletteContentView = W_CreateView(W_VIEW(panel->customPaletteContentFrm));
963 /* XXX Test if we can create a view */
964 W_ResizeView(panel->customPaletteContentView, customPaletteWidth, customPaletteHeight);
965 W_MoveView(panel->customPaletteContentView, 2, 2);
967 /* Create event handler to handle expose/click events in CustomPalette */
968 WMCreateEventHandler(panel->customPaletteContentView,
969 ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
970 ButtonMotionMask, customPaletteHandleActionEvents, panel);
972 WMCreateEventHandler(panel->customPaletteContentView, ExposureMask, customPaletteHandleEvents, panel);
974 panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
975 WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
976 WMSetPopUpButtonText(panel->customPaletteMenuBtn, _("Palette"));
977 WMSetPopUpButtonAction(panel->customPaletteMenuBtn, customPaletteMenuCallback, panel);
978 WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
979 WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
981 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from File..."));
982 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Rename..."));
983 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Remove"));
984 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Copy"));
985 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from Clipboard"));
987 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, 0);
988 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, 0);
989 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuCopy, 0);
990 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuNewFromClipboard, 0);
992 customRenderSpectrum(panel);
993 panel->currentPalette = 0;
994 panel->palx = customPaletteWidth / 2;
995 panel->paly = customPaletteHeight / 2;
997 /* Widgets for the ColorList Panel */
998 panel->colorListFrm = WMCreateFrame(panel->win);
999 WMSetFrameRelief(panel->colorListFrm, WRFlat);
1000 WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
1001 WMMoveWidget(panel->colorListFrm, 5, 80);
1003 panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
1004 WMAddPopUpButtonItem(panel->colorListHistoryBtn, _("X11-Colors"));
1005 WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn,
1006 WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn) - 1);
1007 /* WMSetPopUpButtonAction(panel->colorListHistoryBtn,
1008 * colorListHistoryCallback, panel); */
1009 WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
1010 WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
1012 panel->colorListContentLst = WMCreateList(panel->colorListFrm);
1013 WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
1014 WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
1015 WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
1016 WMMoveWidget(panel->colorListContentLst, 0, 23);
1017 WMHangData(panel->colorListContentLst, panel);
1019 panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1020 WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
1021 WMSetPopUpButtonText(panel->colorListColorMenuBtn, _("Color"));
1022 WMSetPopUpButtonAction(panel->colorListColorMenuBtn, colorListColorMenuCallback, panel);
1023 WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16) / 2, 20);
1024 WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
1026 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Add..."));
1027 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Rename..."));
1028 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Remove"));
1030 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuAdd, 0);
1031 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRename, 0);
1032 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRemove, 0);
1034 panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1035 WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
1036 WMSetPopUpButtonText(panel->colorListListMenuBtn, _("List"));
1037 WMSetPopUpButtonAction(panel->colorListListMenuBtn, colorListListMenuCallback, panel);
1038 WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2, 20);
1039 WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2 + 8, PHEIGHT - 130);
1041 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("New..."));
1042 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Rename..."));
1043 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Remove"));
1045 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuAdd, 0);
1046 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
1047 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
1049 WMRealizeWidget(panel->win);
1050 WMMapSubwidgets(panel->win);
1052 WMMapSubwidgets(panel->wheelFrm);
1053 WMMapSubwidgets(panel->slidersFrm);
1054 WMMapSubwidgets(panel->grayFrm);
1055 WMMapSubwidgets(panel->rgbFrm);
1056 WMMapSubwidgets(panel->cmykFrm);
1057 WMMapSubwidgets(panel->hsbFrm);
1058 WMMapSubwidgets(panel->customPaletteFrm);
1059 WMMapSubwidgets(panel->customPaletteContentFrm);
1060 WMMapSubwidgets(panel->colorListFrm);
1062 /* Pixmap to indicate selection positions
1063 * wheelframe MUST be mapped.
1065 panel->selectionImg = XCreatePixmap(scrPtr->display, WMWidgetXID(panel->win), 4, 4, scrPtr->depth);
1066 XFillRectangle(scrPtr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1067 XFillRectangle(scrPtr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1069 readConfiguration(panel);
1070 readXColors(panel);
1072 return panel;
1075 WMColorPanel *WMGetColorPanel(WMScreen * scrPtr)
1077 WMColorPanel *panel;
1079 if (scrPtr->sharedColorPanel)
1080 return scrPtr->sharedColorPanel;
1082 panel = makeColorPanel(scrPtr, "colorPanel");
1084 scrPtr->sharedColorPanel = panel;
1086 return panel;
1089 void WMFreeColorPanel(WMColorPanel * panel)
1091 W_Screen *scr;
1093 if (!panel)
1094 return;
1096 scr = WMWidgetScreen(panel->win);
1097 if (panel == scr->sharedColorPanel) {
1098 scr->sharedColorPanel = NULL;
1101 WMRemoveNotificationObserver(panel);
1102 WMUnmapWidget(panel->win);
1104 /* fonts */
1105 WMReleaseFont(panel->font8);
1106 WMReleaseFont(panel->font12);
1108 /* pixmaps */
1109 wheelDestroyMatrix(panel->wheelMtrx);
1110 if (panel->wheelImg)
1111 XFreePixmap(scr->display, panel->wheelImg);
1112 if (panel->selectionImg)
1113 XFreePixmap(scr->display, panel->selectionImg);
1114 if (panel->selectionBackImg)
1115 XFreePixmap(scr->display, panel->selectionBackImg);
1116 RReleaseImage(panel->customPaletteImg);
1118 /* structs */
1119 if (panel->lastBrowseDir)
1120 wfree(panel->lastBrowseDir);
1121 if (panel->configurationPath)
1122 wfree(panel->configurationPath);
1124 WMDestroyWidget(panel->win);
1126 wfree(panel);
1129 void WMCloseColorPanel(WMColorPanel * panel)
1131 WMFreeColorPanel(panel);
1134 void WMShowColorPanel(WMColorPanel * panel)
1136 WMScreen *scr = WMWidgetScreen(panel->win);
1137 WMColor *white = WMWhiteColor(scr);
1139 if (panel->color.set == cpNone)
1140 WMSetColorPanelColor(panel, white);
1141 WMReleaseColor(white);
1143 if (panel->mode != WMWheelModeColorPanel)
1144 WMPerformButtonClick(panel->wheelBtn);
1146 WMMapWidget(panel->win);
1149 static void closeWindowCallback(WMWidget * w, void *data)
1151 W_ColorPanel *panel = (W_ColorPanel *) data;
1153 /* Parameter not used, but tell the compiler that it is ok */
1154 (void) w;
1156 WMCloseColorPanel(panel);
1159 static void readConfiguration(W_ColorPanel * panel)
1161 /* XXX Doesn't take care of "invalid" files */
1163 DIR *dPtr;
1164 struct dirent *dp;
1165 struct stat stat_buf;
1166 int item;
1168 if (stat(panel->configurationPath, &stat_buf) != 0) {
1169 if (mkdir(panel->configurationPath, S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH) != 0) {
1170 werror(_("Color Panel: Could not create directory %s needed"
1171 " to store configurations"), panel->configurationPath);
1172 WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
1173 WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
1174 WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
1175 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1176 _("File Error"),
1177 _("Could not create ColorPanel configuration directory"),
1178 _("OK"), NULL, NULL);
1180 return;
1183 if (!(dPtr = opendir(panel->configurationPath))) {
1184 wwarning("%s: %s", _("Color Panel: Could not find file"), panel->configurationPath);
1185 return;
1188 while ((dp = readdir(dPtr)) != NULL) {
1189 unsigned int perm_mask;
1190 char *path = wstrconcat(panel->configurationPath,
1191 dp->d_name);
1193 if (dp->d_name[0] != '.') {
1194 item = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
1195 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
1197 perm_mask = (access(path, R_OK) == 0);
1198 WMSetPopUpButtonItemEnabled(panel->customPaletteHistoryBtn, item, perm_mask);
1200 wfree(path);
1202 closedir(dPtr);
1205 static void readXColors(W_ColorPanel * panel)
1207 WMListItem *item;
1208 const RGBColor *entry;
1210 for (entry = rgbColors; entry->name != NULL; entry++) {
1211 item = WMAddListItem(panel->colorListContentLst, entry->name);
1212 item->clientData = (void *)&(entry->color);
1216 void WMSetColorPanelPickerMode(WMColorPanel * panel, WMColorPanelMode mode)
1218 W_Screen *scr = WMWidgetScreen(panel->win);
1220 if (mode != WMWheelModeColorPanel) {
1221 WMUnmapWidget(panel->wheelFrm);
1222 if (panel->selectionBackImg) {
1223 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1224 panel->selectionBackImg = None;
1227 if (mode != WMGrayModeColorPanel)
1228 WMUnmapWidget(panel->grayFrm);
1229 if (mode != WMRGBModeColorPanel)
1230 WMUnmapWidget(panel->rgbFrm);
1231 if (mode != WMCMYKModeColorPanel)
1232 WMUnmapWidget(panel->cmykFrm);
1233 if (mode != WMHSBModeColorPanel)
1234 WMUnmapWidget(panel->hsbFrm);
1235 if (mode != WMCustomPaletteModeColorPanel) {
1236 WMUnmapWidget(panel->customPaletteFrm);
1237 if (panel->selectionBackImg) {
1238 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1239 panel->selectionBackImg = None;
1242 if (mode != WMColorListModeColorPanel)
1243 WMUnmapWidget(panel->colorListFrm);
1244 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
1245 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1246 WMUnmapWidget(panel->slidersFrm);
1247 else
1248 panel->slidersmode = mode;
1250 if (mode == WMWheelModeColorPanel) {
1251 WMMapWidget(panel->wheelFrm);
1252 WMSetButtonSelected(panel->wheelBtn, True);
1253 if (panel->lastChanged != WMWheelModeColorPanel)
1254 wheelInit(panel);
1255 wheelRender(panel);
1256 wheelPaint(panel);
1257 } else if (mode == WMGrayModeColorPanel) {
1258 WMMapWidget(panel->slidersFrm);
1259 WMSetButtonSelected(panel->slidersBtn, True);
1260 WMMapWidget(panel->grayFrm);
1261 WMSetButtonSelected(panel->grayBtn, True);
1262 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1263 if (panel->lastChanged != WMGrayModeColorPanel)
1264 grayInit(panel);
1265 } else if (mode == WMRGBModeColorPanel) {
1266 WMMapWidget(panel->slidersFrm);
1267 WMSetButtonSelected(panel->slidersBtn, True);
1268 WMMapWidget(panel->rgbFrm);
1269 WMSetButtonSelected(panel->rgbBtn, True);
1270 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1271 if (panel->lastChanged != WMRGBModeColorPanel)
1272 rgbInit(panel);
1273 } else if (mode == WMCMYKModeColorPanel) {
1274 WMMapWidget(panel->slidersFrm);
1275 WMSetButtonSelected(panel->slidersBtn, True);
1276 WMMapWidget(panel->cmykFrm);
1277 WMSetButtonSelected(panel->cmykBtn, True);
1278 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1279 if (panel->lastChanged != WMCMYKModeColorPanel)
1280 cmykInit(panel);
1281 } else if (mode == WMHSBModeColorPanel) {
1282 WMMapWidget(panel->slidersFrm);
1283 WMSetButtonSelected(panel->slidersBtn, True);
1284 WMMapWidget(panel->hsbFrm);
1285 WMSetButtonSelected(panel->hsbBtn, True);
1286 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1287 if (panel->lastChanged != WMHSBModeColorPanel)
1288 hsbInit(panel);
1289 } else if (mode == WMCustomPaletteModeColorPanel) {
1290 WMMapWidget(panel->customPaletteFrm);
1291 WMSetButtonSelected(panel->customPaletteBtn, True);
1292 customSetPalette(panel);
1293 } else if (mode == WMColorListModeColorPanel) {
1294 WMMapWidget(panel->colorListFrm);
1295 WMSetButtonSelected(panel->colorListBtn, True);
1298 panel->mode = mode;
1301 WMColor *WMGetColorPanelColor(WMColorPanel * panel)
1303 return WMGetColorWellColor(panel->colorWell);
1306 void WMSetColorPanelColor(WMColorPanel * panel, WMColor * color)
1308 WMSetColorWellColor(panel->colorWell, color);
1310 panel->color.rgb.red = color->color.red >> 8;
1311 panel->color.rgb.green = color->color.green >> 8;
1312 panel->color.rgb.blue = color->color.blue >> 8;
1313 panel->color.set = cpRGB;
1315 if (panel->mode == panel->lastChanged)
1316 panel->lastChanged = 0;
1318 WMSetColorPanelPickerMode(panel, panel->mode);
1321 static void updateSwatch(WMColorPanel * panel, CPColor color)
1323 WMScreen *scr = WMWidgetScreen(panel->win);
1324 WMColor *wellcolor;
1326 if (color.set != cpRGB)
1327 convertCPColor(&color);
1329 panel->color = color;
1331 wellcolor = WMCreateRGBColor(scr, color.rgb.red << 8, color.rgb.green << 8, color.rgb.blue << 8, True);
1333 WMSetColorWellColor(panel->colorWell, wellcolor);
1334 WMReleaseColor(wellcolor);
1336 if (!panel->flags.dragging || panel->flags.continuous) {
1337 if (panel->action)
1338 (*panel->action) (panel, panel->clientData);
1340 WMPostNotificationName(WMColorPanelColorChangedNotification, panel, NULL);
1344 static void modeButtonCallback(WMWidget * w, void *data)
1346 W_ColorPanel *panel = (W_ColorPanel *) (data);
1348 if (w == panel->wheelBtn)
1349 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1350 else if (w == panel->slidersBtn)
1351 WMSetColorPanelPickerMode(panel, panel->slidersmode);
1352 else if (w == panel->customPaletteBtn)
1353 WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
1354 else if (w == panel->colorListBtn)
1355 WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
1356 else if (w == panel->grayBtn)
1357 WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
1358 else if (w == panel->rgbBtn)
1359 WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
1360 else if (w == panel->cmykBtn)
1361 WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
1362 else if (w == panel->hsbBtn)
1363 WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
1366 /****************** Magnifying Cursor Functions *******************/
1368 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h)
1370 int x0 = 0, y0 = 0, w0 = w, h0 = h;
1371 const int displayWidth = DisplayWidth(scr->display, scr->screen),
1372 displayHeight = DisplayHeight(scr->display, scr->screen);
1374 if (!(image && image->data)) {
1375 /* The image in panel->magnifyGlass->image does not exist yet.
1376 * Grab one from the screen (not beyond) and use it from now on.
1378 if (!(image = XGetImage(scr->display, scr->rootWin,
1379 x - Cursor_x_hot, y - Cursor_y_hot, w, h, AllPlanes, ZPixmap)))
1380 wwarning(_("Color Panel: X failed request"));
1382 return image;
1385 /* Coordinate correction for back pixmap
1386 * if magnifying glass is at screen-borders
1389 /* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
1390 * Hatched area is beyond screen border.
1392 * |<-Cursor_x_hot->|
1393 * ________________|_____
1394 * |/ / / / / / /| | |
1395 * | / / / / / / |(x,y) |
1396 * |/_/_/_/_/_/_/|________|
1397 * |<----x0----->|<--w0-->|
1401 /* Figure 2: Shifting of rectangle-to-grab at bottom/right
1402 * screen borders
1403 * Hatched area is beyond screen border
1405 * |<-Cursor_x_hot->|
1406 * ________________|_______________
1407 * | | | / / / / / /|
1408 * | (x,y)|/ / / / / / |
1409 * |___________________|_/_/_/_/_/_/|
1410 * |<-------w0-------->| |
1411 * |<---------------w--|----------->|
1412 * | |
1413 * x0 Displaywidth-1
1416 if (x < Cursor_x_hot) { /* see fig. 1 */
1417 x0 = Cursor_x_hot - x;
1418 w0 = w - x0;
1421 if (displayWidth - 1 < x - Cursor_x_hot + w) { /* see fig. 2 */
1422 w0 = (displayWidth) - (x - Cursor_x_hot);
1425 if (y < Cursor_y_hot) { /* see fig. 1 */
1426 y0 = Cursor_y_hot - y;
1427 h0 = h - y0;
1430 if (displayHeight - 1 < y - Cursor_y_hot + h) { /* see fig. 2 */
1431 h0 = (displayHeight) - (y - Cursor_y_hot);
1433 /* end of coordinate correction */
1435 /* Grab an image from the screen, clipped if necessary,
1436 * and put it in the existing panel->magnifyGlass->image
1437 * with the corresponding clipping offset.
1439 if (!XGetSubImage(scr->display, scr->rootWin,
1440 x - Cursor_x_hot + x0, y - Cursor_y_hot + y0, w0, h0, AllPlanes, ZPixmap, image, x0, y0))
1441 wwarning(_("Color Panel: X failed request"));
1443 return NULL;
1446 static void magnifyGetImageStored(WMColorPanel * panel, int x1, int y1, int x2, int y2)
1448 /* (x1, y1) = topleft corner of existing rectangle
1449 * (x2, y2) = topleft corner of new position
1452 W_Screen *scr = WMWidgetScreen(panel->win);
1453 int xa = 0, ya = 0, xb = 0, yb = 0;
1454 int width, height;
1455 const int dx = abs(x2 - x1), dy = abs(y2 - y1);
1456 XImage *image;
1457 const int x_min = Cursor_x_hot,
1458 y_min = Cursor_y_hot,
1459 x_max = DisplayWidth(scr->display, scr->screen) - 1 -
1460 (Cursor_mask_width - Cursor_x_hot),
1461 y_max = DisplayHeight(scr->display, scr->screen) - 1 - (Cursor_mask_height - Cursor_y_hot);
1463 if ((dx == 0) && (dy == 0) && panel->magnifyGlass->image)
1464 return; /* No movement */
1466 if (x1 < x2)
1467 xa = dx;
1468 else
1469 xb = dx;
1471 if (y1 < y2)
1472 ya = dy;
1473 else
1474 yb = dy;
1476 width = Cursor_mask_width - dx;
1477 height = Cursor_mask_height - dy;
1479 /* If the traversed distance is larger than the size of the magnifying
1480 * glass contents, there is no need to do dirty rectangles. A whole new
1481 * rectangle can be grabbed (unless that rectangle falls partially
1482 * off screen).
1483 * Destroying the image and setting it to NULL will achieve that later on.
1485 * Of course, grabbing an XImage beyond the borders of the screen will
1486 * cause trouble, this is considdered a special case. Part of the screen
1487 * is grabbed, but there is no need for dirty rectangles.
1489 if ((width <= 0) || (height <= 0)) {
1490 if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
1491 if (panel->magnifyGlass->image)
1492 XDestroyImage(panel->magnifyGlass->image);
1493 panel->magnifyGlass->image = NULL;
1495 } else {
1496 if (panel->magnifyGlass->image) {
1497 /* Get dirty rectangle from panel->magnifyGlass->image */
1498 panel->magnifyGlass->dirtyRect =
1499 XSubImage(panel->magnifyGlass->image, xa, ya, width, height);
1500 if (!panel->magnifyGlass->dirtyRect) {
1501 wwarning(_("Color Panel: X failed request"));
1502 return; /* X returned a NULL from XSubImage */
1507 /* Get image from screen */
1508 image = magnifyGetImage(scr, panel->magnifyGlass->image, x2, y2, Cursor_mask_width, Cursor_mask_height);
1509 if (image) { /* Only reassign if a *new* image was grabbed */
1510 panel->magnifyGlass->image = image;
1511 return;
1514 /* Copy previously stored rectangle on covered part of image */
1515 if (panel->magnifyGlass->image && panel->magnifyGlass->dirtyRect) {
1516 int old_height;
1518 /* "width" and "height" are used as coordinates here,
1519 * and run from [0...width-1] and [0...height-1] respectively.
1521 width--;
1522 height--;
1523 old_height = height;
1525 for (; width >= 0; width--)
1526 for (height = old_height; height >= 0; height--)
1527 XPutPixel(panel->magnifyGlass->image, xb + width, yb + height,
1528 XGetPixel(panel->magnifyGlass->dirtyRect, width, height));
1529 XDestroyImage(panel->magnifyGlass->dirtyRect);
1530 panel->magnifyGlass->dirtyRect = NULL;
1533 return;
1536 static Pixmap magnifyCreatePixmap(WMColorPanel * panel)
1538 W_Screen *scr = WMWidgetScreen(panel->win);
1539 int u, v;
1540 #ifndef USE_XSHAPE
1541 Pixmap pixmap;
1542 #endif
1543 unsigned long color;
1545 if (!panel->magnifyGlass->image)
1546 return None;
1548 if (!panel->magnifyGlass->magPix)
1549 return None;
1552 * Copy an area of only 5x5 pixels from the center of the image.
1554 for (u = 0; u < 5; u++) {
1555 for (v = 0; v < 5; v++) {
1556 color = XGetPixel(panel->magnifyGlass->image, u + 9, v + 9);
1558 XSetForeground(scr->display, scr->copyGC, color);
1560 if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
1561 panel->magnifyGlass->color = ulongToRColor(scr, color);
1563 /* The center square must eventually be centered around the
1564 * hotspot. The image needs shifting to achieve this. The amount of
1565 * shifting is (Cursor_mask_width/2 - 2 * square_size) = 11-10 = 1
1566 * _ _ _ _ _
1567 * |_|_|_|_|_|
1568 * ^------- center of center square == Cursor_x_hot
1570 XFillRectangle(scr->display, panel->magnifyGlass->magPix,
1571 scr->copyGC,
1572 u * 5 + (u == 0 ? 0 : -1), v * 5 + (v == 0 ? 0 : -1),
1573 (u == 0 ? 4 : 5), (v == 0 ? 4 : 5));
1577 #ifdef USE_XSHAPE
1578 return panel->magnifyGlass->magPix;
1579 #else
1580 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width, Cursor_mask_height, scr->depth);
1581 if (!pixmap)
1582 return None;
1584 XPutImage(scr->display, pixmap, scr->copyGC, panel->magnifyGlass->image,
1585 0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
1587 /* Copy the magnified pixmap, with the clip mask, to background pixmap */
1588 XCopyArea(scr->display, panel->magnifyGlass->magPix, pixmap,
1589 scr->clipGC, 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
1590 /* (2,2) puts center pixel on center of glass */
1592 return pixmap;
1593 #endif
1597 static WMView *magnifyCreateView(W_ColorPanel * panel)
1599 W_Screen *scr = WMWidgetScreen(panel->win);
1600 WMView *magView;
1602 magView = W_CreateTopView(scr);
1603 if (!magView)
1604 return NULL;
1606 magView->self = panel->win;
1607 magView->flags.topLevel = 1;
1608 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1609 magView->attribs.override_redirect = True;
1610 magView->attribs.save_under = True;
1612 W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
1614 W_RealizeView(magView);
1616 return magView;
1619 static Cursor magnifyGrabPointer(W_ColorPanel * panel)
1621 W_Screen *scr = WMWidgetScreen(panel->win);
1622 Pixmap magPixmap, magPixmap2;
1623 Cursor magCursor;
1624 XColor fgColor = { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 };
1625 XColor bgColor = { 0, 0xbf00, 0xa000, 0x5000, DoRed | DoGreen | DoBlue, 0 };
1627 /* Cursor creation stuff */
1628 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1629 (char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
1630 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1631 (char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
1633 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1634 &fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
1636 XFreePixmap(scr->display, magPixmap);
1637 XFreePixmap(scr->display, magPixmap2);
1639 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1641 /* Set up Pointer */
1642 XGrabPointer(scr->display, panel->magnifyGlass->view->window, True,
1643 PointerMotionMask | ButtonPressMask,
1644 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1646 return magCursor;
1649 static WMPoint magnifyInitialize(W_ColorPanel * panel)
1651 W_Screen *scr = WMWidgetScreen(panel->win);
1652 int x, y, u, v;
1653 unsigned int mask;
1654 Pixmap pixmap, clip_mask;
1655 WMPoint point;
1656 Window root_return, child_return;
1658 clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1659 (char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1660 1, 0, 1);
1661 panel->magnifyGlass->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
1662 5 * 5 - 1, 5 * 5 - 1, scr->depth);
1664 XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return, &x, &y, &u, &v, &mask);
1666 panel->magnifyGlass->image = NULL;
1668 /* Clipmask to make magnified view-contents circular */
1669 #ifdef USE_XSHAPE
1670 XShapeCombineMask(scr->display, WMViewXID(panel->magnifyGlass->view),
1671 ShapeBounding, 0, 0, clip_mask, ShapeSet);
1672 #else
1673 /* Clip circle in glass cursor */
1674 XSetClipMask(scr->display, scr->clipGC, clip_mask);
1675 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1676 #endif
1678 XFreePixmap(scr->display, clip_mask);
1680 /* Draw initial magnifying glass contents */
1681 magnifyGetImageStored(panel, x, y, x, y);
1683 pixmap = magnifyCreatePixmap(panel);
1684 XSetWindowBackgroundPixmap(scr->display, WMViewXID(panel->magnifyGlass->view), pixmap);
1685 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1686 XFlush(scr->display);
1688 #ifndef USE_XSHAPE
1689 XFreePixmap(scr->display, pixmap);
1690 #endif
1692 point.x = x;
1693 point.y = y;
1695 return point;
1698 static void magnifyPutCursor(WMWidget * w, void *data)
1700 W_ColorPanel *panel = (W_ColorPanel *) (data);
1701 W_Screen *scr = WMWidgetScreen(panel->win);
1702 Cursor magCursor;
1703 Pixmap pixmap;
1704 XEvent event;
1705 WMPoint initialPosition;
1707 /* Parameter not used, but tell the compiler that it is ok */
1708 (void) w;
1710 /* Destroy wheelBackImg, so it'll update properly */
1711 if (panel->selectionBackImg) {
1712 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1713 panel->selectionBackImg = None;
1716 /* Create magnifying glass */
1717 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1718 panel->magnifyGlass->view = magnifyCreateView(panel);
1719 if (!panel->magnifyGlass->view)
1720 return;
1722 initialPosition = magnifyInitialize(panel);
1723 panel->magnifyGlass->x = initialPosition.x;
1724 panel->magnifyGlass->y = initialPosition.y;
1726 W_MoveView(panel->magnifyGlass->view,
1727 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1728 W_MapView(panel->magnifyGlass->view);
1730 magCursor = magnifyGrabPointer(panel);
1732 while (panel->magnifyGlass->image) {
1733 WMNextEvent(scr->display, &event);
1735 /* Pack motion events */
1736 while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
1739 switch (event.type) {
1740 case ButtonPress:
1741 XDestroyImage(panel->magnifyGlass->image);
1742 panel->magnifyGlass->image = NULL;
1744 if (event.xbutton.button == Button1) {
1745 panel->color.rgb = panel->magnifyGlass->color;
1746 panel->color.set = cpRGB;
1747 updateSwatch(panel, panel->color);
1749 switch (panel->mode) {
1750 case WMWheelModeColorPanel:
1751 wheelInit(panel);
1752 wheelRender(panel);
1753 wheelPaint(panel);
1754 break;
1755 case WMGrayModeColorPanel:
1756 grayInit(panel);
1757 break;
1758 case WMRGBModeColorPanel:
1759 rgbInit(panel);
1760 break;
1761 case WMCMYKModeColorPanel:
1762 cmykInit(panel);
1763 break;
1764 case WMHSBModeColorPanel:
1765 hsbInit(panel);
1766 break;
1767 default:
1768 break;
1770 panel->lastChanged = panel->mode;
1772 WMSetButtonSelected(panel->magnifyBtn, False);
1773 break;
1775 case MotionNotify:
1776 while (XPending(event.xmotion.display)) {
1777 XEvent ev;
1778 XPeekEvent(event.xmotion.display, &ev);
1779 if (ev.type == MotionNotify)
1780 XNextEvent(event.xmotion.display, &event);
1781 else
1782 break;
1785 /* Get a "dirty rectangle" */
1786 magnifyGetImageStored(panel,
1787 panel->magnifyGlass->x, panel->magnifyGlass->y,
1788 event.xmotion.x_root, event.xmotion.y_root);
1790 /* Update coordinates */
1791 panel->magnifyGlass->x = event.xmotion.x_root;
1792 panel->magnifyGlass->y = event.xmotion.y_root;
1794 /* Move view */
1795 W_MoveView(panel->magnifyGlass->view,
1796 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1798 /* Put new image (with magn.) in view */
1799 pixmap = magnifyCreatePixmap(panel);
1800 if (pixmap != None) {
1801 /* Change the window background */
1802 XSetWindowBackgroundPixmap(scr->display,
1803 WMViewXID(panel->magnifyGlass->view), pixmap);
1804 /* Force an Expose (handled by X) */
1805 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1806 /* Synchronize the event queue, so the Expose is handled NOW */
1807 XFlush(scr->display);
1808 #ifndef USE_XSHAPE
1809 XFreePixmap(scr->display, pixmap);
1810 #endif
1812 break;
1814 /* Try XQueryPointer for this !!! It returns windows that the pointer
1815 * is over. Note: We found this solving the invisible donkey cap bug
1817 #if 0 /* As it is impossible to make this work in all cases,
1818 * we consider it confusing. Therefore we disabled it.
1820 case FocusOut: /* fall through */
1821 case FocusIn:
1823 * Color Panel window (panel->win) lost or received focus.
1824 * We need to update the pixmap in the magnifying glass.
1826 * BUG Doesn't work with focus switches between two windows
1827 * if none of them is the color panel.
1829 XUngrabPointer(scr->display, CurrentTime);
1830 W_UnmapView(panel->magnifyGlass->view);
1832 magnifyInitialize(panel);
1834 W_MapView(panel->magnifyGlass->view);
1835 XGrabPointer(scr->display, panel->magnifyGlass->view->window,
1836 True, PointerMotionMask | ButtonPressMask,
1837 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1838 break;
1839 #endif
1840 default:
1841 WMHandleEvent(&event);
1842 break;
1843 } /* of switch */
1846 XUngrabPointer(scr->display, CurrentTime);
1847 XFreeCursor(scr->display, magCursor);
1849 XFreePixmap(scr->display, panel->magnifyGlass->magPix);
1850 panel->magnifyGlass->magPix = None;
1852 W_UnmapView(panel->magnifyGlass->view);
1853 W_DestroyView(panel->magnifyGlass->view);
1854 panel->magnifyGlass->view = NULL;
1856 wfree(panel->magnifyGlass);
1859 /****************** ColorWheel Functions ************************/
1861 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height)
1863 wheelMatrix *matrix = NULL;
1864 int i;
1866 assert((width > 0) && (height > 0));
1868 matrix = wmalloc(sizeof(wheelMatrix));
1869 matrix->width = width;
1870 matrix->height = height;
1872 for (i = 0; i < 3; i++) {
1873 matrix->data[i] = wmalloc(width * height * sizeof(unsigned char));
1876 return matrix;
1879 static void wheelDestroyMatrix(wheelMatrix * matrix)
1881 int i;
1883 if (!matrix)
1884 return;
1886 for (i = 0; i < 3; i++) {
1887 if (matrix->data[i])
1888 wfree(matrix->data[i]);
1890 wfree(matrix);
1893 static void wheelInitMatrix(W_ColorPanel * panel)
1895 int i;
1896 int x, y;
1897 unsigned char *rp, *gp, *bp;
1898 CPColor cpColor;
1899 long ofs[4];
1900 int xcor, ycor;
1901 unsigned short sat;
1902 int dhue[4];
1903 const int cw_halfsize = (colorWheelSize + 4) / 2,
1904 cw_sqsize = (colorWheelSize + 4) * (colorWheelSize + 4), uchar_shift = getShift(sizeof(unsigned char));
1906 if (!panel->wheelMtrx)
1907 return;
1909 cpColor.hsv.value = 255;
1910 cpColor.set = cpHSV;
1912 ofs[0] = -1;
1913 ofs[1] = -(colorWheelSize + 4);
1915 /* offsets are counterclockwise (in triangles).
1917 * ofs[0] ---->
1918 * _______________________________________
1919 * [1] |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| o
1920 * s |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| f
1921 * f |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| s
1922 * o | | | | | | | | | | | | | | | | | | | | | [3]
1924 * <---- ofs[2]
1925 * ____
1926 * |\ /| <-- triangles
1927 * | \/ |
1928 * | /\ |
1929 * |/__\|
1932 for (y = 0; y < cw_halfsize; y++) {
1933 for (x = y; x < (colorWheelSize + 4 - y); x++) {
1934 /* (xcor, ycor) is (x,y) relative to center of matrix */
1935 xcor = 2 * x - 4 - colorWheelSize;
1936 ycor = 2 * y - 4 - colorWheelSize;
1938 /* RColor.saturation is unsigned char and will wrap after 255 */
1939 sat = rint(255.0 * sqrt(xcor * xcor + ycor * ycor) / colorWheelSize);
1941 cpColor.hsv.saturation = (unsigned char)sat;
1943 ofs[0]++; /* top quarter of matrix */
1944 ofs[1] += colorWheelSize + 4; /* left quarter */
1945 ofs[2] = cw_sqsize - 1 - ofs[0]; /* bottom quarter */
1946 ofs[3] = cw_sqsize - 1 - ofs[1]; /* right quarter */
1948 if (sat < 256) {
1949 if (xcor != 0)
1950 dhue[0] = rint(atan((double)ycor / (double)xcor) *
1951 (180.0 / WM_PI)) + (xcor < 0 ? 180.0 : 0.0);
1952 else
1953 dhue[0] = 270;
1955 dhue[0] = 360 - dhue[0]; /* Reverse direction of ColorWheel */
1956 dhue[1] = 270 - dhue[0] + (dhue[0] > 270 ? 360 : 0);
1957 dhue[2] = dhue[0] - 180 + (dhue[0] < 180 ? 360 : 0);
1958 dhue[3] = 90 - dhue[0] + (dhue[0] > 90 ? 360 : 0);
1960 for (i = 0; i < 4; i++) {
1961 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1962 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1963 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1965 cpColor.hsv.hue = dhue[i];
1966 convertCPColor(&cpColor);
1968 *rp = (unsigned char)(cpColor.rgb.red);
1969 *gp = (unsigned char)(cpColor.rgb.green);
1970 *bp = (unsigned char)(cpColor.rgb.blue);
1972 } else {
1973 for (i = 0; i < 4; i++) {
1974 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1975 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1976 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1978 *rp = (unsigned char)0;
1979 *gp = (unsigned char)0;
1980 *bp = (unsigned char)0;
1985 ofs[0] += 2 * y + 1;
1986 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2 * y);
1990 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue)
1992 unsigned int i;
1993 unsigned int v;
1995 for (i = 0; i < 256; i++) {
1996 /* We divide by 128 in advance, and check whether that number divides
1997 * by 2 properly. If not, we add one to round the number correctly
1999 v = (i * maxvalue) >> 7;
2000 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + (v & 0x01));
2004 static void wheelRender(W_ColorPanel * panel)
2006 W_Screen *scr = WMWidgetScreen(panel->win);
2007 int x, y;
2008 RImage *image;
2009 unsigned char *ptr;
2010 RColor gray;
2011 unsigned long ofs = 0;
2012 /*unsigned char shift = getShift(sizeof(unsigned char)); */
2014 image = RCreateImage(colorWheelSize + 4, colorWheelSize + 4, True);
2015 if (!image) {
2016 wwarning(_("Color Panel: Could not allocate memory"));
2017 return;
2020 ptr = image->data;
2022 /* TODO Make this transparent istead of gray */
2023 gray.red = gray.blue = 0xae;
2024 gray.green = 0xaa;
2026 for (y = 0; y < colorWheelSize + 4; y++) {
2027 for (x = 0; x < colorWheelSize + 4; x++) {
2028 if (wheelInsideColorWheel(panel, ofs)) {
2029 *(ptr++) =
2030 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]]);
2031 *(ptr++) =
2032 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]]);
2033 *(ptr++) =
2034 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]]);
2035 *(ptr++) = 0;
2036 } else {
2037 *(ptr++) = (unsigned char)(gray.red);
2038 *(ptr++) = (unsigned char)(gray.green);
2039 *(ptr++) = (unsigned char)(gray.blue);
2040 *(ptr++) = 255;
2042 ofs++;
2046 if (panel->wheelImg)
2047 XFreePixmap(scr->display, panel->wheelImg);
2049 RConvertImage(scr->rcontext, image, &panel->wheelImg);
2050 RReleaseImage(image);
2052 /* Check if backimage exists. If it doesn't, allocate and fill it */
2053 if (!panel->selectionBackImg) {
2054 panel->selectionBackImg = XCreatePixmap(scr->display,
2055 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
2056 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2057 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2058 /* -2 is hot spot correction */
2062 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs)
2064 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
2065 (panel->wheelMtrx->data[1][ofs] != 0) && (panel->wheelMtrx->data[2][ofs] != 0));
2068 static void wheelPaint(W_ColorPanel * panel)
2070 W_Screen *scr = WMWidgetScreen(panel->win);
2072 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
2073 scr->copyGC, 0, 0, colorWheelSize + 4, colorWheelSize + 4, 0, 0);
2075 /* Draw selection image */
2076 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2077 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2080 static void wheelHandleEvents(XEvent * event, void *data)
2082 W_ColorPanel *panel = (W_ColorPanel *) data;
2084 switch (event->type) {
2085 case Expose:
2086 if (event->xexpose.count != 0) /* TODO Improve */
2087 break;
2088 wheelPaint(panel);
2089 break;
2093 static void wheelHandleActionEvents(XEvent * event, void *data)
2095 W_ColorPanel *panel = (W_ColorPanel *) data;
2097 switch (event->type) {
2098 case ButtonPress:
2099 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) == COLORWHEEL_PART) {
2101 panel->lastChanged = WMWheelModeColorPanel;
2102 panel->flags.dragging = 1;
2104 wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
2106 break;
2108 case ButtonRelease:
2109 panel->flags.dragging = 0;
2110 if (!panel->flags.continuous) {
2111 if (panel->action)
2112 (*panel->action) (panel, panel->clientData);
2114 break;
2116 case MotionNotify:
2117 if (panel->flags.dragging) {
2118 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) == COLORWHEEL_PART) {
2119 wheelPositionSelection(panel, event->xmotion.x, event->xmotion.y);
2120 } else
2121 wheelPositionSelectionOutBounds(panel, event->xmotion.x, event->xmotion.y);
2123 break;
2127 static int getPickerPart(W_ColorPanel * panel, int x, int y)
2129 int lx, ly;
2130 unsigned long ofs;
2132 lx = x;
2133 ly = y;
2135 if (panel->mode == WMWheelModeColorPanel) {
2136 if ((lx >= 2) && (lx <= 2 + colorWheelSize) && (ly >= 2) && (ly <= 2 + colorWheelSize)) {
2138 ofs = ly * panel->wheelMtrx->width + lx;
2140 if (wheelInsideColorWheel(panel, ofs))
2141 return COLORWHEEL_PART;
2145 if (panel->mode == WMCustomPaletteModeColorPanel) {
2146 if ((lx >= 2) && (lx < customPaletteWidth - 2) && (ly >= 2) && (ly < customPaletteHeight - 2)) {
2147 return CUSTOMPALETTE_PART;
2151 return 0;
2154 static void wheelBrightnessSliderCallback(WMWidget * w, void *data)
2156 int value;
2158 W_ColorPanel *panel = (W_ColorPanel *) data;
2160 /* Parameter not used, but tell the compiler that it is ok */
2161 (void) w;
2163 value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2165 wheelCalculateValues(panel, value);
2167 if (panel->color.set == cpRGB) {
2168 convertCPColor(&panel->color);
2169 panel->color.set = cpHSV;
2172 panel->color.hsv.value = value;
2174 wheelRender(panel);
2175 wheelPaint(panel);
2176 wheelUpdateSelection(panel);
2179 static void wheelUpdateSelection(W_ColorPanel * panel)
2181 W_Screen *scr = WMWidgetScreen(panel->win);
2183 updateSwatch(panel, panel->color);
2184 panel->lastChanged = WMWheelModeColorPanel;
2186 /* Redraw color selector (and make a backup of the part it will cover) */
2187 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2188 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2189 /* "-2" is correction for hotspot location */
2190 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2191 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2192 /* see above */
2195 static void wheelUndrawSelection(W_ColorPanel * panel)
2197 W_Screen *scr = WMWidgetScreen(panel->win);
2199 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
2200 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2201 /* see above */
2204 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y)
2206 unsigned long ofs = (y * panel->wheelMtrx->width) + x;
2208 panel->color.rgb.red = panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]];
2210 panel->color.rgb.green = panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]];
2212 panel->color.rgb.blue = panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]];
2213 panel->color.set = cpRGB;
2215 wheelUndrawSelection(panel);
2217 panel->colx = x;
2218 panel->coly = y;
2220 wheelUpdateSelection(panel);
2221 wheelUpdateBrightnessGradientFromLocation(panel);
2224 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2226 int hue;
2227 int xcor, ycor;
2228 CPColor cpColor;
2230 xcor = x * 2 - colorWheelSize - 4;
2231 ycor = y * 2 - colorWheelSize - 4;
2233 panel->color.hsv.saturation = 255;
2234 panel->color.hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2236 if (xcor != 0)
2237 hue = rint(atan(-(double)ycor / (double)xcor) * (180.0 / WM_PI));
2238 else {
2239 if (ycor < 0)
2240 hue = 90;
2241 else
2242 hue = 270;
2245 if (xcor < 0)
2246 hue += 180;
2248 if ((xcor > 0) && (ycor > 0))
2249 hue += 360;
2251 panel->color.hsv.hue = hue;
2252 panel->color.set = cpHSV;
2253 convertCPColor(&panel->color);
2255 wheelUndrawSelection(panel);
2257 panel->colx = 2 + rint((colorWheelSize * (1.0 + cos(panel->color.hsv.hue * (WM_PI / 180.0)))) / 2.0);
2258 /* "+2" because of "colorWheelSize + 4" */
2259 panel->coly = 2 + rint((colorWheelSize * (1.0 + sin(-panel->color.hsv.hue * (WM_PI / 180.0)))) / 2.0);
2261 wheelUpdateSelection(panel);
2262 cpColor = panel->color;
2263 wheelUpdateBrightnessGradient(panel, cpColor);
2266 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel)
2268 CPColor from;
2269 unsigned long ofs;
2271 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2273 from.rgb.red = panel->wheelMtrx->data[0][ofs];
2274 from.rgb.green = panel->wheelMtrx->data[1][ofs];
2275 from.rgb.blue = panel->wheelMtrx->data[2][ofs];
2276 from.set = cpRGB;
2278 wheelUpdateBrightnessGradient(panel, from);
2281 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor)
2283 RColor to;
2284 RImage *sliderImg;
2285 WMPixmap *sliderPxmp;
2287 to.red = to.green = to.blue = 0;
2289 if (topColor.set == cpHSV)
2290 convertCPColor(&topColor);
2292 sliderImg = RRenderGradient(16, 153, &(topColor.rgb), &to, RGRD_VERTICAL);
2293 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win), sliderImg, 0);
2294 RReleaseImage(sliderImg);
2295 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
2296 WMReleasePixmap(sliderPxmp);
2299 /****************** Grayscale Panel Functions ***************/
2301 static void grayBrightnessSliderCallback(WMWidget * w, void *data)
2303 CPColor cpColor;
2304 int value;
2305 char tmp[4];
2306 W_ColorPanel *panel = (W_ColorPanel *) data;
2308 /* Parameter not used, but tell the compiler that it is ok */
2309 (void) w;
2311 value = WMGetSliderValue(panel->grayBrightnessS);
2313 sprintf(tmp, "%d", value);
2315 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2316 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint(2.55 * value);
2317 cpColor.set = cpRGB;
2319 updateSwatch(panel, cpColor);
2320 panel->lastChanged = WMGrayModeColorPanel;
2323 static void grayPresetButtonCallback(WMWidget * w, void *data)
2325 CPColor cpColor;
2326 char tmp[4];
2327 int value;
2328 int i = 0;
2329 W_ColorPanel *panel = (W_ColorPanel *) data;
2331 while (i < 7) {
2332 if (w == panel->grayPresetBtn[i])
2333 break;
2334 i++;
2337 value = rint((100.0 * i) / 6.0);
2338 sprintf(tmp, "%d", value);
2340 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2341 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * i) / 6.0);
2342 cpColor.set = cpRGB;
2344 WMSetSliderValue(panel->grayBrightnessS, rint((100.0 * i) / 6.0));
2346 updateSwatch(panel, cpColor);
2347 panel->lastChanged = WMGrayModeColorPanel;
2350 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification)
2352 CPColor cpColor;
2353 char tmp[4];
2354 int value;
2355 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2357 /* Parameter not used, but tell the compiler that it is ok */
2358 (void) notification;
2360 value = get_textfield_as_integer(panel->grayBrightnessT);
2361 if (value > 100)
2362 value = 100;
2363 if (value < 0)
2364 value = 0;
2366 sprintf(tmp, "%d", value);
2367 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2368 WMSetSliderValue(panel->grayBrightnessS, value);
2370 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * value) / 100.0);
2371 cpColor.set = cpRGB;
2373 updateSwatch(panel, cpColor);
2374 panel->lastChanged = WMGrayModeColorPanel;
2377 /******************* RGB Panel Functions *****************/
2379 void rgbIntToChar(W_ColorPanel *panel, int *value)
2381 char tmp[4];
2382 const char *format;
2384 switch (panel->rgbState) {
2385 case RGBdec:
2386 format = "%d";
2387 break;
2388 case RGBhex:
2389 format = "%0X";
2390 break;
2393 sprintf(tmp, format, value[0]);
2394 WMSetTextFieldText(panel->rgbRedT, tmp);
2395 sprintf(tmp, format, value[1]);
2396 WMSetTextFieldText(panel->rgbGreenT, tmp);
2397 sprintf(tmp, format, value[2]);
2398 WMSetTextFieldText(panel->rgbBlueT, tmp);
2401 int *rgbCharToInt(W_ColorPanel *panel)
2403 int base = 0;
2404 static int value[3];
2405 char *str;
2407 switch (panel->rgbState) {
2408 case RGBdec:
2409 base = 10;
2410 break;
2411 case RGBhex:
2412 base = 16;
2413 break;
2416 str = WMGetTextFieldText(panel->rgbRedT);
2417 value[0] = strtol(str, NULL, base);
2418 wfree(str);
2420 str = WMGetTextFieldText(panel->rgbGreenT);
2421 value[1] = strtol(str, NULL, base);
2422 wfree(str);
2424 str = WMGetTextFieldText(panel->rgbBlueT);
2425 value[2] = strtol(str, NULL, base);
2426 wfree(str);
2428 return value;
2431 static void rgbSliderCallback(WMWidget * w, void *data)
2433 CPColor cpColor;
2434 int value[3];
2435 W_ColorPanel *panel = (W_ColorPanel *) data;
2437 /* Parameter not used, but tell the compiler that it is ok */
2438 (void) w;
2440 value[0] = WMGetSliderValue(panel->rgbRedS);
2441 value[1] = WMGetSliderValue(panel->rgbGreenS);
2442 value[2] = WMGetSliderValue(panel->rgbBlueS);
2444 rgbIntToChar(panel, value);
2446 cpColor.rgb.red = value[0];
2447 cpColor.rgb.green = value[1];
2448 cpColor.rgb.blue = value[2];
2449 cpColor.set = cpRGB;
2451 updateSwatch(panel, cpColor);
2452 panel->lastChanged = WMRGBModeColorPanel;
2455 static void rgbTextFieldCallback(void *observerData, WMNotification * notification)
2457 CPColor cpColor;
2458 int *value;
2459 int n;
2460 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2462 /* Parameter not used, but tell the compiler that it is ok */
2463 (void) notification;
2465 value = rgbCharToInt(panel);
2467 for (n = 0; n < 3; n++) {
2468 if (value[n] > 255)
2469 value[n] = 255;
2470 if (value[n] < 0)
2471 value[n] = 0;
2474 rgbIntToChar(panel, value);
2476 WMSetSliderValue(panel->rgbRedS, value[0]);
2477 WMSetSliderValue(panel->rgbGreenS, value[1]);
2478 WMSetSliderValue(panel->rgbBlueS, value[2]);
2480 cpColor.rgb.red = value[0];
2481 cpColor.rgb.green = value[1];
2482 cpColor.rgb.blue = value[2];
2483 cpColor.set = cpRGB;
2485 updateSwatch(panel, cpColor);
2486 panel->lastChanged = WMRGBModeColorPanel;
2489 static void rgbDecToHex(WMWidget *w, void *data)
2491 W_ColorPanel *panel = (W_ColorPanel *) data;
2492 int *value;
2494 (void) w;
2496 switch (panel->rgbState) {
2497 case RGBhex:
2498 if (WMGetButtonSelected(panel->rgbDecB)) {
2499 WMSetLabelText(panel->rgbMaxL, "255");
2500 WMRedisplayWidget(panel->rgbMaxL);
2501 value = rgbCharToInt(panel);
2502 panel->rgbState = RGBdec;
2503 rgbIntToChar(panel, value);
2505 break;
2507 case RGBdec:
2508 if (WMGetButtonSelected(panel->rgbHexB)) {
2509 WMSetLabelText(panel->rgbMaxL, "FF");
2510 WMRedisplayWidget(panel->rgbMaxL);
2511 value = rgbCharToInt(panel);
2512 panel->rgbState = RGBhex;
2513 rgbIntToChar(panel, value);
2515 break;
2519 /******************* CMYK Panel Functions *****************/
2521 static void cmykSliderCallback(WMWidget * w, void *data)
2523 CPColor cpColor;
2524 int value[4];
2525 char tmp[4];
2526 W_ColorPanel *panel = (W_ColorPanel *) data;
2527 double scale;
2529 /* Parameter not used, but tell the compiler that it is ok */
2530 (void) w;
2532 value[0] = WMGetSliderValue(panel->cmykCyanS);
2533 value[1] = WMGetSliderValue(panel->cmykMagentaS);
2534 value[2] = WMGetSliderValue(panel->cmykYellowS);
2535 value[3] = WMGetSliderValue(panel->cmykBlackS);
2537 sprintf(tmp, "%d", value[0]);
2538 WMSetTextFieldText(panel->cmykCyanT, tmp);
2539 sprintf(tmp, "%d", value[1]);
2540 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2541 sprintf(tmp, "%d", value[2]);
2542 WMSetTextFieldText(panel->cmykYellowT, tmp);
2543 sprintf(tmp, "%d", value[3]);
2544 WMSetTextFieldText(panel->cmykBlackT, tmp);
2546 scale = 2.55 * (1.0 - (value[3] / 100.0));
2547 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2548 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2549 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2550 cpColor.set = cpRGB;
2552 updateSwatch(panel, cpColor);
2553 panel->lastChanged = WMCMYKModeColorPanel;
2556 static void cmykTextFieldCallback(void *observerData, WMNotification * notification)
2558 CPColor cpColor;
2559 int value[4];
2560 char tmp[4];
2561 int n;
2562 double scale;
2563 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2565 /* Parameter not used, but tell the compiler that it is ok */
2566 (void) notification;
2568 value[0] = get_textfield_as_integer(panel->cmykCyanT);
2569 value[1] = get_textfield_as_integer(panel->cmykMagentaT);
2570 value[2] = get_textfield_as_integer(panel->cmykYellowT);
2571 value[3] = get_textfield_as_integer(panel->cmykBlackT);
2573 for (n = 0; n < 4; n++) {
2574 if (value[n] > 100)
2575 value[n] = 100;
2576 if (value[n] < 0)
2577 value[n] = 0;
2580 sprintf(tmp, "%d", value[0]);
2581 WMSetTextFieldText(panel->cmykCyanT, tmp);
2583 sprintf(tmp, "%d", value[1]);
2584 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2586 sprintf(tmp, "%d", value[2]);
2587 WMSetTextFieldText(panel->cmykYellowT, tmp);
2589 sprintf(tmp, "%d", value[3]);
2590 WMSetTextFieldText(panel->cmykBlackT, tmp);
2592 WMSetSliderValue(panel->cmykCyanS, value[0]);
2593 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2594 WMSetSliderValue(panel->cmykYellowS, value[2]);
2595 WMSetSliderValue(panel->cmykBlackS, value[3]);
2597 scale = 2.55 * (1.0 - (value[3] / 100.0));
2598 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2599 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2600 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2601 cpColor.set = cpRGB;
2603 updateSwatch(panel, cpColor);
2604 panel->lastChanged = WMCMYKModeColorPanel;
2607 /********************** HSB Panel Functions ***********************/
2609 static void hsbSliderCallback(WMWidget * w, void *data)
2611 CPColor cpColor;
2612 int value[3];
2613 char tmp[4];
2614 W_ColorPanel *panel = (W_ColorPanel *) data;
2616 value[0] = WMGetSliderValue(panel->hsbHueS);
2617 value[1] = WMGetSliderValue(panel->hsbSaturationS);
2618 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
2620 sprintf(tmp, "%d", value[0]);
2621 WMSetTextFieldText(panel->hsbHueT, tmp);
2622 sprintf(tmp, "%d", value[1]);
2623 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2624 sprintf(tmp, "%d", value[2]);
2625 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2627 cpColor.hsv.hue = value[0];
2628 cpColor.hsv.saturation = value[1] * 2.55;
2629 cpColor.hsv.value = value[2] * 2.55;
2630 cpColor.set = cpHSV;
2632 convertCPColor(&cpColor);
2634 panel->lastChanged = WMHSBModeColorPanel;
2635 updateSwatch(panel, cpColor);
2637 if (w != panel->hsbBrightnessS)
2638 hsbUpdateBrightnessGradient(panel);
2639 if (w != panel->hsbSaturationS)
2640 hsbUpdateSaturationGradient(panel);
2641 if (w != panel->hsbHueS)
2642 hsbUpdateHueGradient(panel);
2645 static void hsbTextFieldCallback(void *observerData, WMNotification * notification)
2647 CPColor cpColor;
2648 int value[3];
2649 char tmp[4];
2650 int n;
2651 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2653 /* Parameter not used, but tell the compiler that it is ok */
2654 (void) notification;
2656 value[0] = get_textfield_as_integer(panel->hsbHueT);
2657 value[1] = get_textfield_as_integer(panel->hsbSaturationT);
2658 value[2] = get_textfield_as_integer(panel->hsbBrightnessT);
2660 if (value[0] > 359)
2661 value[0] = 359;
2662 if (value[0] < 0)
2663 value[0] = 0;
2665 for (n = 1; n < 3; n++) {
2666 if (value[n] > 100)
2667 value[n] = 100;
2668 if (value[n] < 0)
2669 value[n] = 0;
2672 sprintf(tmp, "%d", value[0]);
2673 WMSetTextFieldText(panel->hsbHueT, tmp);
2674 sprintf(tmp, "%d", value[1]);
2675 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2676 sprintf(tmp, "%d", value[2]);
2677 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2679 WMSetSliderValue(panel->hsbHueS, value[0]);
2680 WMSetSliderValue(panel->hsbSaturationS, value[1]);
2681 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
2683 cpColor.hsv.hue = value[0];
2684 cpColor.hsv.saturation = value[1] * 2.55;
2685 cpColor.hsv.value = value[2] * 2.55;
2686 cpColor.set = cpHSV;
2688 convertCPColor(&cpColor);
2690 panel->lastChanged = WMHSBModeColorPanel;
2691 updateSwatch(panel, cpColor);
2693 hsbUpdateBrightnessGradient(panel);
2694 hsbUpdateSaturationGradient(panel);
2695 hsbUpdateHueGradient(panel);
2698 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel)
2700 W_Screen *scr = WMWidgetScreen(panel->win);
2701 RColor from;
2702 CPColor to;
2703 RImage *sliderImg;
2704 WMPixmap *sliderPxmp;
2706 from.red = from.green = from.blue = 0;
2707 to.hsv = panel->color.hsv;
2708 to.hsv.value = 255;
2709 to.set = cpHSV;
2711 convertCPColor(&to);
2713 sliderImg = RRenderGradient(141, 16, &from, &(to.rgb), RGRD_HORIZONTAL);
2714 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2715 RReleaseImage(sliderImg);
2717 if (sliderPxmp)
2718 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
2719 panel->font12, 2, 0, 100, WALeft, scr->white,
2720 False, _("Brightness"), strlen(_("Brightness")));
2721 else
2722 wwarning(_("Color Panel: Could not allocate memory"));
2724 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
2725 WMReleasePixmap(sliderPxmp);
2728 static void hsbUpdateSaturationGradient(W_ColorPanel * panel)
2730 W_Screen *scr = WMWidgetScreen(panel->win);
2731 CPColor from;
2732 CPColor to;
2733 RImage *sliderImg;
2734 WMPixmap *sliderPxmp;
2736 from.hsv = panel->color.hsv;
2737 from.hsv.saturation = 0;
2738 from.set = cpHSV;
2739 convertCPColor(&from);
2741 to.hsv = panel->color.hsv;
2742 to.hsv.saturation = 255;
2743 to.set = cpHSV;
2744 convertCPColor(&to);
2746 sliderImg = RRenderGradient(141, 16, &(from.rgb), &(to.rgb), RGRD_HORIZONTAL);
2747 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2748 RReleaseImage(sliderImg);
2750 if (sliderPxmp)
2751 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2752 panel->font12, 2, 0, 100, WALeft,
2753 from.hsv.value < 128 ? scr->white : scr->black, False,
2754 _("Saturation"), strlen(_("Saturation")));
2755 else
2756 wwarning(_("Color Panel: Could not allocate memory"));
2758 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
2759 WMReleasePixmap(sliderPxmp);
2762 static void hsbUpdateHueGradient(W_ColorPanel * panel)
2764 W_Screen *scr = WMWidgetScreen(panel->win);
2765 RColor **colors = NULL;
2766 RHSVColor hsvcolor;
2767 RImage *sliderImg;
2768 WMPixmap *sliderPxmp;
2769 int i;
2771 hsvcolor = panel->color.hsv;
2773 colors = wmalloc(sizeof(RColor *) * (8));
2774 for (i = 0; i < 7; i++) {
2775 hsvcolor.hue = (360 * i) / 6;
2776 colors[i] = wmalloc(sizeof(RColor));
2777 RHSVtoRGB(&hsvcolor, colors[i]);
2779 colors[7] = NULL;
2781 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2782 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2783 RReleaseImage(sliderImg);
2785 if (sliderPxmp)
2786 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2787 panel->font12, 2, 0, 100, WALeft,
2788 hsvcolor.value < 128 ? scr->white : scr->black, False, _("Hue"), strlen(_("Hue")));
2789 else
2790 wwarning(_("Color Panel: Could not allocate memory"));
2792 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2793 WMReleasePixmap(sliderPxmp);
2795 for (i = 0; i < 7; i++)
2796 wfree(colors[i]);
2798 wfree(colors);
2801 /*************** Custom Palette Functions ****************/
2803 static void customRenderSpectrum(W_ColorPanel * panel)
2805 RImage *spectrum;
2806 int x, y;
2807 unsigned char *ptr;
2808 CPColor cpColor;
2810 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, False);
2812 ptr = spectrum->data;
2814 for (y = 0; y < SPECTRUM_HEIGHT; y++) {
2815 cpColor.hsv.hue = y;
2816 cpColor.hsv.saturation = 0;
2817 cpColor.hsv.value = 255;
2818 cpColor.set = cpHSV;
2820 for (x = 0; x < SPECTRUM_WIDTH; x++) {
2821 convertCPColor(&cpColor);
2823 *(ptr++) = (unsigned char)cpColor.rgb.red;
2824 *(ptr++) = (unsigned char)cpColor.rgb.green;
2825 *(ptr++) = (unsigned char)cpColor.rgb.blue;
2827 if (x < (SPECTRUM_WIDTH / 2))
2828 cpColor.hsv.saturation++;
2830 if (x > (SPECTRUM_WIDTH / 2))
2831 cpColor.hsv.value--;
2834 if (panel->customPaletteImg) {
2835 RReleaseImage(panel->customPaletteImg);
2836 panel->customPaletteImg = NULL;
2838 panel->customPaletteImg = spectrum;
2841 static void customSetPalette(W_ColorPanel * panel)
2843 W_Screen *scr = WMWidgetScreen(panel->win);
2844 RImage *scaledImg;
2845 Pixmap image;
2847 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth, customPaletteHeight, scr->depth);
2848 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth, customPaletteHeight);
2849 RConvertImage(scr->rcontext, scaledImg, &image);
2850 RReleaseImage(scaledImg);
2852 XCopyArea(scr->display, image, panel->customPaletteContentView->window,
2853 scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2855 /* Check backimage exists. If it doesn't, allocate and fill it */
2856 if (!panel->selectionBackImg) {
2857 panel->selectionBackImg = XCreatePixmap(scr->display,
2858 panel->customPaletteContentView->window, 4, 4, scr->depth);
2861 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
2862 panel->palx - 2, panel->paly - 2, 4, 4, 0, 0);
2863 XCopyArea(scr->display, panel->selectionImg,
2864 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2865 panel->palx - 2, panel->paly - 2);
2866 XFreePixmap(scr->display, image);
2868 panel->palXRatio = (double)(panel->customPaletteImg->width) / (double)(customPaletteWidth);
2869 panel->palYRatio = (double)(panel->customPaletteImg->height) / (double)(customPaletteHeight);
2871 WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
2874 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y)
2876 W_Screen *scr = WMWidgetScreen(panel->win);
2877 unsigned long ofs;
2879 /* undraw selection */
2880 XCopyArea(scr->display, panel->selectionBackImg,
2881 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2882 panel->palx - 2, panel->paly - 2);
2884 panel->palx = x;
2885 panel->paly = y;
2887 ofs = (rint(x * panel->palXRatio) + rint(y * panel->palYRatio) * panel->customPaletteImg->width) * 3;
2889 panel->color.rgb.red = panel->customPaletteImg->data[ofs];
2890 panel->color.rgb.green = panel->customPaletteImg->data[ofs + 1];
2891 panel->color.rgb.blue = panel->customPaletteImg->data[ofs + 2];
2892 panel->color.set = cpRGB;
2894 updateSwatch(panel, panel->color);
2895 panel->lastChanged = WMCustomPaletteModeColorPanel;
2897 /* Redraw color selector (and make a backup of the part it will cover) */
2898 XCopyArea(scr->display, panel->customPaletteContentView->window, panel->selectionBackImg, scr->copyGC, panel->palx - 2, panel->paly - 2, 4, 4, 0, 0); /* "-2" is correction for hotspot location */
2899 XCopyArea(scr->display, panel->selectionImg, panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4, panel->palx - 2, panel->paly - 2); /* see above */
2902 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2904 if (x < 2)
2905 x = 2;
2906 if (y < 2)
2907 y = 2;
2908 if (x >= customPaletteWidth)
2909 x = customPaletteWidth - 2;
2910 if (y >= customPaletteHeight)
2911 y = customPaletteHeight - 2;
2913 customPalettePositionSelection(panel, x, y);
2916 static void customPaletteHandleEvents(XEvent * event, void *data)
2918 W_ColorPanel *panel = (W_ColorPanel *) data;
2920 switch (event->type) {
2921 case Expose:
2922 if (event->xexpose.count != 0) /* TODO Improve. */
2923 break;
2924 customSetPalette(panel);
2925 break;
2929 static void customPaletteHandleActionEvents(XEvent * event, void *data)
2931 W_ColorPanel *panel = (W_ColorPanel *) data;
2932 int x, y;
2934 switch (event->type) {
2935 case ButtonPress:
2936 x = event->xbutton.x;
2937 y = event->xbutton.y;
2939 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2940 panel->flags.dragging = 1;
2941 customPalettePositionSelection(panel, x, y);
2943 break;
2945 case ButtonRelease:
2946 panel->flags.dragging = 0;
2947 if (!panel->flags.continuous) {
2948 if (panel->action)
2949 (*panel->action) (panel, panel->clientData);
2951 break;
2953 case MotionNotify:
2954 x = event->xmotion.x;
2955 y = event->xmotion.y;
2957 if (panel->flags.dragging) {
2958 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2959 customPalettePositionSelection(panel, x, y);
2960 } else
2961 customPalettePositionSelectionOutBounds(panel, x, y);
2963 break;
2967 static void customPaletteMenuCallback(WMWidget * w, void *data)
2969 W_ColorPanel *panel = (W_ColorPanel *) data;
2970 int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
2972 /* Parameter not used, but tell the compiler that it is ok */
2973 (void) w;
2975 switch (item) {
2976 case CPmenuNewFromFile:
2977 customPaletteMenuNewFromFile(panel);
2978 break;
2979 case CPmenuRename:
2980 customPaletteMenuRename(panel);
2981 break;
2982 case CPmenuRemove:
2983 customPaletteMenuRemove(panel);
2984 break;
2985 case CPmenuCopy:
2986 break;
2987 case CPmenuNewFromClipboard:
2988 break;
2992 static void customPaletteMenuNewFromFile(W_ColorPanel * panel)
2994 W_Screen *scr = WMWidgetScreen(panel->win);
2995 WMOpenPanel *browseP;
2996 char *filepath;
2997 char *filename = NULL;
2998 char *spath;
2999 char *tmp;
3000 int i;
3001 RImage *tmpImg = NULL;
3003 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir, "\0") == 0))
3004 spath = wexpandpath(wgethomedir());
3005 else
3006 spath = wexpandpath(panel->lastBrowseDir);
3008 browseP = WMGetOpenPanel(scr);
3009 WMSetFilePanelCanChooseDirectories(browseP, 0);
3010 WMSetFilePanelCanChooseFiles(browseP, 1);
3012 /* Get a filename */
3013 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
3014 _("Open Palette"), RSupportedFileFormats())) {
3015 filepath = WMGetFilePanelFileName(browseP);
3017 /* Get seperation position between path and filename */
3018 i = strrchr(filepath, '/') - filepath + 1;
3019 if (i > strlen(filepath))
3020 i = strlen(filepath);
3022 /* Store last browsed path */
3023 if (panel->lastBrowseDir)
3024 wfree(panel->lastBrowseDir);
3025 panel->lastBrowseDir = wmalloc((i + 1) * sizeof(char));
3026 strncpy(panel->lastBrowseDir, filepath, i);
3027 panel->lastBrowseDir[i] = '\0';
3029 /* Get filename from path */
3030 filename = wstrdup(filepath + i);
3032 /* Check for duplicate files, and rename it if there are any */
3033 tmp = wstrconcat(panel->configurationPath, filename);
3034 while (access(tmp, F_OK) == 0) {
3035 char *newName;
3037 wfree(tmp);
3039 newName = generateNewFilename(filename);
3040 wfree(filename);
3041 filename = newName;
3043 tmp = wstrconcat(panel->configurationPath, filename);
3045 wfree(tmp);
3047 /* Copy image to $(gnustepdir)/Library/Colors/ &
3048 * Add filename to history menu */
3049 if (wcopy_file(panel->configurationPath, filepath, filename) == 0) {
3051 /* filepath is a "local" path now the file has been copied */
3052 wfree(filepath);
3053 filepath = wstrconcat(panel->configurationPath, filename);
3055 /* load the image & add menu entries */
3056 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
3057 if (tmpImg) {
3058 if (panel->customPaletteImg)
3059 RReleaseImage(panel->customPaletteImg);
3060 panel->customPaletteImg = tmpImg;
3062 customSetPalette(panel);
3063 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
3065 panel->currentPalette =
3066 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1;
3068 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3069 panel->currentPalette);
3071 } else {
3072 tmp = wstrconcat(panel->configurationPath, filename);
3074 i = remove(tmp); /* Delete the file, it doesn't belong here */
3075 WMRunAlertPanel(scr, panel->win, _("File Error"),
3076 _("Invalid file format !"), _("OK"), NULL, NULL);
3077 if (i != 0) {
3078 werror(_("can't remove file %s"), tmp);
3079 WMRunAlertPanel(scr, panel->win, _("File Error"),
3080 _("Couldn't remove file from Configuration Directory !"),
3081 _("OK"), NULL, NULL);
3083 wfree(tmp);
3085 wfree(filepath);
3086 wfree(filename);
3088 WMFreeFilePanel(browseP);
3090 wfree(spath);
3093 static void customPaletteMenuRename(W_ColorPanel * panel)
3095 W_Screen *scr = WMWidgetScreen(panel->win);
3096 char *toName = NULL;
3097 char *fromName;
3098 char *toPath, *fromPath;
3099 int item;
3100 int index;
3102 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3103 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
3105 toName = WMRunInputPanel(scr, panel->win, _("Rename"), _("Rename palette to:"),
3106 fromName, _("OK"), _("Cancel"));
3108 if (toName) {
3110 /* As some people do certain stupid things... */
3111 if (strcmp(toName, fromName) == 0) {
3112 wfree(toName);
3113 return;
3116 /* For normal people */
3117 fromPath = wstrconcat(panel->configurationPath, fromName);
3118 toPath = wstrconcat(panel->configurationPath, toName);
3120 if (access(toPath, F_OK) == 0) {
3121 /* Careful, this palette exists already */
3122 if (WMRunAlertPanel(scr, panel->win, _("Warning"),
3123 _("Palette already exists !\n\nOverwrite ?"), _("No"), _("Yes"),
3124 NULL) == 1) {
3125 /* "No" = 0, "Yes" = 1 */
3126 int items = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
3128 remove(toPath);
3130 /* Remove from History list too */
3131 index = 1;
3132 while ((index < items)
3134 (strcmp(WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, index), toName)
3135 != 0))
3136 index++;
3138 if (index < items) {
3139 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, index);
3140 if (index < item)
3141 item--;
3144 } else {
3145 wfree(fromPath);
3146 wfree(toName);
3147 wfree(toPath);
3149 return;
3153 if (rename(fromPath, toPath) != 0)
3154 werror(_("Couldn't rename palette %s to %s"), fromName, toName);
3155 else {
3156 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3157 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item, toName);
3159 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
3161 wfree(fromPath);
3162 wfree(toPath);
3163 wfree(toName);
3167 static void customPaletteMenuRemove(W_ColorPanel * panel)
3169 W_Screen *scr = WMWidgetScreen(panel->win);
3170 char *text;
3171 char *tmp;
3172 int choice;
3173 int item;
3175 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3177 tmp = wstrconcat(_("This will permanently remove the palette "),
3178 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3179 text = wstrconcat(tmp, _(".\n\nAre you sure you want to remove this palette ?"));
3180 wfree(tmp);
3182 choice = WMRunAlertPanel(scr, panel->win, _("Remove"), text, _("Yes"), _("No"), NULL);
3183 /* returns 0 (= "Yes") or 1 (="No") */
3184 wfree(text);
3186 if (choice == 0) {
3188 tmp = wstrconcat(panel->configurationPath,
3189 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3191 if (remove(tmp) == 0) {
3192 /* item-1 always exists */
3193 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3195 customPaletteHistoryCallback(panel->customPaletteHistoryBtn, panel);
3196 customSetPalette(panel);
3198 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3200 } else {
3201 werror(_("Couldn't remove palette %s"), tmp);
3204 wfree(tmp);
3208 static void customPaletteHistoryCallback(WMWidget * w, void *data)
3210 W_ColorPanel *panel = (W_ColorPanel *) data;
3211 W_Screen *scr = WMWidgetScreen(panel->win);
3212 int item;
3213 char *filename;
3214 RImage *tmp = NULL;
3215 unsigned char perm_mask;
3217 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3218 if (item == panel->currentPalette)
3219 return;
3221 if (item == 0) {
3222 customRenderSpectrum(panel);
3224 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, False);
3225 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, False);
3226 } else {
3227 /* Load file from configpath */
3228 filename = wstrconcat(panel->configurationPath,
3229 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3231 /* If the file corresponding to the item does not exist,
3232 * remove it from the history list and select the next one.
3234 perm_mask = (access(filename, F_OK) == 0);
3235 if (!perm_mask) {
3236 /* File does not exist */
3237 wfree(filename);
3238 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3239 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3240 customPaletteHistoryCallback(w, data);
3241 return;
3244 /* Get the image */
3245 tmp = RLoadImage(scr->rcontext, filename, 0);
3246 if (tmp) {
3247 if (panel->customPaletteImg) {
3248 RReleaseImage(panel->customPaletteImg);
3249 panel->customPaletteImg = NULL;
3251 panel->customPaletteImg = tmp;
3254 /* If the image is not writable, don't allow removing/renaming */
3255 perm_mask = (access(filename, W_OK) == 0);
3256 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, perm_mask);
3257 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, perm_mask);
3259 wfree(filename);
3261 customSetPalette(panel);
3263 panel->currentPalette = item;
3266 /************************* ColorList Panel Functions **********************/
3268 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect)
3270 WMScreen *scr = WMWidgetScreen(lPtr);
3271 Display *dpy = WMScreenDisplay(scr);
3272 WMView *view = W_VIEW(lPtr);
3273 RColor *color = (RColor *) WMGetListItem(lPtr, index)->clientData;
3274 W_ColorPanel *panel = WMGetHangedData(lPtr);
3275 int width, height, x, y;
3276 WMColor *fillColor;
3278 width = rect->size.width;
3279 height = rect->size.height;
3280 x = rect->pos.x;
3281 y = rect->pos.y;
3283 if (state & WLDSSelected)
3284 XFillRectangle(dpy, d, WMColorGC(scr->white), x, y, width, height);
3285 else
3286 XFillRectangle(dpy, d, WMColorGC(view->backColor), x, y, width, height);
3288 fillColor = WMCreateRGBColor(scr, color->red << 8, color->green << 8, color->blue << 8, True);
3290 XFillRectangle(dpy, d, WMColorGC(fillColor), x, y, 15, height);
3291 WMReleaseColor(fillColor);
3293 WMDrawString(scr, d, scr->black, panel->font12, x + 18, y, text, strlen(text));
3296 static void colorListSelect(WMWidget * w, void *data)
3298 W_ColorPanel *panel = (W_ColorPanel *) data;
3299 CPColor cpColor;
3301 cpColor.rgb = *((RColor *) WMGetListSelectedItem(w)->clientData);
3302 cpColor.set = cpRGB;
3304 panel->lastChanged = WMColorListModeColorPanel;
3305 updateSwatch(panel, cpColor);
3308 static void colorListColorMenuCallback(WMWidget * w, void *data)
3310 W_ColorPanel *panel = (W_ColorPanel *) data;
3311 int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
3313 /* Parameter not used, but tell the compiler that it is ok */
3314 (void) w;
3316 switch (item) {
3317 case CLmenuAdd:
3318 break;
3319 case CLmenuRename:
3320 break;
3321 case CLmenuRemove:
3322 break;
3326 static void colorListListMenuCallback(WMWidget * w, void *data)
3328 W_ColorPanel *panel = (W_ColorPanel *) data;
3329 int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
3331 /* Parameter not used, but tell the compiler that it is ok */
3332 (void) w;
3334 switch (item) {
3335 case CLmenuAdd:
3336 break;
3337 case CLmenuRename:
3338 break;
3339 case CLmenuRemove:
3340 break;
3344 /*************** Panel Initialisation Functions *****************/
3346 static void wheelInit(W_ColorPanel * panel)
3348 CPColor cpColor;
3350 if (panel->color.set != cpHSV)
3351 convertCPColor(&panel->color);
3353 WMSetSliderValue(panel->wheelBrightnessS, 255 - panel->color.hsv.value);
3355 panel->colx = 2 + rint((colorWheelSize / 2.0) *
3356 (1 + (panel->color.hsv.saturation / 255.0) *
3357 cos(panel->color.hsv.hue * WM_PI / 180.0)));
3358 panel->coly = 2 + rint((colorWheelSize / 2.0) *
3359 (1 + (panel->color.hsv.saturation / 255.0) *
3360 sin(-panel->color.hsv.hue * WM_PI / 180.0)));
3362 wheelCalculateValues(panel, panel->color.hsv.value);
3364 cpColor = panel->color;
3365 cpColor.hsv.value = 255;
3366 cpColor.set = cpHSV;
3367 wheelUpdateBrightnessGradient(panel, cpColor);
3370 static void grayInit(W_ColorPanel * panel)
3372 int value;
3373 char tmp[4];
3375 if (panel->color.set != cpHSV)
3376 convertCPColor(&panel->color);
3378 value = rint(panel->color.hsv.value / 2.55);
3379 WMSetSliderValue(panel->grayBrightnessS, value);
3381 sprintf(tmp, "%d", value);
3382 WMSetTextFieldText(panel->grayBrightnessT, tmp);
3385 static void rgbInit(W_ColorPanel * panel)
3387 char tmp[4];
3388 const char *format;
3390 if (panel->color.set != cpRGB)
3391 convertCPColor(&panel->color);
3393 WMSetSliderValue(panel->rgbRedS, panel->color.rgb.red);
3394 WMSetSliderValue(panel->rgbGreenS, panel->color.rgb.green);
3395 WMSetSliderValue(panel->rgbBlueS, panel->color.rgb.blue);
3397 switch (panel->rgbState) {
3398 case RGBdec:
3399 format = "%d";
3400 break;
3401 case RGBhex:
3402 format = "%0X";
3403 break;
3406 sprintf(tmp, format, panel->color.rgb.red);
3407 WMSetTextFieldText(panel->rgbRedT, tmp);
3408 sprintf(tmp, format, panel->color.rgb.green);
3409 WMSetTextFieldText(panel->rgbGreenT, tmp);
3410 sprintf(tmp, format, panel->color.rgb.blue);
3411 WMSetTextFieldText(panel->rgbBlueT, tmp);
3414 static void cmykInit(W_ColorPanel * panel)
3416 int value[3];
3417 char tmp[4];
3419 if (panel->color.set != cpRGB)
3420 convertCPColor(&panel->color);
3422 value[0] = rint((255 - panel->color.rgb.red) / 2.55);
3423 value[1] = rint((255 - panel->color.rgb.green) / 2.55);
3424 value[2] = rint((255 - panel->color.rgb.blue) / 2.55);
3426 WMSetSliderValue(panel->cmykCyanS, value[0]);
3427 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3428 WMSetSliderValue(panel->cmykYellowS, value[2]);
3429 WMSetSliderValue(panel->cmykBlackS, 0);
3431 sprintf(tmp, "%d", value[0]);
3432 WMSetTextFieldText(panel->cmykCyanT, tmp);
3433 sprintf(tmp, "%d", value[1]);
3434 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3435 sprintf(tmp, "%d", value[2]);
3436 WMSetTextFieldText(panel->cmykYellowT, tmp);
3437 WMSetTextFieldText(panel->cmykBlackT, "0");
3440 static void hsbInit(W_ColorPanel * panel)
3442 int value[3];
3443 char tmp[4];
3445 if (panel->color.set != cpHSV)
3446 convertCPColor(&panel->color);
3448 value[0] = panel->color.hsv.hue;
3449 value[1] = rint(panel->color.hsv.saturation / 2.55);
3450 value[2] = rint(panel->color.hsv.value / 2.55);
3452 WMSetSliderValue(panel->hsbHueS, value[0]);
3453 WMSetSliderValue(panel->hsbSaturationS, value[1]);
3454 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
3456 sprintf(tmp, "%d", value[0]);
3457 WMSetTextFieldText(panel->hsbHueT, tmp);
3458 sprintf(tmp, "%d", value[1]);
3459 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3460 sprintf(tmp, "%d", value[2]);
3461 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3463 hsbUpdateBrightnessGradient(panel);
3464 hsbUpdateSaturationGradient(panel);
3465 hsbUpdateHueGradient(panel);
3468 /************************** Common utility functions ************************/
3470 static char *generateNewFilename(const char *curName)
3472 int n;
3473 char c;
3474 int baseLen;
3475 const char *ptr;
3476 char *newName;
3478 assert(curName);
3480 ptr = curName;
3482 if (((ptr = strrchr(ptr, '{')) == 0) || sscanf(ptr, "{%i}%c", &n, &c) != 1)
3483 return wstrconcat(curName, " {1}");
3485 baseLen = ptr - curName - 1;
3487 newName = wmalloc(baseLen + 16);
3488 strncpy(newName, curName, baseLen);
3490 snprintf(&newName[baseLen], 16, " {%i}", n + 1);
3492 return newName;
3495 static void convertCPColor(CPColor * color)
3497 unsigned short old_hue = 0;
3499 switch (color->set) {
3500 case cpNone:
3501 wwarning(_("Color Panel: Color unspecified"));
3502 return;
3503 case cpRGB:
3504 old_hue = color->hsv.hue;
3505 RRGBtoHSV(&(color->rgb), &(color->hsv));
3507 /* In black the hue is undefined, and may change by conversion
3508 * Same for white. */
3509 if (((color->rgb.red == 0) &&
3510 (color->rgb.green == 0) &&
3511 (color->rgb.blue == 0)) ||
3512 ((color->rgb.red == 0) && (color->rgb.green == 0) && (color->rgb.blue == 255))
3514 color->hsv.hue = old_hue;
3515 break;
3516 case cpHSV:
3517 RHSVtoRGB(&(color->hsv), &(color->rgb));
3518 break;
3522 static RColor ulongToRColor(WMScreen * scr, unsigned long value)
3524 RColor color;
3525 XColor *xcolor = NULL;
3527 xcolor = wmalloc(sizeof(XColor));
3528 xcolor->pixel = value;
3529 XQueryColor(scr->display, scr->rcontext->cmap, xcolor);
3531 color.red = xcolor->red >> 8;
3532 color.green = xcolor->green >> 8;
3533 color.blue = xcolor->blue >> 8;
3534 color.alpha = 0;
3536 wfree(xcolor);
3538 return color;
3541 static unsigned char getShift(unsigned char value)
3543 unsigned char i = -1;
3545 if (value == 0)
3546 return 0;
3548 while (value) {
3549 value >>= 1;
3550 i++;
3553 return i;