util: clarify a bit of the code for parsing commands in wmgenmenu
[wmaker-crm.git] / WINGs / wcolorpanel.c
blob0653be6a418f7a93fd02dcbfa349cc9f8a8403ee
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
267 #define BUFSIZE 1024
269 #define MAX_LENGTH 1024
271 #ifndef M_PI
272 #define M_PI 3.14159265358979323846
273 #endif
275 static char *generateNewFilename(const char *curName);
276 static void convertCPColor(CPColor * color);
277 static RColor ulongToRColor(WMScreen * scr, unsigned long value);
278 static unsigned char getShift(unsigned char value);
280 static void modeButtonCallback(WMWidget * w, void *data);
281 static int getPickerPart(W_ColorPanel * panel, int x, int y);
282 static void readConfiguration(W_ColorPanel * panel);
283 static void readXColors(W_ColorPanel * panel);
285 static void closeWindowCallback(WMWidget * w, void *data);
287 static Cursor magnifyGrabPointer(W_ColorPanel * panel);
288 static WMPoint magnifyInitialize(W_ColorPanel * panel);
289 static void magnifyPutCursor(WMWidget * w, void *data);
290 static Pixmap magnifyCreatePixmap(WMColorPanel * panel);
291 static void magnifyGetImageStored(W_ColorPanel * panel, int x1, int y1, int x2, int y2);
292 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h);
294 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height);
295 static void wheelDestroyMatrix(wheelMatrix * matrix);
296 static void wheelInitMatrix(W_ColorPanel * panel);
297 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue);
298 static void wheelRender(W_ColorPanel * panel);
299 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs);
300 static void wheelPaint(W_ColorPanel * panel);
302 static void wheelHandleEvents(XEvent * event, void *data);
303 static void wheelHandleActionEvents(XEvent * event, void *data);
304 static void wheelBrightnessSliderCallback(WMWidget * w, void *data);
305 static void wheelUpdateSelection(W_ColorPanel * panel);
306 static void wheelUndrawSelection(W_ColorPanel * panel);
308 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y);
309 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
310 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel);
311 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor);
313 static void grayBrightnessSliderCallback(WMWidget * w, void *data);
314 static void grayPresetButtonCallback(WMWidget * w, void *data);
315 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification);
317 static void rgbSliderCallback(WMWidget * w, void *data);
318 static void rgbTextFieldCallback(void *observerData, WMNotification * notification);
319 static void rgbDecToHex(WMWidget *w, void *data);
321 static void cmykSliderCallback(WMWidget * w, void *data);
322 static void cmykTextFieldCallback(void *observerData, WMNotification * notification);
324 static void hsbSliderCallback(WMWidget * w, void *data);
325 static void hsbTextFieldCallback(void *observerData, WMNotification * notification);
326 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel);
327 static void hsbUpdateSaturationGradient(W_ColorPanel * panel);
328 static void hsbUpdateHueGradient(W_ColorPanel * panel);
330 static void customRenderSpectrum(W_ColorPanel * panel);
331 static void customSetPalette(W_ColorPanel * panel);
332 static void customPaletteHandleEvents(XEvent * event, void *data);
333 static void customPaletteHandleActionEvents(XEvent * event, void *data);
334 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y);
335 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
336 static void customPaletteMenuCallback(WMWidget * w, void *data);
337 static void customPaletteHistoryCallback(WMWidget * w, void *data);
339 static void customPaletteMenuNewFromFile(W_ColorPanel * panel);
340 static void customPaletteMenuRename(W_ColorPanel * panel);
341 static void customPaletteMenuRemove(W_ColorPanel * panel);
343 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect);
344 static void colorListSelect(WMWidget * w, void *data);
345 static void colorListColorMenuCallback(WMWidget * w, void *data);
346 static void colorListListMenuCallback(WMWidget * w, void *data);
348 static void wheelInit(W_ColorPanel * panel);
349 static void grayInit(W_ColorPanel * panel);
350 static void rgbInit(W_ColorPanel * panel);
351 static void cmykInit(W_ColorPanel * panel);
352 static void hsbInit(W_ColorPanel * panel);
355 static inline int get_textfield_as_integer(WMTextField *widget)
357 char *str;
358 int value;
360 str = WMGetTextFieldText(widget);
361 value = atoi(str);
362 wfree(str);
363 return value;
366 void WMSetColorPanelAction(WMColorPanel * panel, WMAction2 * action, void *data)
368 panel->action = action;
369 panel->clientData = data;
372 static WMColorPanel *makeColorPanel(WMScreen * scrPtr, const char *name)
374 WMColorPanel *panel;
375 RImage *image;
376 WMPixmap *pixmap;
377 RColor from;
378 RColor to;
379 WMColor *textcolor, *graybuttoncolor;
380 int i;
381 GC bgc = WMColorGC(scrPtr->black);
382 GC wgc = WMColorGC(scrPtr->white);
384 panel = wmalloc(sizeof(WMColorPanel));
385 panel->color.rgb.red = 0;
386 panel->color.rgb.green = 0;
387 panel->color.rgb.blue = 0;
388 panel->color.hsv.hue = 0;
389 panel->color.hsv.saturation = 0;
390 panel->color.hsv.value = 0;
391 panel->color.set = cpNone; /* Color has not been set yet */
393 panel->font8 = WMSystemFontOfSize(scrPtr, 8);
394 panel->font12 = WMSystemFontOfSize(scrPtr, 12);
396 panel->win = WMCreateWindowWithStyle(scrPtr, name,
397 WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
398 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
399 WMSetWindowTitle(panel->win, _("Colors"));
400 WMSetWindowCloseAction(panel->win, closeWindowCallback, panel);
402 /* Set Default ColorPanel Mode(s) */
403 panel->mode = WMWheelModeColorPanel;
404 panel->lastChanged = 0;
405 panel->slidersmode = WMRGBModeColorPanel;
406 panel->configurationPath = wstrconcat(wusergnusteppath(), "/Library/Colors/");
408 /* Some General Purpose Widgets */
409 panel->colorWell = WMCreateColorWell(panel->win);
410 WMResizeWidget(panel->colorWell, 134, 36);
411 WSetColorWellBordered(panel->colorWell, False);
412 WMMoveWidget(panel->colorWell, 56, 4);
414 panel->magnifyBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
415 WMResizeWidget(panel->magnifyBtn, 46, 36);
416 WMMoveWidget(panel->magnifyBtn, 6, 4);
417 WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
418 WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
419 WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
421 panel->wheelBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
422 WMResizeWidget(panel->wheelBtn, 46, 32);
423 WMMoveWidget(panel->wheelBtn, 6, 44);
424 WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
425 WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
426 WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
428 panel->slidersBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
429 WMResizeWidget(panel->slidersBtn, 46, 32);
430 WMMoveWidget(panel->slidersBtn, 52, 44);
431 WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
432 WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
433 WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
435 panel->customPaletteBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
436 WMResizeWidget(panel->customPaletteBtn, 46, 32);
437 WMMoveWidget(panel->customPaletteBtn, 98, 44);
438 WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
439 WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
440 WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
442 panel->colorListBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
443 WMResizeWidget(panel->colorListBtn, 46, 32);
444 WMMoveWidget(panel->colorListBtn, 144, 44);
445 WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
446 WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
447 WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
449 /* Let's Group some of them together */
450 WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
451 WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
452 WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
454 /* Widgets for the ColorWheel Panel */
455 panel->wheelFrm = WMCreateFrame(panel->win);
456 WMSetFrameRelief(panel->wheelFrm, WRFlat);
457 WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
458 WMMoveWidget(panel->wheelFrm, 5, 80);
460 panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
461 /* XXX Can we create a view ? */
462 W_ResizeView(panel->wheelView, colorWheelSize + 4, colorWheelSize + 4);
463 W_MoveView(panel->wheelView, 0, 0);
465 /* Create an event handler to handle expose/click events in ColorWheel */
466 WMCreateEventHandler(panel->wheelView,
467 ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
468 LeaveWindowMask | ButtonMotionMask, wheelHandleActionEvents, panel);
470 WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents, panel);
472 panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
473 WMResizeWidget(panel->wheelBrightnessS, 16, 153);
474 WMMoveWidget(panel->wheelBrightnessS, 5 + colorWheelSize + 14, 1);
475 WMSetSliderMinValue(panel->wheelBrightnessS, 0);
476 WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
477 WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback, panel);
478 WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
480 panel->wheelMtrx = wheelCreateMatrix(colorWheelSize + 4, colorWheelSize + 4);
481 wheelInitMatrix(panel);
483 /* Widgets for the Slider Panels */
484 panel->slidersFrm = WMCreateFrame(panel->win);
485 WMSetFrameRelief(panel->slidersFrm, WRFlat);
486 WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
487 WMMoveWidget(panel->slidersFrm, 4, 80);
489 panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
490 WMSetFrameRelief(panel->seperatorFrm, WRPushed);
491 WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
492 WMMoveWidget(panel->seperatorFrm, 0, 1);
494 panel->grayBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
495 WMResizeWidget(panel->grayBtn, 46, 24);
496 WMMoveWidget(panel->grayBtn, 1, 8);
497 WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
498 WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
499 WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
501 panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
502 WMResizeWidget(panel->rgbBtn, 46, 24);
503 WMMoveWidget(panel->rgbBtn, 47, 8);
504 WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
505 WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
506 WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
508 panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
509 WMResizeWidget(panel->cmykBtn, 46, 24);
510 WMMoveWidget(panel->cmykBtn, 93, 8);
511 WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
512 WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
513 WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
515 panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
516 WMResizeWidget(panel->hsbBtn, 46, 24);
517 WMMoveWidget(panel->hsbBtn, 139, 8);
518 WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
519 WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
520 WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
522 /* Let's Group the Slider Panel Buttons Together */
523 WMGroupButtons(panel->grayBtn, panel->rgbBtn);
524 WMGroupButtons(panel->grayBtn, panel->cmykBtn);
525 WMGroupButtons(panel->grayBtn, panel->hsbBtn);
527 textcolor = WMDarkGrayColor(scrPtr);
529 /* Widgets for GrayScale Panel */
530 panel->grayFrm = WMCreateFrame(panel->slidersFrm);
531 WMSetFrameRelief(panel->grayFrm, WRFlat);
532 WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
533 WMMoveWidget(panel->grayFrm, 0, 34);
535 panel->grayMinL = WMCreateLabel(panel->grayFrm);
536 WMResizeWidget(panel->grayMinL, 20, 10);
537 WMMoveWidget(panel->grayMinL, 2, 2);
538 WMSetLabelText(panel->grayMinL, "0");
539 WMSetLabelTextAlignment(panel->grayMinL, WALeft);
540 WMSetLabelTextColor(panel->grayMinL, textcolor);
541 WMSetLabelFont(panel->grayMinL, panel->font8);
543 panel->grayMaxL = WMCreateLabel(panel->grayFrm);
544 WMResizeWidget(panel->grayMaxL, 40, 10);
545 WMMoveWidget(panel->grayMaxL, 104, 2);
546 WMSetLabelText(panel->grayMaxL, "100");
547 WMSetLabelTextAlignment(panel->grayMaxL, WARight);
548 WMSetLabelTextColor(panel->grayMaxL, textcolor);
549 WMSetLabelFont(panel->grayMaxL, panel->font8);
551 panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
552 WMResizeWidget(panel->grayBrightnessS, 141, 16);
553 WMMoveWidget(panel->grayBrightnessS, 2, 14);
554 WMSetSliderMinValue(panel->grayBrightnessS, 0);
555 WMSetSliderMaxValue(panel->grayBrightnessS, 100);
556 WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
557 WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback, panel);
559 from.red = 0;
560 from.green = 0;
561 from.blue = 0;
563 to.red = 255;
564 to.green = 255;
565 to.blue = 255;
567 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
568 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
569 RReleaseImage(image);
571 if (pixmap)
572 W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap,
573 panel->font12, 2, 0, 100, WALeft, scrPtr->white,
574 False, _("Brightness"), strlen(_("Brightness")));
575 else
576 wwarning(_("Color Panel: Could not allocate memory"));
578 WMSetSliderImage(panel->grayBrightnessS, pixmap);
579 WMReleasePixmap(pixmap);
581 panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
582 WMResizeWidget(panel->grayBrightnessT, 40, 18);
583 WMMoveWidget(panel->grayBrightnessT, 146, 13);
584 WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
585 WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel,
586 WMTextDidEndEditingNotification, panel->grayBrightnessT);
588 for (i = 0; i < 7; i++) {
589 pixmap = WMCreatePixmap(scrPtr, 13, 13, scrPtr->depth, False);
591 graybuttoncolor = WMCreateRGBColor(scrPtr, (255 / 6) * i << 8,
592 (255 / 6) * i << 8, (255 / 6) * i << 8, True);
593 WMPaintColorSwatch(graybuttoncolor, pixmap->pixmap, 0, 0, 15, 15);
594 WMReleaseColor(graybuttoncolor);
596 panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
597 WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
598 WMMoveWidget(panel->grayPresetBtn[i], 2 + (i * 20), 34);
599 WMSetButtonAction(panel->grayPresetBtn[i], grayPresetButtonCallback, panel);
600 WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
601 WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
602 WMReleasePixmap(pixmap);
606 /* End of GrayScale Panel */
608 /* Widgets for RGB Panel */
609 panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
610 WMSetFrameRelief(panel->rgbFrm, WRFlat);
611 WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
612 WMMoveWidget(panel->rgbFrm, 0, 34);
614 panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
615 WMResizeWidget(panel->rgbMinL, 20, 10);
616 WMMoveWidget(panel->rgbMinL, 2, 2);
617 WMSetLabelText(panel->rgbMinL, "0");
618 WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
619 WMSetLabelTextColor(panel->rgbMinL, textcolor);
620 WMSetLabelFont(panel->rgbMinL, panel->font8);
622 panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
623 WMResizeWidget(panel->rgbMaxL, 40, 10);
624 WMMoveWidget(panel->rgbMaxL, 104, 2);
625 WMSetLabelText(panel->rgbMaxL, "255");
626 WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
627 WMSetLabelTextColor(panel->rgbMaxL, textcolor);
628 WMSetLabelFont(panel->rgbMaxL, panel->font8);
630 panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
631 WMResizeWidget(panel->rgbRedS, 141, 16);
632 WMMoveWidget(panel->rgbRedS, 2, 14);
633 WMSetSliderMinValue(panel->rgbRedS, 0);
634 WMSetSliderMaxValue(panel->rgbRedS, 255);
635 WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
636 WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
638 to.red = 255;
639 to.green = 0;
640 to.blue = 0;
642 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
643 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
644 RReleaseImage(image);
646 if (pixmap)
647 W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12,
648 2, 0, 100, WALeft, scrPtr->white, False, _("Red"), strlen(_("Red")));
649 else
650 wwarning(_("Color Panel: Could not allocate memory"));
652 WMSetSliderImage(panel->rgbRedS, pixmap);
653 WMReleasePixmap(pixmap);
655 panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
656 WMResizeWidget(panel->rgbRedT, 40, 18);
657 WMMoveWidget(panel->rgbRedT, 146, 13);
658 WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
659 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbRedT);
661 panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
662 WMResizeWidget(panel->rgbGreenS, 141, 16);
663 WMMoveWidget(panel->rgbGreenS, 2, 36);
664 WMSetSliderMinValue(panel->rgbGreenS, 0);
665 WMSetSliderMaxValue(panel->rgbGreenS, 255);
666 WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
667 WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
669 to.red = 0;
670 to.green = 255;
671 to.blue = 0;
673 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
674 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
675 RReleaseImage(image);
677 if (pixmap)
678 W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12,
679 2, 0, 100, WALeft, scrPtr->white, False, _("Green"), strlen(_("Green")));
680 else
681 wwarning(_("Color Panel: Could not allocate memory"));
683 WMSetSliderImage(panel->rgbGreenS, pixmap);
684 WMReleasePixmap(pixmap);
686 panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
687 WMResizeWidget(panel->rgbGreenT, 40, 18);
688 WMMoveWidget(panel->rgbGreenT, 146, 35);
689 WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
690 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbGreenT);
692 panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
693 WMResizeWidget(panel->rgbBlueS, 141, 16);
694 WMMoveWidget(panel->rgbBlueS, 2, 58);
695 WMSetSliderMinValue(panel->rgbBlueS, 0);
696 WMSetSliderMaxValue(panel->rgbBlueS, 255);
697 WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
698 WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
700 to.red = 0;
701 to.green = 0;
702 to.blue = 255;
704 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
705 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
706 RReleaseImage(image);
708 if (pixmap)
709 W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12,
710 2, 0, 100, WALeft, scrPtr->white, False, _("Blue"), strlen(_("Blue")));
711 else
712 wwarning(_("Color Panel: Could not allocate memory"));
714 WMSetSliderImage(panel->rgbBlueS, pixmap);
715 WMReleasePixmap(pixmap);
717 panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
718 WMResizeWidget(panel->rgbBlueT, 40, 18);
719 WMMoveWidget(panel->rgbBlueT, 146, 57);
720 WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
721 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbBlueT);
723 panel->rgbDecB = WMCreateButton(panel->rgbFrm, WBTRadio);
724 WMSetButtonText(panel->rgbDecB, "Decimal");
725 WMSetButtonSelected(panel->rgbDecB, 1);
726 panel->rgbState = RGBdec;
727 WMSetButtonAction(panel->rgbDecB, rgbDecToHex, panel);
728 WMResizeWidget(panel->rgbDecB, PWIDTH - 8, 23);
729 WMMoveWidget(panel->rgbDecB, 2, 81);
731 panel->rgbHexB = WMCreateButton(panel->rgbFrm, WBTRadio);
732 WMSetButtonText(panel->rgbHexB, "Hexadecimal");
733 WMSetButtonAction(panel->rgbHexB, rgbDecToHex, panel);
734 WMResizeWidget(panel->rgbHexB, PWIDTH - 8, 23);
735 WMMoveWidget(panel->rgbHexB, 2, 104);
737 WMGroupButtons(panel->rgbDecB, panel->rgbHexB);
739 /* End of RGB Panel */
741 /* Widgets for CMYK Panel */
742 panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
743 WMSetFrameRelief(panel->cmykFrm, WRFlat);
744 WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
745 WMMoveWidget(panel->cmykFrm, 0, 34);
747 panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
748 WMResizeWidget(panel->cmykMinL, 20, 10);
749 WMMoveWidget(panel->cmykMinL, 2, 2);
750 WMSetLabelText(panel->cmykMinL, "0");
751 WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
752 WMSetLabelTextColor(panel->cmykMinL, textcolor);
753 WMSetLabelFont(panel->cmykMinL, panel->font8);
755 panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
756 WMResizeWidget(panel->cmykMaxL, 40, 10);
757 WMMoveWidget(panel->cmykMaxL, 104, 2);
758 WMSetLabelText(panel->cmykMaxL, "100");
759 WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
760 WMSetLabelTextColor(panel->cmykMaxL, textcolor);
761 WMSetLabelFont(panel->cmykMaxL, panel->font8);
763 panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
764 WMResizeWidget(panel->cmykCyanS, 141, 16);
765 WMMoveWidget(panel->cmykCyanS, 2, 14);
766 WMSetSliderMinValue(panel->cmykCyanS, 0);
767 WMSetSliderMaxValue(panel->cmykCyanS, 100);
768 WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
769 WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
771 from.red = 255;
772 from.green = 255;
773 from.blue = 255;
775 to.red = 0;
776 to.green = 255;
777 to.blue = 255;
779 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
780 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
781 RReleaseImage(image);
783 if (pixmap)
784 W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12,
785 2, 0, 100, WALeft, scrPtr->black, False, _("Cyan"), strlen(_("Cyan")));
786 else
787 wwarning(_("Color Panel: Could not allocate memory"));
789 WMSetSliderImage(panel->cmykCyanS, pixmap);
790 WMReleasePixmap(pixmap);
792 panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
793 WMResizeWidget(panel->cmykCyanT, 40, 18);
794 WMMoveWidget(panel->cmykCyanT, 146, 13);
795 WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
796 WMAddNotificationObserver(cmykTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->cmykCyanT);
798 panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
799 WMResizeWidget(panel->cmykMagentaS, 141, 16);
800 WMMoveWidget(panel->cmykMagentaS, 2, 36);
801 WMSetSliderMinValue(panel->cmykMagentaS, 0);
802 WMSetSliderMaxValue(panel->cmykMagentaS, 100);
803 WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
804 WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
806 to.red = 255;
807 to.green = 0;
808 to.blue = 255;
810 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
811 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
812 RReleaseImage(image);
814 if (pixmap)
815 W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12,
816 2, 0, 100, WALeft, scrPtr->black, False, _("Magenta"), strlen(_("Magenta")));
817 else
818 wwarning(_("Color Panel: Could not allocate memory"));
820 WMSetSliderImage(panel->cmykMagentaS, pixmap);
821 WMReleasePixmap(pixmap);
823 panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
824 WMResizeWidget(panel->cmykMagentaT, 40, 18);
825 WMMoveWidget(panel->cmykMagentaT, 146, 35);
826 WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
827 WMAddNotificationObserver(cmykTextFieldCallback, panel,
828 WMTextDidEndEditingNotification, panel->cmykMagentaT);
830 panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
831 WMResizeWidget(panel->cmykYellowS, 141, 16);
832 WMMoveWidget(panel->cmykYellowS, 2, 58);
833 WMSetSliderMinValue(panel->cmykYellowS, 0);
834 WMSetSliderMaxValue(panel->cmykYellowS, 100);
835 WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
836 WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
838 to.red = 255;
839 to.green = 255;
840 to.blue = 0;
842 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
843 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
844 RReleaseImage(image);
846 if (pixmap)
847 W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12,
848 2, 0, 100, WALeft, scrPtr->black, False, _("Yellow"), strlen(_("Yellow")));
849 else
850 wwarning(_("Color Panel: Could not allocate memory"));
852 WMSetSliderImage(panel->cmykYellowS, pixmap);
853 WMReleasePixmap(pixmap);
855 panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
856 WMResizeWidget(panel->cmykYellowT, 40, 18);
857 WMMoveWidget(panel->cmykYellowT, 146, 57);
858 WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
859 WMAddNotificationObserver(cmykTextFieldCallback, panel,
860 WMTextDidEndEditingNotification, panel->cmykYellowT);
862 panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
863 WMResizeWidget(panel->cmykBlackS, 141, 16);
864 WMMoveWidget(panel->cmykBlackS, 2, 80);
865 WMSetSliderMinValue(panel->cmykBlackS, 0);
866 WMSetSliderMaxValue(panel->cmykBlackS, 100);
867 WMSetSliderValue(panel->cmykBlackS, 0);
868 WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
869 WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
871 to.red = 0;
872 to.green = 0;
873 to.blue = 0;
875 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
876 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
877 RReleaseImage(image);
879 if (pixmap)
880 W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12,
881 2, 0, 100, WALeft, scrPtr->black, False, _("Black"), strlen(_("Black")));
882 else
883 wwarning(_("Color Panel: Could not allocate memory"));
885 WMSetSliderImage(panel->cmykBlackS, pixmap);
886 WMReleasePixmap(pixmap);
888 panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
889 WMResizeWidget(panel->cmykBlackT, 40, 18);
890 WMMoveWidget(panel->cmykBlackT, 146, 79);
891 WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
892 WMAddNotificationObserver(cmykTextFieldCallback, panel,
893 WMTextDidEndEditingNotification, panel->cmykBlackT);
894 /* End of CMYK Panel */
896 /* Widgets for HSB Panel */
897 panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
898 WMSetFrameRelief(panel->hsbFrm, WRFlat);
899 WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
900 WMMoveWidget(panel->hsbFrm, 0, 34);
902 panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
903 WMResizeWidget(panel->hsbHueS, 141, 16);
904 WMMoveWidget(panel->hsbHueS, 2, 14);
905 WMSetSliderMinValue(panel->hsbHueS, 0);
906 WMSetSliderMaxValue(panel->hsbHueS, 359);
907 WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
908 WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
910 panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
911 WMResizeWidget(panel->hsbHueT, 40, 18);
912 WMMoveWidget(panel->hsbHueT, 146, 13);
913 WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
914 WMAddNotificationObserver(hsbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->hsbHueT);
916 panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
917 WMResizeWidget(panel->hsbSaturationS, 141, 16);
918 WMMoveWidget(panel->hsbSaturationS, 2, 36);
919 WMSetSliderMinValue(panel->hsbSaturationS, 0);
920 WMSetSliderMaxValue(panel->hsbSaturationS, 100);
921 WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
922 WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
924 panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
925 WMResizeWidget(panel->hsbSaturationT, 40, 18);
926 WMMoveWidget(panel->hsbSaturationT, 146, 35);
927 WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
928 WMAddNotificationObserver(hsbTextFieldCallback, panel,
929 WMTextDidEndEditingNotification, panel->hsbSaturationT);
931 panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
932 WMResizeWidget(panel->hsbBrightnessS, 141, 16);
933 WMMoveWidget(panel->hsbBrightnessS, 2, 58);
934 WMSetSliderMinValue(panel->hsbBrightnessS, 0);
935 WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
936 WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
937 WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
939 panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
940 WMResizeWidget(panel->hsbBrightnessT, 40, 18);
941 WMMoveWidget(panel->hsbBrightnessT, 146, 57);
942 WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
943 WMAddNotificationObserver(hsbTextFieldCallback, panel,
944 WMTextDidEndEditingNotification, panel->hsbBrightnessT);
945 /* End of HSB Panel */
947 WMReleaseColor(textcolor);
949 /* Widgets for the CustomPalette Panel */
950 panel->customPaletteFrm = WMCreateFrame(panel->win);
951 WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
952 WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
953 WMMoveWidget(panel->customPaletteFrm, 5, 80);
955 panel->customPaletteHistoryBtn = WMCreatePopUpButton(panel->customPaletteFrm);
956 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, _("Spectrum"));
957 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
958 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1);
959 WMSetPopUpButtonAction(panel->customPaletteHistoryBtn, customPaletteHistoryCallback, panel);
960 WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
961 WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
963 panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
964 WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
965 WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
966 WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
968 panel->customPaletteContentView = W_CreateView(W_VIEW(panel->customPaletteContentFrm));
969 /* XXX Test if we can create a view */
970 W_ResizeView(panel->customPaletteContentView, customPaletteWidth, customPaletteHeight);
971 W_MoveView(panel->customPaletteContentView, 2, 2);
973 /* Create event handler to handle expose/click events in CustomPalette */
974 WMCreateEventHandler(panel->customPaletteContentView,
975 ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
976 ButtonMotionMask, customPaletteHandleActionEvents, panel);
978 WMCreateEventHandler(panel->customPaletteContentView, ExposureMask, customPaletteHandleEvents, panel);
980 panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
981 WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
982 WMSetPopUpButtonText(panel->customPaletteMenuBtn, _("Palette"));
983 WMSetPopUpButtonAction(panel->customPaletteMenuBtn, customPaletteMenuCallback, panel);
984 WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
985 WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
987 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from File..."));
988 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Rename..."));
989 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Remove"));
990 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Copy"));
991 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from Clipboard"));
993 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, 0);
994 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, 0);
995 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuCopy, 0);
996 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuNewFromClipboard, 0);
998 customRenderSpectrum(panel);
999 panel->currentPalette = 0;
1000 panel->palx = customPaletteWidth / 2;
1001 panel->paly = customPaletteHeight / 2;
1003 /* Widgets for the ColorList Panel */
1004 panel->colorListFrm = WMCreateFrame(panel->win);
1005 WMSetFrameRelief(panel->colorListFrm, WRFlat);
1006 WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
1007 WMMoveWidget(panel->colorListFrm, 5, 80);
1009 panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
1010 WMAddPopUpButtonItem(panel->colorListHistoryBtn, _("X11-Colors"));
1011 WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn,
1012 WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn) - 1);
1013 /* WMSetPopUpButtonAction(panel->colorListHistoryBtn,
1014 * colorListHistoryCallback, panel); */
1015 WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
1016 WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
1018 panel->colorListContentLst = WMCreateList(panel->colorListFrm);
1019 WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
1020 WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
1021 WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
1022 WMMoveWidget(panel->colorListContentLst, 0, 23);
1023 WMHangData(panel->colorListContentLst, panel);
1025 panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1026 WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
1027 WMSetPopUpButtonText(panel->colorListColorMenuBtn, _("Color"));
1028 WMSetPopUpButtonAction(panel->colorListColorMenuBtn, colorListColorMenuCallback, panel);
1029 WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16) / 2, 20);
1030 WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
1032 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Add..."));
1033 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Rename..."));
1034 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Remove"));
1036 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuAdd, 0);
1037 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRename, 0);
1038 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRemove, 0);
1040 panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1041 WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
1042 WMSetPopUpButtonText(panel->colorListListMenuBtn, _("List"));
1043 WMSetPopUpButtonAction(panel->colorListListMenuBtn, colorListListMenuCallback, panel);
1044 WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2, 20);
1045 WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2 + 8, PHEIGHT - 130);
1047 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("New..."));
1048 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Rename..."));
1049 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Remove"));
1051 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuAdd, 0);
1052 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
1053 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
1055 WMRealizeWidget(panel->win);
1056 WMMapSubwidgets(panel->win);
1058 WMMapSubwidgets(panel->wheelFrm);
1059 WMMapSubwidgets(panel->slidersFrm);
1060 WMMapSubwidgets(panel->grayFrm);
1061 WMMapSubwidgets(panel->rgbFrm);
1062 WMMapSubwidgets(panel->cmykFrm);
1063 WMMapSubwidgets(panel->hsbFrm);
1064 WMMapSubwidgets(panel->customPaletteFrm);
1065 WMMapSubwidgets(panel->customPaletteContentFrm);
1066 WMMapSubwidgets(panel->colorListFrm);
1068 /* Pixmap to indicate selection positions
1069 * wheelframe MUST be mapped.
1071 panel->selectionImg = XCreatePixmap(scrPtr->display, WMWidgetXID(panel->win), 4, 4, scrPtr->depth);
1072 XFillRectangle(scrPtr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1073 XFillRectangle(scrPtr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1075 readConfiguration(panel);
1076 readXColors(panel);
1078 return panel;
1081 WMColorPanel *WMGetColorPanel(WMScreen * scrPtr)
1083 WMColorPanel *panel;
1085 if (scrPtr->sharedColorPanel)
1086 return scrPtr->sharedColorPanel;
1088 panel = makeColorPanel(scrPtr, "colorPanel");
1090 scrPtr->sharedColorPanel = panel;
1092 return panel;
1095 void WMFreeColorPanel(WMColorPanel * panel)
1097 W_Screen *scr;
1099 if (!panel)
1100 return;
1102 scr = WMWidgetScreen(panel->win);
1103 if (panel == scr->sharedColorPanel) {
1104 scr->sharedColorPanel = NULL;
1107 WMRemoveNotificationObserver(panel);
1108 WMUnmapWidget(panel->win);
1110 /* fonts */
1111 WMReleaseFont(panel->font8);
1112 WMReleaseFont(panel->font12);
1114 /* pixmaps */
1115 wheelDestroyMatrix(panel->wheelMtrx);
1116 if (panel->wheelImg)
1117 XFreePixmap(scr->display, panel->wheelImg);
1118 if (panel->selectionImg)
1119 XFreePixmap(scr->display, panel->selectionImg);
1120 if (panel->selectionBackImg)
1121 XFreePixmap(scr->display, panel->selectionBackImg);
1122 RReleaseImage(panel->customPaletteImg);
1124 /* structs */
1125 if (panel->lastBrowseDir)
1126 wfree(panel->lastBrowseDir);
1127 if (panel->configurationPath)
1128 wfree(panel->configurationPath);
1130 WMDestroyWidget(panel->win);
1132 wfree(panel);
1135 void WMCloseColorPanel(WMColorPanel * panel)
1137 WMFreeColorPanel(panel);
1140 void WMShowColorPanel(WMColorPanel * panel)
1142 WMScreen *scr = WMWidgetScreen(panel->win);
1143 WMColor *white = WMWhiteColor(scr);
1145 if (panel->color.set == cpNone)
1146 WMSetColorPanelColor(panel, white);
1147 WMReleaseColor(white);
1149 if (panel->mode != WMWheelModeColorPanel)
1150 WMPerformButtonClick(panel->wheelBtn);
1152 WMMapWidget(panel->win);
1155 static void closeWindowCallback(WMWidget * w, void *data)
1157 W_ColorPanel *panel = (W_ColorPanel *) data;
1159 /* Parameter not used, but tell the compiler that it is ok */
1160 (void) w;
1162 WMCloseColorPanel(panel);
1165 static void readConfiguration(W_ColorPanel * panel)
1167 /* XXX Doesn't take care of "invalid" files */
1169 DIR *dPtr;
1170 struct dirent *dp;
1171 struct stat stat_buf;
1172 int item;
1174 if (stat(panel->configurationPath, &stat_buf) != 0) {
1175 if (mkdir(panel->configurationPath, S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH) != 0) {
1176 werror(_("Color Panel: Could not create directory %s needed"
1177 " to store configurations"), panel->configurationPath);
1178 WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
1179 WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
1180 WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
1181 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1182 _("File Error"),
1183 _("Could not create ColorPanel configuration directory"),
1184 _("OK"), NULL, NULL);
1186 return;
1189 if (!(dPtr = opendir(panel->configurationPath))) {
1190 wwarning("%s: %s", _("Color Panel: Could not find file"), panel->configurationPath);
1191 return;
1194 while ((dp = readdir(dPtr)) != NULL) {
1195 unsigned int perm_mask;
1196 char *path = wstrconcat(panel->configurationPath,
1197 dp->d_name);
1199 if (dp->d_name[0] != '.') {
1200 item = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
1201 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
1203 perm_mask = (access(path, R_OK) == 0);
1204 WMSetPopUpButtonItemEnabled(panel->customPaletteHistoryBtn, item, perm_mask);
1206 wfree(path);
1208 closedir(dPtr);
1211 static void readXColors(W_ColorPanel * panel)
1213 WMListItem *item;
1214 const RGBColor *entry;
1216 for (entry = rgbColors; entry->name != NULL; entry++) {
1217 item = WMAddListItem(panel->colorListContentLst, entry->name);
1218 item->clientData = (void *)&(entry->color);
1222 void WMSetColorPanelPickerMode(WMColorPanel * panel, WMColorPanelMode mode)
1224 W_Screen *scr = WMWidgetScreen(panel->win);
1226 if (mode != WMWheelModeColorPanel) {
1227 WMUnmapWidget(panel->wheelFrm);
1228 if (panel->selectionBackImg) {
1229 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1230 panel->selectionBackImg = None;
1233 if (mode != WMGrayModeColorPanel)
1234 WMUnmapWidget(panel->grayFrm);
1235 if (mode != WMRGBModeColorPanel)
1236 WMUnmapWidget(panel->rgbFrm);
1237 if (mode != WMCMYKModeColorPanel)
1238 WMUnmapWidget(panel->cmykFrm);
1239 if (mode != WMHSBModeColorPanel)
1240 WMUnmapWidget(panel->hsbFrm);
1241 if (mode != WMCustomPaletteModeColorPanel) {
1242 WMUnmapWidget(panel->customPaletteFrm);
1243 if (panel->selectionBackImg) {
1244 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1245 panel->selectionBackImg = None;
1248 if (mode != WMColorListModeColorPanel)
1249 WMUnmapWidget(panel->colorListFrm);
1250 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
1251 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1252 WMUnmapWidget(panel->slidersFrm);
1253 else
1254 panel->slidersmode = mode;
1256 if (mode == WMWheelModeColorPanel) {
1257 WMMapWidget(panel->wheelFrm);
1258 WMSetButtonSelected(panel->wheelBtn, True);
1259 if (panel->lastChanged != WMWheelModeColorPanel)
1260 wheelInit(panel);
1261 wheelRender(panel);
1262 wheelPaint(panel);
1263 } else if (mode == WMGrayModeColorPanel) {
1264 WMMapWidget(panel->slidersFrm);
1265 WMSetButtonSelected(panel->slidersBtn, True);
1266 WMMapWidget(panel->grayFrm);
1267 WMSetButtonSelected(panel->grayBtn, True);
1268 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1269 if (panel->lastChanged != WMGrayModeColorPanel)
1270 grayInit(panel);
1271 } else if (mode == WMRGBModeColorPanel) {
1272 WMMapWidget(panel->slidersFrm);
1273 WMSetButtonSelected(panel->slidersBtn, True);
1274 WMMapWidget(panel->rgbFrm);
1275 WMSetButtonSelected(panel->rgbBtn, True);
1276 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1277 if (panel->lastChanged != WMRGBModeColorPanel)
1278 rgbInit(panel);
1279 } else if (mode == WMCMYKModeColorPanel) {
1280 WMMapWidget(panel->slidersFrm);
1281 WMSetButtonSelected(panel->slidersBtn, True);
1282 WMMapWidget(panel->cmykFrm);
1283 WMSetButtonSelected(panel->cmykBtn, True);
1284 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1285 if (panel->lastChanged != WMCMYKModeColorPanel)
1286 cmykInit(panel);
1287 } else if (mode == WMHSBModeColorPanel) {
1288 WMMapWidget(panel->slidersFrm);
1289 WMSetButtonSelected(panel->slidersBtn, True);
1290 WMMapWidget(panel->hsbFrm);
1291 WMSetButtonSelected(panel->hsbBtn, True);
1292 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1293 if (panel->lastChanged != WMHSBModeColorPanel)
1294 hsbInit(panel);
1295 } else if (mode == WMCustomPaletteModeColorPanel) {
1296 WMMapWidget(panel->customPaletteFrm);
1297 WMSetButtonSelected(panel->customPaletteBtn, True);
1298 customSetPalette(panel);
1299 } else if (mode == WMColorListModeColorPanel) {
1300 WMMapWidget(panel->colorListFrm);
1301 WMSetButtonSelected(panel->colorListBtn, True);
1304 panel->mode = mode;
1307 WMColor *WMGetColorPanelColor(WMColorPanel * panel)
1309 return WMGetColorWellColor(panel->colorWell);
1312 void WMSetColorPanelColor(WMColorPanel * panel, WMColor * color)
1314 WMSetColorWellColor(panel->colorWell, color);
1316 panel->color.rgb.red = color->color.red >> 8;
1317 panel->color.rgb.green = color->color.green >> 8;
1318 panel->color.rgb.blue = color->color.blue >> 8;
1319 panel->color.set = cpRGB;
1321 if (panel->mode == panel->lastChanged)
1322 panel->lastChanged = 0;
1324 WMSetColorPanelPickerMode(panel, panel->mode);
1327 static void updateSwatch(WMColorPanel * panel, CPColor color)
1329 WMScreen *scr = WMWidgetScreen(panel->win);
1330 WMColor *wellcolor;
1332 if (color.set != cpRGB)
1333 convertCPColor(&color);
1335 panel->color = color;
1337 wellcolor = WMCreateRGBColor(scr, color.rgb.red << 8, color.rgb.green << 8, color.rgb.blue << 8, True);
1339 WMSetColorWellColor(panel->colorWell, wellcolor);
1340 WMReleaseColor(wellcolor);
1342 if (!panel->flags.dragging || panel->flags.continuous) {
1343 if (panel->action)
1344 (*panel->action) (panel, panel->clientData);
1346 WMPostNotificationName(WMColorPanelColorChangedNotification, panel, NULL);
1350 static void modeButtonCallback(WMWidget * w, void *data)
1352 W_ColorPanel *panel = (W_ColorPanel *) (data);
1354 if (w == panel->wheelBtn)
1355 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1356 else if (w == panel->slidersBtn)
1357 WMSetColorPanelPickerMode(panel, panel->slidersmode);
1358 else if (w == panel->customPaletteBtn)
1359 WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
1360 else if (w == panel->colorListBtn)
1361 WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
1362 else if (w == panel->grayBtn)
1363 WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
1364 else if (w == panel->rgbBtn)
1365 WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
1366 else if (w == panel->cmykBtn)
1367 WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
1368 else if (w == panel->hsbBtn)
1369 WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
1372 /****************** Magnifying Cursor Functions *******************/
1374 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h)
1376 int x0 = 0, y0 = 0, w0 = w, h0 = h;
1377 const int displayWidth = DisplayWidth(scr->display, scr->screen),
1378 displayHeight = DisplayHeight(scr->display, scr->screen);
1380 if (!(image && image->data)) {
1381 /* The image in panel->magnifyGlass->image does not exist yet.
1382 * Grab one from the screen (not beyond) and use it from now on.
1384 if (!(image = XGetImage(scr->display, scr->rootWin,
1385 x - Cursor_x_hot, y - Cursor_y_hot, w, h, AllPlanes, ZPixmap)))
1386 wwarning(_("Color Panel: X failed request"));
1388 return image;
1391 /* Coordinate correction for back pixmap
1392 * if magnifying glass is at screen-borders
1395 /* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
1396 * Hatched area is beyond screen border.
1398 * |<-Cursor_x_hot->|
1399 * ________________|_____
1400 * |/ / / / / / /| | |
1401 * | / / / / / / |(x,y) |
1402 * |/_/_/_/_/_/_/|________|
1403 * |<----x0----->|<--w0-->|
1407 /* Figure 2: Shifting of rectangle-to-grab at bottom/right
1408 * screen borders
1409 * Hatched area is beyond screen border
1411 * |<-Cursor_x_hot->|
1412 * ________________|_______________
1413 * | | | / / / / / /|
1414 * | (x,y)|/ / / / / / |
1415 * |___________________|_/_/_/_/_/_/|
1416 * |<-------w0-------->| |
1417 * |<---------------w--|----------->|
1418 * | |
1419 * x0 Displaywidth-1
1422 if (x < Cursor_x_hot) { /* see fig. 1 */
1423 x0 = Cursor_x_hot - x;
1424 w0 = w - x0;
1427 if (displayWidth - 1 < x - Cursor_x_hot + w) { /* see fig. 2 */
1428 w0 = (displayWidth) - (x - Cursor_x_hot);
1431 if (y < Cursor_y_hot) { /* see fig. 1 */
1432 y0 = Cursor_y_hot - y;
1433 h0 = h - y0;
1436 if (displayHeight - 1 < y - Cursor_y_hot + h) { /* see fig. 2 */
1437 h0 = (displayHeight) - (y - Cursor_y_hot);
1439 /* end of coordinate correction */
1441 /* Grab an image from the screen, clipped if necessary,
1442 * and put it in the existing panel->magnifyGlass->image
1443 * with the corresponding clipping offset.
1445 if (!XGetSubImage(scr->display, scr->rootWin,
1446 x - Cursor_x_hot + x0, y - Cursor_y_hot + y0, w0, h0, AllPlanes, ZPixmap, image, x0, y0))
1447 wwarning(_("Color Panel: X failed request"));
1449 return NULL;
1452 static void magnifyGetImageStored(WMColorPanel * panel, int x1, int y1, int x2, int y2)
1454 /* (x1, y1) = topleft corner of existing rectangle
1455 * (x2, y2) = topleft corner of new position
1458 W_Screen *scr = WMWidgetScreen(panel->win);
1459 int xa = 0, ya = 0, xb = 0, yb = 0;
1460 int width, height;
1461 const int dx = abs(x2 - x1), dy = abs(y2 - y1);
1462 XImage *image;
1463 const int x_min = Cursor_x_hot,
1464 y_min = Cursor_y_hot,
1465 x_max = DisplayWidth(scr->display, scr->screen) - 1 -
1466 (Cursor_mask_width - Cursor_x_hot),
1467 y_max = DisplayHeight(scr->display, scr->screen) - 1 - (Cursor_mask_height - Cursor_y_hot);
1469 if ((dx == 0) && (dy == 0) && panel->magnifyGlass->image)
1470 return; /* No movement */
1472 if (x1 < x2)
1473 xa = dx;
1474 else
1475 xb = dx;
1477 if (y1 < y2)
1478 ya = dy;
1479 else
1480 yb = dy;
1482 width = Cursor_mask_width - dx;
1483 height = Cursor_mask_height - dy;
1485 /* If the traversed distance is larger than the size of the magnifying
1486 * glass contents, there is no need to do dirty rectangles. A whole new
1487 * rectangle can be grabbed (unless that rectangle falls partially
1488 * off screen).
1489 * Destroying the image and setting it to NULL will achieve that later on.
1491 * Of course, grabbing an XImage beyond the borders of the screen will
1492 * cause trouble, this is considdered a special case. Part of the screen
1493 * is grabbed, but there is no need for dirty rectangles.
1495 if ((width <= 0) || (height <= 0)) {
1496 if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
1497 if (panel->magnifyGlass->image)
1498 XDestroyImage(panel->magnifyGlass->image);
1499 panel->magnifyGlass->image = NULL;
1501 } else {
1502 if (panel->magnifyGlass->image) {
1503 /* Get dirty rectangle from panel->magnifyGlass->image */
1504 panel->magnifyGlass->dirtyRect =
1505 XSubImage(panel->magnifyGlass->image, xa, ya, width, height);
1506 if (!panel->magnifyGlass->dirtyRect) {
1507 wwarning(_("Color Panel: X failed request"));
1508 return; /* X returned a NULL from XSubImage */
1513 /* Get image from screen */
1514 image = magnifyGetImage(scr, panel->magnifyGlass->image, x2, y2, Cursor_mask_width, Cursor_mask_height);
1515 if (image) { /* Only reassign if a *new* image was grabbed */
1516 panel->magnifyGlass->image = image;
1517 return;
1520 /* Copy previously stored rectangle on covered part of image */
1521 if (panel->magnifyGlass->image && panel->magnifyGlass->dirtyRect) {
1522 int old_height;
1524 /* "width" and "height" are used as coordinates here,
1525 * and run from [0...width-1] and [0...height-1] respectively.
1527 width--;
1528 height--;
1529 old_height = height;
1531 for (; width >= 0; width--)
1532 for (height = old_height; height >= 0; height--)
1533 XPutPixel(panel->magnifyGlass->image, xb + width, yb + height,
1534 XGetPixel(panel->magnifyGlass->dirtyRect, width, height));
1535 XDestroyImage(panel->magnifyGlass->dirtyRect);
1536 panel->magnifyGlass->dirtyRect = NULL;
1539 return;
1542 static Pixmap magnifyCreatePixmap(WMColorPanel * panel)
1544 W_Screen *scr = WMWidgetScreen(panel->win);
1545 int u, v;
1546 #ifndef USE_XSHAPE
1547 Pixmap pixmap;
1548 #endif
1549 unsigned long color;
1551 if (!panel->magnifyGlass->image)
1552 return None;
1554 if (!panel->magnifyGlass->magPix)
1555 return None;
1558 * Copy an area of only 5x5 pixels from the center of the image.
1560 for (u = 0; u < 5; u++) {
1561 for (v = 0; v < 5; v++) {
1562 color = XGetPixel(panel->magnifyGlass->image, u + 9, v + 9);
1564 XSetForeground(scr->display, scr->copyGC, color);
1566 if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
1567 panel->magnifyGlass->color = ulongToRColor(scr, color);
1569 /* The center square must eventually be centered around the
1570 * hotspot. The image needs shifting to achieve this. The amount of
1571 * shifting is (Cursor_mask_width/2 - 2 * square_size) = 11-10 = 1
1572 * _ _ _ _ _
1573 * |_|_|_|_|_|
1574 * ^------- center of center square == Cursor_x_hot
1576 XFillRectangle(scr->display, panel->magnifyGlass->magPix,
1577 scr->copyGC,
1578 u * 5 + (u == 0 ? 0 : -1), v * 5 + (v == 0 ? 0 : -1),
1579 (u == 0 ? 4 : 5), (v == 0 ? 4 : 5));
1583 #ifdef USE_XSHAPE
1584 return panel->magnifyGlass->magPix;
1585 #else
1586 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width, Cursor_mask_height, scr->depth);
1587 if (!pixmap)
1588 return None;
1590 XPutImage(scr->display, pixmap, scr->copyGC, panel->magnifyGlass->image,
1591 0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
1593 /* Copy the magnified pixmap, with the clip mask, to background pixmap */
1594 XCopyArea(scr->display, panel->magnifyGlass->magPix, pixmap,
1595 scr->clipGC, 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
1596 /* (2,2) puts center pixel on center of glass */
1598 return pixmap;
1599 #endif
1603 static WMView *magnifyCreateView(W_ColorPanel * panel)
1605 W_Screen *scr = WMWidgetScreen(panel->win);
1606 WMView *magView;
1608 magView = W_CreateTopView(scr);
1609 if (!magView)
1610 return NULL;
1612 magView->self = panel->win;
1613 magView->flags.topLevel = 1;
1614 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1615 magView->attribs.override_redirect = True;
1616 magView->attribs.save_under = True;
1618 W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
1620 W_RealizeView(magView);
1622 return magView;
1625 static Cursor magnifyGrabPointer(W_ColorPanel * panel)
1627 W_Screen *scr = WMWidgetScreen(panel->win);
1628 Pixmap magPixmap, magPixmap2;
1629 Cursor magCursor;
1630 XColor fgColor = { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 };
1631 XColor bgColor = { 0, 0xbf00, 0xa000, 0x5000, DoRed | DoGreen | DoBlue, 0 };
1633 /* Cursor creation stuff */
1634 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1635 (char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
1636 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1637 (char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
1639 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1640 &fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
1642 XFreePixmap(scr->display, magPixmap);
1643 XFreePixmap(scr->display, magPixmap2);
1645 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1647 /* Set up Pointer */
1648 XGrabPointer(scr->display, panel->magnifyGlass->view->window, True,
1649 PointerMotionMask | ButtonPressMask,
1650 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1652 return magCursor;
1655 static WMPoint magnifyInitialize(W_ColorPanel * panel)
1657 W_Screen *scr = WMWidgetScreen(panel->win);
1658 int x, y, u, v;
1659 unsigned int mask;
1660 Pixmap pixmap, clip_mask;
1661 WMPoint point;
1662 Window root_return, child_return;
1664 clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1665 (char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1666 1, 0, 1);
1667 panel->magnifyGlass->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
1668 5 * 5 - 1, 5 * 5 - 1, scr->depth);
1670 XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return, &x, &y, &u, &v, &mask);
1672 panel->magnifyGlass->image = NULL;
1674 /* Clipmask to make magnified view-contents circular */
1675 #ifdef USE_XSHAPE
1676 XShapeCombineMask(scr->display, WMViewXID(panel->magnifyGlass->view),
1677 ShapeBounding, 0, 0, clip_mask, ShapeSet);
1678 #else
1679 /* Clip circle in glass cursor */
1680 XSetClipMask(scr->display, scr->clipGC, clip_mask);
1681 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1682 #endif
1684 XFreePixmap(scr->display, clip_mask);
1686 /* Draw initial magnifying glass contents */
1687 magnifyGetImageStored(panel, x, y, x, y);
1689 pixmap = magnifyCreatePixmap(panel);
1690 XSetWindowBackgroundPixmap(scr->display, WMViewXID(panel->magnifyGlass->view), pixmap);
1691 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1692 XFlush(scr->display);
1694 #ifndef USE_XSHAPE
1695 XFreePixmap(scr->display, pixmap);
1696 #endif
1698 point.x = x;
1699 point.y = y;
1701 return point;
1704 static void magnifyPutCursor(WMWidget * w, void *data)
1706 W_ColorPanel *panel = (W_ColorPanel *) (data);
1707 W_Screen *scr = WMWidgetScreen(panel->win);
1708 Cursor magCursor;
1709 Pixmap pixmap;
1710 XEvent event;
1711 WMPoint initialPosition;
1713 /* Parameter not used, but tell the compiler that it is ok */
1714 (void) w;
1716 /* Destroy wheelBackImg, so it'll update properly */
1717 if (panel->selectionBackImg) {
1718 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1719 panel->selectionBackImg = None;
1722 /* Create magnifying glass */
1723 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1724 panel->magnifyGlass->view = magnifyCreateView(panel);
1725 if (!panel->magnifyGlass->view)
1726 return;
1728 initialPosition = magnifyInitialize(panel);
1729 panel->magnifyGlass->x = initialPosition.x;
1730 panel->magnifyGlass->y = initialPosition.y;
1732 W_MoveView(panel->magnifyGlass->view,
1733 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1734 W_MapView(panel->magnifyGlass->view);
1736 magCursor = magnifyGrabPointer(panel);
1738 while (panel->magnifyGlass->image) {
1739 WMNextEvent(scr->display, &event);
1741 /* Pack motion events */
1742 while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
1745 switch (event.type) {
1746 case ButtonPress:
1747 XDestroyImage(panel->magnifyGlass->image);
1748 panel->magnifyGlass->image = NULL;
1750 if (event.xbutton.button == Button1) {
1751 panel->color.rgb = panel->magnifyGlass->color;
1752 panel->color.set = cpRGB;
1753 updateSwatch(panel, panel->color);
1755 switch (panel->mode) {
1756 case WMWheelModeColorPanel:
1757 wheelInit(panel);
1758 wheelRender(panel);
1759 wheelPaint(panel);
1760 break;
1761 case WMGrayModeColorPanel:
1762 grayInit(panel);
1763 break;
1764 case WMRGBModeColorPanel:
1765 rgbInit(panel);
1766 break;
1767 case WMCMYKModeColorPanel:
1768 cmykInit(panel);
1769 break;
1770 case WMHSBModeColorPanel:
1771 hsbInit(panel);
1772 break;
1773 default:
1774 break;
1776 panel->lastChanged = panel->mode;
1778 WMSetButtonSelected(panel->magnifyBtn, False);
1779 break;
1781 case MotionNotify:
1782 while (XPending(event.xmotion.display)) {
1783 XEvent ev;
1784 XPeekEvent(event.xmotion.display, &ev);
1785 if (ev.type == MotionNotify)
1786 XNextEvent(event.xmotion.display, &event);
1787 else
1788 break;
1791 /* Get a "dirty rectangle" */
1792 magnifyGetImageStored(panel,
1793 panel->magnifyGlass->x, panel->magnifyGlass->y,
1794 event.xmotion.x_root, event.xmotion.y_root);
1796 /* Update coordinates */
1797 panel->magnifyGlass->x = event.xmotion.x_root;
1798 panel->magnifyGlass->y = event.xmotion.y_root;
1800 /* Move view */
1801 W_MoveView(panel->magnifyGlass->view,
1802 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1804 /* Put new image (with magn.) in view */
1805 pixmap = magnifyCreatePixmap(panel);
1806 if (pixmap != None) {
1807 /* Change the window background */
1808 XSetWindowBackgroundPixmap(scr->display,
1809 WMViewXID(panel->magnifyGlass->view), pixmap);
1810 /* Force an Expose (handled by X) */
1811 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1812 /* Synchronize the event queue, so the Expose is handled NOW */
1813 XFlush(scr->display);
1814 #ifndef USE_XSHAPE
1815 XFreePixmap(scr->display, pixmap);
1816 #endif
1818 break;
1820 /* Try XQueryPointer for this !!! It returns windows that the pointer
1821 * is over. Note: We found this solving the invisible donkey cap bug
1823 #if 0 /* As it is impossible to make this work in all cases,
1824 * we consider it confusing. Therefore we disabled it.
1826 case FocusOut: /* fall through */
1827 case FocusIn:
1829 * Color Panel window (panel->win) lost or received focus.
1830 * We need to update the pixmap in the magnifying glass.
1832 * BUG Doesn't work with focus switches between two windows
1833 * if none of them is the color panel.
1835 XUngrabPointer(scr->display, CurrentTime);
1836 W_UnmapView(panel->magnifyGlass->view);
1838 magnifyInitialize(panel);
1840 W_MapView(panel->magnifyGlass->view);
1841 XGrabPointer(scr->display, panel->magnifyGlass->view->window,
1842 True, PointerMotionMask | ButtonPressMask,
1843 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1844 break;
1845 #endif
1846 default:
1847 WMHandleEvent(&event);
1848 break;
1849 } /* of switch */
1852 XUngrabPointer(scr->display, CurrentTime);
1853 XFreeCursor(scr->display, magCursor);
1855 XFreePixmap(scr->display, panel->magnifyGlass->magPix);
1856 panel->magnifyGlass->magPix = None;
1858 W_UnmapView(panel->magnifyGlass->view);
1859 W_DestroyView(panel->magnifyGlass->view);
1860 panel->magnifyGlass->view = NULL;
1862 wfree(panel->magnifyGlass);
1865 /****************** ColorWheel Functions ************************/
1867 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height)
1869 wheelMatrix *matrix = NULL;
1870 int i;
1872 assert((width > 0) && (height > 0));
1874 matrix = wmalloc(sizeof(wheelMatrix));
1875 matrix->width = width;
1876 matrix->height = height;
1878 for (i = 0; i < 3; i++) {
1879 matrix->data[i] = wmalloc(width * height * sizeof(unsigned char));
1882 return matrix;
1885 static void wheelDestroyMatrix(wheelMatrix * matrix)
1887 int i;
1889 if (!matrix)
1890 return;
1892 for (i = 0; i < 3; i++) {
1893 if (matrix->data[i])
1894 wfree(matrix->data[i]);
1896 wfree(matrix);
1899 static void wheelInitMatrix(W_ColorPanel * panel)
1901 int i;
1902 int x, y;
1903 unsigned char *rp, *gp, *bp;
1904 CPColor cpColor;
1905 long ofs[4];
1906 int xcor, ycor;
1907 unsigned short sat;
1908 int dhue[4];
1909 const int cw_halfsize = (colorWheelSize + 4) / 2,
1910 cw_sqsize = (colorWheelSize + 4) * (colorWheelSize + 4), uchar_shift = getShift(sizeof(unsigned char));
1912 if (!panel->wheelMtrx)
1913 return;
1915 cpColor.hsv.value = 255;
1916 cpColor.set = cpHSV;
1918 ofs[0] = -1;
1919 ofs[1] = -(colorWheelSize + 4);
1921 /* offsets are counterclockwise (in triangles).
1923 * ofs[0] ---->
1924 * _______________________________________
1925 * [1] |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| o
1926 * s |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| f
1927 * f |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| s
1928 * o | | | | | | | | | | | | | | | | | | | | | [3]
1930 * <---- ofs[2]
1931 * ____
1932 * |\ /| <-- triangles
1933 * | \/ |
1934 * | /\ |
1935 * |/__\|
1938 for (y = 0; y < cw_halfsize; y++) {
1939 for (x = y; x < (colorWheelSize + 4 - y); x++) {
1940 /* (xcor, ycor) is (x,y) relative to center of matrix */
1941 xcor = 2 * x - 4 - colorWheelSize;
1942 ycor = 2 * y - 4 - colorWheelSize;
1944 /* RColor.saturation is unsigned char and will wrap after 255 */
1945 sat = rint(255.0 * sqrt(xcor * xcor + ycor * ycor) / colorWheelSize);
1947 cpColor.hsv.saturation = (unsigned char)sat;
1949 ofs[0]++; /* top quarter of matrix */
1950 ofs[1] += colorWheelSize + 4; /* left quarter */
1951 ofs[2] = cw_sqsize - 1 - ofs[0]; /* bottom quarter */
1952 ofs[3] = cw_sqsize - 1 - ofs[1]; /* right quarter */
1954 if (sat < 256) {
1955 if (xcor != 0)
1956 dhue[0] = rint(atan((double)ycor / (double)xcor) *
1957 (180.0 / M_PI)) + (xcor < 0 ? 180.0 : 0.0);
1958 else
1959 dhue[0] = 270;
1961 dhue[0] = 360 - dhue[0]; /* Reverse direction of ColorWheel */
1962 dhue[1] = 270 - dhue[0] + (dhue[0] > 270 ? 360 : 0);
1963 dhue[2] = dhue[0] - 180 + (dhue[0] < 180 ? 360 : 0);
1964 dhue[3] = 90 - dhue[0] + (dhue[0] > 90 ? 360 : 0);
1966 for (i = 0; i < 4; i++) {
1967 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1968 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1969 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1971 cpColor.hsv.hue = dhue[i];
1972 convertCPColor(&cpColor);
1974 *rp = (unsigned char)(cpColor.rgb.red);
1975 *gp = (unsigned char)(cpColor.rgb.green);
1976 *bp = (unsigned char)(cpColor.rgb.blue);
1978 } else {
1979 for (i = 0; i < 4; i++) {
1980 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1981 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1982 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1984 *rp = (unsigned char)0;
1985 *gp = (unsigned char)0;
1986 *bp = (unsigned char)0;
1991 ofs[0] += 2 * y + 1;
1992 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2 * y);
1996 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue)
1998 unsigned int i;
1999 unsigned int v;
2001 for (i = 0; i < 256; i++) {
2002 /* We divide by 128 in advance, and check whether that number divides
2003 * by 2 properly. If not, we add one to round the number correctly
2005 v = (i * maxvalue) >> 7;
2006 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + (v & 0x01));
2010 static void wheelRender(W_ColorPanel * panel)
2012 W_Screen *scr = WMWidgetScreen(panel->win);
2013 int x, y;
2014 RImage *image;
2015 unsigned char *ptr;
2016 RColor gray;
2017 unsigned long ofs = 0;
2018 /*unsigned char shift = getShift(sizeof(unsigned char)); */
2020 image = RCreateImage(colorWheelSize + 4, colorWheelSize + 4, True);
2021 if (!image) {
2022 wwarning(_("Color Panel: Could not allocate memory"));
2023 return;
2026 ptr = image->data;
2028 /* TODO Make this transparent istead of gray */
2029 gray.red = gray.blue = 0xae;
2030 gray.green = 0xaa;
2032 for (y = 0; y < colorWheelSize + 4; y++) {
2033 for (x = 0; x < colorWheelSize + 4; x++) {
2034 if (wheelInsideColorWheel(panel, ofs)) {
2035 *(ptr++) =
2036 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]]);
2037 *(ptr++) =
2038 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]]);
2039 *(ptr++) =
2040 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]]);
2041 *(ptr++) = 0;
2042 } else {
2043 *(ptr++) = (unsigned char)(gray.red);
2044 *(ptr++) = (unsigned char)(gray.green);
2045 *(ptr++) = (unsigned char)(gray.blue);
2046 *(ptr++) = 255;
2048 ofs++;
2052 if (panel->wheelImg)
2053 XFreePixmap(scr->display, panel->wheelImg);
2055 RConvertImage(scr->rcontext, image, &panel->wheelImg);
2056 RReleaseImage(image);
2058 /* Check if backimage exists. If it doesn't, allocate and fill it */
2059 if (!panel->selectionBackImg) {
2060 panel->selectionBackImg = XCreatePixmap(scr->display,
2061 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
2062 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2063 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2064 /* -2 is hot spot correction */
2068 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs)
2070 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
2071 (panel->wheelMtrx->data[1][ofs] != 0) && (panel->wheelMtrx->data[2][ofs] != 0));
2074 static void wheelPaint(W_ColorPanel * panel)
2076 W_Screen *scr = WMWidgetScreen(panel->win);
2078 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
2079 scr->copyGC, 0, 0, colorWheelSize + 4, colorWheelSize + 4, 0, 0);
2081 /* Draw selection image */
2082 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2083 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2086 static void wheelHandleEvents(XEvent * event, void *data)
2088 W_ColorPanel *panel = (W_ColorPanel *) data;
2090 switch (event->type) {
2091 case Expose:
2092 if (event->xexpose.count != 0) /* TODO Improve */
2093 break;
2094 wheelPaint(panel);
2095 break;
2099 static void wheelHandleActionEvents(XEvent * event, void *data)
2101 W_ColorPanel *panel = (W_ColorPanel *) data;
2103 switch (event->type) {
2104 case ButtonPress:
2105 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) == COLORWHEEL_PART) {
2107 panel->lastChanged = WMWheelModeColorPanel;
2108 panel->flags.dragging = 1;
2110 wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
2112 break;
2114 case ButtonRelease:
2115 panel->flags.dragging = 0;
2116 if (!panel->flags.continuous) {
2117 if (panel->action)
2118 (*panel->action) (panel, panel->clientData);
2120 break;
2122 case MotionNotify:
2123 if (panel->flags.dragging) {
2124 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) == COLORWHEEL_PART) {
2125 wheelPositionSelection(panel, event->xmotion.x, event->xmotion.y);
2126 } else
2127 wheelPositionSelectionOutBounds(panel, event->xmotion.x, event->xmotion.y);
2129 break;
2133 static int getPickerPart(W_ColorPanel * panel, int x, int y)
2135 int lx, ly;
2136 unsigned long ofs;
2138 lx = x;
2139 ly = y;
2141 if (panel->mode == WMWheelModeColorPanel) {
2142 if ((lx >= 2) && (lx <= 2 + colorWheelSize) && (ly >= 2) && (ly <= 2 + colorWheelSize)) {
2144 ofs = ly * panel->wheelMtrx->width + lx;
2146 if (wheelInsideColorWheel(panel, ofs))
2147 return COLORWHEEL_PART;
2151 if (panel->mode == WMCustomPaletteModeColorPanel) {
2152 if ((lx >= 2) && (lx < customPaletteWidth - 2) && (ly >= 2) && (ly < customPaletteHeight - 2)) {
2153 return CUSTOMPALETTE_PART;
2157 return 0;
2160 static void wheelBrightnessSliderCallback(WMWidget * w, void *data)
2162 int value;
2164 W_ColorPanel *panel = (W_ColorPanel *) data;
2166 /* Parameter not used, but tell the compiler that it is ok */
2167 (void) w;
2169 value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2171 wheelCalculateValues(panel, value);
2173 if (panel->color.set == cpRGB) {
2174 convertCPColor(&panel->color);
2175 panel->color.set = cpHSV;
2178 panel->color.hsv.value = value;
2180 wheelRender(panel);
2181 wheelPaint(panel);
2182 wheelUpdateSelection(panel);
2185 static void wheelUpdateSelection(W_ColorPanel * panel)
2187 W_Screen *scr = WMWidgetScreen(panel->win);
2189 updateSwatch(panel, panel->color);
2190 panel->lastChanged = WMWheelModeColorPanel;
2192 /* Redraw color selector (and make a backup of the part it will cover) */
2193 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2194 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2195 /* "-2" is correction for hotspot location */
2196 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2197 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2198 /* see above */
2201 static void wheelUndrawSelection(W_ColorPanel * panel)
2203 W_Screen *scr = WMWidgetScreen(panel->win);
2205 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
2206 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2207 /* see above */
2210 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y)
2212 unsigned long ofs = (y * panel->wheelMtrx->width) + x;
2214 panel->color.rgb.red = panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]];
2216 panel->color.rgb.green = panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]];
2218 panel->color.rgb.blue = panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]];
2219 panel->color.set = cpRGB;
2221 wheelUndrawSelection(panel);
2223 panel->colx = x;
2224 panel->coly = y;
2226 wheelUpdateSelection(panel);
2227 wheelUpdateBrightnessGradientFromLocation(panel);
2230 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2232 int hue;
2233 int xcor, ycor;
2234 CPColor cpColor;
2236 xcor = x * 2 - colorWheelSize - 4;
2237 ycor = y * 2 - colorWheelSize - 4;
2239 panel->color.hsv.saturation = 255;
2240 panel->color.hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2242 if (xcor != 0)
2243 hue = rint(atan(-(double)ycor / (double)xcor) * (180.0 / M_PI));
2244 else {
2245 if (ycor < 0)
2246 hue = 90;
2247 else
2248 hue = 270;
2251 if (xcor < 0)
2252 hue += 180;
2254 if ((xcor > 0) && (ycor > 0))
2255 hue += 360;
2257 panel->color.hsv.hue = hue;
2258 panel->color.set = cpHSV;
2259 convertCPColor(&panel->color);
2261 wheelUndrawSelection(panel);
2263 panel->colx = 2 + rint((colorWheelSize * (1.0 + cos(panel->color.hsv.hue * (M_PI / 180.0)))) / 2.0);
2264 /* "+2" because of "colorWheelSize + 4" */
2265 panel->coly = 2 + rint((colorWheelSize * (1.0 + sin(-panel->color.hsv.hue * (M_PI / 180.0)))) / 2.0);
2267 wheelUpdateSelection(panel);
2268 cpColor = panel->color;
2269 wheelUpdateBrightnessGradient(panel, cpColor);
2272 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel)
2274 CPColor from;
2275 unsigned long ofs;
2277 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2279 from.rgb.red = panel->wheelMtrx->data[0][ofs];
2280 from.rgb.green = panel->wheelMtrx->data[1][ofs];
2281 from.rgb.blue = panel->wheelMtrx->data[2][ofs];
2282 from.set = cpRGB;
2284 wheelUpdateBrightnessGradient(panel, from);
2287 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor)
2289 RColor to;
2290 RImage *sliderImg;
2291 WMPixmap *sliderPxmp;
2293 to.red = to.green = to.blue = 0;
2295 if (topColor.set == cpHSV)
2296 convertCPColor(&topColor);
2298 sliderImg = RRenderGradient(16, 153, &(topColor.rgb), &to, RGRD_VERTICAL);
2299 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win), sliderImg, 0);
2300 RReleaseImage(sliderImg);
2301 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
2302 WMReleasePixmap(sliderPxmp);
2305 /****************** Grayscale Panel Functions ***************/
2307 static void grayBrightnessSliderCallback(WMWidget * w, void *data)
2309 CPColor cpColor;
2310 int value;
2311 char tmp[4];
2312 W_ColorPanel *panel = (W_ColorPanel *) data;
2314 /* Parameter not used, but tell the compiler that it is ok */
2315 (void) w;
2317 value = WMGetSliderValue(panel->grayBrightnessS);
2319 sprintf(tmp, "%d", value);
2321 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2322 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint(2.55 * value);
2323 cpColor.set = cpRGB;
2325 updateSwatch(panel, cpColor);
2326 panel->lastChanged = WMGrayModeColorPanel;
2329 static void grayPresetButtonCallback(WMWidget * w, void *data)
2331 CPColor cpColor;
2332 char tmp[4];
2333 int value;
2334 int i = 0;
2335 W_ColorPanel *panel = (W_ColorPanel *) data;
2337 while (i < 7) {
2338 if (w == panel->grayPresetBtn[i])
2339 break;
2340 i++;
2343 value = rint((100.0 * i) / 6.0);
2344 sprintf(tmp, "%d", value);
2346 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2347 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * i) / 6.0);
2348 cpColor.set = cpRGB;
2350 WMSetSliderValue(panel->grayBrightnessS, rint((100.0 * i) / 6.0));
2352 updateSwatch(panel, cpColor);
2353 panel->lastChanged = WMGrayModeColorPanel;
2356 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification)
2358 CPColor cpColor;
2359 char tmp[4];
2360 int value;
2361 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2363 /* Parameter not used, but tell the compiler that it is ok */
2364 (void) notification;
2366 value = get_textfield_as_integer(panel->grayBrightnessT);
2367 if (value > 100)
2368 value = 100;
2369 if (value < 0)
2370 value = 0;
2372 sprintf(tmp, "%d", value);
2373 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2374 WMSetSliderValue(panel->grayBrightnessS, value);
2376 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * value) / 100.0);
2377 cpColor.set = cpRGB;
2379 updateSwatch(panel, cpColor);
2380 panel->lastChanged = WMGrayModeColorPanel;
2383 /******************* RGB Panel Functions *****************/
2385 void rgbIntToChar(W_ColorPanel *panel, int *value)
2387 char tmp[4];
2388 const char *format;
2390 switch (panel->rgbState) {
2391 case RGBdec:
2392 format = "%d";
2393 break;
2394 case RGBhex:
2395 format = "%0X";
2396 break;
2399 sprintf(tmp, format, value[0]);
2400 WMSetTextFieldText(panel->rgbRedT, tmp);
2401 sprintf(tmp, format, value[1]);
2402 WMSetTextFieldText(panel->rgbGreenT, tmp);
2403 sprintf(tmp, format, value[2]);
2404 WMSetTextFieldText(panel->rgbBlueT, tmp);
2407 int *rgbCharToInt(W_ColorPanel *panel)
2409 int base = 0;
2410 static int value[3];
2411 char *str;
2413 switch (panel->rgbState) {
2414 case RGBdec:
2415 base = 10;
2416 break;
2417 case RGBhex:
2418 base = 16;
2419 break;
2422 str = WMGetTextFieldText(panel->rgbRedT);
2423 value[0] = strtol(str, NULL, base);
2424 wfree(str);
2426 str = WMGetTextFieldText(panel->rgbGreenT);
2427 value[1] = strtol(str, NULL, base);
2428 wfree(str);
2430 str = WMGetTextFieldText(panel->rgbBlueT);
2431 value[2] = strtol(str, NULL, base);
2432 wfree(str);
2434 return value;
2437 static void rgbSliderCallback(WMWidget * w, void *data)
2439 CPColor cpColor;
2440 int value[3];
2441 W_ColorPanel *panel = (W_ColorPanel *) data;
2443 /* Parameter not used, but tell the compiler that it is ok */
2444 (void) w;
2446 value[0] = WMGetSliderValue(panel->rgbRedS);
2447 value[1] = WMGetSliderValue(panel->rgbGreenS);
2448 value[2] = WMGetSliderValue(panel->rgbBlueS);
2450 rgbIntToChar(panel, value);
2452 cpColor.rgb.red = value[0];
2453 cpColor.rgb.green = value[1];
2454 cpColor.rgb.blue = value[2];
2455 cpColor.set = cpRGB;
2457 updateSwatch(panel, cpColor);
2458 panel->lastChanged = WMRGBModeColorPanel;
2461 static void rgbTextFieldCallback(void *observerData, WMNotification * notification)
2463 CPColor cpColor;
2464 int *value;
2465 int n;
2466 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2468 /* Parameter not used, but tell the compiler that it is ok */
2469 (void) notification;
2471 value = rgbCharToInt(panel);
2473 for (n = 0; n < 3; n++) {
2474 if (value[n] > 255)
2475 value[n] = 255;
2476 if (value[n] < 0)
2477 value[n] = 0;
2480 rgbIntToChar(panel, value);
2482 WMSetSliderValue(panel->rgbRedS, value[0]);
2483 WMSetSliderValue(panel->rgbGreenS, value[1]);
2484 WMSetSliderValue(panel->rgbBlueS, value[2]);
2486 cpColor.rgb.red = value[0];
2487 cpColor.rgb.green = value[1];
2488 cpColor.rgb.blue = value[2];
2489 cpColor.set = cpRGB;
2491 updateSwatch(panel, cpColor);
2492 panel->lastChanged = WMRGBModeColorPanel;
2495 static void rgbDecToHex(WMWidget *w, void *data)
2497 W_ColorPanel *panel = (W_ColorPanel *) data;
2498 int *value;
2500 (void) w;
2502 switch (panel->rgbState) {
2503 case RGBhex:
2504 if (WMGetButtonSelected(panel->rgbDecB)) {
2505 WMSetLabelText(panel->rgbMaxL, "255");
2506 WMRedisplayWidget(panel->rgbMaxL);
2507 value = rgbCharToInt(panel);
2508 panel->rgbState = RGBdec;
2509 rgbIntToChar(panel, value);
2511 break;
2513 case RGBdec:
2514 if (WMGetButtonSelected(panel->rgbHexB)) {
2515 WMSetLabelText(panel->rgbMaxL, "FF");
2516 WMRedisplayWidget(panel->rgbMaxL);
2517 value = rgbCharToInt(panel);
2518 panel->rgbState = RGBhex;
2519 rgbIntToChar(panel, value);
2521 break;
2525 /******************* CMYK Panel Functions *****************/
2527 static void cmykSliderCallback(WMWidget * w, void *data)
2529 CPColor cpColor;
2530 int value[4];
2531 char tmp[4];
2532 W_ColorPanel *panel = (W_ColorPanel *) data;
2533 double scale;
2535 /* Parameter not used, but tell the compiler that it is ok */
2536 (void) w;
2538 value[0] = WMGetSliderValue(panel->cmykCyanS);
2539 value[1] = WMGetSliderValue(panel->cmykMagentaS);
2540 value[2] = WMGetSliderValue(panel->cmykYellowS);
2541 value[3] = WMGetSliderValue(panel->cmykBlackS);
2543 sprintf(tmp, "%d", value[0]);
2544 WMSetTextFieldText(panel->cmykCyanT, tmp);
2545 sprintf(tmp, "%d", value[1]);
2546 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2547 sprintf(tmp, "%d", value[2]);
2548 WMSetTextFieldText(panel->cmykYellowT, tmp);
2549 sprintf(tmp, "%d", value[3]);
2550 WMSetTextFieldText(panel->cmykBlackT, tmp);
2552 scale = 2.55 * (1.0 - (value[3] / 100.0));
2553 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2554 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2555 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2556 cpColor.set = cpRGB;
2558 updateSwatch(panel, cpColor);
2559 panel->lastChanged = WMCMYKModeColorPanel;
2562 static void cmykTextFieldCallback(void *observerData, WMNotification * notification)
2564 CPColor cpColor;
2565 int value[4];
2566 char tmp[4];
2567 int n;
2568 double scale;
2569 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2571 /* Parameter not used, but tell the compiler that it is ok */
2572 (void) notification;
2574 value[0] = get_textfield_as_integer(panel->cmykCyanT);
2575 value[1] = get_textfield_as_integer(panel->cmykMagentaT);
2576 value[2] = get_textfield_as_integer(panel->cmykYellowT);
2577 value[3] = get_textfield_as_integer(panel->cmykBlackT);
2579 for (n = 0; n < 4; n++) {
2580 if (value[n] > 100)
2581 value[n] = 100;
2582 if (value[n] < 0)
2583 value[n] = 0;
2586 sprintf(tmp, "%d", value[0]);
2587 WMSetTextFieldText(panel->cmykCyanT, tmp);
2589 sprintf(tmp, "%d", value[1]);
2590 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2592 sprintf(tmp, "%d", value[2]);
2593 WMSetTextFieldText(panel->cmykYellowT, tmp);
2595 sprintf(tmp, "%d", value[3]);
2596 WMSetTextFieldText(panel->cmykBlackT, tmp);
2598 WMSetSliderValue(panel->cmykCyanS, value[0]);
2599 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2600 WMSetSliderValue(panel->cmykYellowS, value[2]);
2601 WMSetSliderValue(panel->cmykBlackS, value[3]);
2603 scale = 2.55 * (1.0 - (value[3] / 100.0));
2604 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2605 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2606 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2607 cpColor.set = cpRGB;
2609 updateSwatch(panel, cpColor);
2610 panel->lastChanged = WMCMYKModeColorPanel;
2613 /********************** HSB Panel Functions ***********************/
2615 static void hsbSliderCallback(WMWidget * w, void *data)
2617 CPColor cpColor;
2618 int value[3];
2619 char tmp[4];
2620 W_ColorPanel *panel = (W_ColorPanel *) data;
2622 value[0] = WMGetSliderValue(panel->hsbHueS);
2623 value[1] = WMGetSliderValue(panel->hsbSaturationS);
2624 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
2626 sprintf(tmp, "%d", value[0]);
2627 WMSetTextFieldText(panel->hsbHueT, tmp);
2628 sprintf(tmp, "%d", value[1]);
2629 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2630 sprintf(tmp, "%d", value[2]);
2631 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2633 cpColor.hsv.hue = value[0];
2634 cpColor.hsv.saturation = value[1] * 2.55;
2635 cpColor.hsv.value = value[2] * 2.55;
2636 cpColor.set = cpHSV;
2638 convertCPColor(&cpColor);
2640 panel->lastChanged = WMHSBModeColorPanel;
2641 updateSwatch(panel, cpColor);
2643 if (w != panel->hsbBrightnessS)
2644 hsbUpdateBrightnessGradient(panel);
2645 if (w != panel->hsbSaturationS)
2646 hsbUpdateSaturationGradient(panel);
2647 if (w != panel->hsbHueS)
2648 hsbUpdateHueGradient(panel);
2651 static void hsbTextFieldCallback(void *observerData, WMNotification * notification)
2653 CPColor cpColor;
2654 int value[3];
2655 char tmp[4];
2656 int n;
2657 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2659 /* Parameter not used, but tell the compiler that it is ok */
2660 (void) notification;
2662 value[0] = get_textfield_as_integer(panel->hsbHueT);
2663 value[1] = get_textfield_as_integer(panel->hsbSaturationT);
2664 value[2] = get_textfield_as_integer(panel->hsbBrightnessT);
2666 if (value[0] > 359)
2667 value[0] = 359;
2668 if (value[0] < 0)
2669 value[0] = 0;
2671 for (n = 1; n < 3; n++) {
2672 if (value[n] > 100)
2673 value[n] = 100;
2674 if (value[n] < 0)
2675 value[n] = 0;
2678 sprintf(tmp, "%d", value[0]);
2679 WMSetTextFieldText(panel->hsbHueT, tmp);
2680 sprintf(tmp, "%d", value[1]);
2681 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2682 sprintf(tmp, "%d", value[2]);
2683 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2685 WMSetSliderValue(panel->hsbHueS, value[0]);
2686 WMSetSliderValue(panel->hsbSaturationS, value[1]);
2687 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
2689 cpColor.hsv.hue = value[0];
2690 cpColor.hsv.saturation = value[1] * 2.55;
2691 cpColor.hsv.value = value[2] * 2.55;
2692 cpColor.set = cpHSV;
2694 convertCPColor(&cpColor);
2696 panel->lastChanged = WMHSBModeColorPanel;
2697 updateSwatch(panel, cpColor);
2699 hsbUpdateBrightnessGradient(panel);
2700 hsbUpdateSaturationGradient(panel);
2701 hsbUpdateHueGradient(panel);
2704 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel)
2706 W_Screen *scr = WMWidgetScreen(panel->win);
2707 RColor from;
2708 CPColor to;
2709 RImage *sliderImg;
2710 WMPixmap *sliderPxmp;
2712 from.red = from.green = from.blue = 0;
2713 to.hsv = panel->color.hsv;
2714 to.hsv.value = 255;
2715 to.set = cpHSV;
2717 convertCPColor(&to);
2719 sliderImg = RRenderGradient(141, 16, &from, &(to.rgb), RGRD_HORIZONTAL);
2720 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2721 RReleaseImage(sliderImg);
2723 if (sliderPxmp)
2724 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
2725 panel->font12, 2, 0, 100, WALeft, scr->white,
2726 False, _("Brightness"), strlen(_("Brightness")));
2727 else
2728 wwarning(_("Color Panel: Could not allocate memory"));
2730 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
2731 WMReleasePixmap(sliderPxmp);
2734 static void hsbUpdateSaturationGradient(W_ColorPanel * panel)
2736 W_Screen *scr = WMWidgetScreen(panel->win);
2737 CPColor from;
2738 CPColor to;
2739 RImage *sliderImg;
2740 WMPixmap *sliderPxmp;
2742 from.hsv = panel->color.hsv;
2743 from.hsv.saturation = 0;
2744 from.set = cpHSV;
2745 convertCPColor(&from);
2747 to.hsv = panel->color.hsv;
2748 to.hsv.saturation = 255;
2749 to.set = cpHSV;
2750 convertCPColor(&to);
2752 sliderImg = RRenderGradient(141, 16, &(from.rgb), &(to.rgb), RGRD_HORIZONTAL);
2753 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2754 RReleaseImage(sliderImg);
2756 if (sliderPxmp)
2757 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2758 panel->font12, 2, 0, 100, WALeft,
2759 from.hsv.value < 128 ? scr->white : scr->black, False,
2760 _("Saturation"), strlen(_("Saturation")));
2761 else
2762 wwarning(_("Color Panel: Could not allocate memory"));
2764 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
2765 WMReleasePixmap(sliderPxmp);
2768 static void hsbUpdateHueGradient(W_ColorPanel * panel)
2770 W_Screen *scr = WMWidgetScreen(panel->win);
2771 RColor **colors = NULL;
2772 RHSVColor hsvcolor;
2773 RImage *sliderImg;
2774 WMPixmap *sliderPxmp;
2775 int i;
2777 hsvcolor = panel->color.hsv;
2779 colors = wmalloc(sizeof(RColor *) * (8));
2780 for (i = 0; i < 7; i++) {
2781 hsvcolor.hue = (360 * i) / 6;
2782 colors[i] = wmalloc(sizeof(RColor));
2783 RHSVtoRGB(&hsvcolor, colors[i]);
2785 colors[7] = NULL;
2787 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2788 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2789 RReleaseImage(sliderImg);
2791 if (sliderPxmp)
2792 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2793 panel->font12, 2, 0, 100, WALeft,
2794 hsvcolor.value < 128 ? scr->white : scr->black, False, _("Hue"), strlen(_("Hue")));
2795 else
2796 wwarning(_("Color Panel: Could not allocate memory"));
2798 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2799 WMReleasePixmap(sliderPxmp);
2801 for (i = 0; i < 7; i++)
2802 wfree(colors[i]);
2804 wfree(colors);
2807 /*************** Custom Palette Functions ****************/
2809 static void customRenderSpectrum(W_ColorPanel * panel)
2811 RImage *spectrum;
2812 int x, y;
2813 unsigned char *ptr;
2814 CPColor cpColor;
2816 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, False);
2818 ptr = spectrum->data;
2820 for (y = 0; y < SPECTRUM_HEIGHT; y++) {
2821 cpColor.hsv.hue = y;
2822 cpColor.hsv.saturation = 0;
2823 cpColor.hsv.value = 255;
2824 cpColor.set = cpHSV;
2826 for (x = 0; x < SPECTRUM_WIDTH; x++) {
2827 convertCPColor(&cpColor);
2829 *(ptr++) = (unsigned char)cpColor.rgb.red;
2830 *(ptr++) = (unsigned char)cpColor.rgb.green;
2831 *(ptr++) = (unsigned char)cpColor.rgb.blue;
2833 if (x < (SPECTRUM_WIDTH / 2))
2834 cpColor.hsv.saturation++;
2836 if (x > (SPECTRUM_WIDTH / 2))
2837 cpColor.hsv.value--;
2840 if (panel->customPaletteImg) {
2841 RReleaseImage(panel->customPaletteImg);
2842 panel->customPaletteImg = NULL;
2844 panel->customPaletteImg = spectrum;
2847 static void customSetPalette(W_ColorPanel * panel)
2849 W_Screen *scr = WMWidgetScreen(panel->win);
2850 RImage *scaledImg;
2851 Pixmap image;
2853 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth, customPaletteHeight, scr->depth);
2854 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth, customPaletteHeight);
2855 RConvertImage(scr->rcontext, scaledImg, &image);
2856 RReleaseImage(scaledImg);
2858 XCopyArea(scr->display, image, panel->customPaletteContentView->window,
2859 scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2861 /* Check backimage exists. If it doesn't, allocate and fill it */
2862 if (!panel->selectionBackImg) {
2863 panel->selectionBackImg = XCreatePixmap(scr->display,
2864 panel->customPaletteContentView->window, 4, 4, scr->depth);
2867 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
2868 panel->palx - 2, panel->paly - 2, 4, 4, 0, 0);
2869 XCopyArea(scr->display, panel->selectionImg,
2870 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2871 panel->palx - 2, panel->paly - 2);
2872 XFreePixmap(scr->display, image);
2874 panel->palXRatio = (double)(panel->customPaletteImg->width) / (double)(customPaletteWidth);
2875 panel->palYRatio = (double)(panel->customPaletteImg->height) / (double)(customPaletteHeight);
2877 WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
2880 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y)
2882 W_Screen *scr = WMWidgetScreen(panel->win);
2883 unsigned long ofs;
2885 /* undraw selection */
2886 XCopyArea(scr->display, panel->selectionBackImg,
2887 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2888 panel->palx - 2, panel->paly - 2);
2890 panel->palx = x;
2891 panel->paly = y;
2893 ofs = (rint(x * panel->palXRatio) + rint(y * panel->palYRatio) * panel->customPaletteImg->width) * 3;
2895 panel->color.rgb.red = panel->customPaletteImg->data[ofs];
2896 panel->color.rgb.green = panel->customPaletteImg->data[ofs + 1];
2897 panel->color.rgb.blue = panel->customPaletteImg->data[ofs + 2];
2898 panel->color.set = cpRGB;
2900 updateSwatch(panel, panel->color);
2901 panel->lastChanged = WMCustomPaletteModeColorPanel;
2903 /* Redraw color selector (and make a backup of the part it will cover) */
2904 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 */
2905 XCopyArea(scr->display, panel->selectionImg, panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4, panel->palx - 2, panel->paly - 2); /* see above */
2908 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2910 if (x < 2)
2911 x = 2;
2912 if (y < 2)
2913 y = 2;
2914 if (x >= customPaletteWidth)
2915 x = customPaletteWidth - 2;
2916 if (y >= customPaletteHeight)
2917 y = customPaletteHeight - 2;
2919 customPalettePositionSelection(panel, x, y);
2922 static void customPaletteHandleEvents(XEvent * event, void *data)
2924 W_ColorPanel *panel = (W_ColorPanel *) data;
2926 switch (event->type) {
2927 case Expose:
2928 if (event->xexpose.count != 0) /* TODO Improve. */
2929 break;
2930 customSetPalette(panel);
2931 break;
2935 static void customPaletteHandleActionEvents(XEvent * event, void *data)
2937 W_ColorPanel *panel = (W_ColorPanel *) data;
2938 int x, y;
2940 switch (event->type) {
2941 case ButtonPress:
2942 x = event->xbutton.x;
2943 y = event->xbutton.y;
2945 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2946 panel->flags.dragging = 1;
2947 customPalettePositionSelection(panel, x, y);
2949 break;
2951 case ButtonRelease:
2952 panel->flags.dragging = 0;
2953 if (!panel->flags.continuous) {
2954 if (panel->action)
2955 (*panel->action) (panel, panel->clientData);
2957 break;
2959 case MotionNotify:
2960 x = event->xmotion.x;
2961 y = event->xmotion.y;
2963 if (panel->flags.dragging) {
2964 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2965 customPalettePositionSelection(panel, x, y);
2966 } else
2967 customPalettePositionSelectionOutBounds(panel, x, y);
2969 break;
2973 static void customPaletteMenuCallback(WMWidget * w, void *data)
2975 W_ColorPanel *panel = (W_ColorPanel *) data;
2976 int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
2978 /* Parameter not used, but tell the compiler that it is ok */
2979 (void) w;
2981 switch (item) {
2982 case CPmenuNewFromFile:
2983 customPaletteMenuNewFromFile(panel);
2984 break;
2985 case CPmenuRename:
2986 customPaletteMenuRename(panel);
2987 break;
2988 case CPmenuRemove:
2989 customPaletteMenuRemove(panel);
2990 break;
2991 case CPmenuCopy:
2992 break;
2993 case CPmenuNewFromClipboard:
2994 break;
2998 static void customPaletteMenuNewFromFile(W_ColorPanel * panel)
3000 W_Screen *scr = WMWidgetScreen(panel->win);
3001 WMOpenPanel *browseP;
3002 char *filepath;
3003 char *filename = NULL;
3004 char *spath;
3005 char *tmp;
3006 int i;
3007 RImage *tmpImg = NULL;
3009 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir, "\0") == 0))
3010 spath = wexpandpath(wgethomedir());
3011 else
3012 spath = wexpandpath(panel->lastBrowseDir);
3014 browseP = WMGetOpenPanel(scr);
3015 WMSetFilePanelCanChooseDirectories(browseP, 0);
3016 WMSetFilePanelCanChooseFiles(browseP, 1);
3018 /* Get a filename */
3019 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
3020 _("Open Palette"), RSupportedFileFormats())) {
3021 filepath = WMGetFilePanelFileName(browseP);
3023 /* Get seperation position between path and filename */
3024 i = strrchr(filepath, '/') - filepath + 1;
3025 if (i > strlen(filepath))
3026 i = strlen(filepath);
3028 /* Store last browsed path */
3029 if (panel->lastBrowseDir)
3030 wfree(panel->lastBrowseDir);
3031 panel->lastBrowseDir = wmalloc((i + 1) * sizeof(char));
3032 strncpy(panel->lastBrowseDir, filepath, i);
3033 panel->lastBrowseDir[i] = '\0';
3035 /* Get filename from path */
3036 filename = wstrdup(filepath + i);
3038 /* Check for duplicate files, and rename it if there are any */
3039 tmp = wstrconcat(panel->configurationPath, filename);
3040 while (access(tmp, F_OK) == 0) {
3041 char *newName;
3043 wfree(tmp);
3045 newName = generateNewFilename(filename);
3046 wfree(filename);
3047 filename = newName;
3049 tmp = wstrconcat(panel->configurationPath, filename);
3051 wfree(tmp);
3053 /* Copy image to $(gnustepdir)/Library/Colors/ &
3054 * Add filename to history menu */
3055 if (wcopy_file(panel->configurationPath, filepath, filename) == 0) {
3057 /* filepath is a "local" path now the file has been copied */
3058 wfree(filepath);
3059 filepath = wstrconcat(panel->configurationPath, filename);
3061 /* load the image & add menu entries */
3062 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
3063 if (tmpImg) {
3064 if (panel->customPaletteImg)
3065 RReleaseImage(panel->customPaletteImg);
3066 panel->customPaletteImg = tmpImg;
3068 customSetPalette(panel);
3069 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
3071 panel->currentPalette =
3072 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1;
3074 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3075 panel->currentPalette);
3077 } else {
3078 tmp = wstrconcat(panel->configurationPath, filename);
3080 i = remove(tmp); /* Delete the file, it doesn't belong here */
3081 WMRunAlertPanel(scr, panel->win, _("File Error"),
3082 _("Invalid file format !"), _("OK"), NULL, NULL);
3083 if (i != 0) {
3084 werror(_("can't remove file %s"), tmp);
3085 WMRunAlertPanel(scr, panel->win, _("File Error"),
3086 _("Couldn't remove file from Configuration Directory !"),
3087 _("OK"), NULL, NULL);
3089 wfree(tmp);
3091 wfree(filepath);
3092 wfree(filename);
3094 WMFreeFilePanel(browseP);
3096 wfree(spath);
3099 static void customPaletteMenuRename(W_ColorPanel * panel)
3101 W_Screen *scr = WMWidgetScreen(panel->win);
3102 char *toName = NULL;
3103 char *fromName;
3104 char *toPath, *fromPath;
3105 int item;
3106 int index;
3108 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3109 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
3111 toName = WMRunInputPanel(scr, panel->win, _("Rename"), _("Rename palette to:"),
3112 fromName, _("OK"), _("Cancel"));
3114 if (toName) {
3116 /* As some people do certain stupid things... */
3117 if (strcmp(toName, fromName) == 0) {
3118 wfree(toName);
3119 return;
3122 /* For normal people */
3123 fromPath = wstrconcat(panel->configurationPath, fromName);
3124 toPath = wstrconcat(panel->configurationPath, toName);
3126 if (access(toPath, F_OK) == 0) {
3127 /* Careful, this palette exists already */
3128 if (WMRunAlertPanel(scr, panel->win, _("Warning"),
3129 _("Palette already exists !\n\nOverwrite ?"), _("No"), _("Yes"),
3130 NULL) == 1) {
3131 /* "No" = 0, "Yes" = 1 */
3132 int items = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
3134 remove(toPath);
3136 /* Remove from History list too */
3137 index = 1;
3138 while ((index < items)
3140 (strcmp(WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, index), toName)
3141 != 0))
3142 index++;
3144 if (index < items) {
3145 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, index);
3146 if (index < item)
3147 item--;
3150 } else {
3151 wfree(fromPath);
3152 wfree(toName);
3153 wfree(toPath);
3155 return;
3159 if (rename(fromPath, toPath) != 0)
3160 werror(_("Couldn't rename palette %s to %s"), fromName, toName);
3161 else {
3162 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3163 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item, toName);
3165 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
3167 wfree(fromPath);
3168 wfree(toPath);
3169 wfree(toName);
3173 static void customPaletteMenuRemove(W_ColorPanel * panel)
3175 W_Screen *scr = WMWidgetScreen(panel->win);
3176 char *text;
3177 char *tmp;
3178 int choice;
3179 int item;
3181 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3183 tmp = wstrconcat(_("This will permanently remove the palette "),
3184 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3185 text = wstrconcat(tmp, _(".\n\nAre you sure you want to remove this palette ?"));
3186 wfree(tmp);
3188 choice = WMRunAlertPanel(scr, panel->win, _("Remove"), text, _("Yes"), _("No"), NULL);
3189 /* returns 0 (= "Yes") or 1 (="No") */
3190 wfree(text);
3192 if (choice == 0) {
3194 tmp = wstrconcat(panel->configurationPath,
3195 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3197 if (remove(tmp) == 0) {
3198 /* item-1 always exists */
3199 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3201 customPaletteHistoryCallback(panel->customPaletteHistoryBtn, panel);
3202 customSetPalette(panel);
3204 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3206 } else {
3207 werror(_("Couldn't remove palette %s"), tmp);
3210 wfree(tmp);
3214 static void customPaletteHistoryCallback(WMWidget * w, void *data)
3216 W_ColorPanel *panel = (W_ColorPanel *) data;
3217 W_Screen *scr = WMWidgetScreen(panel->win);
3218 int item;
3219 char *filename;
3220 RImage *tmp = NULL;
3221 unsigned char perm_mask;
3223 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3224 if (item == panel->currentPalette)
3225 return;
3227 if (item == 0) {
3228 customRenderSpectrum(panel);
3230 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, False);
3231 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, False);
3232 } else {
3233 /* Load file from configpath */
3234 filename = wstrconcat(panel->configurationPath,
3235 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3237 /* If the file corresponding to the item does not exist,
3238 * remove it from the history list and select the next one.
3240 perm_mask = (access(filename, F_OK) == 0);
3241 if (!perm_mask) {
3242 /* File does not exist */
3243 wfree(filename);
3244 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3245 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3246 customPaletteHistoryCallback(w, data);
3247 return;
3250 /* Get the image */
3251 tmp = RLoadImage(scr->rcontext, filename, 0);
3252 if (tmp) {
3253 if (panel->customPaletteImg) {
3254 RReleaseImage(panel->customPaletteImg);
3255 panel->customPaletteImg = NULL;
3257 panel->customPaletteImg = tmp;
3260 /* If the image is not writable, don't allow removing/renaming */
3261 perm_mask = (access(filename, W_OK) == 0);
3262 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, perm_mask);
3263 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, perm_mask);
3265 wfree(filename);
3267 customSetPalette(panel);
3269 panel->currentPalette = item;
3272 /************************* ColorList Panel Functions **********************/
3274 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect)
3276 WMScreen *scr = WMWidgetScreen(lPtr);
3277 Display *dpy = WMScreenDisplay(scr);
3278 WMView *view = W_VIEW(lPtr);
3279 RColor *color = (RColor *) WMGetListItem(lPtr, index)->clientData;
3280 W_ColorPanel *panel = WMGetHangedData(lPtr);
3281 int width, height, x, y;
3282 WMColor *fillColor;
3284 width = rect->size.width;
3285 height = rect->size.height;
3286 x = rect->pos.x;
3287 y = rect->pos.y;
3289 if (state & WLDSSelected)
3290 XFillRectangle(dpy, d, WMColorGC(scr->white), x, y, width, height);
3291 else
3292 XFillRectangle(dpy, d, WMColorGC(view->backColor), x, y, width, height);
3294 fillColor = WMCreateRGBColor(scr, color->red << 8, color->green << 8, color->blue << 8, True);
3296 XFillRectangle(dpy, d, WMColorGC(fillColor), x, y, 15, height);
3297 WMReleaseColor(fillColor);
3299 WMDrawString(scr, d, scr->black, panel->font12, x + 18, y, text, strlen(text));
3302 static void colorListSelect(WMWidget * w, void *data)
3304 W_ColorPanel *panel = (W_ColorPanel *) data;
3305 CPColor cpColor;
3307 cpColor.rgb = *((RColor *) WMGetListSelectedItem(w)->clientData);
3308 cpColor.set = cpRGB;
3310 panel->lastChanged = WMColorListModeColorPanel;
3311 updateSwatch(panel, cpColor);
3314 static void colorListColorMenuCallback(WMWidget * w, void *data)
3316 W_ColorPanel *panel = (W_ColorPanel *) data;
3317 int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
3319 /* Parameter not used, but tell the compiler that it is ok */
3320 (void) w;
3322 switch (item) {
3323 case CLmenuAdd:
3324 break;
3325 case CLmenuRename:
3326 break;
3327 case CLmenuRemove:
3328 break;
3332 static void colorListListMenuCallback(WMWidget * w, void *data)
3334 W_ColorPanel *panel = (W_ColorPanel *) data;
3335 int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
3337 /* Parameter not used, but tell the compiler that it is ok */
3338 (void) w;
3340 switch (item) {
3341 case CLmenuAdd:
3342 break;
3343 case CLmenuRename:
3344 break;
3345 case CLmenuRemove:
3346 break;
3350 /*************** Panel Initialisation Functions *****************/
3352 static void wheelInit(W_ColorPanel * panel)
3354 CPColor cpColor;
3356 if (panel->color.set != cpHSV)
3357 convertCPColor(&panel->color);
3359 WMSetSliderValue(panel->wheelBrightnessS, 255 - panel->color.hsv.value);
3361 panel->colx = 2 + rint((colorWheelSize / 2.0) *
3362 (1 + (panel->color.hsv.saturation / 255.0) *
3363 cos(panel->color.hsv.hue * M_PI / 180.0)));
3364 panel->coly = 2 + rint((colorWheelSize / 2.0) *
3365 (1 + (panel->color.hsv.saturation / 255.0) *
3366 sin(-panel->color.hsv.hue * M_PI / 180.0)));
3368 wheelCalculateValues(panel, panel->color.hsv.value);
3370 cpColor = panel->color;
3371 cpColor.hsv.value = 255;
3372 cpColor.set = cpHSV;
3373 wheelUpdateBrightnessGradient(panel, cpColor);
3376 static void grayInit(W_ColorPanel * panel)
3378 int value;
3379 char tmp[4];
3381 if (panel->color.set != cpHSV)
3382 convertCPColor(&panel->color);
3384 value = rint(panel->color.hsv.value / 2.55);
3385 WMSetSliderValue(panel->grayBrightnessS, value);
3387 sprintf(tmp, "%d", value);
3388 WMSetTextFieldText(panel->grayBrightnessT, tmp);
3391 static void rgbInit(W_ColorPanel * panel)
3393 char tmp[4];
3395 if (panel->color.set != cpRGB)
3396 convertCPColor(&panel->color);
3398 WMSetSliderValue(panel->rgbRedS, panel->color.rgb.red);
3399 WMSetSliderValue(panel->rgbGreenS, panel->color.rgb.green);
3400 WMSetSliderValue(panel->rgbBlueS, panel->color.rgb.blue);
3402 sprintf(tmp, "%d", panel->color.rgb.red);
3403 WMSetTextFieldText(panel->rgbRedT, tmp);
3404 sprintf(tmp, "%d", panel->color.rgb.green);
3405 WMSetTextFieldText(panel->rgbGreenT, tmp);
3406 sprintf(tmp, "%d", panel->color.rgb.blue);
3407 WMSetTextFieldText(panel->rgbBlueT, tmp);
3410 static void cmykInit(W_ColorPanel * panel)
3412 int value[3];
3413 char tmp[4];
3415 if (panel->color.set != cpRGB)
3416 convertCPColor(&panel->color);
3418 value[0] = rint((255 - panel->color.rgb.red) / 2.55);
3419 value[1] = rint((255 - panel->color.rgb.green) / 2.55);
3420 value[2] = rint((255 - panel->color.rgb.blue) / 2.55);
3422 WMSetSliderValue(panel->cmykCyanS, value[0]);
3423 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3424 WMSetSliderValue(panel->cmykYellowS, value[2]);
3425 WMSetSliderValue(panel->cmykBlackS, 0);
3427 sprintf(tmp, "%d", value[0]);
3428 WMSetTextFieldText(panel->cmykCyanT, tmp);
3429 sprintf(tmp, "%d", value[1]);
3430 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3431 sprintf(tmp, "%d", value[2]);
3432 WMSetTextFieldText(panel->cmykYellowT, tmp);
3433 WMSetTextFieldText(panel->cmykBlackT, "0");
3436 static void hsbInit(W_ColorPanel * panel)
3438 int value[3];
3439 char tmp[4];
3441 if (panel->color.set != cpHSV)
3442 convertCPColor(&panel->color);
3444 value[0] = panel->color.hsv.hue;
3445 value[1] = rint(panel->color.hsv.saturation / 2.55);
3446 value[2] = rint(panel->color.hsv.value / 2.55);
3448 WMSetSliderValue(panel->hsbHueS, value[0]);
3449 WMSetSliderValue(panel->hsbSaturationS, value[1]);
3450 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
3452 sprintf(tmp, "%d", value[0]);
3453 WMSetTextFieldText(panel->hsbHueT, tmp);
3454 sprintf(tmp, "%d", value[1]);
3455 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3456 sprintf(tmp, "%d", value[2]);
3457 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3459 hsbUpdateBrightnessGradient(panel);
3460 hsbUpdateSaturationGradient(panel);
3461 hsbUpdateHueGradient(panel);
3464 /************************** Common utility functions ************************/
3466 static char *generateNewFilename(const char *curName)
3468 int n;
3469 char c;
3470 int baseLen;
3471 const char *ptr;
3472 char *newName;
3474 assert(curName);
3476 ptr = curName;
3478 if (((ptr = strrchr(ptr, '{')) == 0) || sscanf(ptr, "{%i}%c", &n, &c) != 1)
3479 return wstrconcat(curName, " {1}");
3481 baseLen = ptr - curName - 1;
3483 newName = wmalloc(baseLen + 16);
3484 strncpy(newName, curName, baseLen);
3486 snprintf(&newName[baseLen], 16, " {%i}", n + 1);
3488 return newName;
3491 static void convertCPColor(CPColor * color)
3493 unsigned short old_hue = 0;
3495 switch (color->set) {
3496 case cpNone:
3497 wwarning(_("Color Panel: Color unspecified"));
3498 return;
3499 case cpRGB:
3500 old_hue = color->hsv.hue;
3501 RRGBtoHSV(&(color->rgb), &(color->hsv));
3503 /* In black the hue is undefined, and may change by conversion
3504 * Same for white. */
3505 if (((color->rgb.red == 0) &&
3506 (color->rgb.green == 0) &&
3507 (color->rgb.blue == 0)) ||
3508 ((color->rgb.red == 0) && (color->rgb.green == 0) && (color->rgb.blue == 255))
3510 color->hsv.hue = old_hue;
3511 break;
3512 case cpHSV:
3513 RHSVtoRGB(&(color->hsv), &(color->rgb));
3514 break;
3518 #define ABS_SHIFT(val, shift) \
3519 (((shift) > 0) ? (val) >> (shift) : (val) << -(shift))
3521 static RColor ulongToRColor(WMScreen * scr, unsigned long value)
3523 RColor color;
3524 XColor *xcolor = NULL;
3526 xcolor = wmalloc(sizeof(XColor));
3527 xcolor->pixel = value;
3528 XQueryColor(scr->display, scr->rcontext->cmap, xcolor);
3530 color.red = xcolor->red >> 8;
3531 color.green = xcolor->green >> 8;
3532 color.blue = xcolor->blue >> 8;
3533 color.alpha = 0;
3535 wfree(xcolor);
3537 return color;
3540 static unsigned char getShift(unsigned char value)
3542 unsigned char i = -1;
3544 if (value == 0)
3545 return 0;
3547 while (value) {
3548 value >>= 1;
3549 i++;
3552 return i;