WINGs: changed use of 'if' on panel->rgbState into a switch
[wmaker-crm.git] / WINGs / wcolorpanel.c
blob579fded7111b366b6dccad70ddb6d264366e70d6
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);
357 void WMSetColorPanelAction(WMColorPanel * panel, WMAction2 * action, void *data)
359 panel->action = action;
360 panel->clientData = data;
363 static WMColorPanel *makeColorPanel(WMScreen * scrPtr, const char *name)
365 WMColorPanel *panel;
366 RImage *image;
367 WMPixmap *pixmap;
368 RColor from;
369 RColor to;
370 WMColor *textcolor, *graybuttoncolor;
371 int i;
372 GC bgc = WMColorGC(scrPtr->black);
373 GC wgc = WMColorGC(scrPtr->white);
375 panel = wmalloc(sizeof(WMColorPanel));
376 panel->color.rgb.red = 0;
377 panel->color.rgb.green = 0;
378 panel->color.rgb.blue = 0;
379 panel->color.hsv.hue = 0;
380 panel->color.hsv.saturation = 0;
381 panel->color.hsv.value = 0;
382 panel->color.set = cpNone; /* Color has not been set yet */
384 panel->font8 = WMSystemFontOfSize(scrPtr, 8);
385 panel->font12 = WMSystemFontOfSize(scrPtr, 12);
387 panel->win = WMCreateWindowWithStyle(scrPtr, name,
388 WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
389 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
390 WMSetWindowTitle(panel->win, _("Colors"));
391 WMSetWindowCloseAction(panel->win, closeWindowCallback, panel);
393 /* Set Default ColorPanel Mode(s) */
394 panel->mode = WMWheelModeColorPanel;
395 panel->lastChanged = 0;
396 panel->slidersmode = WMRGBModeColorPanel;
397 panel->configurationPath = wstrconcat(wusergnusteppath(), "/Library/Colors/");
399 /* Some General Purpose Widgets */
400 panel->colorWell = WMCreateColorWell(panel->win);
401 WMResizeWidget(panel->colorWell, 134, 36);
402 WSetColorWellBordered(panel->colorWell, False);
403 WMMoveWidget(panel->colorWell, 56, 4);
405 panel->magnifyBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
406 WMResizeWidget(panel->magnifyBtn, 46, 36);
407 WMMoveWidget(panel->magnifyBtn, 6, 4);
408 WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
409 WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
410 WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
412 panel->wheelBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
413 WMResizeWidget(panel->wheelBtn, 46, 32);
414 WMMoveWidget(panel->wheelBtn, 6, 44);
415 WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
416 WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
417 WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
419 panel->slidersBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
420 WMResizeWidget(panel->slidersBtn, 46, 32);
421 WMMoveWidget(panel->slidersBtn, 52, 44);
422 WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
423 WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
424 WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
426 panel->customPaletteBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
427 WMResizeWidget(panel->customPaletteBtn, 46, 32);
428 WMMoveWidget(panel->customPaletteBtn, 98, 44);
429 WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
430 WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
431 WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
433 panel->colorListBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
434 WMResizeWidget(panel->colorListBtn, 46, 32);
435 WMMoveWidget(panel->colorListBtn, 144, 44);
436 WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
437 WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
438 WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
440 /* Let's Group some of them together */
441 WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
442 WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
443 WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
445 /* Widgets for the ColorWheel Panel */
446 panel->wheelFrm = WMCreateFrame(panel->win);
447 WMSetFrameRelief(panel->wheelFrm, WRFlat);
448 WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
449 WMMoveWidget(panel->wheelFrm, 5, 80);
451 panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
452 /* XXX Can we create a view ? */
453 W_ResizeView(panel->wheelView, colorWheelSize + 4, colorWheelSize + 4);
454 W_MoveView(panel->wheelView, 0, 0);
456 /* Create an event handler to handle expose/click events in ColorWheel */
457 WMCreateEventHandler(panel->wheelView,
458 ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
459 LeaveWindowMask | ButtonMotionMask, wheelHandleActionEvents, panel);
461 WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents, panel);
463 panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
464 WMResizeWidget(panel->wheelBrightnessS, 16, 153);
465 WMMoveWidget(panel->wheelBrightnessS, 5 + colorWheelSize + 14, 1);
466 WMSetSliderMinValue(panel->wheelBrightnessS, 0);
467 WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
468 WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback, panel);
469 WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
471 panel->wheelMtrx = wheelCreateMatrix(colorWheelSize + 4, colorWheelSize + 4);
472 wheelInitMatrix(panel);
474 /* Widgets for the Slider Panels */
475 panel->slidersFrm = WMCreateFrame(panel->win);
476 WMSetFrameRelief(panel->slidersFrm, WRFlat);
477 WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
478 WMMoveWidget(panel->slidersFrm, 4, 80);
480 panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
481 WMSetFrameRelief(panel->seperatorFrm, WRPushed);
482 WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
483 WMMoveWidget(panel->seperatorFrm, 0, 1);
485 panel->grayBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
486 WMResizeWidget(panel->grayBtn, 46, 24);
487 WMMoveWidget(panel->grayBtn, 1, 8);
488 WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
489 WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
490 WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
492 panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
493 WMResizeWidget(panel->rgbBtn, 46, 24);
494 WMMoveWidget(panel->rgbBtn, 47, 8);
495 WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
496 WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
497 WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
499 panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
500 WMResizeWidget(panel->cmykBtn, 46, 24);
501 WMMoveWidget(panel->cmykBtn, 93, 8);
502 WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
503 WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
504 WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
506 panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
507 WMResizeWidget(panel->hsbBtn, 46, 24);
508 WMMoveWidget(panel->hsbBtn, 139, 8);
509 WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
510 WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
511 WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
513 /* Let's Group the Slider Panel Buttons Together */
514 WMGroupButtons(panel->grayBtn, panel->rgbBtn);
515 WMGroupButtons(panel->grayBtn, panel->cmykBtn);
516 WMGroupButtons(panel->grayBtn, panel->hsbBtn);
518 textcolor = WMDarkGrayColor(scrPtr);
520 /* Widgets for GrayScale Panel */
521 panel->grayFrm = WMCreateFrame(panel->slidersFrm);
522 WMSetFrameRelief(panel->grayFrm, WRFlat);
523 WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
524 WMMoveWidget(panel->grayFrm, 0, 34);
526 panel->grayMinL = WMCreateLabel(panel->grayFrm);
527 WMResizeWidget(panel->grayMinL, 20, 10);
528 WMMoveWidget(panel->grayMinL, 2, 2);
529 WMSetLabelText(panel->grayMinL, "0");
530 WMSetLabelTextAlignment(panel->grayMinL, WALeft);
531 WMSetLabelTextColor(panel->grayMinL, textcolor);
532 WMSetLabelFont(panel->grayMinL, panel->font8);
534 panel->grayMaxL = WMCreateLabel(panel->grayFrm);
535 WMResizeWidget(panel->grayMaxL, 40, 10);
536 WMMoveWidget(panel->grayMaxL, 104, 2);
537 WMSetLabelText(panel->grayMaxL, "100");
538 WMSetLabelTextAlignment(panel->grayMaxL, WARight);
539 WMSetLabelTextColor(panel->grayMaxL, textcolor);
540 WMSetLabelFont(panel->grayMaxL, panel->font8);
542 panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
543 WMResizeWidget(panel->grayBrightnessS, 141, 16);
544 WMMoveWidget(panel->grayBrightnessS, 2, 14);
545 WMSetSliderMinValue(panel->grayBrightnessS, 0);
546 WMSetSliderMaxValue(panel->grayBrightnessS, 100);
547 WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
548 WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback, panel);
550 from.red = 0;
551 from.green = 0;
552 from.blue = 0;
554 to.red = 255;
555 to.green = 255;
556 to.blue = 255;
558 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
559 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
560 RReleaseImage(image);
562 if (pixmap)
563 W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap,
564 panel->font12, 2, 0, 100, WALeft, scrPtr->white,
565 False, _("Brightness"), strlen(_("Brightness")));
566 else
567 wwarning(_("Color Panel: Could not allocate memory"));
569 WMSetSliderImage(panel->grayBrightnessS, pixmap);
570 WMReleasePixmap(pixmap);
572 panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
573 WMResizeWidget(panel->grayBrightnessT, 40, 18);
574 WMMoveWidget(panel->grayBrightnessT, 146, 13);
575 WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
576 WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel,
577 WMTextDidEndEditingNotification, panel->grayBrightnessT);
579 for (i = 0; i < 7; i++) {
580 pixmap = WMCreatePixmap(scrPtr, 13, 13, scrPtr->depth, False);
582 graybuttoncolor = WMCreateRGBColor(scrPtr, (255 / 6) * i << 8,
583 (255 / 6) * i << 8, (255 / 6) * i << 8, True);
584 WMPaintColorSwatch(graybuttoncolor, pixmap->pixmap, 0, 0, 15, 15);
585 WMReleaseColor(graybuttoncolor);
587 panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
588 WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
589 WMMoveWidget(panel->grayPresetBtn[i], 2 + (i * 20), 34);
590 WMSetButtonAction(panel->grayPresetBtn[i], grayPresetButtonCallback, panel);
591 WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
592 WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
593 WMReleasePixmap(pixmap);
597 /* End of GrayScale Panel */
599 /* Widgets for RGB Panel */
600 panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
601 WMSetFrameRelief(panel->rgbFrm, WRFlat);
602 WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
603 WMMoveWidget(panel->rgbFrm, 0, 34);
605 panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
606 WMResizeWidget(panel->rgbMinL, 20, 10);
607 WMMoveWidget(panel->rgbMinL, 2, 2);
608 WMSetLabelText(panel->rgbMinL, "0");
609 WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
610 WMSetLabelTextColor(panel->rgbMinL, textcolor);
611 WMSetLabelFont(panel->rgbMinL, panel->font8);
613 panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
614 WMResizeWidget(panel->rgbMaxL, 40, 10);
615 WMMoveWidget(panel->rgbMaxL, 104, 2);
616 WMSetLabelText(panel->rgbMaxL, "255");
617 WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
618 WMSetLabelTextColor(panel->rgbMaxL, textcolor);
619 WMSetLabelFont(panel->rgbMaxL, panel->font8);
621 panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
622 WMResizeWidget(panel->rgbRedS, 141, 16);
623 WMMoveWidget(panel->rgbRedS, 2, 14);
624 WMSetSliderMinValue(panel->rgbRedS, 0);
625 WMSetSliderMaxValue(panel->rgbRedS, 255);
626 WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
627 WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
629 to.red = 255;
630 to.green = 0;
631 to.blue = 0;
633 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
634 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
635 RReleaseImage(image);
637 if (pixmap)
638 W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12,
639 2, 0, 100, WALeft, scrPtr->white, False, _("Red"), strlen(_("Red")));
640 else
641 wwarning(_("Color Panel: Could not allocate memory"));
643 WMSetSliderImage(panel->rgbRedS, pixmap);
644 WMReleasePixmap(pixmap);
646 panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
647 WMResizeWidget(panel->rgbRedT, 40, 18);
648 WMMoveWidget(panel->rgbRedT, 146, 13);
649 WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
650 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbRedT);
652 panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
653 WMResizeWidget(panel->rgbGreenS, 141, 16);
654 WMMoveWidget(panel->rgbGreenS, 2, 36);
655 WMSetSliderMinValue(panel->rgbGreenS, 0);
656 WMSetSliderMaxValue(panel->rgbGreenS, 255);
657 WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
658 WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
660 to.red = 0;
661 to.green = 255;
662 to.blue = 0;
664 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
665 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
666 RReleaseImage(image);
668 if (pixmap)
669 W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12,
670 2, 0, 100, WALeft, scrPtr->white, False, _("Green"), strlen(_("Green")));
671 else
672 wwarning(_("Color Panel: Could not allocate memory"));
674 WMSetSliderImage(panel->rgbGreenS, pixmap);
675 WMReleasePixmap(pixmap);
677 panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
678 WMResizeWidget(panel->rgbGreenT, 40, 18);
679 WMMoveWidget(panel->rgbGreenT, 146, 35);
680 WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
681 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbGreenT);
683 panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
684 WMResizeWidget(panel->rgbBlueS, 141, 16);
685 WMMoveWidget(panel->rgbBlueS, 2, 58);
686 WMSetSliderMinValue(panel->rgbBlueS, 0);
687 WMSetSliderMaxValue(panel->rgbBlueS, 255);
688 WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
689 WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
691 to.red = 0;
692 to.green = 0;
693 to.blue = 255;
695 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
696 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
697 RReleaseImage(image);
699 if (pixmap)
700 W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12,
701 2, 0, 100, WALeft, scrPtr->white, False, _("Blue"), strlen(_("Blue")));
702 else
703 wwarning(_("Color Panel: Could not allocate memory"));
705 WMSetSliderImage(panel->rgbBlueS, pixmap);
706 WMReleasePixmap(pixmap);
708 panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
709 WMResizeWidget(panel->rgbBlueT, 40, 18);
710 WMMoveWidget(panel->rgbBlueT, 146, 57);
711 WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
712 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbBlueT);
714 panel->rgbDecB = WMCreateButton(panel->rgbFrm, WBTRadio);
715 WMSetButtonText(panel->rgbDecB, "Decimal");
716 WMSetButtonSelected(panel->rgbDecB, 1);
717 panel->rgbState = RGBdec;
718 WMSetButtonAction(panel->rgbDecB, rgbDecToHex, panel);
719 WMResizeWidget(panel->rgbDecB, PWIDTH - 8, 23);
720 WMMoveWidget(panel->rgbDecB, 2, 81);
722 panel->rgbHexB = WMCreateButton(panel->rgbFrm, WBTRadio);
723 WMSetButtonText(panel->rgbHexB, "Hexadecimal");
724 WMSetButtonAction(panel->rgbHexB, rgbDecToHex, panel);
725 WMResizeWidget(panel->rgbHexB, PWIDTH - 8, 23);
726 WMMoveWidget(panel->rgbHexB, 2, 104);
728 WMGroupButtons(panel->rgbDecB, panel->rgbHexB);
730 /* End of RGB Panel */
732 /* Widgets for CMYK Panel */
733 panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
734 WMSetFrameRelief(panel->cmykFrm, WRFlat);
735 WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
736 WMMoveWidget(panel->cmykFrm, 0, 34);
738 panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
739 WMResizeWidget(panel->cmykMinL, 20, 10);
740 WMMoveWidget(panel->cmykMinL, 2, 2);
741 WMSetLabelText(panel->cmykMinL, "0");
742 WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
743 WMSetLabelTextColor(panel->cmykMinL, textcolor);
744 WMSetLabelFont(panel->cmykMinL, panel->font8);
746 panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
747 WMResizeWidget(panel->cmykMaxL, 40, 10);
748 WMMoveWidget(panel->cmykMaxL, 104, 2);
749 WMSetLabelText(panel->cmykMaxL, "100");
750 WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
751 WMSetLabelTextColor(panel->cmykMaxL, textcolor);
752 WMSetLabelFont(panel->cmykMaxL, panel->font8);
754 panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
755 WMResizeWidget(panel->cmykCyanS, 141, 16);
756 WMMoveWidget(panel->cmykCyanS, 2, 14);
757 WMSetSliderMinValue(panel->cmykCyanS, 0);
758 WMSetSliderMaxValue(panel->cmykCyanS, 100);
759 WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
760 WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
762 from.red = 255;
763 from.green = 255;
764 from.blue = 255;
766 to.red = 0;
767 to.green = 255;
768 to.blue = 255;
770 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
771 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
772 RReleaseImage(image);
774 if (pixmap)
775 W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12,
776 2, 0, 100, WALeft, scrPtr->black, False, _("Cyan"), strlen(_("Cyan")));
777 else
778 wwarning(_("Color Panel: Could not allocate memory"));
780 WMSetSliderImage(panel->cmykCyanS, pixmap);
781 WMReleasePixmap(pixmap);
783 panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
784 WMResizeWidget(panel->cmykCyanT, 40, 18);
785 WMMoveWidget(panel->cmykCyanT, 146, 13);
786 WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
787 WMAddNotificationObserver(cmykTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->cmykCyanT);
789 panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
790 WMResizeWidget(panel->cmykMagentaS, 141, 16);
791 WMMoveWidget(panel->cmykMagentaS, 2, 36);
792 WMSetSliderMinValue(panel->cmykMagentaS, 0);
793 WMSetSliderMaxValue(panel->cmykMagentaS, 100);
794 WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
795 WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
797 to.red = 255;
798 to.green = 0;
799 to.blue = 255;
801 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
802 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
803 RReleaseImage(image);
805 if (pixmap)
806 W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12,
807 2, 0, 100, WALeft, scrPtr->black, False, _("Magenta"), strlen(_("Magenta")));
808 else
809 wwarning(_("Color Panel: Could not allocate memory"));
811 WMSetSliderImage(panel->cmykMagentaS, pixmap);
812 WMReleasePixmap(pixmap);
814 panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
815 WMResizeWidget(panel->cmykMagentaT, 40, 18);
816 WMMoveWidget(panel->cmykMagentaT, 146, 35);
817 WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
818 WMAddNotificationObserver(cmykTextFieldCallback, panel,
819 WMTextDidEndEditingNotification, panel->cmykMagentaT);
821 panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
822 WMResizeWidget(panel->cmykYellowS, 141, 16);
823 WMMoveWidget(panel->cmykYellowS, 2, 58);
824 WMSetSliderMinValue(panel->cmykYellowS, 0);
825 WMSetSliderMaxValue(panel->cmykYellowS, 100);
826 WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
827 WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
829 to.red = 255;
830 to.green = 255;
831 to.blue = 0;
833 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
834 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
835 RReleaseImage(image);
837 if (pixmap)
838 W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12,
839 2, 0, 100, WALeft, scrPtr->black, False, _("Yellow"), strlen(_("Yellow")));
840 else
841 wwarning(_("Color Panel: Could not allocate memory"));
843 WMSetSliderImage(panel->cmykYellowS, pixmap);
844 WMReleasePixmap(pixmap);
846 panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
847 WMResizeWidget(panel->cmykYellowT, 40, 18);
848 WMMoveWidget(panel->cmykYellowT, 146, 57);
849 WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
850 WMAddNotificationObserver(cmykTextFieldCallback, panel,
851 WMTextDidEndEditingNotification, panel->cmykYellowT);
853 panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
854 WMResizeWidget(panel->cmykBlackS, 141, 16);
855 WMMoveWidget(panel->cmykBlackS, 2, 80);
856 WMSetSliderMinValue(panel->cmykBlackS, 0);
857 WMSetSliderMaxValue(panel->cmykBlackS, 100);
858 WMSetSliderValue(panel->cmykBlackS, 0);
859 WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
860 WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
862 to.red = 0;
863 to.green = 0;
864 to.blue = 0;
866 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
867 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
868 RReleaseImage(image);
870 if (pixmap)
871 W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12,
872 2, 0, 100, WALeft, scrPtr->black, False, _("Black"), strlen(_("Black")));
873 else
874 wwarning(_("Color Panel: Could not allocate memory"));
876 WMSetSliderImage(panel->cmykBlackS, pixmap);
877 WMReleasePixmap(pixmap);
879 panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
880 WMResizeWidget(panel->cmykBlackT, 40, 18);
881 WMMoveWidget(panel->cmykBlackT, 146, 79);
882 WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
883 WMAddNotificationObserver(cmykTextFieldCallback, panel,
884 WMTextDidEndEditingNotification, panel->cmykBlackT);
885 /* End of CMYK Panel */
887 /* Widgets for HSB Panel */
888 panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
889 WMSetFrameRelief(panel->hsbFrm, WRFlat);
890 WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
891 WMMoveWidget(panel->hsbFrm, 0, 34);
893 panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
894 WMResizeWidget(panel->hsbHueS, 141, 16);
895 WMMoveWidget(panel->hsbHueS, 2, 14);
896 WMSetSliderMinValue(panel->hsbHueS, 0);
897 WMSetSliderMaxValue(panel->hsbHueS, 359);
898 WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
899 WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
901 panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
902 WMResizeWidget(panel->hsbHueT, 40, 18);
903 WMMoveWidget(panel->hsbHueT, 146, 13);
904 WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
905 WMAddNotificationObserver(hsbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->hsbHueT);
907 panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
908 WMResizeWidget(panel->hsbSaturationS, 141, 16);
909 WMMoveWidget(panel->hsbSaturationS, 2, 36);
910 WMSetSliderMinValue(panel->hsbSaturationS, 0);
911 WMSetSliderMaxValue(panel->hsbSaturationS, 100);
912 WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
913 WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
915 panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
916 WMResizeWidget(panel->hsbSaturationT, 40, 18);
917 WMMoveWidget(panel->hsbSaturationT, 146, 35);
918 WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
919 WMAddNotificationObserver(hsbTextFieldCallback, panel,
920 WMTextDidEndEditingNotification, panel->hsbSaturationT);
922 panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
923 WMResizeWidget(panel->hsbBrightnessS, 141, 16);
924 WMMoveWidget(panel->hsbBrightnessS, 2, 58);
925 WMSetSliderMinValue(panel->hsbBrightnessS, 0);
926 WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
927 WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
928 WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
930 panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
931 WMResizeWidget(panel->hsbBrightnessT, 40, 18);
932 WMMoveWidget(panel->hsbBrightnessT, 146, 57);
933 WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
934 WMAddNotificationObserver(hsbTextFieldCallback, panel,
935 WMTextDidEndEditingNotification, panel->hsbBrightnessT);
936 /* End of HSB Panel */
938 WMReleaseColor(textcolor);
940 /* Widgets for the CustomPalette Panel */
941 panel->customPaletteFrm = WMCreateFrame(panel->win);
942 WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
943 WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
944 WMMoveWidget(panel->customPaletteFrm, 5, 80);
946 panel->customPaletteHistoryBtn = WMCreatePopUpButton(panel->customPaletteFrm);
947 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, _("Spectrum"));
948 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
949 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1);
950 WMSetPopUpButtonAction(panel->customPaletteHistoryBtn, customPaletteHistoryCallback, panel);
951 WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
952 WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
954 panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
955 WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
956 WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
957 WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
959 panel->customPaletteContentView = W_CreateView(W_VIEW(panel->customPaletteContentFrm));
960 /* XXX Test if we can create a view */
961 W_ResizeView(panel->customPaletteContentView, customPaletteWidth, customPaletteHeight);
962 W_MoveView(panel->customPaletteContentView, 2, 2);
964 /* Create event handler to handle expose/click events in CustomPalette */
965 WMCreateEventHandler(panel->customPaletteContentView,
966 ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
967 ButtonMotionMask, customPaletteHandleActionEvents, panel);
969 WMCreateEventHandler(panel->customPaletteContentView, ExposureMask, customPaletteHandleEvents, panel);
971 panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
972 WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
973 WMSetPopUpButtonText(panel->customPaletteMenuBtn, _("Palette"));
974 WMSetPopUpButtonAction(panel->customPaletteMenuBtn, customPaletteMenuCallback, panel);
975 WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
976 WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
978 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from File..."));
979 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Rename..."));
980 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Remove"));
981 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Copy"));
982 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from Clipboard"));
984 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, 0);
985 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, 0);
986 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuCopy, 0);
987 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuNewFromClipboard, 0);
989 customRenderSpectrum(panel);
990 panel->currentPalette = 0;
991 panel->palx = customPaletteWidth / 2;
992 panel->paly = customPaletteHeight / 2;
994 /* Widgets for the ColorList Panel */
995 panel->colorListFrm = WMCreateFrame(panel->win);
996 WMSetFrameRelief(panel->colorListFrm, WRFlat);
997 WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
998 WMMoveWidget(panel->colorListFrm, 5, 80);
1000 panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
1001 WMAddPopUpButtonItem(panel->colorListHistoryBtn, _("X11-Colors"));
1002 WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn,
1003 WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn) - 1);
1004 /* WMSetPopUpButtonAction(panel->colorListHistoryBtn,
1005 * colorListHistoryCallback, panel); */
1006 WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
1007 WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
1009 panel->colorListContentLst = WMCreateList(panel->colorListFrm);
1010 WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
1011 WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
1012 WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
1013 WMMoveWidget(panel->colorListContentLst, 0, 23);
1014 WMHangData(panel->colorListContentLst, panel);
1016 panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1017 WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
1018 WMSetPopUpButtonText(panel->colorListColorMenuBtn, _("Color"));
1019 WMSetPopUpButtonAction(panel->colorListColorMenuBtn, colorListColorMenuCallback, panel);
1020 WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16) / 2, 20);
1021 WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
1023 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Add..."));
1024 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Rename..."));
1025 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Remove"));
1027 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuAdd, 0);
1028 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRename, 0);
1029 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRemove, 0);
1031 panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1032 WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
1033 WMSetPopUpButtonText(panel->colorListListMenuBtn, _("List"));
1034 WMSetPopUpButtonAction(panel->colorListListMenuBtn, colorListListMenuCallback, panel);
1035 WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2, 20);
1036 WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2 + 8, PHEIGHT - 130);
1038 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("New..."));
1039 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Rename..."));
1040 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Remove"));
1042 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuAdd, 0);
1043 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
1044 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
1046 WMRealizeWidget(panel->win);
1047 WMMapSubwidgets(panel->win);
1049 WMMapSubwidgets(panel->wheelFrm);
1050 WMMapSubwidgets(panel->slidersFrm);
1051 WMMapSubwidgets(panel->grayFrm);
1052 WMMapSubwidgets(panel->rgbFrm);
1053 WMMapSubwidgets(panel->cmykFrm);
1054 WMMapSubwidgets(panel->hsbFrm);
1055 WMMapSubwidgets(panel->customPaletteFrm);
1056 WMMapSubwidgets(panel->customPaletteContentFrm);
1057 WMMapSubwidgets(panel->colorListFrm);
1059 /* Pixmap to indicate selection positions
1060 * wheelframe MUST be mapped.
1062 panel->selectionImg = XCreatePixmap(scrPtr->display, WMWidgetXID(panel->win), 4, 4, scrPtr->depth);
1063 XFillRectangle(scrPtr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1064 XFillRectangle(scrPtr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1066 readConfiguration(panel);
1067 readXColors(panel);
1069 return panel;
1072 WMColorPanel *WMGetColorPanel(WMScreen * scrPtr)
1074 WMColorPanel *panel;
1076 if (scrPtr->sharedColorPanel)
1077 return scrPtr->sharedColorPanel;
1079 panel = makeColorPanel(scrPtr, "colorPanel");
1081 scrPtr->sharedColorPanel = panel;
1083 return panel;
1086 void WMFreeColorPanel(WMColorPanel * panel)
1088 W_Screen *scr = WMWidgetScreen(panel->win);
1090 if (panel == scr->sharedColorPanel) {
1091 scr->sharedColorPanel = NULL;
1094 if (!panel)
1095 return;
1097 WMRemoveNotificationObserver(panel);
1098 WMUnmapWidget(panel->win);
1100 /* fonts */
1101 WMReleaseFont(panel->font8);
1102 WMReleaseFont(panel->font12);
1104 /* pixmaps */
1105 wheelDestroyMatrix(panel->wheelMtrx);
1106 if (panel->wheelImg)
1107 XFreePixmap(scr->display, panel->wheelImg);
1108 if (panel->selectionImg)
1109 XFreePixmap(scr->display, panel->selectionImg);
1110 if (panel->selectionBackImg)
1111 XFreePixmap(scr->display, panel->selectionBackImg);
1112 RReleaseImage(panel->customPaletteImg);
1114 /* structs */
1115 if (panel->lastBrowseDir)
1116 wfree(panel->lastBrowseDir);
1117 if (panel->configurationPath)
1118 wfree(panel->configurationPath);
1120 WMDestroyWidget(panel->win);
1122 wfree(panel);
1125 void WMCloseColorPanel(WMColorPanel * panel)
1127 WMFreeColorPanel(panel);
1130 void WMShowColorPanel(WMColorPanel * panel)
1132 WMScreen *scr = WMWidgetScreen(panel->win);
1133 WMColor *white = WMWhiteColor(scr);
1135 if (panel->color.set == cpNone)
1136 WMSetColorPanelColor(panel, white);
1137 WMReleaseColor(white);
1139 if (panel->mode != WMWheelModeColorPanel)
1140 WMPerformButtonClick(panel->wheelBtn);
1142 WMMapWidget(panel->win);
1145 static void closeWindowCallback(WMWidget * w, void *data)
1147 W_ColorPanel *panel = (W_ColorPanel *) data;
1149 /* Parameter not used, but tell the compiler that it is ok */
1150 (void) w;
1152 WMCloseColorPanel(panel);
1155 static void readConfiguration(W_ColorPanel * panel)
1157 /* XXX Doesn't take care of "invalid" files */
1159 DIR *dPtr;
1160 struct dirent *dp;
1161 struct stat stat_buf;
1162 int item;
1164 if (stat(panel->configurationPath, &stat_buf) != 0) {
1165 if (mkdir(panel->configurationPath, S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH) != 0) {
1166 werror(_("Color Panel: Could not create directory %s needed"
1167 " to store configurations"), panel->configurationPath);
1168 WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
1169 WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
1170 WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
1171 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1172 _("File Error"),
1173 _("Could not create ColorPanel configuration directory"),
1174 _("OK"), NULL, NULL);
1176 return;
1179 if (!(dPtr = opendir(panel->configurationPath))) {
1180 wwarning("%s: %s", _("Color Panel: Could not find file"), panel->configurationPath);
1181 return;
1184 while ((dp = readdir(dPtr)) != NULL) {
1185 unsigned int perm_mask;
1186 char *path = wstrconcat(panel->configurationPath,
1187 dp->d_name);
1189 if (dp->d_name[0] != '.') {
1190 item = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
1191 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
1193 perm_mask = (access(path, R_OK) == 0);
1194 WMSetPopUpButtonItemEnabled(panel->customPaletteHistoryBtn, item, perm_mask);
1196 wfree(path);
1198 closedir(dPtr);
1201 static void readXColors(W_ColorPanel * panel)
1203 WMListItem *item;
1204 const RGBColor *entry;
1206 for (entry = rgbColors; entry->name != NULL; entry++) {
1207 item = WMAddListItem(panel->colorListContentLst, entry->name);
1208 item->clientData = (void *)&(entry->color);
1212 void WMSetColorPanelPickerMode(WMColorPanel * panel, WMColorPanelMode mode)
1214 W_Screen *scr = WMWidgetScreen(panel->win);
1216 if (mode != WMWheelModeColorPanel) {
1217 WMUnmapWidget(panel->wheelFrm);
1218 if (panel->selectionBackImg) {
1219 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1220 panel->selectionBackImg = None;
1223 if (mode != WMGrayModeColorPanel)
1224 WMUnmapWidget(panel->grayFrm);
1225 if (mode != WMRGBModeColorPanel)
1226 WMUnmapWidget(panel->rgbFrm);
1227 if (mode != WMCMYKModeColorPanel)
1228 WMUnmapWidget(panel->cmykFrm);
1229 if (mode != WMHSBModeColorPanel)
1230 WMUnmapWidget(panel->hsbFrm);
1231 if (mode != WMCustomPaletteModeColorPanel) {
1232 WMUnmapWidget(panel->customPaletteFrm);
1233 if (panel->selectionBackImg) {
1234 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1235 panel->selectionBackImg = None;
1238 if (mode != WMColorListModeColorPanel)
1239 WMUnmapWidget(panel->colorListFrm);
1240 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
1241 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1242 WMUnmapWidget(panel->slidersFrm);
1243 else
1244 panel->slidersmode = mode;
1246 if (mode == WMWheelModeColorPanel) {
1247 WMMapWidget(panel->wheelFrm);
1248 WMSetButtonSelected(panel->wheelBtn, True);
1249 if (panel->lastChanged != WMWheelModeColorPanel)
1250 wheelInit(panel);
1251 wheelRender(panel);
1252 wheelPaint(panel);
1253 } else if (mode == WMGrayModeColorPanel) {
1254 WMMapWidget(panel->slidersFrm);
1255 WMSetButtonSelected(panel->slidersBtn, True);
1256 WMMapWidget(panel->grayFrm);
1257 WMSetButtonSelected(panel->grayBtn, True);
1258 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1259 if (panel->lastChanged != WMGrayModeColorPanel)
1260 grayInit(panel);
1261 } else if (mode == WMRGBModeColorPanel) {
1262 WMMapWidget(panel->slidersFrm);
1263 WMSetButtonSelected(panel->slidersBtn, True);
1264 WMMapWidget(panel->rgbFrm);
1265 WMSetButtonSelected(panel->rgbBtn, True);
1266 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1267 if (panel->lastChanged != WMRGBModeColorPanel)
1268 rgbInit(panel);
1269 } else if (mode == WMCMYKModeColorPanel) {
1270 WMMapWidget(panel->slidersFrm);
1271 WMSetButtonSelected(panel->slidersBtn, True);
1272 WMMapWidget(panel->cmykFrm);
1273 WMSetButtonSelected(panel->cmykBtn, True);
1274 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1275 if (panel->lastChanged != WMCMYKModeColorPanel)
1276 cmykInit(panel);
1277 } else if (mode == WMHSBModeColorPanel) {
1278 WMMapWidget(panel->slidersFrm);
1279 WMSetButtonSelected(panel->slidersBtn, True);
1280 WMMapWidget(panel->hsbFrm);
1281 WMSetButtonSelected(panel->hsbBtn, True);
1282 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1283 if (panel->lastChanged != WMHSBModeColorPanel)
1284 hsbInit(panel);
1285 } else if (mode == WMCustomPaletteModeColorPanel) {
1286 WMMapWidget(panel->customPaletteFrm);
1287 WMSetButtonSelected(panel->customPaletteBtn, True);
1288 customSetPalette(panel);
1289 } else if (mode == WMColorListModeColorPanel) {
1290 WMMapWidget(panel->colorListFrm);
1291 WMSetButtonSelected(panel->colorListBtn, True);
1294 panel->mode = mode;
1297 WMColor *WMGetColorPanelColor(WMColorPanel * panel)
1299 return WMGetColorWellColor(panel->colorWell);
1302 void WMSetColorPanelColor(WMColorPanel * panel, WMColor * color)
1304 WMSetColorWellColor(panel->colorWell, color);
1306 panel->color.rgb.red = color->color.red >> 8;
1307 panel->color.rgb.green = color->color.green >> 8;
1308 panel->color.rgb.blue = color->color.blue >> 8;
1309 panel->color.set = cpRGB;
1311 if (panel->mode == panel->lastChanged)
1312 panel->lastChanged = 0;
1314 WMSetColorPanelPickerMode(panel, panel->mode);
1317 static void updateSwatch(WMColorPanel * panel, CPColor color)
1319 WMScreen *scr = WMWidgetScreen(panel->win);
1320 WMColor *wellcolor;
1322 if (color.set != cpRGB)
1323 convertCPColor(&color);
1325 panel->color = color;
1327 wellcolor = WMCreateRGBColor(scr, color.rgb.red << 8, color.rgb.green << 8, color.rgb.blue << 8, True);
1329 WMSetColorWellColor(panel->colorWell, wellcolor);
1330 WMReleaseColor(wellcolor);
1332 if (!panel->flags.dragging || panel->flags.continuous) {
1333 if (panel->action)
1334 (*panel->action) (panel, panel->clientData);
1336 WMPostNotificationName(WMColorPanelColorChangedNotification, panel, NULL);
1340 static void modeButtonCallback(WMWidget * w, void *data)
1342 W_ColorPanel *panel = (W_ColorPanel *) (data);
1344 if (w == panel->wheelBtn)
1345 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1346 else if (w == panel->slidersBtn)
1347 WMSetColorPanelPickerMode(panel, panel->slidersmode);
1348 else if (w == panel->customPaletteBtn)
1349 WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
1350 else if (w == panel->colorListBtn)
1351 WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
1352 else if (w == panel->grayBtn)
1353 WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
1354 else if (w == panel->rgbBtn)
1355 WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
1356 else if (w == panel->cmykBtn)
1357 WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
1358 else if (w == panel->hsbBtn)
1359 WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
1362 /****************** Magnifying Cursor Functions *******************/
1364 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h)
1366 int x0 = 0, y0 = 0, w0 = w, h0 = h;
1367 const int displayWidth = DisplayWidth(scr->display, scr->screen),
1368 displayHeight = DisplayHeight(scr->display, scr->screen);
1370 if (!(image && image->data)) {
1371 /* The image in panel->magnifyGlass->image does not exist yet.
1372 * Grab one from the screen (not beyond) and use it from now on.
1374 if (!(image = XGetImage(scr->display, scr->rootWin,
1375 x - Cursor_x_hot, y - Cursor_y_hot, w, h, AllPlanes, ZPixmap)))
1376 wwarning(_("Color Panel: X failed request"));
1378 return image;
1381 /* Coordinate correction for back pixmap
1382 * if magnifying glass is at screen-borders
1385 /* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
1386 * Hatched area is beyond screen border.
1388 * |<-Cursor_x_hot->|
1389 * ________________|_____
1390 * |/ / / / / / /| | |
1391 * | / / / / / / |(x,y) |
1392 * |/_/_/_/_/_/_/|________|
1393 * |<----x0----->|<--w0-->|
1397 /* Figure 2: Shifting of rectangle-to-grab at bottom/right
1398 * screen borders
1399 * Hatched area is beyond screen border
1401 * |<-Cursor_x_hot->|
1402 * ________________|_______________
1403 * | | | / / / / / /|
1404 * | (x,y)|/ / / / / / |
1405 * |___________________|_/_/_/_/_/_/|
1406 * |<-------w0-------->| |
1407 * |<---------------w--|----------->|
1408 * | |
1409 * x0 Displaywidth-1
1412 if (x < Cursor_x_hot) { /* see fig. 1 */
1413 x0 = Cursor_x_hot - x;
1414 w0 = w - x0;
1417 if (displayWidth - 1 < x - Cursor_x_hot + w) { /* see fig. 2 */
1418 w0 = (displayWidth) - (x - Cursor_x_hot);
1421 if (y < Cursor_y_hot) { /* see fig. 1 */
1422 y0 = Cursor_y_hot - y;
1423 h0 = h - y0;
1426 if (displayHeight - 1 < y - Cursor_y_hot + h) { /* see fig. 2 */
1427 h0 = (displayHeight) - (y - Cursor_y_hot);
1429 /* end of coordinate correction */
1431 /* Grab an image from the screen, clipped if necessary,
1432 * and put it in the existing panel->magnifyGlass->image
1433 * with the corresponding clipping offset.
1435 if (!XGetSubImage(scr->display, scr->rootWin,
1436 x - Cursor_x_hot + x0, y - Cursor_y_hot + y0, w0, h0, AllPlanes, ZPixmap, image, x0, y0))
1437 wwarning(_("Color Panel: X failed request"));
1439 return NULL;
1442 static void magnifyGetImageStored(WMColorPanel * panel, int x1, int y1, int x2, int y2)
1444 /* (x1, y1) = topleft corner of existing rectangle
1445 * (x2, y2) = topleft corner of new position
1448 W_Screen *scr = WMWidgetScreen(panel->win);
1449 int xa = 0, ya = 0, xb = 0, yb = 0;
1450 int width, height;
1451 const int dx = abs(x2 - x1), dy = abs(y2 - y1);
1452 XImage *image;
1453 const int x_min = Cursor_x_hot,
1454 y_min = Cursor_y_hot,
1455 x_max = DisplayWidth(scr->display, scr->screen) - 1 -
1456 (Cursor_mask_width - Cursor_x_hot),
1457 y_max = DisplayHeight(scr->display, scr->screen) - 1 - (Cursor_mask_height - Cursor_y_hot);
1459 if ((dx == 0) && (dy == 0) && panel->magnifyGlass->image)
1460 return; /* No movement */
1462 if (x1 < x2)
1463 xa = dx;
1464 else
1465 xb = dx;
1467 if (y1 < y2)
1468 ya = dy;
1469 else
1470 yb = dy;
1472 width = Cursor_mask_width - dx;
1473 height = Cursor_mask_height - dy;
1475 /* If the traversed distance is larger than the size of the magnifying
1476 * glass contents, there is no need to do dirty rectangles. A whole new
1477 * rectangle can be grabbed (unless that rectangle falls partially
1478 * off screen).
1479 * Destroying the image and setting it to NULL will achieve that later on.
1481 * Of course, grabbing an XImage beyond the borders of the screen will
1482 * cause trouble, this is considdered a special case. Part of the screen
1483 * is grabbed, but there is no need for dirty rectangles.
1485 if ((width <= 0) || (height <= 0)) {
1486 if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
1487 if (panel->magnifyGlass->image)
1488 XDestroyImage(panel->magnifyGlass->image);
1489 panel->magnifyGlass->image = NULL;
1491 } else {
1492 if (panel->magnifyGlass->image) {
1493 /* Get dirty rectangle from panel->magnifyGlass->image */
1494 panel->magnifyGlass->dirtyRect =
1495 XSubImage(panel->magnifyGlass->image, xa, ya, width, height);
1496 if (!panel->magnifyGlass->dirtyRect) {
1497 wwarning(_("Color Panel: X failed request"));
1498 return; /* X returned a NULL from XSubImage */
1503 /* Get image from screen */
1504 image = magnifyGetImage(scr, panel->magnifyGlass->image, x2, y2, Cursor_mask_width, Cursor_mask_height);
1505 if (image) { /* Only reassign if a *new* image was grabbed */
1506 panel->magnifyGlass->image = image;
1507 return;
1510 /* Copy previously stored rectangle on covered part of image */
1511 if (panel->magnifyGlass->image && panel->magnifyGlass->dirtyRect) {
1512 int old_height;
1514 /* "width" and "height" are used as coordinates here,
1515 * and run from [0...width-1] and [0...height-1] respectively.
1517 width--;
1518 height--;
1519 old_height = height;
1521 for (; width >= 0; width--)
1522 for (height = old_height; height >= 0; height--)
1523 XPutPixel(panel->magnifyGlass->image, xb + width, yb + height,
1524 XGetPixel(panel->magnifyGlass->dirtyRect, width, height));
1525 XDestroyImage(panel->magnifyGlass->dirtyRect);
1526 panel->magnifyGlass->dirtyRect = NULL;
1529 return;
1532 static Pixmap magnifyCreatePixmap(WMColorPanel * panel)
1534 W_Screen *scr = WMWidgetScreen(panel->win);
1535 int u, v;
1536 #ifndef USE_XSHAPE
1537 Pixmap pixmap;
1538 #endif
1539 unsigned long color;
1541 if (!panel->magnifyGlass->image)
1542 return None;
1544 if (!panel->magnifyGlass->magPix)
1545 return None;
1548 * Copy an area of only 5x5 pixels from the center of the image.
1550 for (u = 0; u < 5; u++) {
1551 for (v = 0; v < 5; v++) {
1552 color = XGetPixel(panel->magnifyGlass->image, u + 9, v + 9);
1554 XSetForeground(scr->display, scr->copyGC, color);
1556 if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
1557 panel->magnifyGlass->color = ulongToRColor(scr, color);
1559 /* The center square must eventually be centered around the
1560 * hotspot. The image needs shifting to achieve this. The amount of
1561 * shifting is (Cursor_mask_width/2 - 2 * square_size) = 11-10 = 1
1562 * _ _ _ _ _
1563 * |_|_|_|_|_|
1564 * ^------- center of center square == Cursor_x_hot
1566 XFillRectangle(scr->display, panel->magnifyGlass->magPix,
1567 scr->copyGC,
1568 u * 5 + (u == 0 ? 0 : -1), v * 5 + (v == 0 ? 0 : -1),
1569 (u == 0 ? 4 : 5), (v == 0 ? 4 : 5));
1573 #ifdef USE_XSHAPE
1574 return panel->magnifyGlass->magPix;
1575 #else
1576 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width, Cursor_mask_height, scr->depth);
1577 if (!pixmap)
1578 return None;
1580 XPutImage(scr->display, pixmap, scr->copyGC, panel->magnifyGlass->image,
1581 0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
1583 /* Copy the magnified pixmap, with the clip mask, to background pixmap */
1584 XCopyArea(scr->display, panel->magnifyGlass->magPix, pixmap,
1585 scr->clipGC, 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
1586 /* (2,2) puts center pixel on center of glass */
1588 return pixmap;
1589 #endif
1593 static WMView *magnifyCreateView(W_ColorPanel * panel)
1595 W_Screen *scr = WMWidgetScreen(panel->win);
1596 WMView *magView;
1598 magView = W_CreateTopView(scr);
1599 if (!magView)
1600 return NULL;
1602 magView->self = panel->win;
1603 magView->flags.topLevel = 1;
1604 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1605 magView->attribs.override_redirect = True;
1606 magView->attribs.save_under = True;
1608 W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
1610 W_RealizeView(magView);
1612 return magView;
1615 static Cursor magnifyGrabPointer(W_ColorPanel * panel)
1617 W_Screen *scr = WMWidgetScreen(panel->win);
1618 Pixmap magPixmap, magPixmap2;
1619 Cursor magCursor;
1620 XColor fgColor = { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 };
1621 XColor bgColor = { 0, 0xbf00, 0xa000, 0x5000, DoRed | DoGreen | DoBlue, 0 };
1623 /* Cursor creation stuff */
1624 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1625 (char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
1626 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1627 (char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
1629 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1630 &fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
1632 XFreePixmap(scr->display, magPixmap);
1633 XFreePixmap(scr->display, magPixmap2);
1635 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1637 /* Set up Pointer */
1638 XGrabPointer(scr->display, panel->magnifyGlass->view->window, True,
1639 PointerMotionMask | ButtonPressMask,
1640 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1642 return magCursor;
1645 static WMPoint magnifyInitialize(W_ColorPanel * panel)
1647 W_Screen *scr = WMWidgetScreen(panel->win);
1648 int x, y, u, v;
1649 unsigned int mask;
1650 Pixmap pixmap, clip_mask;
1651 WMPoint point;
1652 Window root_return, child_return;
1654 clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1655 (char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1656 1, 0, 1);
1657 panel->magnifyGlass->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
1658 5 * 5 - 1, 5 * 5 - 1, scr->depth);
1660 XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return, &x, &y, &u, &v, &mask);
1662 panel->magnifyGlass->image = NULL;
1664 /* Clipmask to make magnified view-contents circular */
1665 #ifdef USE_XSHAPE
1666 XShapeCombineMask(scr->display, WMViewXID(panel->magnifyGlass->view),
1667 ShapeBounding, 0, 0, clip_mask, ShapeSet);
1668 #else
1669 /* Clip circle in glass cursor */
1670 XSetClipMask(scr->display, scr->clipGC, clip_mask);
1671 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1672 #endif
1674 XFreePixmap(scr->display, clip_mask);
1676 /* Draw initial magnifying glass contents */
1677 magnifyGetImageStored(panel, x, y, x, y);
1679 pixmap = magnifyCreatePixmap(panel);
1680 XSetWindowBackgroundPixmap(scr->display, WMViewXID(panel->magnifyGlass->view), pixmap);
1681 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1682 XFlush(scr->display);
1684 #ifndef USE_XSHAPE
1685 XFreePixmap(scr->display, pixmap);
1686 #endif
1688 point.x = x;
1689 point.y = y;
1691 return point;
1694 static void magnifyPutCursor(WMWidget * w, void *data)
1696 W_ColorPanel *panel = (W_ColorPanel *) (data);
1697 W_Screen *scr = WMWidgetScreen(panel->win);
1698 Cursor magCursor;
1699 Pixmap pixmap;
1700 XEvent event;
1701 WMPoint initialPosition;
1703 /* Parameter not used, but tell the compiler that it is ok */
1704 (void) w;
1706 /* Destroy wheelBackImg, so it'll update properly */
1707 if (panel->selectionBackImg) {
1708 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1709 panel->selectionBackImg = None;
1712 /* Create magnifying glass */
1713 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1714 panel->magnifyGlass->view = magnifyCreateView(panel);
1715 if (!panel->magnifyGlass->view)
1716 return;
1718 initialPosition = magnifyInitialize(panel);
1719 panel->magnifyGlass->x = initialPosition.x;
1720 panel->magnifyGlass->y = initialPosition.y;
1722 W_MoveView(panel->magnifyGlass->view,
1723 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1724 W_MapView(panel->magnifyGlass->view);
1726 magCursor = magnifyGrabPointer(panel);
1728 while (panel->magnifyGlass->image) {
1729 WMNextEvent(scr->display, &event);
1731 /* Pack motion events */
1732 while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
1735 switch (event.type) {
1736 case ButtonPress:
1737 XDestroyImage(panel->magnifyGlass->image);
1738 panel->magnifyGlass->image = NULL;
1740 if (event.xbutton.button == Button1) {
1741 panel->color.rgb = panel->magnifyGlass->color;
1742 panel->color.set = cpRGB;
1743 updateSwatch(panel, panel->color);
1745 switch (panel->mode) {
1746 case WMWheelModeColorPanel:
1747 wheelInit(panel);
1748 wheelRender(panel);
1749 wheelPaint(panel);
1750 break;
1751 case WMGrayModeColorPanel:
1752 grayInit(panel);
1753 break;
1754 case WMRGBModeColorPanel:
1755 rgbInit(panel);
1756 break;
1757 case WMCMYKModeColorPanel:
1758 cmykInit(panel);
1759 break;
1760 case WMHSBModeColorPanel:
1761 hsbInit(panel);
1762 break;
1763 default:
1764 break;
1766 panel->lastChanged = panel->mode;
1768 WMSetButtonSelected(panel->magnifyBtn, False);
1769 break;
1771 case MotionNotify:
1772 while (XPending(event.xmotion.display)) {
1773 XEvent ev;
1774 XPeekEvent(event.xmotion.display, &ev);
1775 if (ev.type == MotionNotify)
1776 XNextEvent(event.xmotion.display, &event);
1777 else
1778 break;
1781 /* Get a "dirty rectangle" */
1782 magnifyGetImageStored(panel,
1783 panel->magnifyGlass->x, panel->magnifyGlass->y,
1784 event.xmotion.x_root, event.xmotion.y_root);
1786 /* Update coordinates */
1787 panel->magnifyGlass->x = event.xmotion.x_root;
1788 panel->magnifyGlass->y = event.xmotion.y_root;
1790 /* Move view */
1791 W_MoveView(panel->magnifyGlass->view,
1792 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1794 /* Put new image (with magn.) in view */
1795 pixmap = magnifyCreatePixmap(panel);
1796 if (pixmap != None) {
1797 /* Change the window background */
1798 XSetWindowBackgroundPixmap(scr->display,
1799 WMViewXID(panel->magnifyGlass->view), pixmap);
1800 /* Force an Expose (handled by X) */
1801 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1802 /* Synchronize the event queue, so the Expose is handled NOW */
1803 XFlush(scr->display);
1804 #ifndef USE_XSHAPE
1805 XFreePixmap(scr->display, pixmap);
1806 #endif
1808 break;
1810 /* Try XQueryPointer for this !!! It returns windows that the pointer
1811 * is over. Note: We found this solving the invisible donkey cap bug
1813 #if 0 /* As it is impossible to make this work in all cases,
1814 * we consider it confusing. Therefore we disabled it.
1816 case FocusOut: /* fall through */
1817 case FocusIn:
1819 * Color Panel window (panel->win) lost or received focus.
1820 * We need to update the pixmap in the magnifying glass.
1822 * BUG Doesn't work with focus switches between two windows
1823 * if none of them is the color panel.
1825 XUngrabPointer(scr->display, CurrentTime);
1826 W_UnmapView(panel->magnifyGlass->view);
1828 magnifyInitialize(panel);
1830 W_MapView(panel->magnifyGlass->view);
1831 XGrabPointer(scr->display, panel->magnifyGlass->view->window,
1832 True, PointerMotionMask | ButtonPressMask,
1833 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1834 break;
1835 #endif
1836 default:
1837 WMHandleEvent(&event);
1838 break;
1839 } /* of switch */
1842 XUngrabPointer(scr->display, CurrentTime);
1843 XFreeCursor(scr->display, magCursor);
1845 XFreePixmap(scr->display, panel->magnifyGlass->magPix);
1846 panel->magnifyGlass->magPix = None;
1848 W_UnmapView(panel->magnifyGlass->view);
1849 W_DestroyView(panel->magnifyGlass->view);
1850 panel->magnifyGlass->view = NULL;
1852 wfree(panel->magnifyGlass);
1855 /****************** ColorWheel Functions ************************/
1857 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height)
1859 wheelMatrix *matrix = NULL;
1860 int i;
1862 assert((width > 0) && (height > 0));
1864 matrix = wmalloc(sizeof(wheelMatrix));
1865 matrix->width = width;
1866 matrix->height = height;
1868 for (i = 0; i < 3; i++) {
1869 matrix->data[i] = wmalloc(width * height * sizeof(unsigned char));
1872 return matrix;
1875 static void wheelDestroyMatrix(wheelMatrix * matrix)
1877 int i;
1879 if (!matrix)
1880 return;
1882 for (i = 0; i < 3; i++) {
1883 if (matrix->data[i])
1884 wfree(matrix->data[i]);
1886 wfree(matrix);
1889 static void wheelInitMatrix(W_ColorPanel * panel)
1891 int i;
1892 int x, y;
1893 unsigned char *rp, *gp, *bp;
1894 CPColor cpColor;
1895 long ofs[4];
1896 int xcor, ycor;
1897 unsigned short sat;
1898 int dhue[4];
1899 const int cw_halfsize = (colorWheelSize + 4) / 2,
1900 cw_sqsize = (colorWheelSize + 4) * (colorWheelSize + 4), uchar_shift = getShift(sizeof(unsigned char));
1902 if (!panel->wheelMtrx)
1903 return;
1905 cpColor.hsv.value = 255;
1906 cpColor.set = cpHSV;
1908 ofs[0] = -1;
1909 ofs[1] = -(colorWheelSize + 4);
1911 /* offsets are counterclockwise (in triangles).
1913 * ofs[0] ---->
1914 * _______________________________________
1915 * [1] |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| o
1916 * s |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| f
1917 * f |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| s
1918 * o | | | | | | | | | | | | | | | | | | | | | [3]
1920 * <---- ofs[2]
1921 * ____
1922 * |\ /| <-- triangles
1923 * | \/ |
1924 * | /\ |
1925 * |/__\|
1928 for (y = 0; y < cw_halfsize; y++) {
1929 for (x = y; x < (colorWheelSize + 4 - y); x++) {
1930 /* (xcor, ycor) is (x,y) relative to center of matrix */
1931 xcor = 2 * x - 4 - colorWheelSize;
1932 ycor = 2 * y - 4 - colorWheelSize;
1934 /* RColor.saturation is unsigned char and will wrap after 255 */
1935 sat = rint(255.0 * sqrt(xcor * xcor + ycor * ycor) / colorWheelSize);
1937 cpColor.hsv.saturation = (unsigned char)sat;
1939 ofs[0]++; /* top quarter of matrix */
1940 ofs[1] += colorWheelSize + 4; /* left quarter */
1941 ofs[2] = cw_sqsize - 1 - ofs[0]; /* bottom quarter */
1942 ofs[3] = cw_sqsize - 1 - ofs[1]; /* right quarter */
1944 if (sat < 256) {
1945 if (xcor != 0)
1946 dhue[0] = rint(atan((double)ycor / (double)xcor) *
1947 (180.0 / M_PI)) + (xcor < 0 ? 180.0 : 0.0);
1948 else
1949 dhue[0] = 270;
1951 dhue[0] = 360 - dhue[0]; /* Reverse direction of ColorWheel */
1952 dhue[1] = 270 - dhue[0] + (dhue[0] > 270 ? 360 : 0);
1953 dhue[2] = dhue[0] - 180 + (dhue[0] < 180 ? 360 : 0);
1954 dhue[3] = 90 - dhue[0] + (dhue[0] > 90 ? 360 : 0);
1956 for (i = 0; i < 4; i++) {
1957 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1958 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1959 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1961 cpColor.hsv.hue = dhue[i];
1962 convertCPColor(&cpColor);
1964 *rp = (unsigned char)(cpColor.rgb.red);
1965 *gp = (unsigned char)(cpColor.rgb.green);
1966 *bp = (unsigned char)(cpColor.rgb.blue);
1968 } else {
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 *rp = (unsigned char)0;
1975 *gp = (unsigned char)0;
1976 *bp = (unsigned char)0;
1981 ofs[0] += 2 * y + 1;
1982 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2 * y);
1986 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue)
1988 unsigned int i;
1989 unsigned int v;
1991 for (i = 0; i < 256; i++) {
1992 /* We divide by 128 in advance, and check whether that number divides
1993 * by 2 properly. If not, we add one to round the number correctly
1995 v = (i * maxvalue) >> 7;
1996 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + (v & 0x01));
2000 static void wheelRender(W_ColorPanel * panel)
2002 W_Screen *scr = WMWidgetScreen(panel->win);
2003 int x, y;
2004 RImage *image;
2005 unsigned char *ptr;
2006 RColor gray;
2007 unsigned long ofs = 0;
2008 /*unsigned char shift = getShift(sizeof(unsigned char)); */
2010 image = RCreateImage(colorWheelSize + 4, colorWheelSize + 4, True);
2011 if (!image) {
2012 wwarning(_("Color Panel: Could not allocate memory"));
2013 return;
2016 ptr = image->data;
2018 /* TODO Make this transparent istead of gray */
2019 gray.red = gray.blue = 0xae;
2020 gray.green = 0xaa;
2022 for (y = 0; y < colorWheelSize + 4; y++) {
2023 for (x = 0; x < colorWheelSize + 4; x++) {
2024 if (wheelInsideColorWheel(panel, ofs)) {
2025 *(ptr++) =
2026 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]]);
2027 *(ptr++) =
2028 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]]);
2029 *(ptr++) =
2030 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]]);
2031 *(ptr++) = 0;
2032 } else {
2033 *(ptr++) = (unsigned char)(gray.red);
2034 *(ptr++) = (unsigned char)(gray.green);
2035 *(ptr++) = (unsigned char)(gray.blue);
2036 *(ptr++) = 255;
2038 ofs++;
2042 if (panel->wheelImg)
2043 XFreePixmap(scr->display, panel->wheelImg);
2045 RConvertImage(scr->rcontext, image, &panel->wheelImg);
2046 RReleaseImage(image);
2048 /* Check if backimage exists. If it doesn't, allocate and fill it */
2049 if (!panel->selectionBackImg) {
2050 panel->selectionBackImg = XCreatePixmap(scr->display,
2051 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
2052 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2053 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2054 /* -2 is hot spot correction */
2058 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs)
2060 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
2061 (panel->wheelMtrx->data[1][ofs] != 0) && (panel->wheelMtrx->data[2][ofs] != 0));
2064 static void wheelPaint(W_ColorPanel * panel)
2066 W_Screen *scr = WMWidgetScreen(panel->win);
2068 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
2069 scr->copyGC, 0, 0, colorWheelSize + 4, colorWheelSize + 4, 0, 0);
2071 /* Draw selection image */
2072 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2073 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2076 static void wheelHandleEvents(XEvent * event, void *data)
2078 W_ColorPanel *panel = (W_ColorPanel *) data;
2080 switch (event->type) {
2081 case Expose:
2082 if (event->xexpose.count != 0) /* TODO Improve */
2083 break;
2084 wheelPaint(panel);
2085 break;
2089 static void wheelHandleActionEvents(XEvent * event, void *data)
2091 W_ColorPanel *panel = (W_ColorPanel *) data;
2093 switch (event->type) {
2094 case ButtonPress:
2095 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) == COLORWHEEL_PART) {
2097 panel->lastChanged = WMWheelModeColorPanel;
2098 panel->flags.dragging = 1;
2100 wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
2102 break;
2104 case ButtonRelease:
2105 panel->flags.dragging = 0;
2106 if (!panel->flags.continuous) {
2107 if (panel->action)
2108 (*panel->action) (panel, panel->clientData);
2110 break;
2112 case MotionNotify:
2113 if (panel->flags.dragging) {
2114 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) == COLORWHEEL_PART) {
2115 wheelPositionSelection(panel, event->xmotion.x, event->xmotion.y);
2116 } else
2117 wheelPositionSelectionOutBounds(panel, event->xmotion.x, event->xmotion.y);
2119 break;
2123 static int getPickerPart(W_ColorPanel * panel, int x, int y)
2125 int lx, ly;
2126 unsigned long ofs;
2128 lx = x;
2129 ly = y;
2131 if (panel->mode == WMWheelModeColorPanel) {
2132 if ((lx >= 2) && (lx <= 2 + colorWheelSize) && (ly >= 2) && (ly <= 2 + colorWheelSize)) {
2134 ofs = ly * panel->wheelMtrx->width + lx;
2136 if (wheelInsideColorWheel(panel, ofs))
2137 return COLORWHEEL_PART;
2141 if (panel->mode == WMCustomPaletteModeColorPanel) {
2142 if ((lx >= 2) && (lx < customPaletteWidth - 2) && (ly >= 2) && (ly < customPaletteHeight - 2)) {
2143 return CUSTOMPALETTE_PART;
2147 return 0;
2150 static void wheelBrightnessSliderCallback(WMWidget * w, void *data)
2152 int value;
2154 W_ColorPanel *panel = (W_ColorPanel *) data;
2156 /* Parameter not used, but tell the compiler that it is ok */
2157 (void) w;
2159 value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2161 wheelCalculateValues(panel, value);
2163 if (panel->color.set == cpRGB) {
2164 convertCPColor(&panel->color);
2165 panel->color.set = cpHSV;
2168 panel->color.hsv.value = value;
2170 wheelRender(panel);
2171 wheelPaint(panel);
2172 wheelUpdateSelection(panel);
2175 static void wheelUpdateSelection(W_ColorPanel * panel)
2177 W_Screen *scr = WMWidgetScreen(panel->win);
2179 updateSwatch(panel, panel->color);
2180 panel->lastChanged = WMWheelModeColorPanel;
2182 /* Redraw color selector (and make a backup of the part it will cover) */
2183 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2184 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2185 /* "-2" is correction for hotspot location */
2186 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2187 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2188 /* see above */
2191 static void wheelUndrawSelection(W_ColorPanel * panel)
2193 W_Screen *scr = WMWidgetScreen(panel->win);
2195 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
2196 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2197 /* see above */
2200 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y)
2202 unsigned long ofs = (y * panel->wheelMtrx->width) + x;
2204 panel->color.rgb.red = panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]];
2206 panel->color.rgb.green = panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]];
2208 panel->color.rgb.blue = panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]];
2209 panel->color.set = cpRGB;
2211 wheelUndrawSelection(panel);
2213 panel->colx = x;
2214 panel->coly = y;
2216 wheelUpdateSelection(panel);
2217 wheelUpdateBrightnessGradientFromLocation(panel);
2220 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2222 int hue;
2223 int xcor, ycor;
2224 CPColor cpColor;
2226 xcor = x * 2 - colorWheelSize - 4;
2227 ycor = y * 2 - colorWheelSize - 4;
2229 panel->color.hsv.saturation = 255;
2230 panel->color.hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2232 if (xcor != 0)
2233 hue = rint(atan(-(double)ycor / (double)xcor) * (180.0 / M_PI));
2234 else {
2235 if (ycor < 0)
2236 hue = 90;
2237 else
2238 hue = 270;
2241 if (xcor < 0)
2242 hue += 180;
2244 if ((xcor > 0) && (ycor > 0))
2245 hue += 360;
2247 panel->color.hsv.hue = hue;
2248 panel->color.set = cpHSV;
2249 convertCPColor(&panel->color);
2251 wheelUndrawSelection(panel);
2253 panel->colx = 2 + rint((colorWheelSize * (1.0 + cos(panel->color.hsv.hue * (M_PI / 180.0)))) / 2.0);
2254 /* "+2" because of "colorWheelSize + 4" */
2255 panel->coly = 2 + rint((colorWheelSize * (1.0 + sin(-panel->color.hsv.hue * (M_PI / 180.0)))) / 2.0);
2257 wheelUpdateSelection(panel);
2258 cpColor = panel->color;
2259 wheelUpdateBrightnessGradient(panel, cpColor);
2262 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel)
2264 CPColor from;
2265 unsigned long ofs;
2267 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2269 from.rgb.red = panel->wheelMtrx->data[0][ofs];
2270 from.rgb.green = panel->wheelMtrx->data[1][ofs];
2271 from.rgb.blue = panel->wheelMtrx->data[2][ofs];
2272 from.set = cpRGB;
2274 wheelUpdateBrightnessGradient(panel, from);
2277 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor)
2279 RColor to;
2280 RImage *sliderImg;
2281 WMPixmap *sliderPxmp;
2283 to.red = to.green = to.blue = 0;
2285 if (topColor.set == cpHSV)
2286 convertCPColor(&topColor);
2288 sliderImg = RRenderGradient(16, 153, &(topColor.rgb), &to, RGRD_VERTICAL);
2289 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win), sliderImg, 0);
2290 RReleaseImage(sliderImg);
2291 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
2292 WMReleasePixmap(sliderPxmp);
2295 /****************** Grayscale Panel Functions ***************/
2297 static void grayBrightnessSliderCallback(WMWidget * w, void *data)
2299 CPColor cpColor;
2300 int value;
2301 char tmp[4];
2302 W_ColorPanel *panel = (W_ColorPanel *) data;
2304 /* Parameter not used, but tell the compiler that it is ok */
2305 (void) w;
2307 value = WMGetSliderValue(panel->grayBrightnessS);
2309 sprintf(tmp, "%d", value);
2311 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2312 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint(2.55 * value);
2313 cpColor.set = cpRGB;
2315 updateSwatch(panel, cpColor);
2316 panel->lastChanged = WMGrayModeColorPanel;
2319 static void grayPresetButtonCallback(WMWidget * w, void *data)
2321 CPColor cpColor;
2322 char tmp[4];
2323 int value;
2324 int i = 0;
2325 W_ColorPanel *panel = (W_ColorPanel *) data;
2327 while (i < 7) {
2328 if (w == panel->grayPresetBtn[i])
2329 break;
2330 i++;
2333 value = rint((100.0 * i) / 6.0);
2334 sprintf(tmp, "%d", value);
2336 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2337 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * i) / 6.0);
2338 cpColor.set = cpRGB;
2340 WMSetSliderValue(panel->grayBrightnessS, rint((100.0 * i) / 6.0));
2342 updateSwatch(panel, cpColor);
2343 panel->lastChanged = WMGrayModeColorPanel;
2346 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification)
2348 CPColor cpColor;
2349 char tmp[4];
2350 int value;
2351 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2353 /* Parameter not used, but tell the compiler that it is ok */
2354 (void) notification;
2356 value = atoi(WMGetTextFieldText(panel->grayBrightnessT));
2357 if (value > 100)
2358 value = 100;
2359 if (value < 0)
2360 value = 0;
2362 sprintf(tmp, "%d", value);
2363 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2364 WMSetSliderValue(panel->grayBrightnessS, value);
2366 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * value) / 100.0);
2367 cpColor.set = cpRGB;
2369 updateSwatch(panel, cpColor);
2370 panel->lastChanged = WMGrayModeColorPanel;
2373 /******************* RGB Panel Functions *****************/
2375 void rgbIntToChar(W_ColorPanel *panel, int *value)
2377 char tmp[4];
2378 const char *format;
2380 switch (panel->rgbState) {
2381 case RGBdec:
2382 format = "%d";
2383 break;
2384 case RGBhex:
2385 format = "%0X";
2386 break;
2389 sprintf(tmp, format, value[0]);
2390 WMSetTextFieldText(panel->rgbRedT, tmp);
2391 sprintf(tmp, format, value[1]);
2392 WMSetTextFieldText(panel->rgbGreenT, tmp);
2393 sprintf(tmp, format, value[2]);
2394 WMSetTextFieldText(panel->rgbBlueT, tmp);
2397 int *rgbCharToInt(W_ColorPanel *panel)
2399 int base = 0;
2400 static int value[3];
2402 switch (panel->rgbState) {
2403 case RGBdec:
2404 base = 10;
2405 break;
2406 case RGBhex:
2407 base = 16;
2408 break;
2411 value[0] = strtol(WMGetTextFieldText(panel->rgbRedT), NULL, base);
2412 value[1] = strtol(WMGetTextFieldText(panel->rgbGreenT), NULL, base);
2413 value[2] = strtol(WMGetTextFieldText(panel->rgbBlueT), NULL, base);
2415 return value;
2418 static void rgbSliderCallback(WMWidget * w, void *data)
2420 CPColor cpColor;
2421 int value[3];
2422 W_ColorPanel *panel = (W_ColorPanel *) data;
2424 /* Parameter not used, but tell the compiler that it is ok */
2425 (void) w;
2427 value[0] = WMGetSliderValue(panel->rgbRedS);
2428 value[1] = WMGetSliderValue(panel->rgbGreenS);
2429 value[2] = WMGetSliderValue(panel->rgbBlueS);
2431 rgbIntToChar(panel, value);
2433 cpColor.rgb.red = value[0];
2434 cpColor.rgb.green = value[1];
2435 cpColor.rgb.blue = value[2];
2436 cpColor.set = cpRGB;
2438 updateSwatch(panel, cpColor);
2439 panel->lastChanged = WMRGBModeColorPanel;
2442 static void rgbTextFieldCallback(void *observerData, WMNotification * notification)
2444 CPColor cpColor;
2445 int *value;
2446 int n;
2447 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2449 /* Parameter not used, but tell the compiler that it is ok */
2450 (void) notification;
2452 value = rgbCharToInt(panel);
2454 for (n = 0; n < 3; n++) {
2455 if (value[n] > 255)
2456 value[n] = 255;
2457 if (value[n] < 0)
2458 value[n] = 0;
2461 rgbIntToChar(panel, value);
2463 WMSetSliderValue(panel->rgbRedS, value[0]);
2464 WMSetSliderValue(panel->rgbGreenS, value[1]);
2465 WMSetSliderValue(panel->rgbBlueS, value[2]);
2467 cpColor.rgb.red = value[0];
2468 cpColor.rgb.green = value[1];
2469 cpColor.rgb.blue = value[2];
2470 cpColor.set = cpRGB;
2472 updateSwatch(panel, cpColor);
2473 panel->lastChanged = WMRGBModeColorPanel;
2476 static void rgbDecToHex(WMWidget *w, void *data)
2478 W_ColorPanel *panel = (W_ColorPanel *) data;
2479 int *value;
2481 (void) w;
2483 switch (panel->rgbState) {
2484 case RGBhex:
2485 if (WMGetButtonSelected(panel->rgbDecB)) {
2486 WMSetLabelText(panel->rgbMaxL, "255");
2487 WMRedisplayWidget(panel->rgbMaxL);
2488 value = rgbCharToInt(panel);
2489 panel->rgbState = RGBdec;
2490 rgbIntToChar(panel, value);
2492 break;
2494 case RGBdec:
2495 if (WMGetButtonSelected(panel->rgbHexB)) {
2496 WMSetLabelText(panel->rgbMaxL, "FF");
2497 WMRedisplayWidget(panel->rgbMaxL);
2498 value = rgbCharToInt(panel);
2499 panel->rgbState = RGBhex;
2500 rgbIntToChar(panel, value);
2502 break;
2506 /******************* CMYK Panel Functions *****************/
2508 static void cmykSliderCallback(WMWidget * w, void *data)
2510 CPColor cpColor;
2511 int value[4];
2512 char tmp[4];
2513 W_ColorPanel *panel = (W_ColorPanel *) data;
2514 double scale;
2516 /* Parameter not used, but tell the compiler that it is ok */
2517 (void) w;
2519 value[0] = WMGetSliderValue(panel->cmykCyanS);
2520 value[1] = WMGetSliderValue(panel->cmykMagentaS);
2521 value[2] = WMGetSliderValue(panel->cmykYellowS);
2522 value[3] = WMGetSliderValue(panel->cmykBlackS);
2524 sprintf(tmp, "%d", value[0]);
2525 WMSetTextFieldText(panel->cmykCyanT, tmp);
2526 sprintf(tmp, "%d", value[1]);
2527 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2528 sprintf(tmp, "%d", value[2]);
2529 WMSetTextFieldText(panel->cmykYellowT, tmp);
2530 sprintf(tmp, "%d", value[3]);
2531 WMSetTextFieldText(panel->cmykBlackT, tmp);
2533 scale = 2.55 * (1.0 - (value[3] / 100.0));
2534 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2535 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2536 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2537 cpColor.set = cpRGB;
2539 updateSwatch(panel, cpColor);
2540 panel->lastChanged = WMCMYKModeColorPanel;
2543 static void cmykTextFieldCallback(void *observerData, WMNotification * notification)
2545 CPColor cpColor;
2546 int value[4];
2547 char tmp[4];
2548 int n;
2549 double scale;
2550 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2552 /* Parameter not used, but tell the compiler that it is ok */
2553 (void) notification;
2555 value[0] = atoi(WMGetTextFieldText(panel->cmykCyanT));
2556 value[1] = atoi(WMGetTextFieldText(panel->cmykMagentaT));
2557 value[2] = atoi(WMGetTextFieldText(panel->cmykYellowT));
2558 value[3] = atoi(WMGetTextFieldText(panel->cmykBlackT));
2560 for (n = 0; n < 4; n++) {
2561 if (value[n] > 100)
2562 value[n] = 100;
2563 if (value[n] < 0)
2564 value[n] = 0;
2567 sprintf(tmp, "%d", value[0]);
2568 WMSetTextFieldText(panel->cmykCyanT, tmp);
2570 sprintf(tmp, "%d", value[1]);
2571 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2573 sprintf(tmp, "%d", value[2]);
2574 WMSetTextFieldText(panel->cmykYellowT, tmp);
2576 sprintf(tmp, "%d", value[3]);
2577 WMSetTextFieldText(panel->cmykBlackT, tmp);
2579 WMSetSliderValue(panel->cmykCyanS, value[0]);
2580 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2581 WMSetSliderValue(panel->cmykYellowS, value[2]);
2582 WMSetSliderValue(panel->cmykBlackS, value[3]);
2584 scale = 2.55 * (1.0 - (value[3] / 100.0));
2585 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2586 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2587 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2588 cpColor.set = cpRGB;
2590 updateSwatch(panel, cpColor);
2591 panel->lastChanged = WMCMYKModeColorPanel;
2594 /********************** HSB Panel Functions ***********************/
2596 static void hsbSliderCallback(WMWidget * w, void *data)
2598 CPColor cpColor;
2599 int value[3];
2600 char tmp[4];
2601 W_ColorPanel *panel = (W_ColorPanel *) data;
2603 value[0] = WMGetSliderValue(panel->hsbHueS);
2604 value[1] = WMGetSliderValue(panel->hsbSaturationS);
2605 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
2607 sprintf(tmp, "%d", value[0]);
2608 WMSetTextFieldText(panel->hsbHueT, tmp);
2609 sprintf(tmp, "%d", value[1]);
2610 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2611 sprintf(tmp, "%d", value[2]);
2612 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2614 cpColor.hsv.hue = value[0];
2615 cpColor.hsv.saturation = value[1] * 2.55;
2616 cpColor.hsv.value = value[2] * 2.55;
2617 cpColor.set = cpHSV;
2619 convertCPColor(&cpColor);
2621 panel->lastChanged = WMHSBModeColorPanel;
2622 updateSwatch(panel, cpColor);
2624 if (w != panel->hsbBrightnessS)
2625 hsbUpdateBrightnessGradient(panel);
2626 if (w != panel->hsbSaturationS)
2627 hsbUpdateSaturationGradient(panel);
2628 if (w != panel->hsbHueS)
2629 hsbUpdateHueGradient(panel);
2632 static void hsbTextFieldCallback(void *observerData, WMNotification * notification)
2634 CPColor cpColor;
2635 int value[3];
2636 char tmp[4];
2637 int n;
2638 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2640 /* Parameter not used, but tell the compiler that it is ok */
2641 (void) notification;
2643 value[0] = atoi(WMGetTextFieldText(panel->hsbHueT));
2644 value[1] = atoi(WMGetTextFieldText(panel->hsbSaturationT));
2645 value[2] = atoi(WMGetTextFieldText(panel->hsbBrightnessT));
2647 if (value[0] > 359)
2648 value[0] = 359;
2649 if (value[0] < 0)
2650 value[0] = 0;
2652 for (n = 1; n < 3; n++) {
2653 if (value[n] > 100)
2654 value[n] = 100;
2655 if (value[n] < 0)
2656 value[n] = 0;
2659 sprintf(tmp, "%d", value[0]);
2660 WMSetTextFieldText(panel->hsbHueT, tmp);
2661 sprintf(tmp, "%d", value[1]);
2662 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2663 sprintf(tmp, "%d", value[2]);
2664 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2666 WMSetSliderValue(panel->hsbHueS, value[0]);
2667 WMSetSliderValue(panel->hsbSaturationS, value[1]);
2668 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
2670 cpColor.hsv.hue = value[0];
2671 cpColor.hsv.saturation = value[1] * 2.55;
2672 cpColor.hsv.value = value[2] * 2.55;
2673 cpColor.set = cpHSV;
2675 convertCPColor(&cpColor);
2677 panel->lastChanged = WMHSBModeColorPanel;
2678 updateSwatch(panel, cpColor);
2680 hsbUpdateBrightnessGradient(panel);
2681 hsbUpdateSaturationGradient(panel);
2682 hsbUpdateHueGradient(panel);
2685 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel)
2687 W_Screen *scr = WMWidgetScreen(panel->win);
2688 RColor from;
2689 CPColor to;
2690 RImage *sliderImg;
2691 WMPixmap *sliderPxmp;
2693 from.red = from.green = from.blue = 0;
2694 to.hsv = panel->color.hsv;
2695 to.hsv.value = 255;
2696 to.set = cpHSV;
2698 convertCPColor(&to);
2700 sliderImg = RRenderGradient(141, 16, &from, &(to.rgb), RGRD_HORIZONTAL);
2701 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2702 RReleaseImage(sliderImg);
2704 if (sliderPxmp)
2705 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
2706 panel->font12, 2, 0, 100, WALeft, scr->white,
2707 False, _("Brightness"), strlen(_("Brightness")));
2708 else
2709 wwarning(_("Color Panel: Could not allocate memory"));
2711 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
2712 WMReleasePixmap(sliderPxmp);
2715 static void hsbUpdateSaturationGradient(W_ColorPanel * panel)
2717 W_Screen *scr = WMWidgetScreen(panel->win);
2718 CPColor from;
2719 CPColor to;
2720 RImage *sliderImg;
2721 WMPixmap *sliderPxmp;
2723 from.hsv = panel->color.hsv;
2724 from.hsv.saturation = 0;
2725 from.set = cpHSV;
2726 convertCPColor(&from);
2728 to.hsv = panel->color.hsv;
2729 to.hsv.saturation = 255;
2730 to.set = cpHSV;
2731 convertCPColor(&to);
2733 sliderImg = RRenderGradient(141, 16, &(from.rgb), &(to.rgb), RGRD_HORIZONTAL);
2734 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2735 RReleaseImage(sliderImg);
2737 if (sliderPxmp)
2738 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2739 panel->font12, 2, 0, 100, WALeft,
2740 from.hsv.value < 128 ? scr->white : scr->black, False,
2741 _("Saturation"), strlen(_("Saturation")));
2742 else
2743 wwarning(_("Color Panel: Could not allocate memory"));
2745 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
2746 WMReleasePixmap(sliderPxmp);
2749 static void hsbUpdateHueGradient(W_ColorPanel * panel)
2751 W_Screen *scr = WMWidgetScreen(panel->win);
2752 RColor **colors = NULL;
2753 RHSVColor hsvcolor;
2754 RImage *sliderImg;
2755 WMPixmap *sliderPxmp;
2756 int i;
2758 hsvcolor = panel->color.hsv;
2760 colors = wmalloc(sizeof(RColor *) * (8));
2761 for (i = 0; i < 7; i++) {
2762 hsvcolor.hue = (360 * i) / 6;
2763 colors[i] = wmalloc(sizeof(RColor));
2764 RHSVtoRGB(&hsvcolor, colors[i]);
2766 colors[7] = NULL;
2768 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2769 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2770 RReleaseImage(sliderImg);
2772 if (sliderPxmp)
2773 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2774 panel->font12, 2, 0, 100, WALeft,
2775 hsvcolor.value < 128 ? scr->white : scr->black, False, _("Hue"), strlen(_("Hue")));
2776 else
2777 wwarning(_("Color Panel: Could not allocate memory"));
2779 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2780 WMReleasePixmap(sliderPxmp);
2782 for (i = 0; i < 7; i++)
2783 wfree(colors[i]);
2785 wfree(colors);
2788 /*************** Custom Palette Functions ****************/
2790 static void customRenderSpectrum(W_ColorPanel * panel)
2792 RImage *spectrum;
2793 int x, y;
2794 unsigned char *ptr;
2795 CPColor cpColor;
2797 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, False);
2799 ptr = spectrum->data;
2801 for (y = 0; y < SPECTRUM_HEIGHT; y++) {
2802 cpColor.hsv.hue = y;
2803 cpColor.hsv.saturation = 0;
2804 cpColor.hsv.value = 255;
2805 cpColor.set = cpHSV;
2807 for (x = 0; x < SPECTRUM_WIDTH; x++) {
2808 convertCPColor(&cpColor);
2810 *(ptr++) = (unsigned char)cpColor.rgb.red;
2811 *(ptr++) = (unsigned char)cpColor.rgb.green;
2812 *(ptr++) = (unsigned char)cpColor.rgb.blue;
2814 if (x < (SPECTRUM_WIDTH / 2))
2815 cpColor.hsv.saturation++;
2817 if (x > (SPECTRUM_WIDTH / 2))
2818 cpColor.hsv.value--;
2821 if (panel->customPaletteImg) {
2822 RReleaseImage(panel->customPaletteImg);
2823 panel->customPaletteImg = NULL;
2825 panel->customPaletteImg = spectrum;
2828 static void customSetPalette(W_ColorPanel * panel)
2830 W_Screen *scr = WMWidgetScreen(panel->win);
2831 RImage *scaledImg;
2832 Pixmap image;
2834 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth, customPaletteHeight, scr->depth);
2835 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth, customPaletteHeight);
2836 RConvertImage(scr->rcontext, scaledImg, &image);
2837 RReleaseImage(scaledImg);
2839 XCopyArea(scr->display, image, panel->customPaletteContentView->window,
2840 scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2842 /* Check backimage exists. If it doesn't, allocate and fill it */
2843 if (!panel->selectionBackImg) {
2844 panel->selectionBackImg = XCreatePixmap(scr->display,
2845 panel->customPaletteContentView->window, 4, 4, scr->depth);
2848 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
2849 panel->palx - 2, panel->paly - 2, 4, 4, 0, 0);
2850 XCopyArea(scr->display, panel->selectionImg,
2851 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2852 panel->palx - 2, panel->paly - 2);
2853 XFreePixmap(scr->display, image);
2855 panel->palXRatio = (double)(panel->customPaletteImg->width) / (double)(customPaletteWidth);
2856 panel->palYRatio = (double)(panel->customPaletteImg->height) / (double)(customPaletteHeight);
2858 WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
2861 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y)
2863 W_Screen *scr = WMWidgetScreen(panel->win);
2864 unsigned long ofs;
2866 /* undraw selection */
2867 XCopyArea(scr->display, panel->selectionBackImg,
2868 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2869 panel->palx - 2, panel->paly - 2);
2871 panel->palx = x;
2872 panel->paly = y;
2874 ofs = (rint(x * panel->palXRatio) + rint(y * panel->palYRatio) * panel->customPaletteImg->width) * 3;
2876 panel->color.rgb.red = panel->customPaletteImg->data[ofs];
2877 panel->color.rgb.green = panel->customPaletteImg->data[ofs + 1];
2878 panel->color.rgb.blue = panel->customPaletteImg->data[ofs + 2];
2879 panel->color.set = cpRGB;
2881 updateSwatch(panel, panel->color);
2882 panel->lastChanged = WMCustomPaletteModeColorPanel;
2884 /* Redraw color selector (and make a backup of the part it will cover) */
2885 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 */
2886 XCopyArea(scr->display, panel->selectionImg, panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4, panel->palx - 2, panel->paly - 2); /* see above */
2889 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2891 if (x < 2)
2892 x = 2;
2893 if (y < 2)
2894 y = 2;
2895 if (x >= customPaletteWidth)
2896 x = customPaletteWidth - 2;
2897 if (y >= customPaletteHeight)
2898 y = customPaletteHeight - 2;
2900 customPalettePositionSelection(panel, x, y);
2903 static void customPaletteHandleEvents(XEvent * event, void *data)
2905 W_ColorPanel *panel = (W_ColorPanel *) data;
2907 switch (event->type) {
2908 case Expose:
2909 if (event->xexpose.count != 0) /* TODO Improve. */
2910 break;
2911 customSetPalette(panel);
2912 break;
2916 static void customPaletteHandleActionEvents(XEvent * event, void *data)
2918 W_ColorPanel *panel = (W_ColorPanel *) data;
2919 int x, y;
2921 switch (event->type) {
2922 case ButtonPress:
2923 x = event->xbutton.x;
2924 y = event->xbutton.y;
2926 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2927 panel->flags.dragging = 1;
2928 customPalettePositionSelection(panel, x, y);
2930 break;
2932 case ButtonRelease:
2933 panel->flags.dragging = 0;
2934 if (!panel->flags.continuous) {
2935 if (panel->action)
2936 (*panel->action) (panel, panel->clientData);
2938 break;
2940 case MotionNotify:
2941 x = event->xmotion.x;
2942 y = event->xmotion.y;
2944 if (panel->flags.dragging) {
2945 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2946 customPalettePositionSelection(panel, x, y);
2947 } else
2948 customPalettePositionSelectionOutBounds(panel, x, y);
2950 break;
2954 static void customPaletteMenuCallback(WMWidget * w, void *data)
2956 W_ColorPanel *panel = (W_ColorPanel *) data;
2957 int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
2959 /* Parameter not used, but tell the compiler that it is ok */
2960 (void) w;
2962 switch (item) {
2963 case CPmenuNewFromFile:
2964 customPaletteMenuNewFromFile(panel);
2965 break;
2966 case CPmenuRename:
2967 customPaletteMenuRename(panel);
2968 break;
2969 case CPmenuRemove:
2970 customPaletteMenuRemove(panel);
2971 break;
2972 case CPmenuCopy:
2973 break;
2974 case CPmenuNewFromClipboard:
2975 break;
2979 static void customPaletteMenuNewFromFile(W_ColorPanel * panel)
2981 W_Screen *scr = WMWidgetScreen(panel->win);
2982 WMOpenPanel *browseP;
2983 char *filepath;
2984 char *filename = NULL;
2985 char *spath;
2986 char *tmp;
2987 int i;
2988 RImage *tmpImg = NULL;
2990 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir, "\0") == 0))
2991 spath = wexpandpath(wgethomedir());
2992 else
2993 spath = wexpandpath(panel->lastBrowseDir);
2995 browseP = WMGetOpenPanel(scr);
2996 WMSetFilePanelCanChooseDirectories(browseP, 0);
2997 WMSetFilePanelCanChooseFiles(browseP, 1);
2999 /* Get a filename */
3000 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
3001 _("Open Palette"), RSupportedFileFormats())) {
3002 filepath = WMGetFilePanelFileName(browseP);
3004 /* Get seperation position between path and filename */
3005 i = strrchr(filepath, '/') - filepath + 1;
3006 if (i > strlen(filepath))
3007 i = strlen(filepath);
3009 /* Store last browsed path */
3010 if (panel->lastBrowseDir)
3011 wfree(panel->lastBrowseDir);
3012 panel->lastBrowseDir = wmalloc((i + 1) * sizeof(char));
3013 strncpy(panel->lastBrowseDir, filepath, i);
3014 panel->lastBrowseDir[i] = '\0';
3016 /* Get filename from path */
3017 filename = wstrdup(filepath + i);
3019 /* Check for duplicate files, and rename it if there are any */
3020 tmp = wstrconcat(panel->configurationPath, filename);
3021 while (access(tmp, F_OK) == 0) {
3022 char *newName;
3024 wfree(tmp);
3026 newName = generateNewFilename(filename);
3027 wfree(filename);
3028 filename = newName;
3030 tmp = wstrconcat(panel->configurationPath, filename);
3032 wfree(tmp);
3034 /* Copy image to $(gnustepdir)/Library/Colors/ &
3035 * Add filename to history menu */
3036 if (wcopy_file(panel->configurationPath, filepath, filename) == 0) {
3038 /* filepath is a "local" path now the file has been copied */
3039 wfree(filepath);
3040 filepath = wstrconcat(panel->configurationPath, filename);
3042 /* load the image & add menu entries */
3043 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
3044 if (tmpImg) {
3045 if (panel->customPaletteImg)
3046 RReleaseImage(panel->customPaletteImg);
3047 panel->customPaletteImg = tmpImg;
3049 customSetPalette(panel);
3050 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
3052 panel->currentPalette =
3053 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1;
3055 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3056 panel->currentPalette);
3058 } else {
3059 tmp = wstrconcat(panel->configurationPath, filename);
3061 i = remove(tmp); /* Delete the file, it doesn't belong here */
3062 WMRunAlertPanel(scr, panel->win, _("File Error"),
3063 _("Invalid file format !"), _("OK"), NULL, NULL);
3064 if (i != 0) {
3065 werror(_("can't remove file %s"), tmp);
3066 WMRunAlertPanel(scr, panel->win, _("File Error"),
3067 _("Couldn't remove file from Configuration Directory !"),
3068 _("OK"), NULL, NULL);
3070 wfree(tmp);
3072 wfree(filepath);
3073 wfree(filename);
3075 WMFreeFilePanel(browseP);
3077 wfree(spath);
3080 static void customPaletteMenuRename(W_ColorPanel * panel)
3082 W_Screen *scr = WMWidgetScreen(panel->win);
3083 char *toName = NULL;
3084 char *fromName;
3085 char *toPath, *fromPath;
3086 int item;
3087 int index;
3089 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3090 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
3092 toName = WMRunInputPanel(scr, panel->win, _("Rename"), _("Rename palette to:"),
3093 fromName, _("OK"), _("Cancel"));
3095 if (toName) {
3097 /* As some people do certain stupid things... */
3098 if (strcmp(toName, fromName) == 0) {
3099 wfree(toName);
3100 return;
3103 /* For normal people */
3104 fromPath = wstrconcat(panel->configurationPath, fromName);
3105 toPath = wstrconcat(panel->configurationPath, toName);
3107 if (access(toPath, F_OK) == 0) {
3108 /* Careful, this palette exists already */
3109 if (WMRunAlertPanel(scr, panel->win, _("Warning"),
3110 _("Palette already exists !\n\nOverwrite ?"), _("No"), _("Yes"),
3111 NULL) == 1) {
3112 /* "No" = 0, "Yes" = 1 */
3113 int items = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
3115 remove(toPath);
3117 /* Remove from History list too */
3118 index = 1;
3119 while ((index < items)
3121 (strcmp(WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, index), toName)
3122 != 0))
3123 index++;
3125 if (index < items) {
3126 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, index);
3127 if (index < item)
3128 item--;
3131 } else {
3132 wfree(fromPath);
3133 wfree(toName);
3134 wfree(toPath);
3136 return;
3140 if (rename(fromPath, toPath) != 0)
3141 werror(_("Couldn't rename palette %s to %s"), fromName, toName);
3142 else {
3143 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3144 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item, toName);
3146 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
3148 wfree(fromPath);
3149 wfree(toPath);
3150 wfree(toName);
3154 static void customPaletteMenuRemove(W_ColorPanel * panel)
3156 W_Screen *scr = WMWidgetScreen(panel->win);
3157 char *text;
3158 char *tmp;
3159 int choice;
3160 int item;
3162 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3164 tmp = wstrconcat(_("This will permanently remove the palette "),
3165 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3166 text = wstrconcat(tmp, _(".\n\nAre you sure you want to remove this palette ?"));
3167 wfree(tmp);
3169 choice = WMRunAlertPanel(scr, panel->win, _("Remove"), text, _("Yes"), _("No"), NULL);
3170 /* returns 0 (= "Yes") or 1 (="No") */
3171 wfree(text);
3173 if (choice == 0) {
3175 tmp = wstrconcat(panel->configurationPath,
3176 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3178 if (remove(tmp) == 0) {
3179 /* item-1 always exists */
3180 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3182 customPaletteHistoryCallback(panel->customPaletteHistoryBtn, panel);
3183 customSetPalette(panel);
3185 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3187 } else {
3188 werror(_("Couldn't remove palette %s"), tmp);
3191 wfree(tmp);
3195 static void customPaletteHistoryCallback(WMWidget * w, void *data)
3197 W_ColorPanel *panel = (W_ColorPanel *) data;
3198 W_Screen *scr = WMWidgetScreen(panel->win);
3199 int item;
3200 char *filename;
3201 RImage *tmp = NULL;
3202 unsigned char perm_mask;
3204 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3205 if (item == panel->currentPalette)
3206 return;
3208 if (item == 0) {
3209 customRenderSpectrum(panel);
3211 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, False);
3212 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, False);
3213 } else {
3214 /* Load file from configpath */
3215 filename = wstrconcat(panel->configurationPath,
3216 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3218 /* If the file corresponding to the item does not exist,
3219 * remove it from the history list and select the next one.
3221 perm_mask = (access(filename, F_OK) == 0);
3222 if (!perm_mask) {
3223 /* File does not exist */
3224 wfree(filename);
3225 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3226 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3227 customPaletteHistoryCallback(w, data);
3228 return;
3231 /* Get the image */
3232 tmp = RLoadImage(scr->rcontext, filename, 0);
3233 if (tmp) {
3234 if (panel->customPaletteImg) {
3235 RReleaseImage(panel->customPaletteImg);
3236 panel->customPaletteImg = NULL;
3238 panel->customPaletteImg = tmp;
3241 /* If the image is not writable, don't allow removing/renaming */
3242 perm_mask = (access(filename, W_OK) == 0);
3243 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, perm_mask);
3244 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, perm_mask);
3246 wfree(filename);
3248 customSetPalette(panel);
3250 panel->currentPalette = item;
3253 /************************* ColorList Panel Functions **********************/
3255 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect)
3257 WMScreen *scr = WMWidgetScreen(lPtr);
3258 Display *dpy = WMScreenDisplay(scr);
3259 WMView *view = W_VIEW(lPtr);
3260 RColor *color = (RColor *) WMGetListItem(lPtr, index)->clientData;
3261 W_ColorPanel *panel = WMGetHangedData(lPtr);
3262 int width, height, x, y;
3263 WMColor *fillColor;
3265 width = rect->size.width;
3266 height = rect->size.height;
3267 x = rect->pos.x;
3268 y = rect->pos.y;
3270 if (state & WLDSSelected)
3271 XFillRectangle(dpy, d, WMColorGC(scr->white), x, y, width, height);
3272 else
3273 XFillRectangle(dpy, d, WMColorGC(view->backColor), x, y, width, height);
3275 fillColor = WMCreateRGBColor(scr, color->red << 8, color->green << 8, color->blue << 8, True);
3277 XFillRectangle(dpy, d, WMColorGC(fillColor), x, y, 15, height);
3278 WMReleaseColor(fillColor);
3280 WMDrawString(scr, d, scr->black, panel->font12, x + 18, y, text, strlen(text));
3283 static void colorListSelect(WMWidget * w, void *data)
3285 W_ColorPanel *panel = (W_ColorPanel *) data;
3286 CPColor cpColor;
3288 cpColor.rgb = *((RColor *) WMGetListSelectedItem(w)->clientData);
3289 cpColor.set = cpRGB;
3291 panel->lastChanged = WMColorListModeColorPanel;
3292 updateSwatch(panel, cpColor);
3295 static void colorListColorMenuCallback(WMWidget * w, void *data)
3297 W_ColorPanel *panel = (W_ColorPanel *) data;
3298 int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
3300 /* Parameter not used, but tell the compiler that it is ok */
3301 (void) w;
3303 switch (item) {
3304 case CLmenuAdd:
3305 break;
3306 case CLmenuRename:
3307 break;
3308 case CLmenuRemove:
3309 break;
3313 static void colorListListMenuCallback(WMWidget * w, void *data)
3315 W_ColorPanel *panel = (W_ColorPanel *) data;
3316 int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
3318 /* Parameter not used, but tell the compiler that it is ok */
3319 (void) w;
3321 switch (item) {
3322 case CLmenuAdd:
3323 break;
3324 case CLmenuRename:
3325 break;
3326 case CLmenuRemove:
3327 break;
3331 /*************** Panel Initialisation Functions *****************/
3333 static void wheelInit(W_ColorPanel * panel)
3335 CPColor cpColor;
3337 if (panel->color.set != cpHSV)
3338 convertCPColor(&panel->color);
3340 WMSetSliderValue(panel->wheelBrightnessS, 255 - panel->color.hsv.value);
3342 panel->colx = 2 + rint((colorWheelSize / 2.0) *
3343 (1 + (panel->color.hsv.saturation / 255.0) *
3344 cos(panel->color.hsv.hue * M_PI / 180.0)));
3345 panel->coly = 2 + rint((colorWheelSize / 2.0) *
3346 (1 + (panel->color.hsv.saturation / 255.0) *
3347 sin(-panel->color.hsv.hue * M_PI / 180.0)));
3349 wheelCalculateValues(panel, panel->color.hsv.value);
3351 cpColor = panel->color;
3352 cpColor.hsv.value = 255;
3353 cpColor.set = cpHSV;
3354 wheelUpdateBrightnessGradient(panel, cpColor);
3357 static void grayInit(W_ColorPanel * panel)
3359 int value;
3360 char tmp[4];
3362 if (panel->color.set != cpHSV)
3363 convertCPColor(&panel->color);
3365 value = rint(panel->color.hsv.value / 2.55);
3366 WMSetSliderValue(panel->grayBrightnessS, value);
3368 sprintf(tmp, "%d", value);
3369 WMSetTextFieldText(panel->grayBrightnessT, tmp);
3372 static void rgbInit(W_ColorPanel * panel)
3374 char tmp[4];
3376 if (panel->color.set != cpRGB)
3377 convertCPColor(&panel->color);
3379 WMSetSliderValue(panel->rgbRedS, panel->color.rgb.red);
3380 WMSetSliderValue(panel->rgbGreenS, panel->color.rgb.green);
3381 WMSetSliderValue(panel->rgbBlueS, panel->color.rgb.blue);
3383 sprintf(tmp, "%d", panel->color.rgb.red);
3384 WMSetTextFieldText(panel->rgbRedT, tmp);
3385 sprintf(tmp, "%d", panel->color.rgb.green);
3386 WMSetTextFieldText(panel->rgbGreenT, tmp);
3387 sprintf(tmp, "%d", panel->color.rgb.blue);
3388 WMSetTextFieldText(panel->rgbBlueT, tmp);
3391 static void cmykInit(W_ColorPanel * panel)
3393 int value[3];
3394 char tmp[4];
3396 if (panel->color.set != cpRGB)
3397 convertCPColor(&panel->color);
3399 value[0] = rint((255 - panel->color.rgb.red) / 2.55);
3400 value[1] = rint((255 - panel->color.rgb.green) / 2.55);
3401 value[2] = rint((255 - panel->color.rgb.blue) / 2.55);
3403 WMSetSliderValue(panel->cmykCyanS, value[0]);
3404 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3405 WMSetSliderValue(panel->cmykYellowS, value[2]);
3406 WMSetSliderValue(panel->cmykBlackS, 0);
3408 sprintf(tmp, "%d", value[0]);
3409 WMSetTextFieldText(panel->cmykCyanT, tmp);
3410 sprintf(tmp, "%d", value[1]);
3411 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3412 sprintf(tmp, "%d", value[2]);
3413 WMSetTextFieldText(panel->cmykYellowT, tmp);
3414 WMSetTextFieldText(panel->cmykBlackT, "0");
3417 static void hsbInit(W_ColorPanel * panel)
3419 int value[3];
3420 char tmp[4];
3422 if (panel->color.set != cpHSV)
3423 convertCPColor(&panel->color);
3425 value[0] = panel->color.hsv.hue;
3426 value[1] = rint(panel->color.hsv.saturation / 2.55);
3427 value[2] = rint(panel->color.hsv.value / 2.55);
3429 WMSetSliderValue(panel->hsbHueS, value[0]);
3430 WMSetSliderValue(panel->hsbSaturationS, value[1]);
3431 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
3433 sprintf(tmp, "%d", value[0]);
3434 WMSetTextFieldText(panel->hsbHueT, tmp);
3435 sprintf(tmp, "%d", value[1]);
3436 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3437 sprintf(tmp, "%d", value[2]);
3438 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3440 hsbUpdateBrightnessGradient(panel);
3441 hsbUpdateSaturationGradient(panel);
3442 hsbUpdateHueGradient(panel);
3445 /************************** Common utility functions ************************/
3447 static char *generateNewFilename(const char *curName)
3449 int n;
3450 char c;
3451 int baseLen;
3452 const char *ptr;
3453 char *newName;
3455 assert(curName);
3457 ptr = curName;
3459 if (((ptr = strrchr(ptr, '{')) == 0) || sscanf(ptr, "{%i}%c", &n, &c) != 1)
3460 return wstrconcat(curName, " {1}");
3462 baseLen = ptr - curName - 1;
3464 newName = wmalloc(baseLen + 16);
3465 strncpy(newName, curName, baseLen);
3467 snprintf(&newName[baseLen], 16, " {%i}", n + 1);
3469 return newName;
3472 static void convertCPColor(CPColor * color)
3474 unsigned short old_hue = 0;
3476 switch (color->set) {
3477 case cpNone:
3478 wwarning(_("Color Panel: Color unspecified"));
3479 return;
3480 case cpRGB:
3481 old_hue = color->hsv.hue;
3482 RRGBtoHSV(&(color->rgb), &(color->hsv));
3484 /* In black the hue is undefined, and may change by conversion
3485 * Same for white. */
3486 if (((color->rgb.red == 0) &&
3487 (color->rgb.green == 0) &&
3488 (color->rgb.blue == 0)) ||
3489 ((color->rgb.red == 0) && (color->rgb.green == 0) && (color->rgb.blue == 255))
3491 color->hsv.hue = old_hue;
3492 break;
3493 case cpHSV:
3494 RHSVtoRGB(&(color->hsv), &(color->rgb));
3495 break;
3499 #define ABS_SHIFT(val, shift) \
3500 (((shift) > 0) ? (val) >> (shift) : (val) << -(shift))
3502 static RColor ulongToRColor(WMScreen * scr, unsigned long value)
3504 RColor color;
3505 XColor *xcolor = NULL;
3507 xcolor = wmalloc(sizeof(XColor));
3508 xcolor->pixel = value;
3509 XQueryColor(scr->display, scr->rcontext->cmap, xcolor);
3511 color.red = xcolor->red >> 8;
3512 color.green = xcolor->green >> 8;
3513 color.blue = xcolor->blue >> 8;
3514 color.alpha = 0;
3516 wfree(xcolor);
3518 return color;
3521 static unsigned char getShift(unsigned char value)
3523 unsigned char i = -1;
3525 if (value == 0)
3526 return 0;
3528 while (value) {
3529 value >>= 1;
3530 i++;
3533 return i;