Update Serbian translation from master branch
[wmaker-crm.git] / WINGs / wcolorpanel.c
blobb799e0d0522bdcdebf23aab38b9e3498a8411bb1
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 const 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 static unsigned char Cursor_shape_bits[] = {
71 0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
72 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
73 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
74 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
75 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
76 0x00, 0x08, 0x00, 0x70, 0x00, 0x10, 0x00, 0xf8, 0x00, 0x20, 0x00, 0xfc, 0x01, 0xc0, 0x81,
77 0xfb, 0x03, 0x00, 0x7e, 0xf0, 0x07, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xc0, 0x1f, 0x00,
78 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xfc,
79 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x70
82 /* Clip-mask for magnified pixels */
83 #define Cursor_mask_width 24
84 #define Cursor_mask_height 24
85 static unsigned char Cursor_mask_bits[] = {
86 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0xff, 0x07,
87 0xf0, 0xff, 0x0f, 0xf8, 0xff, 0x1f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f,
88 0xfc, 0xff, 0x3f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f,
89 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfc, 0xff, 0x3f,
90 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xf8, 0xff, 0x1f, 0xf0, 0xff, 0x0f,
91 0xe0, 0xff, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00
94 typedef struct MovingView {
95 WMView *view; /* The view this is all about */
96 XImage *image; /* What's under the view */
97 XImage *dirtyRect; /* Storage of overlapped image area */
98 Pixmap magPix; /* Magnified part of pixmap */
99 RColor color; /* Color of a pixel in the image */
100 int x, y; /* Position of view */
101 } MovingView;
103 typedef struct CPColor {
104 RColor rgb; /* The RGB values of the color */
105 RHSVColor hsv; /* The HSV values of the color */
106 enum { /* Which one was last set ? */
107 cpNone,
108 cpRGB,
109 cpHSV
110 } set;
111 } CPColor;
113 typedef struct WheelMatrix {
114 unsigned int width, height; /* Size of the colorwheel */
115 unsigned char *data[3]; /* Wheel data (R,G,B) */
116 unsigned char values[256]; /* Precalculated values R,G & B = 0-255 */
117 } wheelMatrix;
119 typedef struct W_ColorPanel {
120 WMWindow *win;
121 WMFont *font8;
122 WMFont *font12;
123 void *clientData;
124 WMAction2 *action;
126 /* Common Stuff */
127 WMColorWell *colorWell;
128 WMButton *magnifyBtn;
129 WMButton *wheelBtn;
130 WMButton *slidersBtn;
131 WMButton *customPaletteBtn;
132 WMButton *colorListBtn;
134 /* Magnifying Glass */
135 MovingView *magnifyGlass;
137 /* ColorWheel Panel */
138 WMFrame *wheelFrm;
139 WMSlider *wheelBrightnessS;
140 WMView *wheelView;
142 /* Slider Panels */
143 WMFrame *slidersFrm;
144 WMFrame *seperatorFrm;
145 WMButton *grayBtn;
146 WMButton *rgbBtn;
147 WMButton *cmykBtn;
148 WMButton *hsbBtn;
149 /* Gray Scale Panel */
150 WMFrame *grayFrm;
151 WMLabel *grayMinL;
152 WMLabel *grayMaxL;
153 WMSlider *grayBrightnessS;
154 WMTextField *grayBrightnessT;
155 WMButton *grayPresetBtn[7];
157 /* RGB Panel */
158 WMButton *rgbDecB;
159 WMButton *rgbHexB;
160 WMFrame *rgbFrm;
161 WMLabel *rgbMinL;
162 WMLabel *rgbMaxL;
163 WMSlider *rgbRedS;
164 WMSlider *rgbGreenS;
165 WMSlider *rgbBlueS;
166 WMTextField *rgbRedT;
167 WMTextField *rgbGreenT;
168 WMTextField *rgbBlueT;
169 enum {
170 RGBdec,
171 RGBhex
172 } rgbState;
174 /* CMYK Panel */
175 WMFrame *cmykFrm;
176 WMLabel *cmykMinL;
177 WMLabel *cmykMaxL;
178 WMSlider *cmykCyanS;
179 WMSlider *cmykMagentaS;
180 WMSlider *cmykYellowS;
181 WMSlider *cmykBlackS;
182 WMTextField *cmykCyanT;
183 WMTextField *cmykMagentaT;
184 WMTextField *cmykYellowT;
185 WMTextField *cmykBlackT;
187 /* HSB Panel */
188 WMFrame *hsbFrm;
189 WMSlider *hsbHueS;
190 WMSlider *hsbSaturationS;
191 WMSlider *hsbBrightnessS;
192 WMTextField *hsbHueT;
193 WMTextField *hsbSaturationT;
194 WMTextField *hsbBrightnessT;
196 /* Custom Palette Panel */
197 WMFrame *customPaletteFrm;
198 WMPopUpButton *customPaletteHistoryBtn;
199 WMFrame *customPaletteContentFrm;
200 WMPopUpButton *customPaletteMenuBtn;
201 WMView *customPaletteContentView;
203 /* Color List Panel */
204 WMFrame *colorListFrm;
205 WMPopUpButton *colorListHistoryBtn;
206 WMList *colorListContentLst;
207 WMPopUpButton *colorListColorMenuBtn;
208 WMPopUpButton *colorListListMenuBtn;
210 /* Look-Up Tables and Images */
211 wheelMatrix *wheelMtrx;
212 Pixmap wheelImg;
213 Pixmap selectionImg;
214 Pixmap selectionBackImg;
215 RImage *customPaletteImg;
216 char *lastBrowseDir;
218 /* Common Data Fields */
219 CPColor color; /* Current color */
220 WMColorPanelMode mode; /* Current color selection mode */
221 WMColorPanelMode slidersmode; /* Current color sel. mode sliders panel */
222 WMColorPanelMode lastChanged; /* Panel that last changed the color */
223 int colx, coly; /* (x,y) of sel.-marker in WheelMode */
224 int palx, paly; /* (x,y) of sel.-marker in
225 CustomPaletteMode */
226 double palXRatio, palYRatio; /* Ratios in x & y between
227 original and scaled
228 palettesize */
229 int currentPalette;
230 char *configurationPath;
232 struct {
233 unsigned int continuous:1;
234 unsigned int dragging:1;
235 } flags;
236 } W_ColorPanel;
238 enum {
239 CPmenuNewFromFile,
240 CPmenuRename,
241 CPmenuRemove,
242 CPmenuCopy,
243 CPmenuNewFromClipboard
244 } customPaletteMenuItem;
246 enum {
247 CLmenuAdd,
248 CLmenuRename,
249 CLmenuRemove
250 } colorListMenuItem;
252 #define PWIDTH 194
253 #define PHEIGHT 266
254 #define colorWheelSize 150
255 #define customPaletteWidth 182
256 #define customPaletteHeight 106
257 #define knobThickness 8
259 #define SPECTRUM_WIDTH 511
260 #define SPECTRUM_HEIGHT 360
262 #define COLORWHEEL_PART 1
263 #define CUSTOMPALETTE_PART 2
266 static char *generateNewFilename(const char *curName);
267 static void convertCPColor(CPColor * color);
268 static RColor ulongToRColor(WMScreen * scr, unsigned long value);
269 static unsigned char getShift(unsigned char value);
271 static void modeButtonCallback(WMWidget * w, void *data);
272 static int getPickerPart(W_ColorPanel * panel, int x, int y);
273 static void readConfiguration(W_ColorPanel * panel);
274 static void readXColors(W_ColorPanel * panel);
276 static void closeWindowCallback(WMWidget * w, void *data);
278 static Cursor magnifyGrabPointer(W_ColorPanel * panel);
279 static WMPoint magnifyInitialize(W_ColorPanel * panel);
280 static void magnifyPutCursor(WMWidget * w, void *data);
281 static Pixmap magnifyCreatePixmap(WMColorPanel * panel);
282 static void magnifyGetImageStored(W_ColorPanel * panel, int x1, int y1, int x2, int y2);
283 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h);
285 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height);
286 static void wheelDestroyMatrix(wheelMatrix * matrix);
287 static void wheelInitMatrix(W_ColorPanel * panel);
288 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue);
289 static void wheelRender(W_ColorPanel * panel);
290 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs);
291 static void wheelPaint(W_ColorPanel * panel);
293 static void wheelHandleEvents(XEvent * event, void *data);
294 static void wheelHandleActionEvents(XEvent * event, void *data);
295 static void wheelBrightnessSliderCallback(WMWidget * w, void *data);
296 static void wheelUpdateSelection(W_ColorPanel * panel);
297 static void wheelUndrawSelection(W_ColorPanel * panel);
299 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y);
300 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
301 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel);
302 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor);
304 static void grayBrightnessSliderCallback(WMWidget * w, void *data);
305 static void grayPresetButtonCallback(WMWidget * w, void *data);
306 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification);
308 static void rgbSliderCallback(WMWidget * w, void *data);
309 static void rgbTextFieldCallback(void *observerData, WMNotification * notification);
310 static void rgbDecToHex(WMWidget *w, void *data);
312 static void cmykSliderCallback(WMWidget * w, void *data);
313 static void cmykTextFieldCallback(void *observerData, WMNotification * notification);
315 static void hsbSliderCallback(WMWidget * w, void *data);
316 static void hsbTextFieldCallback(void *observerData, WMNotification * notification);
317 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel);
318 static void hsbUpdateSaturationGradient(W_ColorPanel * panel);
319 static void hsbUpdateHueGradient(W_ColorPanel * panel);
321 static void customRenderSpectrum(W_ColorPanel * panel);
322 static void customSetPalette(W_ColorPanel * panel);
323 static void customPaletteHandleEvents(XEvent * event, void *data);
324 static void customPaletteHandleActionEvents(XEvent * event, void *data);
325 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y);
326 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
327 static void customPaletteMenuCallback(WMWidget * w, void *data);
328 static void customPaletteHistoryCallback(WMWidget * w, void *data);
330 static void customPaletteMenuNewFromFile(W_ColorPanel * panel);
331 static void customPaletteMenuRename(W_ColorPanel * panel);
332 static void customPaletteMenuRemove(W_ColorPanel * panel);
334 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect);
335 static void colorListSelect(WMWidget * w, void *data);
336 static void colorListColorMenuCallback(WMWidget * w, void *data);
337 static void colorListListMenuCallback(WMWidget * w, void *data);
339 static void wheelInit(W_ColorPanel * panel);
340 static void grayInit(W_ColorPanel * panel);
341 static void rgbInit(W_ColorPanel * panel);
342 static void cmykInit(W_ColorPanel * panel);
343 static void hsbInit(W_ColorPanel * panel);
346 static inline int get_textfield_as_integer(WMTextField *widget)
348 char *str;
349 int value;
351 str = WMGetTextFieldText(widget);
352 value = atoi(str);
353 wfree(str);
354 return value;
357 void WMSetColorPanelAction(WMColorPanel * panel, WMAction2 * action, void *data)
359 panel->action = action;
360 panel->clientData = data;
363 static WMColorPanel *makeColorPanel(WMScreen * scrPtr, const char *name)
365 WMColorPanel *panel;
366 RImage *image;
367 WMPixmap *pixmap;
368 RColor from;
369 RColor to;
370 WMColor *textcolor, *graybuttoncolor;
371 int i;
372 GC bgc = WMColorGC(scrPtr->black);
373 GC wgc = WMColorGC(scrPtr->white);
375 panel = wmalloc(sizeof(WMColorPanel));
376 panel->color.rgb.red = 0;
377 panel->color.rgb.green = 0;
378 panel->color.rgb.blue = 0;
379 panel->color.hsv.hue = 0;
380 panel->color.hsv.saturation = 0;
381 panel->color.hsv.value = 0;
382 panel->color.set = cpNone; /* Color has not been set yet */
384 panel->font8 = WMSystemFontOfSize(scrPtr, 8);
385 panel->font12 = WMSystemFontOfSize(scrPtr, 12);
387 panel->win = WMCreateWindowWithStyle(scrPtr, name,
388 WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
389 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
390 WMSetWindowTitle(panel->win, _("Colors"));
391 WMSetWindowCloseAction(panel->win, closeWindowCallback, panel);
393 /* Set Default ColorPanel Mode(s) */
394 panel->mode = WMWheelModeColorPanel;
395 panel->lastChanged = 0;
396 panel->slidersmode = WMRGBModeColorPanel;
397 panel->configurationPath = wstrconcat(wuserdatapath(), "/Colors/");
399 /* Some General Purpose Widgets */
400 panel->colorWell = WMCreateColorWell(panel->win);
401 WMResizeWidget(panel->colorWell, 134, 36);
402 WSetColorWellBordered(panel->colorWell, False);
403 WMMoveWidget(panel->colorWell, 56, 4);
405 panel->magnifyBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
406 WMResizeWidget(panel->magnifyBtn, 46, 36);
407 WMMoveWidget(panel->magnifyBtn, 6, 4);
408 WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
409 WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
410 WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
412 panel->wheelBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
413 WMResizeWidget(panel->wheelBtn, 46, 32);
414 WMMoveWidget(panel->wheelBtn, 6, 44);
415 WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
416 WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
417 WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
419 panel->slidersBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
420 WMResizeWidget(panel->slidersBtn, 46, 32);
421 WMMoveWidget(panel->slidersBtn, 52, 44);
422 WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
423 WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
424 WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
426 panel->customPaletteBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
427 WMResizeWidget(panel->customPaletteBtn, 46, 32);
428 WMMoveWidget(panel->customPaletteBtn, 98, 44);
429 WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
430 WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
431 WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
433 panel->colorListBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
434 WMResizeWidget(panel->colorListBtn, 46, 32);
435 WMMoveWidget(panel->colorListBtn, 144, 44);
436 WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
437 WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
438 WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
440 /* Let's Group some of them together */
441 WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
442 WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
443 WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
445 /* Widgets for the ColorWheel Panel */
446 panel->wheelFrm = WMCreateFrame(panel->win);
447 WMSetFrameRelief(panel->wheelFrm, WRFlat);
448 WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
449 WMMoveWidget(panel->wheelFrm, 5, 80);
451 panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
452 /* XXX Can we create a view ? */
453 W_ResizeView(panel->wheelView, colorWheelSize + 4, colorWheelSize + 4);
454 W_MoveView(panel->wheelView, 0, 0);
456 /* Create an event handler to handle expose/click events in ColorWheel */
457 WMCreateEventHandler(panel->wheelView,
458 ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
459 LeaveWindowMask | ButtonMotionMask, wheelHandleActionEvents, panel);
461 WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents, panel);
463 panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
464 WMResizeWidget(panel->wheelBrightnessS, 16, 153);
465 WMMoveWidget(panel->wheelBrightnessS, 5 + colorWheelSize + 14, 1);
466 WMSetSliderMinValue(panel->wheelBrightnessS, 0);
467 WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
468 WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback, panel);
469 WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
471 panel->wheelMtrx = wheelCreateMatrix(colorWheelSize + 4, colorWheelSize + 4);
472 wheelInitMatrix(panel);
474 /* Widgets for the Slider Panels */
475 panel->slidersFrm = WMCreateFrame(panel->win);
476 WMSetFrameRelief(panel->slidersFrm, WRFlat);
477 WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
478 WMMoveWidget(panel->slidersFrm, 4, 80);
480 panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
481 WMSetFrameRelief(panel->seperatorFrm, WRPushed);
482 WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
483 WMMoveWidget(panel->seperatorFrm, 0, 1);
485 panel->grayBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
486 WMResizeWidget(panel->grayBtn, 46, 24);
487 WMMoveWidget(panel->grayBtn, 1, 8);
488 WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
489 WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
490 WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
492 panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
493 WMResizeWidget(panel->rgbBtn, 46, 24);
494 WMMoveWidget(panel->rgbBtn, 47, 8);
495 WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
496 WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
497 WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
499 panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
500 WMResizeWidget(panel->cmykBtn, 46, 24);
501 WMMoveWidget(panel->cmykBtn, 93, 8);
502 WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
503 WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
504 WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
506 panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
507 WMResizeWidget(panel->hsbBtn, 46, 24);
508 WMMoveWidget(panel->hsbBtn, 139, 8);
509 WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
510 WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
511 WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
513 /* Let's Group the Slider Panel Buttons Together */
514 WMGroupButtons(panel->grayBtn, panel->rgbBtn);
515 WMGroupButtons(panel->grayBtn, panel->cmykBtn);
516 WMGroupButtons(panel->grayBtn, panel->hsbBtn);
518 textcolor = WMDarkGrayColor(scrPtr);
520 /* Widgets for GrayScale Panel */
521 panel->grayFrm = WMCreateFrame(panel->slidersFrm);
522 WMSetFrameRelief(panel->grayFrm, WRFlat);
523 WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
524 WMMoveWidget(panel->grayFrm, 0, 34);
526 panel->grayMinL = WMCreateLabel(panel->grayFrm);
527 WMResizeWidget(panel->grayMinL, 20, 10);
528 WMMoveWidget(panel->grayMinL, 2, 2);
529 WMSetLabelText(panel->grayMinL, "0");
530 WMSetLabelTextAlignment(panel->grayMinL, WALeft);
531 WMSetLabelTextColor(panel->grayMinL, textcolor);
532 WMSetLabelFont(panel->grayMinL, panel->font8);
534 panel->grayMaxL = WMCreateLabel(panel->grayFrm);
535 WMResizeWidget(panel->grayMaxL, 40, 10);
536 WMMoveWidget(panel->grayMaxL, 104, 2);
537 WMSetLabelText(panel->grayMaxL, "100");
538 WMSetLabelTextAlignment(panel->grayMaxL, WARight);
539 WMSetLabelTextColor(panel->grayMaxL, textcolor);
540 WMSetLabelFont(panel->grayMaxL, panel->font8);
542 panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
543 WMResizeWidget(panel->grayBrightnessS, 141, 16);
544 WMMoveWidget(panel->grayBrightnessS, 2, 14);
545 WMSetSliderMinValue(panel->grayBrightnessS, 0);
546 WMSetSliderMaxValue(panel->grayBrightnessS, 100);
547 WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
548 WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback, panel);
550 from.red = 0;
551 from.green = 0;
552 from.blue = 0;
554 to.red = 255;
555 to.green = 255;
556 to.blue = 255;
558 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
559 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
560 RReleaseImage(image);
562 if (pixmap)
563 W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap,
564 panel->font12, 2, 0, 100, WALeft, scrPtr->white,
565 False, _("Brightness"), strlen(_("Brightness")));
566 else
567 wwarning(_("Color Panel: Could not allocate memory"));
569 WMSetSliderImage(panel->grayBrightnessS, pixmap);
570 WMReleasePixmap(pixmap);
572 panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
573 WMResizeWidget(panel->grayBrightnessT, 40, 18);
574 WMMoveWidget(panel->grayBrightnessT, 146, 13);
575 WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
576 WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel,
577 WMTextDidEndEditingNotification, panel->grayBrightnessT);
579 for (i = 0; i < 7; i++) {
580 pixmap = WMCreatePixmap(scrPtr, 13, 13, scrPtr->depth, False);
582 graybuttoncolor = WMCreateRGBColor(scrPtr, (255 / 6) * i << 8,
583 (255 / 6) * i << 8, (255 / 6) * i << 8, True);
584 WMPaintColorSwatch(graybuttoncolor, pixmap->pixmap, 0, 0, 15, 15);
585 WMReleaseColor(graybuttoncolor);
587 panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
588 WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
589 WMMoveWidget(panel->grayPresetBtn[i], 2 + (i * 20), 34);
590 WMSetButtonAction(panel->grayPresetBtn[i], grayPresetButtonCallback, panel);
591 WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
592 WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
593 WMReleasePixmap(pixmap);
597 /* End of GrayScale Panel */
599 /* Widgets for RGB Panel */
600 panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
601 WMSetFrameRelief(panel->rgbFrm, WRFlat);
602 WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
603 WMMoveWidget(panel->rgbFrm, 0, 34);
605 panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
606 WMResizeWidget(panel->rgbMinL, 20, 10);
607 WMMoveWidget(panel->rgbMinL, 2, 2);
608 WMSetLabelText(panel->rgbMinL, "0");
609 WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
610 WMSetLabelTextColor(panel->rgbMinL, textcolor);
611 WMSetLabelFont(panel->rgbMinL, panel->font8);
613 panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
614 WMResizeWidget(panel->rgbMaxL, 40, 10);
615 WMMoveWidget(panel->rgbMaxL, 104, 2);
616 WMSetLabelText(panel->rgbMaxL, "255");
617 WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
618 WMSetLabelTextColor(panel->rgbMaxL, textcolor);
619 WMSetLabelFont(panel->rgbMaxL, panel->font8);
621 panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
622 WMResizeWidget(panel->rgbRedS, 141, 16);
623 WMMoveWidget(panel->rgbRedS, 2, 14);
624 WMSetSliderMinValue(panel->rgbRedS, 0);
625 WMSetSliderMaxValue(panel->rgbRedS, 255);
626 WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
627 WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
629 to.red = 255;
630 to.green = 0;
631 to.blue = 0;
633 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
634 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
635 RReleaseImage(image);
637 if (pixmap)
638 W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12,
639 2, 0, 100, WALeft, scrPtr->white, False, _("Red"), strlen(_("Red")));
640 else
641 wwarning(_("Color Panel: Could not allocate memory"));
643 WMSetSliderImage(panel->rgbRedS, pixmap);
644 WMReleasePixmap(pixmap);
646 panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
647 WMResizeWidget(panel->rgbRedT, 40, 18);
648 WMMoveWidget(panel->rgbRedT, 146, 13);
649 WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
650 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbRedT);
652 panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
653 WMResizeWidget(panel->rgbGreenS, 141, 16);
654 WMMoveWidget(panel->rgbGreenS, 2, 36);
655 WMSetSliderMinValue(panel->rgbGreenS, 0);
656 WMSetSliderMaxValue(panel->rgbGreenS, 255);
657 WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
658 WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
660 to.red = 0;
661 to.green = 255;
662 to.blue = 0;
664 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
665 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
666 RReleaseImage(image);
668 if (pixmap)
669 W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12,
670 2, 0, 100, WALeft, scrPtr->white, False, _("Green"), strlen(_("Green")));
671 else
672 wwarning(_("Color Panel: Could not allocate memory"));
674 WMSetSliderImage(panel->rgbGreenS, pixmap);
675 WMReleasePixmap(pixmap);
677 panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
678 WMResizeWidget(panel->rgbGreenT, 40, 18);
679 WMMoveWidget(panel->rgbGreenT, 146, 35);
680 WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
681 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbGreenT);
683 panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
684 WMResizeWidget(panel->rgbBlueS, 141, 16);
685 WMMoveWidget(panel->rgbBlueS, 2, 58);
686 WMSetSliderMinValue(panel->rgbBlueS, 0);
687 WMSetSliderMaxValue(panel->rgbBlueS, 255);
688 WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
689 WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
691 to.red = 0;
692 to.green = 0;
693 to.blue = 255;
695 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
696 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
697 RReleaseImage(image);
699 if (pixmap)
700 W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12,
701 2, 0, 100, WALeft, scrPtr->white, False, _("Blue"), strlen(_("Blue")));
702 else
703 wwarning(_("Color Panel: Could not allocate memory"));
705 WMSetSliderImage(panel->rgbBlueS, pixmap);
706 WMReleasePixmap(pixmap);
708 panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
709 WMResizeWidget(panel->rgbBlueT, 40, 18);
710 WMMoveWidget(panel->rgbBlueT, 146, 57);
711 WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
712 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbBlueT);
714 panel->rgbDecB = WMCreateButton(panel->rgbFrm, WBTRadio);
715 WMSetButtonText(panel->rgbDecB, _("Decimal"));
716 WMSetButtonSelected(panel->rgbDecB, 1);
717 panel->rgbState = RGBdec;
718 WMSetButtonAction(panel->rgbDecB, rgbDecToHex, panel);
719 WMResizeWidget(panel->rgbDecB, PWIDTH - 8, 23);
720 WMMoveWidget(panel->rgbDecB, 2, 81);
722 panel->rgbHexB = WMCreateButton(panel->rgbFrm, WBTRadio);
723 WMSetButtonText(panel->rgbHexB, _("Hexadecimal"));
724 WMSetButtonAction(panel->rgbHexB, rgbDecToHex, panel);
725 WMResizeWidget(panel->rgbHexB, PWIDTH - 8, 23);
726 WMMoveWidget(panel->rgbHexB, 2, 104);
728 WMGroupButtons(panel->rgbDecB, panel->rgbHexB);
730 /* End of RGB Panel */
732 /* Widgets for CMYK Panel */
733 panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
734 WMSetFrameRelief(panel->cmykFrm, WRFlat);
735 WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
736 WMMoveWidget(panel->cmykFrm, 0, 34);
738 panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
739 WMResizeWidget(panel->cmykMinL, 20, 10);
740 WMMoveWidget(panel->cmykMinL, 2, 2);
741 WMSetLabelText(panel->cmykMinL, "0");
742 WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
743 WMSetLabelTextColor(panel->cmykMinL, textcolor);
744 WMSetLabelFont(panel->cmykMinL, panel->font8);
746 panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
747 WMResizeWidget(panel->cmykMaxL, 40, 10);
748 WMMoveWidget(panel->cmykMaxL, 104, 2);
749 WMSetLabelText(panel->cmykMaxL, "100");
750 WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
751 WMSetLabelTextColor(panel->cmykMaxL, textcolor);
752 WMSetLabelFont(panel->cmykMaxL, panel->font8);
754 panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
755 WMResizeWidget(panel->cmykCyanS, 141, 16);
756 WMMoveWidget(panel->cmykCyanS, 2, 14);
757 WMSetSliderMinValue(panel->cmykCyanS, 0);
758 WMSetSliderMaxValue(panel->cmykCyanS, 100);
759 WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
760 WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
762 from.red = 255;
763 from.green = 255;
764 from.blue = 255;
766 to.red = 0;
767 to.green = 255;
768 to.blue = 255;
770 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
771 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
772 RReleaseImage(image);
774 if (pixmap)
775 W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12,
776 2, 0, 100, WALeft, scrPtr->black, False, _("Cyan"), strlen(_("Cyan")));
777 else
778 wwarning(_("Color Panel: Could not allocate memory"));
780 WMSetSliderImage(panel->cmykCyanS, pixmap);
781 WMReleasePixmap(pixmap);
783 panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
784 WMResizeWidget(panel->cmykCyanT, 40, 18);
785 WMMoveWidget(panel->cmykCyanT, 146, 13);
786 WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
787 WMAddNotificationObserver(cmykTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->cmykCyanT);
789 panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
790 WMResizeWidget(panel->cmykMagentaS, 141, 16);
791 WMMoveWidget(panel->cmykMagentaS, 2, 36);
792 WMSetSliderMinValue(panel->cmykMagentaS, 0);
793 WMSetSliderMaxValue(panel->cmykMagentaS, 100);
794 WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
795 WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
797 to.red = 255;
798 to.green = 0;
799 to.blue = 255;
801 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
802 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
803 RReleaseImage(image);
805 if (pixmap)
806 W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12,
807 2, 0, 100, WALeft, scrPtr->black, False, _("Magenta"), strlen(_("Magenta")));
808 else
809 wwarning(_("Color Panel: Could not allocate memory"));
811 WMSetSliderImage(panel->cmykMagentaS, pixmap);
812 WMReleasePixmap(pixmap);
814 panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
815 WMResizeWidget(panel->cmykMagentaT, 40, 18);
816 WMMoveWidget(panel->cmykMagentaT, 146, 35);
817 WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
818 WMAddNotificationObserver(cmykTextFieldCallback, panel,
819 WMTextDidEndEditingNotification, panel->cmykMagentaT);
821 panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
822 WMResizeWidget(panel->cmykYellowS, 141, 16);
823 WMMoveWidget(panel->cmykYellowS, 2, 58);
824 WMSetSliderMinValue(panel->cmykYellowS, 0);
825 WMSetSliderMaxValue(panel->cmykYellowS, 100);
826 WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
827 WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
829 to.red = 255;
830 to.green = 255;
831 to.blue = 0;
833 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
834 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
835 RReleaseImage(image);
837 if (pixmap)
838 W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12,
839 2, 0, 100, WALeft, scrPtr->black, False, _("Yellow"), strlen(_("Yellow")));
840 else
841 wwarning(_("Color Panel: Could not allocate memory"));
843 WMSetSliderImage(panel->cmykYellowS, pixmap);
844 WMReleasePixmap(pixmap);
846 panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
847 WMResizeWidget(panel->cmykYellowT, 40, 18);
848 WMMoveWidget(panel->cmykYellowT, 146, 57);
849 WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
850 WMAddNotificationObserver(cmykTextFieldCallback, panel,
851 WMTextDidEndEditingNotification, panel->cmykYellowT);
853 panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
854 WMResizeWidget(panel->cmykBlackS, 141, 16);
855 WMMoveWidget(panel->cmykBlackS, 2, 80);
856 WMSetSliderMinValue(panel->cmykBlackS, 0);
857 WMSetSliderMaxValue(panel->cmykBlackS, 100);
858 WMSetSliderValue(panel->cmykBlackS, 0);
859 WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
860 WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
862 to.red = 0;
863 to.green = 0;
864 to.blue = 0;
866 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
867 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
868 RReleaseImage(image);
870 if (pixmap)
871 W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12,
872 2, 0, 100, WALeft, scrPtr->black, False, _("Black"), strlen(_("Black")));
873 else
874 wwarning(_("Color Panel: Could not allocate memory"));
876 WMSetSliderImage(panel->cmykBlackS, pixmap);
877 WMReleasePixmap(pixmap);
879 panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
880 WMResizeWidget(panel->cmykBlackT, 40, 18);
881 WMMoveWidget(panel->cmykBlackT, 146, 79);
882 WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
883 WMAddNotificationObserver(cmykTextFieldCallback, panel,
884 WMTextDidEndEditingNotification, panel->cmykBlackT);
885 /* End of CMYK Panel */
887 /* Widgets for HSB Panel */
888 panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
889 WMSetFrameRelief(panel->hsbFrm, WRFlat);
890 WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
891 WMMoveWidget(panel->hsbFrm, 0, 34);
893 panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
894 WMResizeWidget(panel->hsbHueS, 141, 16);
895 WMMoveWidget(panel->hsbHueS, 2, 14);
896 WMSetSliderMinValue(panel->hsbHueS, 0);
897 WMSetSliderMaxValue(panel->hsbHueS, 359);
898 WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
899 WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
901 panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
902 WMResizeWidget(panel->hsbHueT, 40, 18);
903 WMMoveWidget(panel->hsbHueT, 146, 13);
904 WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
905 WMAddNotificationObserver(hsbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->hsbHueT);
907 panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
908 WMResizeWidget(panel->hsbSaturationS, 141, 16);
909 WMMoveWidget(panel->hsbSaturationS, 2, 36);
910 WMSetSliderMinValue(panel->hsbSaturationS, 0);
911 WMSetSliderMaxValue(panel->hsbSaturationS, 100);
912 WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
913 WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
915 panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
916 WMResizeWidget(panel->hsbSaturationT, 40, 18);
917 WMMoveWidget(panel->hsbSaturationT, 146, 35);
918 WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
919 WMAddNotificationObserver(hsbTextFieldCallback, panel,
920 WMTextDidEndEditingNotification, panel->hsbSaturationT);
922 panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
923 WMResizeWidget(panel->hsbBrightnessS, 141, 16);
924 WMMoveWidget(panel->hsbBrightnessS, 2, 58);
925 WMSetSliderMinValue(panel->hsbBrightnessS, 0);
926 WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
927 WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
928 WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
930 panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
931 WMResizeWidget(panel->hsbBrightnessT, 40, 18);
932 WMMoveWidget(panel->hsbBrightnessT, 146, 57);
933 WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
934 WMAddNotificationObserver(hsbTextFieldCallback, panel,
935 WMTextDidEndEditingNotification, panel->hsbBrightnessT);
936 /* End of HSB Panel */
938 WMReleaseColor(textcolor);
940 /* Widgets for the CustomPalette Panel */
941 panel->customPaletteFrm = WMCreateFrame(panel->win);
942 WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
943 WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
944 WMMoveWidget(panel->customPaletteFrm, 5, 80);
946 panel->customPaletteHistoryBtn = WMCreatePopUpButton(panel->customPaletteFrm);
947 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, _("Spectrum"));
948 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
949 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1);
950 WMSetPopUpButtonAction(panel->customPaletteHistoryBtn, customPaletteHistoryCallback, panel);
951 WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
952 WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
954 panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
955 WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
956 WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
957 WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
959 panel->customPaletteContentView = W_CreateView(W_VIEW(panel->customPaletteContentFrm));
960 /* XXX Test if we can create a view */
961 W_ResizeView(panel->customPaletteContentView, customPaletteWidth, customPaletteHeight);
962 W_MoveView(panel->customPaletteContentView, 2, 2);
964 /* Create event handler to handle expose/click events in CustomPalette */
965 WMCreateEventHandler(panel->customPaletteContentView,
966 ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
967 ButtonMotionMask, customPaletteHandleActionEvents, panel);
969 WMCreateEventHandler(panel->customPaletteContentView, ExposureMask, customPaletteHandleEvents, panel);
971 panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
972 WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
973 WMSetPopUpButtonText(panel->customPaletteMenuBtn, _("Palette"));
974 WMSetPopUpButtonAction(panel->customPaletteMenuBtn, customPaletteMenuCallback, panel);
975 WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
976 WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
978 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from File..."));
979 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Rename..."));
980 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Remove"));
981 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Copy"));
982 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from Clipboard"));
984 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, 0);
985 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, 0);
986 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuCopy, 0);
987 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuNewFromClipboard, 0);
989 customRenderSpectrum(panel);
990 panel->currentPalette = 0;
991 panel->palx = customPaletteWidth / 2;
992 panel->paly = customPaletteHeight / 2;
994 /* Widgets for the ColorList Panel */
995 panel->colorListFrm = WMCreateFrame(panel->win);
996 WMSetFrameRelief(panel->colorListFrm, WRFlat);
997 WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
998 WMMoveWidget(panel->colorListFrm, 5, 80);
1000 panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
1001 WMAddPopUpButtonItem(panel->colorListHistoryBtn, _("X11-Colors"));
1002 WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn,
1003 WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn) - 1);
1004 /* WMSetPopUpButtonAction(panel->colorListHistoryBtn,
1005 * colorListHistoryCallback, panel); */
1006 WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
1007 WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
1009 panel->colorListContentLst = WMCreateList(panel->colorListFrm);
1010 WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
1011 WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
1012 WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
1013 WMMoveWidget(panel->colorListContentLst, 0, 23);
1014 WMHangData(panel->colorListContentLst, panel);
1016 panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1017 WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
1018 WMSetPopUpButtonText(panel->colorListColorMenuBtn, _("Color"));
1019 WMSetPopUpButtonAction(panel->colorListColorMenuBtn, colorListColorMenuCallback, panel);
1020 WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16) / 2, 20);
1021 WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
1023 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Add..."));
1024 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Rename..."));
1025 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Remove"));
1027 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuAdd, 0);
1028 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRename, 0);
1029 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRemove, 0);
1031 panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1032 WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
1033 WMSetPopUpButtonText(panel->colorListListMenuBtn, _("List"));
1034 WMSetPopUpButtonAction(panel->colorListListMenuBtn, colorListListMenuCallback, panel);
1035 WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2, 20);
1036 WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2 + 8, PHEIGHT - 130);
1038 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("New..."));
1039 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Rename..."));
1040 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Remove"));
1042 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuAdd, 0);
1043 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
1044 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
1046 WMRealizeWidget(panel->win);
1047 WMMapSubwidgets(panel->win);
1049 WMMapSubwidgets(panel->wheelFrm);
1050 WMMapSubwidgets(panel->slidersFrm);
1051 WMMapSubwidgets(panel->grayFrm);
1052 WMMapSubwidgets(panel->rgbFrm);
1053 WMMapSubwidgets(panel->cmykFrm);
1054 WMMapSubwidgets(panel->hsbFrm);
1055 WMMapSubwidgets(panel->customPaletteFrm);
1056 WMMapSubwidgets(panel->customPaletteContentFrm);
1057 WMMapSubwidgets(panel->colorListFrm);
1059 /* Pixmap to indicate selection positions
1060 * wheelframe MUST be mapped.
1062 panel->selectionImg = XCreatePixmap(scrPtr->display, WMWidgetXID(panel->win), 4, 4, scrPtr->depth);
1063 XFillRectangle(scrPtr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1064 XFillRectangle(scrPtr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1066 readConfiguration(panel);
1067 readXColors(panel);
1069 return panel;
1072 WMColorPanel *WMGetColorPanel(WMScreen * scrPtr)
1074 WMColorPanel *panel;
1076 if (scrPtr->sharedColorPanel)
1077 return scrPtr->sharedColorPanel;
1079 panel = makeColorPanel(scrPtr, "colorPanel");
1081 scrPtr->sharedColorPanel = panel;
1083 return panel;
1086 void WMFreeColorPanel(WMColorPanel * panel)
1088 W_Screen *scr;
1090 if (!panel)
1091 return;
1093 scr = WMWidgetScreen(panel->win);
1094 if (panel == scr->sharedColorPanel) {
1095 scr->sharedColorPanel = NULL;
1098 WMRemoveNotificationObserver(panel);
1099 WMUnmapWidget(panel->win);
1101 /* fonts */
1102 WMReleaseFont(panel->font8);
1103 WMReleaseFont(panel->font12);
1105 /* pixmaps */
1106 wheelDestroyMatrix(panel->wheelMtrx);
1107 if (panel->wheelImg)
1108 XFreePixmap(scr->display, panel->wheelImg);
1109 if (panel->selectionImg)
1110 XFreePixmap(scr->display, panel->selectionImg);
1111 if (panel->selectionBackImg)
1112 XFreePixmap(scr->display, panel->selectionBackImg);
1113 RReleaseImage(panel->customPaletteImg);
1115 /* structs */
1116 if (panel->lastBrowseDir)
1117 wfree(panel->lastBrowseDir);
1118 if (panel->configurationPath)
1119 wfree(panel->configurationPath);
1121 WMDestroyWidget(panel->win);
1123 wfree(panel);
1126 void WMCloseColorPanel(WMColorPanel * panel)
1128 WMFreeColorPanel(panel);
1131 void WMShowColorPanel(WMColorPanel * panel)
1133 WMScreen *scr = WMWidgetScreen(panel->win);
1134 WMColor *white = WMWhiteColor(scr);
1136 if (panel->color.set == cpNone)
1137 WMSetColorPanelColor(panel, white);
1138 WMReleaseColor(white);
1140 if (panel->mode != WMWheelModeColorPanel)
1141 WMPerformButtonClick(panel->wheelBtn);
1143 WMMapWidget(panel->win);
1146 static void closeWindowCallback(WMWidget * w, void *data)
1148 W_ColorPanel *panel = (W_ColorPanel *) data;
1150 /* Parameter not used, but tell the compiler that it is ok */
1151 (void) w;
1153 WMCloseColorPanel(panel);
1156 static void readConfiguration(W_ColorPanel * panel)
1158 /* XXX Doesn't take care of "invalid" files */
1160 DIR *dPtr;
1161 struct dirent *dp;
1162 int item;
1164 if (!wmkdirhier(panel->configurationPath)) {
1165 werror(_("Color Panel: Could not create directory %s needed"
1166 " to store configurations"), panel->configurationPath);
1167 WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
1168 WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
1169 WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
1170 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1171 _("File Error"),
1172 _("Could not create ColorPanel configuration directory"),
1173 _("OK"), NULL, NULL);
1174 return;
1177 if (!(dPtr = opendir(panel->configurationPath))) {
1178 wwarning("%s: %s", _("Color Panel: Could not find file"), panel->configurationPath);
1179 return;
1182 while ((dp = readdir(dPtr)) != NULL) {
1183 unsigned int perm_mask;
1184 char *path = wstrconcat(panel->configurationPath,
1185 dp->d_name);
1187 if (dp->d_name[0] != '.') {
1188 item = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
1189 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
1191 perm_mask = (access(path, R_OK) == 0);
1192 WMSetPopUpButtonItemEnabled(panel->customPaletteHistoryBtn, item, perm_mask);
1194 wfree(path);
1196 closedir(dPtr);
1199 static void readXColors(W_ColorPanel * panel)
1201 WMListItem *item;
1202 const RGBColor *entry;
1204 for (entry = rgbColors; entry->name != NULL; entry++) {
1205 item = WMAddListItem(panel->colorListContentLst, entry->name);
1206 item->clientData = (void *)&(entry->color);
1210 void WMSetColorPanelPickerMode(WMColorPanel * panel, WMColorPanelMode mode)
1212 W_Screen *scr = WMWidgetScreen(panel->win);
1214 if (mode != WMWheelModeColorPanel) {
1215 WMUnmapWidget(panel->wheelFrm);
1216 if (panel->selectionBackImg) {
1217 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1218 panel->selectionBackImg = None;
1221 if (mode != WMGrayModeColorPanel)
1222 WMUnmapWidget(panel->grayFrm);
1223 if (mode != WMRGBModeColorPanel)
1224 WMUnmapWidget(panel->rgbFrm);
1225 if (mode != WMCMYKModeColorPanel)
1226 WMUnmapWidget(panel->cmykFrm);
1227 if (mode != WMHSBModeColorPanel)
1228 WMUnmapWidget(panel->hsbFrm);
1229 if (mode != WMCustomPaletteModeColorPanel) {
1230 WMUnmapWidget(panel->customPaletteFrm);
1231 if (panel->selectionBackImg) {
1232 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1233 panel->selectionBackImg = None;
1236 if (mode != WMColorListModeColorPanel)
1237 WMUnmapWidget(panel->colorListFrm);
1238 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
1239 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1240 WMUnmapWidget(panel->slidersFrm);
1241 else
1242 panel->slidersmode = mode;
1244 if (mode == WMWheelModeColorPanel) {
1245 WMMapWidget(panel->wheelFrm);
1246 WMSetButtonSelected(panel->wheelBtn, True);
1247 if (panel->lastChanged != WMWheelModeColorPanel)
1248 wheelInit(panel);
1249 wheelRender(panel);
1250 wheelPaint(panel);
1251 } else if (mode == WMGrayModeColorPanel) {
1252 WMMapWidget(panel->slidersFrm);
1253 WMSetButtonSelected(panel->slidersBtn, True);
1254 WMMapWidget(panel->grayFrm);
1255 WMSetButtonSelected(panel->grayBtn, True);
1256 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1257 if (panel->lastChanged != WMGrayModeColorPanel)
1258 grayInit(panel);
1259 } else if (mode == WMRGBModeColorPanel) {
1260 WMMapWidget(panel->slidersFrm);
1261 WMSetButtonSelected(panel->slidersBtn, True);
1262 WMMapWidget(panel->rgbFrm);
1263 WMSetButtonSelected(panel->rgbBtn, True);
1264 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1265 if (panel->lastChanged != WMRGBModeColorPanel)
1266 rgbInit(panel);
1267 } else if (mode == WMCMYKModeColorPanel) {
1268 WMMapWidget(panel->slidersFrm);
1269 WMSetButtonSelected(panel->slidersBtn, True);
1270 WMMapWidget(panel->cmykFrm);
1271 WMSetButtonSelected(panel->cmykBtn, True);
1272 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1273 if (panel->lastChanged != WMCMYKModeColorPanel)
1274 cmykInit(panel);
1275 } else if (mode == WMHSBModeColorPanel) {
1276 WMMapWidget(panel->slidersFrm);
1277 WMSetButtonSelected(panel->slidersBtn, True);
1278 WMMapWidget(panel->hsbFrm);
1279 WMSetButtonSelected(panel->hsbBtn, True);
1280 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1281 if (panel->lastChanged != WMHSBModeColorPanel)
1282 hsbInit(panel);
1283 } else if (mode == WMCustomPaletteModeColorPanel) {
1284 WMMapWidget(panel->customPaletteFrm);
1285 WMSetButtonSelected(panel->customPaletteBtn, True);
1286 customSetPalette(panel);
1287 } else if (mode == WMColorListModeColorPanel) {
1288 WMMapWidget(panel->colorListFrm);
1289 WMSetButtonSelected(panel->colorListBtn, True);
1292 panel->mode = mode;
1295 WMColor *WMGetColorPanelColor(WMColorPanel * panel)
1297 return WMGetColorWellColor(panel->colorWell);
1300 void WMSetColorPanelColor(WMColorPanel * panel, WMColor * color)
1302 WMSetColorWellColor(panel->colorWell, color);
1304 panel->color.rgb.red = color->color.red >> 8;
1305 panel->color.rgb.green = color->color.green >> 8;
1306 panel->color.rgb.blue = color->color.blue >> 8;
1307 panel->color.set = cpRGB;
1309 if (panel->mode == panel->lastChanged)
1310 panel->lastChanged = 0;
1312 WMSetColorPanelPickerMode(panel, panel->mode);
1315 static void updateSwatch(WMColorPanel * panel, CPColor color)
1317 WMScreen *scr = WMWidgetScreen(panel->win);
1318 WMColor *wellcolor;
1320 if (color.set != cpRGB)
1321 convertCPColor(&color);
1323 panel->color = color;
1325 wellcolor = WMCreateRGBColor(scr, color.rgb.red << 8, color.rgb.green << 8, color.rgb.blue << 8, True);
1327 WMSetColorWellColor(panel->colorWell, wellcolor);
1328 WMReleaseColor(wellcolor);
1330 if (!panel->flags.dragging || panel->flags.continuous) {
1331 if (panel->action)
1332 (*panel->action) (panel, panel->clientData);
1334 WMPostNotificationName(WMColorPanelColorChangedNotification, panel, NULL);
1338 static void modeButtonCallback(WMWidget * w, void *data)
1340 W_ColorPanel *panel = (W_ColorPanel *) (data);
1342 if (w == panel->wheelBtn)
1343 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1344 else if (w == panel->slidersBtn)
1345 WMSetColorPanelPickerMode(panel, panel->slidersmode);
1346 else if (w == panel->customPaletteBtn)
1347 WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
1348 else if (w == panel->colorListBtn)
1349 WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
1350 else if (w == panel->grayBtn)
1351 WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
1352 else if (w == panel->rgbBtn)
1353 WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
1354 else if (w == panel->cmykBtn)
1355 WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
1356 else if (w == panel->hsbBtn)
1357 WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
1360 /****************** Magnifying Cursor Functions *******************/
1362 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h)
1364 int x0 = 0, y0 = 0, w0 = w, h0 = h;
1365 const int displayWidth = DisplayWidth(scr->display, scr->screen),
1366 displayHeight = DisplayHeight(scr->display, scr->screen);
1368 if (!(image && image->data)) {
1369 /* The image in panel->magnifyGlass->image does not exist yet.
1370 * Grab one from the screen (not beyond) and use it from now on.
1372 if (!(image = XGetImage(scr->display, scr->rootWin,
1373 x - Cursor_x_hot, y - Cursor_y_hot, w, h, AllPlanes, ZPixmap)))
1374 wwarning(_("Color Panel: X failed request"));
1376 return image;
1379 /* Coordinate correction for back pixmap
1380 * if magnifying glass is at screen-borders
1383 /* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
1384 * Hatched area is beyond screen border.
1386 * |<-Cursor_x_hot->|
1387 * ________________|_____
1388 * |/ / / / / / /| | |
1389 * | / / / / / / |(x,y) |
1390 * |/_/_/_/_/_/_/|________|
1391 * |<----x0----->|<--w0-->|
1395 /* Figure 2: Shifting of rectangle-to-grab at bottom/right
1396 * screen borders
1397 * Hatched area is beyond screen border
1399 * |<-Cursor_x_hot->|
1400 * ________________|_______________
1401 * | | | / / / / / /|
1402 * | (x,y)|/ / / / / / |
1403 * |___________________|_/_/_/_/_/_/|
1404 * |<-------w0-------->| |
1405 * |<---------------w--|----------->|
1406 * | |
1407 * x0 Displaywidth-1
1410 if (x < Cursor_x_hot) { /* see fig. 1 */
1411 x0 = Cursor_x_hot - x;
1412 w0 = w - x0;
1415 if (displayWidth - 1 < x - Cursor_x_hot + w) { /* see fig. 2 */
1416 w0 = (displayWidth) - (x - Cursor_x_hot);
1419 if (y < Cursor_y_hot) { /* see fig. 1 */
1420 y0 = Cursor_y_hot - y;
1421 h0 = h - y0;
1424 if (displayHeight - 1 < y - Cursor_y_hot + h) { /* see fig. 2 */
1425 h0 = (displayHeight) - (y - Cursor_y_hot);
1427 /* end of coordinate correction */
1429 /* Grab an image from the screen, clipped if necessary,
1430 * and put it in the existing panel->magnifyGlass->image
1431 * with the corresponding clipping offset.
1433 if (!XGetSubImage(scr->display, scr->rootWin,
1434 x - Cursor_x_hot + x0, y - Cursor_y_hot + y0, w0, h0, AllPlanes, ZPixmap, image, x0, y0))
1435 wwarning(_("Color Panel: X failed request"));
1437 return NULL;
1440 static void magnifyGetImageStored(WMColorPanel * panel, int x1, int y1, int x2, int y2)
1442 /* (x1, y1) = topleft corner of existing rectangle
1443 * (x2, y2) = topleft corner of new position
1446 W_Screen *scr = WMWidgetScreen(panel->win);
1447 int xa = 0, ya = 0, xb = 0, yb = 0;
1448 int width, height;
1449 const int dx = abs(x2 - x1), dy = abs(y2 - y1);
1450 XImage *image;
1451 const int x_min = Cursor_x_hot,
1452 y_min = Cursor_y_hot,
1453 x_max = DisplayWidth(scr->display, scr->screen) - 1 -
1454 (Cursor_mask_width - Cursor_x_hot),
1455 y_max = DisplayHeight(scr->display, scr->screen) - 1 - (Cursor_mask_height - Cursor_y_hot);
1457 if ((dx == 0) && (dy == 0) && panel->magnifyGlass->image)
1458 return; /* No movement */
1460 if (x1 < x2)
1461 xa = dx;
1462 else
1463 xb = dx;
1465 if (y1 < y2)
1466 ya = dy;
1467 else
1468 yb = dy;
1470 width = Cursor_mask_width - dx;
1471 height = Cursor_mask_height - dy;
1473 /* If the traversed distance is larger than the size of the magnifying
1474 * glass contents, there is no need to do dirty rectangles. A whole new
1475 * rectangle can be grabbed (unless that rectangle falls partially
1476 * off screen).
1477 * Destroying the image and setting it to NULL will achieve that later on.
1479 * Of course, grabbing an XImage beyond the borders of the screen will
1480 * cause trouble, this is considdered a special case. Part of the screen
1481 * is grabbed, but there is no need for dirty rectangles.
1483 if ((width <= 0) || (height <= 0)) {
1484 if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
1485 if (panel->magnifyGlass->image)
1486 XDestroyImage(panel->magnifyGlass->image);
1487 panel->magnifyGlass->image = NULL;
1489 } else {
1490 if (panel->magnifyGlass->image) {
1491 /* Get dirty rectangle from panel->magnifyGlass->image */
1492 panel->magnifyGlass->dirtyRect =
1493 XSubImage(panel->magnifyGlass->image, xa, ya, width, height);
1494 if (!panel->magnifyGlass->dirtyRect) {
1495 wwarning(_("Color Panel: X failed request"));
1496 return; /* X returned a NULL from XSubImage */
1501 /* Get image from screen */
1502 image = magnifyGetImage(scr, panel->magnifyGlass->image, x2, y2, Cursor_mask_width, Cursor_mask_height);
1503 if (image) { /* Only reassign if a *new* image was grabbed */
1504 panel->magnifyGlass->image = image;
1505 return;
1508 /* Copy previously stored rectangle on covered part of image */
1509 if (panel->magnifyGlass->image && panel->magnifyGlass->dirtyRect) {
1510 int old_height;
1512 /* "width" and "height" are used as coordinates here,
1513 * and run from [0...width-1] and [0...height-1] respectively.
1515 width--;
1516 height--;
1517 old_height = height;
1519 for (; width >= 0; width--)
1520 for (height = old_height; height >= 0; height--)
1521 XPutPixel(panel->magnifyGlass->image, xb + width, yb + height,
1522 XGetPixel(panel->magnifyGlass->dirtyRect, width, height));
1523 XDestroyImage(panel->magnifyGlass->dirtyRect);
1524 panel->magnifyGlass->dirtyRect = NULL;
1527 return;
1530 static Pixmap magnifyCreatePixmap(WMColorPanel * panel)
1532 W_Screen *scr = WMWidgetScreen(panel->win);
1533 int u, v;
1534 #ifndef USE_XSHAPE
1535 Pixmap pixmap;
1536 #endif
1537 unsigned long color;
1539 if (!panel->magnifyGlass->image)
1540 return None;
1542 if (!panel->magnifyGlass->magPix)
1543 return None;
1546 * Copy an area of only 5x5 pixels from the center of the image.
1548 for (u = 0; u < 5; u++) {
1549 for (v = 0; v < 5; v++) {
1550 color = XGetPixel(panel->magnifyGlass->image, u + 9, v + 9);
1552 XSetForeground(scr->display, scr->copyGC, color);
1554 if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
1555 panel->magnifyGlass->color = ulongToRColor(scr, color);
1557 /* The center square must eventually be centered around the
1558 * hotspot. The image needs shifting to achieve this. The amount of
1559 * shifting is (Cursor_mask_width/2 - 2 * square_size) = 11-10 = 1
1560 * _ _ _ _ _
1561 * |_|_|_|_|_|
1562 * ^------- center of center square == Cursor_x_hot
1564 XFillRectangle(scr->display, panel->magnifyGlass->magPix,
1565 scr->copyGC,
1566 u * 5 + (u == 0 ? 0 : -1), v * 5 + (v == 0 ? 0 : -1),
1567 (u == 0 ? 4 : 5), (v == 0 ? 4 : 5));
1571 #ifdef USE_XSHAPE
1572 return panel->magnifyGlass->magPix;
1573 #else
1574 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width, Cursor_mask_height, scr->depth);
1575 if (!pixmap)
1576 return None;
1578 XPutImage(scr->display, pixmap, scr->copyGC, panel->magnifyGlass->image,
1579 0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
1581 /* Copy the magnified pixmap, with the clip mask, to background pixmap */
1582 XCopyArea(scr->display, panel->magnifyGlass->magPix, pixmap,
1583 scr->clipGC, 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
1584 /* (2,2) puts center pixel on center of glass */
1586 return pixmap;
1587 #endif
1591 static WMView *magnifyCreateView(W_ColorPanel * panel)
1593 W_Screen *scr = WMWidgetScreen(panel->win);
1594 WMView *magView;
1596 magView = W_CreateTopView(scr);
1597 if (!magView)
1598 return NULL;
1600 magView->self = panel->win;
1601 magView->flags.topLevel = 1;
1602 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1603 magView->attribs.override_redirect = True;
1604 magView->attribs.save_under = True;
1606 W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
1608 W_RealizeView(magView);
1610 return magView;
1613 static Cursor magnifyGrabPointer(W_ColorPanel * panel)
1615 W_Screen *scr = WMWidgetScreen(panel->win);
1616 Pixmap magPixmap, magPixmap2;
1617 Cursor magCursor;
1618 XColor fgColor = { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 };
1619 XColor bgColor = { 0, 0xbf00, 0xa000, 0x5000, DoRed | DoGreen | DoBlue, 0 };
1621 /* Cursor creation stuff */
1622 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1623 (char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
1624 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1625 (char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
1627 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1628 &fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
1630 XFreePixmap(scr->display, magPixmap);
1631 XFreePixmap(scr->display, magPixmap2);
1633 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1635 /* Set up Pointer */
1636 XGrabPointer(scr->display, panel->magnifyGlass->view->window, True,
1637 PointerMotionMask | ButtonPressMask,
1638 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1640 return magCursor;
1643 static WMPoint magnifyInitialize(W_ColorPanel * panel)
1645 W_Screen *scr = WMWidgetScreen(panel->win);
1646 int x, y, u, v;
1647 unsigned int mask;
1648 Pixmap pixmap, clip_mask;
1649 WMPoint point;
1650 Window root_return, child_return;
1652 clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1653 (char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1654 1, 0, 1);
1655 panel->magnifyGlass->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
1656 5 * 5 - 1, 5 * 5 - 1, scr->depth);
1658 XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return, &x, &y, &u, &v, &mask);
1660 panel->magnifyGlass->image = NULL;
1662 /* Clipmask to make magnified view-contents circular */
1663 #ifdef USE_XSHAPE
1664 XShapeCombineMask(scr->display, WMViewXID(panel->magnifyGlass->view),
1665 ShapeBounding, 0, 0, clip_mask, ShapeSet);
1666 #else
1667 /* Clip circle in glass cursor */
1668 XSetClipMask(scr->display, scr->clipGC, clip_mask);
1669 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1670 #endif
1672 XFreePixmap(scr->display, clip_mask);
1674 /* Draw initial magnifying glass contents */
1675 magnifyGetImageStored(panel, x, y, x, y);
1677 pixmap = magnifyCreatePixmap(panel);
1678 XSetWindowBackgroundPixmap(scr->display, WMViewXID(panel->magnifyGlass->view), pixmap);
1679 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1680 XFlush(scr->display);
1682 #ifndef USE_XSHAPE
1683 XFreePixmap(scr->display, pixmap);
1684 #endif
1686 point.x = x;
1687 point.y = y;
1689 return point;
1692 static void magnifyPutCursor(WMWidget * w, void *data)
1694 W_ColorPanel *panel = (W_ColorPanel *) (data);
1695 W_Screen *scr = WMWidgetScreen(panel->win);
1696 Cursor magCursor;
1697 Pixmap pixmap;
1698 XEvent event;
1699 WMPoint initialPosition;
1701 /* Parameter not used, but tell the compiler that it is ok */
1702 (void) w;
1704 /* Destroy wheelBackImg, so it'll update properly */
1705 if (panel->selectionBackImg) {
1706 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1707 panel->selectionBackImg = None;
1710 /* Create magnifying glass */
1711 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1712 panel->magnifyGlass->view = magnifyCreateView(panel);
1713 if (!panel->magnifyGlass->view)
1714 return;
1716 initialPosition = magnifyInitialize(panel);
1717 panel->magnifyGlass->x = initialPosition.x;
1718 panel->magnifyGlass->y = initialPosition.y;
1720 W_MoveView(panel->magnifyGlass->view,
1721 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1722 W_MapView(panel->magnifyGlass->view);
1724 magCursor = magnifyGrabPointer(panel);
1726 while (panel->magnifyGlass->image) {
1727 WMNextEvent(scr->display, &event);
1729 /* Pack motion events */
1730 while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
1733 switch (event.type) {
1734 case ButtonPress:
1735 XDestroyImage(panel->magnifyGlass->image);
1736 panel->magnifyGlass->image = NULL;
1738 if (event.xbutton.button == Button1) {
1739 panel->color.rgb = panel->magnifyGlass->color;
1740 panel->color.set = cpRGB;
1741 updateSwatch(panel, panel->color);
1743 switch (panel->mode) {
1744 case WMWheelModeColorPanel:
1745 wheelInit(panel);
1746 wheelRender(panel);
1747 wheelPaint(panel);
1748 break;
1749 case WMGrayModeColorPanel:
1750 grayInit(panel);
1751 break;
1752 case WMRGBModeColorPanel:
1753 rgbInit(panel);
1754 break;
1755 case WMCMYKModeColorPanel:
1756 cmykInit(panel);
1757 break;
1758 case WMHSBModeColorPanel:
1759 hsbInit(panel);
1760 break;
1761 default:
1762 break;
1764 panel->lastChanged = panel->mode;
1766 WMSetButtonSelected(panel->magnifyBtn, False);
1767 break;
1769 case MotionNotify:
1770 while (XPending(event.xmotion.display)) {
1771 XEvent ev;
1772 XPeekEvent(event.xmotion.display, &ev);
1773 if (ev.type == MotionNotify)
1774 XNextEvent(event.xmotion.display, &event);
1775 else
1776 break;
1779 /* Get a "dirty rectangle" */
1780 magnifyGetImageStored(panel,
1781 panel->magnifyGlass->x, panel->magnifyGlass->y,
1782 event.xmotion.x_root, event.xmotion.y_root);
1784 /* Update coordinates */
1785 panel->magnifyGlass->x = event.xmotion.x_root;
1786 panel->magnifyGlass->y = event.xmotion.y_root;
1788 /* Move view */
1789 W_MoveView(panel->magnifyGlass->view,
1790 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1792 /* Put new image (with magn.) in view */
1793 pixmap = magnifyCreatePixmap(panel);
1794 if (pixmap != None) {
1795 /* Change the window background */
1796 XSetWindowBackgroundPixmap(scr->display,
1797 WMViewXID(panel->magnifyGlass->view), pixmap);
1798 /* Force an Expose (handled by X) */
1799 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1800 /* Synchronize the event queue, so the Expose is handled NOW */
1801 XFlush(scr->display);
1802 #ifndef USE_XSHAPE
1803 XFreePixmap(scr->display, pixmap);
1804 #endif
1806 break;
1808 /* Try XQueryPointer for this !!! It returns windows that the pointer
1809 * is over. Note: We found this solving the invisible donkey cap bug
1811 #if 0 /* As it is impossible to make this work in all cases,
1812 * we consider it confusing. Therefore we disabled it.
1814 case FocusOut: /* fall through */
1815 case FocusIn:
1817 * Color Panel window (panel->win) lost or received focus.
1818 * We need to update the pixmap in the magnifying glass.
1820 * BUG Doesn't work with focus switches between two windows
1821 * if none of them is the color panel.
1823 XUngrabPointer(scr->display, CurrentTime);
1824 W_UnmapView(panel->magnifyGlass->view);
1826 magnifyInitialize(panel);
1828 W_MapView(panel->magnifyGlass->view);
1829 XGrabPointer(scr->display, panel->magnifyGlass->view->window,
1830 True, PointerMotionMask | ButtonPressMask,
1831 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1832 break;
1833 #endif
1834 default:
1835 WMHandleEvent(&event);
1836 break;
1837 } /* of switch */
1840 XUngrabPointer(scr->display, CurrentTime);
1841 XFreeCursor(scr->display, magCursor);
1843 XFreePixmap(scr->display, panel->magnifyGlass->magPix);
1844 panel->magnifyGlass->magPix = None;
1846 W_UnmapView(panel->magnifyGlass->view);
1847 W_DestroyView(panel->magnifyGlass->view);
1848 panel->magnifyGlass->view = NULL;
1850 wfree(panel->magnifyGlass);
1853 /****************** ColorWheel Functions ************************/
1855 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height)
1857 wheelMatrix *matrix = NULL;
1858 int i;
1860 assert((width > 0) && (height > 0));
1862 matrix = wmalloc(sizeof(wheelMatrix));
1863 matrix->width = width;
1864 matrix->height = height;
1866 for (i = 0; i < 3; i++) {
1867 matrix->data[i] = wmalloc(width * height * sizeof(unsigned char));
1870 return matrix;
1873 static void wheelDestroyMatrix(wheelMatrix * matrix)
1875 int i;
1877 if (!matrix)
1878 return;
1880 for (i = 0; i < 3; i++) {
1881 if (matrix->data[i])
1882 wfree(matrix->data[i]);
1884 wfree(matrix);
1887 static void wheelInitMatrix(W_ColorPanel * panel)
1889 int i;
1890 int x, y;
1891 unsigned char *rp, *gp, *bp;
1892 CPColor cpColor;
1893 long ofs[4];
1894 int xcor, ycor;
1895 unsigned short sat;
1896 int dhue[4];
1897 const int cw_halfsize = (colorWheelSize + 4) / 2,
1898 cw_sqsize = (colorWheelSize + 4) * (colorWheelSize + 4), uchar_shift = getShift(sizeof(unsigned char));
1900 if (!panel->wheelMtrx)
1901 return;
1903 cpColor.hsv.value = 255;
1904 cpColor.set = cpHSV;
1906 ofs[0] = -1;
1907 ofs[1] = -(colorWheelSize + 4);
1909 /* offsets are counterclockwise (in triangles).
1911 * ofs[0] ---->
1912 * _______________________________________
1913 * [1] |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| o
1914 * s |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| f
1915 * f |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| s
1916 * o | | | | | | | | | | | | | | | | | | | | | [3]
1918 * <---- ofs[2]
1919 * ____
1920 * |\ /| <-- triangles
1921 * | \/ |
1922 * | /\ |
1923 * |/__\|
1926 for (y = 0; y < cw_halfsize; y++) {
1927 for (x = y; x < (colorWheelSize + 4 - y); x++) {
1928 /* (xcor, ycor) is (x,y) relative to center of matrix */
1929 xcor = 2 * x - 4 - colorWheelSize;
1930 ycor = 2 * y - 4 - colorWheelSize;
1932 /* RColor.saturation is unsigned char and will wrap after 255 */
1933 sat = rint(255.0 * sqrt(xcor * xcor + ycor * ycor) / colorWheelSize);
1935 cpColor.hsv.saturation = (unsigned char)sat;
1937 ofs[0]++; /* top quarter of matrix */
1938 ofs[1] += colorWheelSize + 4; /* left quarter */
1939 ofs[2] = cw_sqsize - 1 - ofs[0]; /* bottom quarter */
1940 ofs[3] = cw_sqsize - 1 - ofs[1]; /* right quarter */
1942 if (sat < 256) {
1943 if (xcor != 0)
1944 dhue[0] = rint(atan((double)ycor / (double)xcor) *
1945 (180.0 / WM_PI)) + (xcor < 0 ? 180.0 : 0.0);
1946 else
1947 dhue[0] = 270;
1949 dhue[0] = 360 - dhue[0]; /* Reverse direction of ColorWheel */
1950 dhue[1] = 270 - dhue[0] + (dhue[0] > 270 ? 360 : 0);
1951 dhue[2] = dhue[0] - 180 + (dhue[0] < 180 ? 360 : 0);
1952 dhue[3] = 90 - dhue[0] + (dhue[0] > 90 ? 360 : 0);
1954 for (i = 0; i < 4; i++) {
1955 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1956 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1957 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1959 cpColor.hsv.hue = dhue[i];
1960 convertCPColor(&cpColor);
1962 *rp = (unsigned char)(cpColor.rgb.red);
1963 *gp = (unsigned char)(cpColor.rgb.green);
1964 *bp = (unsigned char)(cpColor.rgb.blue);
1966 } else {
1967 for (i = 0; i < 4; i++) {
1968 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1969 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1970 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1972 *rp = (unsigned char)0;
1973 *gp = (unsigned char)0;
1974 *bp = (unsigned char)0;
1979 ofs[0] += 2 * y + 1;
1980 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2 * y);
1984 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue)
1986 unsigned int i;
1987 unsigned int v;
1989 for (i = 0; i < 256; i++) {
1990 /* We divide by 128 in advance, and check whether that number divides
1991 * by 2 properly. If not, we add one to round the number correctly
1993 v = (i * maxvalue) >> 7;
1994 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + (v & 0x01));
1998 static void wheelRender(W_ColorPanel * panel)
2000 W_Screen *scr = WMWidgetScreen(panel->win);
2001 int x, y;
2002 RImage *image;
2003 unsigned char *ptr;
2004 RColor gray;
2005 unsigned long ofs = 0;
2006 /*unsigned char shift = getShift(sizeof(unsigned char)); */
2008 image = RCreateImage(colorWheelSize + 4, colorWheelSize + 4, True);
2009 if (!image) {
2010 wwarning(_("Color Panel: Could not allocate memory"));
2011 return;
2014 ptr = image->data;
2016 /* TODO Make this transparent istead of gray */
2017 gray.red = gray.blue = 0xae;
2018 gray.green = 0xaa;
2020 for (y = 0; y < colorWheelSize + 4; y++) {
2021 for (x = 0; x < colorWheelSize + 4; x++) {
2022 if (wheelInsideColorWheel(panel, ofs)) {
2023 *(ptr++) =
2024 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]]);
2025 *(ptr++) =
2026 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]]);
2027 *(ptr++) =
2028 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]]);
2029 *(ptr++) = 0;
2030 } else {
2031 *(ptr++) = (unsigned char)(gray.red);
2032 *(ptr++) = (unsigned char)(gray.green);
2033 *(ptr++) = (unsigned char)(gray.blue);
2034 *(ptr++) = 255;
2036 ofs++;
2040 if (panel->wheelImg)
2041 XFreePixmap(scr->display, panel->wheelImg);
2043 RConvertImage(scr->rcontext, image, &panel->wheelImg);
2044 RReleaseImage(image);
2046 /* Check if backimage exists. If it doesn't, allocate and fill it */
2047 if (!panel->selectionBackImg) {
2048 panel->selectionBackImg = XCreatePixmap(scr->display,
2049 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
2050 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2051 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2052 /* -2 is hot spot correction */
2056 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs)
2058 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
2059 (panel->wheelMtrx->data[1][ofs] != 0) && (panel->wheelMtrx->data[2][ofs] != 0));
2062 static void wheelPaint(W_ColorPanel * panel)
2064 W_Screen *scr = WMWidgetScreen(panel->win);
2066 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
2067 scr->copyGC, 0, 0, colorWheelSize + 4, colorWheelSize + 4, 0, 0);
2069 /* Draw selection image */
2070 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2071 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2074 static void wheelHandleEvents(XEvent * event, void *data)
2076 W_ColorPanel *panel = (W_ColorPanel *) data;
2078 switch (event->type) {
2079 case Expose:
2080 if (event->xexpose.count != 0) /* TODO Improve */
2081 break;
2082 wheelPaint(panel);
2083 break;
2087 static void wheelHandleActionEvents(XEvent * event, void *data)
2089 W_ColorPanel *panel = (W_ColorPanel *) data;
2091 switch (event->type) {
2092 case ButtonPress:
2093 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) == COLORWHEEL_PART) {
2095 panel->lastChanged = WMWheelModeColorPanel;
2096 panel->flags.dragging = 1;
2098 wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
2100 break;
2102 case ButtonRelease:
2103 panel->flags.dragging = 0;
2104 if (!panel->flags.continuous) {
2105 if (panel->action)
2106 (*panel->action) (panel, panel->clientData);
2108 break;
2110 case MotionNotify:
2111 if (panel->flags.dragging) {
2112 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) == COLORWHEEL_PART) {
2113 wheelPositionSelection(panel, event->xmotion.x, event->xmotion.y);
2114 } else
2115 wheelPositionSelectionOutBounds(panel, event->xmotion.x, event->xmotion.y);
2117 break;
2121 static int getPickerPart(W_ColorPanel * panel, int x, int y)
2123 int lx, ly;
2124 unsigned long ofs;
2126 lx = x;
2127 ly = y;
2129 if (panel->mode == WMWheelModeColorPanel) {
2130 if ((lx >= 2) && (lx <= 2 + colorWheelSize) && (ly >= 2) && (ly <= 2 + colorWheelSize)) {
2132 ofs = ly * panel->wheelMtrx->width + lx;
2134 if (wheelInsideColorWheel(panel, ofs))
2135 return COLORWHEEL_PART;
2139 if (panel->mode == WMCustomPaletteModeColorPanel) {
2140 if ((lx >= 2) && (lx < customPaletteWidth - 2) && (ly >= 2) && (ly < customPaletteHeight - 2)) {
2141 return CUSTOMPALETTE_PART;
2145 return 0;
2148 static void wheelBrightnessSliderCallback(WMWidget * w, void *data)
2150 int value;
2152 W_ColorPanel *panel = (W_ColorPanel *) data;
2154 /* Parameter not used, but tell the compiler that it is ok */
2155 (void) w;
2157 value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2159 wheelCalculateValues(panel, value);
2161 if (panel->color.set == cpRGB) {
2162 convertCPColor(&panel->color);
2163 panel->color.set = cpHSV;
2166 panel->color.hsv.value = value;
2168 wheelRender(panel);
2169 wheelPaint(panel);
2170 wheelUpdateSelection(panel);
2173 static void wheelUpdateSelection(W_ColorPanel * panel)
2175 W_Screen *scr = WMWidgetScreen(panel->win);
2177 updateSwatch(panel, panel->color);
2178 panel->lastChanged = WMWheelModeColorPanel;
2180 /* Redraw color selector (and make a backup of the part it will cover) */
2181 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2182 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2183 /* "-2" is correction for hotspot location */
2184 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2185 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2186 /* see above */
2189 static void wheelUndrawSelection(W_ColorPanel * panel)
2191 W_Screen *scr = WMWidgetScreen(panel->win);
2193 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
2194 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2195 /* see above */
2198 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y)
2200 unsigned long ofs = (y * panel->wheelMtrx->width) + x;
2202 panel->color.rgb.red = panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]];
2204 panel->color.rgb.green = panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]];
2206 panel->color.rgb.blue = panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]];
2207 panel->color.set = cpRGB;
2209 wheelUndrawSelection(panel);
2211 panel->colx = x;
2212 panel->coly = y;
2214 wheelUpdateSelection(panel);
2215 wheelUpdateBrightnessGradientFromLocation(panel);
2218 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2220 int hue;
2221 int xcor, ycor;
2222 CPColor cpColor;
2224 xcor = x * 2 - colorWheelSize - 4;
2225 ycor = y * 2 - colorWheelSize - 4;
2227 panel->color.hsv.saturation = 255;
2228 panel->color.hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2230 if (xcor != 0)
2231 hue = rint(atan(-(double)ycor / (double)xcor) * (180.0 / WM_PI));
2232 else {
2233 if (ycor < 0)
2234 hue = 90;
2235 else
2236 hue = 270;
2239 if (xcor < 0)
2240 hue += 180;
2242 if ((xcor > 0) && (ycor > 0))
2243 hue += 360;
2245 panel->color.hsv.hue = hue;
2246 panel->color.set = cpHSV;
2247 convertCPColor(&panel->color);
2249 wheelUndrawSelection(panel);
2251 panel->colx = 2 + rint((colorWheelSize * (1.0 + cos(panel->color.hsv.hue * (WM_PI / 180.0)))) / 2.0);
2252 /* "+2" because of "colorWheelSize + 4" */
2253 panel->coly = 2 + rint((colorWheelSize * (1.0 + sin(-panel->color.hsv.hue * (WM_PI / 180.0)))) / 2.0);
2255 wheelUpdateSelection(panel);
2256 cpColor = panel->color;
2257 wheelUpdateBrightnessGradient(panel, cpColor);
2260 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel)
2262 CPColor from = {};
2263 unsigned long ofs;
2265 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2267 from.rgb.red = panel->wheelMtrx->data[0][ofs];
2268 from.rgb.green = panel->wheelMtrx->data[1][ofs];
2269 from.rgb.blue = panel->wheelMtrx->data[2][ofs];
2270 from.set = cpRGB;
2272 wheelUpdateBrightnessGradient(panel, from);
2275 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor)
2277 RColor to;
2278 RImage *sliderImg;
2279 WMPixmap *sliderPxmp;
2281 to.red = to.green = to.blue = 0;
2283 if (topColor.set == cpHSV)
2284 convertCPColor(&topColor);
2286 sliderImg = RRenderGradient(16, 153, &(topColor.rgb), &to, RGRD_VERTICAL);
2287 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win), sliderImg, 0);
2288 RReleaseImage(sliderImg);
2289 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
2290 WMReleasePixmap(sliderPxmp);
2293 /****************** Grayscale Panel Functions ***************/
2295 static void grayBrightnessSliderCallback(WMWidget * w, void *data)
2297 CPColor cpColor;
2298 int value;
2299 char tmp[4];
2300 W_ColorPanel *panel = (W_ColorPanel *) data;
2302 /* Parameter not used, but tell the compiler that it is ok */
2303 (void) w;
2305 value = WMGetSliderValue(panel->grayBrightnessS);
2307 sprintf(tmp, "%d", value);
2309 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2310 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint(2.55 * value);
2311 cpColor.set = cpRGB;
2313 updateSwatch(panel, cpColor);
2314 panel->lastChanged = WMGrayModeColorPanel;
2317 static void grayPresetButtonCallback(WMWidget * w, void *data)
2319 CPColor cpColor;
2320 char tmp[4];
2321 int value;
2322 int i = 0;
2323 W_ColorPanel *panel = (W_ColorPanel *) data;
2325 while (i < 7) {
2326 if (w == panel->grayPresetBtn[i])
2327 break;
2328 i++;
2331 value = rint((100.0 * i) / 6.0);
2332 sprintf(tmp, "%d", value);
2334 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2335 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * i) / 6.0);
2336 cpColor.set = cpRGB;
2338 WMSetSliderValue(panel->grayBrightnessS, rint((100.0 * i) / 6.0));
2340 updateSwatch(panel, cpColor);
2341 panel->lastChanged = WMGrayModeColorPanel;
2344 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification)
2346 CPColor cpColor;
2347 char tmp[4];
2348 int value;
2349 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2351 /* Parameter not used, but tell the compiler that it is ok */
2352 (void) notification;
2354 value = get_textfield_as_integer(panel->grayBrightnessT);
2355 if (value > 100)
2356 value = 100;
2357 if (value < 0)
2358 value = 0;
2360 sprintf(tmp, "%d", value);
2361 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2362 WMSetSliderValue(panel->grayBrightnessS, value);
2364 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * value) / 100.0);
2365 cpColor.set = cpRGB;
2367 updateSwatch(panel, cpColor);
2368 panel->lastChanged = WMGrayModeColorPanel;
2371 /******************* RGB Panel Functions *****************/
2373 void rgbIntToChar(W_ColorPanel *panel, int *value)
2375 char tmp[4];
2376 const char *format;
2378 switch (panel->rgbState) {
2379 case RGBdec:
2380 format = "%d";
2381 break;
2382 case RGBhex:
2383 format = "%0X";
2384 break;
2385 default:
2386 format = "";
2389 sprintf(tmp, format, value[0]);
2390 WMSetTextFieldText(panel->rgbRedT, tmp);
2391 sprintf(tmp, format, value[1]);
2392 WMSetTextFieldText(panel->rgbGreenT, tmp);
2393 sprintf(tmp, format, value[2]);
2394 WMSetTextFieldText(panel->rgbBlueT, tmp);
2397 int *rgbCharToInt(W_ColorPanel *panel)
2399 int base = 0;
2400 static int value[3];
2401 char *str;
2403 switch (panel->rgbState) {
2404 case RGBdec:
2405 base = 10;
2406 break;
2407 case RGBhex:
2408 base = 16;
2409 break;
2412 str = WMGetTextFieldText(panel->rgbRedT);
2413 value[0] = strtol(str, NULL, base);
2414 wfree(str);
2416 str = WMGetTextFieldText(panel->rgbGreenT);
2417 value[1] = strtol(str, NULL, base);
2418 wfree(str);
2420 str = WMGetTextFieldText(panel->rgbBlueT);
2421 value[2] = strtol(str, NULL, base);
2422 wfree(str);
2424 return value;
2427 static void rgbSliderCallback(WMWidget * w, void *data)
2429 CPColor cpColor;
2430 int value[3];
2431 W_ColorPanel *panel = (W_ColorPanel *) data;
2433 /* Parameter not used, but tell the compiler that it is ok */
2434 (void) w;
2436 value[0] = WMGetSliderValue(panel->rgbRedS);
2437 value[1] = WMGetSliderValue(panel->rgbGreenS);
2438 value[2] = WMGetSliderValue(panel->rgbBlueS);
2440 rgbIntToChar(panel, value);
2442 cpColor.rgb.red = value[0];
2443 cpColor.rgb.green = value[1];
2444 cpColor.rgb.blue = value[2];
2445 cpColor.set = cpRGB;
2447 updateSwatch(panel, cpColor);
2448 panel->lastChanged = WMRGBModeColorPanel;
2451 static void rgbTextFieldCallback(void *observerData, WMNotification * notification)
2453 CPColor cpColor;
2454 int *value;
2455 int n;
2456 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2458 /* Parameter not used, but tell the compiler that it is ok */
2459 (void) notification;
2461 value = rgbCharToInt(panel);
2463 for (n = 0; n < 3; n++) {
2464 if (value[n] > 255)
2465 value[n] = 255;
2466 if (value[n] < 0)
2467 value[n] = 0;
2470 rgbIntToChar(panel, value);
2472 WMSetSliderValue(panel->rgbRedS, value[0]);
2473 WMSetSliderValue(panel->rgbGreenS, value[1]);
2474 WMSetSliderValue(panel->rgbBlueS, value[2]);
2476 cpColor.rgb.red = value[0];
2477 cpColor.rgb.green = value[1];
2478 cpColor.rgb.blue = value[2];
2479 cpColor.set = cpRGB;
2481 updateSwatch(panel, cpColor);
2482 panel->lastChanged = WMRGBModeColorPanel;
2485 static void rgbDecToHex(WMWidget *w, void *data)
2487 W_ColorPanel *panel = (W_ColorPanel *) data;
2488 int *value;
2490 (void) w;
2492 switch (panel->rgbState) {
2493 case RGBhex:
2494 if (WMGetButtonSelected(panel->rgbDecB)) {
2495 WMSetLabelText(panel->rgbMaxL, "255");
2496 WMRedisplayWidget(panel->rgbMaxL);
2497 value = rgbCharToInt(panel);
2498 panel->rgbState = RGBdec;
2499 rgbIntToChar(panel, value);
2501 break;
2503 case RGBdec:
2504 if (WMGetButtonSelected(panel->rgbHexB)) {
2505 WMSetLabelText(panel->rgbMaxL, "FF");
2506 WMRedisplayWidget(panel->rgbMaxL);
2507 value = rgbCharToInt(panel);
2508 panel->rgbState = RGBhex;
2509 rgbIntToChar(panel, value);
2511 break;
2515 /******************* CMYK Panel Functions *****************/
2517 static void cmykSliderCallback(WMWidget * w, void *data)
2519 CPColor cpColor;
2520 int value[4];
2521 char tmp[4];
2522 W_ColorPanel *panel = (W_ColorPanel *) data;
2523 double scale;
2525 /* Parameter not used, but tell the compiler that it is ok */
2526 (void) w;
2528 value[0] = WMGetSliderValue(panel->cmykCyanS);
2529 value[1] = WMGetSliderValue(panel->cmykMagentaS);
2530 value[2] = WMGetSliderValue(panel->cmykYellowS);
2531 value[3] = WMGetSliderValue(panel->cmykBlackS);
2533 sprintf(tmp, "%d", value[0]);
2534 WMSetTextFieldText(panel->cmykCyanT, tmp);
2535 sprintf(tmp, "%d", value[1]);
2536 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2537 sprintf(tmp, "%d", value[2]);
2538 WMSetTextFieldText(panel->cmykYellowT, tmp);
2539 sprintf(tmp, "%d", value[3]);
2540 WMSetTextFieldText(panel->cmykBlackT, tmp);
2542 scale = 2.55 * (1.0 - (value[3] / 100.0));
2543 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2544 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2545 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2546 cpColor.set = cpRGB;
2548 updateSwatch(panel, cpColor);
2549 panel->lastChanged = WMCMYKModeColorPanel;
2552 static void cmykTextFieldCallback(void *observerData, WMNotification * notification)
2554 CPColor cpColor;
2555 int value[4];
2556 char tmp[4];
2557 int n;
2558 double scale;
2559 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2561 /* Parameter not used, but tell the compiler that it is ok */
2562 (void) notification;
2564 value[0] = get_textfield_as_integer(panel->cmykCyanT);
2565 value[1] = get_textfield_as_integer(panel->cmykMagentaT);
2566 value[2] = get_textfield_as_integer(panel->cmykYellowT);
2567 value[3] = get_textfield_as_integer(panel->cmykBlackT);
2569 for (n = 0; n < 4; n++) {
2570 if (value[n] > 100)
2571 value[n] = 100;
2572 if (value[n] < 0)
2573 value[n] = 0;
2576 sprintf(tmp, "%d", value[0]);
2577 WMSetTextFieldText(panel->cmykCyanT, tmp);
2579 sprintf(tmp, "%d", value[1]);
2580 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2582 sprintf(tmp, "%d", value[2]);
2583 WMSetTextFieldText(panel->cmykYellowT, tmp);
2585 sprintf(tmp, "%d", value[3]);
2586 WMSetTextFieldText(panel->cmykBlackT, tmp);
2588 WMSetSliderValue(panel->cmykCyanS, value[0]);
2589 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2590 WMSetSliderValue(panel->cmykYellowS, value[2]);
2591 WMSetSliderValue(panel->cmykBlackS, value[3]);
2593 scale = 2.55 * (1.0 - (value[3] / 100.0));
2594 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2595 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2596 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2597 cpColor.set = cpRGB;
2599 updateSwatch(panel, cpColor);
2600 panel->lastChanged = WMCMYKModeColorPanel;
2603 /********************** HSB Panel Functions ***********************/
2605 static void hsbSliderCallback(WMWidget * w, void *data)
2607 CPColor cpColor = {};
2608 int value[3];
2609 char tmp[4];
2610 W_ColorPanel *panel = (W_ColorPanel *) data;
2612 value[0] = WMGetSliderValue(panel->hsbHueS);
2613 value[1] = WMGetSliderValue(panel->hsbSaturationS);
2614 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
2616 sprintf(tmp, "%d", value[0]);
2617 WMSetTextFieldText(panel->hsbHueT, tmp);
2618 sprintf(tmp, "%d", value[1]);
2619 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2620 sprintf(tmp, "%d", value[2]);
2621 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2623 cpColor.hsv.hue = value[0];
2624 cpColor.hsv.saturation = value[1] * 2.55;
2625 cpColor.hsv.value = value[2] * 2.55;
2626 cpColor.set = cpHSV;
2628 convertCPColor(&cpColor);
2630 panel->lastChanged = WMHSBModeColorPanel;
2631 updateSwatch(panel, cpColor);
2633 if (w != panel->hsbBrightnessS)
2634 hsbUpdateBrightnessGradient(panel);
2635 if (w != panel->hsbSaturationS)
2636 hsbUpdateSaturationGradient(panel);
2637 if (w != panel->hsbHueS)
2638 hsbUpdateHueGradient(panel);
2641 static void hsbTextFieldCallback(void *observerData, WMNotification * notification)
2643 CPColor cpColor = {};
2644 int value[3];
2645 char tmp[12]; /* We only 4 bytes needed, but compilers cannot know that */
2646 int n;
2647 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2649 /* Parameter not used, but tell the compiler that it is ok */
2650 (void) notification;
2652 value[0] = get_textfield_as_integer(panel->hsbHueT);
2653 value[1] = get_textfield_as_integer(panel->hsbSaturationT);
2654 value[2] = get_textfield_as_integer(panel->hsbBrightnessT);
2656 if (value[0] > 359)
2657 value[0] = 359;
2658 if (value[0] < 0)
2659 value[0] = 0;
2661 for (n = 1; n < 3; n++) {
2662 if (value[n] > 100)
2663 value[n] = 100;
2664 if (value[n] < 0)
2665 value[n] = 0;
2668 sprintf(tmp, "%d", value[0]);
2669 WMSetTextFieldText(panel->hsbHueT, tmp);
2670 sprintf(tmp, "%d", value[1]);
2671 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2672 sprintf(tmp, "%d", value[2]);
2673 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2675 WMSetSliderValue(panel->hsbHueS, value[0]);
2676 WMSetSliderValue(panel->hsbSaturationS, value[1]);
2677 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
2679 cpColor.hsv.hue = value[0];
2680 cpColor.hsv.saturation = value[1] * 2.55;
2681 cpColor.hsv.value = value[2] * 2.55;
2682 cpColor.set = cpHSV;
2684 convertCPColor(&cpColor);
2686 panel->lastChanged = WMHSBModeColorPanel;
2687 updateSwatch(panel, cpColor);
2689 hsbUpdateBrightnessGradient(panel);
2690 hsbUpdateSaturationGradient(panel);
2691 hsbUpdateHueGradient(panel);
2694 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel)
2696 W_Screen *scr = WMWidgetScreen(panel->win);
2697 RColor from;
2698 CPColor to;
2699 RImage *sliderImg;
2700 WMPixmap *sliderPxmp;
2702 from.red = from.green = from.blue = 0;
2703 to.hsv = panel->color.hsv;
2704 to.hsv.value = 255;
2705 to.set = cpHSV;
2707 convertCPColor(&to);
2709 sliderImg = RRenderGradient(141, 16, &from, &(to.rgb), RGRD_HORIZONTAL);
2710 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2711 RReleaseImage(sliderImg);
2713 if (sliderPxmp)
2714 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
2715 panel->font12, 2, 0, 100, WALeft, scr->white,
2716 False, _("Brightness"), strlen(_("Brightness")));
2717 else
2718 wwarning(_("Color Panel: Could not allocate memory"));
2720 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
2721 WMReleasePixmap(sliderPxmp);
2724 static void hsbUpdateSaturationGradient(W_ColorPanel * panel)
2726 W_Screen *scr = WMWidgetScreen(panel->win);
2727 CPColor from;
2728 CPColor to;
2729 RImage *sliderImg;
2730 WMPixmap *sliderPxmp;
2732 from.hsv = panel->color.hsv;
2733 from.hsv.saturation = 0;
2734 from.set = cpHSV;
2735 convertCPColor(&from);
2737 to.hsv = panel->color.hsv;
2738 to.hsv.saturation = 255;
2739 to.set = cpHSV;
2740 convertCPColor(&to);
2742 sliderImg = RRenderGradient(141, 16, &(from.rgb), &(to.rgb), RGRD_HORIZONTAL);
2743 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2744 RReleaseImage(sliderImg);
2746 if (sliderPxmp)
2747 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2748 panel->font12, 2, 0, 100, WALeft,
2749 from.hsv.value < 128 ? scr->white : scr->black, False,
2750 _("Saturation"), strlen(_("Saturation")));
2751 else
2752 wwarning(_("Color Panel: Could not allocate memory"));
2754 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
2755 WMReleasePixmap(sliderPxmp);
2758 static void hsbUpdateHueGradient(W_ColorPanel * panel)
2760 W_Screen *scr = WMWidgetScreen(panel->win);
2761 RColor **colors = NULL;
2762 RHSVColor hsvcolor;
2763 RImage *sliderImg;
2764 WMPixmap *sliderPxmp;
2765 int i;
2767 hsvcolor = panel->color.hsv;
2769 colors = wmalloc(sizeof(RColor *) * (8));
2770 for (i = 0; i < 7; i++) {
2771 hsvcolor.hue = (360 * i) / 6;
2772 colors[i] = wmalloc(sizeof(RColor));
2773 RHSVtoRGB(&hsvcolor, colors[i]);
2775 colors[7] = NULL;
2777 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2778 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2779 RReleaseImage(sliderImg);
2781 if (sliderPxmp)
2782 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2783 panel->font12, 2, 0, 100, WALeft,
2784 hsvcolor.value < 128 ? scr->white : scr->black, False, _("Hue"), strlen(_("Hue")));
2785 else
2786 wwarning(_("Color Panel: Could not allocate memory"));
2788 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2789 WMReleasePixmap(sliderPxmp);
2791 for (i = 0; i < 7; i++)
2792 wfree(colors[i]);
2794 wfree(colors);
2797 /*************** Custom Palette Functions ****************/
2799 static void customRenderSpectrum(W_ColorPanel * panel)
2801 RImage *spectrum;
2802 int x, y;
2803 unsigned char *ptr;
2804 CPColor cpColor;
2806 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, False);
2808 ptr = spectrum->data;
2810 for (y = 0; y < SPECTRUM_HEIGHT; y++) {
2811 cpColor.hsv.hue = y;
2812 cpColor.hsv.saturation = 0;
2813 cpColor.hsv.value = 255;
2814 cpColor.set = cpHSV;
2816 for (x = 0; x < SPECTRUM_WIDTH; x++) {
2817 convertCPColor(&cpColor);
2819 *(ptr++) = (unsigned char)cpColor.rgb.red;
2820 *(ptr++) = (unsigned char)cpColor.rgb.green;
2821 *(ptr++) = (unsigned char)cpColor.rgb.blue;
2823 if (x < (SPECTRUM_WIDTH / 2))
2824 cpColor.hsv.saturation++;
2826 if (x > (SPECTRUM_WIDTH / 2))
2827 cpColor.hsv.value--;
2830 if (panel->customPaletteImg) {
2831 RReleaseImage(panel->customPaletteImg);
2832 panel->customPaletteImg = NULL;
2834 panel->customPaletteImg = spectrum;
2837 static void customSetPalette(W_ColorPanel * panel)
2839 W_Screen *scr = WMWidgetScreen(panel->win);
2840 RImage *scaledImg;
2841 Pixmap image;
2843 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth, customPaletteHeight, scr->depth);
2844 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth, customPaletteHeight);
2845 RConvertImage(scr->rcontext, scaledImg, &image);
2846 RReleaseImage(scaledImg);
2848 XCopyArea(scr->display, image, panel->customPaletteContentView->window,
2849 scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2851 /* Check backimage exists. If it doesn't, allocate and fill it */
2852 if (!panel->selectionBackImg) {
2853 panel->selectionBackImg = XCreatePixmap(scr->display,
2854 panel->customPaletteContentView->window, 4, 4, scr->depth);
2857 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
2858 panel->palx - 2, panel->paly - 2, 4, 4, 0, 0);
2859 XCopyArea(scr->display, panel->selectionImg,
2860 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2861 panel->palx - 2, panel->paly - 2);
2862 XFreePixmap(scr->display, image);
2864 panel->palXRatio = (double)(panel->customPaletteImg->width) / (double)(customPaletteWidth);
2865 panel->palYRatio = (double)(panel->customPaletteImg->height) / (double)(customPaletteHeight);
2868 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y)
2870 W_Screen *scr = WMWidgetScreen(panel->win);
2871 unsigned long ofs;
2873 /* undraw selection */
2874 XCopyArea(scr->display, panel->selectionBackImg,
2875 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2876 panel->palx - 2, panel->paly - 2);
2878 panel->palx = x;
2879 panel->paly = y;
2881 ofs = (rint(x * panel->palXRatio) + rint(y * panel->palYRatio) * panel->customPaletteImg->width) * 3;
2883 panel->color.rgb.red = panel->customPaletteImg->data[ofs];
2884 panel->color.rgb.green = panel->customPaletteImg->data[ofs + 1];
2885 panel->color.rgb.blue = panel->customPaletteImg->data[ofs + 2];
2886 panel->color.set = cpRGB;
2888 updateSwatch(panel, panel->color);
2889 panel->lastChanged = WMCustomPaletteModeColorPanel;
2891 /* Redraw color selector (and make a backup of the part it will cover) */
2892 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 */
2893 XCopyArea(scr->display, panel->selectionImg, panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4, panel->palx - 2, panel->paly - 2); /* see above */
2896 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2898 if (x < 2)
2899 x = 2;
2900 if (y < 2)
2901 y = 2;
2902 if (x >= customPaletteWidth)
2903 x = customPaletteWidth - 2;
2904 if (y >= customPaletteHeight)
2905 y = customPaletteHeight - 2;
2907 customPalettePositionSelection(panel, x, y);
2910 static void customPaletteHandleEvents(XEvent * event, void *data)
2912 W_ColorPanel *panel = (W_ColorPanel *) data;
2914 switch (event->type) {
2915 case Expose:
2916 if (event->xexpose.count != 0) /* TODO Improve. */
2917 break;
2918 customSetPalette(panel);
2919 break;
2923 static void customPaletteHandleActionEvents(XEvent * event, void *data)
2925 W_ColorPanel *panel = (W_ColorPanel *) data;
2926 int x, y;
2928 switch (event->type) {
2929 case ButtonPress:
2930 x = event->xbutton.x;
2931 y = event->xbutton.y;
2933 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2934 panel->flags.dragging = 1;
2935 customPalettePositionSelection(panel, x, y);
2937 break;
2939 case ButtonRelease:
2940 panel->flags.dragging = 0;
2941 if (!panel->flags.continuous) {
2942 if (panel->action)
2943 (*panel->action) (panel, panel->clientData);
2945 break;
2947 case MotionNotify:
2948 x = event->xmotion.x;
2949 y = event->xmotion.y;
2951 if (panel->flags.dragging) {
2952 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2953 customPalettePositionSelection(panel, x, y);
2954 } else
2955 customPalettePositionSelectionOutBounds(panel, x, y);
2957 break;
2961 static void customPaletteMenuCallback(WMWidget * w, void *data)
2963 W_ColorPanel *panel = (W_ColorPanel *) data;
2964 int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
2966 /* Parameter not used, but tell the compiler that it is ok */
2967 (void) w;
2969 switch (item) {
2970 case CPmenuNewFromFile:
2971 customPaletteMenuNewFromFile(panel);
2972 break;
2973 case CPmenuRename:
2974 customPaletteMenuRename(panel);
2975 break;
2976 case CPmenuRemove:
2977 customPaletteMenuRemove(panel);
2978 break;
2979 case CPmenuCopy:
2980 break;
2981 case CPmenuNewFromClipboard:
2982 break;
2986 static void customPaletteMenuNewFromFile(W_ColorPanel * panel)
2988 W_Screen *scr = WMWidgetScreen(panel->win);
2989 WMOpenPanel *browseP;
2990 char *filepath;
2991 char *filename = NULL;
2992 char *spath;
2993 char *tmp;
2994 int i;
2995 RImage *tmpImg = NULL;
2997 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir, "\0") == 0))
2998 spath = wexpandpath(wgethomedir());
2999 else
3000 spath = wexpandpath(panel->lastBrowseDir);
3002 browseP = WMGetOpenPanel(scr);
3003 WMSetFilePanelCanChooseDirectories(browseP, 0);
3004 WMSetFilePanelCanChooseFiles(browseP, 1);
3006 /* Get a filename */
3007 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
3008 _("Open Palette"), RSupportedFileFormats())) {
3009 filepath = WMGetFilePanelFileName(browseP);
3011 /* Get seperation position between path and filename */
3012 i = strrchr(filepath, '/') - filepath + 1;
3013 if (i > strlen(filepath))
3014 i = strlen(filepath);
3016 /* Store last browsed path */
3017 if (panel->lastBrowseDir)
3018 wfree(panel->lastBrowseDir);
3019 panel->lastBrowseDir = wmalloc((i + 1) * sizeof(char));
3020 strncpy(panel->lastBrowseDir, filepath, i);
3021 panel->lastBrowseDir[i] = '\0';
3023 /* Get filename from path */
3024 filename = wstrdup(filepath + i);
3026 /* Check for duplicate files, and rename it if there are any */
3027 tmp = wstrconcat(panel->configurationPath, filename);
3028 while (access(tmp, F_OK) == 0) {
3029 char *newName;
3031 wfree(tmp);
3033 newName = generateNewFilename(filename);
3034 wfree(filename);
3035 filename = newName;
3037 tmp = wstrconcat(panel->configurationPath, filename);
3039 wfree(tmp);
3041 /* Copy image to $(gnustepdir)/Library/Colors/ &
3042 * Add filename to history menu */
3043 if (wcopy_file(panel->configurationPath, filepath, filename) == 0) {
3045 /* filepath is a "local" path now the file has been copied */
3046 wfree(filepath);
3047 filepath = wstrconcat(panel->configurationPath, filename);
3049 /* load the image & add menu entries */
3050 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
3051 if (tmpImg) {
3052 if (panel->customPaletteImg)
3053 RReleaseImage(panel->customPaletteImg);
3054 panel->customPaletteImg = tmpImg;
3056 customSetPalette(panel);
3057 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
3059 panel->currentPalette =
3060 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1;
3062 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3063 panel->currentPalette);
3065 } else {
3066 tmp = wstrconcat(panel->configurationPath, filename);
3068 i = remove(tmp); /* Delete the file, it doesn't belong here */
3069 WMRunAlertPanel(scr, panel->win, _("File Error"),
3070 _("Invalid file format !"), _("OK"), NULL, NULL);
3071 if (i != 0) {
3072 werror(_("can't remove file %s"), tmp);
3073 WMRunAlertPanel(scr, panel->win, _("File Error"),
3074 _("Couldn't remove file from Configuration Directory !"),
3075 _("OK"), NULL, NULL);
3077 wfree(tmp);
3079 wfree(filepath);
3080 wfree(filename);
3082 WMFreeFilePanel(browseP);
3084 wfree(spath);
3087 static void customPaletteMenuRename(W_ColorPanel * panel)
3089 W_Screen *scr = WMWidgetScreen(panel->win);
3090 char *toName = NULL;
3091 char *fromName;
3092 char *toPath, *fromPath;
3093 int item;
3094 int index;
3096 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3097 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
3099 toName = WMRunInputPanel(scr, panel->win, _("Rename"), _("Rename palette to:"),
3100 fromName, _("OK"), _("Cancel"));
3102 if (toName) {
3104 /* As some people do certain stupid things... */
3105 if (strcmp(toName, fromName) == 0) {
3106 wfree(toName);
3107 return;
3110 /* For normal people */
3111 fromPath = wstrconcat(panel->configurationPath, fromName);
3112 toPath = wstrconcat(panel->configurationPath, toName);
3114 if (access(toPath, F_OK) == 0) {
3115 /* Careful, this palette exists already */
3116 if (WMRunAlertPanel(scr, panel->win, _("Warning"),
3117 _("Palette already exists !\n\nOverwrite ?"), _("No"), _("Yes"),
3118 NULL) == 1) {
3119 /* "No" = 0, "Yes" = 1 */
3120 int items = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
3122 remove(toPath);
3124 /* Remove from History list too */
3125 index = 1;
3126 while ((index < items)
3128 (strcmp(WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, index), toName)
3129 != 0))
3130 index++;
3132 if (index < items) {
3133 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, index);
3134 if (index < item)
3135 item--;
3138 } else {
3139 wfree(fromPath);
3140 wfree(toName);
3141 wfree(toPath);
3143 return;
3147 if (rename(fromPath, toPath) != 0)
3148 werror(_("Couldn't rename palette %s to %s"), fromName, toName);
3149 else {
3150 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3151 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item, toName);
3153 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
3155 wfree(fromPath);
3156 wfree(toPath);
3157 wfree(toName);
3161 static void customPaletteMenuRemove(W_ColorPanel * panel)
3163 W_Screen *scr = WMWidgetScreen(panel->win);
3164 char *text;
3165 char *tmp;
3166 int choice;
3167 int item;
3169 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3171 tmp = wstrconcat(_("This will permanently remove the palette "),
3172 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3173 text = wstrconcat(tmp, _(".\n\nAre you sure you want to remove this palette ?"));
3174 wfree(tmp);
3176 choice = WMRunAlertPanel(scr, panel->win, _("Remove"), text, _("Yes"), _("No"), NULL);
3177 /* returns 0 (= "Yes") or 1 (="No") */
3178 wfree(text);
3180 if (choice == 0) {
3182 tmp = wstrconcat(panel->configurationPath,
3183 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3185 if (remove(tmp) == 0) {
3186 /* item-1 always exists */
3187 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3189 customPaletteHistoryCallback(panel->customPaletteHistoryBtn, panel);
3190 customSetPalette(panel);
3192 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3194 } else {
3195 werror(_("Couldn't remove palette %s"), tmp);
3198 wfree(tmp);
3202 static void customPaletteHistoryCallback(WMWidget * w, void *data)
3204 W_ColorPanel *panel = (W_ColorPanel *) data;
3205 W_Screen *scr = WMWidgetScreen(panel->win);
3206 int item;
3207 char *filename;
3208 RImage *tmp = NULL;
3209 unsigned char perm_mask;
3211 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3212 if (item == panel->currentPalette)
3213 return;
3215 if (item == 0) {
3216 customRenderSpectrum(panel);
3218 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, False);
3219 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, False);
3220 } else {
3221 /* Load file from configpath */
3222 filename = wstrconcat(panel->configurationPath,
3223 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3225 /* If the file corresponding to the item does not exist,
3226 * remove it from the history list and select the next one.
3228 perm_mask = (access(filename, F_OK) == 0);
3229 if (!perm_mask) {
3230 /* File does not exist */
3231 wfree(filename);
3232 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3233 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3234 customPaletteHistoryCallback(w, data);
3235 return;
3238 /* Get the image */
3239 tmp = RLoadImage(scr->rcontext, filename, 0);
3240 if (tmp) {
3241 if (panel->customPaletteImg) {
3242 RReleaseImage(panel->customPaletteImg);
3243 panel->customPaletteImg = NULL;
3245 panel->customPaletteImg = tmp;
3248 /* If the image is not writable, don't allow removing/renaming */
3249 perm_mask = (access(filename, W_OK) == 0);
3250 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, perm_mask);
3251 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, perm_mask);
3253 wfree(filename);
3255 customSetPalette(panel);
3257 panel->currentPalette = item;
3260 /************************* ColorList Panel Functions **********************/
3262 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect)
3264 WMScreen *scr = WMWidgetScreen(lPtr);
3265 Display *dpy = WMScreenDisplay(scr);
3266 WMView *view = W_VIEW(lPtr);
3267 RColor *color = (RColor *) WMGetListItem(lPtr, index)->clientData;
3268 W_ColorPanel *panel = WMGetHangedData(lPtr);
3269 int width, height, x, y;
3270 WMColor *fillColor;
3272 width = rect->size.width;
3273 height = rect->size.height;
3274 x = rect->pos.x;
3275 y = rect->pos.y;
3277 if (state & WLDSSelected)
3278 XFillRectangle(dpy, d, WMColorGC(scr->white), x, y, width, height);
3279 else
3280 XFillRectangle(dpy, d, WMColorGC(view->backColor), x, y, width, height);
3282 fillColor = WMCreateRGBColor(scr, color->red << 8, color->green << 8, color->blue << 8, True);
3284 XFillRectangle(dpy, d, WMColorGC(fillColor), x, y, 15, height);
3285 WMReleaseColor(fillColor);
3287 WMDrawString(scr, d, scr->black, panel->font12, x + 18, y, text, strlen(text));
3290 static void colorListSelect(WMWidget * w, void *data)
3292 W_ColorPanel *panel = (W_ColorPanel *) data;
3293 CPColor cpColor;
3295 cpColor.rgb = *((RColor *) WMGetListSelectedItem(w)->clientData);
3296 cpColor.set = cpRGB;
3298 panel->lastChanged = WMColorListModeColorPanel;
3299 updateSwatch(panel, cpColor);
3302 static void colorListColorMenuCallback(WMWidget * w, void *data)
3304 W_ColorPanel *panel = (W_ColorPanel *) data;
3305 int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
3307 /* Parameter not used, but tell the compiler that it is ok */
3308 (void) w;
3310 switch (item) {
3311 case CLmenuAdd:
3312 break;
3313 case CLmenuRename:
3314 break;
3315 case CLmenuRemove:
3316 break;
3320 static void colorListListMenuCallback(WMWidget * w, void *data)
3322 W_ColorPanel *panel = (W_ColorPanel *) data;
3323 int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
3325 /* Parameter not used, but tell the compiler that it is ok */
3326 (void) w;
3328 switch (item) {
3329 case CLmenuAdd:
3330 break;
3331 case CLmenuRename:
3332 break;
3333 case CLmenuRemove:
3334 break;
3338 /*************** Panel Initialisation Functions *****************/
3340 static void wheelInit(W_ColorPanel * panel)
3342 CPColor cpColor;
3344 if (panel->color.set != cpHSV)
3345 convertCPColor(&panel->color);
3347 WMSetSliderValue(panel->wheelBrightnessS, 255 - panel->color.hsv.value);
3349 panel->colx = 2 + rint((colorWheelSize / 2.0) *
3350 (1 + (panel->color.hsv.saturation / 255.0) *
3351 cos(panel->color.hsv.hue * WM_PI / 180.0)));
3352 panel->coly = 2 + rint((colorWheelSize / 2.0) *
3353 (1 + (panel->color.hsv.saturation / 255.0) *
3354 sin(-panel->color.hsv.hue * WM_PI / 180.0)));
3356 wheelCalculateValues(panel, panel->color.hsv.value);
3358 cpColor = panel->color;
3359 cpColor.hsv.value = 255;
3360 cpColor.set = cpHSV;
3361 wheelUpdateBrightnessGradient(panel, cpColor);
3364 static void grayInit(W_ColorPanel * panel)
3366 int value;
3367 char tmp[4];
3369 if (panel->color.set != cpHSV)
3370 convertCPColor(&panel->color);
3372 value = rint(panel->color.hsv.value / 2.55);
3373 WMSetSliderValue(panel->grayBrightnessS, value);
3375 sprintf(tmp, "%d", value);
3376 WMSetTextFieldText(panel->grayBrightnessT, tmp);
3379 static void rgbInit(W_ColorPanel * panel)
3381 char tmp[4];
3382 const char *format;
3384 if (panel->color.set != cpRGB)
3385 convertCPColor(&panel->color);
3387 WMSetSliderValue(panel->rgbRedS, panel->color.rgb.red);
3388 WMSetSliderValue(panel->rgbGreenS, panel->color.rgb.green);
3389 WMSetSliderValue(panel->rgbBlueS, panel->color.rgb.blue);
3391 switch (panel->rgbState) {
3392 case RGBdec:
3393 format = "%d";
3394 break;
3395 case RGBhex:
3396 format = "%0X";
3397 break;
3398 default:
3399 /* Avoid compiler warning */
3400 format = "";
3403 sprintf(tmp, format, panel->color.rgb.red);
3404 WMSetTextFieldText(panel->rgbRedT, tmp);
3405 sprintf(tmp, format, panel->color.rgb.green);
3406 WMSetTextFieldText(panel->rgbGreenT, tmp);
3407 sprintf(tmp, format, panel->color.rgb.blue);
3408 WMSetTextFieldText(panel->rgbBlueT, tmp);
3411 static void cmykInit(W_ColorPanel * panel)
3413 int value[3];
3414 char tmp[4];
3416 if (panel->color.set != cpRGB)
3417 convertCPColor(&panel->color);
3419 value[0] = rint((255 - panel->color.rgb.red) / 2.55);
3420 value[1] = rint((255 - panel->color.rgb.green) / 2.55);
3421 value[2] = rint((255 - panel->color.rgb.blue) / 2.55);
3423 WMSetSliderValue(panel->cmykCyanS, value[0]);
3424 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3425 WMSetSliderValue(panel->cmykYellowS, value[2]);
3426 WMSetSliderValue(panel->cmykBlackS, 0);
3428 sprintf(tmp, "%d", value[0]);
3429 WMSetTextFieldText(panel->cmykCyanT, tmp);
3430 sprintf(tmp, "%d", value[1]);
3431 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3432 sprintf(tmp, "%d", value[2]);
3433 WMSetTextFieldText(panel->cmykYellowT, tmp);
3434 WMSetTextFieldText(panel->cmykBlackT, "0");
3437 static void hsbInit(W_ColorPanel * panel)
3439 int value[3];
3440 char tmp[4];
3442 if (panel->color.set != cpHSV)
3443 convertCPColor(&panel->color);
3445 value[0] = panel->color.hsv.hue;
3446 value[1] = rint(panel->color.hsv.saturation / 2.55);
3447 value[2] = rint(panel->color.hsv.value / 2.55);
3449 WMSetSliderValue(panel->hsbHueS, value[0]);
3450 WMSetSliderValue(panel->hsbSaturationS, value[1]);
3451 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
3453 sprintf(tmp, "%hu", value[0]);
3454 WMSetTextFieldText(panel->hsbHueT, tmp);
3455 sprintf(tmp, "%d", value[1]);
3456 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3457 sprintf(tmp, "%d", value[2]);
3458 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3460 hsbUpdateBrightnessGradient(panel);
3461 hsbUpdateSaturationGradient(panel);
3462 hsbUpdateHueGradient(panel);
3465 /************************** Common utility functions ************************/
3467 static char *generateNewFilename(const char *curName)
3469 int n;
3470 char c;
3471 int baseLen;
3472 const char *ptr;
3473 char *newName;
3475 assert(curName);
3477 ptr = curName;
3479 if (((ptr = strrchr(ptr, '{')) == 0) || sscanf(ptr, "{%i}%c", &n, &c) != 1)
3480 return wstrconcat(curName, " {1}");
3482 baseLen = ptr - curName - 1;
3484 newName = wmalloc(baseLen + 16);
3485 strncpy(newName, curName, baseLen);
3487 snprintf(&newName[baseLen], 16, " {%i}", n + 1);
3489 return newName;
3492 static void convertCPColor(CPColor * color)
3494 unsigned short old_hue = 0;
3496 switch (color->set) {
3497 case cpNone:
3498 wwarning(_("Color Panel: Color unspecified"));
3499 return;
3500 case cpRGB:
3501 old_hue = color->hsv.hue;
3502 RRGBtoHSV(&(color->rgb), &(color->hsv));
3505 * For pure grey colors, the Hue is generally calculated
3506 * as 0, but in reality the Hue does not matter.
3508 * But in an interactive GUI it is interresting to remember
3509 * the previous Hue because if user moves away from perfect
3510 * grey then he could be interrested in finding back his
3511 * previous tint
3513 if ((color->rgb.red == color->rgb.green) &&
3514 (color->rgb.red == color->rgb.blue) )
3515 color->hsv.hue = old_hue;
3516 break;
3517 case cpHSV:
3518 RHSVtoRGB(&(color->hsv), &(color->rgb));
3519 break;
3523 static RColor ulongToRColor(WMScreen * scr, unsigned long value)
3525 RColor color;
3526 XColor *xcolor = NULL;
3528 xcolor = wmalloc(sizeof(XColor));
3529 xcolor->pixel = value;
3530 XQueryColor(scr->display, scr->rcontext->cmap, xcolor);
3532 color.red = xcolor->red >> 8;
3533 color.green = xcolor->green >> 8;
3534 color.blue = xcolor->blue >> 8;
3535 color.alpha = 0;
3537 wfree(xcolor);
3539 return color;
3542 static unsigned char getShift(unsigned char value)
3544 unsigned char i = -1;
3546 if (value == 0)
3547 return 0;
3549 while (value) {
3550 value >>= 1;
3551 i++;
3554 return i;