remove a few unused constant for size of buffers
[wmaker-crm.git] / WINGs / wcolorpanel.c
blob12d54480450e78c03242718053498e3b9c867218
1 /*
2 * ColorPanel for WINGs
4 * by ]d : Original idea and basic initial code
5 * Pascal Hofstee : Code for wheeldrawing and calculating
6 * colors from it.
7 * Primary coder of this Color Panel.
8 * Alban Hertroys : Optimizations for algorithms for color-
9 * wheel. Also custom ColorPalettes and
10 * magnifying glass. Secondary coder ;)
11 * Alfredo K. Kojima : For pointing out memory-allocation
12 * problems and similair code-issues
13 * Marco van Hylckama-Vlieg : For once again doing the artwork ;-)
17 /* TODO:
18 * - Look at further optimization of colorWheel matrix calculation.
19 * It appears to be rather symmetric in angles of 60 degrees,
20 * while it is optimized in angles of 90 degrees.
21 * - Custom color-lists and custom colors in custom color-lists.
22 * - Stored colors
23 * - Resizing
26 #include "wconfig.h"
27 #include "WINGsP.h"
28 #include "rgb.h"
30 #include <errno.h>
31 #include <math.h>
32 #include <unistd.h>
33 #include <ctype.h>
34 #include <fcntl.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <dirent.h>
40 /* BUG There's something fishy with shaped windows */
41 /* Whithout shape extension the magnified image is completely broken -Dan */
43 #ifdef USE_XSHAPE
44 # include <X11/extensions/shape.h>
45 #endif
47 char *WMColorPanelColorChangedNotification = "WMColorPanelColorChangedNotification";
50 * Bitmaps for magnifying glass cursor
53 /* Cursor */
54 #define Cursor_x_hot 11
55 #define Cursor_y_hot 11
56 #define Cursor_width 32
57 #define Cursor_height 32
58 static unsigned char Cursor_bits[] = {
59 0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
60 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
61 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
62 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
63 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
64 0x00, 0x08, 0x00, 0x50, 0x00, 0x10, 0x00, 0x88, 0x00, 0x20, 0x00, 0x5c, 0x01, 0xc0, 0x81,
65 0x3b, 0x02, 0x00, 0x7e, 0x70, 0x05, 0x00, 0x00, 0xe0, 0x08, 0x00, 0x00, 0xc0, 0x15, 0x00,
66 0x00, 0x80, 0x23, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x5c,
67 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x70
70 /* Cursor shape-mask */
71 #define Cursor_shape_width 32
72 #define Cursor_shape_height 32
73 static unsigned char Cursor_shape_bits[] = {
74 0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
75 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
76 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
77 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
78 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
79 0x00, 0x08, 0x00, 0x70, 0x00, 0x10, 0x00, 0xf8, 0x00, 0x20, 0x00, 0xfc, 0x01, 0xc0, 0x81,
80 0xfb, 0x03, 0x00, 0x7e, 0xf0, 0x07, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xc0, 0x1f, 0x00,
81 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xfc,
82 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x70
85 /* Clip-mask for magnified pixels */
86 #define Cursor_mask_width 24
87 #define Cursor_mask_height 24
88 static unsigned char Cursor_mask_bits[] = {
89 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0xff, 0x07,
90 0xf0, 0xff, 0x0f, 0xf8, 0xff, 0x1f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f,
91 0xfc, 0xff, 0x3f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f,
92 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfc, 0xff, 0x3f,
93 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xf8, 0xff, 0x1f, 0xf0, 0xff, 0x0f,
94 0xe0, 0xff, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00
97 typedef struct MovingView {
98 WMView *view; /* The view this is all about */
99 XImage *image; /* What's under the view */
100 XImage *dirtyRect; /* Storage of overlapped image area */
101 Pixmap magPix; /* Magnified part of pixmap */
102 RColor color; /* Color of a pixel in the image */
103 int x, y; /* Position of view */
104 } MovingView;
106 typedef struct CPColor {
107 RColor rgb; /* The RGB values of the color */
108 RHSVColor hsv; /* The HSV values of the color */
109 enum { /* Which one was last set ? */
110 cpNone,
111 cpRGB,
112 cpHSV
113 } set;
114 } CPColor;
116 typedef struct WheelMatrix {
117 unsigned int width, height; /* Size of the colorwheel */
118 unsigned char *data[3]; /* Wheel data (R,G,B) */
119 unsigned char values[256]; /* Precalculated values R,G & B = 0-255 */
120 } wheelMatrix;
122 typedef struct W_ColorPanel {
123 WMWindow *win;
124 WMFont *font8;
125 WMFont *font12;
126 void *clientData;
127 WMAction2 *action;
129 /* Common Stuff */
130 WMColorWell *colorWell;
131 WMButton *magnifyBtn;
132 WMButton *wheelBtn;
133 WMButton *slidersBtn;
134 WMButton *customPaletteBtn;
135 WMButton *colorListBtn;
137 /* Magnifying Glass */
138 MovingView *magnifyGlass;
140 /* ColorWheel Panel */
141 WMFrame *wheelFrm;
142 WMSlider *wheelBrightnessS;
143 WMView *wheelView;
145 /* Slider Panels */
146 WMFrame *slidersFrm;
147 WMFrame *seperatorFrm;
148 WMButton *grayBtn;
149 WMButton *rgbBtn;
150 WMButton *cmykBtn;
151 WMButton *hsbBtn;
152 /* Gray Scale Panel */
153 WMFrame *grayFrm;
154 WMLabel *grayMinL;
155 WMLabel *grayMaxL;
156 WMSlider *grayBrightnessS;
157 WMTextField *grayBrightnessT;
158 WMButton *grayPresetBtn[7];
160 /* RGB Panel */
161 WMButton *rgbDecB;
162 WMButton *rgbHexB;
163 WMFrame *rgbFrm;
164 WMLabel *rgbMinL;
165 WMLabel *rgbMaxL;
166 WMSlider *rgbRedS;
167 WMSlider *rgbGreenS;
168 WMSlider *rgbBlueS;
169 WMTextField *rgbRedT;
170 WMTextField *rgbGreenT;
171 WMTextField *rgbBlueT;
172 enum {
173 RGBdec,
174 RGBhex
175 } rgbState;
177 /* CMYK Panel */
178 WMFrame *cmykFrm;
179 WMLabel *cmykMinL;
180 WMLabel *cmykMaxL;
181 WMSlider *cmykCyanS;
182 WMSlider *cmykMagentaS;
183 WMSlider *cmykYellowS;
184 WMSlider *cmykBlackS;
185 WMTextField *cmykCyanT;
186 WMTextField *cmykMagentaT;
187 WMTextField *cmykYellowT;
188 WMTextField *cmykBlackT;
190 /* HSB Panel */
191 WMFrame *hsbFrm;
192 WMSlider *hsbHueS;
193 WMSlider *hsbSaturationS;
194 WMSlider *hsbBrightnessS;
195 WMTextField *hsbHueT;
196 WMTextField *hsbSaturationT;
197 WMTextField *hsbBrightnessT;
199 /* Custom Palette Panel */
200 WMFrame *customPaletteFrm;
201 WMPopUpButton *customPaletteHistoryBtn;
202 WMFrame *customPaletteContentFrm;
203 WMPopUpButton *customPaletteMenuBtn;
204 WMView *customPaletteContentView;
206 /* Color List Panel */
207 WMFrame *colorListFrm;
208 WMPopUpButton *colorListHistoryBtn;
209 WMList *colorListContentLst;
210 WMPopUpButton *colorListColorMenuBtn;
211 WMPopUpButton *colorListListMenuBtn;
213 /* Look-Up Tables and Images */
214 wheelMatrix *wheelMtrx;
215 Pixmap wheelImg;
216 Pixmap selectionImg;
217 Pixmap selectionBackImg;
218 RImage *customPaletteImg;
219 char *lastBrowseDir;
221 /* Common Data Fields */
222 CPColor color; /* Current color */
223 WMColorPanelMode mode; /* Current color selection mode */
224 WMColorPanelMode slidersmode; /* Current color sel. mode sliders panel */
225 WMColorPanelMode lastChanged; /* Panel that last changed the color */
226 int colx, coly; /* (x,y) of sel.-marker in WheelMode */
227 int palx, paly; /* (x,y) of sel.-marker in
228 CustomPaletteMode */
229 double palXRatio, palYRatio; /* Ratios in x & y between
230 original and scaled
231 palettesize */
232 int currentPalette;
233 char *configurationPath;
235 struct {
236 unsigned int continuous:1;
237 unsigned int dragging:1;
238 } flags;
239 } W_ColorPanel;
241 enum {
242 CPmenuNewFromFile,
243 CPmenuRename,
244 CPmenuRemove,
245 CPmenuCopy,
246 CPmenuNewFromClipboard
247 } customPaletteMenuItem;
249 enum {
250 CLmenuAdd,
251 CLmenuRename,
252 CLmenuRemove
253 } colorListMenuItem;
255 #define PWIDTH 194
256 #define PHEIGHT 266
257 #define colorWheelSize 150
258 #define customPaletteWidth 182
259 #define customPaletteHeight 106
260 #define knobThickness 8
262 #define SPECTRUM_WIDTH 511
263 #define SPECTRUM_HEIGHT 360
265 #define COLORWHEEL_PART 1
266 #define CUSTOMPALETTE_PART 2
268 #ifndef M_PI
269 #define M_PI 3.14159265358979323846
270 #endif
272 static char *generateNewFilename(const char *curName);
273 static void convertCPColor(CPColor * color);
274 static RColor ulongToRColor(WMScreen * scr, unsigned long value);
275 static unsigned char getShift(unsigned char value);
277 static void modeButtonCallback(WMWidget * w, void *data);
278 static int getPickerPart(W_ColorPanel * panel, int x, int y);
279 static void readConfiguration(W_ColorPanel * panel);
280 static void readXColors(W_ColorPanel * panel);
282 static void closeWindowCallback(WMWidget * w, void *data);
284 static Cursor magnifyGrabPointer(W_ColorPanel * panel);
285 static WMPoint magnifyInitialize(W_ColorPanel * panel);
286 static void magnifyPutCursor(WMWidget * w, void *data);
287 static Pixmap magnifyCreatePixmap(WMColorPanel * panel);
288 static void magnifyGetImageStored(W_ColorPanel * panel, int x1, int y1, int x2, int y2);
289 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h);
291 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height);
292 static void wheelDestroyMatrix(wheelMatrix * matrix);
293 static void wheelInitMatrix(W_ColorPanel * panel);
294 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue);
295 static void wheelRender(W_ColorPanel * panel);
296 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs);
297 static void wheelPaint(W_ColorPanel * panel);
299 static void wheelHandleEvents(XEvent * event, void *data);
300 static void wheelHandleActionEvents(XEvent * event, void *data);
301 static void wheelBrightnessSliderCallback(WMWidget * w, void *data);
302 static void wheelUpdateSelection(W_ColorPanel * panel);
303 static void wheelUndrawSelection(W_ColorPanel * panel);
305 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y);
306 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
307 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel);
308 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor);
310 static void grayBrightnessSliderCallback(WMWidget * w, void *data);
311 static void grayPresetButtonCallback(WMWidget * w, void *data);
312 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification);
314 static void rgbSliderCallback(WMWidget * w, void *data);
315 static void rgbTextFieldCallback(void *observerData, WMNotification * notification);
316 static void rgbDecToHex(WMWidget *w, void *data);
318 static void cmykSliderCallback(WMWidget * w, void *data);
319 static void cmykTextFieldCallback(void *observerData, WMNotification * notification);
321 static void hsbSliderCallback(WMWidget * w, void *data);
322 static void hsbTextFieldCallback(void *observerData, WMNotification * notification);
323 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel);
324 static void hsbUpdateSaturationGradient(W_ColorPanel * panel);
325 static void hsbUpdateHueGradient(W_ColorPanel * panel);
327 static void customRenderSpectrum(W_ColorPanel * panel);
328 static void customSetPalette(W_ColorPanel * panel);
329 static void customPaletteHandleEvents(XEvent * event, void *data);
330 static void customPaletteHandleActionEvents(XEvent * event, void *data);
331 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y);
332 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
333 static void customPaletteMenuCallback(WMWidget * w, void *data);
334 static void customPaletteHistoryCallback(WMWidget * w, void *data);
336 static void customPaletteMenuNewFromFile(W_ColorPanel * panel);
337 static void customPaletteMenuRename(W_ColorPanel * panel);
338 static void customPaletteMenuRemove(W_ColorPanel * panel);
340 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect);
341 static void colorListSelect(WMWidget * w, void *data);
342 static void colorListColorMenuCallback(WMWidget * w, void *data);
343 static void colorListListMenuCallback(WMWidget * w, void *data);
345 static void wheelInit(W_ColorPanel * panel);
346 static void grayInit(W_ColorPanel * panel);
347 static void rgbInit(W_ColorPanel * panel);
348 static void cmykInit(W_ColorPanel * panel);
349 static void hsbInit(W_ColorPanel * panel);
352 static inline int get_textfield_as_integer(WMTextField *widget)
354 char *str;
355 int value;
357 str = WMGetTextFieldText(widget);
358 value = atoi(str);
359 wfree(str);
360 return value;
363 void WMSetColorPanelAction(WMColorPanel * panel, WMAction2 * action, void *data)
365 panel->action = action;
366 panel->clientData = data;
369 static WMColorPanel *makeColorPanel(WMScreen * scrPtr, const char *name)
371 WMColorPanel *panel;
372 RImage *image;
373 WMPixmap *pixmap;
374 RColor from;
375 RColor to;
376 WMColor *textcolor, *graybuttoncolor;
377 int i;
378 GC bgc = WMColorGC(scrPtr->black);
379 GC wgc = WMColorGC(scrPtr->white);
381 panel = wmalloc(sizeof(WMColorPanel));
382 panel->color.rgb.red = 0;
383 panel->color.rgb.green = 0;
384 panel->color.rgb.blue = 0;
385 panel->color.hsv.hue = 0;
386 panel->color.hsv.saturation = 0;
387 panel->color.hsv.value = 0;
388 panel->color.set = cpNone; /* Color has not been set yet */
390 panel->font8 = WMSystemFontOfSize(scrPtr, 8);
391 panel->font12 = WMSystemFontOfSize(scrPtr, 12);
393 panel->win = WMCreateWindowWithStyle(scrPtr, name,
394 WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
395 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
396 WMSetWindowTitle(panel->win, _("Colors"));
397 WMSetWindowCloseAction(panel->win, closeWindowCallback, panel);
399 /* Set Default ColorPanel Mode(s) */
400 panel->mode = WMWheelModeColorPanel;
401 panel->lastChanged = 0;
402 panel->slidersmode = WMRGBModeColorPanel;
403 panel->configurationPath = wstrconcat(wusergnusteppath(), "/Library/Colors/");
405 /* Some General Purpose Widgets */
406 panel->colorWell = WMCreateColorWell(panel->win);
407 WMResizeWidget(panel->colorWell, 134, 36);
408 WSetColorWellBordered(panel->colorWell, False);
409 WMMoveWidget(panel->colorWell, 56, 4);
411 panel->magnifyBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
412 WMResizeWidget(panel->magnifyBtn, 46, 36);
413 WMMoveWidget(panel->magnifyBtn, 6, 4);
414 WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
415 WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
416 WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
418 panel->wheelBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
419 WMResizeWidget(panel->wheelBtn, 46, 32);
420 WMMoveWidget(panel->wheelBtn, 6, 44);
421 WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
422 WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
423 WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
425 panel->slidersBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
426 WMResizeWidget(panel->slidersBtn, 46, 32);
427 WMMoveWidget(panel->slidersBtn, 52, 44);
428 WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
429 WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
430 WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
432 panel->customPaletteBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
433 WMResizeWidget(panel->customPaletteBtn, 46, 32);
434 WMMoveWidget(panel->customPaletteBtn, 98, 44);
435 WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
436 WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
437 WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
439 panel->colorListBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
440 WMResizeWidget(panel->colorListBtn, 46, 32);
441 WMMoveWidget(panel->colorListBtn, 144, 44);
442 WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
443 WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
444 WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
446 /* Let's Group some of them together */
447 WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
448 WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
449 WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
451 /* Widgets for the ColorWheel Panel */
452 panel->wheelFrm = WMCreateFrame(panel->win);
453 WMSetFrameRelief(panel->wheelFrm, WRFlat);
454 WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
455 WMMoveWidget(panel->wheelFrm, 5, 80);
457 panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
458 /* XXX Can we create a view ? */
459 W_ResizeView(panel->wheelView, colorWheelSize + 4, colorWheelSize + 4);
460 W_MoveView(panel->wheelView, 0, 0);
462 /* Create an event handler to handle expose/click events in ColorWheel */
463 WMCreateEventHandler(panel->wheelView,
464 ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
465 LeaveWindowMask | ButtonMotionMask, wheelHandleActionEvents, panel);
467 WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents, panel);
469 panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
470 WMResizeWidget(panel->wheelBrightnessS, 16, 153);
471 WMMoveWidget(panel->wheelBrightnessS, 5 + colorWheelSize + 14, 1);
472 WMSetSliderMinValue(panel->wheelBrightnessS, 0);
473 WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
474 WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback, panel);
475 WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
477 panel->wheelMtrx = wheelCreateMatrix(colorWheelSize + 4, colorWheelSize + 4);
478 wheelInitMatrix(panel);
480 /* Widgets for the Slider Panels */
481 panel->slidersFrm = WMCreateFrame(panel->win);
482 WMSetFrameRelief(panel->slidersFrm, WRFlat);
483 WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
484 WMMoveWidget(panel->slidersFrm, 4, 80);
486 panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
487 WMSetFrameRelief(panel->seperatorFrm, WRPushed);
488 WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
489 WMMoveWidget(panel->seperatorFrm, 0, 1);
491 panel->grayBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
492 WMResizeWidget(panel->grayBtn, 46, 24);
493 WMMoveWidget(panel->grayBtn, 1, 8);
494 WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
495 WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
496 WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
498 panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
499 WMResizeWidget(panel->rgbBtn, 46, 24);
500 WMMoveWidget(panel->rgbBtn, 47, 8);
501 WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
502 WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
503 WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
505 panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
506 WMResizeWidget(panel->cmykBtn, 46, 24);
507 WMMoveWidget(panel->cmykBtn, 93, 8);
508 WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
509 WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
510 WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
512 panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
513 WMResizeWidget(panel->hsbBtn, 46, 24);
514 WMMoveWidget(panel->hsbBtn, 139, 8);
515 WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
516 WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
517 WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
519 /* Let's Group the Slider Panel Buttons Together */
520 WMGroupButtons(panel->grayBtn, panel->rgbBtn);
521 WMGroupButtons(panel->grayBtn, panel->cmykBtn);
522 WMGroupButtons(panel->grayBtn, panel->hsbBtn);
524 textcolor = WMDarkGrayColor(scrPtr);
526 /* Widgets for GrayScale Panel */
527 panel->grayFrm = WMCreateFrame(panel->slidersFrm);
528 WMSetFrameRelief(panel->grayFrm, WRFlat);
529 WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
530 WMMoveWidget(panel->grayFrm, 0, 34);
532 panel->grayMinL = WMCreateLabel(panel->grayFrm);
533 WMResizeWidget(panel->grayMinL, 20, 10);
534 WMMoveWidget(panel->grayMinL, 2, 2);
535 WMSetLabelText(panel->grayMinL, "0");
536 WMSetLabelTextAlignment(panel->grayMinL, WALeft);
537 WMSetLabelTextColor(panel->grayMinL, textcolor);
538 WMSetLabelFont(panel->grayMinL, panel->font8);
540 panel->grayMaxL = WMCreateLabel(panel->grayFrm);
541 WMResizeWidget(panel->grayMaxL, 40, 10);
542 WMMoveWidget(panel->grayMaxL, 104, 2);
543 WMSetLabelText(panel->grayMaxL, "100");
544 WMSetLabelTextAlignment(panel->grayMaxL, WARight);
545 WMSetLabelTextColor(panel->grayMaxL, textcolor);
546 WMSetLabelFont(panel->grayMaxL, panel->font8);
548 panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
549 WMResizeWidget(panel->grayBrightnessS, 141, 16);
550 WMMoveWidget(panel->grayBrightnessS, 2, 14);
551 WMSetSliderMinValue(panel->grayBrightnessS, 0);
552 WMSetSliderMaxValue(panel->grayBrightnessS, 100);
553 WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
554 WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback, panel);
556 from.red = 0;
557 from.green = 0;
558 from.blue = 0;
560 to.red = 255;
561 to.green = 255;
562 to.blue = 255;
564 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
565 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
566 RReleaseImage(image);
568 if (pixmap)
569 W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap,
570 panel->font12, 2, 0, 100, WALeft, scrPtr->white,
571 False, _("Brightness"), strlen(_("Brightness")));
572 else
573 wwarning(_("Color Panel: Could not allocate memory"));
575 WMSetSliderImage(panel->grayBrightnessS, pixmap);
576 WMReleasePixmap(pixmap);
578 panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
579 WMResizeWidget(panel->grayBrightnessT, 40, 18);
580 WMMoveWidget(panel->grayBrightnessT, 146, 13);
581 WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
582 WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel,
583 WMTextDidEndEditingNotification, panel->grayBrightnessT);
585 for (i = 0; i < 7; i++) {
586 pixmap = WMCreatePixmap(scrPtr, 13, 13, scrPtr->depth, False);
588 graybuttoncolor = WMCreateRGBColor(scrPtr, (255 / 6) * i << 8,
589 (255 / 6) * i << 8, (255 / 6) * i << 8, True);
590 WMPaintColorSwatch(graybuttoncolor, pixmap->pixmap, 0, 0, 15, 15);
591 WMReleaseColor(graybuttoncolor);
593 panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
594 WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
595 WMMoveWidget(panel->grayPresetBtn[i], 2 + (i * 20), 34);
596 WMSetButtonAction(panel->grayPresetBtn[i], grayPresetButtonCallback, panel);
597 WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
598 WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
599 WMReleasePixmap(pixmap);
603 /* End of GrayScale Panel */
605 /* Widgets for RGB Panel */
606 panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
607 WMSetFrameRelief(panel->rgbFrm, WRFlat);
608 WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
609 WMMoveWidget(panel->rgbFrm, 0, 34);
611 panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
612 WMResizeWidget(panel->rgbMinL, 20, 10);
613 WMMoveWidget(panel->rgbMinL, 2, 2);
614 WMSetLabelText(panel->rgbMinL, "0");
615 WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
616 WMSetLabelTextColor(panel->rgbMinL, textcolor);
617 WMSetLabelFont(panel->rgbMinL, panel->font8);
619 panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
620 WMResizeWidget(panel->rgbMaxL, 40, 10);
621 WMMoveWidget(panel->rgbMaxL, 104, 2);
622 WMSetLabelText(panel->rgbMaxL, "255");
623 WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
624 WMSetLabelTextColor(panel->rgbMaxL, textcolor);
625 WMSetLabelFont(panel->rgbMaxL, panel->font8);
627 panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
628 WMResizeWidget(panel->rgbRedS, 141, 16);
629 WMMoveWidget(panel->rgbRedS, 2, 14);
630 WMSetSliderMinValue(panel->rgbRedS, 0);
631 WMSetSliderMaxValue(panel->rgbRedS, 255);
632 WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
633 WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
635 to.red = 255;
636 to.green = 0;
637 to.blue = 0;
639 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
640 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
641 RReleaseImage(image);
643 if (pixmap)
644 W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12,
645 2, 0, 100, WALeft, scrPtr->white, False, _("Red"), strlen(_("Red")));
646 else
647 wwarning(_("Color Panel: Could not allocate memory"));
649 WMSetSliderImage(panel->rgbRedS, pixmap);
650 WMReleasePixmap(pixmap);
652 panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
653 WMResizeWidget(panel->rgbRedT, 40, 18);
654 WMMoveWidget(panel->rgbRedT, 146, 13);
655 WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
656 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbRedT);
658 panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
659 WMResizeWidget(panel->rgbGreenS, 141, 16);
660 WMMoveWidget(panel->rgbGreenS, 2, 36);
661 WMSetSliderMinValue(panel->rgbGreenS, 0);
662 WMSetSliderMaxValue(panel->rgbGreenS, 255);
663 WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
664 WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
666 to.red = 0;
667 to.green = 255;
668 to.blue = 0;
670 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
671 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
672 RReleaseImage(image);
674 if (pixmap)
675 W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12,
676 2, 0, 100, WALeft, scrPtr->white, False, _("Green"), strlen(_("Green")));
677 else
678 wwarning(_("Color Panel: Could not allocate memory"));
680 WMSetSliderImage(panel->rgbGreenS, pixmap);
681 WMReleasePixmap(pixmap);
683 panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
684 WMResizeWidget(panel->rgbGreenT, 40, 18);
685 WMMoveWidget(panel->rgbGreenT, 146, 35);
686 WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
687 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbGreenT);
689 panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
690 WMResizeWidget(panel->rgbBlueS, 141, 16);
691 WMMoveWidget(panel->rgbBlueS, 2, 58);
692 WMSetSliderMinValue(panel->rgbBlueS, 0);
693 WMSetSliderMaxValue(panel->rgbBlueS, 255);
694 WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
695 WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
697 to.red = 0;
698 to.green = 0;
699 to.blue = 255;
701 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
702 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
703 RReleaseImage(image);
705 if (pixmap)
706 W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12,
707 2, 0, 100, WALeft, scrPtr->white, False, _("Blue"), strlen(_("Blue")));
708 else
709 wwarning(_("Color Panel: Could not allocate memory"));
711 WMSetSliderImage(panel->rgbBlueS, pixmap);
712 WMReleasePixmap(pixmap);
714 panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
715 WMResizeWidget(panel->rgbBlueT, 40, 18);
716 WMMoveWidget(panel->rgbBlueT, 146, 57);
717 WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
718 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbBlueT);
720 panel->rgbDecB = WMCreateButton(panel->rgbFrm, WBTRadio);
721 WMSetButtonText(panel->rgbDecB, _("Decimal"));
722 WMSetButtonSelected(panel->rgbDecB, 1);
723 panel->rgbState = RGBdec;
724 WMSetButtonAction(panel->rgbDecB, rgbDecToHex, panel);
725 WMResizeWidget(panel->rgbDecB, PWIDTH - 8, 23);
726 WMMoveWidget(panel->rgbDecB, 2, 81);
728 panel->rgbHexB = WMCreateButton(panel->rgbFrm, WBTRadio);
729 WMSetButtonText(panel->rgbHexB, _("Hexadecimal"));
730 WMSetButtonAction(panel->rgbHexB, rgbDecToHex, panel);
731 WMResizeWidget(panel->rgbHexB, PWIDTH - 8, 23);
732 WMMoveWidget(panel->rgbHexB, 2, 104);
734 WMGroupButtons(panel->rgbDecB, panel->rgbHexB);
736 /* End of RGB Panel */
738 /* Widgets for CMYK Panel */
739 panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
740 WMSetFrameRelief(panel->cmykFrm, WRFlat);
741 WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
742 WMMoveWidget(panel->cmykFrm, 0, 34);
744 panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
745 WMResizeWidget(panel->cmykMinL, 20, 10);
746 WMMoveWidget(panel->cmykMinL, 2, 2);
747 WMSetLabelText(panel->cmykMinL, "0");
748 WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
749 WMSetLabelTextColor(panel->cmykMinL, textcolor);
750 WMSetLabelFont(panel->cmykMinL, panel->font8);
752 panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
753 WMResizeWidget(panel->cmykMaxL, 40, 10);
754 WMMoveWidget(panel->cmykMaxL, 104, 2);
755 WMSetLabelText(panel->cmykMaxL, "100");
756 WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
757 WMSetLabelTextColor(panel->cmykMaxL, textcolor);
758 WMSetLabelFont(panel->cmykMaxL, panel->font8);
760 panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
761 WMResizeWidget(panel->cmykCyanS, 141, 16);
762 WMMoveWidget(panel->cmykCyanS, 2, 14);
763 WMSetSliderMinValue(panel->cmykCyanS, 0);
764 WMSetSliderMaxValue(panel->cmykCyanS, 100);
765 WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
766 WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
768 from.red = 255;
769 from.green = 255;
770 from.blue = 255;
772 to.red = 0;
773 to.green = 255;
774 to.blue = 255;
776 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
777 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
778 RReleaseImage(image);
780 if (pixmap)
781 W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12,
782 2, 0, 100, WALeft, scrPtr->black, False, _("Cyan"), strlen(_("Cyan")));
783 else
784 wwarning(_("Color Panel: Could not allocate memory"));
786 WMSetSliderImage(panel->cmykCyanS, pixmap);
787 WMReleasePixmap(pixmap);
789 panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
790 WMResizeWidget(panel->cmykCyanT, 40, 18);
791 WMMoveWidget(panel->cmykCyanT, 146, 13);
792 WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
793 WMAddNotificationObserver(cmykTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->cmykCyanT);
795 panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
796 WMResizeWidget(panel->cmykMagentaS, 141, 16);
797 WMMoveWidget(panel->cmykMagentaS, 2, 36);
798 WMSetSliderMinValue(panel->cmykMagentaS, 0);
799 WMSetSliderMaxValue(panel->cmykMagentaS, 100);
800 WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
801 WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
803 to.red = 255;
804 to.green = 0;
805 to.blue = 255;
807 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
808 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
809 RReleaseImage(image);
811 if (pixmap)
812 W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12,
813 2, 0, 100, WALeft, scrPtr->black, False, _("Magenta"), strlen(_("Magenta")));
814 else
815 wwarning(_("Color Panel: Could not allocate memory"));
817 WMSetSliderImage(panel->cmykMagentaS, pixmap);
818 WMReleasePixmap(pixmap);
820 panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
821 WMResizeWidget(panel->cmykMagentaT, 40, 18);
822 WMMoveWidget(panel->cmykMagentaT, 146, 35);
823 WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
824 WMAddNotificationObserver(cmykTextFieldCallback, panel,
825 WMTextDidEndEditingNotification, panel->cmykMagentaT);
827 panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
828 WMResizeWidget(panel->cmykYellowS, 141, 16);
829 WMMoveWidget(panel->cmykYellowS, 2, 58);
830 WMSetSliderMinValue(panel->cmykYellowS, 0);
831 WMSetSliderMaxValue(panel->cmykYellowS, 100);
832 WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
833 WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
835 to.red = 255;
836 to.green = 255;
837 to.blue = 0;
839 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
840 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
841 RReleaseImage(image);
843 if (pixmap)
844 W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12,
845 2, 0, 100, WALeft, scrPtr->black, False, _("Yellow"), strlen(_("Yellow")));
846 else
847 wwarning(_("Color Panel: Could not allocate memory"));
849 WMSetSliderImage(panel->cmykYellowS, pixmap);
850 WMReleasePixmap(pixmap);
852 panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
853 WMResizeWidget(panel->cmykYellowT, 40, 18);
854 WMMoveWidget(panel->cmykYellowT, 146, 57);
855 WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
856 WMAddNotificationObserver(cmykTextFieldCallback, panel,
857 WMTextDidEndEditingNotification, panel->cmykYellowT);
859 panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
860 WMResizeWidget(panel->cmykBlackS, 141, 16);
861 WMMoveWidget(panel->cmykBlackS, 2, 80);
862 WMSetSliderMinValue(panel->cmykBlackS, 0);
863 WMSetSliderMaxValue(panel->cmykBlackS, 100);
864 WMSetSliderValue(panel->cmykBlackS, 0);
865 WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
866 WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
868 to.red = 0;
869 to.green = 0;
870 to.blue = 0;
872 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
873 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
874 RReleaseImage(image);
876 if (pixmap)
877 W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12,
878 2, 0, 100, WALeft, scrPtr->black, False, _("Black"), strlen(_("Black")));
879 else
880 wwarning(_("Color Panel: Could not allocate memory"));
882 WMSetSliderImage(panel->cmykBlackS, pixmap);
883 WMReleasePixmap(pixmap);
885 panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
886 WMResizeWidget(panel->cmykBlackT, 40, 18);
887 WMMoveWidget(panel->cmykBlackT, 146, 79);
888 WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
889 WMAddNotificationObserver(cmykTextFieldCallback, panel,
890 WMTextDidEndEditingNotification, panel->cmykBlackT);
891 /* End of CMYK Panel */
893 /* Widgets for HSB Panel */
894 panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
895 WMSetFrameRelief(panel->hsbFrm, WRFlat);
896 WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
897 WMMoveWidget(panel->hsbFrm, 0, 34);
899 panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
900 WMResizeWidget(panel->hsbHueS, 141, 16);
901 WMMoveWidget(panel->hsbHueS, 2, 14);
902 WMSetSliderMinValue(panel->hsbHueS, 0);
903 WMSetSliderMaxValue(panel->hsbHueS, 359);
904 WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
905 WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
907 panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
908 WMResizeWidget(panel->hsbHueT, 40, 18);
909 WMMoveWidget(panel->hsbHueT, 146, 13);
910 WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
911 WMAddNotificationObserver(hsbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->hsbHueT);
913 panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
914 WMResizeWidget(panel->hsbSaturationS, 141, 16);
915 WMMoveWidget(panel->hsbSaturationS, 2, 36);
916 WMSetSliderMinValue(panel->hsbSaturationS, 0);
917 WMSetSliderMaxValue(panel->hsbSaturationS, 100);
918 WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
919 WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
921 panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
922 WMResizeWidget(panel->hsbSaturationT, 40, 18);
923 WMMoveWidget(panel->hsbSaturationT, 146, 35);
924 WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
925 WMAddNotificationObserver(hsbTextFieldCallback, panel,
926 WMTextDidEndEditingNotification, panel->hsbSaturationT);
928 panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
929 WMResizeWidget(panel->hsbBrightnessS, 141, 16);
930 WMMoveWidget(panel->hsbBrightnessS, 2, 58);
931 WMSetSliderMinValue(panel->hsbBrightnessS, 0);
932 WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
933 WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
934 WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
936 panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
937 WMResizeWidget(panel->hsbBrightnessT, 40, 18);
938 WMMoveWidget(panel->hsbBrightnessT, 146, 57);
939 WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
940 WMAddNotificationObserver(hsbTextFieldCallback, panel,
941 WMTextDidEndEditingNotification, panel->hsbBrightnessT);
942 /* End of HSB Panel */
944 WMReleaseColor(textcolor);
946 /* Widgets for the CustomPalette Panel */
947 panel->customPaletteFrm = WMCreateFrame(panel->win);
948 WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
949 WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
950 WMMoveWidget(panel->customPaletteFrm, 5, 80);
952 panel->customPaletteHistoryBtn = WMCreatePopUpButton(panel->customPaletteFrm);
953 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, _("Spectrum"));
954 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
955 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1);
956 WMSetPopUpButtonAction(panel->customPaletteHistoryBtn, customPaletteHistoryCallback, panel);
957 WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
958 WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
960 panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
961 WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
962 WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
963 WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
965 panel->customPaletteContentView = W_CreateView(W_VIEW(panel->customPaletteContentFrm));
966 /* XXX Test if we can create a view */
967 W_ResizeView(panel->customPaletteContentView, customPaletteWidth, customPaletteHeight);
968 W_MoveView(panel->customPaletteContentView, 2, 2);
970 /* Create event handler to handle expose/click events in CustomPalette */
971 WMCreateEventHandler(panel->customPaletteContentView,
972 ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
973 ButtonMotionMask, customPaletteHandleActionEvents, panel);
975 WMCreateEventHandler(panel->customPaletteContentView, ExposureMask, customPaletteHandleEvents, panel);
977 panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
978 WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
979 WMSetPopUpButtonText(panel->customPaletteMenuBtn, _("Palette"));
980 WMSetPopUpButtonAction(panel->customPaletteMenuBtn, customPaletteMenuCallback, panel);
981 WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
982 WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
984 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from File..."));
985 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Rename..."));
986 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Remove"));
987 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Copy"));
988 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from Clipboard"));
990 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, 0);
991 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, 0);
992 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuCopy, 0);
993 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuNewFromClipboard, 0);
995 customRenderSpectrum(panel);
996 panel->currentPalette = 0;
997 panel->palx = customPaletteWidth / 2;
998 panel->paly = customPaletteHeight / 2;
1000 /* Widgets for the ColorList Panel */
1001 panel->colorListFrm = WMCreateFrame(panel->win);
1002 WMSetFrameRelief(panel->colorListFrm, WRFlat);
1003 WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
1004 WMMoveWidget(panel->colorListFrm, 5, 80);
1006 panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
1007 WMAddPopUpButtonItem(panel->colorListHistoryBtn, _("X11-Colors"));
1008 WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn,
1009 WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn) - 1);
1010 /* WMSetPopUpButtonAction(panel->colorListHistoryBtn,
1011 * colorListHistoryCallback, panel); */
1012 WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
1013 WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
1015 panel->colorListContentLst = WMCreateList(panel->colorListFrm);
1016 WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
1017 WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
1018 WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
1019 WMMoveWidget(panel->colorListContentLst, 0, 23);
1020 WMHangData(panel->colorListContentLst, panel);
1022 panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1023 WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
1024 WMSetPopUpButtonText(panel->colorListColorMenuBtn, _("Color"));
1025 WMSetPopUpButtonAction(panel->colorListColorMenuBtn, colorListColorMenuCallback, panel);
1026 WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16) / 2, 20);
1027 WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
1029 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Add..."));
1030 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Rename..."));
1031 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Remove"));
1033 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuAdd, 0);
1034 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRename, 0);
1035 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRemove, 0);
1037 panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1038 WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
1039 WMSetPopUpButtonText(panel->colorListListMenuBtn, _("List"));
1040 WMSetPopUpButtonAction(panel->colorListListMenuBtn, colorListListMenuCallback, panel);
1041 WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2, 20);
1042 WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2 + 8, PHEIGHT - 130);
1044 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("New..."));
1045 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Rename..."));
1046 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Remove"));
1048 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuAdd, 0);
1049 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
1050 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
1052 WMRealizeWidget(panel->win);
1053 WMMapSubwidgets(panel->win);
1055 WMMapSubwidgets(panel->wheelFrm);
1056 WMMapSubwidgets(panel->slidersFrm);
1057 WMMapSubwidgets(panel->grayFrm);
1058 WMMapSubwidgets(panel->rgbFrm);
1059 WMMapSubwidgets(panel->cmykFrm);
1060 WMMapSubwidgets(panel->hsbFrm);
1061 WMMapSubwidgets(panel->customPaletteFrm);
1062 WMMapSubwidgets(panel->customPaletteContentFrm);
1063 WMMapSubwidgets(panel->colorListFrm);
1065 /* Pixmap to indicate selection positions
1066 * wheelframe MUST be mapped.
1068 panel->selectionImg = XCreatePixmap(scrPtr->display, WMWidgetXID(panel->win), 4, 4, scrPtr->depth);
1069 XFillRectangle(scrPtr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1070 XFillRectangle(scrPtr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1072 readConfiguration(panel);
1073 readXColors(panel);
1075 return panel;
1078 WMColorPanel *WMGetColorPanel(WMScreen * scrPtr)
1080 WMColorPanel *panel;
1082 if (scrPtr->sharedColorPanel)
1083 return scrPtr->sharedColorPanel;
1085 panel = makeColorPanel(scrPtr, "colorPanel");
1087 scrPtr->sharedColorPanel = panel;
1089 return panel;
1092 void WMFreeColorPanel(WMColorPanel * panel)
1094 W_Screen *scr;
1096 if (!panel)
1097 return;
1099 scr = WMWidgetScreen(panel->win);
1100 if (panel == scr->sharedColorPanel) {
1101 scr->sharedColorPanel = NULL;
1104 WMRemoveNotificationObserver(panel);
1105 WMUnmapWidget(panel->win);
1107 /* fonts */
1108 WMReleaseFont(panel->font8);
1109 WMReleaseFont(panel->font12);
1111 /* pixmaps */
1112 wheelDestroyMatrix(panel->wheelMtrx);
1113 if (panel->wheelImg)
1114 XFreePixmap(scr->display, panel->wheelImg);
1115 if (panel->selectionImg)
1116 XFreePixmap(scr->display, panel->selectionImg);
1117 if (panel->selectionBackImg)
1118 XFreePixmap(scr->display, panel->selectionBackImg);
1119 RReleaseImage(panel->customPaletteImg);
1121 /* structs */
1122 if (panel->lastBrowseDir)
1123 wfree(panel->lastBrowseDir);
1124 if (panel->configurationPath)
1125 wfree(panel->configurationPath);
1127 WMDestroyWidget(panel->win);
1129 wfree(panel);
1132 void WMCloseColorPanel(WMColorPanel * panel)
1134 WMFreeColorPanel(panel);
1137 void WMShowColorPanel(WMColorPanel * panel)
1139 WMScreen *scr = WMWidgetScreen(panel->win);
1140 WMColor *white = WMWhiteColor(scr);
1142 if (panel->color.set == cpNone)
1143 WMSetColorPanelColor(panel, white);
1144 WMReleaseColor(white);
1146 if (panel->mode != WMWheelModeColorPanel)
1147 WMPerformButtonClick(panel->wheelBtn);
1149 WMMapWidget(panel->win);
1152 static void closeWindowCallback(WMWidget * w, void *data)
1154 W_ColorPanel *panel = (W_ColorPanel *) data;
1156 /* Parameter not used, but tell the compiler that it is ok */
1157 (void) w;
1159 WMCloseColorPanel(panel);
1162 static void readConfiguration(W_ColorPanel * panel)
1164 /* XXX Doesn't take care of "invalid" files */
1166 DIR *dPtr;
1167 struct dirent *dp;
1168 struct stat stat_buf;
1169 int item;
1171 if (stat(panel->configurationPath, &stat_buf) != 0) {
1172 if (mkdir(panel->configurationPath, S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH) != 0) {
1173 werror(_("Color Panel: Could not create directory %s needed"
1174 " to store configurations"), panel->configurationPath);
1175 WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
1176 WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
1177 WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
1178 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1179 _("File Error"),
1180 _("Could not create ColorPanel configuration directory"),
1181 _("OK"), NULL, NULL);
1183 return;
1186 if (!(dPtr = opendir(panel->configurationPath))) {
1187 wwarning("%s: %s", _("Color Panel: Could not find file"), panel->configurationPath);
1188 return;
1191 while ((dp = readdir(dPtr)) != NULL) {
1192 unsigned int perm_mask;
1193 char *path = wstrconcat(panel->configurationPath,
1194 dp->d_name);
1196 if (dp->d_name[0] != '.') {
1197 item = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
1198 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
1200 perm_mask = (access(path, R_OK) == 0);
1201 WMSetPopUpButtonItemEnabled(panel->customPaletteHistoryBtn, item, perm_mask);
1203 wfree(path);
1205 closedir(dPtr);
1208 static void readXColors(W_ColorPanel * panel)
1210 WMListItem *item;
1211 const RGBColor *entry;
1213 for (entry = rgbColors; entry->name != NULL; entry++) {
1214 item = WMAddListItem(panel->colorListContentLst, entry->name);
1215 item->clientData = (void *)&(entry->color);
1219 void WMSetColorPanelPickerMode(WMColorPanel * panel, WMColorPanelMode mode)
1221 W_Screen *scr = WMWidgetScreen(panel->win);
1223 if (mode != WMWheelModeColorPanel) {
1224 WMUnmapWidget(panel->wheelFrm);
1225 if (panel->selectionBackImg) {
1226 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1227 panel->selectionBackImg = None;
1230 if (mode != WMGrayModeColorPanel)
1231 WMUnmapWidget(panel->grayFrm);
1232 if (mode != WMRGBModeColorPanel)
1233 WMUnmapWidget(panel->rgbFrm);
1234 if (mode != WMCMYKModeColorPanel)
1235 WMUnmapWidget(panel->cmykFrm);
1236 if (mode != WMHSBModeColorPanel)
1237 WMUnmapWidget(panel->hsbFrm);
1238 if (mode != WMCustomPaletteModeColorPanel) {
1239 WMUnmapWidget(panel->customPaletteFrm);
1240 if (panel->selectionBackImg) {
1241 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1242 panel->selectionBackImg = None;
1245 if (mode != WMColorListModeColorPanel)
1246 WMUnmapWidget(panel->colorListFrm);
1247 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
1248 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1249 WMUnmapWidget(panel->slidersFrm);
1250 else
1251 panel->slidersmode = mode;
1253 if (mode == WMWheelModeColorPanel) {
1254 WMMapWidget(panel->wheelFrm);
1255 WMSetButtonSelected(panel->wheelBtn, True);
1256 if (panel->lastChanged != WMWheelModeColorPanel)
1257 wheelInit(panel);
1258 wheelRender(panel);
1259 wheelPaint(panel);
1260 } else if (mode == WMGrayModeColorPanel) {
1261 WMMapWidget(panel->slidersFrm);
1262 WMSetButtonSelected(panel->slidersBtn, True);
1263 WMMapWidget(panel->grayFrm);
1264 WMSetButtonSelected(panel->grayBtn, True);
1265 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1266 if (panel->lastChanged != WMGrayModeColorPanel)
1267 grayInit(panel);
1268 } else if (mode == WMRGBModeColorPanel) {
1269 WMMapWidget(panel->slidersFrm);
1270 WMSetButtonSelected(panel->slidersBtn, True);
1271 WMMapWidget(panel->rgbFrm);
1272 WMSetButtonSelected(panel->rgbBtn, True);
1273 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1274 if (panel->lastChanged != WMRGBModeColorPanel)
1275 rgbInit(panel);
1276 } else if (mode == WMCMYKModeColorPanel) {
1277 WMMapWidget(panel->slidersFrm);
1278 WMSetButtonSelected(panel->slidersBtn, True);
1279 WMMapWidget(panel->cmykFrm);
1280 WMSetButtonSelected(panel->cmykBtn, True);
1281 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1282 if (panel->lastChanged != WMCMYKModeColorPanel)
1283 cmykInit(panel);
1284 } else if (mode == WMHSBModeColorPanel) {
1285 WMMapWidget(panel->slidersFrm);
1286 WMSetButtonSelected(panel->slidersBtn, True);
1287 WMMapWidget(panel->hsbFrm);
1288 WMSetButtonSelected(panel->hsbBtn, True);
1289 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1290 if (panel->lastChanged != WMHSBModeColorPanel)
1291 hsbInit(panel);
1292 } else if (mode == WMCustomPaletteModeColorPanel) {
1293 WMMapWidget(panel->customPaletteFrm);
1294 WMSetButtonSelected(panel->customPaletteBtn, True);
1295 customSetPalette(panel);
1296 } else if (mode == WMColorListModeColorPanel) {
1297 WMMapWidget(panel->colorListFrm);
1298 WMSetButtonSelected(panel->colorListBtn, True);
1301 panel->mode = mode;
1304 WMColor *WMGetColorPanelColor(WMColorPanel * panel)
1306 return WMGetColorWellColor(panel->colorWell);
1309 void WMSetColorPanelColor(WMColorPanel * panel, WMColor * color)
1311 WMSetColorWellColor(panel->colorWell, color);
1313 panel->color.rgb.red = color->color.red >> 8;
1314 panel->color.rgb.green = color->color.green >> 8;
1315 panel->color.rgb.blue = color->color.blue >> 8;
1316 panel->color.set = cpRGB;
1318 if (panel->mode == panel->lastChanged)
1319 panel->lastChanged = 0;
1321 WMSetColorPanelPickerMode(panel, panel->mode);
1324 static void updateSwatch(WMColorPanel * panel, CPColor color)
1326 WMScreen *scr = WMWidgetScreen(panel->win);
1327 WMColor *wellcolor;
1329 if (color.set != cpRGB)
1330 convertCPColor(&color);
1332 panel->color = color;
1334 wellcolor = WMCreateRGBColor(scr, color.rgb.red << 8, color.rgb.green << 8, color.rgb.blue << 8, True);
1336 WMSetColorWellColor(panel->colorWell, wellcolor);
1337 WMReleaseColor(wellcolor);
1339 if (!panel->flags.dragging || panel->flags.continuous) {
1340 if (panel->action)
1341 (*panel->action) (panel, panel->clientData);
1343 WMPostNotificationName(WMColorPanelColorChangedNotification, panel, NULL);
1347 static void modeButtonCallback(WMWidget * w, void *data)
1349 W_ColorPanel *panel = (W_ColorPanel *) (data);
1351 if (w == panel->wheelBtn)
1352 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1353 else if (w == panel->slidersBtn)
1354 WMSetColorPanelPickerMode(panel, panel->slidersmode);
1355 else if (w == panel->customPaletteBtn)
1356 WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
1357 else if (w == panel->colorListBtn)
1358 WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
1359 else if (w == panel->grayBtn)
1360 WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
1361 else if (w == panel->rgbBtn)
1362 WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
1363 else if (w == panel->cmykBtn)
1364 WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
1365 else if (w == panel->hsbBtn)
1366 WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
1369 /****************** Magnifying Cursor Functions *******************/
1371 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h)
1373 int x0 = 0, y0 = 0, w0 = w, h0 = h;
1374 const int displayWidth = DisplayWidth(scr->display, scr->screen),
1375 displayHeight = DisplayHeight(scr->display, scr->screen);
1377 if (!(image && image->data)) {
1378 /* The image in panel->magnifyGlass->image does not exist yet.
1379 * Grab one from the screen (not beyond) and use it from now on.
1381 if (!(image = XGetImage(scr->display, scr->rootWin,
1382 x - Cursor_x_hot, y - Cursor_y_hot, w, h, AllPlanes, ZPixmap)))
1383 wwarning(_("Color Panel: X failed request"));
1385 return image;
1388 /* Coordinate correction for back pixmap
1389 * if magnifying glass is at screen-borders
1392 /* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
1393 * Hatched area is beyond screen border.
1395 * |<-Cursor_x_hot->|
1396 * ________________|_____
1397 * |/ / / / / / /| | |
1398 * | / / / / / / |(x,y) |
1399 * |/_/_/_/_/_/_/|________|
1400 * |<----x0----->|<--w0-->|
1404 /* Figure 2: Shifting of rectangle-to-grab at bottom/right
1405 * screen borders
1406 * Hatched area is beyond screen border
1408 * |<-Cursor_x_hot->|
1409 * ________________|_______________
1410 * | | | / / / / / /|
1411 * | (x,y)|/ / / / / / |
1412 * |___________________|_/_/_/_/_/_/|
1413 * |<-------w0-------->| |
1414 * |<---------------w--|----------->|
1415 * | |
1416 * x0 Displaywidth-1
1419 if (x < Cursor_x_hot) { /* see fig. 1 */
1420 x0 = Cursor_x_hot - x;
1421 w0 = w - x0;
1424 if (displayWidth - 1 < x - Cursor_x_hot + w) { /* see fig. 2 */
1425 w0 = (displayWidth) - (x - Cursor_x_hot);
1428 if (y < Cursor_y_hot) { /* see fig. 1 */
1429 y0 = Cursor_y_hot - y;
1430 h0 = h - y0;
1433 if (displayHeight - 1 < y - Cursor_y_hot + h) { /* see fig. 2 */
1434 h0 = (displayHeight) - (y - Cursor_y_hot);
1436 /* end of coordinate correction */
1438 /* Grab an image from the screen, clipped if necessary,
1439 * and put it in the existing panel->magnifyGlass->image
1440 * with the corresponding clipping offset.
1442 if (!XGetSubImage(scr->display, scr->rootWin,
1443 x - Cursor_x_hot + x0, y - Cursor_y_hot + y0, w0, h0, AllPlanes, ZPixmap, image, x0, y0))
1444 wwarning(_("Color Panel: X failed request"));
1446 return NULL;
1449 static void magnifyGetImageStored(WMColorPanel * panel, int x1, int y1, int x2, int y2)
1451 /* (x1, y1) = topleft corner of existing rectangle
1452 * (x2, y2) = topleft corner of new position
1455 W_Screen *scr = WMWidgetScreen(panel->win);
1456 int xa = 0, ya = 0, xb = 0, yb = 0;
1457 int width, height;
1458 const int dx = abs(x2 - x1), dy = abs(y2 - y1);
1459 XImage *image;
1460 const int x_min = Cursor_x_hot,
1461 y_min = Cursor_y_hot,
1462 x_max = DisplayWidth(scr->display, scr->screen) - 1 -
1463 (Cursor_mask_width - Cursor_x_hot),
1464 y_max = DisplayHeight(scr->display, scr->screen) - 1 - (Cursor_mask_height - Cursor_y_hot);
1466 if ((dx == 0) && (dy == 0) && panel->magnifyGlass->image)
1467 return; /* No movement */
1469 if (x1 < x2)
1470 xa = dx;
1471 else
1472 xb = dx;
1474 if (y1 < y2)
1475 ya = dy;
1476 else
1477 yb = dy;
1479 width = Cursor_mask_width - dx;
1480 height = Cursor_mask_height - dy;
1482 /* If the traversed distance is larger than the size of the magnifying
1483 * glass contents, there is no need to do dirty rectangles. A whole new
1484 * rectangle can be grabbed (unless that rectangle falls partially
1485 * off screen).
1486 * Destroying the image and setting it to NULL will achieve that later on.
1488 * Of course, grabbing an XImage beyond the borders of the screen will
1489 * cause trouble, this is considdered a special case. Part of the screen
1490 * is grabbed, but there is no need for dirty rectangles.
1492 if ((width <= 0) || (height <= 0)) {
1493 if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
1494 if (panel->magnifyGlass->image)
1495 XDestroyImage(panel->magnifyGlass->image);
1496 panel->magnifyGlass->image = NULL;
1498 } else {
1499 if (panel->magnifyGlass->image) {
1500 /* Get dirty rectangle from panel->magnifyGlass->image */
1501 panel->magnifyGlass->dirtyRect =
1502 XSubImage(panel->magnifyGlass->image, xa, ya, width, height);
1503 if (!panel->magnifyGlass->dirtyRect) {
1504 wwarning(_("Color Panel: X failed request"));
1505 return; /* X returned a NULL from XSubImage */
1510 /* Get image from screen */
1511 image = magnifyGetImage(scr, panel->magnifyGlass->image, x2, y2, Cursor_mask_width, Cursor_mask_height);
1512 if (image) { /* Only reassign if a *new* image was grabbed */
1513 panel->magnifyGlass->image = image;
1514 return;
1517 /* Copy previously stored rectangle on covered part of image */
1518 if (panel->magnifyGlass->image && panel->magnifyGlass->dirtyRect) {
1519 int old_height;
1521 /* "width" and "height" are used as coordinates here,
1522 * and run from [0...width-1] and [0...height-1] respectively.
1524 width--;
1525 height--;
1526 old_height = height;
1528 for (; width >= 0; width--)
1529 for (height = old_height; height >= 0; height--)
1530 XPutPixel(panel->magnifyGlass->image, xb + width, yb + height,
1531 XGetPixel(panel->magnifyGlass->dirtyRect, width, height));
1532 XDestroyImage(panel->magnifyGlass->dirtyRect);
1533 panel->magnifyGlass->dirtyRect = NULL;
1536 return;
1539 static Pixmap magnifyCreatePixmap(WMColorPanel * panel)
1541 W_Screen *scr = WMWidgetScreen(panel->win);
1542 int u, v;
1543 #ifndef USE_XSHAPE
1544 Pixmap pixmap;
1545 #endif
1546 unsigned long color;
1548 if (!panel->magnifyGlass->image)
1549 return None;
1551 if (!panel->magnifyGlass->magPix)
1552 return None;
1555 * Copy an area of only 5x5 pixels from the center of the image.
1557 for (u = 0; u < 5; u++) {
1558 for (v = 0; v < 5; v++) {
1559 color = XGetPixel(panel->magnifyGlass->image, u + 9, v + 9);
1561 XSetForeground(scr->display, scr->copyGC, color);
1563 if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
1564 panel->magnifyGlass->color = ulongToRColor(scr, color);
1566 /* The center square must eventually be centered around the
1567 * hotspot. The image needs shifting to achieve this. The amount of
1568 * shifting is (Cursor_mask_width/2 - 2 * square_size) = 11-10 = 1
1569 * _ _ _ _ _
1570 * |_|_|_|_|_|
1571 * ^------- center of center square == Cursor_x_hot
1573 XFillRectangle(scr->display, panel->magnifyGlass->magPix,
1574 scr->copyGC,
1575 u * 5 + (u == 0 ? 0 : -1), v * 5 + (v == 0 ? 0 : -1),
1576 (u == 0 ? 4 : 5), (v == 0 ? 4 : 5));
1580 #ifdef USE_XSHAPE
1581 return panel->magnifyGlass->magPix;
1582 #else
1583 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width, Cursor_mask_height, scr->depth);
1584 if (!pixmap)
1585 return None;
1587 XPutImage(scr->display, pixmap, scr->copyGC, panel->magnifyGlass->image,
1588 0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
1590 /* Copy the magnified pixmap, with the clip mask, to background pixmap */
1591 XCopyArea(scr->display, panel->magnifyGlass->magPix, pixmap,
1592 scr->clipGC, 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
1593 /* (2,2) puts center pixel on center of glass */
1595 return pixmap;
1596 #endif
1600 static WMView *magnifyCreateView(W_ColorPanel * panel)
1602 W_Screen *scr = WMWidgetScreen(panel->win);
1603 WMView *magView;
1605 magView = W_CreateTopView(scr);
1606 if (!magView)
1607 return NULL;
1609 magView->self = panel->win;
1610 magView->flags.topLevel = 1;
1611 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1612 magView->attribs.override_redirect = True;
1613 magView->attribs.save_under = True;
1615 W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
1617 W_RealizeView(magView);
1619 return magView;
1622 static Cursor magnifyGrabPointer(W_ColorPanel * panel)
1624 W_Screen *scr = WMWidgetScreen(panel->win);
1625 Pixmap magPixmap, magPixmap2;
1626 Cursor magCursor;
1627 XColor fgColor = { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 };
1628 XColor bgColor = { 0, 0xbf00, 0xa000, 0x5000, DoRed | DoGreen | DoBlue, 0 };
1630 /* Cursor creation stuff */
1631 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1632 (char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
1633 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1634 (char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
1636 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1637 &fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
1639 XFreePixmap(scr->display, magPixmap);
1640 XFreePixmap(scr->display, magPixmap2);
1642 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1644 /* Set up Pointer */
1645 XGrabPointer(scr->display, panel->magnifyGlass->view->window, True,
1646 PointerMotionMask | ButtonPressMask,
1647 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1649 return magCursor;
1652 static WMPoint magnifyInitialize(W_ColorPanel * panel)
1654 W_Screen *scr = WMWidgetScreen(panel->win);
1655 int x, y, u, v;
1656 unsigned int mask;
1657 Pixmap pixmap, clip_mask;
1658 WMPoint point;
1659 Window root_return, child_return;
1661 clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1662 (char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1663 1, 0, 1);
1664 panel->magnifyGlass->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
1665 5 * 5 - 1, 5 * 5 - 1, scr->depth);
1667 XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return, &x, &y, &u, &v, &mask);
1669 panel->magnifyGlass->image = NULL;
1671 /* Clipmask to make magnified view-contents circular */
1672 #ifdef USE_XSHAPE
1673 XShapeCombineMask(scr->display, WMViewXID(panel->magnifyGlass->view),
1674 ShapeBounding, 0, 0, clip_mask, ShapeSet);
1675 #else
1676 /* Clip circle in glass cursor */
1677 XSetClipMask(scr->display, scr->clipGC, clip_mask);
1678 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1679 #endif
1681 XFreePixmap(scr->display, clip_mask);
1683 /* Draw initial magnifying glass contents */
1684 magnifyGetImageStored(panel, x, y, x, y);
1686 pixmap = magnifyCreatePixmap(panel);
1687 XSetWindowBackgroundPixmap(scr->display, WMViewXID(panel->magnifyGlass->view), pixmap);
1688 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1689 XFlush(scr->display);
1691 #ifndef USE_XSHAPE
1692 XFreePixmap(scr->display, pixmap);
1693 #endif
1695 point.x = x;
1696 point.y = y;
1698 return point;
1701 static void magnifyPutCursor(WMWidget * w, void *data)
1703 W_ColorPanel *panel = (W_ColorPanel *) (data);
1704 W_Screen *scr = WMWidgetScreen(panel->win);
1705 Cursor magCursor;
1706 Pixmap pixmap;
1707 XEvent event;
1708 WMPoint initialPosition;
1710 /* Parameter not used, but tell the compiler that it is ok */
1711 (void) w;
1713 /* Destroy wheelBackImg, so it'll update properly */
1714 if (panel->selectionBackImg) {
1715 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1716 panel->selectionBackImg = None;
1719 /* Create magnifying glass */
1720 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1721 panel->magnifyGlass->view = magnifyCreateView(panel);
1722 if (!panel->magnifyGlass->view)
1723 return;
1725 initialPosition = magnifyInitialize(panel);
1726 panel->magnifyGlass->x = initialPosition.x;
1727 panel->magnifyGlass->y = initialPosition.y;
1729 W_MoveView(panel->magnifyGlass->view,
1730 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1731 W_MapView(panel->magnifyGlass->view);
1733 magCursor = magnifyGrabPointer(panel);
1735 while (panel->magnifyGlass->image) {
1736 WMNextEvent(scr->display, &event);
1738 /* Pack motion events */
1739 while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
1742 switch (event.type) {
1743 case ButtonPress:
1744 XDestroyImage(panel->magnifyGlass->image);
1745 panel->magnifyGlass->image = NULL;
1747 if (event.xbutton.button == Button1) {
1748 panel->color.rgb = panel->magnifyGlass->color;
1749 panel->color.set = cpRGB;
1750 updateSwatch(panel, panel->color);
1752 switch (panel->mode) {
1753 case WMWheelModeColorPanel:
1754 wheelInit(panel);
1755 wheelRender(panel);
1756 wheelPaint(panel);
1757 break;
1758 case WMGrayModeColorPanel:
1759 grayInit(panel);
1760 break;
1761 case WMRGBModeColorPanel:
1762 rgbInit(panel);
1763 break;
1764 case WMCMYKModeColorPanel:
1765 cmykInit(panel);
1766 break;
1767 case WMHSBModeColorPanel:
1768 hsbInit(panel);
1769 break;
1770 default:
1771 break;
1773 panel->lastChanged = panel->mode;
1775 WMSetButtonSelected(panel->magnifyBtn, False);
1776 break;
1778 case MotionNotify:
1779 while (XPending(event.xmotion.display)) {
1780 XEvent ev;
1781 XPeekEvent(event.xmotion.display, &ev);
1782 if (ev.type == MotionNotify)
1783 XNextEvent(event.xmotion.display, &event);
1784 else
1785 break;
1788 /* Get a "dirty rectangle" */
1789 magnifyGetImageStored(panel,
1790 panel->magnifyGlass->x, panel->magnifyGlass->y,
1791 event.xmotion.x_root, event.xmotion.y_root);
1793 /* Update coordinates */
1794 panel->magnifyGlass->x = event.xmotion.x_root;
1795 panel->magnifyGlass->y = event.xmotion.y_root;
1797 /* Move view */
1798 W_MoveView(panel->magnifyGlass->view,
1799 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1801 /* Put new image (with magn.) in view */
1802 pixmap = magnifyCreatePixmap(panel);
1803 if (pixmap != None) {
1804 /* Change the window background */
1805 XSetWindowBackgroundPixmap(scr->display,
1806 WMViewXID(panel->magnifyGlass->view), pixmap);
1807 /* Force an Expose (handled by X) */
1808 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1809 /* Synchronize the event queue, so the Expose is handled NOW */
1810 XFlush(scr->display);
1811 #ifndef USE_XSHAPE
1812 XFreePixmap(scr->display, pixmap);
1813 #endif
1815 break;
1817 /* Try XQueryPointer for this !!! It returns windows that the pointer
1818 * is over. Note: We found this solving the invisible donkey cap bug
1820 #if 0 /* As it is impossible to make this work in all cases,
1821 * we consider it confusing. Therefore we disabled it.
1823 case FocusOut: /* fall through */
1824 case FocusIn:
1826 * Color Panel window (panel->win) lost or received focus.
1827 * We need to update the pixmap in the magnifying glass.
1829 * BUG Doesn't work with focus switches between two windows
1830 * if none of them is the color panel.
1832 XUngrabPointer(scr->display, CurrentTime);
1833 W_UnmapView(panel->magnifyGlass->view);
1835 magnifyInitialize(panel);
1837 W_MapView(panel->magnifyGlass->view);
1838 XGrabPointer(scr->display, panel->magnifyGlass->view->window,
1839 True, PointerMotionMask | ButtonPressMask,
1840 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1841 break;
1842 #endif
1843 default:
1844 WMHandleEvent(&event);
1845 break;
1846 } /* of switch */
1849 XUngrabPointer(scr->display, CurrentTime);
1850 XFreeCursor(scr->display, magCursor);
1852 XFreePixmap(scr->display, panel->magnifyGlass->magPix);
1853 panel->magnifyGlass->magPix = None;
1855 W_UnmapView(panel->magnifyGlass->view);
1856 W_DestroyView(panel->magnifyGlass->view);
1857 panel->magnifyGlass->view = NULL;
1859 wfree(panel->magnifyGlass);
1862 /****************** ColorWheel Functions ************************/
1864 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height)
1866 wheelMatrix *matrix = NULL;
1867 int i;
1869 assert((width > 0) && (height > 0));
1871 matrix = wmalloc(sizeof(wheelMatrix));
1872 matrix->width = width;
1873 matrix->height = height;
1875 for (i = 0; i < 3; i++) {
1876 matrix->data[i] = wmalloc(width * height * sizeof(unsigned char));
1879 return matrix;
1882 static void wheelDestroyMatrix(wheelMatrix * matrix)
1884 int i;
1886 if (!matrix)
1887 return;
1889 for (i = 0; i < 3; i++) {
1890 if (matrix->data[i])
1891 wfree(matrix->data[i]);
1893 wfree(matrix);
1896 static void wheelInitMatrix(W_ColorPanel * panel)
1898 int i;
1899 int x, y;
1900 unsigned char *rp, *gp, *bp;
1901 CPColor cpColor;
1902 long ofs[4];
1903 int xcor, ycor;
1904 unsigned short sat;
1905 int dhue[4];
1906 const int cw_halfsize = (colorWheelSize + 4) / 2,
1907 cw_sqsize = (colorWheelSize + 4) * (colorWheelSize + 4), uchar_shift = getShift(sizeof(unsigned char));
1909 if (!panel->wheelMtrx)
1910 return;
1912 cpColor.hsv.value = 255;
1913 cpColor.set = cpHSV;
1915 ofs[0] = -1;
1916 ofs[1] = -(colorWheelSize + 4);
1918 /* offsets are counterclockwise (in triangles).
1920 * ofs[0] ---->
1921 * _______________________________________
1922 * [1] |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| o
1923 * s |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| f
1924 * f |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| s
1925 * o | | | | | | | | | | | | | | | | | | | | | [3]
1927 * <---- ofs[2]
1928 * ____
1929 * |\ /| <-- triangles
1930 * | \/ |
1931 * | /\ |
1932 * |/__\|
1935 for (y = 0; y < cw_halfsize; y++) {
1936 for (x = y; x < (colorWheelSize + 4 - y); x++) {
1937 /* (xcor, ycor) is (x,y) relative to center of matrix */
1938 xcor = 2 * x - 4 - colorWheelSize;
1939 ycor = 2 * y - 4 - colorWheelSize;
1941 /* RColor.saturation is unsigned char and will wrap after 255 */
1942 sat = rint(255.0 * sqrt(xcor * xcor + ycor * ycor) / colorWheelSize);
1944 cpColor.hsv.saturation = (unsigned char)sat;
1946 ofs[0]++; /* top quarter of matrix */
1947 ofs[1] += colorWheelSize + 4; /* left quarter */
1948 ofs[2] = cw_sqsize - 1 - ofs[0]; /* bottom quarter */
1949 ofs[3] = cw_sqsize - 1 - ofs[1]; /* right quarter */
1951 if (sat < 256) {
1952 if (xcor != 0)
1953 dhue[0] = rint(atan((double)ycor / (double)xcor) *
1954 (180.0 / M_PI)) + (xcor < 0 ? 180.0 : 0.0);
1955 else
1956 dhue[0] = 270;
1958 dhue[0] = 360 - dhue[0]; /* Reverse direction of ColorWheel */
1959 dhue[1] = 270 - dhue[0] + (dhue[0] > 270 ? 360 : 0);
1960 dhue[2] = dhue[0] - 180 + (dhue[0] < 180 ? 360 : 0);
1961 dhue[3] = 90 - dhue[0] + (dhue[0] > 90 ? 360 : 0);
1963 for (i = 0; i < 4; i++) {
1964 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1965 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1966 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1968 cpColor.hsv.hue = dhue[i];
1969 convertCPColor(&cpColor);
1971 *rp = (unsigned char)(cpColor.rgb.red);
1972 *gp = (unsigned char)(cpColor.rgb.green);
1973 *bp = (unsigned char)(cpColor.rgb.blue);
1975 } else {
1976 for (i = 0; i < 4; i++) {
1977 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1978 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1979 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1981 *rp = (unsigned char)0;
1982 *gp = (unsigned char)0;
1983 *bp = (unsigned char)0;
1988 ofs[0] += 2 * y + 1;
1989 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2 * y);
1993 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue)
1995 unsigned int i;
1996 unsigned int v;
1998 for (i = 0; i < 256; i++) {
1999 /* We divide by 128 in advance, and check whether that number divides
2000 * by 2 properly. If not, we add one to round the number correctly
2002 v = (i * maxvalue) >> 7;
2003 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + (v & 0x01));
2007 static void wheelRender(W_ColorPanel * panel)
2009 W_Screen *scr = WMWidgetScreen(panel->win);
2010 int x, y;
2011 RImage *image;
2012 unsigned char *ptr;
2013 RColor gray;
2014 unsigned long ofs = 0;
2015 /*unsigned char shift = getShift(sizeof(unsigned char)); */
2017 image = RCreateImage(colorWheelSize + 4, colorWheelSize + 4, True);
2018 if (!image) {
2019 wwarning(_("Color Panel: Could not allocate memory"));
2020 return;
2023 ptr = image->data;
2025 /* TODO Make this transparent istead of gray */
2026 gray.red = gray.blue = 0xae;
2027 gray.green = 0xaa;
2029 for (y = 0; y < colorWheelSize + 4; y++) {
2030 for (x = 0; x < colorWheelSize + 4; x++) {
2031 if (wheelInsideColorWheel(panel, ofs)) {
2032 *(ptr++) =
2033 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]]);
2034 *(ptr++) =
2035 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]]);
2036 *(ptr++) =
2037 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]]);
2038 *(ptr++) = 0;
2039 } else {
2040 *(ptr++) = (unsigned char)(gray.red);
2041 *(ptr++) = (unsigned char)(gray.green);
2042 *(ptr++) = (unsigned char)(gray.blue);
2043 *(ptr++) = 255;
2045 ofs++;
2049 if (panel->wheelImg)
2050 XFreePixmap(scr->display, panel->wheelImg);
2052 RConvertImage(scr->rcontext, image, &panel->wheelImg);
2053 RReleaseImage(image);
2055 /* Check if backimage exists. If it doesn't, allocate and fill it */
2056 if (!panel->selectionBackImg) {
2057 panel->selectionBackImg = XCreatePixmap(scr->display,
2058 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
2059 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2060 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2061 /* -2 is hot spot correction */
2065 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs)
2067 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
2068 (panel->wheelMtrx->data[1][ofs] != 0) && (panel->wheelMtrx->data[2][ofs] != 0));
2071 static void wheelPaint(W_ColorPanel * panel)
2073 W_Screen *scr = WMWidgetScreen(panel->win);
2075 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
2076 scr->copyGC, 0, 0, colorWheelSize + 4, colorWheelSize + 4, 0, 0);
2078 /* Draw selection image */
2079 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2080 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2083 static void wheelHandleEvents(XEvent * event, void *data)
2085 W_ColorPanel *panel = (W_ColorPanel *) data;
2087 switch (event->type) {
2088 case Expose:
2089 if (event->xexpose.count != 0) /* TODO Improve */
2090 break;
2091 wheelPaint(panel);
2092 break;
2096 static void wheelHandleActionEvents(XEvent * event, void *data)
2098 W_ColorPanel *panel = (W_ColorPanel *) data;
2100 switch (event->type) {
2101 case ButtonPress:
2102 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) == COLORWHEEL_PART) {
2104 panel->lastChanged = WMWheelModeColorPanel;
2105 panel->flags.dragging = 1;
2107 wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
2109 break;
2111 case ButtonRelease:
2112 panel->flags.dragging = 0;
2113 if (!panel->flags.continuous) {
2114 if (panel->action)
2115 (*panel->action) (panel, panel->clientData);
2117 break;
2119 case MotionNotify:
2120 if (panel->flags.dragging) {
2121 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) == COLORWHEEL_PART) {
2122 wheelPositionSelection(panel, event->xmotion.x, event->xmotion.y);
2123 } else
2124 wheelPositionSelectionOutBounds(panel, event->xmotion.x, event->xmotion.y);
2126 break;
2130 static int getPickerPart(W_ColorPanel * panel, int x, int y)
2132 int lx, ly;
2133 unsigned long ofs;
2135 lx = x;
2136 ly = y;
2138 if (panel->mode == WMWheelModeColorPanel) {
2139 if ((lx >= 2) && (lx <= 2 + colorWheelSize) && (ly >= 2) && (ly <= 2 + colorWheelSize)) {
2141 ofs = ly * panel->wheelMtrx->width + lx;
2143 if (wheelInsideColorWheel(panel, ofs))
2144 return COLORWHEEL_PART;
2148 if (panel->mode == WMCustomPaletteModeColorPanel) {
2149 if ((lx >= 2) && (lx < customPaletteWidth - 2) && (ly >= 2) && (ly < customPaletteHeight - 2)) {
2150 return CUSTOMPALETTE_PART;
2154 return 0;
2157 static void wheelBrightnessSliderCallback(WMWidget * w, void *data)
2159 int value;
2161 W_ColorPanel *panel = (W_ColorPanel *) data;
2163 /* Parameter not used, but tell the compiler that it is ok */
2164 (void) w;
2166 value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2168 wheelCalculateValues(panel, value);
2170 if (panel->color.set == cpRGB) {
2171 convertCPColor(&panel->color);
2172 panel->color.set = cpHSV;
2175 panel->color.hsv.value = value;
2177 wheelRender(panel);
2178 wheelPaint(panel);
2179 wheelUpdateSelection(panel);
2182 static void wheelUpdateSelection(W_ColorPanel * panel)
2184 W_Screen *scr = WMWidgetScreen(panel->win);
2186 updateSwatch(panel, panel->color);
2187 panel->lastChanged = WMWheelModeColorPanel;
2189 /* Redraw color selector (and make a backup of the part it will cover) */
2190 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2191 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2192 /* "-2" is correction for hotspot location */
2193 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2194 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2195 /* see above */
2198 static void wheelUndrawSelection(W_ColorPanel * panel)
2200 W_Screen *scr = WMWidgetScreen(panel->win);
2202 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
2203 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2204 /* see above */
2207 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y)
2209 unsigned long ofs = (y * panel->wheelMtrx->width) + x;
2211 panel->color.rgb.red = panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]];
2213 panel->color.rgb.green = panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]];
2215 panel->color.rgb.blue = panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]];
2216 panel->color.set = cpRGB;
2218 wheelUndrawSelection(panel);
2220 panel->colx = x;
2221 panel->coly = y;
2223 wheelUpdateSelection(panel);
2224 wheelUpdateBrightnessGradientFromLocation(panel);
2227 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2229 int hue;
2230 int xcor, ycor;
2231 CPColor cpColor;
2233 xcor = x * 2 - colorWheelSize - 4;
2234 ycor = y * 2 - colorWheelSize - 4;
2236 panel->color.hsv.saturation = 255;
2237 panel->color.hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2239 if (xcor != 0)
2240 hue = rint(atan(-(double)ycor / (double)xcor) * (180.0 / M_PI));
2241 else {
2242 if (ycor < 0)
2243 hue = 90;
2244 else
2245 hue = 270;
2248 if (xcor < 0)
2249 hue += 180;
2251 if ((xcor > 0) && (ycor > 0))
2252 hue += 360;
2254 panel->color.hsv.hue = hue;
2255 panel->color.set = cpHSV;
2256 convertCPColor(&panel->color);
2258 wheelUndrawSelection(panel);
2260 panel->colx = 2 + rint((colorWheelSize * (1.0 + cos(panel->color.hsv.hue * (M_PI / 180.0)))) / 2.0);
2261 /* "+2" because of "colorWheelSize + 4" */
2262 panel->coly = 2 + rint((colorWheelSize * (1.0 + sin(-panel->color.hsv.hue * (M_PI / 180.0)))) / 2.0);
2264 wheelUpdateSelection(panel);
2265 cpColor = panel->color;
2266 wheelUpdateBrightnessGradient(panel, cpColor);
2269 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel)
2271 CPColor from;
2272 unsigned long ofs;
2274 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2276 from.rgb.red = panel->wheelMtrx->data[0][ofs];
2277 from.rgb.green = panel->wheelMtrx->data[1][ofs];
2278 from.rgb.blue = panel->wheelMtrx->data[2][ofs];
2279 from.set = cpRGB;
2281 wheelUpdateBrightnessGradient(panel, from);
2284 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor)
2286 RColor to;
2287 RImage *sliderImg;
2288 WMPixmap *sliderPxmp;
2290 to.red = to.green = to.blue = 0;
2292 if (topColor.set == cpHSV)
2293 convertCPColor(&topColor);
2295 sliderImg = RRenderGradient(16, 153, &(topColor.rgb), &to, RGRD_VERTICAL);
2296 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win), sliderImg, 0);
2297 RReleaseImage(sliderImg);
2298 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
2299 WMReleasePixmap(sliderPxmp);
2302 /****************** Grayscale Panel Functions ***************/
2304 static void grayBrightnessSliderCallback(WMWidget * w, void *data)
2306 CPColor cpColor;
2307 int value;
2308 char tmp[4];
2309 W_ColorPanel *panel = (W_ColorPanel *) data;
2311 /* Parameter not used, but tell the compiler that it is ok */
2312 (void) w;
2314 value = WMGetSliderValue(panel->grayBrightnessS);
2316 sprintf(tmp, "%d", value);
2318 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2319 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint(2.55 * value);
2320 cpColor.set = cpRGB;
2322 updateSwatch(panel, cpColor);
2323 panel->lastChanged = WMGrayModeColorPanel;
2326 static void grayPresetButtonCallback(WMWidget * w, void *data)
2328 CPColor cpColor;
2329 char tmp[4];
2330 int value;
2331 int i = 0;
2332 W_ColorPanel *panel = (W_ColorPanel *) data;
2334 while (i < 7) {
2335 if (w == panel->grayPresetBtn[i])
2336 break;
2337 i++;
2340 value = rint((100.0 * i) / 6.0);
2341 sprintf(tmp, "%d", value);
2343 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2344 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * i) / 6.0);
2345 cpColor.set = cpRGB;
2347 WMSetSliderValue(panel->grayBrightnessS, rint((100.0 * i) / 6.0));
2349 updateSwatch(panel, cpColor);
2350 panel->lastChanged = WMGrayModeColorPanel;
2353 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification)
2355 CPColor cpColor;
2356 char tmp[4];
2357 int value;
2358 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2360 /* Parameter not used, but tell the compiler that it is ok */
2361 (void) notification;
2363 value = get_textfield_as_integer(panel->grayBrightnessT);
2364 if (value > 100)
2365 value = 100;
2366 if (value < 0)
2367 value = 0;
2369 sprintf(tmp, "%d", value);
2370 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2371 WMSetSliderValue(panel->grayBrightnessS, value);
2373 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * value) / 100.0);
2374 cpColor.set = cpRGB;
2376 updateSwatch(panel, cpColor);
2377 panel->lastChanged = WMGrayModeColorPanel;
2380 /******************* RGB Panel Functions *****************/
2382 void rgbIntToChar(W_ColorPanel *panel, int *value)
2384 char tmp[4];
2385 const char *format;
2387 switch (panel->rgbState) {
2388 case RGBdec:
2389 format = "%d";
2390 break;
2391 case RGBhex:
2392 format = "%0X";
2393 break;
2396 sprintf(tmp, format, value[0]);
2397 WMSetTextFieldText(panel->rgbRedT, tmp);
2398 sprintf(tmp, format, value[1]);
2399 WMSetTextFieldText(panel->rgbGreenT, tmp);
2400 sprintf(tmp, format, value[2]);
2401 WMSetTextFieldText(panel->rgbBlueT, tmp);
2404 int *rgbCharToInt(W_ColorPanel *panel)
2406 int base = 0;
2407 static int value[3];
2408 char *str;
2410 switch (panel->rgbState) {
2411 case RGBdec:
2412 base = 10;
2413 break;
2414 case RGBhex:
2415 base = 16;
2416 break;
2419 str = WMGetTextFieldText(panel->rgbRedT);
2420 value[0] = strtol(str, NULL, base);
2421 wfree(str);
2423 str = WMGetTextFieldText(panel->rgbGreenT);
2424 value[1] = strtol(str, NULL, base);
2425 wfree(str);
2427 str = WMGetTextFieldText(panel->rgbBlueT);
2428 value[2] = strtol(str, NULL, base);
2429 wfree(str);
2431 return value;
2434 static void rgbSliderCallback(WMWidget * w, void *data)
2436 CPColor cpColor;
2437 int value[3];
2438 W_ColorPanel *panel = (W_ColorPanel *) data;
2440 /* Parameter not used, but tell the compiler that it is ok */
2441 (void) w;
2443 value[0] = WMGetSliderValue(panel->rgbRedS);
2444 value[1] = WMGetSliderValue(panel->rgbGreenS);
2445 value[2] = WMGetSliderValue(panel->rgbBlueS);
2447 rgbIntToChar(panel, value);
2449 cpColor.rgb.red = value[0];
2450 cpColor.rgb.green = value[1];
2451 cpColor.rgb.blue = value[2];
2452 cpColor.set = cpRGB;
2454 updateSwatch(panel, cpColor);
2455 panel->lastChanged = WMRGBModeColorPanel;
2458 static void rgbTextFieldCallback(void *observerData, WMNotification * notification)
2460 CPColor cpColor;
2461 int *value;
2462 int n;
2463 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2465 /* Parameter not used, but tell the compiler that it is ok */
2466 (void) notification;
2468 value = rgbCharToInt(panel);
2470 for (n = 0; n < 3; n++) {
2471 if (value[n] > 255)
2472 value[n] = 255;
2473 if (value[n] < 0)
2474 value[n] = 0;
2477 rgbIntToChar(panel, value);
2479 WMSetSliderValue(panel->rgbRedS, value[0]);
2480 WMSetSliderValue(panel->rgbGreenS, value[1]);
2481 WMSetSliderValue(panel->rgbBlueS, value[2]);
2483 cpColor.rgb.red = value[0];
2484 cpColor.rgb.green = value[1];
2485 cpColor.rgb.blue = value[2];
2486 cpColor.set = cpRGB;
2488 updateSwatch(panel, cpColor);
2489 panel->lastChanged = WMRGBModeColorPanel;
2492 static void rgbDecToHex(WMWidget *w, void *data)
2494 W_ColorPanel *panel = (W_ColorPanel *) data;
2495 int *value;
2497 (void) w;
2499 switch (panel->rgbState) {
2500 case RGBhex:
2501 if (WMGetButtonSelected(panel->rgbDecB)) {
2502 WMSetLabelText(panel->rgbMaxL, "255");
2503 WMRedisplayWidget(panel->rgbMaxL);
2504 value = rgbCharToInt(panel);
2505 panel->rgbState = RGBdec;
2506 rgbIntToChar(panel, value);
2508 break;
2510 case RGBdec:
2511 if (WMGetButtonSelected(panel->rgbHexB)) {
2512 WMSetLabelText(panel->rgbMaxL, "FF");
2513 WMRedisplayWidget(panel->rgbMaxL);
2514 value = rgbCharToInt(panel);
2515 panel->rgbState = RGBhex;
2516 rgbIntToChar(panel, value);
2518 break;
2522 /******************* CMYK Panel Functions *****************/
2524 static void cmykSliderCallback(WMWidget * w, void *data)
2526 CPColor cpColor;
2527 int value[4];
2528 char tmp[4];
2529 W_ColorPanel *panel = (W_ColorPanel *) data;
2530 double scale;
2532 /* Parameter not used, but tell the compiler that it is ok */
2533 (void) w;
2535 value[0] = WMGetSliderValue(panel->cmykCyanS);
2536 value[1] = WMGetSliderValue(panel->cmykMagentaS);
2537 value[2] = WMGetSliderValue(panel->cmykYellowS);
2538 value[3] = WMGetSliderValue(panel->cmykBlackS);
2540 sprintf(tmp, "%d", value[0]);
2541 WMSetTextFieldText(panel->cmykCyanT, tmp);
2542 sprintf(tmp, "%d", value[1]);
2543 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2544 sprintf(tmp, "%d", value[2]);
2545 WMSetTextFieldText(panel->cmykYellowT, tmp);
2546 sprintf(tmp, "%d", value[3]);
2547 WMSetTextFieldText(panel->cmykBlackT, tmp);
2549 scale = 2.55 * (1.0 - (value[3] / 100.0));
2550 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2551 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2552 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2553 cpColor.set = cpRGB;
2555 updateSwatch(panel, cpColor);
2556 panel->lastChanged = WMCMYKModeColorPanel;
2559 static void cmykTextFieldCallback(void *observerData, WMNotification * notification)
2561 CPColor cpColor;
2562 int value[4];
2563 char tmp[4];
2564 int n;
2565 double scale;
2566 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2568 /* Parameter not used, but tell the compiler that it is ok */
2569 (void) notification;
2571 value[0] = get_textfield_as_integer(panel->cmykCyanT);
2572 value[1] = get_textfield_as_integer(panel->cmykMagentaT);
2573 value[2] = get_textfield_as_integer(panel->cmykYellowT);
2574 value[3] = get_textfield_as_integer(panel->cmykBlackT);
2576 for (n = 0; n < 4; n++) {
2577 if (value[n] > 100)
2578 value[n] = 100;
2579 if (value[n] < 0)
2580 value[n] = 0;
2583 sprintf(tmp, "%d", value[0]);
2584 WMSetTextFieldText(panel->cmykCyanT, tmp);
2586 sprintf(tmp, "%d", value[1]);
2587 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2589 sprintf(tmp, "%d", value[2]);
2590 WMSetTextFieldText(panel->cmykYellowT, tmp);
2592 sprintf(tmp, "%d", value[3]);
2593 WMSetTextFieldText(panel->cmykBlackT, tmp);
2595 WMSetSliderValue(panel->cmykCyanS, value[0]);
2596 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2597 WMSetSliderValue(panel->cmykYellowS, value[2]);
2598 WMSetSliderValue(panel->cmykBlackS, value[3]);
2600 scale = 2.55 * (1.0 - (value[3] / 100.0));
2601 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2602 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2603 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2604 cpColor.set = cpRGB;
2606 updateSwatch(panel, cpColor);
2607 panel->lastChanged = WMCMYKModeColorPanel;
2610 /********************** HSB Panel Functions ***********************/
2612 static void hsbSliderCallback(WMWidget * w, void *data)
2614 CPColor cpColor;
2615 int value[3];
2616 char tmp[4];
2617 W_ColorPanel *panel = (W_ColorPanel *) data;
2619 value[0] = WMGetSliderValue(panel->hsbHueS);
2620 value[1] = WMGetSliderValue(panel->hsbSaturationS);
2621 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
2623 sprintf(tmp, "%d", value[0]);
2624 WMSetTextFieldText(panel->hsbHueT, tmp);
2625 sprintf(tmp, "%d", value[1]);
2626 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2627 sprintf(tmp, "%d", value[2]);
2628 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2630 cpColor.hsv.hue = value[0];
2631 cpColor.hsv.saturation = value[1] * 2.55;
2632 cpColor.hsv.value = value[2] * 2.55;
2633 cpColor.set = cpHSV;
2635 convertCPColor(&cpColor);
2637 panel->lastChanged = WMHSBModeColorPanel;
2638 updateSwatch(panel, cpColor);
2640 if (w != panel->hsbBrightnessS)
2641 hsbUpdateBrightnessGradient(panel);
2642 if (w != panel->hsbSaturationS)
2643 hsbUpdateSaturationGradient(panel);
2644 if (w != panel->hsbHueS)
2645 hsbUpdateHueGradient(panel);
2648 static void hsbTextFieldCallback(void *observerData, WMNotification * notification)
2650 CPColor cpColor;
2651 int value[3];
2652 char tmp[4];
2653 int n;
2654 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2656 /* Parameter not used, but tell the compiler that it is ok */
2657 (void) notification;
2659 value[0] = get_textfield_as_integer(panel->hsbHueT);
2660 value[1] = get_textfield_as_integer(panel->hsbSaturationT);
2661 value[2] = get_textfield_as_integer(panel->hsbBrightnessT);
2663 if (value[0] > 359)
2664 value[0] = 359;
2665 if (value[0] < 0)
2666 value[0] = 0;
2668 for (n = 1; n < 3; n++) {
2669 if (value[n] > 100)
2670 value[n] = 100;
2671 if (value[n] < 0)
2672 value[n] = 0;
2675 sprintf(tmp, "%d", value[0]);
2676 WMSetTextFieldText(panel->hsbHueT, tmp);
2677 sprintf(tmp, "%d", value[1]);
2678 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2679 sprintf(tmp, "%d", value[2]);
2680 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2682 WMSetSliderValue(panel->hsbHueS, value[0]);
2683 WMSetSliderValue(panel->hsbSaturationS, value[1]);
2684 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
2686 cpColor.hsv.hue = value[0];
2687 cpColor.hsv.saturation = value[1] * 2.55;
2688 cpColor.hsv.value = value[2] * 2.55;
2689 cpColor.set = cpHSV;
2691 convertCPColor(&cpColor);
2693 panel->lastChanged = WMHSBModeColorPanel;
2694 updateSwatch(panel, cpColor);
2696 hsbUpdateBrightnessGradient(panel);
2697 hsbUpdateSaturationGradient(panel);
2698 hsbUpdateHueGradient(panel);
2701 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel)
2703 W_Screen *scr = WMWidgetScreen(panel->win);
2704 RColor from;
2705 CPColor to;
2706 RImage *sliderImg;
2707 WMPixmap *sliderPxmp;
2709 from.red = from.green = from.blue = 0;
2710 to.hsv = panel->color.hsv;
2711 to.hsv.value = 255;
2712 to.set = cpHSV;
2714 convertCPColor(&to);
2716 sliderImg = RRenderGradient(141, 16, &from, &(to.rgb), RGRD_HORIZONTAL);
2717 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2718 RReleaseImage(sliderImg);
2720 if (sliderPxmp)
2721 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
2722 panel->font12, 2, 0, 100, WALeft, scr->white,
2723 False, _("Brightness"), strlen(_("Brightness")));
2724 else
2725 wwarning(_("Color Panel: Could not allocate memory"));
2727 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
2728 WMReleasePixmap(sliderPxmp);
2731 static void hsbUpdateSaturationGradient(W_ColorPanel * panel)
2733 W_Screen *scr = WMWidgetScreen(panel->win);
2734 CPColor from;
2735 CPColor to;
2736 RImage *sliderImg;
2737 WMPixmap *sliderPxmp;
2739 from.hsv = panel->color.hsv;
2740 from.hsv.saturation = 0;
2741 from.set = cpHSV;
2742 convertCPColor(&from);
2744 to.hsv = panel->color.hsv;
2745 to.hsv.saturation = 255;
2746 to.set = cpHSV;
2747 convertCPColor(&to);
2749 sliderImg = RRenderGradient(141, 16, &(from.rgb), &(to.rgb), RGRD_HORIZONTAL);
2750 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2751 RReleaseImage(sliderImg);
2753 if (sliderPxmp)
2754 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2755 panel->font12, 2, 0, 100, WALeft,
2756 from.hsv.value < 128 ? scr->white : scr->black, False,
2757 _("Saturation"), strlen(_("Saturation")));
2758 else
2759 wwarning(_("Color Panel: Could not allocate memory"));
2761 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
2762 WMReleasePixmap(sliderPxmp);
2765 static void hsbUpdateHueGradient(W_ColorPanel * panel)
2767 W_Screen *scr = WMWidgetScreen(panel->win);
2768 RColor **colors = NULL;
2769 RHSVColor hsvcolor;
2770 RImage *sliderImg;
2771 WMPixmap *sliderPxmp;
2772 int i;
2774 hsvcolor = panel->color.hsv;
2776 colors = wmalloc(sizeof(RColor *) * (8));
2777 for (i = 0; i < 7; i++) {
2778 hsvcolor.hue = (360 * i) / 6;
2779 colors[i] = wmalloc(sizeof(RColor));
2780 RHSVtoRGB(&hsvcolor, colors[i]);
2782 colors[7] = NULL;
2784 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2785 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2786 RReleaseImage(sliderImg);
2788 if (sliderPxmp)
2789 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2790 panel->font12, 2, 0, 100, WALeft,
2791 hsvcolor.value < 128 ? scr->white : scr->black, False, _("Hue"), strlen(_("Hue")));
2792 else
2793 wwarning(_("Color Panel: Could not allocate memory"));
2795 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2796 WMReleasePixmap(sliderPxmp);
2798 for (i = 0; i < 7; i++)
2799 wfree(colors[i]);
2801 wfree(colors);
2804 /*************** Custom Palette Functions ****************/
2806 static void customRenderSpectrum(W_ColorPanel * panel)
2808 RImage *spectrum;
2809 int x, y;
2810 unsigned char *ptr;
2811 CPColor cpColor;
2813 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, False);
2815 ptr = spectrum->data;
2817 for (y = 0; y < SPECTRUM_HEIGHT; y++) {
2818 cpColor.hsv.hue = y;
2819 cpColor.hsv.saturation = 0;
2820 cpColor.hsv.value = 255;
2821 cpColor.set = cpHSV;
2823 for (x = 0; x < SPECTRUM_WIDTH; x++) {
2824 convertCPColor(&cpColor);
2826 *(ptr++) = (unsigned char)cpColor.rgb.red;
2827 *(ptr++) = (unsigned char)cpColor.rgb.green;
2828 *(ptr++) = (unsigned char)cpColor.rgb.blue;
2830 if (x < (SPECTRUM_WIDTH / 2))
2831 cpColor.hsv.saturation++;
2833 if (x > (SPECTRUM_WIDTH / 2))
2834 cpColor.hsv.value--;
2837 if (panel->customPaletteImg) {
2838 RReleaseImage(panel->customPaletteImg);
2839 panel->customPaletteImg = NULL;
2841 panel->customPaletteImg = spectrum;
2844 static void customSetPalette(W_ColorPanel * panel)
2846 W_Screen *scr = WMWidgetScreen(panel->win);
2847 RImage *scaledImg;
2848 Pixmap image;
2850 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth, customPaletteHeight, scr->depth);
2851 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth, customPaletteHeight);
2852 RConvertImage(scr->rcontext, scaledImg, &image);
2853 RReleaseImage(scaledImg);
2855 XCopyArea(scr->display, image, panel->customPaletteContentView->window,
2856 scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2858 /* Check backimage exists. If it doesn't, allocate and fill it */
2859 if (!panel->selectionBackImg) {
2860 panel->selectionBackImg = XCreatePixmap(scr->display,
2861 panel->customPaletteContentView->window, 4, 4, scr->depth);
2864 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
2865 panel->palx - 2, panel->paly - 2, 4, 4, 0, 0);
2866 XCopyArea(scr->display, panel->selectionImg,
2867 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2868 panel->palx - 2, panel->paly - 2);
2869 XFreePixmap(scr->display, image);
2871 panel->palXRatio = (double)(panel->customPaletteImg->width) / (double)(customPaletteWidth);
2872 panel->palYRatio = (double)(panel->customPaletteImg->height) / (double)(customPaletteHeight);
2874 WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
2877 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y)
2879 W_Screen *scr = WMWidgetScreen(panel->win);
2880 unsigned long ofs;
2882 /* undraw selection */
2883 XCopyArea(scr->display, panel->selectionBackImg,
2884 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2885 panel->palx - 2, panel->paly - 2);
2887 panel->palx = x;
2888 panel->paly = y;
2890 ofs = (rint(x * panel->palXRatio) + rint(y * panel->palYRatio) * panel->customPaletteImg->width) * 3;
2892 panel->color.rgb.red = panel->customPaletteImg->data[ofs];
2893 panel->color.rgb.green = panel->customPaletteImg->data[ofs + 1];
2894 panel->color.rgb.blue = panel->customPaletteImg->data[ofs + 2];
2895 panel->color.set = cpRGB;
2897 updateSwatch(panel, panel->color);
2898 panel->lastChanged = WMCustomPaletteModeColorPanel;
2900 /* Redraw color selector (and make a backup of the part it will cover) */
2901 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 */
2902 XCopyArea(scr->display, panel->selectionImg, panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4, panel->palx - 2, panel->paly - 2); /* see above */
2905 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2907 if (x < 2)
2908 x = 2;
2909 if (y < 2)
2910 y = 2;
2911 if (x >= customPaletteWidth)
2912 x = customPaletteWidth - 2;
2913 if (y >= customPaletteHeight)
2914 y = customPaletteHeight - 2;
2916 customPalettePositionSelection(panel, x, y);
2919 static void customPaletteHandleEvents(XEvent * event, void *data)
2921 W_ColorPanel *panel = (W_ColorPanel *) data;
2923 switch (event->type) {
2924 case Expose:
2925 if (event->xexpose.count != 0) /* TODO Improve. */
2926 break;
2927 customSetPalette(panel);
2928 break;
2932 static void customPaletteHandleActionEvents(XEvent * event, void *data)
2934 W_ColorPanel *panel = (W_ColorPanel *) data;
2935 int x, y;
2937 switch (event->type) {
2938 case ButtonPress:
2939 x = event->xbutton.x;
2940 y = event->xbutton.y;
2942 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2943 panel->flags.dragging = 1;
2944 customPalettePositionSelection(panel, x, y);
2946 break;
2948 case ButtonRelease:
2949 panel->flags.dragging = 0;
2950 if (!panel->flags.continuous) {
2951 if (panel->action)
2952 (*panel->action) (panel, panel->clientData);
2954 break;
2956 case MotionNotify:
2957 x = event->xmotion.x;
2958 y = event->xmotion.y;
2960 if (panel->flags.dragging) {
2961 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2962 customPalettePositionSelection(panel, x, y);
2963 } else
2964 customPalettePositionSelectionOutBounds(panel, x, y);
2966 break;
2970 static void customPaletteMenuCallback(WMWidget * w, void *data)
2972 W_ColorPanel *panel = (W_ColorPanel *) data;
2973 int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
2975 /* Parameter not used, but tell the compiler that it is ok */
2976 (void) w;
2978 switch (item) {
2979 case CPmenuNewFromFile:
2980 customPaletteMenuNewFromFile(panel);
2981 break;
2982 case CPmenuRename:
2983 customPaletteMenuRename(panel);
2984 break;
2985 case CPmenuRemove:
2986 customPaletteMenuRemove(panel);
2987 break;
2988 case CPmenuCopy:
2989 break;
2990 case CPmenuNewFromClipboard:
2991 break;
2995 static void customPaletteMenuNewFromFile(W_ColorPanel * panel)
2997 W_Screen *scr = WMWidgetScreen(panel->win);
2998 WMOpenPanel *browseP;
2999 char *filepath;
3000 char *filename = NULL;
3001 char *spath;
3002 char *tmp;
3003 int i;
3004 RImage *tmpImg = NULL;
3006 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir, "\0") == 0))
3007 spath = wexpandpath(wgethomedir());
3008 else
3009 spath = wexpandpath(panel->lastBrowseDir);
3011 browseP = WMGetOpenPanel(scr);
3012 WMSetFilePanelCanChooseDirectories(browseP, 0);
3013 WMSetFilePanelCanChooseFiles(browseP, 1);
3015 /* Get a filename */
3016 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
3017 _("Open Palette"), RSupportedFileFormats())) {
3018 filepath = WMGetFilePanelFileName(browseP);
3020 /* Get seperation position between path and filename */
3021 i = strrchr(filepath, '/') - filepath + 1;
3022 if (i > strlen(filepath))
3023 i = strlen(filepath);
3025 /* Store last browsed path */
3026 if (panel->lastBrowseDir)
3027 wfree(panel->lastBrowseDir);
3028 panel->lastBrowseDir = wmalloc((i + 1) * sizeof(char));
3029 strncpy(panel->lastBrowseDir, filepath, i);
3030 panel->lastBrowseDir[i] = '\0';
3032 /* Get filename from path */
3033 filename = wstrdup(filepath + i);
3035 /* Check for duplicate files, and rename it if there are any */
3036 tmp = wstrconcat(panel->configurationPath, filename);
3037 while (access(tmp, F_OK) == 0) {
3038 char *newName;
3040 wfree(tmp);
3042 newName = generateNewFilename(filename);
3043 wfree(filename);
3044 filename = newName;
3046 tmp = wstrconcat(panel->configurationPath, filename);
3048 wfree(tmp);
3050 /* Copy image to $(gnustepdir)/Library/Colors/ &
3051 * Add filename to history menu */
3052 if (wcopy_file(panel->configurationPath, filepath, filename) == 0) {
3054 /* filepath is a "local" path now the file has been copied */
3055 wfree(filepath);
3056 filepath = wstrconcat(panel->configurationPath, filename);
3058 /* load the image & add menu entries */
3059 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
3060 if (tmpImg) {
3061 if (panel->customPaletteImg)
3062 RReleaseImage(panel->customPaletteImg);
3063 panel->customPaletteImg = tmpImg;
3065 customSetPalette(panel);
3066 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
3068 panel->currentPalette =
3069 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1;
3071 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3072 panel->currentPalette);
3074 } else {
3075 tmp = wstrconcat(panel->configurationPath, filename);
3077 i = remove(tmp); /* Delete the file, it doesn't belong here */
3078 WMRunAlertPanel(scr, panel->win, _("File Error"),
3079 _("Invalid file format !"), _("OK"), NULL, NULL);
3080 if (i != 0) {
3081 werror(_("can't remove file %s"), tmp);
3082 WMRunAlertPanel(scr, panel->win, _("File Error"),
3083 _("Couldn't remove file from Configuration Directory !"),
3084 _("OK"), NULL, NULL);
3086 wfree(tmp);
3088 wfree(filepath);
3089 wfree(filename);
3091 WMFreeFilePanel(browseP);
3093 wfree(spath);
3096 static void customPaletteMenuRename(W_ColorPanel * panel)
3098 W_Screen *scr = WMWidgetScreen(panel->win);
3099 char *toName = NULL;
3100 char *fromName;
3101 char *toPath, *fromPath;
3102 int item;
3103 int index;
3105 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3106 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
3108 toName = WMRunInputPanel(scr, panel->win, _("Rename"), _("Rename palette to:"),
3109 fromName, _("OK"), _("Cancel"));
3111 if (toName) {
3113 /* As some people do certain stupid things... */
3114 if (strcmp(toName, fromName) == 0) {
3115 wfree(toName);
3116 return;
3119 /* For normal people */
3120 fromPath = wstrconcat(panel->configurationPath, fromName);
3121 toPath = wstrconcat(panel->configurationPath, toName);
3123 if (access(toPath, F_OK) == 0) {
3124 /* Careful, this palette exists already */
3125 if (WMRunAlertPanel(scr, panel->win, _("Warning"),
3126 _("Palette already exists !\n\nOverwrite ?"), _("No"), _("Yes"),
3127 NULL) == 1) {
3128 /* "No" = 0, "Yes" = 1 */
3129 int items = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
3131 remove(toPath);
3133 /* Remove from History list too */
3134 index = 1;
3135 while ((index < items)
3137 (strcmp(WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, index), toName)
3138 != 0))
3139 index++;
3141 if (index < items) {
3142 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, index);
3143 if (index < item)
3144 item--;
3147 } else {
3148 wfree(fromPath);
3149 wfree(toName);
3150 wfree(toPath);
3152 return;
3156 if (rename(fromPath, toPath) != 0)
3157 werror(_("Couldn't rename palette %s to %s"), fromName, toName);
3158 else {
3159 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3160 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item, toName);
3162 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
3164 wfree(fromPath);
3165 wfree(toPath);
3166 wfree(toName);
3170 static void customPaletteMenuRemove(W_ColorPanel * panel)
3172 W_Screen *scr = WMWidgetScreen(panel->win);
3173 char *text;
3174 char *tmp;
3175 int choice;
3176 int item;
3178 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3180 tmp = wstrconcat(_("This will permanently remove the palette "),
3181 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3182 text = wstrconcat(tmp, _(".\n\nAre you sure you want to remove this palette ?"));
3183 wfree(tmp);
3185 choice = WMRunAlertPanel(scr, panel->win, _("Remove"), text, _("Yes"), _("No"), NULL);
3186 /* returns 0 (= "Yes") or 1 (="No") */
3187 wfree(text);
3189 if (choice == 0) {
3191 tmp = wstrconcat(panel->configurationPath,
3192 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3194 if (remove(tmp) == 0) {
3195 /* item-1 always exists */
3196 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3198 customPaletteHistoryCallback(panel->customPaletteHistoryBtn, panel);
3199 customSetPalette(panel);
3201 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3203 } else {
3204 werror(_("Couldn't remove palette %s"), tmp);
3207 wfree(tmp);
3211 static void customPaletteHistoryCallback(WMWidget * w, void *data)
3213 W_ColorPanel *panel = (W_ColorPanel *) data;
3214 W_Screen *scr = WMWidgetScreen(panel->win);
3215 int item;
3216 char *filename;
3217 RImage *tmp = NULL;
3218 unsigned char perm_mask;
3220 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3221 if (item == panel->currentPalette)
3222 return;
3224 if (item == 0) {
3225 customRenderSpectrum(panel);
3227 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, False);
3228 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, False);
3229 } else {
3230 /* Load file from configpath */
3231 filename = wstrconcat(panel->configurationPath,
3232 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3234 /* If the file corresponding to the item does not exist,
3235 * remove it from the history list and select the next one.
3237 perm_mask = (access(filename, F_OK) == 0);
3238 if (!perm_mask) {
3239 /* File does not exist */
3240 wfree(filename);
3241 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3242 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3243 customPaletteHistoryCallback(w, data);
3244 return;
3247 /* Get the image */
3248 tmp = RLoadImage(scr->rcontext, filename, 0);
3249 if (tmp) {
3250 if (panel->customPaletteImg) {
3251 RReleaseImage(panel->customPaletteImg);
3252 panel->customPaletteImg = NULL;
3254 panel->customPaletteImg = tmp;
3257 /* If the image is not writable, don't allow removing/renaming */
3258 perm_mask = (access(filename, W_OK) == 0);
3259 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, perm_mask);
3260 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, perm_mask);
3262 wfree(filename);
3264 customSetPalette(panel);
3266 panel->currentPalette = item;
3269 /************************* ColorList Panel Functions **********************/
3271 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect)
3273 WMScreen *scr = WMWidgetScreen(lPtr);
3274 Display *dpy = WMScreenDisplay(scr);
3275 WMView *view = W_VIEW(lPtr);
3276 RColor *color = (RColor *) WMGetListItem(lPtr, index)->clientData;
3277 W_ColorPanel *panel = WMGetHangedData(lPtr);
3278 int width, height, x, y;
3279 WMColor *fillColor;
3281 width = rect->size.width;
3282 height = rect->size.height;
3283 x = rect->pos.x;
3284 y = rect->pos.y;
3286 if (state & WLDSSelected)
3287 XFillRectangle(dpy, d, WMColorGC(scr->white), x, y, width, height);
3288 else
3289 XFillRectangle(dpy, d, WMColorGC(view->backColor), x, y, width, height);
3291 fillColor = WMCreateRGBColor(scr, color->red << 8, color->green << 8, color->blue << 8, True);
3293 XFillRectangle(dpy, d, WMColorGC(fillColor), x, y, 15, height);
3294 WMReleaseColor(fillColor);
3296 WMDrawString(scr, d, scr->black, panel->font12, x + 18, y, text, strlen(text));
3299 static void colorListSelect(WMWidget * w, void *data)
3301 W_ColorPanel *panel = (W_ColorPanel *) data;
3302 CPColor cpColor;
3304 cpColor.rgb = *((RColor *) WMGetListSelectedItem(w)->clientData);
3305 cpColor.set = cpRGB;
3307 panel->lastChanged = WMColorListModeColorPanel;
3308 updateSwatch(panel, cpColor);
3311 static void colorListColorMenuCallback(WMWidget * w, void *data)
3313 W_ColorPanel *panel = (W_ColorPanel *) data;
3314 int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
3316 /* Parameter not used, but tell the compiler that it is ok */
3317 (void) w;
3319 switch (item) {
3320 case CLmenuAdd:
3321 break;
3322 case CLmenuRename:
3323 break;
3324 case CLmenuRemove:
3325 break;
3329 static void colorListListMenuCallback(WMWidget * w, void *data)
3331 W_ColorPanel *panel = (W_ColorPanel *) data;
3332 int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
3334 /* Parameter not used, but tell the compiler that it is ok */
3335 (void) w;
3337 switch (item) {
3338 case CLmenuAdd:
3339 break;
3340 case CLmenuRename:
3341 break;
3342 case CLmenuRemove:
3343 break;
3347 /*************** Panel Initialisation Functions *****************/
3349 static void wheelInit(W_ColorPanel * panel)
3351 CPColor cpColor;
3353 if (panel->color.set != cpHSV)
3354 convertCPColor(&panel->color);
3356 WMSetSliderValue(panel->wheelBrightnessS, 255 - panel->color.hsv.value);
3358 panel->colx = 2 + rint((colorWheelSize / 2.0) *
3359 (1 + (panel->color.hsv.saturation / 255.0) *
3360 cos(panel->color.hsv.hue * M_PI / 180.0)));
3361 panel->coly = 2 + rint((colorWheelSize / 2.0) *
3362 (1 + (panel->color.hsv.saturation / 255.0) *
3363 sin(-panel->color.hsv.hue * M_PI / 180.0)));
3365 wheelCalculateValues(panel, panel->color.hsv.value);
3367 cpColor = panel->color;
3368 cpColor.hsv.value = 255;
3369 cpColor.set = cpHSV;
3370 wheelUpdateBrightnessGradient(panel, cpColor);
3373 static void grayInit(W_ColorPanel * panel)
3375 int value;
3376 char tmp[4];
3378 if (panel->color.set != cpHSV)
3379 convertCPColor(&panel->color);
3381 value = rint(panel->color.hsv.value / 2.55);
3382 WMSetSliderValue(panel->grayBrightnessS, value);
3384 sprintf(tmp, "%d", value);
3385 WMSetTextFieldText(panel->grayBrightnessT, tmp);
3388 static void rgbInit(W_ColorPanel * panel)
3390 char tmp[4];
3391 const char *format;
3393 if (panel->color.set != cpRGB)
3394 convertCPColor(&panel->color);
3396 WMSetSliderValue(panel->rgbRedS, panel->color.rgb.red);
3397 WMSetSliderValue(panel->rgbGreenS, panel->color.rgb.green);
3398 WMSetSliderValue(panel->rgbBlueS, panel->color.rgb.blue);
3400 switch (panel->rgbState) {
3401 case RGBdec:
3402 format = "%d";
3403 break;
3404 case RGBhex:
3405 format = "%0X";
3406 break;
3409 sprintf(tmp, format, panel->color.rgb.red);
3410 WMSetTextFieldText(panel->rgbRedT, tmp);
3411 sprintf(tmp, format, panel->color.rgb.green);
3412 WMSetTextFieldText(panel->rgbGreenT, tmp);
3413 sprintf(tmp, format, panel->color.rgb.blue);
3414 WMSetTextFieldText(panel->rgbBlueT, tmp);
3417 static void cmykInit(W_ColorPanel * panel)
3419 int value[3];
3420 char tmp[4];
3422 if (panel->color.set != cpRGB)
3423 convertCPColor(&panel->color);
3425 value[0] = rint((255 - panel->color.rgb.red) / 2.55);
3426 value[1] = rint((255 - panel->color.rgb.green) / 2.55);
3427 value[2] = rint((255 - panel->color.rgb.blue) / 2.55);
3429 WMSetSliderValue(panel->cmykCyanS, value[0]);
3430 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3431 WMSetSliderValue(panel->cmykYellowS, value[2]);
3432 WMSetSliderValue(panel->cmykBlackS, 0);
3434 sprintf(tmp, "%d", value[0]);
3435 WMSetTextFieldText(panel->cmykCyanT, tmp);
3436 sprintf(tmp, "%d", value[1]);
3437 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3438 sprintf(tmp, "%d", value[2]);
3439 WMSetTextFieldText(panel->cmykYellowT, tmp);
3440 WMSetTextFieldText(panel->cmykBlackT, "0");
3443 static void hsbInit(W_ColorPanel * panel)
3445 int value[3];
3446 char tmp[4];
3448 if (panel->color.set != cpHSV)
3449 convertCPColor(&panel->color);
3451 value[0] = panel->color.hsv.hue;
3452 value[1] = rint(panel->color.hsv.saturation / 2.55);
3453 value[2] = rint(panel->color.hsv.value / 2.55);
3455 WMSetSliderValue(panel->hsbHueS, value[0]);
3456 WMSetSliderValue(panel->hsbSaturationS, value[1]);
3457 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
3459 sprintf(tmp, "%d", value[0]);
3460 WMSetTextFieldText(panel->hsbHueT, tmp);
3461 sprintf(tmp, "%d", value[1]);
3462 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3463 sprintf(tmp, "%d", value[2]);
3464 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3466 hsbUpdateBrightnessGradient(panel);
3467 hsbUpdateSaturationGradient(panel);
3468 hsbUpdateHueGradient(panel);
3471 /************************** Common utility functions ************************/
3473 static char *generateNewFilename(const char *curName)
3475 int n;
3476 char c;
3477 int baseLen;
3478 const char *ptr;
3479 char *newName;
3481 assert(curName);
3483 ptr = curName;
3485 if (((ptr = strrchr(ptr, '{')) == 0) || sscanf(ptr, "{%i}%c", &n, &c) != 1)
3486 return wstrconcat(curName, " {1}");
3488 baseLen = ptr - curName - 1;
3490 newName = wmalloc(baseLen + 16);
3491 strncpy(newName, curName, baseLen);
3493 snprintf(&newName[baseLen], 16, " {%i}", n + 1);
3495 return newName;
3498 static void convertCPColor(CPColor * color)
3500 unsigned short old_hue = 0;
3502 switch (color->set) {
3503 case cpNone:
3504 wwarning(_("Color Panel: Color unspecified"));
3505 return;
3506 case cpRGB:
3507 old_hue = color->hsv.hue;
3508 RRGBtoHSV(&(color->rgb), &(color->hsv));
3510 /* In black the hue is undefined, and may change by conversion
3511 * Same for white. */
3512 if (((color->rgb.red == 0) &&
3513 (color->rgb.green == 0) &&
3514 (color->rgb.blue == 0)) ||
3515 ((color->rgb.red == 0) && (color->rgb.green == 0) && (color->rgb.blue == 255))
3517 color->hsv.hue = old_hue;
3518 break;
3519 case cpHSV:
3520 RHSVtoRGB(&(color->hsv), &(color->rgb));
3521 break;
3525 static RColor ulongToRColor(WMScreen * scr, unsigned long value)
3527 RColor color;
3528 XColor *xcolor = NULL;
3530 xcolor = wmalloc(sizeof(XColor));
3531 xcolor->pixel = value;
3532 XQueryColor(scr->display, scr->rcontext->cmap, xcolor);
3534 color.red = xcolor->red >> 8;
3535 color.green = xcolor->green >> 8;
3536 color.blue = xcolor->blue >> 8;
3537 color.alpha = 0;
3539 wfree(xcolor);
3541 return color;
3544 static unsigned char getShift(unsigned char value)
3546 unsigned char i = -1;
3548 if (value == 0)
3549 return 0;
3551 while (value) {
3552 value >>= 1;
3553 i++;
3556 return i;