WPrefs: make fall-back value look like a fall-back value in Texture Panel (Coverity...
[wmaker-crm.git] / WINGs / wcolorpanel.c
blob60655cdf524ef0d69d5ce2c73f7a0fe221c19131
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>
39 #define RETRY( x ) do { \
40 x; \
41 } while (errno == EINTR);
43 /* BUG There's something fishy with shaped windows */
44 /* Whithout shape extension the magnified image is completely broken -Dan */
46 #ifdef USE_XSHAPE
47 # include <X11/extensions/shape.h>
48 #endif
50 char *WMColorPanelColorChangedNotification = "WMColorPanelColorChangedNotification";
53 * Bitmaps for magnifying glass cursor
56 /* Cursor */
57 #define Cursor_x_hot 11
58 #define Cursor_y_hot 11
59 #define Cursor_width 32
60 #define Cursor_height 32
61 static unsigned char Cursor_bits[] = {
62 0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
63 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
64 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
65 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
66 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
67 0x00, 0x08, 0x00, 0x50, 0x00, 0x10, 0x00, 0x88, 0x00, 0x20, 0x00, 0x5c, 0x01, 0xc0, 0x81,
68 0x3b, 0x02, 0x00, 0x7e, 0x70, 0x05, 0x00, 0x00, 0xe0, 0x08, 0x00, 0x00, 0xc0, 0x15, 0x00,
69 0x00, 0x80, 0x23, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x5c,
70 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x70
73 /* Cursor shape-mask */
74 #define Cursor_shape_width 32
75 #define Cursor_shape_height 32
76 static unsigned char Cursor_shape_bits[] = {
77 0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
78 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
79 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
80 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
81 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
82 0x00, 0x08, 0x00, 0x70, 0x00, 0x10, 0x00, 0xf8, 0x00, 0x20, 0x00, 0xfc, 0x01, 0xc0, 0x81,
83 0xfb, 0x03, 0x00, 0x7e, 0xf0, 0x07, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xc0, 0x1f, 0x00,
84 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xfc,
85 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x70
88 /* Clip-mask for magnified pixels */
89 #define Cursor_mask_width 24
90 #define Cursor_mask_height 24
91 static unsigned char Cursor_mask_bits[] = {
92 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0xff, 0x07,
93 0xf0, 0xff, 0x0f, 0xf8, 0xff, 0x1f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f,
94 0xfc, 0xff, 0x3f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f,
95 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfc, 0xff, 0x3f,
96 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xf8, 0xff, 0x1f, 0xf0, 0xff, 0x0f,
97 0xe0, 0xff, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00
100 typedef struct MovingView {
101 WMView *view; /* The view this is all about */
102 XImage *image; /* What's under the view */
103 XImage *dirtyRect; /* Storage of overlapped image area */
104 Pixmap magPix; /* Magnified part of pixmap */
105 RColor color; /* Color of a pixel in the image */
106 int x, y; /* Position of view */
107 } MovingView;
109 typedef struct CPColor {
110 RColor rgb; /* The RGB values of the color */
111 RHSVColor hsv; /* The HSV values of the color */
112 enum { /* Which one was last set ? */
113 cpNone,
114 cpRGB,
115 cpHSV
116 } set;
117 } CPColor;
119 typedef struct WheelMatrix {
120 unsigned int width, height; /* Size of the colorwheel */
121 unsigned char *data[3]; /* Wheel data (R,G,B) */
122 unsigned char values[256]; /* Precalculated values R,G & B = 0-255 */
123 } wheelMatrix;
125 typedef struct W_ColorPanel {
126 WMWindow *win;
127 WMFont *font8;
128 WMFont *font12;
129 void *clientData;
130 WMAction2 *action;
132 /* Common Stuff */
133 WMColorWell *colorWell;
134 WMButton *magnifyBtn;
135 WMButton *wheelBtn;
136 WMButton *slidersBtn;
137 WMButton *customPaletteBtn;
138 WMButton *colorListBtn;
140 /* Magnifying Glass */
141 MovingView *magnifyGlass;
143 /* ColorWheel Panel */
144 WMFrame *wheelFrm;
145 WMSlider *wheelBrightnessS;
146 WMView *wheelView;
148 /* Slider Panels */
149 WMFrame *slidersFrm;
150 WMFrame *seperatorFrm;
151 WMButton *grayBtn;
152 WMButton *rgbBtn;
153 WMButton *cmykBtn;
154 WMButton *hsbBtn;
155 /* Gray Scale Panel */
156 WMFrame *grayFrm;
157 WMLabel *grayMinL;
158 WMLabel *grayMaxL;
159 WMSlider *grayBrightnessS;
160 WMTextField *grayBrightnessT;
161 WMButton *grayPresetBtn[7];
163 /* RGB Panel */
164 WMButton *rgbDecB;
165 WMButton *rgbHexB;
166 WMFrame *rgbFrm;
167 WMLabel *rgbMinL;
168 WMLabel *rgbMaxL;
169 WMSlider *rgbRedS;
170 WMSlider *rgbGreenS;
171 WMSlider *rgbBlueS;
172 WMTextField *rgbRedT;
173 WMTextField *rgbGreenT;
174 WMTextField *rgbBlueT;
175 enum {
176 RGBdec,
177 RGBhex
178 } rgbState;
180 /* CMYK Panel */
181 WMFrame *cmykFrm;
182 WMLabel *cmykMinL;
183 WMLabel *cmykMaxL;
184 WMSlider *cmykCyanS;
185 WMSlider *cmykMagentaS;
186 WMSlider *cmykYellowS;
187 WMSlider *cmykBlackS;
188 WMTextField *cmykCyanT;
189 WMTextField *cmykMagentaT;
190 WMTextField *cmykYellowT;
191 WMTextField *cmykBlackT;
193 /* HSB Panel */
194 WMFrame *hsbFrm;
195 WMSlider *hsbHueS;
196 WMSlider *hsbSaturationS;
197 WMSlider *hsbBrightnessS;
198 WMTextField *hsbHueT;
199 WMTextField *hsbSaturationT;
200 WMTextField *hsbBrightnessT;
202 /* Custom Palette Panel */
203 WMFrame *customPaletteFrm;
204 WMPopUpButton *customPaletteHistoryBtn;
205 WMFrame *customPaletteContentFrm;
206 WMPopUpButton *customPaletteMenuBtn;
207 WMView *customPaletteContentView;
209 /* Color List Panel */
210 WMFrame *colorListFrm;
211 WMPopUpButton *colorListHistoryBtn;
212 WMList *colorListContentLst;
213 WMPopUpButton *colorListColorMenuBtn;
214 WMPopUpButton *colorListListMenuBtn;
216 /* Look-Up Tables and Images */
217 wheelMatrix *wheelMtrx;
218 Pixmap wheelImg;
219 Pixmap selectionImg;
220 Pixmap selectionBackImg;
221 RImage *customPaletteImg;
222 char *lastBrowseDir;
224 /* Common Data Fields */
225 CPColor color; /* Current color */
226 WMColorPanelMode mode; /* Current color selection mode */
227 WMColorPanelMode slidersmode; /* Current color sel. mode sliders panel */
228 WMColorPanelMode lastChanged; /* Panel that last changed the color */
229 int colx, coly; /* (x,y) of sel.-marker in WheelMode */
230 int palx, paly; /* (x,y) of sel.-marker in
231 CustomPaletteMode */
232 double palXRatio, palYRatio; /* Ratios in x & y between
233 original and scaled
234 palettesize */
235 int currentPalette;
236 char *configurationPath;
238 struct {
239 unsigned int continuous:1;
240 unsigned int dragging:1;
241 } flags;
242 } W_ColorPanel;
244 enum {
245 CPmenuNewFromFile,
246 CPmenuRename,
247 CPmenuRemove,
248 CPmenuCopy,
249 CPmenuNewFromClipboard
250 } customPaletteMenuItem;
252 enum {
253 CLmenuAdd,
254 CLmenuRename,
255 CLmenuRemove
256 } colorListMenuItem;
258 #define PWIDTH 194
259 #define PHEIGHT 266
260 #define colorWheelSize 150
261 #define customPaletteWidth 182
262 #define customPaletteHeight 106
263 #define knobThickness 8
265 #define SPECTRUM_WIDTH 511
266 #define SPECTRUM_HEIGHT 360
268 #define COLORWHEEL_PART 1
269 #define CUSTOMPALETTE_PART 2
270 #define BUFSIZE 1024
272 #define MAX_LENGTH 1024
274 #ifndef M_PI
275 #define M_PI 3.14159265358979323846
276 #endif
278 static char *generateNewFilename(const char *curName);
279 static void convertCPColor(CPColor * color);
280 static RColor ulongToRColor(WMScreen * scr, unsigned long value);
281 static unsigned char getShift(unsigned char value);
283 static void modeButtonCallback(WMWidget * w, void *data);
284 static int getPickerPart(W_ColorPanel * panel, int x, int y);
285 static void readConfiguration(W_ColorPanel * panel);
286 static void readXColors(W_ColorPanel * panel);
288 static void closeWindowCallback(WMWidget * w, void *data);
290 static Cursor magnifyGrabPointer(W_ColorPanel * panel);
291 static WMPoint magnifyInitialize(W_ColorPanel * panel);
292 static void magnifyPutCursor(WMWidget * w, void *data);
293 static Pixmap magnifyCreatePixmap(WMColorPanel * panel);
294 static void magnifyGetImageStored(W_ColorPanel * panel, int x1, int y1, int x2, int y2);
295 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h);
297 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height);
298 static void wheelDestroyMatrix(wheelMatrix * matrix);
299 static void wheelInitMatrix(W_ColorPanel * panel);
300 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue);
301 static void wheelRender(W_ColorPanel * panel);
302 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs);
303 static void wheelPaint(W_ColorPanel * panel);
305 static void wheelHandleEvents(XEvent * event, void *data);
306 static void wheelHandleActionEvents(XEvent * event, void *data);
307 static void wheelBrightnessSliderCallback(WMWidget * w, void *data);
308 static void wheelUpdateSelection(W_ColorPanel * panel);
309 static void wheelUndrawSelection(W_ColorPanel * panel);
311 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y);
312 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
313 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel);
314 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor);
316 static void grayBrightnessSliderCallback(WMWidget * w, void *data);
317 static void grayPresetButtonCallback(WMWidget * w, void *data);
318 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification);
320 static void rgbSliderCallback(WMWidget * w, void *data);
321 static void rgbTextFieldCallback(void *observerData, WMNotification * notification);
322 static void rgbDecToHex(WMWidget *w, void *data);
324 static void cmykSliderCallback(WMWidget * w, void *data);
325 static void cmykTextFieldCallback(void *observerData, WMNotification * notification);
327 static void hsbSliderCallback(WMWidget * w, void *data);
328 static void hsbTextFieldCallback(void *observerData, WMNotification * notification);
329 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel);
330 static void hsbUpdateSaturationGradient(W_ColorPanel * panel);
331 static void hsbUpdateHueGradient(W_ColorPanel * panel);
333 static void customRenderSpectrum(W_ColorPanel * panel);
334 static void customSetPalette(W_ColorPanel * panel);
335 static void customPaletteHandleEvents(XEvent * event, void *data);
336 static void customPaletteHandleActionEvents(XEvent * event, void *data);
337 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y);
338 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
339 static void customPaletteMenuCallback(WMWidget * w, void *data);
340 static void customPaletteHistoryCallback(WMWidget * w, void *data);
342 static void customPaletteMenuNewFromFile(W_ColorPanel * panel);
343 static void customPaletteMenuRename(W_ColorPanel * panel);
344 static void customPaletteMenuRemove(W_ColorPanel * panel);
346 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect);
347 static void colorListSelect(WMWidget * w, void *data);
348 static void colorListColorMenuCallback(WMWidget * w, void *data);
349 static void colorListListMenuCallback(WMWidget * w, void *data);
351 static void wheelInit(W_ColorPanel * panel);
352 static void grayInit(W_ColorPanel * panel);
353 static void rgbInit(W_ColorPanel * panel);
354 static void cmykInit(W_ColorPanel * panel);
355 static void hsbInit(W_ColorPanel * panel);
358 static inline int get_textfield_as_integer(WMTextField *widget)
360 char *str;
361 int value;
363 str = WMGetTextFieldText(widget);
364 value = atoi(str);
365 wfree(str);
366 return value;
369 void WMSetColorPanelAction(WMColorPanel * panel, WMAction2 * action, void *data)
371 panel->action = action;
372 panel->clientData = data;
375 static WMColorPanel *makeColorPanel(WMScreen * scrPtr, const char *name)
377 WMColorPanel *panel;
378 RImage *image;
379 WMPixmap *pixmap;
380 RColor from;
381 RColor to;
382 WMColor *textcolor, *graybuttoncolor;
383 int i;
384 GC bgc = WMColorGC(scrPtr->black);
385 GC wgc = WMColorGC(scrPtr->white);
387 panel = wmalloc(sizeof(WMColorPanel));
388 panel->color.rgb.red = 0;
389 panel->color.rgb.green = 0;
390 panel->color.rgb.blue = 0;
391 panel->color.hsv.hue = 0;
392 panel->color.hsv.saturation = 0;
393 panel->color.hsv.value = 0;
394 panel->color.set = cpNone; /* Color has not been set yet */
396 panel->font8 = WMSystemFontOfSize(scrPtr, 8);
397 panel->font12 = WMSystemFontOfSize(scrPtr, 12);
399 panel->win = WMCreateWindowWithStyle(scrPtr, name,
400 WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
401 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
402 WMSetWindowTitle(panel->win, _("Colors"));
403 WMSetWindowCloseAction(panel->win, closeWindowCallback, panel);
405 /* Set Default ColorPanel Mode(s) */
406 panel->mode = WMWheelModeColorPanel;
407 panel->lastChanged = 0;
408 panel->slidersmode = WMRGBModeColorPanel;
409 panel->configurationPath = wstrconcat(wusergnusteppath(), "/Library/Colors/");
411 /* Some General Purpose Widgets */
412 panel->colorWell = WMCreateColorWell(panel->win);
413 WMResizeWidget(panel->colorWell, 134, 36);
414 WSetColorWellBordered(panel->colorWell, False);
415 WMMoveWidget(panel->colorWell, 56, 4);
417 panel->magnifyBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
418 WMResizeWidget(panel->magnifyBtn, 46, 36);
419 WMMoveWidget(panel->magnifyBtn, 6, 4);
420 WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
421 WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
422 WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
424 panel->wheelBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
425 WMResizeWidget(panel->wheelBtn, 46, 32);
426 WMMoveWidget(panel->wheelBtn, 6, 44);
427 WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
428 WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
429 WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
431 panel->slidersBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
432 WMResizeWidget(panel->slidersBtn, 46, 32);
433 WMMoveWidget(panel->slidersBtn, 52, 44);
434 WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
435 WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
436 WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
438 panel->customPaletteBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
439 WMResizeWidget(panel->customPaletteBtn, 46, 32);
440 WMMoveWidget(panel->customPaletteBtn, 98, 44);
441 WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
442 WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
443 WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
445 panel->colorListBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
446 WMResizeWidget(panel->colorListBtn, 46, 32);
447 WMMoveWidget(panel->colorListBtn, 144, 44);
448 WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
449 WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
450 WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
452 /* Let's Group some of them together */
453 WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
454 WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
455 WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
457 /* Widgets for the ColorWheel Panel */
458 panel->wheelFrm = WMCreateFrame(panel->win);
459 WMSetFrameRelief(panel->wheelFrm, WRFlat);
460 WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
461 WMMoveWidget(panel->wheelFrm, 5, 80);
463 panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
464 /* XXX Can we create a view ? */
465 W_ResizeView(panel->wheelView, colorWheelSize + 4, colorWheelSize + 4);
466 W_MoveView(panel->wheelView, 0, 0);
468 /* Create an event handler to handle expose/click events in ColorWheel */
469 WMCreateEventHandler(panel->wheelView,
470 ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
471 LeaveWindowMask | ButtonMotionMask, wheelHandleActionEvents, panel);
473 WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents, panel);
475 panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
476 WMResizeWidget(panel->wheelBrightnessS, 16, 153);
477 WMMoveWidget(panel->wheelBrightnessS, 5 + colorWheelSize + 14, 1);
478 WMSetSliderMinValue(panel->wheelBrightnessS, 0);
479 WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
480 WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback, panel);
481 WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
483 panel->wheelMtrx = wheelCreateMatrix(colorWheelSize + 4, colorWheelSize + 4);
484 wheelInitMatrix(panel);
486 /* Widgets for the Slider Panels */
487 panel->slidersFrm = WMCreateFrame(panel->win);
488 WMSetFrameRelief(panel->slidersFrm, WRFlat);
489 WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
490 WMMoveWidget(panel->slidersFrm, 4, 80);
492 panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
493 WMSetFrameRelief(panel->seperatorFrm, WRPushed);
494 WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
495 WMMoveWidget(panel->seperatorFrm, 0, 1);
497 panel->grayBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
498 WMResizeWidget(panel->grayBtn, 46, 24);
499 WMMoveWidget(panel->grayBtn, 1, 8);
500 WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
501 WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
502 WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
504 panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
505 WMResizeWidget(panel->rgbBtn, 46, 24);
506 WMMoveWidget(panel->rgbBtn, 47, 8);
507 WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
508 WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
509 WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
511 panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
512 WMResizeWidget(panel->cmykBtn, 46, 24);
513 WMMoveWidget(panel->cmykBtn, 93, 8);
514 WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
515 WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
516 WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
518 panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
519 WMResizeWidget(panel->hsbBtn, 46, 24);
520 WMMoveWidget(panel->hsbBtn, 139, 8);
521 WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
522 WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
523 WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
525 /* Let's Group the Slider Panel Buttons Together */
526 WMGroupButtons(panel->grayBtn, panel->rgbBtn);
527 WMGroupButtons(panel->grayBtn, panel->cmykBtn);
528 WMGroupButtons(panel->grayBtn, panel->hsbBtn);
530 textcolor = WMDarkGrayColor(scrPtr);
532 /* Widgets for GrayScale Panel */
533 panel->grayFrm = WMCreateFrame(panel->slidersFrm);
534 WMSetFrameRelief(panel->grayFrm, WRFlat);
535 WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
536 WMMoveWidget(panel->grayFrm, 0, 34);
538 panel->grayMinL = WMCreateLabel(panel->grayFrm);
539 WMResizeWidget(panel->grayMinL, 20, 10);
540 WMMoveWidget(panel->grayMinL, 2, 2);
541 WMSetLabelText(panel->grayMinL, "0");
542 WMSetLabelTextAlignment(panel->grayMinL, WALeft);
543 WMSetLabelTextColor(panel->grayMinL, textcolor);
544 WMSetLabelFont(panel->grayMinL, panel->font8);
546 panel->grayMaxL = WMCreateLabel(panel->grayFrm);
547 WMResizeWidget(panel->grayMaxL, 40, 10);
548 WMMoveWidget(panel->grayMaxL, 104, 2);
549 WMSetLabelText(panel->grayMaxL, "100");
550 WMSetLabelTextAlignment(panel->grayMaxL, WARight);
551 WMSetLabelTextColor(panel->grayMaxL, textcolor);
552 WMSetLabelFont(panel->grayMaxL, panel->font8);
554 panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
555 WMResizeWidget(panel->grayBrightnessS, 141, 16);
556 WMMoveWidget(panel->grayBrightnessS, 2, 14);
557 WMSetSliderMinValue(panel->grayBrightnessS, 0);
558 WMSetSliderMaxValue(panel->grayBrightnessS, 100);
559 WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
560 WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback, panel);
562 from.red = 0;
563 from.green = 0;
564 from.blue = 0;
566 to.red = 255;
567 to.green = 255;
568 to.blue = 255;
570 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
571 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
572 RReleaseImage(image);
574 if (pixmap)
575 W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap,
576 panel->font12, 2, 0, 100, WALeft, scrPtr->white,
577 False, _("Brightness"), strlen(_("Brightness")));
578 else
579 wwarning(_("Color Panel: Could not allocate memory"));
581 WMSetSliderImage(panel->grayBrightnessS, pixmap);
582 WMReleasePixmap(pixmap);
584 panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
585 WMResizeWidget(panel->grayBrightnessT, 40, 18);
586 WMMoveWidget(panel->grayBrightnessT, 146, 13);
587 WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
588 WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel,
589 WMTextDidEndEditingNotification, panel->grayBrightnessT);
591 for (i = 0; i < 7; i++) {
592 pixmap = WMCreatePixmap(scrPtr, 13, 13, scrPtr->depth, False);
594 graybuttoncolor = WMCreateRGBColor(scrPtr, (255 / 6) * i << 8,
595 (255 / 6) * i << 8, (255 / 6) * i << 8, True);
596 WMPaintColorSwatch(graybuttoncolor, pixmap->pixmap, 0, 0, 15, 15);
597 WMReleaseColor(graybuttoncolor);
599 panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
600 WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
601 WMMoveWidget(panel->grayPresetBtn[i], 2 + (i * 20), 34);
602 WMSetButtonAction(panel->grayPresetBtn[i], grayPresetButtonCallback, panel);
603 WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
604 WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
605 WMReleasePixmap(pixmap);
609 /* End of GrayScale Panel */
611 /* Widgets for RGB Panel */
612 panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
613 WMSetFrameRelief(panel->rgbFrm, WRFlat);
614 WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
615 WMMoveWidget(panel->rgbFrm, 0, 34);
617 panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
618 WMResizeWidget(panel->rgbMinL, 20, 10);
619 WMMoveWidget(panel->rgbMinL, 2, 2);
620 WMSetLabelText(panel->rgbMinL, "0");
621 WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
622 WMSetLabelTextColor(panel->rgbMinL, textcolor);
623 WMSetLabelFont(panel->rgbMinL, panel->font8);
625 panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
626 WMResizeWidget(panel->rgbMaxL, 40, 10);
627 WMMoveWidget(panel->rgbMaxL, 104, 2);
628 WMSetLabelText(panel->rgbMaxL, "255");
629 WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
630 WMSetLabelTextColor(panel->rgbMaxL, textcolor);
631 WMSetLabelFont(panel->rgbMaxL, panel->font8);
633 panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
634 WMResizeWidget(panel->rgbRedS, 141, 16);
635 WMMoveWidget(panel->rgbRedS, 2, 14);
636 WMSetSliderMinValue(panel->rgbRedS, 0);
637 WMSetSliderMaxValue(panel->rgbRedS, 255);
638 WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
639 WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
641 to.red = 255;
642 to.green = 0;
643 to.blue = 0;
645 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
646 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
647 RReleaseImage(image);
649 if (pixmap)
650 W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12,
651 2, 0, 100, WALeft, scrPtr->white, False, _("Red"), strlen(_("Red")));
652 else
653 wwarning(_("Color Panel: Could not allocate memory"));
655 WMSetSliderImage(panel->rgbRedS, pixmap);
656 WMReleasePixmap(pixmap);
658 panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
659 WMResizeWidget(panel->rgbRedT, 40, 18);
660 WMMoveWidget(panel->rgbRedT, 146, 13);
661 WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
662 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbRedT);
664 panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
665 WMResizeWidget(panel->rgbGreenS, 141, 16);
666 WMMoveWidget(panel->rgbGreenS, 2, 36);
667 WMSetSliderMinValue(panel->rgbGreenS, 0);
668 WMSetSliderMaxValue(panel->rgbGreenS, 255);
669 WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
670 WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
672 to.red = 0;
673 to.green = 255;
674 to.blue = 0;
676 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
677 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
678 RReleaseImage(image);
680 if (pixmap)
681 W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12,
682 2, 0, 100, WALeft, scrPtr->white, False, _("Green"), strlen(_("Green")));
683 else
684 wwarning(_("Color Panel: Could not allocate memory"));
686 WMSetSliderImage(panel->rgbGreenS, pixmap);
687 WMReleasePixmap(pixmap);
689 panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
690 WMResizeWidget(panel->rgbGreenT, 40, 18);
691 WMMoveWidget(panel->rgbGreenT, 146, 35);
692 WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
693 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbGreenT);
695 panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
696 WMResizeWidget(panel->rgbBlueS, 141, 16);
697 WMMoveWidget(panel->rgbBlueS, 2, 58);
698 WMSetSliderMinValue(panel->rgbBlueS, 0);
699 WMSetSliderMaxValue(panel->rgbBlueS, 255);
700 WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
701 WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
703 to.red = 0;
704 to.green = 0;
705 to.blue = 255;
707 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
708 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
709 RReleaseImage(image);
711 if (pixmap)
712 W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12,
713 2, 0, 100, WALeft, scrPtr->white, False, _("Blue"), strlen(_("Blue")));
714 else
715 wwarning(_("Color Panel: Could not allocate memory"));
717 WMSetSliderImage(panel->rgbBlueS, pixmap);
718 WMReleasePixmap(pixmap);
720 panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
721 WMResizeWidget(panel->rgbBlueT, 40, 18);
722 WMMoveWidget(panel->rgbBlueT, 146, 57);
723 WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
724 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbBlueT);
726 panel->rgbDecB = WMCreateButton(panel->rgbFrm, WBTRadio);
727 WMSetButtonText(panel->rgbDecB, "Decimal");
728 WMSetButtonSelected(panel->rgbDecB, 1);
729 panel->rgbState = RGBdec;
730 WMSetButtonAction(panel->rgbDecB, rgbDecToHex, panel);
731 WMResizeWidget(panel->rgbDecB, PWIDTH - 8, 23);
732 WMMoveWidget(panel->rgbDecB, 2, 81);
734 panel->rgbHexB = WMCreateButton(panel->rgbFrm, WBTRadio);
735 WMSetButtonText(panel->rgbHexB, "Hexadecimal");
736 WMSetButtonAction(panel->rgbHexB, rgbDecToHex, panel);
737 WMResizeWidget(panel->rgbHexB, PWIDTH - 8, 23);
738 WMMoveWidget(panel->rgbHexB, 2, 104);
740 WMGroupButtons(panel->rgbDecB, panel->rgbHexB);
742 /* End of RGB Panel */
744 /* Widgets for CMYK Panel */
745 panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
746 WMSetFrameRelief(panel->cmykFrm, WRFlat);
747 WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
748 WMMoveWidget(panel->cmykFrm, 0, 34);
750 panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
751 WMResizeWidget(panel->cmykMinL, 20, 10);
752 WMMoveWidget(panel->cmykMinL, 2, 2);
753 WMSetLabelText(panel->cmykMinL, "0");
754 WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
755 WMSetLabelTextColor(panel->cmykMinL, textcolor);
756 WMSetLabelFont(panel->cmykMinL, panel->font8);
758 panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
759 WMResizeWidget(panel->cmykMaxL, 40, 10);
760 WMMoveWidget(panel->cmykMaxL, 104, 2);
761 WMSetLabelText(panel->cmykMaxL, "100");
762 WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
763 WMSetLabelTextColor(panel->cmykMaxL, textcolor);
764 WMSetLabelFont(panel->cmykMaxL, panel->font8);
766 panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
767 WMResizeWidget(panel->cmykCyanS, 141, 16);
768 WMMoveWidget(panel->cmykCyanS, 2, 14);
769 WMSetSliderMinValue(panel->cmykCyanS, 0);
770 WMSetSliderMaxValue(panel->cmykCyanS, 100);
771 WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
772 WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
774 from.red = 255;
775 from.green = 255;
776 from.blue = 255;
778 to.red = 0;
779 to.green = 255;
780 to.blue = 255;
782 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
783 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
784 RReleaseImage(image);
786 if (pixmap)
787 W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12,
788 2, 0, 100, WALeft, scrPtr->black, False, _("Cyan"), strlen(_("Cyan")));
789 else
790 wwarning(_("Color Panel: Could not allocate memory"));
792 WMSetSliderImage(panel->cmykCyanS, pixmap);
793 WMReleasePixmap(pixmap);
795 panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
796 WMResizeWidget(panel->cmykCyanT, 40, 18);
797 WMMoveWidget(panel->cmykCyanT, 146, 13);
798 WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
799 WMAddNotificationObserver(cmykTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->cmykCyanT);
801 panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
802 WMResizeWidget(panel->cmykMagentaS, 141, 16);
803 WMMoveWidget(panel->cmykMagentaS, 2, 36);
804 WMSetSliderMinValue(panel->cmykMagentaS, 0);
805 WMSetSliderMaxValue(panel->cmykMagentaS, 100);
806 WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
807 WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
809 to.red = 255;
810 to.green = 0;
811 to.blue = 255;
813 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
814 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
815 RReleaseImage(image);
817 if (pixmap)
818 W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12,
819 2, 0, 100, WALeft, scrPtr->black, False, _("Magenta"), strlen(_("Magenta")));
820 else
821 wwarning(_("Color Panel: Could not allocate memory"));
823 WMSetSliderImage(panel->cmykMagentaS, pixmap);
824 WMReleasePixmap(pixmap);
826 panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
827 WMResizeWidget(panel->cmykMagentaT, 40, 18);
828 WMMoveWidget(panel->cmykMagentaT, 146, 35);
829 WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
830 WMAddNotificationObserver(cmykTextFieldCallback, panel,
831 WMTextDidEndEditingNotification, panel->cmykMagentaT);
833 panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
834 WMResizeWidget(panel->cmykYellowS, 141, 16);
835 WMMoveWidget(panel->cmykYellowS, 2, 58);
836 WMSetSliderMinValue(panel->cmykYellowS, 0);
837 WMSetSliderMaxValue(panel->cmykYellowS, 100);
838 WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
839 WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
841 to.red = 255;
842 to.green = 255;
843 to.blue = 0;
845 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
846 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
847 RReleaseImage(image);
849 if (pixmap)
850 W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12,
851 2, 0, 100, WALeft, scrPtr->black, False, _("Yellow"), strlen(_("Yellow")));
852 else
853 wwarning(_("Color Panel: Could not allocate memory"));
855 WMSetSliderImage(panel->cmykYellowS, pixmap);
856 WMReleasePixmap(pixmap);
858 panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
859 WMResizeWidget(panel->cmykYellowT, 40, 18);
860 WMMoveWidget(panel->cmykYellowT, 146, 57);
861 WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
862 WMAddNotificationObserver(cmykTextFieldCallback, panel,
863 WMTextDidEndEditingNotification, panel->cmykYellowT);
865 panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
866 WMResizeWidget(panel->cmykBlackS, 141, 16);
867 WMMoveWidget(panel->cmykBlackS, 2, 80);
868 WMSetSliderMinValue(panel->cmykBlackS, 0);
869 WMSetSliderMaxValue(panel->cmykBlackS, 100);
870 WMSetSliderValue(panel->cmykBlackS, 0);
871 WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
872 WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
874 to.red = 0;
875 to.green = 0;
876 to.blue = 0;
878 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
879 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
880 RReleaseImage(image);
882 if (pixmap)
883 W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12,
884 2, 0, 100, WALeft, scrPtr->black, False, _("Black"), strlen(_("Black")));
885 else
886 wwarning(_("Color Panel: Could not allocate memory"));
888 WMSetSliderImage(panel->cmykBlackS, pixmap);
889 WMReleasePixmap(pixmap);
891 panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
892 WMResizeWidget(panel->cmykBlackT, 40, 18);
893 WMMoveWidget(panel->cmykBlackT, 146, 79);
894 WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
895 WMAddNotificationObserver(cmykTextFieldCallback, panel,
896 WMTextDidEndEditingNotification, panel->cmykBlackT);
897 /* End of CMYK Panel */
899 /* Widgets for HSB Panel */
900 panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
901 WMSetFrameRelief(panel->hsbFrm, WRFlat);
902 WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
903 WMMoveWidget(panel->hsbFrm, 0, 34);
905 panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
906 WMResizeWidget(panel->hsbHueS, 141, 16);
907 WMMoveWidget(panel->hsbHueS, 2, 14);
908 WMSetSliderMinValue(panel->hsbHueS, 0);
909 WMSetSliderMaxValue(panel->hsbHueS, 359);
910 WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
911 WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
913 panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
914 WMResizeWidget(panel->hsbHueT, 40, 18);
915 WMMoveWidget(panel->hsbHueT, 146, 13);
916 WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
917 WMAddNotificationObserver(hsbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->hsbHueT);
919 panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
920 WMResizeWidget(panel->hsbSaturationS, 141, 16);
921 WMMoveWidget(panel->hsbSaturationS, 2, 36);
922 WMSetSliderMinValue(panel->hsbSaturationS, 0);
923 WMSetSliderMaxValue(panel->hsbSaturationS, 100);
924 WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
925 WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
927 panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
928 WMResizeWidget(panel->hsbSaturationT, 40, 18);
929 WMMoveWidget(panel->hsbSaturationT, 146, 35);
930 WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
931 WMAddNotificationObserver(hsbTextFieldCallback, panel,
932 WMTextDidEndEditingNotification, panel->hsbSaturationT);
934 panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
935 WMResizeWidget(panel->hsbBrightnessS, 141, 16);
936 WMMoveWidget(panel->hsbBrightnessS, 2, 58);
937 WMSetSliderMinValue(panel->hsbBrightnessS, 0);
938 WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
939 WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
940 WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
942 panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
943 WMResizeWidget(panel->hsbBrightnessT, 40, 18);
944 WMMoveWidget(panel->hsbBrightnessT, 146, 57);
945 WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
946 WMAddNotificationObserver(hsbTextFieldCallback, panel,
947 WMTextDidEndEditingNotification, panel->hsbBrightnessT);
948 /* End of HSB Panel */
950 WMReleaseColor(textcolor);
952 /* Widgets for the CustomPalette Panel */
953 panel->customPaletteFrm = WMCreateFrame(panel->win);
954 WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
955 WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
956 WMMoveWidget(panel->customPaletteFrm, 5, 80);
958 panel->customPaletteHistoryBtn = WMCreatePopUpButton(panel->customPaletteFrm);
959 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, _("Spectrum"));
960 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
961 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1);
962 WMSetPopUpButtonAction(panel->customPaletteHistoryBtn, customPaletteHistoryCallback, panel);
963 WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
964 WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
966 panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
967 WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
968 WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
969 WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
971 panel->customPaletteContentView = W_CreateView(W_VIEW(panel->customPaletteContentFrm));
972 /* XXX Test if we can create a view */
973 W_ResizeView(panel->customPaletteContentView, customPaletteWidth, customPaletteHeight);
974 W_MoveView(panel->customPaletteContentView, 2, 2);
976 /* Create event handler to handle expose/click events in CustomPalette */
977 WMCreateEventHandler(panel->customPaletteContentView,
978 ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
979 ButtonMotionMask, customPaletteHandleActionEvents, panel);
981 WMCreateEventHandler(panel->customPaletteContentView, ExposureMask, customPaletteHandleEvents, panel);
983 panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
984 WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
985 WMSetPopUpButtonText(panel->customPaletteMenuBtn, _("Palette"));
986 WMSetPopUpButtonAction(panel->customPaletteMenuBtn, customPaletteMenuCallback, panel);
987 WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
988 WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
990 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from File..."));
991 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Rename..."));
992 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Remove"));
993 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Copy"));
994 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from Clipboard"));
996 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, 0);
997 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, 0);
998 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuCopy, 0);
999 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuNewFromClipboard, 0);
1001 customRenderSpectrum(panel);
1002 panel->currentPalette = 0;
1003 panel->palx = customPaletteWidth / 2;
1004 panel->paly = customPaletteHeight / 2;
1006 /* Widgets for the ColorList Panel */
1007 panel->colorListFrm = WMCreateFrame(panel->win);
1008 WMSetFrameRelief(panel->colorListFrm, WRFlat);
1009 WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
1010 WMMoveWidget(panel->colorListFrm, 5, 80);
1012 panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
1013 WMAddPopUpButtonItem(panel->colorListHistoryBtn, _("X11-Colors"));
1014 WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn,
1015 WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn) - 1);
1016 /* WMSetPopUpButtonAction(panel->colorListHistoryBtn,
1017 * colorListHistoryCallback, panel); */
1018 WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
1019 WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
1021 panel->colorListContentLst = WMCreateList(panel->colorListFrm);
1022 WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
1023 WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
1024 WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
1025 WMMoveWidget(panel->colorListContentLst, 0, 23);
1026 WMHangData(panel->colorListContentLst, panel);
1028 panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1029 WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
1030 WMSetPopUpButtonText(panel->colorListColorMenuBtn, _("Color"));
1031 WMSetPopUpButtonAction(panel->colorListColorMenuBtn, colorListColorMenuCallback, panel);
1032 WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16) / 2, 20);
1033 WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
1035 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Add..."));
1036 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Rename..."));
1037 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Remove"));
1039 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuAdd, 0);
1040 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRename, 0);
1041 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRemove, 0);
1043 panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1044 WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
1045 WMSetPopUpButtonText(panel->colorListListMenuBtn, _("List"));
1046 WMSetPopUpButtonAction(panel->colorListListMenuBtn, colorListListMenuCallback, panel);
1047 WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2, 20);
1048 WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2 + 8, PHEIGHT - 130);
1050 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("New..."));
1051 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Rename..."));
1052 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Remove"));
1054 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuAdd, 0);
1055 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
1056 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
1058 WMRealizeWidget(panel->win);
1059 WMMapSubwidgets(panel->win);
1061 WMMapSubwidgets(panel->wheelFrm);
1062 WMMapSubwidgets(panel->slidersFrm);
1063 WMMapSubwidgets(panel->grayFrm);
1064 WMMapSubwidgets(panel->rgbFrm);
1065 WMMapSubwidgets(panel->cmykFrm);
1066 WMMapSubwidgets(panel->hsbFrm);
1067 WMMapSubwidgets(panel->customPaletteFrm);
1068 WMMapSubwidgets(panel->customPaletteContentFrm);
1069 WMMapSubwidgets(panel->colorListFrm);
1071 /* Pixmap to indicate selection positions
1072 * wheelframe MUST be mapped.
1074 panel->selectionImg = XCreatePixmap(scrPtr->display, WMWidgetXID(panel->win), 4, 4, scrPtr->depth);
1075 XFillRectangle(scrPtr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1076 XFillRectangle(scrPtr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1078 readConfiguration(panel);
1079 readXColors(panel);
1081 return panel;
1084 WMColorPanel *WMGetColorPanel(WMScreen * scrPtr)
1086 WMColorPanel *panel;
1088 if (scrPtr->sharedColorPanel)
1089 return scrPtr->sharedColorPanel;
1091 panel = makeColorPanel(scrPtr, "colorPanel");
1093 scrPtr->sharedColorPanel = panel;
1095 return panel;
1098 void WMFreeColorPanel(WMColorPanel * panel)
1100 W_Screen *scr;
1102 if (!panel)
1103 return;
1105 scr = WMWidgetScreen(panel->win);
1106 if (panel == scr->sharedColorPanel) {
1107 scr->sharedColorPanel = NULL;
1110 WMRemoveNotificationObserver(panel);
1111 WMUnmapWidget(panel->win);
1113 /* fonts */
1114 WMReleaseFont(panel->font8);
1115 WMReleaseFont(panel->font12);
1117 /* pixmaps */
1118 wheelDestroyMatrix(panel->wheelMtrx);
1119 if (panel->wheelImg)
1120 XFreePixmap(scr->display, panel->wheelImg);
1121 if (panel->selectionImg)
1122 XFreePixmap(scr->display, panel->selectionImg);
1123 if (panel->selectionBackImg)
1124 XFreePixmap(scr->display, panel->selectionBackImg);
1125 RReleaseImage(panel->customPaletteImg);
1127 /* structs */
1128 if (panel->lastBrowseDir)
1129 wfree(panel->lastBrowseDir);
1130 if (panel->configurationPath)
1131 wfree(panel->configurationPath);
1133 WMDestroyWidget(panel->win);
1135 wfree(panel);
1138 void WMCloseColorPanel(WMColorPanel * panel)
1140 WMFreeColorPanel(panel);
1143 void WMShowColorPanel(WMColorPanel * panel)
1145 WMScreen *scr = WMWidgetScreen(panel->win);
1146 WMColor *white = WMWhiteColor(scr);
1148 if (panel->color.set == cpNone)
1149 WMSetColorPanelColor(panel, white);
1150 WMReleaseColor(white);
1152 if (panel->mode != WMWheelModeColorPanel)
1153 WMPerformButtonClick(panel->wheelBtn);
1155 WMMapWidget(panel->win);
1158 static void closeWindowCallback(WMWidget * w, void *data)
1160 W_ColorPanel *panel = (W_ColorPanel *) data;
1162 /* Parameter not used, but tell the compiler that it is ok */
1163 (void) w;
1165 WMCloseColorPanel(panel);
1168 static void readConfiguration(W_ColorPanel * panel)
1170 /* XXX Doesn't take care of "invalid" files */
1172 DIR *dPtr;
1173 struct dirent *dp;
1174 struct stat stat_buf;
1175 int item;
1177 if (stat(panel->configurationPath, &stat_buf) != 0) {
1178 if (mkdir(panel->configurationPath, S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH) != 0) {
1179 werror(_("Color Panel: Could not create directory %s needed"
1180 " to store configurations"), panel->configurationPath);
1181 WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
1182 WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
1183 WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
1184 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1185 _("File Error"),
1186 _("Could not create ColorPanel configuration directory"),
1187 _("OK"), NULL, NULL);
1189 return;
1192 if (!(dPtr = opendir(panel->configurationPath))) {
1193 wwarning("%s: %s", _("Color Panel: Could not find file"), panel->configurationPath);
1194 return;
1197 while ((dp = readdir(dPtr)) != NULL) {
1198 unsigned int perm_mask;
1199 char *path = wstrconcat(panel->configurationPath,
1200 dp->d_name);
1202 if (dp->d_name[0] != '.') {
1203 item = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
1204 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
1206 perm_mask = (access(path, R_OK) == 0);
1207 WMSetPopUpButtonItemEnabled(panel->customPaletteHistoryBtn, item, perm_mask);
1209 wfree(path);
1211 closedir(dPtr);
1214 static void readXColors(W_ColorPanel * panel)
1216 WMListItem *item;
1217 const RGBColor *entry;
1219 for (entry = rgbColors; entry->name != NULL; entry++) {
1220 item = WMAddListItem(panel->colorListContentLst, entry->name);
1221 item->clientData = (void *)&(entry->color);
1225 void WMSetColorPanelPickerMode(WMColorPanel * panel, WMColorPanelMode mode)
1227 W_Screen *scr = WMWidgetScreen(panel->win);
1229 if (mode != WMWheelModeColorPanel) {
1230 WMUnmapWidget(panel->wheelFrm);
1231 if (panel->selectionBackImg) {
1232 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1233 panel->selectionBackImg = None;
1236 if (mode != WMGrayModeColorPanel)
1237 WMUnmapWidget(panel->grayFrm);
1238 if (mode != WMRGBModeColorPanel)
1239 WMUnmapWidget(panel->rgbFrm);
1240 if (mode != WMCMYKModeColorPanel)
1241 WMUnmapWidget(panel->cmykFrm);
1242 if (mode != WMHSBModeColorPanel)
1243 WMUnmapWidget(panel->hsbFrm);
1244 if (mode != WMCustomPaletteModeColorPanel) {
1245 WMUnmapWidget(panel->customPaletteFrm);
1246 if (panel->selectionBackImg) {
1247 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1248 panel->selectionBackImg = None;
1251 if (mode != WMColorListModeColorPanel)
1252 WMUnmapWidget(panel->colorListFrm);
1253 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
1254 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1255 WMUnmapWidget(panel->slidersFrm);
1256 else
1257 panel->slidersmode = mode;
1259 if (mode == WMWheelModeColorPanel) {
1260 WMMapWidget(panel->wheelFrm);
1261 WMSetButtonSelected(panel->wheelBtn, True);
1262 if (panel->lastChanged != WMWheelModeColorPanel)
1263 wheelInit(panel);
1264 wheelRender(panel);
1265 wheelPaint(panel);
1266 } else if (mode == WMGrayModeColorPanel) {
1267 WMMapWidget(panel->slidersFrm);
1268 WMSetButtonSelected(panel->slidersBtn, True);
1269 WMMapWidget(panel->grayFrm);
1270 WMSetButtonSelected(panel->grayBtn, True);
1271 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1272 if (panel->lastChanged != WMGrayModeColorPanel)
1273 grayInit(panel);
1274 } else if (mode == WMRGBModeColorPanel) {
1275 WMMapWidget(panel->slidersFrm);
1276 WMSetButtonSelected(panel->slidersBtn, True);
1277 WMMapWidget(panel->rgbFrm);
1278 WMSetButtonSelected(panel->rgbBtn, True);
1279 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1280 if (panel->lastChanged != WMRGBModeColorPanel)
1281 rgbInit(panel);
1282 } else if (mode == WMCMYKModeColorPanel) {
1283 WMMapWidget(panel->slidersFrm);
1284 WMSetButtonSelected(panel->slidersBtn, True);
1285 WMMapWidget(panel->cmykFrm);
1286 WMSetButtonSelected(panel->cmykBtn, True);
1287 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1288 if (panel->lastChanged != WMCMYKModeColorPanel)
1289 cmykInit(panel);
1290 } else if (mode == WMHSBModeColorPanel) {
1291 WMMapWidget(panel->slidersFrm);
1292 WMSetButtonSelected(panel->slidersBtn, True);
1293 WMMapWidget(panel->hsbFrm);
1294 WMSetButtonSelected(panel->hsbBtn, True);
1295 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1296 if (panel->lastChanged != WMHSBModeColorPanel)
1297 hsbInit(panel);
1298 } else if (mode == WMCustomPaletteModeColorPanel) {
1299 WMMapWidget(panel->customPaletteFrm);
1300 WMSetButtonSelected(panel->customPaletteBtn, True);
1301 customSetPalette(panel);
1302 } else if (mode == WMColorListModeColorPanel) {
1303 WMMapWidget(panel->colorListFrm);
1304 WMSetButtonSelected(panel->colorListBtn, True);
1307 panel->mode = mode;
1310 WMColor *WMGetColorPanelColor(WMColorPanel * panel)
1312 return WMGetColorWellColor(panel->colorWell);
1315 void WMSetColorPanelColor(WMColorPanel * panel, WMColor * color)
1317 WMSetColorWellColor(panel->colorWell, color);
1319 panel->color.rgb.red = color->color.red >> 8;
1320 panel->color.rgb.green = color->color.green >> 8;
1321 panel->color.rgb.blue = color->color.blue >> 8;
1322 panel->color.set = cpRGB;
1324 if (panel->mode == panel->lastChanged)
1325 panel->lastChanged = 0;
1327 WMSetColorPanelPickerMode(panel, panel->mode);
1330 static void updateSwatch(WMColorPanel * panel, CPColor color)
1332 WMScreen *scr = WMWidgetScreen(panel->win);
1333 WMColor *wellcolor;
1335 if (color.set != cpRGB)
1336 convertCPColor(&color);
1338 panel->color = color;
1340 wellcolor = WMCreateRGBColor(scr, color.rgb.red << 8, color.rgb.green << 8, color.rgb.blue << 8, True);
1342 WMSetColorWellColor(panel->colorWell, wellcolor);
1343 WMReleaseColor(wellcolor);
1345 if (!panel->flags.dragging || panel->flags.continuous) {
1346 if (panel->action)
1347 (*panel->action) (panel, panel->clientData);
1349 WMPostNotificationName(WMColorPanelColorChangedNotification, panel, NULL);
1353 static void modeButtonCallback(WMWidget * w, void *data)
1355 W_ColorPanel *panel = (W_ColorPanel *) (data);
1357 if (w == panel->wheelBtn)
1358 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1359 else if (w == panel->slidersBtn)
1360 WMSetColorPanelPickerMode(panel, panel->slidersmode);
1361 else if (w == panel->customPaletteBtn)
1362 WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
1363 else if (w == panel->colorListBtn)
1364 WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
1365 else if (w == panel->grayBtn)
1366 WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
1367 else if (w == panel->rgbBtn)
1368 WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
1369 else if (w == panel->cmykBtn)
1370 WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
1371 else if (w == panel->hsbBtn)
1372 WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
1375 /****************** Magnifying Cursor Functions *******************/
1377 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h)
1379 int x0 = 0, y0 = 0, w0 = w, h0 = h;
1380 const int displayWidth = DisplayWidth(scr->display, scr->screen),
1381 displayHeight = DisplayHeight(scr->display, scr->screen);
1383 if (!(image && image->data)) {
1384 /* The image in panel->magnifyGlass->image does not exist yet.
1385 * Grab one from the screen (not beyond) and use it from now on.
1387 if (!(image = XGetImage(scr->display, scr->rootWin,
1388 x - Cursor_x_hot, y - Cursor_y_hot, w, h, AllPlanes, ZPixmap)))
1389 wwarning(_("Color Panel: X failed request"));
1391 return image;
1394 /* Coordinate correction for back pixmap
1395 * if magnifying glass is at screen-borders
1398 /* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
1399 * Hatched area is beyond screen border.
1401 * |<-Cursor_x_hot->|
1402 * ________________|_____
1403 * |/ / / / / / /| | |
1404 * | / / / / / / |(x,y) |
1405 * |/_/_/_/_/_/_/|________|
1406 * |<----x0----->|<--w0-->|
1410 /* Figure 2: Shifting of rectangle-to-grab at bottom/right
1411 * screen borders
1412 * Hatched area is beyond screen border
1414 * |<-Cursor_x_hot->|
1415 * ________________|_______________
1416 * | | | / / / / / /|
1417 * | (x,y)|/ / / / / / |
1418 * |___________________|_/_/_/_/_/_/|
1419 * |<-------w0-------->| |
1420 * |<---------------w--|----------->|
1421 * | |
1422 * x0 Displaywidth-1
1425 if (x < Cursor_x_hot) { /* see fig. 1 */
1426 x0 = Cursor_x_hot - x;
1427 w0 = w - x0;
1430 if (displayWidth - 1 < x - Cursor_x_hot + w) { /* see fig. 2 */
1431 w0 = (displayWidth) - (x - Cursor_x_hot);
1434 if (y < Cursor_y_hot) { /* see fig. 1 */
1435 y0 = Cursor_y_hot - y;
1436 h0 = h - y0;
1439 if (displayHeight - 1 < y - Cursor_y_hot + h) { /* see fig. 2 */
1440 h0 = (displayHeight) - (y - Cursor_y_hot);
1442 /* end of coordinate correction */
1444 /* Grab an image from the screen, clipped if necessary,
1445 * and put it in the existing panel->magnifyGlass->image
1446 * with the corresponding clipping offset.
1448 if (!XGetSubImage(scr->display, scr->rootWin,
1449 x - Cursor_x_hot + x0, y - Cursor_y_hot + y0, w0, h0, AllPlanes, ZPixmap, image, x0, y0))
1450 wwarning(_("Color Panel: X failed request"));
1452 return NULL;
1455 static void magnifyGetImageStored(WMColorPanel * panel, int x1, int y1, int x2, int y2)
1457 /* (x1, y1) = topleft corner of existing rectangle
1458 * (x2, y2) = topleft corner of new position
1461 W_Screen *scr = WMWidgetScreen(panel->win);
1462 int xa = 0, ya = 0, xb = 0, yb = 0;
1463 int width, height;
1464 const int dx = abs(x2 - x1), dy = abs(y2 - y1);
1465 XImage *image;
1466 const int x_min = Cursor_x_hot,
1467 y_min = Cursor_y_hot,
1468 x_max = DisplayWidth(scr->display, scr->screen) - 1 -
1469 (Cursor_mask_width - Cursor_x_hot),
1470 y_max = DisplayHeight(scr->display, scr->screen) - 1 - (Cursor_mask_height - Cursor_y_hot);
1472 if ((dx == 0) && (dy == 0) && panel->magnifyGlass->image)
1473 return; /* No movement */
1475 if (x1 < x2)
1476 xa = dx;
1477 else
1478 xb = dx;
1480 if (y1 < y2)
1481 ya = dy;
1482 else
1483 yb = dy;
1485 width = Cursor_mask_width - dx;
1486 height = Cursor_mask_height - dy;
1488 /* If the traversed distance is larger than the size of the magnifying
1489 * glass contents, there is no need to do dirty rectangles. A whole new
1490 * rectangle can be grabbed (unless that rectangle falls partially
1491 * off screen).
1492 * Destroying the image and setting it to NULL will achieve that later on.
1494 * Of course, grabbing an XImage beyond the borders of the screen will
1495 * cause trouble, this is considdered a special case. Part of the screen
1496 * is grabbed, but there is no need for dirty rectangles.
1498 if ((width <= 0) || (height <= 0)) {
1499 if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
1500 if (panel->magnifyGlass->image)
1501 XDestroyImage(panel->magnifyGlass->image);
1502 panel->magnifyGlass->image = NULL;
1504 } else {
1505 if (panel->magnifyGlass->image) {
1506 /* Get dirty rectangle from panel->magnifyGlass->image */
1507 panel->magnifyGlass->dirtyRect =
1508 XSubImage(panel->magnifyGlass->image, xa, ya, width, height);
1509 if (!panel->magnifyGlass->dirtyRect) {
1510 wwarning(_("Color Panel: X failed request"));
1511 return; /* X returned a NULL from XSubImage */
1516 /* Get image from screen */
1517 image = magnifyGetImage(scr, panel->magnifyGlass->image, x2, y2, Cursor_mask_width, Cursor_mask_height);
1518 if (image) { /* Only reassign if a *new* image was grabbed */
1519 panel->magnifyGlass->image = image;
1520 return;
1523 /* Copy previously stored rectangle on covered part of image */
1524 if (panel->magnifyGlass->image && panel->magnifyGlass->dirtyRect) {
1525 int old_height;
1527 /* "width" and "height" are used as coordinates here,
1528 * and run from [0...width-1] and [0...height-1] respectively.
1530 width--;
1531 height--;
1532 old_height = height;
1534 for (; width >= 0; width--)
1535 for (height = old_height; height >= 0; height--)
1536 XPutPixel(panel->magnifyGlass->image, xb + width, yb + height,
1537 XGetPixel(panel->magnifyGlass->dirtyRect, width, height));
1538 XDestroyImage(panel->magnifyGlass->dirtyRect);
1539 panel->magnifyGlass->dirtyRect = NULL;
1542 return;
1545 static Pixmap magnifyCreatePixmap(WMColorPanel * panel)
1547 W_Screen *scr = WMWidgetScreen(panel->win);
1548 int u, v;
1549 #ifndef USE_XSHAPE
1550 Pixmap pixmap;
1551 #endif
1552 unsigned long color;
1554 if (!panel->magnifyGlass->image)
1555 return None;
1557 if (!panel->magnifyGlass->magPix)
1558 return None;
1561 * Copy an area of only 5x5 pixels from the center of the image.
1563 for (u = 0; u < 5; u++) {
1564 for (v = 0; v < 5; v++) {
1565 color = XGetPixel(panel->magnifyGlass->image, u + 9, v + 9);
1567 XSetForeground(scr->display, scr->copyGC, color);
1569 if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
1570 panel->magnifyGlass->color = ulongToRColor(scr, color);
1572 /* The center square must eventually be centered around the
1573 * hotspot. The image needs shifting to achieve this. The amount of
1574 * shifting is (Cursor_mask_width/2 - 2 * square_size) = 11-10 = 1
1575 * _ _ _ _ _
1576 * |_|_|_|_|_|
1577 * ^------- center of center square == Cursor_x_hot
1579 XFillRectangle(scr->display, panel->magnifyGlass->magPix,
1580 scr->copyGC,
1581 u * 5 + (u == 0 ? 0 : -1), v * 5 + (v == 0 ? 0 : -1),
1582 (u == 0 ? 4 : 5), (v == 0 ? 4 : 5));
1586 #ifdef USE_XSHAPE
1587 return panel->magnifyGlass->magPix;
1588 #else
1589 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width, Cursor_mask_height, scr->depth);
1590 if (!pixmap)
1591 return None;
1593 XPutImage(scr->display, pixmap, scr->copyGC, panel->magnifyGlass->image,
1594 0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
1596 /* Copy the magnified pixmap, with the clip mask, to background pixmap */
1597 XCopyArea(scr->display, panel->magnifyGlass->magPix, pixmap,
1598 scr->clipGC, 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
1599 /* (2,2) puts center pixel on center of glass */
1601 return pixmap;
1602 #endif
1606 static WMView *magnifyCreateView(W_ColorPanel * panel)
1608 W_Screen *scr = WMWidgetScreen(panel->win);
1609 WMView *magView;
1611 magView = W_CreateTopView(scr);
1612 if (!magView)
1613 return NULL;
1615 magView->self = panel->win;
1616 magView->flags.topLevel = 1;
1617 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1618 magView->attribs.override_redirect = True;
1619 magView->attribs.save_under = True;
1621 W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
1623 W_RealizeView(magView);
1625 return magView;
1628 static Cursor magnifyGrabPointer(W_ColorPanel * panel)
1630 W_Screen *scr = WMWidgetScreen(panel->win);
1631 Pixmap magPixmap, magPixmap2;
1632 Cursor magCursor;
1633 XColor fgColor = { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 };
1634 XColor bgColor = { 0, 0xbf00, 0xa000, 0x5000, DoRed | DoGreen | DoBlue, 0 };
1636 /* Cursor creation stuff */
1637 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1638 (char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
1639 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1640 (char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
1642 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1643 &fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
1645 XFreePixmap(scr->display, magPixmap);
1646 XFreePixmap(scr->display, magPixmap2);
1648 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1650 /* Set up Pointer */
1651 XGrabPointer(scr->display, panel->magnifyGlass->view->window, True,
1652 PointerMotionMask | ButtonPressMask,
1653 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1655 return magCursor;
1658 static WMPoint magnifyInitialize(W_ColorPanel * panel)
1660 W_Screen *scr = WMWidgetScreen(panel->win);
1661 int x, y, u, v;
1662 unsigned int mask;
1663 Pixmap pixmap, clip_mask;
1664 WMPoint point;
1665 Window root_return, child_return;
1667 clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1668 (char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1669 1, 0, 1);
1670 panel->magnifyGlass->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
1671 5 * 5 - 1, 5 * 5 - 1, scr->depth);
1673 XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return, &x, &y, &u, &v, &mask);
1675 panel->magnifyGlass->image = NULL;
1677 /* Clipmask to make magnified view-contents circular */
1678 #ifdef USE_XSHAPE
1679 XShapeCombineMask(scr->display, WMViewXID(panel->magnifyGlass->view),
1680 ShapeBounding, 0, 0, clip_mask, ShapeSet);
1681 #else
1682 /* Clip circle in glass cursor */
1683 XSetClipMask(scr->display, scr->clipGC, clip_mask);
1684 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1685 #endif
1687 XFreePixmap(scr->display, clip_mask);
1689 /* Draw initial magnifying glass contents */
1690 magnifyGetImageStored(panel, x, y, x, y);
1692 pixmap = magnifyCreatePixmap(panel);
1693 XSetWindowBackgroundPixmap(scr->display, WMViewXID(panel->magnifyGlass->view), pixmap);
1694 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1695 XFlush(scr->display);
1697 #ifndef USE_XSHAPE
1698 XFreePixmap(scr->display, pixmap);
1699 #endif
1701 point.x = x;
1702 point.y = y;
1704 return point;
1707 static void magnifyPutCursor(WMWidget * w, void *data)
1709 W_ColorPanel *panel = (W_ColorPanel *) (data);
1710 W_Screen *scr = WMWidgetScreen(panel->win);
1711 Cursor magCursor;
1712 Pixmap pixmap;
1713 XEvent event;
1714 WMPoint initialPosition;
1716 /* Parameter not used, but tell the compiler that it is ok */
1717 (void) w;
1719 /* Destroy wheelBackImg, so it'll update properly */
1720 if (panel->selectionBackImg) {
1721 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1722 panel->selectionBackImg = None;
1725 /* Create magnifying glass */
1726 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1727 panel->magnifyGlass->view = magnifyCreateView(panel);
1728 if (!panel->magnifyGlass->view)
1729 return;
1731 initialPosition = magnifyInitialize(panel);
1732 panel->magnifyGlass->x = initialPosition.x;
1733 panel->magnifyGlass->y = initialPosition.y;
1735 W_MoveView(panel->magnifyGlass->view,
1736 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1737 W_MapView(panel->magnifyGlass->view);
1739 magCursor = magnifyGrabPointer(panel);
1741 while (panel->magnifyGlass->image) {
1742 WMNextEvent(scr->display, &event);
1744 /* Pack motion events */
1745 while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
1748 switch (event.type) {
1749 case ButtonPress:
1750 XDestroyImage(panel->magnifyGlass->image);
1751 panel->magnifyGlass->image = NULL;
1753 if (event.xbutton.button == Button1) {
1754 panel->color.rgb = panel->magnifyGlass->color;
1755 panel->color.set = cpRGB;
1756 updateSwatch(panel, panel->color);
1758 switch (panel->mode) {
1759 case WMWheelModeColorPanel:
1760 wheelInit(panel);
1761 wheelRender(panel);
1762 wheelPaint(panel);
1763 break;
1764 case WMGrayModeColorPanel:
1765 grayInit(panel);
1766 break;
1767 case WMRGBModeColorPanel:
1768 rgbInit(panel);
1769 break;
1770 case WMCMYKModeColorPanel:
1771 cmykInit(panel);
1772 break;
1773 case WMHSBModeColorPanel:
1774 hsbInit(panel);
1775 break;
1776 default:
1777 break;
1779 panel->lastChanged = panel->mode;
1781 WMSetButtonSelected(panel->magnifyBtn, False);
1782 break;
1784 case MotionNotify:
1785 while (XPending(event.xmotion.display)) {
1786 XEvent ev;
1787 XPeekEvent(event.xmotion.display, &ev);
1788 if (ev.type == MotionNotify)
1789 XNextEvent(event.xmotion.display, &event);
1790 else
1791 break;
1794 /* Get a "dirty rectangle" */
1795 magnifyGetImageStored(panel,
1796 panel->magnifyGlass->x, panel->magnifyGlass->y,
1797 event.xmotion.x_root, event.xmotion.y_root);
1799 /* Update coordinates */
1800 panel->magnifyGlass->x = event.xmotion.x_root;
1801 panel->magnifyGlass->y = event.xmotion.y_root;
1803 /* Move view */
1804 W_MoveView(panel->magnifyGlass->view,
1805 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1807 /* Put new image (with magn.) in view */
1808 pixmap = magnifyCreatePixmap(panel);
1809 if (pixmap != None) {
1810 /* Change the window background */
1811 XSetWindowBackgroundPixmap(scr->display,
1812 WMViewXID(panel->magnifyGlass->view), pixmap);
1813 /* Force an Expose (handled by X) */
1814 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1815 /* Synchronize the event queue, so the Expose is handled NOW */
1816 XFlush(scr->display);
1817 #ifndef USE_XSHAPE
1818 XFreePixmap(scr->display, pixmap);
1819 #endif
1821 break;
1823 /* Try XQueryPointer for this !!! It returns windows that the pointer
1824 * is over. Note: We found this solving the invisible donkey cap bug
1826 #if 0 /* As it is impossible to make this work in all cases,
1827 * we consider it confusing. Therefore we disabled it.
1829 case FocusOut: /* fall through */
1830 case FocusIn:
1832 * Color Panel window (panel->win) lost or received focus.
1833 * We need to update the pixmap in the magnifying glass.
1835 * BUG Doesn't work with focus switches between two windows
1836 * if none of them is the color panel.
1838 XUngrabPointer(scr->display, CurrentTime);
1839 W_UnmapView(panel->magnifyGlass->view);
1841 magnifyInitialize(panel);
1843 W_MapView(panel->magnifyGlass->view);
1844 XGrabPointer(scr->display, panel->magnifyGlass->view->window,
1845 True, PointerMotionMask | ButtonPressMask,
1846 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1847 break;
1848 #endif
1849 default:
1850 WMHandleEvent(&event);
1851 break;
1852 } /* of switch */
1855 XUngrabPointer(scr->display, CurrentTime);
1856 XFreeCursor(scr->display, magCursor);
1858 XFreePixmap(scr->display, panel->magnifyGlass->magPix);
1859 panel->magnifyGlass->magPix = None;
1861 W_UnmapView(panel->magnifyGlass->view);
1862 W_DestroyView(panel->magnifyGlass->view);
1863 panel->magnifyGlass->view = NULL;
1865 wfree(panel->magnifyGlass);
1868 /****************** ColorWheel Functions ************************/
1870 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height)
1872 wheelMatrix *matrix = NULL;
1873 int i;
1875 assert((width > 0) && (height > 0));
1877 matrix = wmalloc(sizeof(wheelMatrix));
1878 matrix->width = width;
1879 matrix->height = height;
1881 for (i = 0; i < 3; i++) {
1882 matrix->data[i] = wmalloc(width * height * sizeof(unsigned char));
1885 return matrix;
1888 static void wheelDestroyMatrix(wheelMatrix * matrix)
1890 int i;
1892 if (!matrix)
1893 return;
1895 for (i = 0; i < 3; i++) {
1896 if (matrix->data[i])
1897 wfree(matrix->data[i]);
1899 wfree(matrix);
1902 static void wheelInitMatrix(W_ColorPanel * panel)
1904 int i;
1905 int x, y;
1906 unsigned char *rp, *gp, *bp;
1907 CPColor cpColor;
1908 long ofs[4];
1909 int xcor, ycor;
1910 unsigned short sat;
1911 int dhue[4];
1912 const int cw_halfsize = (colorWheelSize + 4) / 2,
1913 cw_sqsize = (colorWheelSize + 4) * (colorWheelSize + 4), uchar_shift = getShift(sizeof(unsigned char));
1915 if (!panel->wheelMtrx)
1916 return;
1918 cpColor.hsv.value = 255;
1919 cpColor.set = cpHSV;
1921 ofs[0] = -1;
1922 ofs[1] = -(colorWheelSize + 4);
1924 /* offsets are counterclockwise (in triangles).
1926 * ofs[0] ---->
1927 * _______________________________________
1928 * [1] |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| o
1929 * s |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| f
1930 * f |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| s
1931 * o | | | | | | | | | | | | | | | | | | | | | [3]
1933 * <---- ofs[2]
1934 * ____
1935 * |\ /| <-- triangles
1936 * | \/ |
1937 * | /\ |
1938 * |/__\|
1941 for (y = 0; y < cw_halfsize; y++) {
1942 for (x = y; x < (colorWheelSize + 4 - y); x++) {
1943 /* (xcor, ycor) is (x,y) relative to center of matrix */
1944 xcor = 2 * x - 4 - colorWheelSize;
1945 ycor = 2 * y - 4 - colorWheelSize;
1947 /* RColor.saturation is unsigned char and will wrap after 255 */
1948 sat = rint(255.0 * sqrt(xcor * xcor + ycor * ycor) / colorWheelSize);
1950 cpColor.hsv.saturation = (unsigned char)sat;
1952 ofs[0]++; /* top quarter of matrix */
1953 ofs[1] += colorWheelSize + 4; /* left quarter */
1954 ofs[2] = cw_sqsize - 1 - ofs[0]; /* bottom quarter */
1955 ofs[3] = cw_sqsize - 1 - ofs[1]; /* right quarter */
1957 if (sat < 256) {
1958 if (xcor != 0)
1959 dhue[0] = rint(atan((double)ycor / (double)xcor) *
1960 (180.0 / M_PI)) + (xcor < 0 ? 180.0 : 0.0);
1961 else
1962 dhue[0] = 270;
1964 dhue[0] = 360 - dhue[0]; /* Reverse direction of ColorWheel */
1965 dhue[1] = 270 - dhue[0] + (dhue[0] > 270 ? 360 : 0);
1966 dhue[2] = dhue[0] - 180 + (dhue[0] < 180 ? 360 : 0);
1967 dhue[3] = 90 - dhue[0] + (dhue[0] > 90 ? 360 : 0);
1969 for (i = 0; i < 4; i++) {
1970 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1971 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1972 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1974 cpColor.hsv.hue = dhue[i];
1975 convertCPColor(&cpColor);
1977 *rp = (unsigned char)(cpColor.rgb.red);
1978 *gp = (unsigned char)(cpColor.rgb.green);
1979 *bp = (unsigned char)(cpColor.rgb.blue);
1981 } else {
1982 for (i = 0; i < 4; i++) {
1983 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1984 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1985 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1987 *rp = (unsigned char)0;
1988 *gp = (unsigned char)0;
1989 *bp = (unsigned char)0;
1994 ofs[0] += 2 * y + 1;
1995 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2 * y);
1999 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue)
2001 unsigned int i;
2002 unsigned int v;
2004 for (i = 0; i < 256; i++) {
2005 /* We divide by 128 in advance, and check whether that number divides
2006 * by 2 properly. If not, we add one to round the number correctly
2008 v = (i * maxvalue) >> 7;
2009 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + (v & 0x01));
2013 static void wheelRender(W_ColorPanel * panel)
2015 W_Screen *scr = WMWidgetScreen(panel->win);
2016 int x, y;
2017 RImage *image;
2018 unsigned char *ptr;
2019 RColor gray;
2020 unsigned long ofs = 0;
2021 /*unsigned char shift = getShift(sizeof(unsigned char)); */
2023 image = RCreateImage(colorWheelSize + 4, colorWheelSize + 4, True);
2024 if (!image) {
2025 wwarning(_("Color Panel: Could not allocate memory"));
2026 return;
2029 ptr = image->data;
2031 /* TODO Make this transparent istead of gray */
2032 gray.red = gray.blue = 0xae;
2033 gray.green = 0xaa;
2035 for (y = 0; y < colorWheelSize + 4; y++) {
2036 for (x = 0; x < colorWheelSize + 4; x++) {
2037 if (wheelInsideColorWheel(panel, ofs)) {
2038 *(ptr++) =
2039 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]]);
2040 *(ptr++) =
2041 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]]);
2042 *(ptr++) =
2043 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]]);
2044 *(ptr++) = 0;
2045 } else {
2046 *(ptr++) = (unsigned char)(gray.red);
2047 *(ptr++) = (unsigned char)(gray.green);
2048 *(ptr++) = (unsigned char)(gray.blue);
2049 *(ptr++) = 255;
2051 ofs++;
2055 if (panel->wheelImg)
2056 XFreePixmap(scr->display, panel->wheelImg);
2058 RConvertImage(scr->rcontext, image, &panel->wheelImg);
2059 RReleaseImage(image);
2061 /* Check if backimage exists. If it doesn't, allocate and fill it */
2062 if (!panel->selectionBackImg) {
2063 panel->selectionBackImg = XCreatePixmap(scr->display,
2064 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
2065 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2066 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2067 /* -2 is hot spot correction */
2071 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs)
2073 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
2074 (panel->wheelMtrx->data[1][ofs] != 0) && (panel->wheelMtrx->data[2][ofs] != 0));
2077 static void wheelPaint(W_ColorPanel * panel)
2079 W_Screen *scr = WMWidgetScreen(panel->win);
2081 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
2082 scr->copyGC, 0, 0, colorWheelSize + 4, colorWheelSize + 4, 0, 0);
2084 /* Draw selection image */
2085 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2086 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2089 static void wheelHandleEvents(XEvent * event, void *data)
2091 W_ColorPanel *panel = (W_ColorPanel *) data;
2093 switch (event->type) {
2094 case Expose:
2095 if (event->xexpose.count != 0) /* TODO Improve */
2096 break;
2097 wheelPaint(panel);
2098 break;
2102 static void wheelHandleActionEvents(XEvent * event, void *data)
2104 W_ColorPanel *panel = (W_ColorPanel *) data;
2106 switch (event->type) {
2107 case ButtonPress:
2108 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) == COLORWHEEL_PART) {
2110 panel->lastChanged = WMWheelModeColorPanel;
2111 panel->flags.dragging = 1;
2113 wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
2115 break;
2117 case ButtonRelease:
2118 panel->flags.dragging = 0;
2119 if (!panel->flags.continuous) {
2120 if (panel->action)
2121 (*panel->action) (panel, panel->clientData);
2123 break;
2125 case MotionNotify:
2126 if (panel->flags.dragging) {
2127 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) == COLORWHEEL_PART) {
2128 wheelPositionSelection(panel, event->xmotion.x, event->xmotion.y);
2129 } else
2130 wheelPositionSelectionOutBounds(panel, event->xmotion.x, event->xmotion.y);
2132 break;
2136 static int getPickerPart(W_ColorPanel * panel, int x, int y)
2138 int lx, ly;
2139 unsigned long ofs;
2141 lx = x;
2142 ly = y;
2144 if (panel->mode == WMWheelModeColorPanel) {
2145 if ((lx >= 2) && (lx <= 2 + colorWheelSize) && (ly >= 2) && (ly <= 2 + colorWheelSize)) {
2147 ofs = ly * panel->wheelMtrx->width + lx;
2149 if (wheelInsideColorWheel(panel, ofs))
2150 return COLORWHEEL_PART;
2154 if (panel->mode == WMCustomPaletteModeColorPanel) {
2155 if ((lx >= 2) && (lx < customPaletteWidth - 2) && (ly >= 2) && (ly < customPaletteHeight - 2)) {
2156 return CUSTOMPALETTE_PART;
2160 return 0;
2163 static void wheelBrightnessSliderCallback(WMWidget * w, void *data)
2165 int value;
2167 W_ColorPanel *panel = (W_ColorPanel *) data;
2169 /* Parameter not used, but tell the compiler that it is ok */
2170 (void) w;
2172 value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2174 wheelCalculateValues(panel, value);
2176 if (panel->color.set == cpRGB) {
2177 convertCPColor(&panel->color);
2178 panel->color.set = cpHSV;
2181 panel->color.hsv.value = value;
2183 wheelRender(panel);
2184 wheelPaint(panel);
2185 wheelUpdateSelection(panel);
2188 static void wheelUpdateSelection(W_ColorPanel * panel)
2190 W_Screen *scr = WMWidgetScreen(panel->win);
2192 updateSwatch(panel, panel->color);
2193 panel->lastChanged = WMWheelModeColorPanel;
2195 /* Redraw color selector (and make a backup of the part it will cover) */
2196 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2197 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2198 /* "-2" is correction for hotspot location */
2199 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2200 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2201 /* see above */
2204 static void wheelUndrawSelection(W_ColorPanel * panel)
2206 W_Screen *scr = WMWidgetScreen(panel->win);
2208 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
2209 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2210 /* see above */
2213 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y)
2215 unsigned long ofs = (y * panel->wheelMtrx->width) + x;
2217 panel->color.rgb.red = panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]];
2219 panel->color.rgb.green = panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]];
2221 panel->color.rgb.blue = panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]];
2222 panel->color.set = cpRGB;
2224 wheelUndrawSelection(panel);
2226 panel->colx = x;
2227 panel->coly = y;
2229 wheelUpdateSelection(panel);
2230 wheelUpdateBrightnessGradientFromLocation(panel);
2233 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2235 int hue;
2236 int xcor, ycor;
2237 CPColor cpColor;
2239 xcor = x * 2 - colorWheelSize - 4;
2240 ycor = y * 2 - colorWheelSize - 4;
2242 panel->color.hsv.saturation = 255;
2243 panel->color.hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2245 if (xcor != 0)
2246 hue = rint(atan(-(double)ycor / (double)xcor) * (180.0 / M_PI));
2247 else {
2248 if (ycor < 0)
2249 hue = 90;
2250 else
2251 hue = 270;
2254 if (xcor < 0)
2255 hue += 180;
2257 if ((xcor > 0) && (ycor > 0))
2258 hue += 360;
2260 panel->color.hsv.hue = hue;
2261 panel->color.set = cpHSV;
2262 convertCPColor(&panel->color);
2264 wheelUndrawSelection(panel);
2266 panel->colx = 2 + rint((colorWheelSize * (1.0 + cos(panel->color.hsv.hue * (M_PI / 180.0)))) / 2.0);
2267 /* "+2" because of "colorWheelSize + 4" */
2268 panel->coly = 2 + rint((colorWheelSize * (1.0 + sin(-panel->color.hsv.hue * (M_PI / 180.0)))) / 2.0);
2270 wheelUpdateSelection(panel);
2271 cpColor = panel->color;
2272 wheelUpdateBrightnessGradient(panel, cpColor);
2275 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel)
2277 CPColor from;
2278 unsigned long ofs;
2280 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2282 from.rgb.red = panel->wheelMtrx->data[0][ofs];
2283 from.rgb.green = panel->wheelMtrx->data[1][ofs];
2284 from.rgb.blue = panel->wheelMtrx->data[2][ofs];
2285 from.set = cpRGB;
2287 wheelUpdateBrightnessGradient(panel, from);
2290 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor)
2292 RColor to;
2293 RImage *sliderImg;
2294 WMPixmap *sliderPxmp;
2296 to.red = to.green = to.blue = 0;
2298 if (topColor.set == cpHSV)
2299 convertCPColor(&topColor);
2301 sliderImg = RRenderGradient(16, 153, &(topColor.rgb), &to, RGRD_VERTICAL);
2302 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win), sliderImg, 0);
2303 RReleaseImage(sliderImg);
2304 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
2305 WMReleasePixmap(sliderPxmp);
2308 /****************** Grayscale Panel Functions ***************/
2310 static void grayBrightnessSliderCallback(WMWidget * w, void *data)
2312 CPColor cpColor;
2313 int value;
2314 char tmp[4];
2315 W_ColorPanel *panel = (W_ColorPanel *) data;
2317 /* Parameter not used, but tell the compiler that it is ok */
2318 (void) w;
2320 value = WMGetSliderValue(panel->grayBrightnessS);
2322 sprintf(tmp, "%d", value);
2324 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2325 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint(2.55 * value);
2326 cpColor.set = cpRGB;
2328 updateSwatch(panel, cpColor);
2329 panel->lastChanged = WMGrayModeColorPanel;
2332 static void grayPresetButtonCallback(WMWidget * w, void *data)
2334 CPColor cpColor;
2335 char tmp[4];
2336 int value;
2337 int i = 0;
2338 W_ColorPanel *panel = (W_ColorPanel *) data;
2340 while (i < 7) {
2341 if (w == panel->grayPresetBtn[i])
2342 break;
2343 i++;
2346 value = rint((100.0 * i) / 6.0);
2347 sprintf(tmp, "%d", value);
2349 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2350 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * i) / 6.0);
2351 cpColor.set = cpRGB;
2353 WMSetSliderValue(panel->grayBrightnessS, rint((100.0 * i) / 6.0));
2355 updateSwatch(panel, cpColor);
2356 panel->lastChanged = WMGrayModeColorPanel;
2359 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification)
2361 CPColor cpColor;
2362 char tmp[4];
2363 int value;
2364 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2366 /* Parameter not used, but tell the compiler that it is ok */
2367 (void) notification;
2369 value = get_textfield_as_integer(panel->grayBrightnessT);
2370 if (value > 100)
2371 value = 100;
2372 if (value < 0)
2373 value = 0;
2375 sprintf(tmp, "%d", value);
2376 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2377 WMSetSliderValue(panel->grayBrightnessS, value);
2379 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * value) / 100.0);
2380 cpColor.set = cpRGB;
2382 updateSwatch(panel, cpColor);
2383 panel->lastChanged = WMGrayModeColorPanel;
2386 /******************* RGB Panel Functions *****************/
2388 void rgbIntToChar(W_ColorPanel *panel, int *value)
2390 char tmp[4];
2391 const char *format;
2393 switch (panel->rgbState) {
2394 case RGBdec:
2395 format = "%d";
2396 break;
2397 case RGBhex:
2398 format = "%0X";
2399 break;
2402 sprintf(tmp, format, value[0]);
2403 WMSetTextFieldText(panel->rgbRedT, tmp);
2404 sprintf(tmp, format, value[1]);
2405 WMSetTextFieldText(panel->rgbGreenT, tmp);
2406 sprintf(tmp, format, value[2]);
2407 WMSetTextFieldText(panel->rgbBlueT, tmp);
2410 int *rgbCharToInt(W_ColorPanel *panel)
2412 int base = 0;
2413 static int value[3];
2414 char *str;
2416 switch (panel->rgbState) {
2417 case RGBdec:
2418 base = 10;
2419 break;
2420 case RGBhex:
2421 base = 16;
2422 break;
2425 str = WMGetTextFieldText(panel->rgbRedT);
2426 value[0] = strtol(str, NULL, base);
2427 wfree(str);
2429 str = WMGetTextFieldText(panel->rgbGreenT);
2430 value[1] = strtol(str, NULL, base);
2431 wfree(str);
2433 str = WMGetTextFieldText(panel->rgbBlueT);
2434 value[2] = strtol(str, NULL, base);
2435 wfree(str);
2437 return value;
2440 static void rgbSliderCallback(WMWidget * w, void *data)
2442 CPColor cpColor;
2443 int value[3];
2444 W_ColorPanel *panel = (W_ColorPanel *) data;
2446 /* Parameter not used, but tell the compiler that it is ok */
2447 (void) w;
2449 value[0] = WMGetSliderValue(panel->rgbRedS);
2450 value[1] = WMGetSliderValue(panel->rgbGreenS);
2451 value[2] = WMGetSliderValue(panel->rgbBlueS);
2453 rgbIntToChar(panel, value);
2455 cpColor.rgb.red = value[0];
2456 cpColor.rgb.green = value[1];
2457 cpColor.rgb.blue = value[2];
2458 cpColor.set = cpRGB;
2460 updateSwatch(panel, cpColor);
2461 panel->lastChanged = WMRGBModeColorPanel;
2464 static void rgbTextFieldCallback(void *observerData, WMNotification * notification)
2466 CPColor cpColor;
2467 int *value;
2468 int n;
2469 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2471 /* Parameter not used, but tell the compiler that it is ok */
2472 (void) notification;
2474 value = rgbCharToInt(panel);
2476 for (n = 0; n < 3; n++) {
2477 if (value[n] > 255)
2478 value[n] = 255;
2479 if (value[n] < 0)
2480 value[n] = 0;
2483 rgbIntToChar(panel, value);
2485 WMSetSliderValue(panel->rgbRedS, value[0]);
2486 WMSetSliderValue(panel->rgbGreenS, value[1]);
2487 WMSetSliderValue(panel->rgbBlueS, value[2]);
2489 cpColor.rgb.red = value[0];
2490 cpColor.rgb.green = value[1];
2491 cpColor.rgb.blue = value[2];
2492 cpColor.set = cpRGB;
2494 updateSwatch(panel, cpColor);
2495 panel->lastChanged = WMRGBModeColorPanel;
2498 static void rgbDecToHex(WMWidget *w, void *data)
2500 W_ColorPanel *panel = (W_ColorPanel *) data;
2501 int *value;
2503 (void) w;
2505 switch (panel->rgbState) {
2506 case RGBhex:
2507 if (WMGetButtonSelected(panel->rgbDecB)) {
2508 WMSetLabelText(panel->rgbMaxL, "255");
2509 WMRedisplayWidget(panel->rgbMaxL);
2510 value = rgbCharToInt(panel);
2511 panel->rgbState = RGBdec;
2512 rgbIntToChar(panel, value);
2514 break;
2516 case RGBdec:
2517 if (WMGetButtonSelected(panel->rgbHexB)) {
2518 WMSetLabelText(panel->rgbMaxL, "FF");
2519 WMRedisplayWidget(panel->rgbMaxL);
2520 value = rgbCharToInt(panel);
2521 panel->rgbState = RGBhex;
2522 rgbIntToChar(panel, value);
2524 break;
2528 /******************* CMYK Panel Functions *****************/
2530 static void cmykSliderCallback(WMWidget * w, void *data)
2532 CPColor cpColor;
2533 int value[4];
2534 char tmp[4];
2535 W_ColorPanel *panel = (W_ColorPanel *) data;
2536 double scale;
2538 /* Parameter not used, but tell the compiler that it is ok */
2539 (void) w;
2541 value[0] = WMGetSliderValue(panel->cmykCyanS);
2542 value[1] = WMGetSliderValue(panel->cmykMagentaS);
2543 value[2] = WMGetSliderValue(panel->cmykYellowS);
2544 value[3] = WMGetSliderValue(panel->cmykBlackS);
2546 sprintf(tmp, "%d", value[0]);
2547 WMSetTextFieldText(panel->cmykCyanT, tmp);
2548 sprintf(tmp, "%d", value[1]);
2549 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2550 sprintf(tmp, "%d", value[2]);
2551 WMSetTextFieldText(panel->cmykYellowT, tmp);
2552 sprintf(tmp, "%d", value[3]);
2553 WMSetTextFieldText(panel->cmykBlackT, tmp);
2555 scale = 2.55 * (1.0 - (value[3] / 100.0));
2556 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2557 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2558 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2559 cpColor.set = cpRGB;
2561 updateSwatch(panel, cpColor);
2562 panel->lastChanged = WMCMYKModeColorPanel;
2565 static void cmykTextFieldCallback(void *observerData, WMNotification * notification)
2567 CPColor cpColor;
2568 int value[4];
2569 char tmp[4];
2570 int n;
2571 double scale;
2572 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2574 /* Parameter not used, but tell the compiler that it is ok */
2575 (void) notification;
2577 value[0] = get_textfield_as_integer(panel->cmykCyanT);
2578 value[1] = get_textfield_as_integer(panel->cmykMagentaT);
2579 value[2] = get_textfield_as_integer(panel->cmykYellowT);
2580 value[3] = get_textfield_as_integer(panel->cmykBlackT);
2582 for (n = 0; n < 4; n++) {
2583 if (value[n] > 100)
2584 value[n] = 100;
2585 if (value[n] < 0)
2586 value[n] = 0;
2589 sprintf(tmp, "%d", value[0]);
2590 WMSetTextFieldText(panel->cmykCyanT, tmp);
2592 sprintf(tmp, "%d", value[1]);
2593 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2595 sprintf(tmp, "%d", value[2]);
2596 WMSetTextFieldText(panel->cmykYellowT, tmp);
2598 sprintf(tmp, "%d", value[3]);
2599 WMSetTextFieldText(panel->cmykBlackT, tmp);
2601 WMSetSliderValue(panel->cmykCyanS, value[0]);
2602 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2603 WMSetSliderValue(panel->cmykYellowS, value[2]);
2604 WMSetSliderValue(panel->cmykBlackS, value[3]);
2606 scale = 2.55 * (1.0 - (value[3] / 100.0));
2607 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2608 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2609 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2610 cpColor.set = cpRGB;
2612 updateSwatch(panel, cpColor);
2613 panel->lastChanged = WMCMYKModeColorPanel;
2616 /********************** HSB Panel Functions ***********************/
2618 static void hsbSliderCallback(WMWidget * w, void *data)
2620 CPColor cpColor;
2621 int value[3];
2622 char tmp[4];
2623 W_ColorPanel *panel = (W_ColorPanel *) data;
2625 value[0] = WMGetSliderValue(panel->hsbHueS);
2626 value[1] = WMGetSliderValue(panel->hsbSaturationS);
2627 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
2629 sprintf(tmp, "%d", value[0]);
2630 WMSetTextFieldText(panel->hsbHueT, tmp);
2631 sprintf(tmp, "%d", value[1]);
2632 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2633 sprintf(tmp, "%d", value[2]);
2634 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2636 cpColor.hsv.hue = value[0];
2637 cpColor.hsv.saturation = value[1] * 2.55;
2638 cpColor.hsv.value = value[2] * 2.55;
2639 cpColor.set = cpHSV;
2641 convertCPColor(&cpColor);
2643 panel->lastChanged = WMHSBModeColorPanel;
2644 updateSwatch(panel, cpColor);
2646 if (w != panel->hsbBrightnessS)
2647 hsbUpdateBrightnessGradient(panel);
2648 if (w != panel->hsbSaturationS)
2649 hsbUpdateSaturationGradient(panel);
2650 if (w != panel->hsbHueS)
2651 hsbUpdateHueGradient(panel);
2654 static void hsbTextFieldCallback(void *observerData, WMNotification * notification)
2656 CPColor cpColor;
2657 int value[3];
2658 char tmp[4];
2659 int n;
2660 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2662 /* Parameter not used, but tell the compiler that it is ok */
2663 (void) notification;
2665 value[0] = get_textfield_as_integer(panel->hsbHueT);
2666 value[1] = get_textfield_as_integer(panel->hsbSaturationT);
2667 value[2] = get_textfield_as_integer(panel->hsbBrightnessT);
2669 if (value[0] > 359)
2670 value[0] = 359;
2671 if (value[0] < 0)
2672 value[0] = 0;
2674 for (n = 1; n < 3; n++) {
2675 if (value[n] > 100)
2676 value[n] = 100;
2677 if (value[n] < 0)
2678 value[n] = 0;
2681 sprintf(tmp, "%d", value[0]);
2682 WMSetTextFieldText(panel->hsbHueT, tmp);
2683 sprintf(tmp, "%d", value[1]);
2684 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2685 sprintf(tmp, "%d", value[2]);
2686 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2688 WMSetSliderValue(panel->hsbHueS, value[0]);
2689 WMSetSliderValue(panel->hsbSaturationS, value[1]);
2690 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
2692 cpColor.hsv.hue = value[0];
2693 cpColor.hsv.saturation = value[1] * 2.55;
2694 cpColor.hsv.value = value[2] * 2.55;
2695 cpColor.set = cpHSV;
2697 convertCPColor(&cpColor);
2699 panel->lastChanged = WMHSBModeColorPanel;
2700 updateSwatch(panel, cpColor);
2702 hsbUpdateBrightnessGradient(panel);
2703 hsbUpdateSaturationGradient(panel);
2704 hsbUpdateHueGradient(panel);
2707 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel)
2709 W_Screen *scr = WMWidgetScreen(panel->win);
2710 RColor from;
2711 CPColor to;
2712 RImage *sliderImg;
2713 WMPixmap *sliderPxmp;
2715 from.red = from.green = from.blue = 0;
2716 to.hsv = panel->color.hsv;
2717 to.hsv.value = 255;
2718 to.set = cpHSV;
2720 convertCPColor(&to);
2722 sliderImg = RRenderGradient(141, 16, &from, &(to.rgb), RGRD_HORIZONTAL);
2723 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2724 RReleaseImage(sliderImg);
2726 if (sliderPxmp)
2727 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
2728 panel->font12, 2, 0, 100, WALeft, scr->white,
2729 False, _("Brightness"), strlen(_("Brightness")));
2730 else
2731 wwarning(_("Color Panel: Could not allocate memory"));
2733 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
2734 WMReleasePixmap(sliderPxmp);
2737 static void hsbUpdateSaturationGradient(W_ColorPanel * panel)
2739 W_Screen *scr = WMWidgetScreen(panel->win);
2740 CPColor from;
2741 CPColor to;
2742 RImage *sliderImg;
2743 WMPixmap *sliderPxmp;
2745 from.hsv = panel->color.hsv;
2746 from.hsv.saturation = 0;
2747 from.set = cpHSV;
2748 convertCPColor(&from);
2750 to.hsv = panel->color.hsv;
2751 to.hsv.saturation = 255;
2752 to.set = cpHSV;
2753 convertCPColor(&to);
2755 sliderImg = RRenderGradient(141, 16, &(from.rgb), &(to.rgb), RGRD_HORIZONTAL);
2756 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2757 RReleaseImage(sliderImg);
2759 if (sliderPxmp)
2760 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2761 panel->font12, 2, 0, 100, WALeft,
2762 from.hsv.value < 128 ? scr->white : scr->black, False,
2763 _("Saturation"), strlen(_("Saturation")));
2764 else
2765 wwarning(_("Color Panel: Could not allocate memory"));
2767 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
2768 WMReleasePixmap(sliderPxmp);
2771 static void hsbUpdateHueGradient(W_ColorPanel * panel)
2773 W_Screen *scr = WMWidgetScreen(panel->win);
2774 RColor **colors = NULL;
2775 RHSVColor hsvcolor;
2776 RImage *sliderImg;
2777 WMPixmap *sliderPxmp;
2778 int i;
2780 hsvcolor = panel->color.hsv;
2782 colors = wmalloc(sizeof(RColor *) * (8));
2783 for (i = 0; i < 7; i++) {
2784 hsvcolor.hue = (360 * i) / 6;
2785 colors[i] = wmalloc(sizeof(RColor));
2786 RHSVtoRGB(&hsvcolor, colors[i]);
2788 colors[7] = NULL;
2790 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2791 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2792 RReleaseImage(sliderImg);
2794 if (sliderPxmp)
2795 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2796 panel->font12, 2, 0, 100, WALeft,
2797 hsvcolor.value < 128 ? scr->white : scr->black, False, _("Hue"), strlen(_("Hue")));
2798 else
2799 wwarning(_("Color Panel: Could not allocate memory"));
2801 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2802 WMReleasePixmap(sliderPxmp);
2804 for (i = 0; i < 7; i++)
2805 wfree(colors[i]);
2807 wfree(colors);
2810 /*************** Custom Palette Functions ****************/
2812 static void customRenderSpectrum(W_ColorPanel * panel)
2814 RImage *spectrum;
2815 int x, y;
2816 unsigned char *ptr;
2817 CPColor cpColor;
2819 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, False);
2821 ptr = spectrum->data;
2823 for (y = 0; y < SPECTRUM_HEIGHT; y++) {
2824 cpColor.hsv.hue = y;
2825 cpColor.hsv.saturation = 0;
2826 cpColor.hsv.value = 255;
2827 cpColor.set = cpHSV;
2829 for (x = 0; x < SPECTRUM_WIDTH; x++) {
2830 convertCPColor(&cpColor);
2832 *(ptr++) = (unsigned char)cpColor.rgb.red;
2833 *(ptr++) = (unsigned char)cpColor.rgb.green;
2834 *(ptr++) = (unsigned char)cpColor.rgb.blue;
2836 if (x < (SPECTRUM_WIDTH / 2))
2837 cpColor.hsv.saturation++;
2839 if (x > (SPECTRUM_WIDTH / 2))
2840 cpColor.hsv.value--;
2843 if (panel->customPaletteImg) {
2844 RReleaseImage(panel->customPaletteImg);
2845 panel->customPaletteImg = NULL;
2847 panel->customPaletteImg = spectrum;
2850 static void customSetPalette(W_ColorPanel * panel)
2852 W_Screen *scr = WMWidgetScreen(panel->win);
2853 RImage *scaledImg;
2854 Pixmap image;
2856 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth, customPaletteHeight, scr->depth);
2857 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth, customPaletteHeight);
2858 RConvertImage(scr->rcontext, scaledImg, &image);
2859 RReleaseImage(scaledImg);
2861 XCopyArea(scr->display, image, panel->customPaletteContentView->window,
2862 scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2864 /* Check backimage exists. If it doesn't, allocate and fill it */
2865 if (!panel->selectionBackImg) {
2866 panel->selectionBackImg = XCreatePixmap(scr->display,
2867 panel->customPaletteContentView->window, 4, 4, scr->depth);
2870 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
2871 panel->palx - 2, panel->paly - 2, 4, 4, 0, 0);
2872 XCopyArea(scr->display, panel->selectionImg,
2873 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2874 panel->palx - 2, panel->paly - 2);
2875 XFreePixmap(scr->display, image);
2877 panel->palXRatio = (double)(panel->customPaletteImg->width) / (double)(customPaletteWidth);
2878 panel->palYRatio = (double)(panel->customPaletteImg->height) / (double)(customPaletteHeight);
2880 WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
2883 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y)
2885 W_Screen *scr = WMWidgetScreen(panel->win);
2886 unsigned long ofs;
2888 /* undraw selection */
2889 XCopyArea(scr->display, panel->selectionBackImg,
2890 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2891 panel->palx - 2, panel->paly - 2);
2893 panel->palx = x;
2894 panel->paly = y;
2896 ofs = (rint(x * panel->palXRatio) + rint(y * panel->palYRatio) * panel->customPaletteImg->width) * 3;
2898 panel->color.rgb.red = panel->customPaletteImg->data[ofs];
2899 panel->color.rgb.green = panel->customPaletteImg->data[ofs + 1];
2900 panel->color.rgb.blue = panel->customPaletteImg->data[ofs + 2];
2901 panel->color.set = cpRGB;
2903 updateSwatch(panel, panel->color);
2904 panel->lastChanged = WMCustomPaletteModeColorPanel;
2906 /* Redraw color selector (and make a backup of the part it will cover) */
2907 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 */
2908 XCopyArea(scr->display, panel->selectionImg, panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4, panel->palx - 2, panel->paly - 2); /* see above */
2911 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2913 if (x < 2)
2914 x = 2;
2915 if (y < 2)
2916 y = 2;
2917 if (x >= customPaletteWidth)
2918 x = customPaletteWidth - 2;
2919 if (y >= customPaletteHeight)
2920 y = customPaletteHeight - 2;
2922 customPalettePositionSelection(panel, x, y);
2925 static void customPaletteHandleEvents(XEvent * event, void *data)
2927 W_ColorPanel *panel = (W_ColorPanel *) data;
2929 switch (event->type) {
2930 case Expose:
2931 if (event->xexpose.count != 0) /* TODO Improve. */
2932 break;
2933 customSetPalette(panel);
2934 break;
2938 static void customPaletteHandleActionEvents(XEvent * event, void *data)
2940 W_ColorPanel *panel = (W_ColorPanel *) data;
2941 int x, y;
2943 switch (event->type) {
2944 case ButtonPress:
2945 x = event->xbutton.x;
2946 y = event->xbutton.y;
2948 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2949 panel->flags.dragging = 1;
2950 customPalettePositionSelection(panel, x, y);
2952 break;
2954 case ButtonRelease:
2955 panel->flags.dragging = 0;
2956 if (!panel->flags.continuous) {
2957 if (panel->action)
2958 (*panel->action) (panel, panel->clientData);
2960 break;
2962 case MotionNotify:
2963 x = event->xmotion.x;
2964 y = event->xmotion.y;
2966 if (panel->flags.dragging) {
2967 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2968 customPalettePositionSelection(panel, x, y);
2969 } else
2970 customPalettePositionSelectionOutBounds(panel, x, y);
2972 break;
2976 static void customPaletteMenuCallback(WMWidget * w, void *data)
2978 W_ColorPanel *panel = (W_ColorPanel *) data;
2979 int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
2981 /* Parameter not used, but tell the compiler that it is ok */
2982 (void) w;
2984 switch (item) {
2985 case CPmenuNewFromFile:
2986 customPaletteMenuNewFromFile(panel);
2987 break;
2988 case CPmenuRename:
2989 customPaletteMenuRename(panel);
2990 break;
2991 case CPmenuRemove:
2992 customPaletteMenuRemove(panel);
2993 break;
2994 case CPmenuCopy:
2995 break;
2996 case CPmenuNewFromClipboard:
2997 break;
3001 static void customPaletteMenuNewFromFile(W_ColorPanel * panel)
3003 W_Screen *scr = WMWidgetScreen(panel->win);
3004 WMOpenPanel *browseP;
3005 char *filepath;
3006 char *filename = NULL;
3007 char *spath;
3008 char *tmp;
3009 int i;
3010 RImage *tmpImg = NULL;
3012 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir, "\0") == 0))
3013 spath = wexpandpath(wgethomedir());
3014 else
3015 spath = wexpandpath(panel->lastBrowseDir);
3017 browseP = WMGetOpenPanel(scr);
3018 WMSetFilePanelCanChooseDirectories(browseP, 0);
3019 WMSetFilePanelCanChooseFiles(browseP, 1);
3021 /* Get a filename */
3022 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
3023 _("Open Palette"), RSupportedFileFormats())) {
3024 filepath = WMGetFilePanelFileName(browseP);
3026 /* Get seperation position between path and filename */
3027 i = strrchr(filepath, '/') - filepath + 1;
3028 if (i > strlen(filepath))
3029 i = strlen(filepath);
3031 /* Store last browsed path */
3032 if (panel->lastBrowseDir)
3033 wfree(panel->lastBrowseDir);
3034 panel->lastBrowseDir = wmalloc((i + 1) * sizeof(char));
3035 strncpy(panel->lastBrowseDir, filepath, i);
3036 panel->lastBrowseDir[i] = '\0';
3038 /* Get filename from path */
3039 filename = wstrdup(filepath + i);
3041 /* Check for duplicate files, and rename it if there are any */
3042 tmp = wstrconcat(panel->configurationPath, filename);
3043 while (access(tmp, F_OK) == 0) {
3044 char *newName;
3046 wfree(tmp);
3048 newName = generateNewFilename(filename);
3049 wfree(filename);
3050 filename = newName;
3052 tmp = wstrconcat(panel->configurationPath, filename);
3054 wfree(tmp);
3056 /* Copy image to $(gnustepdir)/Library/Colors/ &
3057 * Add filename to history menu */
3058 if (wcopy_file(panel->configurationPath, filepath, filename) == 0) {
3060 /* filepath is a "local" path now the file has been copied */
3061 wfree(filepath);
3062 filepath = wstrconcat(panel->configurationPath, filename);
3064 /* load the image & add menu entries */
3065 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
3066 if (tmpImg) {
3067 if (panel->customPaletteImg)
3068 RReleaseImage(panel->customPaletteImg);
3069 panel->customPaletteImg = tmpImg;
3071 customSetPalette(panel);
3072 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
3074 panel->currentPalette =
3075 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1;
3077 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3078 panel->currentPalette);
3080 } else {
3081 tmp = wstrconcat(panel->configurationPath, filename);
3083 i = remove(tmp); /* Delete the file, it doesn't belong here */
3084 WMRunAlertPanel(scr, panel->win, _("File Error"),
3085 _("Invalid file format !"), _("OK"), NULL, NULL);
3086 if (i != 0) {
3087 werror(_("can't remove file %s"), tmp);
3088 WMRunAlertPanel(scr, panel->win, _("File Error"),
3089 _("Couldn't remove file from Configuration Directory !"),
3090 _("OK"), NULL, NULL);
3092 wfree(tmp);
3094 wfree(filepath);
3095 wfree(filename);
3097 WMFreeFilePanel(browseP);
3099 wfree(spath);
3102 static void customPaletteMenuRename(W_ColorPanel * panel)
3104 W_Screen *scr = WMWidgetScreen(panel->win);
3105 char *toName = NULL;
3106 char *fromName;
3107 char *toPath, *fromPath;
3108 int item;
3109 int index;
3111 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3112 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
3114 toName = WMRunInputPanel(scr, panel->win, _("Rename"), _("Rename palette to:"),
3115 fromName, _("OK"), _("Cancel"));
3117 if (toName) {
3119 /* As some people do certain stupid things... */
3120 if (strcmp(toName, fromName) == 0) {
3121 wfree(toName);
3122 return;
3125 /* For normal people */
3126 fromPath = wstrconcat(panel->configurationPath, fromName);
3127 toPath = wstrconcat(panel->configurationPath, toName);
3129 if (access(toPath, F_OK) == 0) {
3130 /* Careful, this palette exists already */
3131 if (WMRunAlertPanel(scr, panel->win, _("Warning"),
3132 _("Palette already exists !\n\nOverwrite ?"), _("No"), _("Yes"),
3133 NULL) == 1) {
3134 /* "No" = 0, "Yes" = 1 */
3135 int items = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
3137 remove(toPath);
3139 /* Remove from History list too */
3140 index = 1;
3141 while ((index < items)
3143 (strcmp(WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, index), toName)
3144 != 0))
3145 index++;
3147 if (index < items) {
3148 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, index);
3149 if (index < item)
3150 item--;
3153 } else {
3154 wfree(fromPath);
3155 wfree(toName);
3156 wfree(toPath);
3158 return;
3162 if (rename(fromPath, toPath) != 0)
3163 werror(_("Couldn't rename palette %s to %s"), fromName, toName);
3164 else {
3165 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3166 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item, toName);
3168 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
3170 wfree(fromPath);
3171 wfree(toPath);
3172 wfree(toName);
3176 static void customPaletteMenuRemove(W_ColorPanel * panel)
3178 W_Screen *scr = WMWidgetScreen(panel->win);
3179 char *text;
3180 char *tmp;
3181 int choice;
3182 int item;
3184 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3186 tmp = wstrconcat(_("This will permanently remove the palette "),
3187 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3188 text = wstrconcat(tmp, _(".\n\nAre you sure you want to remove this palette ?"));
3189 wfree(tmp);
3191 choice = WMRunAlertPanel(scr, panel->win, _("Remove"), text, _("Yes"), _("No"), NULL);
3192 /* returns 0 (= "Yes") or 1 (="No") */
3193 wfree(text);
3195 if (choice == 0) {
3197 tmp = wstrconcat(panel->configurationPath,
3198 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3200 if (remove(tmp) == 0) {
3201 /* item-1 always exists */
3202 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3204 customPaletteHistoryCallback(panel->customPaletteHistoryBtn, panel);
3205 customSetPalette(panel);
3207 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3209 } else {
3210 werror(_("Couldn't remove palette %s"), tmp);
3213 wfree(tmp);
3217 static void customPaletteHistoryCallback(WMWidget * w, void *data)
3219 W_ColorPanel *panel = (W_ColorPanel *) data;
3220 W_Screen *scr = WMWidgetScreen(panel->win);
3221 int item;
3222 char *filename;
3223 RImage *tmp = NULL;
3224 unsigned char perm_mask;
3226 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3227 if (item == panel->currentPalette)
3228 return;
3230 if (item == 0) {
3231 customRenderSpectrum(panel);
3233 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, False);
3234 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, False);
3235 } else {
3236 /* Load file from configpath */
3237 filename = wstrconcat(panel->configurationPath,
3238 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3240 /* If the file corresponding to the item does not exist,
3241 * remove it from the history list and select the next one.
3243 perm_mask = (access(filename, F_OK) == 0);
3244 if (!perm_mask) {
3245 /* File does not exist */
3246 wfree(filename);
3247 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3248 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3249 customPaletteHistoryCallback(w, data);
3250 return;
3253 /* Get the image */
3254 tmp = RLoadImage(scr->rcontext, filename, 0);
3255 if (tmp) {
3256 if (panel->customPaletteImg) {
3257 RReleaseImage(panel->customPaletteImg);
3258 panel->customPaletteImg = NULL;
3260 panel->customPaletteImg = tmp;
3263 /* If the image is not writable, don't allow removing/renaming */
3264 perm_mask = (access(filename, W_OK) == 0);
3265 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, perm_mask);
3266 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, perm_mask);
3268 wfree(filename);
3270 customSetPalette(panel);
3272 panel->currentPalette = item;
3275 /************************* ColorList Panel Functions **********************/
3277 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect)
3279 WMScreen *scr = WMWidgetScreen(lPtr);
3280 Display *dpy = WMScreenDisplay(scr);
3281 WMView *view = W_VIEW(lPtr);
3282 RColor *color = (RColor *) WMGetListItem(lPtr, index)->clientData;
3283 W_ColorPanel *panel = WMGetHangedData(lPtr);
3284 int width, height, x, y;
3285 WMColor *fillColor;
3287 width = rect->size.width;
3288 height = rect->size.height;
3289 x = rect->pos.x;
3290 y = rect->pos.y;
3292 if (state & WLDSSelected)
3293 XFillRectangle(dpy, d, WMColorGC(scr->white), x, y, width, height);
3294 else
3295 XFillRectangle(dpy, d, WMColorGC(view->backColor), x, y, width, height);
3297 fillColor = WMCreateRGBColor(scr, color->red << 8, color->green << 8, color->blue << 8, True);
3299 XFillRectangle(dpy, d, WMColorGC(fillColor), x, y, 15, height);
3300 WMReleaseColor(fillColor);
3302 WMDrawString(scr, d, scr->black, panel->font12, x + 18, y, text, strlen(text));
3305 static void colorListSelect(WMWidget * w, void *data)
3307 W_ColorPanel *panel = (W_ColorPanel *) data;
3308 CPColor cpColor;
3310 cpColor.rgb = *((RColor *) WMGetListSelectedItem(w)->clientData);
3311 cpColor.set = cpRGB;
3313 panel->lastChanged = WMColorListModeColorPanel;
3314 updateSwatch(panel, cpColor);
3317 static void colorListColorMenuCallback(WMWidget * w, void *data)
3319 W_ColorPanel *panel = (W_ColorPanel *) data;
3320 int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
3322 /* Parameter not used, but tell the compiler that it is ok */
3323 (void) w;
3325 switch (item) {
3326 case CLmenuAdd:
3327 break;
3328 case CLmenuRename:
3329 break;
3330 case CLmenuRemove:
3331 break;
3335 static void colorListListMenuCallback(WMWidget * w, void *data)
3337 W_ColorPanel *panel = (W_ColorPanel *) data;
3338 int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
3340 /* Parameter not used, but tell the compiler that it is ok */
3341 (void) w;
3343 switch (item) {
3344 case CLmenuAdd:
3345 break;
3346 case CLmenuRename:
3347 break;
3348 case CLmenuRemove:
3349 break;
3353 /*************** Panel Initialisation Functions *****************/
3355 static void wheelInit(W_ColorPanel * panel)
3357 CPColor cpColor;
3359 if (panel->color.set != cpHSV)
3360 convertCPColor(&panel->color);
3362 WMSetSliderValue(panel->wheelBrightnessS, 255 - panel->color.hsv.value);
3364 panel->colx = 2 + rint((colorWheelSize / 2.0) *
3365 (1 + (panel->color.hsv.saturation / 255.0) *
3366 cos(panel->color.hsv.hue * M_PI / 180.0)));
3367 panel->coly = 2 + rint((colorWheelSize / 2.0) *
3368 (1 + (panel->color.hsv.saturation / 255.0) *
3369 sin(-panel->color.hsv.hue * M_PI / 180.0)));
3371 wheelCalculateValues(panel, panel->color.hsv.value);
3373 cpColor = panel->color;
3374 cpColor.hsv.value = 255;
3375 cpColor.set = cpHSV;
3376 wheelUpdateBrightnessGradient(panel, cpColor);
3379 static void grayInit(W_ColorPanel * panel)
3381 int value;
3382 char tmp[4];
3384 if (panel->color.set != cpHSV)
3385 convertCPColor(&panel->color);
3387 value = rint(panel->color.hsv.value / 2.55);
3388 WMSetSliderValue(panel->grayBrightnessS, value);
3390 sprintf(tmp, "%d", value);
3391 WMSetTextFieldText(panel->grayBrightnessT, tmp);
3394 static void rgbInit(W_ColorPanel * panel)
3396 char tmp[4];
3398 if (panel->color.set != cpRGB)
3399 convertCPColor(&panel->color);
3401 WMSetSliderValue(panel->rgbRedS, panel->color.rgb.red);
3402 WMSetSliderValue(panel->rgbGreenS, panel->color.rgb.green);
3403 WMSetSliderValue(panel->rgbBlueS, panel->color.rgb.blue);
3405 sprintf(tmp, "%d", panel->color.rgb.red);
3406 WMSetTextFieldText(panel->rgbRedT, tmp);
3407 sprintf(tmp, "%d", panel->color.rgb.green);
3408 WMSetTextFieldText(panel->rgbGreenT, tmp);
3409 sprintf(tmp, "%d", panel->color.rgb.blue);
3410 WMSetTextFieldText(panel->rgbBlueT, tmp);
3413 static void cmykInit(W_ColorPanel * panel)
3415 int value[3];
3416 char tmp[4];
3418 if (panel->color.set != cpRGB)
3419 convertCPColor(&panel->color);
3421 value[0] = rint((255 - panel->color.rgb.red) / 2.55);
3422 value[1] = rint((255 - panel->color.rgb.green) / 2.55);
3423 value[2] = rint((255 - panel->color.rgb.blue) / 2.55);
3425 WMSetSliderValue(panel->cmykCyanS, value[0]);
3426 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3427 WMSetSliderValue(panel->cmykYellowS, value[2]);
3428 WMSetSliderValue(panel->cmykBlackS, 0);
3430 sprintf(tmp, "%d", value[0]);
3431 WMSetTextFieldText(panel->cmykCyanT, tmp);
3432 sprintf(tmp, "%d", value[1]);
3433 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3434 sprintf(tmp, "%d", value[2]);
3435 WMSetTextFieldText(panel->cmykYellowT, tmp);
3436 WMSetTextFieldText(panel->cmykBlackT, "0");
3439 static void hsbInit(W_ColorPanel * panel)
3441 int value[3];
3442 char tmp[4];
3444 if (panel->color.set != cpHSV)
3445 convertCPColor(&panel->color);
3447 value[0] = panel->color.hsv.hue;
3448 value[1] = rint(panel->color.hsv.saturation / 2.55);
3449 value[2] = rint(panel->color.hsv.value / 2.55);
3451 WMSetSliderValue(panel->hsbHueS, value[0]);
3452 WMSetSliderValue(panel->hsbSaturationS, value[1]);
3453 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
3455 sprintf(tmp, "%d", value[0]);
3456 WMSetTextFieldText(panel->hsbHueT, tmp);
3457 sprintf(tmp, "%d", value[1]);
3458 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3459 sprintf(tmp, "%d", value[2]);
3460 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3462 hsbUpdateBrightnessGradient(panel);
3463 hsbUpdateSaturationGradient(panel);
3464 hsbUpdateHueGradient(panel);
3467 /************************** Common utility functions ************************/
3469 static char *generateNewFilename(const char *curName)
3471 int n;
3472 char c;
3473 int baseLen;
3474 const char *ptr;
3475 char *newName;
3477 assert(curName);
3479 ptr = curName;
3481 if (((ptr = strrchr(ptr, '{')) == 0) || sscanf(ptr, "{%i}%c", &n, &c) != 1)
3482 return wstrconcat(curName, " {1}");
3484 baseLen = ptr - curName - 1;
3486 newName = wmalloc(baseLen + 16);
3487 strncpy(newName, curName, baseLen);
3489 snprintf(&newName[baseLen], 16, " {%i}", n + 1);
3491 return newName;
3494 static void convertCPColor(CPColor * color)
3496 unsigned short old_hue = 0;
3498 switch (color->set) {
3499 case cpNone:
3500 wwarning(_("Color Panel: Color unspecified"));
3501 return;
3502 case cpRGB:
3503 old_hue = color->hsv.hue;
3504 RRGBtoHSV(&(color->rgb), &(color->hsv));
3506 /* In black the hue is undefined, and may change by conversion
3507 * Same for white. */
3508 if (((color->rgb.red == 0) &&
3509 (color->rgb.green == 0) &&
3510 (color->rgb.blue == 0)) ||
3511 ((color->rgb.red == 0) && (color->rgb.green == 0) && (color->rgb.blue == 255))
3513 color->hsv.hue = old_hue;
3514 break;
3515 case cpHSV:
3516 RHSVtoRGB(&(color->hsv), &(color->rgb));
3517 break;
3521 #define ABS_SHIFT(val, shift) \
3522 (((shift) > 0) ? (val) >> (shift) : (val) << -(shift))
3524 static RColor ulongToRColor(WMScreen * scr, unsigned long value)
3526 RColor color;
3527 XColor *xcolor = NULL;
3529 xcolor = wmalloc(sizeof(XColor));
3530 xcolor->pixel = value;
3531 XQueryColor(scr->display, scr->rcontext->cmap, xcolor);
3533 color.red = xcolor->red >> 8;
3534 color.green = xcolor->green >> 8;
3535 color.blue = xcolor->blue >> 8;
3536 color.alpha = 0;
3538 wfree(xcolor);
3540 return color;
3543 static unsigned char getShift(unsigned char value)
3545 unsigned char i = -1;
3547 if (value == 0)
3548 return 0;
3550 while (value) {
3551 value >>= 1;
3552 i++;
3555 return i;