menu: For consistency, use appearance.menu for English-language menus.
[wmaker-crm.git] / WINGs / wcolorpanel.c
blob2cd180653a508cb849b37595e9c8f6de2ec46999
1 /*
2 * ColorPanel for WINGs
4 * by ]d : Original idea and basic initial code
5 * Pascal Hofstee : Code for wheeldrawing and calculating
6 * colors from it.
7 * Primary coder of this Color Panel.
8 * Alban Hertroys : Optimizations for algorithms for color-
9 * wheel. Also custom ColorPalettes and
10 * magnifying glass. Secondary coder ;)
11 * Alfredo K. Kojima : For pointing out memory-allocation
12 * problems and similair code-issues
13 * Marco van Hylckama-Vlieg : For once again doing the artwork ;-)
17 /* TODO:
18 * - Look at further optimization of colorWheel matrix calculation.
19 * It appears to be rather symmetric in angles of 60 degrees,
20 * while it is optimized in angles of 90 degrees.
21 * - Custom color-lists and custom colors in custom color-lists.
22 * - Stored colors
23 * - Resizing
26 #include "wconfig.h"
27 #include "WINGsP.h"
28 #include "rgb.h"
30 #include <errno.h>
31 #include <math.h>
32 #include <unistd.h>
33 #include <ctype.h>
34 #include <fcntl.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <dirent.h>
40 /* BUG There's something fishy with shaped windows */
41 /* Whithout shape extension the magnified image is completely broken -Dan */
43 #ifdef USE_XSHAPE
44 # include <X11/extensions/shape.h>
45 #endif
47 char *WMColorPanelColorChangedNotification = "WMColorPanelColorChangedNotification";
50 * Bitmaps for magnifying glass cursor
53 /* Cursor */
54 #define Cursor_x_hot 11
55 #define Cursor_y_hot 11
56 #define Cursor_width 32
57 #define Cursor_height 32
58 static unsigned char Cursor_bits[] = {
59 0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
60 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
61 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
62 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
63 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
64 0x00, 0x08, 0x00, 0x50, 0x00, 0x10, 0x00, 0x88, 0x00, 0x20, 0x00, 0x5c, 0x01, 0xc0, 0x81,
65 0x3b, 0x02, 0x00, 0x7e, 0x70, 0x05, 0x00, 0x00, 0xe0, 0x08, 0x00, 0x00, 0xc0, 0x15, 0x00,
66 0x00, 0x80, 0x23, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x5c,
67 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x70
70 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(wusergnusteppath(), "/Library/Colors/");
399 /* Some General Purpose Widgets */
400 panel->colorWell = WMCreateColorWell(panel->win);
401 WMResizeWidget(panel->colorWell, 134, 36);
402 WSetColorWellBordered(panel->colorWell, False);
403 WMMoveWidget(panel->colorWell, 56, 4);
405 panel->magnifyBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
406 WMResizeWidget(panel->magnifyBtn, 46, 36);
407 WMMoveWidget(panel->magnifyBtn, 6, 4);
408 WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
409 WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
410 WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
412 panel->wheelBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
413 WMResizeWidget(panel->wheelBtn, 46, 32);
414 WMMoveWidget(panel->wheelBtn, 6, 44);
415 WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
416 WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
417 WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
419 panel->slidersBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
420 WMResizeWidget(panel->slidersBtn, 46, 32);
421 WMMoveWidget(panel->slidersBtn, 52, 44);
422 WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
423 WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
424 WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
426 panel->customPaletteBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
427 WMResizeWidget(panel->customPaletteBtn, 46, 32);
428 WMMoveWidget(panel->customPaletteBtn, 98, 44);
429 WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
430 WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
431 WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
433 panel->colorListBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
434 WMResizeWidget(panel->colorListBtn, 46, 32);
435 WMMoveWidget(panel->colorListBtn, 144, 44);
436 WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
437 WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
438 WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
440 /* Let's Group some of them together */
441 WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
442 WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
443 WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
445 /* Widgets for the ColorWheel Panel */
446 panel->wheelFrm = WMCreateFrame(panel->win);
447 WMSetFrameRelief(panel->wheelFrm, WRFlat);
448 WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
449 WMMoveWidget(panel->wheelFrm, 5, 80);
451 panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
452 /* XXX Can we create a view ? */
453 W_ResizeView(panel->wheelView, colorWheelSize + 4, colorWheelSize + 4);
454 W_MoveView(panel->wheelView, 0, 0);
456 /* Create an event handler to handle expose/click events in ColorWheel */
457 WMCreateEventHandler(panel->wheelView,
458 ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
459 LeaveWindowMask | ButtonMotionMask, wheelHandleActionEvents, panel);
461 WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents, panel);
463 panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
464 WMResizeWidget(panel->wheelBrightnessS, 16, 153);
465 WMMoveWidget(panel->wheelBrightnessS, 5 + colorWheelSize + 14, 1);
466 WMSetSliderMinValue(panel->wheelBrightnessS, 0);
467 WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
468 WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback, panel);
469 WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
471 panel->wheelMtrx = wheelCreateMatrix(colorWheelSize + 4, colorWheelSize + 4);
472 wheelInitMatrix(panel);
474 /* Widgets for the Slider Panels */
475 panel->slidersFrm = WMCreateFrame(panel->win);
476 WMSetFrameRelief(panel->slidersFrm, WRFlat);
477 WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
478 WMMoveWidget(panel->slidersFrm, 4, 80);
480 panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
481 WMSetFrameRelief(panel->seperatorFrm, WRPushed);
482 WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
483 WMMoveWidget(panel->seperatorFrm, 0, 1);
485 panel->grayBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
486 WMResizeWidget(panel->grayBtn, 46, 24);
487 WMMoveWidget(panel->grayBtn, 1, 8);
488 WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
489 WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
490 WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
492 panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
493 WMResizeWidget(panel->rgbBtn, 46, 24);
494 WMMoveWidget(panel->rgbBtn, 47, 8);
495 WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
496 WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
497 WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
499 panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
500 WMResizeWidget(panel->cmykBtn, 46, 24);
501 WMMoveWidget(panel->cmykBtn, 93, 8);
502 WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
503 WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
504 WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
506 panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
507 WMResizeWidget(panel->hsbBtn, 46, 24);
508 WMMoveWidget(panel->hsbBtn, 139, 8);
509 WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
510 WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
511 WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
513 /* Let's Group the Slider Panel Buttons Together */
514 WMGroupButtons(panel->grayBtn, panel->rgbBtn);
515 WMGroupButtons(panel->grayBtn, panel->cmykBtn);
516 WMGroupButtons(panel->grayBtn, panel->hsbBtn);
518 textcolor = WMDarkGrayColor(scrPtr);
520 /* Widgets for GrayScale Panel */
521 panel->grayFrm = WMCreateFrame(panel->slidersFrm);
522 WMSetFrameRelief(panel->grayFrm, WRFlat);
523 WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
524 WMMoveWidget(panel->grayFrm, 0, 34);
526 panel->grayMinL = WMCreateLabel(panel->grayFrm);
527 WMResizeWidget(panel->grayMinL, 20, 10);
528 WMMoveWidget(panel->grayMinL, 2, 2);
529 WMSetLabelText(panel->grayMinL, "0");
530 WMSetLabelTextAlignment(panel->grayMinL, WALeft);
531 WMSetLabelTextColor(panel->grayMinL, textcolor);
532 WMSetLabelFont(panel->grayMinL, panel->font8);
534 panel->grayMaxL = WMCreateLabel(panel->grayFrm);
535 WMResizeWidget(panel->grayMaxL, 40, 10);
536 WMMoveWidget(panel->grayMaxL, 104, 2);
537 WMSetLabelText(panel->grayMaxL, "100");
538 WMSetLabelTextAlignment(panel->grayMaxL, WARight);
539 WMSetLabelTextColor(panel->grayMaxL, textcolor);
540 WMSetLabelFont(panel->grayMaxL, panel->font8);
542 panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
543 WMResizeWidget(panel->grayBrightnessS, 141, 16);
544 WMMoveWidget(panel->grayBrightnessS, 2, 14);
545 WMSetSliderMinValue(panel->grayBrightnessS, 0);
546 WMSetSliderMaxValue(panel->grayBrightnessS, 100);
547 WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
548 WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback, panel);
550 from.red = 0;
551 from.green = 0;
552 from.blue = 0;
554 to.red = 255;
555 to.green = 255;
556 to.blue = 255;
558 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
559 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
560 RReleaseImage(image);
562 if (pixmap)
563 W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap,
564 panel->font12, 2, 0, 100, WALeft, scrPtr->white,
565 False, _("Brightness"), strlen(_("Brightness")));
566 else
567 wwarning(_("Color Panel: Could not allocate memory"));
569 WMSetSliderImage(panel->grayBrightnessS, pixmap);
570 WMReleasePixmap(pixmap);
572 panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
573 WMResizeWidget(panel->grayBrightnessT, 40, 18);
574 WMMoveWidget(panel->grayBrightnessT, 146, 13);
575 WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
576 WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel,
577 WMTextDidEndEditingNotification, panel->grayBrightnessT);
579 for (i = 0; i < 7; i++) {
580 pixmap = WMCreatePixmap(scrPtr, 13, 13, scrPtr->depth, False);
582 graybuttoncolor = WMCreateRGBColor(scrPtr, (255 / 6) * i << 8,
583 (255 / 6) * i << 8, (255 / 6) * i << 8, True);
584 WMPaintColorSwatch(graybuttoncolor, pixmap->pixmap, 0, 0, 15, 15);
585 WMReleaseColor(graybuttoncolor);
587 panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
588 WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
589 WMMoveWidget(panel->grayPresetBtn[i], 2 + (i * 20), 34);
590 WMSetButtonAction(panel->grayPresetBtn[i], grayPresetButtonCallback, panel);
591 WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
592 WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
593 WMReleasePixmap(pixmap);
597 /* End of GrayScale Panel */
599 /* Widgets for RGB Panel */
600 panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
601 WMSetFrameRelief(panel->rgbFrm, WRFlat);
602 WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
603 WMMoveWidget(panel->rgbFrm, 0, 34);
605 panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
606 WMResizeWidget(panel->rgbMinL, 20, 10);
607 WMMoveWidget(panel->rgbMinL, 2, 2);
608 WMSetLabelText(panel->rgbMinL, "0");
609 WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
610 WMSetLabelTextColor(panel->rgbMinL, textcolor);
611 WMSetLabelFont(panel->rgbMinL, panel->font8);
613 panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
614 WMResizeWidget(panel->rgbMaxL, 40, 10);
615 WMMoveWidget(panel->rgbMaxL, 104, 2);
616 WMSetLabelText(panel->rgbMaxL, "255");
617 WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
618 WMSetLabelTextColor(panel->rgbMaxL, textcolor);
619 WMSetLabelFont(panel->rgbMaxL, panel->font8);
621 panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
622 WMResizeWidget(panel->rgbRedS, 141, 16);
623 WMMoveWidget(panel->rgbRedS, 2, 14);
624 WMSetSliderMinValue(panel->rgbRedS, 0);
625 WMSetSliderMaxValue(panel->rgbRedS, 255);
626 WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
627 WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
629 to.red = 255;
630 to.green = 0;
631 to.blue = 0;
633 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
634 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
635 RReleaseImage(image);
637 if (pixmap)
638 W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12,
639 2, 0, 100, WALeft, scrPtr->white, False, _("Red"), strlen(_("Red")));
640 else
641 wwarning(_("Color Panel: Could not allocate memory"));
643 WMSetSliderImage(panel->rgbRedS, pixmap);
644 WMReleasePixmap(pixmap);
646 panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
647 WMResizeWidget(panel->rgbRedT, 40, 18);
648 WMMoveWidget(panel->rgbRedT, 146, 13);
649 WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
650 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbRedT);
652 panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
653 WMResizeWidget(panel->rgbGreenS, 141, 16);
654 WMMoveWidget(panel->rgbGreenS, 2, 36);
655 WMSetSliderMinValue(panel->rgbGreenS, 0);
656 WMSetSliderMaxValue(panel->rgbGreenS, 255);
657 WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
658 WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
660 to.red = 0;
661 to.green = 255;
662 to.blue = 0;
664 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
665 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
666 RReleaseImage(image);
668 if (pixmap)
669 W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12,
670 2, 0, 100, WALeft, scrPtr->white, False, _("Green"), strlen(_("Green")));
671 else
672 wwarning(_("Color Panel: Could not allocate memory"));
674 WMSetSliderImage(panel->rgbGreenS, pixmap);
675 WMReleasePixmap(pixmap);
677 panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
678 WMResizeWidget(panel->rgbGreenT, 40, 18);
679 WMMoveWidget(panel->rgbGreenT, 146, 35);
680 WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
681 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbGreenT);
683 panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
684 WMResizeWidget(panel->rgbBlueS, 141, 16);
685 WMMoveWidget(panel->rgbBlueS, 2, 58);
686 WMSetSliderMinValue(panel->rgbBlueS, 0);
687 WMSetSliderMaxValue(panel->rgbBlueS, 255);
688 WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
689 WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
691 to.red = 0;
692 to.green = 0;
693 to.blue = 255;
695 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
696 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
697 RReleaseImage(image);
699 if (pixmap)
700 W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12,
701 2, 0, 100, WALeft, scrPtr->white, False, _("Blue"), strlen(_("Blue")));
702 else
703 wwarning(_("Color Panel: Could not allocate memory"));
705 WMSetSliderImage(panel->rgbBlueS, pixmap);
706 WMReleasePixmap(pixmap);
708 panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
709 WMResizeWidget(panel->rgbBlueT, 40, 18);
710 WMMoveWidget(panel->rgbBlueT, 146, 57);
711 WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
712 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbBlueT);
714 panel->rgbDecB = WMCreateButton(panel->rgbFrm, WBTRadio);
715 WMSetButtonText(panel->rgbDecB, _("Decimal"));
716 WMSetButtonSelected(panel->rgbDecB, 1);
717 panel->rgbState = RGBdec;
718 WMSetButtonAction(panel->rgbDecB, rgbDecToHex, panel);
719 WMResizeWidget(panel->rgbDecB, PWIDTH - 8, 23);
720 WMMoveWidget(panel->rgbDecB, 2, 81);
722 panel->rgbHexB = WMCreateButton(panel->rgbFrm, WBTRadio);
723 WMSetButtonText(panel->rgbHexB, _("Hexadecimal"));
724 WMSetButtonAction(panel->rgbHexB, rgbDecToHex, panel);
725 WMResizeWidget(panel->rgbHexB, PWIDTH - 8, 23);
726 WMMoveWidget(panel->rgbHexB, 2, 104);
728 WMGroupButtons(panel->rgbDecB, panel->rgbHexB);
730 /* End of RGB Panel */
732 /* Widgets for CMYK Panel */
733 panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
734 WMSetFrameRelief(panel->cmykFrm, WRFlat);
735 WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
736 WMMoveWidget(panel->cmykFrm, 0, 34);
738 panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
739 WMResizeWidget(panel->cmykMinL, 20, 10);
740 WMMoveWidget(panel->cmykMinL, 2, 2);
741 WMSetLabelText(panel->cmykMinL, "0");
742 WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
743 WMSetLabelTextColor(panel->cmykMinL, textcolor);
744 WMSetLabelFont(panel->cmykMinL, panel->font8);
746 panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
747 WMResizeWidget(panel->cmykMaxL, 40, 10);
748 WMMoveWidget(panel->cmykMaxL, 104, 2);
749 WMSetLabelText(panel->cmykMaxL, "100");
750 WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
751 WMSetLabelTextColor(panel->cmykMaxL, textcolor);
752 WMSetLabelFont(panel->cmykMaxL, panel->font8);
754 panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
755 WMResizeWidget(panel->cmykCyanS, 141, 16);
756 WMMoveWidget(panel->cmykCyanS, 2, 14);
757 WMSetSliderMinValue(panel->cmykCyanS, 0);
758 WMSetSliderMaxValue(panel->cmykCyanS, 100);
759 WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
760 WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
762 from.red = 255;
763 from.green = 255;
764 from.blue = 255;
766 to.red = 0;
767 to.green = 255;
768 to.blue = 255;
770 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
771 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
772 RReleaseImage(image);
774 if (pixmap)
775 W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12,
776 2, 0, 100, WALeft, scrPtr->black, False, _("Cyan"), strlen(_("Cyan")));
777 else
778 wwarning(_("Color Panel: Could not allocate memory"));
780 WMSetSliderImage(panel->cmykCyanS, pixmap);
781 WMReleasePixmap(pixmap);
783 panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
784 WMResizeWidget(panel->cmykCyanT, 40, 18);
785 WMMoveWidget(panel->cmykCyanT, 146, 13);
786 WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
787 WMAddNotificationObserver(cmykTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->cmykCyanT);
789 panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
790 WMResizeWidget(panel->cmykMagentaS, 141, 16);
791 WMMoveWidget(panel->cmykMagentaS, 2, 36);
792 WMSetSliderMinValue(panel->cmykMagentaS, 0);
793 WMSetSliderMaxValue(panel->cmykMagentaS, 100);
794 WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
795 WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
797 to.red = 255;
798 to.green = 0;
799 to.blue = 255;
801 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
802 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
803 RReleaseImage(image);
805 if (pixmap)
806 W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12,
807 2, 0, 100, WALeft, scrPtr->black, False, _("Magenta"), strlen(_("Magenta")));
808 else
809 wwarning(_("Color Panel: Could not allocate memory"));
811 WMSetSliderImage(panel->cmykMagentaS, pixmap);
812 WMReleasePixmap(pixmap);
814 panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
815 WMResizeWidget(panel->cmykMagentaT, 40, 18);
816 WMMoveWidget(panel->cmykMagentaT, 146, 35);
817 WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
818 WMAddNotificationObserver(cmykTextFieldCallback, panel,
819 WMTextDidEndEditingNotification, panel->cmykMagentaT);
821 panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
822 WMResizeWidget(panel->cmykYellowS, 141, 16);
823 WMMoveWidget(panel->cmykYellowS, 2, 58);
824 WMSetSliderMinValue(panel->cmykYellowS, 0);
825 WMSetSliderMaxValue(panel->cmykYellowS, 100);
826 WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
827 WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
829 to.red = 255;
830 to.green = 255;
831 to.blue = 0;
833 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
834 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
835 RReleaseImage(image);
837 if (pixmap)
838 W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12,
839 2, 0, 100, WALeft, scrPtr->black, False, _("Yellow"), strlen(_("Yellow")));
840 else
841 wwarning(_("Color Panel: Could not allocate memory"));
843 WMSetSliderImage(panel->cmykYellowS, pixmap);
844 WMReleasePixmap(pixmap);
846 panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
847 WMResizeWidget(panel->cmykYellowT, 40, 18);
848 WMMoveWidget(panel->cmykYellowT, 146, 57);
849 WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
850 WMAddNotificationObserver(cmykTextFieldCallback, panel,
851 WMTextDidEndEditingNotification, panel->cmykYellowT);
853 panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
854 WMResizeWidget(panel->cmykBlackS, 141, 16);
855 WMMoveWidget(panel->cmykBlackS, 2, 80);
856 WMSetSliderMinValue(panel->cmykBlackS, 0);
857 WMSetSliderMaxValue(panel->cmykBlackS, 100);
858 WMSetSliderValue(panel->cmykBlackS, 0);
859 WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
860 WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
862 to.red = 0;
863 to.green = 0;
864 to.blue = 0;
866 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
867 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
868 RReleaseImage(image);
870 if (pixmap)
871 W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12,
872 2, 0, 100, WALeft, scrPtr->black, False, _("Black"), strlen(_("Black")));
873 else
874 wwarning(_("Color Panel: Could not allocate memory"));
876 WMSetSliderImage(panel->cmykBlackS, pixmap);
877 WMReleasePixmap(pixmap);
879 panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
880 WMResizeWidget(panel->cmykBlackT, 40, 18);
881 WMMoveWidget(panel->cmykBlackT, 146, 79);
882 WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
883 WMAddNotificationObserver(cmykTextFieldCallback, panel,
884 WMTextDidEndEditingNotification, panel->cmykBlackT);
885 /* End of CMYK Panel */
887 /* Widgets for HSB Panel */
888 panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
889 WMSetFrameRelief(panel->hsbFrm, WRFlat);
890 WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
891 WMMoveWidget(panel->hsbFrm, 0, 34);
893 panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
894 WMResizeWidget(panel->hsbHueS, 141, 16);
895 WMMoveWidget(panel->hsbHueS, 2, 14);
896 WMSetSliderMinValue(panel->hsbHueS, 0);
897 WMSetSliderMaxValue(panel->hsbHueS, 359);
898 WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
899 WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
901 panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
902 WMResizeWidget(panel->hsbHueT, 40, 18);
903 WMMoveWidget(panel->hsbHueT, 146, 13);
904 WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
905 WMAddNotificationObserver(hsbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->hsbHueT);
907 panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
908 WMResizeWidget(panel->hsbSaturationS, 141, 16);
909 WMMoveWidget(panel->hsbSaturationS, 2, 36);
910 WMSetSliderMinValue(panel->hsbSaturationS, 0);
911 WMSetSliderMaxValue(panel->hsbSaturationS, 100);
912 WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
913 WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
915 panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
916 WMResizeWidget(panel->hsbSaturationT, 40, 18);
917 WMMoveWidget(panel->hsbSaturationT, 146, 35);
918 WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
919 WMAddNotificationObserver(hsbTextFieldCallback, panel,
920 WMTextDidEndEditingNotification, panel->hsbSaturationT);
922 panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
923 WMResizeWidget(panel->hsbBrightnessS, 141, 16);
924 WMMoveWidget(panel->hsbBrightnessS, 2, 58);
925 WMSetSliderMinValue(panel->hsbBrightnessS, 0);
926 WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
927 WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
928 WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
930 panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
931 WMResizeWidget(panel->hsbBrightnessT, 40, 18);
932 WMMoveWidget(panel->hsbBrightnessT, 146, 57);
933 WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
934 WMAddNotificationObserver(hsbTextFieldCallback, panel,
935 WMTextDidEndEditingNotification, panel->hsbBrightnessT);
936 /* End of HSB Panel */
938 WMReleaseColor(textcolor);
940 /* Widgets for the CustomPalette Panel */
941 panel->customPaletteFrm = WMCreateFrame(panel->win);
942 WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
943 WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
944 WMMoveWidget(panel->customPaletteFrm, 5, 80);
946 panel->customPaletteHistoryBtn = WMCreatePopUpButton(panel->customPaletteFrm);
947 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, _("Spectrum"));
948 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
949 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1);
950 WMSetPopUpButtonAction(panel->customPaletteHistoryBtn, customPaletteHistoryCallback, panel);
951 WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
952 WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
954 panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
955 WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
956 WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
957 WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
959 panel->customPaletteContentView = W_CreateView(W_VIEW(panel->customPaletteContentFrm));
960 /* XXX Test if we can create a view */
961 W_ResizeView(panel->customPaletteContentView, customPaletteWidth, customPaletteHeight);
962 W_MoveView(panel->customPaletteContentView, 2, 2);
964 /* Create event handler to handle expose/click events in CustomPalette */
965 WMCreateEventHandler(panel->customPaletteContentView,
966 ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
967 ButtonMotionMask, customPaletteHandleActionEvents, panel);
969 WMCreateEventHandler(panel->customPaletteContentView, ExposureMask, customPaletteHandleEvents, panel);
971 panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
972 WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
973 WMSetPopUpButtonText(panel->customPaletteMenuBtn, _("Palette"));
974 WMSetPopUpButtonAction(panel->customPaletteMenuBtn, customPaletteMenuCallback, panel);
975 WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
976 WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
978 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from File..."));
979 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Rename..."));
980 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Remove"));
981 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Copy"));
982 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from Clipboard"));
984 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, 0);
985 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, 0);
986 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuCopy, 0);
987 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuNewFromClipboard, 0);
989 customRenderSpectrum(panel);
990 panel->currentPalette = 0;
991 panel->palx = customPaletteWidth / 2;
992 panel->paly = customPaletteHeight / 2;
994 /* Widgets for the ColorList Panel */
995 panel->colorListFrm = WMCreateFrame(panel->win);
996 WMSetFrameRelief(panel->colorListFrm, WRFlat);
997 WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
998 WMMoveWidget(panel->colorListFrm, 5, 80);
1000 panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
1001 WMAddPopUpButtonItem(panel->colorListHistoryBtn, _("X11-Colors"));
1002 WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn,
1003 WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn) - 1);
1004 /* WMSetPopUpButtonAction(panel->colorListHistoryBtn,
1005 * colorListHistoryCallback, panel); */
1006 WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
1007 WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
1009 panel->colorListContentLst = WMCreateList(panel->colorListFrm);
1010 WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
1011 WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
1012 WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
1013 WMMoveWidget(panel->colorListContentLst, 0, 23);
1014 WMHangData(panel->colorListContentLst, panel);
1016 panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1017 WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
1018 WMSetPopUpButtonText(panel->colorListColorMenuBtn, _("Color"));
1019 WMSetPopUpButtonAction(panel->colorListColorMenuBtn, colorListColorMenuCallback, panel);
1020 WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16) / 2, 20);
1021 WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
1023 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Add..."));
1024 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Rename..."));
1025 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Remove"));
1027 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuAdd, 0);
1028 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRename, 0);
1029 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRemove, 0);
1031 panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1032 WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
1033 WMSetPopUpButtonText(panel->colorListListMenuBtn, _("List"));
1034 WMSetPopUpButtonAction(panel->colorListListMenuBtn, colorListListMenuCallback, panel);
1035 WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2, 20);
1036 WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2 + 8, PHEIGHT - 130);
1038 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("New..."));
1039 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Rename..."));
1040 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Remove"));
1042 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuAdd, 0);
1043 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
1044 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
1046 WMRealizeWidget(panel->win);
1047 WMMapSubwidgets(panel->win);
1049 WMMapSubwidgets(panel->wheelFrm);
1050 WMMapSubwidgets(panel->slidersFrm);
1051 WMMapSubwidgets(panel->grayFrm);
1052 WMMapSubwidgets(panel->rgbFrm);
1053 WMMapSubwidgets(panel->cmykFrm);
1054 WMMapSubwidgets(panel->hsbFrm);
1055 WMMapSubwidgets(panel->customPaletteFrm);
1056 WMMapSubwidgets(panel->customPaletteContentFrm);
1057 WMMapSubwidgets(panel->colorListFrm);
1059 /* Pixmap to indicate selection positions
1060 * wheelframe MUST be mapped.
1062 panel->selectionImg = XCreatePixmap(scrPtr->display, WMWidgetXID(panel->win), 4, 4, scrPtr->depth);
1063 XFillRectangle(scrPtr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1064 XFillRectangle(scrPtr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1066 readConfiguration(panel);
1067 readXColors(panel);
1069 return panel;
1072 WMColorPanel *WMGetColorPanel(WMScreen * scrPtr)
1074 WMColorPanel *panel;
1076 if (scrPtr->sharedColorPanel)
1077 return scrPtr->sharedColorPanel;
1079 panel = makeColorPanel(scrPtr, "colorPanel");
1081 scrPtr->sharedColorPanel = panel;
1083 return panel;
1086 void WMFreeColorPanel(WMColorPanel * panel)
1088 W_Screen *scr;
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 struct stat stat_buf;
1163 int item;
1165 if (stat(panel->configurationPath, &stat_buf) != 0) {
1166 if (mkdir(panel->configurationPath, S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH) != 0) {
1167 werror(_("Color Panel: Could not create directory %s needed"
1168 " to store configurations"), panel->configurationPath);
1169 WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
1170 WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
1171 WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
1172 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1173 _("File Error"),
1174 _("Could not create ColorPanel configuration directory"),
1175 _("OK"), NULL, NULL);
1177 return;
1180 if (!(dPtr = opendir(panel->configurationPath))) {
1181 wwarning("%s: %s", _("Color Panel: Could not find file"), panel->configurationPath);
1182 return;
1185 while ((dp = readdir(dPtr)) != NULL) {
1186 unsigned int perm_mask;
1187 char *path = wstrconcat(panel->configurationPath,
1188 dp->d_name);
1190 if (dp->d_name[0] != '.') {
1191 item = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
1192 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
1194 perm_mask = (access(path, R_OK) == 0);
1195 WMSetPopUpButtonItemEnabled(panel->customPaletteHistoryBtn, item, perm_mask);
1197 wfree(path);
1199 closedir(dPtr);
1202 static void readXColors(W_ColorPanel * panel)
1204 WMListItem *item;
1205 const RGBColor *entry;
1207 for (entry = rgbColors; entry->name != NULL; entry++) {
1208 item = WMAddListItem(panel->colorListContentLst, entry->name);
1209 item->clientData = (void *)&(entry->color);
1213 void WMSetColorPanelPickerMode(WMColorPanel * panel, WMColorPanelMode mode)
1215 W_Screen *scr = WMWidgetScreen(panel->win);
1217 if (mode != WMWheelModeColorPanel) {
1218 WMUnmapWidget(panel->wheelFrm);
1219 if (panel->selectionBackImg) {
1220 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1221 panel->selectionBackImg = None;
1224 if (mode != WMGrayModeColorPanel)
1225 WMUnmapWidget(panel->grayFrm);
1226 if (mode != WMRGBModeColorPanel)
1227 WMUnmapWidget(panel->rgbFrm);
1228 if (mode != WMCMYKModeColorPanel)
1229 WMUnmapWidget(panel->cmykFrm);
1230 if (mode != WMHSBModeColorPanel)
1231 WMUnmapWidget(panel->hsbFrm);
1232 if (mode != WMCustomPaletteModeColorPanel) {
1233 WMUnmapWidget(panel->customPaletteFrm);
1234 if (panel->selectionBackImg) {
1235 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1236 panel->selectionBackImg = None;
1239 if (mode != WMColorListModeColorPanel)
1240 WMUnmapWidget(panel->colorListFrm);
1241 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
1242 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1243 WMUnmapWidget(panel->slidersFrm);
1244 else
1245 panel->slidersmode = mode;
1247 if (mode == WMWheelModeColorPanel) {
1248 WMMapWidget(panel->wheelFrm);
1249 WMSetButtonSelected(panel->wheelBtn, True);
1250 if (panel->lastChanged != WMWheelModeColorPanel)
1251 wheelInit(panel);
1252 wheelRender(panel);
1253 wheelPaint(panel);
1254 } else if (mode == WMGrayModeColorPanel) {
1255 WMMapWidget(panel->slidersFrm);
1256 WMSetButtonSelected(panel->slidersBtn, True);
1257 WMMapWidget(panel->grayFrm);
1258 WMSetButtonSelected(panel->grayBtn, True);
1259 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1260 if (panel->lastChanged != WMGrayModeColorPanel)
1261 grayInit(panel);
1262 } else if (mode == WMRGBModeColorPanel) {
1263 WMMapWidget(panel->slidersFrm);
1264 WMSetButtonSelected(panel->slidersBtn, True);
1265 WMMapWidget(panel->rgbFrm);
1266 WMSetButtonSelected(panel->rgbBtn, True);
1267 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1268 if (panel->lastChanged != WMRGBModeColorPanel)
1269 rgbInit(panel);
1270 } else if (mode == WMCMYKModeColorPanel) {
1271 WMMapWidget(panel->slidersFrm);
1272 WMSetButtonSelected(panel->slidersBtn, True);
1273 WMMapWidget(panel->cmykFrm);
1274 WMSetButtonSelected(panel->cmykBtn, True);
1275 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1276 if (panel->lastChanged != WMCMYKModeColorPanel)
1277 cmykInit(panel);
1278 } else if (mode == WMHSBModeColorPanel) {
1279 WMMapWidget(panel->slidersFrm);
1280 WMSetButtonSelected(panel->slidersBtn, True);
1281 WMMapWidget(panel->hsbFrm);
1282 WMSetButtonSelected(panel->hsbBtn, True);
1283 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1284 if (panel->lastChanged != WMHSBModeColorPanel)
1285 hsbInit(panel);
1286 } else if (mode == WMCustomPaletteModeColorPanel) {
1287 WMMapWidget(panel->customPaletteFrm);
1288 WMSetButtonSelected(panel->customPaletteBtn, True);
1289 customSetPalette(panel);
1290 } else if (mode == WMColorListModeColorPanel) {
1291 WMMapWidget(panel->colorListFrm);
1292 WMSetButtonSelected(panel->colorListBtn, True);
1295 panel->mode = mode;
1298 WMColor *WMGetColorPanelColor(WMColorPanel * panel)
1300 return WMGetColorWellColor(panel->colorWell);
1303 void WMSetColorPanelColor(WMColorPanel * panel, WMColor * color)
1305 WMSetColorWellColor(panel->colorWell, color);
1307 panel->color.rgb.red = color->color.red >> 8;
1308 panel->color.rgb.green = color->color.green >> 8;
1309 panel->color.rgb.blue = color->color.blue >> 8;
1310 panel->color.set = cpRGB;
1312 if (panel->mode == panel->lastChanged)
1313 panel->lastChanged = 0;
1315 WMSetColorPanelPickerMode(panel, panel->mode);
1318 static void updateSwatch(WMColorPanel * panel, CPColor color)
1320 WMScreen *scr = WMWidgetScreen(panel->win);
1321 WMColor *wellcolor;
1323 if (color.set != cpRGB)
1324 convertCPColor(&color);
1326 panel->color = color;
1328 wellcolor = WMCreateRGBColor(scr, color.rgb.red << 8, color.rgb.green << 8, color.rgb.blue << 8, True);
1330 WMSetColorWellColor(panel->colorWell, wellcolor);
1331 WMReleaseColor(wellcolor);
1333 if (!panel->flags.dragging || panel->flags.continuous) {
1334 if (panel->action)
1335 (*panel->action) (panel, panel->clientData);
1337 WMPostNotificationName(WMColorPanelColorChangedNotification, panel, NULL);
1341 static void modeButtonCallback(WMWidget * w, void *data)
1343 W_ColorPanel *panel = (W_ColorPanel *) (data);
1345 if (w == panel->wheelBtn)
1346 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1347 else if (w == panel->slidersBtn)
1348 WMSetColorPanelPickerMode(panel, panel->slidersmode);
1349 else if (w == panel->customPaletteBtn)
1350 WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
1351 else if (w == panel->colorListBtn)
1352 WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
1353 else if (w == panel->grayBtn)
1354 WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
1355 else if (w == panel->rgbBtn)
1356 WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
1357 else if (w == panel->cmykBtn)
1358 WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
1359 else if (w == panel->hsbBtn)
1360 WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
1363 /****************** Magnifying Cursor Functions *******************/
1365 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h)
1367 int x0 = 0, y0 = 0, w0 = w, h0 = h;
1368 const int displayWidth = DisplayWidth(scr->display, scr->screen),
1369 displayHeight = DisplayHeight(scr->display, scr->screen);
1371 if (!(image && image->data)) {
1372 /* The image in panel->magnifyGlass->image does not exist yet.
1373 * Grab one from the screen (not beyond) and use it from now on.
1375 if (!(image = XGetImage(scr->display, scr->rootWin,
1376 x - Cursor_x_hot, y - Cursor_y_hot, w, h, AllPlanes, ZPixmap)))
1377 wwarning(_("Color Panel: X failed request"));
1379 return image;
1382 /* Coordinate correction for back pixmap
1383 * if magnifying glass is at screen-borders
1386 /* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
1387 * Hatched area is beyond screen border.
1389 * |<-Cursor_x_hot->|
1390 * ________________|_____
1391 * |/ / / / / / /| | |
1392 * | / / / / / / |(x,y) |
1393 * |/_/_/_/_/_/_/|________|
1394 * |<----x0----->|<--w0-->|
1398 /* Figure 2: Shifting of rectangle-to-grab at bottom/right
1399 * screen borders
1400 * Hatched area is beyond screen border
1402 * |<-Cursor_x_hot->|
1403 * ________________|_______________
1404 * | | | / / / / / /|
1405 * | (x,y)|/ / / / / / |
1406 * |___________________|_/_/_/_/_/_/|
1407 * |<-------w0-------->| |
1408 * |<---------------w--|----------->|
1409 * | |
1410 * x0 Displaywidth-1
1413 if (x < Cursor_x_hot) { /* see fig. 1 */
1414 x0 = Cursor_x_hot - x;
1415 w0 = w - x0;
1418 if (displayWidth - 1 < x - Cursor_x_hot + w) { /* see fig. 2 */
1419 w0 = (displayWidth) - (x - Cursor_x_hot);
1422 if (y < Cursor_y_hot) { /* see fig. 1 */
1423 y0 = Cursor_y_hot - y;
1424 h0 = h - y0;
1427 if (displayHeight - 1 < y - Cursor_y_hot + h) { /* see fig. 2 */
1428 h0 = (displayHeight) - (y - Cursor_y_hot);
1430 /* end of coordinate correction */
1432 /* Grab an image from the screen, clipped if necessary,
1433 * and put it in the existing panel->magnifyGlass->image
1434 * with the corresponding clipping offset.
1436 if (!XGetSubImage(scr->display, scr->rootWin,
1437 x - Cursor_x_hot + x0, y - Cursor_y_hot + y0, w0, h0, AllPlanes, ZPixmap, image, x0, y0))
1438 wwarning(_("Color Panel: X failed request"));
1440 return NULL;
1443 static void magnifyGetImageStored(WMColorPanel * panel, int x1, int y1, int x2, int y2)
1445 /* (x1, y1) = topleft corner of existing rectangle
1446 * (x2, y2) = topleft corner of new position
1449 W_Screen *scr = WMWidgetScreen(panel->win);
1450 int xa = 0, ya = 0, xb = 0, yb = 0;
1451 int width, height;
1452 const int dx = abs(x2 - x1), dy = abs(y2 - y1);
1453 XImage *image;
1454 const int x_min = Cursor_x_hot,
1455 y_min = Cursor_y_hot,
1456 x_max = DisplayWidth(scr->display, scr->screen) - 1 -
1457 (Cursor_mask_width - Cursor_x_hot),
1458 y_max = DisplayHeight(scr->display, scr->screen) - 1 - (Cursor_mask_height - Cursor_y_hot);
1460 if ((dx == 0) && (dy == 0) && panel->magnifyGlass->image)
1461 return; /* No movement */
1463 if (x1 < x2)
1464 xa = dx;
1465 else
1466 xb = dx;
1468 if (y1 < y2)
1469 ya = dy;
1470 else
1471 yb = dy;
1473 width = Cursor_mask_width - dx;
1474 height = Cursor_mask_height - dy;
1476 /* If the traversed distance is larger than the size of the magnifying
1477 * glass contents, there is no need to do dirty rectangles. A whole new
1478 * rectangle can be grabbed (unless that rectangle falls partially
1479 * off screen).
1480 * Destroying the image and setting it to NULL will achieve that later on.
1482 * Of course, grabbing an XImage beyond the borders of the screen will
1483 * cause trouble, this is considdered a special case. Part of the screen
1484 * is grabbed, but there is no need for dirty rectangles.
1486 if ((width <= 0) || (height <= 0)) {
1487 if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
1488 if (panel->magnifyGlass->image)
1489 XDestroyImage(panel->magnifyGlass->image);
1490 panel->magnifyGlass->image = NULL;
1492 } else {
1493 if (panel->magnifyGlass->image) {
1494 /* Get dirty rectangle from panel->magnifyGlass->image */
1495 panel->magnifyGlass->dirtyRect =
1496 XSubImage(panel->magnifyGlass->image, xa, ya, width, height);
1497 if (!panel->magnifyGlass->dirtyRect) {
1498 wwarning(_("Color Panel: X failed request"));
1499 return; /* X returned a NULL from XSubImage */
1504 /* Get image from screen */
1505 image = magnifyGetImage(scr, panel->magnifyGlass->image, x2, y2, Cursor_mask_width, Cursor_mask_height);
1506 if (image) { /* Only reassign if a *new* image was grabbed */
1507 panel->magnifyGlass->image = image;
1508 return;
1511 /* Copy previously stored rectangle on covered part of image */
1512 if (panel->magnifyGlass->image && panel->magnifyGlass->dirtyRect) {
1513 int old_height;
1515 /* "width" and "height" are used as coordinates here,
1516 * and run from [0...width-1] and [0...height-1] respectively.
1518 width--;
1519 height--;
1520 old_height = height;
1522 for (; width >= 0; width--)
1523 for (height = old_height; height >= 0; height--)
1524 XPutPixel(panel->magnifyGlass->image, xb + width, yb + height,
1525 XGetPixel(panel->magnifyGlass->dirtyRect, width, height));
1526 XDestroyImage(panel->magnifyGlass->dirtyRect);
1527 panel->magnifyGlass->dirtyRect = NULL;
1530 return;
1533 static Pixmap magnifyCreatePixmap(WMColorPanel * panel)
1535 W_Screen *scr = WMWidgetScreen(panel->win);
1536 int u, v;
1537 #ifndef USE_XSHAPE
1538 Pixmap pixmap;
1539 #endif
1540 unsigned long color;
1542 if (!panel->magnifyGlass->image)
1543 return None;
1545 if (!panel->magnifyGlass->magPix)
1546 return None;
1549 * Copy an area of only 5x5 pixels from the center of the image.
1551 for (u = 0; u < 5; u++) {
1552 for (v = 0; v < 5; v++) {
1553 color = XGetPixel(panel->magnifyGlass->image, u + 9, v + 9);
1555 XSetForeground(scr->display, scr->copyGC, color);
1557 if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
1558 panel->magnifyGlass->color = ulongToRColor(scr, color);
1560 /* The center square must eventually be centered around the
1561 * hotspot. The image needs shifting to achieve this. The amount of
1562 * shifting is (Cursor_mask_width/2 - 2 * square_size) = 11-10 = 1
1563 * _ _ _ _ _
1564 * |_|_|_|_|_|
1565 * ^------- center of center square == Cursor_x_hot
1567 XFillRectangle(scr->display, panel->magnifyGlass->magPix,
1568 scr->copyGC,
1569 u * 5 + (u == 0 ? 0 : -1), v * 5 + (v == 0 ? 0 : -1),
1570 (u == 0 ? 4 : 5), (v == 0 ? 4 : 5));
1574 #ifdef USE_XSHAPE
1575 return panel->magnifyGlass->magPix;
1576 #else
1577 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width, Cursor_mask_height, scr->depth);
1578 if (!pixmap)
1579 return None;
1581 XPutImage(scr->display, pixmap, scr->copyGC, panel->magnifyGlass->image,
1582 0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
1584 /* Copy the magnified pixmap, with the clip mask, to background pixmap */
1585 XCopyArea(scr->display, panel->magnifyGlass->magPix, pixmap,
1586 scr->clipGC, 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
1587 /* (2,2) puts center pixel on center of glass */
1589 return pixmap;
1590 #endif
1594 static WMView *magnifyCreateView(W_ColorPanel * panel)
1596 W_Screen *scr = WMWidgetScreen(panel->win);
1597 WMView *magView;
1599 magView = W_CreateTopView(scr);
1600 if (!magView)
1601 return NULL;
1603 magView->self = panel->win;
1604 magView->flags.topLevel = 1;
1605 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1606 magView->attribs.override_redirect = True;
1607 magView->attribs.save_under = True;
1609 W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
1611 W_RealizeView(magView);
1613 return magView;
1616 static Cursor magnifyGrabPointer(W_ColorPanel * panel)
1618 W_Screen *scr = WMWidgetScreen(panel->win);
1619 Pixmap magPixmap, magPixmap2;
1620 Cursor magCursor;
1621 XColor fgColor = { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 };
1622 XColor bgColor = { 0, 0xbf00, 0xa000, 0x5000, DoRed | DoGreen | DoBlue, 0 };
1624 /* Cursor creation stuff */
1625 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1626 (char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
1627 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1628 (char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
1630 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1631 &fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
1633 XFreePixmap(scr->display, magPixmap);
1634 XFreePixmap(scr->display, magPixmap2);
1636 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1638 /* Set up Pointer */
1639 XGrabPointer(scr->display, panel->magnifyGlass->view->window, True,
1640 PointerMotionMask | ButtonPressMask,
1641 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1643 return magCursor;
1646 static WMPoint magnifyInitialize(W_ColorPanel * panel)
1648 W_Screen *scr = WMWidgetScreen(panel->win);
1649 int x, y, u, v;
1650 unsigned int mask;
1651 Pixmap pixmap, clip_mask;
1652 WMPoint point;
1653 Window root_return, child_return;
1655 clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1656 (char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1657 1, 0, 1);
1658 panel->magnifyGlass->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
1659 5 * 5 - 1, 5 * 5 - 1, scr->depth);
1661 XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return, &x, &y, &u, &v, &mask);
1663 panel->magnifyGlass->image = NULL;
1665 /* Clipmask to make magnified view-contents circular */
1666 #ifdef USE_XSHAPE
1667 XShapeCombineMask(scr->display, WMViewXID(panel->magnifyGlass->view),
1668 ShapeBounding, 0, 0, clip_mask, ShapeSet);
1669 #else
1670 /* Clip circle in glass cursor */
1671 XSetClipMask(scr->display, scr->clipGC, clip_mask);
1672 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1673 #endif
1675 XFreePixmap(scr->display, clip_mask);
1677 /* Draw initial magnifying glass contents */
1678 magnifyGetImageStored(panel, x, y, x, y);
1680 pixmap = magnifyCreatePixmap(panel);
1681 XSetWindowBackgroundPixmap(scr->display, WMViewXID(panel->magnifyGlass->view), pixmap);
1682 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1683 XFlush(scr->display);
1685 #ifndef USE_XSHAPE
1686 XFreePixmap(scr->display, pixmap);
1687 #endif
1689 point.x = x;
1690 point.y = y;
1692 return point;
1695 static void magnifyPutCursor(WMWidget * w, void *data)
1697 W_ColorPanel *panel = (W_ColorPanel *) (data);
1698 W_Screen *scr = WMWidgetScreen(panel->win);
1699 Cursor magCursor;
1700 Pixmap pixmap;
1701 XEvent event;
1702 WMPoint initialPosition;
1704 /* Parameter not used, but tell the compiler that it is ok */
1705 (void) w;
1707 /* Destroy wheelBackImg, so it'll update properly */
1708 if (panel->selectionBackImg) {
1709 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1710 panel->selectionBackImg = None;
1713 /* Create magnifying glass */
1714 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1715 panel->magnifyGlass->view = magnifyCreateView(panel);
1716 if (!panel->magnifyGlass->view)
1717 return;
1719 initialPosition = magnifyInitialize(panel);
1720 panel->magnifyGlass->x = initialPosition.x;
1721 panel->magnifyGlass->y = initialPosition.y;
1723 W_MoveView(panel->magnifyGlass->view,
1724 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1725 W_MapView(panel->magnifyGlass->view);
1727 magCursor = magnifyGrabPointer(panel);
1729 while (panel->magnifyGlass->image) {
1730 WMNextEvent(scr->display, &event);
1732 /* Pack motion events */
1733 while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
1736 switch (event.type) {
1737 case ButtonPress:
1738 XDestroyImage(panel->magnifyGlass->image);
1739 panel->magnifyGlass->image = NULL;
1741 if (event.xbutton.button == Button1) {
1742 panel->color.rgb = panel->magnifyGlass->color;
1743 panel->color.set = cpRGB;
1744 updateSwatch(panel, panel->color);
1746 switch (panel->mode) {
1747 case WMWheelModeColorPanel:
1748 wheelInit(panel);
1749 wheelRender(panel);
1750 wheelPaint(panel);
1751 break;
1752 case WMGrayModeColorPanel:
1753 grayInit(panel);
1754 break;
1755 case WMRGBModeColorPanel:
1756 rgbInit(panel);
1757 break;
1758 case WMCMYKModeColorPanel:
1759 cmykInit(panel);
1760 break;
1761 case WMHSBModeColorPanel:
1762 hsbInit(panel);
1763 break;
1764 default:
1765 break;
1767 panel->lastChanged = panel->mode;
1769 WMSetButtonSelected(panel->magnifyBtn, False);
1770 break;
1772 case MotionNotify:
1773 while (XPending(event.xmotion.display)) {
1774 XEvent ev;
1775 XPeekEvent(event.xmotion.display, &ev);
1776 if (ev.type == MotionNotify)
1777 XNextEvent(event.xmotion.display, &event);
1778 else
1779 break;
1782 /* Get a "dirty rectangle" */
1783 magnifyGetImageStored(panel,
1784 panel->magnifyGlass->x, panel->magnifyGlass->y,
1785 event.xmotion.x_root, event.xmotion.y_root);
1787 /* Update coordinates */
1788 panel->magnifyGlass->x = event.xmotion.x_root;
1789 panel->magnifyGlass->y = event.xmotion.y_root;
1791 /* Move view */
1792 W_MoveView(panel->magnifyGlass->view,
1793 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1795 /* Put new image (with magn.) in view */
1796 pixmap = magnifyCreatePixmap(panel);
1797 if (pixmap != None) {
1798 /* Change the window background */
1799 XSetWindowBackgroundPixmap(scr->display,
1800 WMViewXID(panel->magnifyGlass->view), pixmap);
1801 /* Force an Expose (handled by X) */
1802 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1803 /* Synchronize the event queue, so the Expose is handled NOW */
1804 XFlush(scr->display);
1805 #ifndef USE_XSHAPE
1806 XFreePixmap(scr->display, pixmap);
1807 #endif
1809 break;
1811 /* Try XQueryPointer for this !!! It returns windows that the pointer
1812 * is over. Note: We found this solving the invisible donkey cap bug
1814 #if 0 /* As it is impossible to make this work in all cases,
1815 * we consider it confusing. Therefore we disabled it.
1817 case FocusOut: /* fall through */
1818 case FocusIn:
1820 * Color Panel window (panel->win) lost or received focus.
1821 * We need to update the pixmap in the magnifying glass.
1823 * BUG Doesn't work with focus switches between two windows
1824 * if none of them is the color panel.
1826 XUngrabPointer(scr->display, CurrentTime);
1827 W_UnmapView(panel->magnifyGlass->view);
1829 magnifyInitialize(panel);
1831 W_MapView(panel->magnifyGlass->view);
1832 XGrabPointer(scr->display, panel->magnifyGlass->view->window,
1833 True, PointerMotionMask | ButtonPressMask,
1834 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1835 break;
1836 #endif
1837 default:
1838 WMHandleEvent(&event);
1839 break;
1840 } /* of switch */
1843 XUngrabPointer(scr->display, CurrentTime);
1844 XFreeCursor(scr->display, magCursor);
1846 XFreePixmap(scr->display, panel->magnifyGlass->magPix);
1847 panel->magnifyGlass->magPix = None;
1849 W_UnmapView(panel->magnifyGlass->view);
1850 W_DestroyView(panel->magnifyGlass->view);
1851 panel->magnifyGlass->view = NULL;
1853 wfree(panel->magnifyGlass);
1856 /****************** ColorWheel Functions ************************/
1858 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height)
1860 wheelMatrix *matrix = NULL;
1861 int i;
1863 assert((width > 0) && (height > 0));
1865 matrix = wmalloc(sizeof(wheelMatrix));
1866 matrix->width = width;
1867 matrix->height = height;
1869 for (i = 0; i < 3; i++) {
1870 matrix->data[i] = wmalloc(width * height * sizeof(unsigned char));
1873 return matrix;
1876 static void wheelDestroyMatrix(wheelMatrix * matrix)
1878 int i;
1880 if (!matrix)
1881 return;
1883 for (i = 0; i < 3; i++) {
1884 if (matrix->data[i])
1885 wfree(matrix->data[i]);
1887 wfree(matrix);
1890 static void wheelInitMatrix(W_ColorPanel * panel)
1892 int i;
1893 int x, y;
1894 unsigned char *rp, *gp, *bp;
1895 CPColor cpColor;
1896 long ofs[4];
1897 int xcor, ycor;
1898 unsigned short sat;
1899 int dhue[4];
1900 const int cw_halfsize = (colorWheelSize + 4) / 2,
1901 cw_sqsize = (colorWheelSize + 4) * (colorWheelSize + 4), uchar_shift = getShift(sizeof(unsigned char));
1903 if (!panel->wheelMtrx)
1904 return;
1906 cpColor.hsv.value = 255;
1907 cpColor.set = cpHSV;
1909 ofs[0] = -1;
1910 ofs[1] = -(colorWheelSize + 4);
1912 /* offsets are counterclockwise (in triangles).
1914 * ofs[0] ---->
1915 * _______________________________________
1916 * [1] |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| o
1917 * s |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| f
1918 * f |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| s
1919 * o | | | | | | | | | | | | | | | | | | | | | [3]
1921 * <---- ofs[2]
1922 * ____
1923 * |\ /| <-- triangles
1924 * | \/ |
1925 * | /\ |
1926 * |/__\|
1929 for (y = 0; y < cw_halfsize; y++) {
1930 for (x = y; x < (colorWheelSize + 4 - y); x++) {
1931 /* (xcor, ycor) is (x,y) relative to center of matrix */
1932 xcor = 2 * x - 4 - colorWheelSize;
1933 ycor = 2 * y - 4 - colorWheelSize;
1935 /* RColor.saturation is unsigned char and will wrap after 255 */
1936 sat = rint(255.0 * sqrt(xcor * xcor + ycor * ycor) / colorWheelSize);
1938 cpColor.hsv.saturation = (unsigned char)sat;
1940 ofs[0]++; /* top quarter of matrix */
1941 ofs[1] += colorWheelSize + 4; /* left quarter */
1942 ofs[2] = cw_sqsize - 1 - ofs[0]; /* bottom quarter */
1943 ofs[3] = cw_sqsize - 1 - ofs[1]; /* right quarter */
1945 if (sat < 256) {
1946 if (xcor != 0)
1947 dhue[0] = rint(atan((double)ycor / (double)xcor) *
1948 (180.0 / WM_PI)) + (xcor < 0 ? 180.0 : 0.0);
1949 else
1950 dhue[0] = 270;
1952 dhue[0] = 360 - dhue[0]; /* Reverse direction of ColorWheel */
1953 dhue[1] = 270 - dhue[0] + (dhue[0] > 270 ? 360 : 0);
1954 dhue[2] = dhue[0] - 180 + (dhue[0] < 180 ? 360 : 0);
1955 dhue[3] = 90 - dhue[0] + (dhue[0] > 90 ? 360 : 0);
1957 for (i = 0; i < 4; i++) {
1958 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1959 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1960 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1962 cpColor.hsv.hue = dhue[i];
1963 convertCPColor(&cpColor);
1965 *rp = (unsigned char)(cpColor.rgb.red);
1966 *gp = (unsigned char)(cpColor.rgb.green);
1967 *bp = (unsigned char)(cpColor.rgb.blue);
1969 } else {
1970 for (i = 0; i < 4; i++) {
1971 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1972 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1973 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1975 *rp = (unsigned char)0;
1976 *gp = (unsigned char)0;
1977 *bp = (unsigned char)0;
1982 ofs[0] += 2 * y + 1;
1983 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2 * y);
1987 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue)
1989 unsigned int i;
1990 unsigned int v;
1992 for (i = 0; i < 256; i++) {
1993 /* We divide by 128 in advance, and check whether that number divides
1994 * by 2 properly. If not, we add one to round the number correctly
1996 v = (i * maxvalue) >> 7;
1997 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + (v & 0x01));
2001 static void wheelRender(W_ColorPanel * panel)
2003 W_Screen *scr = WMWidgetScreen(panel->win);
2004 int x, y;
2005 RImage *image;
2006 unsigned char *ptr;
2007 RColor gray;
2008 unsigned long ofs = 0;
2009 /*unsigned char shift = getShift(sizeof(unsigned char)); */
2011 image = RCreateImage(colorWheelSize + 4, colorWheelSize + 4, True);
2012 if (!image) {
2013 wwarning(_("Color Panel: Could not allocate memory"));
2014 return;
2017 ptr = image->data;
2019 /* TODO Make this transparent istead of gray */
2020 gray.red = gray.blue = 0xae;
2021 gray.green = 0xaa;
2023 for (y = 0; y < colorWheelSize + 4; y++) {
2024 for (x = 0; x < colorWheelSize + 4; x++) {
2025 if (wheelInsideColorWheel(panel, ofs)) {
2026 *(ptr++) =
2027 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]]);
2028 *(ptr++) =
2029 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]]);
2030 *(ptr++) =
2031 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]]);
2032 *(ptr++) = 0;
2033 } else {
2034 *(ptr++) = (unsigned char)(gray.red);
2035 *(ptr++) = (unsigned char)(gray.green);
2036 *(ptr++) = (unsigned char)(gray.blue);
2037 *(ptr++) = 255;
2039 ofs++;
2043 if (panel->wheelImg)
2044 XFreePixmap(scr->display, panel->wheelImg);
2046 RConvertImage(scr->rcontext, image, &panel->wheelImg);
2047 RReleaseImage(image);
2049 /* Check if backimage exists. If it doesn't, allocate and fill it */
2050 if (!panel->selectionBackImg) {
2051 panel->selectionBackImg = XCreatePixmap(scr->display,
2052 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
2053 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2054 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2055 /* -2 is hot spot correction */
2059 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs)
2061 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
2062 (panel->wheelMtrx->data[1][ofs] != 0) && (panel->wheelMtrx->data[2][ofs] != 0));
2065 static void wheelPaint(W_ColorPanel * panel)
2067 W_Screen *scr = WMWidgetScreen(panel->win);
2069 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
2070 scr->copyGC, 0, 0, colorWheelSize + 4, colorWheelSize + 4, 0, 0);
2072 /* Draw selection image */
2073 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2074 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2077 static void wheelHandleEvents(XEvent * event, void *data)
2079 W_ColorPanel *panel = (W_ColorPanel *) data;
2081 switch (event->type) {
2082 case Expose:
2083 if (event->xexpose.count != 0) /* TODO Improve */
2084 break;
2085 wheelPaint(panel);
2086 break;
2090 static void wheelHandleActionEvents(XEvent * event, void *data)
2092 W_ColorPanel *panel = (W_ColorPanel *) data;
2094 switch (event->type) {
2095 case ButtonPress:
2096 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) == COLORWHEEL_PART) {
2098 panel->lastChanged = WMWheelModeColorPanel;
2099 panel->flags.dragging = 1;
2101 wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
2103 break;
2105 case ButtonRelease:
2106 panel->flags.dragging = 0;
2107 if (!panel->flags.continuous) {
2108 if (panel->action)
2109 (*panel->action) (panel, panel->clientData);
2111 break;
2113 case MotionNotify:
2114 if (panel->flags.dragging) {
2115 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) == COLORWHEEL_PART) {
2116 wheelPositionSelection(panel, event->xmotion.x, event->xmotion.y);
2117 } else
2118 wheelPositionSelectionOutBounds(panel, event->xmotion.x, event->xmotion.y);
2120 break;
2124 static int getPickerPart(W_ColorPanel * panel, int x, int y)
2126 int lx, ly;
2127 unsigned long ofs;
2129 lx = x;
2130 ly = y;
2132 if (panel->mode == WMWheelModeColorPanel) {
2133 if ((lx >= 2) && (lx <= 2 + colorWheelSize) && (ly >= 2) && (ly <= 2 + colorWheelSize)) {
2135 ofs = ly * panel->wheelMtrx->width + lx;
2137 if (wheelInsideColorWheel(panel, ofs))
2138 return COLORWHEEL_PART;
2142 if (panel->mode == WMCustomPaletteModeColorPanel) {
2143 if ((lx >= 2) && (lx < customPaletteWidth - 2) && (ly >= 2) && (ly < customPaletteHeight - 2)) {
2144 return CUSTOMPALETTE_PART;
2148 return 0;
2151 static void wheelBrightnessSliderCallback(WMWidget * w, void *data)
2153 int value;
2155 W_ColorPanel *panel = (W_ColorPanel *) data;
2157 /* Parameter not used, but tell the compiler that it is ok */
2158 (void) w;
2160 value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2162 wheelCalculateValues(panel, value);
2164 if (panel->color.set == cpRGB) {
2165 convertCPColor(&panel->color);
2166 panel->color.set = cpHSV;
2169 panel->color.hsv.value = value;
2171 wheelRender(panel);
2172 wheelPaint(panel);
2173 wheelUpdateSelection(panel);
2176 static void wheelUpdateSelection(W_ColorPanel * panel)
2178 W_Screen *scr = WMWidgetScreen(panel->win);
2180 updateSwatch(panel, panel->color);
2181 panel->lastChanged = WMWheelModeColorPanel;
2183 /* Redraw color selector (and make a backup of the part it will cover) */
2184 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2185 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2186 /* "-2" is correction for hotspot location */
2187 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2188 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2189 /* see above */
2192 static void wheelUndrawSelection(W_ColorPanel * panel)
2194 W_Screen *scr = WMWidgetScreen(panel->win);
2196 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
2197 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2198 /* see above */
2201 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y)
2203 unsigned long ofs = (y * panel->wheelMtrx->width) + x;
2205 panel->color.rgb.red = panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]];
2207 panel->color.rgb.green = panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]];
2209 panel->color.rgb.blue = panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]];
2210 panel->color.set = cpRGB;
2212 wheelUndrawSelection(panel);
2214 panel->colx = x;
2215 panel->coly = y;
2217 wheelUpdateSelection(panel);
2218 wheelUpdateBrightnessGradientFromLocation(panel);
2221 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2223 int hue;
2224 int xcor, ycor;
2225 CPColor cpColor;
2227 xcor = x * 2 - colorWheelSize - 4;
2228 ycor = y * 2 - colorWheelSize - 4;
2230 panel->color.hsv.saturation = 255;
2231 panel->color.hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2233 if (xcor != 0)
2234 hue = rint(atan(-(double)ycor / (double)xcor) * (180.0 / WM_PI));
2235 else {
2236 if (ycor < 0)
2237 hue = 90;
2238 else
2239 hue = 270;
2242 if (xcor < 0)
2243 hue += 180;
2245 if ((xcor > 0) && (ycor > 0))
2246 hue += 360;
2248 panel->color.hsv.hue = hue;
2249 panel->color.set = cpHSV;
2250 convertCPColor(&panel->color);
2252 wheelUndrawSelection(panel);
2254 panel->colx = 2 + rint((colorWheelSize * (1.0 + cos(panel->color.hsv.hue * (WM_PI / 180.0)))) / 2.0);
2255 /* "+2" because of "colorWheelSize + 4" */
2256 panel->coly = 2 + rint((colorWheelSize * (1.0 + sin(-panel->color.hsv.hue * (WM_PI / 180.0)))) / 2.0);
2258 wheelUpdateSelection(panel);
2259 cpColor = panel->color;
2260 wheelUpdateBrightnessGradient(panel, cpColor);
2263 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel)
2265 CPColor from;
2266 unsigned long ofs;
2268 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2270 from.rgb.red = panel->wheelMtrx->data[0][ofs];
2271 from.rgb.green = panel->wheelMtrx->data[1][ofs];
2272 from.rgb.blue = panel->wheelMtrx->data[2][ofs];
2273 from.set = cpRGB;
2275 wheelUpdateBrightnessGradient(panel, from);
2278 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor)
2280 RColor to;
2281 RImage *sliderImg;
2282 WMPixmap *sliderPxmp;
2284 to.red = to.green = to.blue = 0;
2286 if (topColor.set == cpHSV)
2287 convertCPColor(&topColor);
2289 sliderImg = RRenderGradient(16, 153, &(topColor.rgb), &to, RGRD_VERTICAL);
2290 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win), sliderImg, 0);
2291 RReleaseImage(sliderImg);
2292 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
2293 WMReleasePixmap(sliderPxmp);
2296 /****************** Grayscale Panel Functions ***************/
2298 static void grayBrightnessSliderCallback(WMWidget * w, void *data)
2300 CPColor cpColor;
2301 int value;
2302 char tmp[4];
2303 W_ColorPanel *panel = (W_ColorPanel *) data;
2305 /* Parameter not used, but tell the compiler that it is ok */
2306 (void) w;
2308 value = WMGetSliderValue(panel->grayBrightnessS);
2310 sprintf(tmp, "%d", value);
2312 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2313 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint(2.55 * value);
2314 cpColor.set = cpRGB;
2316 updateSwatch(panel, cpColor);
2317 panel->lastChanged = WMGrayModeColorPanel;
2320 static void grayPresetButtonCallback(WMWidget * w, void *data)
2322 CPColor cpColor;
2323 char tmp[4];
2324 int value;
2325 int i = 0;
2326 W_ColorPanel *panel = (W_ColorPanel *) data;
2328 while (i < 7) {
2329 if (w == panel->grayPresetBtn[i])
2330 break;
2331 i++;
2334 value = rint((100.0 * i) / 6.0);
2335 sprintf(tmp, "%d", value);
2337 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2338 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * i) / 6.0);
2339 cpColor.set = cpRGB;
2341 WMSetSliderValue(panel->grayBrightnessS, rint((100.0 * i) / 6.0));
2343 updateSwatch(panel, cpColor);
2344 panel->lastChanged = WMGrayModeColorPanel;
2347 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification)
2349 CPColor cpColor;
2350 char tmp[4];
2351 int value;
2352 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2354 /* Parameter not used, but tell the compiler that it is ok */
2355 (void) notification;
2357 value = get_textfield_as_integer(panel->grayBrightnessT);
2358 if (value > 100)
2359 value = 100;
2360 if (value < 0)
2361 value = 0;
2363 sprintf(tmp, "%d", value);
2364 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2365 WMSetSliderValue(panel->grayBrightnessS, value);
2367 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * value) / 100.0);
2368 cpColor.set = cpRGB;
2370 updateSwatch(panel, cpColor);
2371 panel->lastChanged = WMGrayModeColorPanel;
2374 /******************* RGB Panel Functions *****************/
2376 void rgbIntToChar(W_ColorPanel *panel, int *value)
2378 char tmp[4];
2379 const char *format;
2381 switch (panel->rgbState) {
2382 case RGBdec:
2383 format = "%d";
2384 break;
2385 case RGBhex:
2386 format = "%0X";
2387 break;
2390 sprintf(tmp, format, value[0]);
2391 WMSetTextFieldText(panel->rgbRedT, tmp);
2392 sprintf(tmp, format, value[1]);
2393 WMSetTextFieldText(panel->rgbGreenT, tmp);
2394 sprintf(tmp, format, value[2]);
2395 WMSetTextFieldText(panel->rgbBlueT, tmp);
2398 int *rgbCharToInt(W_ColorPanel *panel)
2400 int base = 0;
2401 static int value[3];
2402 char *str;
2404 switch (panel->rgbState) {
2405 case RGBdec:
2406 base = 10;
2407 break;
2408 case RGBhex:
2409 base = 16;
2410 break;
2413 str = WMGetTextFieldText(panel->rgbRedT);
2414 value[0] = strtol(str, NULL, base);
2415 wfree(str);
2417 str = WMGetTextFieldText(panel->rgbGreenT);
2418 value[1] = strtol(str, NULL, base);
2419 wfree(str);
2421 str = WMGetTextFieldText(panel->rgbBlueT);
2422 value[2] = strtol(str, NULL, base);
2423 wfree(str);
2425 return value;
2428 static void rgbSliderCallback(WMWidget * w, void *data)
2430 CPColor cpColor;
2431 int value[3];
2432 W_ColorPanel *panel = (W_ColorPanel *) data;
2434 /* Parameter not used, but tell the compiler that it is ok */
2435 (void) w;
2437 value[0] = WMGetSliderValue(panel->rgbRedS);
2438 value[1] = WMGetSliderValue(panel->rgbGreenS);
2439 value[2] = WMGetSliderValue(panel->rgbBlueS);
2441 rgbIntToChar(panel, value);
2443 cpColor.rgb.red = value[0];
2444 cpColor.rgb.green = value[1];
2445 cpColor.rgb.blue = value[2];
2446 cpColor.set = cpRGB;
2448 updateSwatch(panel, cpColor);
2449 panel->lastChanged = WMRGBModeColorPanel;
2452 static void rgbTextFieldCallback(void *observerData, WMNotification * notification)
2454 CPColor cpColor;
2455 int *value;
2456 int n;
2457 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2459 /* Parameter not used, but tell the compiler that it is ok */
2460 (void) notification;
2462 value = rgbCharToInt(panel);
2464 for (n = 0; n < 3; n++) {
2465 if (value[n] > 255)
2466 value[n] = 255;
2467 if (value[n] < 0)
2468 value[n] = 0;
2471 rgbIntToChar(panel, value);
2473 WMSetSliderValue(panel->rgbRedS, value[0]);
2474 WMSetSliderValue(panel->rgbGreenS, value[1]);
2475 WMSetSliderValue(panel->rgbBlueS, value[2]);
2477 cpColor.rgb.red = value[0];
2478 cpColor.rgb.green = value[1];
2479 cpColor.rgb.blue = value[2];
2480 cpColor.set = cpRGB;
2482 updateSwatch(panel, cpColor);
2483 panel->lastChanged = WMRGBModeColorPanel;
2486 static void rgbDecToHex(WMWidget *w, void *data)
2488 W_ColorPanel *panel = (W_ColorPanel *) data;
2489 int *value;
2491 (void) w;
2493 switch (panel->rgbState) {
2494 case RGBhex:
2495 if (WMGetButtonSelected(panel->rgbDecB)) {
2496 WMSetLabelText(panel->rgbMaxL, "255");
2497 WMRedisplayWidget(panel->rgbMaxL);
2498 value = rgbCharToInt(panel);
2499 panel->rgbState = RGBdec;
2500 rgbIntToChar(panel, value);
2502 break;
2504 case RGBdec:
2505 if (WMGetButtonSelected(panel->rgbHexB)) {
2506 WMSetLabelText(panel->rgbMaxL, "FF");
2507 WMRedisplayWidget(panel->rgbMaxL);
2508 value = rgbCharToInt(panel);
2509 panel->rgbState = RGBhex;
2510 rgbIntToChar(panel, value);
2512 break;
2516 /******************* CMYK Panel Functions *****************/
2518 static void cmykSliderCallback(WMWidget * w, void *data)
2520 CPColor cpColor;
2521 int value[4];
2522 char tmp[4];
2523 W_ColorPanel *panel = (W_ColorPanel *) data;
2524 double scale;
2526 /* Parameter not used, but tell the compiler that it is ok */
2527 (void) w;
2529 value[0] = WMGetSliderValue(panel->cmykCyanS);
2530 value[1] = WMGetSliderValue(panel->cmykMagentaS);
2531 value[2] = WMGetSliderValue(panel->cmykYellowS);
2532 value[3] = WMGetSliderValue(panel->cmykBlackS);
2534 sprintf(tmp, "%d", value[0]);
2535 WMSetTextFieldText(panel->cmykCyanT, tmp);
2536 sprintf(tmp, "%d", value[1]);
2537 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2538 sprintf(tmp, "%d", value[2]);
2539 WMSetTextFieldText(panel->cmykYellowT, tmp);
2540 sprintf(tmp, "%d", value[3]);
2541 WMSetTextFieldText(panel->cmykBlackT, tmp);
2543 scale = 2.55 * (1.0 - (value[3] / 100.0));
2544 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2545 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2546 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2547 cpColor.set = cpRGB;
2549 updateSwatch(panel, cpColor);
2550 panel->lastChanged = WMCMYKModeColorPanel;
2553 static void cmykTextFieldCallback(void *observerData, WMNotification * notification)
2555 CPColor cpColor;
2556 int value[4];
2557 char tmp[4];
2558 int n;
2559 double scale;
2560 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2562 /* Parameter not used, but tell the compiler that it is ok */
2563 (void) notification;
2565 value[0] = get_textfield_as_integer(panel->cmykCyanT);
2566 value[1] = get_textfield_as_integer(panel->cmykMagentaT);
2567 value[2] = get_textfield_as_integer(panel->cmykYellowT);
2568 value[3] = get_textfield_as_integer(panel->cmykBlackT);
2570 for (n = 0; n < 4; n++) {
2571 if (value[n] > 100)
2572 value[n] = 100;
2573 if (value[n] < 0)
2574 value[n] = 0;
2577 sprintf(tmp, "%d", value[0]);
2578 WMSetTextFieldText(panel->cmykCyanT, tmp);
2580 sprintf(tmp, "%d", value[1]);
2581 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2583 sprintf(tmp, "%d", value[2]);
2584 WMSetTextFieldText(panel->cmykYellowT, tmp);
2586 sprintf(tmp, "%d", value[3]);
2587 WMSetTextFieldText(panel->cmykBlackT, tmp);
2589 WMSetSliderValue(panel->cmykCyanS, value[0]);
2590 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2591 WMSetSliderValue(panel->cmykYellowS, value[2]);
2592 WMSetSliderValue(panel->cmykBlackS, value[3]);
2594 scale = 2.55 * (1.0 - (value[3] / 100.0));
2595 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2596 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2597 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2598 cpColor.set = cpRGB;
2600 updateSwatch(panel, cpColor);
2601 panel->lastChanged = WMCMYKModeColorPanel;
2604 /********************** HSB Panel Functions ***********************/
2606 static void hsbSliderCallback(WMWidget * w, void *data)
2608 CPColor cpColor;
2609 int value[3];
2610 char tmp[4];
2611 W_ColorPanel *panel = (W_ColorPanel *) data;
2613 value[0] = WMGetSliderValue(panel->hsbHueS);
2614 value[1] = WMGetSliderValue(panel->hsbSaturationS);
2615 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
2617 sprintf(tmp, "%d", value[0]);
2618 WMSetTextFieldText(panel->hsbHueT, tmp);
2619 sprintf(tmp, "%d", value[1]);
2620 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2621 sprintf(tmp, "%d", value[2]);
2622 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2624 cpColor.hsv.hue = value[0];
2625 cpColor.hsv.saturation = value[1] * 2.55;
2626 cpColor.hsv.value = value[2] * 2.55;
2627 cpColor.set = cpHSV;
2629 convertCPColor(&cpColor);
2631 panel->lastChanged = WMHSBModeColorPanel;
2632 updateSwatch(panel, cpColor);
2634 if (w != panel->hsbBrightnessS)
2635 hsbUpdateBrightnessGradient(panel);
2636 if (w != panel->hsbSaturationS)
2637 hsbUpdateSaturationGradient(panel);
2638 if (w != panel->hsbHueS)
2639 hsbUpdateHueGradient(panel);
2642 static void hsbTextFieldCallback(void *observerData, WMNotification * notification)
2644 CPColor cpColor;
2645 int value[3];
2646 char tmp[4];
2647 int n;
2648 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2650 /* Parameter not used, but tell the compiler that it is ok */
2651 (void) notification;
2653 value[0] = get_textfield_as_integer(panel->hsbHueT);
2654 value[1] = get_textfield_as_integer(panel->hsbSaturationT);
2655 value[2] = get_textfield_as_integer(panel->hsbBrightnessT);
2657 if (value[0] > 359)
2658 value[0] = 359;
2659 if (value[0] < 0)
2660 value[0] = 0;
2662 for (n = 1; n < 3; n++) {
2663 if (value[n] > 100)
2664 value[n] = 100;
2665 if (value[n] < 0)
2666 value[n] = 0;
2669 sprintf(tmp, "%d", value[0]);
2670 WMSetTextFieldText(panel->hsbHueT, tmp);
2671 sprintf(tmp, "%d", value[1]);
2672 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2673 sprintf(tmp, "%d", value[2]);
2674 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2676 WMSetSliderValue(panel->hsbHueS, value[0]);
2677 WMSetSliderValue(panel->hsbSaturationS, value[1]);
2678 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
2680 cpColor.hsv.hue = value[0];
2681 cpColor.hsv.saturation = value[1] * 2.55;
2682 cpColor.hsv.value = value[2] * 2.55;
2683 cpColor.set = cpHSV;
2685 convertCPColor(&cpColor);
2687 panel->lastChanged = WMHSBModeColorPanel;
2688 updateSwatch(panel, cpColor);
2690 hsbUpdateBrightnessGradient(panel);
2691 hsbUpdateSaturationGradient(panel);
2692 hsbUpdateHueGradient(panel);
2695 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel)
2697 W_Screen *scr = WMWidgetScreen(panel->win);
2698 RColor from;
2699 CPColor to;
2700 RImage *sliderImg;
2701 WMPixmap *sliderPxmp;
2703 from.red = from.green = from.blue = 0;
2704 to.hsv = panel->color.hsv;
2705 to.hsv.value = 255;
2706 to.set = cpHSV;
2708 convertCPColor(&to);
2710 sliderImg = RRenderGradient(141, 16, &from, &(to.rgb), RGRD_HORIZONTAL);
2711 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2712 RReleaseImage(sliderImg);
2714 if (sliderPxmp)
2715 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
2716 panel->font12, 2, 0, 100, WALeft, scr->white,
2717 False, _("Brightness"), strlen(_("Brightness")));
2718 else
2719 wwarning(_("Color Panel: Could not allocate memory"));
2721 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
2722 WMReleasePixmap(sliderPxmp);
2725 static void hsbUpdateSaturationGradient(W_ColorPanel * panel)
2727 W_Screen *scr = WMWidgetScreen(panel->win);
2728 CPColor from;
2729 CPColor to;
2730 RImage *sliderImg;
2731 WMPixmap *sliderPxmp;
2733 from.hsv = panel->color.hsv;
2734 from.hsv.saturation = 0;
2735 from.set = cpHSV;
2736 convertCPColor(&from);
2738 to.hsv = panel->color.hsv;
2739 to.hsv.saturation = 255;
2740 to.set = cpHSV;
2741 convertCPColor(&to);
2743 sliderImg = RRenderGradient(141, 16, &(from.rgb), &(to.rgb), RGRD_HORIZONTAL);
2744 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2745 RReleaseImage(sliderImg);
2747 if (sliderPxmp)
2748 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2749 panel->font12, 2, 0, 100, WALeft,
2750 from.hsv.value < 128 ? scr->white : scr->black, False,
2751 _("Saturation"), strlen(_("Saturation")));
2752 else
2753 wwarning(_("Color Panel: Could not allocate memory"));
2755 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
2756 WMReleasePixmap(sliderPxmp);
2759 static void hsbUpdateHueGradient(W_ColorPanel * panel)
2761 W_Screen *scr = WMWidgetScreen(panel->win);
2762 RColor **colors = NULL;
2763 RHSVColor hsvcolor;
2764 RImage *sliderImg;
2765 WMPixmap *sliderPxmp;
2766 int i;
2768 hsvcolor = panel->color.hsv;
2770 colors = wmalloc(sizeof(RColor *) * (8));
2771 for (i = 0; i < 7; i++) {
2772 hsvcolor.hue = (360 * i) / 6;
2773 colors[i] = wmalloc(sizeof(RColor));
2774 RHSVtoRGB(&hsvcolor, colors[i]);
2776 colors[7] = NULL;
2778 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2779 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2780 RReleaseImage(sliderImg);
2782 if (sliderPxmp)
2783 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2784 panel->font12, 2, 0, 100, WALeft,
2785 hsvcolor.value < 128 ? scr->white : scr->black, False, _("Hue"), strlen(_("Hue")));
2786 else
2787 wwarning(_("Color Panel: Could not allocate memory"));
2789 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2790 WMReleasePixmap(sliderPxmp);
2792 for (i = 0; i < 7; i++)
2793 wfree(colors[i]);
2795 wfree(colors);
2798 /*************** Custom Palette Functions ****************/
2800 static void customRenderSpectrum(W_ColorPanel * panel)
2802 RImage *spectrum;
2803 int x, y;
2804 unsigned char *ptr;
2805 CPColor cpColor;
2807 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, False);
2809 ptr = spectrum->data;
2811 for (y = 0; y < SPECTRUM_HEIGHT; y++) {
2812 cpColor.hsv.hue = y;
2813 cpColor.hsv.saturation = 0;
2814 cpColor.hsv.value = 255;
2815 cpColor.set = cpHSV;
2817 for (x = 0; x < SPECTRUM_WIDTH; x++) {
2818 convertCPColor(&cpColor);
2820 *(ptr++) = (unsigned char)cpColor.rgb.red;
2821 *(ptr++) = (unsigned char)cpColor.rgb.green;
2822 *(ptr++) = (unsigned char)cpColor.rgb.blue;
2824 if (x < (SPECTRUM_WIDTH / 2))
2825 cpColor.hsv.saturation++;
2827 if (x > (SPECTRUM_WIDTH / 2))
2828 cpColor.hsv.value--;
2831 if (panel->customPaletteImg) {
2832 RReleaseImage(panel->customPaletteImg);
2833 panel->customPaletteImg = NULL;
2835 panel->customPaletteImg = spectrum;
2838 static void customSetPalette(W_ColorPanel * panel)
2840 W_Screen *scr = WMWidgetScreen(panel->win);
2841 RImage *scaledImg;
2842 Pixmap image;
2844 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth, customPaletteHeight, scr->depth);
2845 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth, customPaletteHeight);
2846 RConvertImage(scr->rcontext, scaledImg, &image);
2847 RReleaseImage(scaledImg);
2849 XCopyArea(scr->display, image, panel->customPaletteContentView->window,
2850 scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2852 /* Check backimage exists. If it doesn't, allocate and fill it */
2853 if (!panel->selectionBackImg) {
2854 panel->selectionBackImg = XCreatePixmap(scr->display,
2855 panel->customPaletteContentView->window, 4, 4, scr->depth);
2858 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
2859 panel->palx - 2, panel->paly - 2, 4, 4, 0, 0);
2860 XCopyArea(scr->display, panel->selectionImg,
2861 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2862 panel->palx - 2, panel->paly - 2);
2863 XFreePixmap(scr->display, image);
2865 panel->palXRatio = (double)(panel->customPaletteImg->width) / (double)(customPaletteWidth);
2866 panel->palYRatio = (double)(panel->customPaletteImg->height) / (double)(customPaletteHeight);
2869 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y)
2871 W_Screen *scr = WMWidgetScreen(panel->win);
2872 unsigned long ofs;
2874 /* undraw selection */
2875 XCopyArea(scr->display, panel->selectionBackImg,
2876 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2877 panel->palx - 2, panel->paly - 2);
2879 panel->palx = x;
2880 panel->paly = y;
2882 ofs = (rint(x * panel->palXRatio) + rint(y * panel->palYRatio) * panel->customPaletteImg->width) * 3;
2884 panel->color.rgb.red = panel->customPaletteImg->data[ofs];
2885 panel->color.rgb.green = panel->customPaletteImg->data[ofs + 1];
2886 panel->color.rgb.blue = panel->customPaletteImg->data[ofs + 2];
2887 panel->color.set = cpRGB;
2889 updateSwatch(panel, panel->color);
2890 panel->lastChanged = WMCustomPaletteModeColorPanel;
2892 /* Redraw color selector (and make a backup of the part it will cover) */
2893 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 */
2894 XCopyArea(scr->display, panel->selectionImg, panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4, panel->palx - 2, panel->paly - 2); /* see above */
2897 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2899 if (x < 2)
2900 x = 2;
2901 if (y < 2)
2902 y = 2;
2903 if (x >= customPaletteWidth)
2904 x = customPaletteWidth - 2;
2905 if (y >= customPaletteHeight)
2906 y = customPaletteHeight - 2;
2908 customPalettePositionSelection(panel, x, y);
2911 static void customPaletteHandleEvents(XEvent * event, void *data)
2913 W_ColorPanel *panel = (W_ColorPanel *) data;
2915 switch (event->type) {
2916 case Expose:
2917 if (event->xexpose.count != 0) /* TODO Improve. */
2918 break;
2919 customSetPalette(panel);
2920 break;
2924 static void customPaletteHandleActionEvents(XEvent * event, void *data)
2926 W_ColorPanel *panel = (W_ColorPanel *) data;
2927 int x, y;
2929 switch (event->type) {
2930 case ButtonPress:
2931 x = event->xbutton.x;
2932 y = event->xbutton.y;
2934 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2935 panel->flags.dragging = 1;
2936 customPalettePositionSelection(panel, x, y);
2938 break;
2940 case ButtonRelease:
2941 panel->flags.dragging = 0;
2942 if (!panel->flags.continuous) {
2943 if (panel->action)
2944 (*panel->action) (panel, panel->clientData);
2946 break;
2948 case MotionNotify:
2949 x = event->xmotion.x;
2950 y = event->xmotion.y;
2952 if (panel->flags.dragging) {
2953 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2954 customPalettePositionSelection(panel, x, y);
2955 } else
2956 customPalettePositionSelectionOutBounds(panel, x, y);
2958 break;
2962 static void customPaletteMenuCallback(WMWidget * w, void *data)
2964 W_ColorPanel *panel = (W_ColorPanel *) data;
2965 int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
2967 /* Parameter not used, but tell the compiler that it is ok */
2968 (void) w;
2970 switch (item) {
2971 case CPmenuNewFromFile:
2972 customPaletteMenuNewFromFile(panel);
2973 break;
2974 case CPmenuRename:
2975 customPaletteMenuRename(panel);
2976 break;
2977 case CPmenuRemove:
2978 customPaletteMenuRemove(panel);
2979 break;
2980 case CPmenuCopy:
2981 break;
2982 case CPmenuNewFromClipboard:
2983 break;
2987 static void customPaletteMenuNewFromFile(W_ColorPanel * panel)
2989 W_Screen *scr = WMWidgetScreen(panel->win);
2990 WMOpenPanel *browseP;
2991 char *filepath;
2992 char *filename = NULL;
2993 char *spath;
2994 char *tmp;
2995 int i;
2996 RImage *tmpImg = NULL;
2998 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir, "\0") == 0))
2999 spath = wexpandpath(wgethomedir());
3000 else
3001 spath = wexpandpath(panel->lastBrowseDir);
3003 browseP = WMGetOpenPanel(scr);
3004 WMSetFilePanelCanChooseDirectories(browseP, 0);
3005 WMSetFilePanelCanChooseFiles(browseP, 1);
3007 /* Get a filename */
3008 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
3009 _("Open Palette"), RSupportedFileFormats())) {
3010 filepath = WMGetFilePanelFileName(browseP);
3012 /* Get seperation position between path and filename */
3013 i = strrchr(filepath, '/') - filepath + 1;
3014 if (i > strlen(filepath))
3015 i = strlen(filepath);
3017 /* Store last browsed path */
3018 if (panel->lastBrowseDir)
3019 wfree(panel->lastBrowseDir);
3020 panel->lastBrowseDir = wmalloc((i + 1) * sizeof(char));
3021 strncpy(panel->lastBrowseDir, filepath, i);
3022 panel->lastBrowseDir[i] = '\0';
3024 /* Get filename from path */
3025 filename = wstrdup(filepath + i);
3027 /* Check for duplicate files, and rename it if there are any */
3028 tmp = wstrconcat(panel->configurationPath, filename);
3029 while (access(tmp, F_OK) == 0) {
3030 char *newName;
3032 wfree(tmp);
3034 newName = generateNewFilename(filename);
3035 wfree(filename);
3036 filename = newName;
3038 tmp = wstrconcat(panel->configurationPath, filename);
3040 wfree(tmp);
3042 /* Copy image to $(gnustepdir)/Library/Colors/ &
3043 * Add filename to history menu */
3044 if (wcopy_file(panel->configurationPath, filepath, filename) == 0) {
3046 /* filepath is a "local" path now the file has been copied */
3047 wfree(filepath);
3048 filepath = wstrconcat(panel->configurationPath, filename);
3050 /* load the image & add menu entries */
3051 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
3052 if (tmpImg) {
3053 if (panel->customPaletteImg)
3054 RReleaseImage(panel->customPaletteImg);
3055 panel->customPaletteImg = tmpImg;
3057 customSetPalette(panel);
3058 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
3060 panel->currentPalette =
3061 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1;
3063 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3064 panel->currentPalette);
3066 } else {
3067 tmp = wstrconcat(panel->configurationPath, filename);
3069 i = remove(tmp); /* Delete the file, it doesn't belong here */
3070 WMRunAlertPanel(scr, panel->win, _("File Error"),
3071 _("Invalid file format !"), _("OK"), NULL, NULL);
3072 if (i != 0) {
3073 werror(_("can't remove file %s"), tmp);
3074 WMRunAlertPanel(scr, panel->win, _("File Error"),
3075 _("Couldn't remove file from Configuration Directory !"),
3076 _("OK"), NULL, NULL);
3078 wfree(tmp);
3080 wfree(filepath);
3081 wfree(filename);
3083 WMFreeFilePanel(browseP);
3085 wfree(spath);
3088 static void customPaletteMenuRename(W_ColorPanel * panel)
3090 W_Screen *scr = WMWidgetScreen(panel->win);
3091 char *toName = NULL;
3092 char *fromName;
3093 char *toPath, *fromPath;
3094 int item;
3095 int index;
3097 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3098 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
3100 toName = WMRunInputPanel(scr, panel->win, _("Rename"), _("Rename palette to:"),
3101 fromName, _("OK"), _("Cancel"));
3103 if (toName) {
3105 /* As some people do certain stupid things... */
3106 if (strcmp(toName, fromName) == 0) {
3107 wfree(toName);
3108 return;
3111 /* For normal people */
3112 fromPath = wstrconcat(panel->configurationPath, fromName);
3113 toPath = wstrconcat(panel->configurationPath, toName);
3115 if (access(toPath, F_OK) == 0) {
3116 /* Careful, this palette exists already */
3117 if (WMRunAlertPanel(scr, panel->win, _("Warning"),
3118 _("Palette already exists !\n\nOverwrite ?"), _("No"), _("Yes"),
3119 NULL) == 1) {
3120 /* "No" = 0, "Yes" = 1 */
3121 int items = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
3123 remove(toPath);
3125 /* Remove from History list too */
3126 index = 1;
3127 while ((index < items)
3129 (strcmp(WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, index), toName)
3130 != 0))
3131 index++;
3133 if (index < items) {
3134 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, index);
3135 if (index < item)
3136 item--;
3139 } else {
3140 wfree(fromPath);
3141 wfree(toName);
3142 wfree(toPath);
3144 return;
3148 if (rename(fromPath, toPath) != 0)
3149 werror(_("Couldn't rename palette %s to %s"), fromName, toName);
3150 else {
3151 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3152 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item, toName);
3154 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
3156 wfree(fromPath);
3157 wfree(toPath);
3158 wfree(toName);
3162 static void customPaletteMenuRemove(W_ColorPanel * panel)
3164 W_Screen *scr = WMWidgetScreen(panel->win);
3165 char *text;
3166 char *tmp;
3167 int choice;
3168 int item;
3170 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3172 tmp = wstrconcat(_("This will permanently remove the palette "),
3173 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3174 text = wstrconcat(tmp, _(".\n\nAre you sure you want to remove this palette ?"));
3175 wfree(tmp);
3177 choice = WMRunAlertPanel(scr, panel->win, _("Remove"), text, _("Yes"), _("No"), NULL);
3178 /* returns 0 (= "Yes") or 1 (="No") */
3179 wfree(text);
3181 if (choice == 0) {
3183 tmp = wstrconcat(panel->configurationPath,
3184 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3186 if (remove(tmp) == 0) {
3187 /* item-1 always exists */
3188 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3190 customPaletteHistoryCallback(panel->customPaletteHistoryBtn, panel);
3191 customSetPalette(panel);
3193 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3195 } else {
3196 werror(_("Couldn't remove palette %s"), tmp);
3199 wfree(tmp);
3203 static void customPaletteHistoryCallback(WMWidget * w, void *data)
3205 W_ColorPanel *panel = (W_ColorPanel *) data;
3206 W_Screen *scr = WMWidgetScreen(panel->win);
3207 int item;
3208 char *filename;
3209 RImage *tmp = NULL;
3210 unsigned char perm_mask;
3212 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3213 if (item == panel->currentPalette)
3214 return;
3216 if (item == 0) {
3217 customRenderSpectrum(panel);
3219 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, False);
3220 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, False);
3221 } else {
3222 /* Load file from configpath */
3223 filename = wstrconcat(panel->configurationPath,
3224 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3226 /* If the file corresponding to the item does not exist,
3227 * remove it from the history list and select the next one.
3229 perm_mask = (access(filename, F_OK) == 0);
3230 if (!perm_mask) {
3231 /* File does not exist */
3232 wfree(filename);
3233 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3234 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3235 customPaletteHistoryCallback(w, data);
3236 return;
3239 /* Get the image */
3240 tmp = RLoadImage(scr->rcontext, filename, 0);
3241 if (tmp) {
3242 if (panel->customPaletteImg) {
3243 RReleaseImage(panel->customPaletteImg);
3244 panel->customPaletteImg = NULL;
3246 panel->customPaletteImg = tmp;
3249 /* If the image is not writable, don't allow removing/renaming */
3250 perm_mask = (access(filename, W_OK) == 0);
3251 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, perm_mask);
3252 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, perm_mask);
3254 wfree(filename);
3256 customSetPalette(panel);
3258 panel->currentPalette = item;
3261 /************************* ColorList Panel Functions **********************/
3263 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect)
3265 WMScreen *scr = WMWidgetScreen(lPtr);
3266 Display *dpy = WMScreenDisplay(scr);
3267 WMView *view = W_VIEW(lPtr);
3268 RColor *color = (RColor *) WMGetListItem(lPtr, index)->clientData;
3269 W_ColorPanel *panel = WMGetHangedData(lPtr);
3270 int width, height, x, y;
3271 WMColor *fillColor;
3273 width = rect->size.width;
3274 height = rect->size.height;
3275 x = rect->pos.x;
3276 y = rect->pos.y;
3278 if (state & WLDSSelected)
3279 XFillRectangle(dpy, d, WMColorGC(scr->white), x, y, width, height);
3280 else
3281 XFillRectangle(dpy, d, WMColorGC(view->backColor), x, y, width, height);
3283 fillColor = WMCreateRGBColor(scr, color->red << 8, color->green << 8, color->blue << 8, True);
3285 XFillRectangle(dpy, d, WMColorGC(fillColor), x, y, 15, height);
3286 WMReleaseColor(fillColor);
3288 WMDrawString(scr, d, scr->black, panel->font12, x + 18, y, text, strlen(text));
3291 static void colorListSelect(WMWidget * w, void *data)
3293 W_ColorPanel *panel = (W_ColorPanel *) data;
3294 CPColor cpColor;
3296 cpColor.rgb = *((RColor *) WMGetListSelectedItem(w)->clientData);
3297 cpColor.set = cpRGB;
3299 panel->lastChanged = WMColorListModeColorPanel;
3300 updateSwatch(panel, cpColor);
3303 static void colorListColorMenuCallback(WMWidget * w, void *data)
3305 W_ColorPanel *panel = (W_ColorPanel *) data;
3306 int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
3308 /* Parameter not used, but tell the compiler that it is ok */
3309 (void) w;
3311 switch (item) {
3312 case CLmenuAdd:
3313 break;
3314 case CLmenuRename:
3315 break;
3316 case CLmenuRemove:
3317 break;
3321 static void colorListListMenuCallback(WMWidget * w, void *data)
3323 W_ColorPanel *panel = (W_ColorPanel *) data;
3324 int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
3326 /* Parameter not used, but tell the compiler that it is ok */
3327 (void) w;
3329 switch (item) {
3330 case CLmenuAdd:
3331 break;
3332 case CLmenuRename:
3333 break;
3334 case CLmenuRemove:
3335 break;
3339 /*************** Panel Initialisation Functions *****************/
3341 static void wheelInit(W_ColorPanel * panel)
3343 CPColor cpColor;
3345 if (panel->color.set != cpHSV)
3346 convertCPColor(&panel->color);
3348 WMSetSliderValue(panel->wheelBrightnessS, 255 - panel->color.hsv.value);
3350 panel->colx = 2 + rint((colorWheelSize / 2.0) *
3351 (1 + (panel->color.hsv.saturation / 255.0) *
3352 cos(panel->color.hsv.hue * WM_PI / 180.0)));
3353 panel->coly = 2 + rint((colorWheelSize / 2.0) *
3354 (1 + (panel->color.hsv.saturation / 255.0) *
3355 sin(-panel->color.hsv.hue * WM_PI / 180.0)));
3357 wheelCalculateValues(panel, panel->color.hsv.value);
3359 cpColor = panel->color;
3360 cpColor.hsv.value = 255;
3361 cpColor.set = cpHSV;
3362 wheelUpdateBrightnessGradient(panel, cpColor);
3365 static void grayInit(W_ColorPanel * panel)
3367 int value;
3368 char tmp[4];
3370 if (panel->color.set != cpHSV)
3371 convertCPColor(&panel->color);
3373 value = rint(panel->color.hsv.value / 2.55);
3374 WMSetSliderValue(panel->grayBrightnessS, value);
3376 sprintf(tmp, "%d", value);
3377 WMSetTextFieldText(panel->grayBrightnessT, tmp);
3380 static void rgbInit(W_ColorPanel * panel)
3382 char tmp[4];
3383 const char *format;
3385 if (panel->color.set != cpRGB)
3386 convertCPColor(&panel->color);
3388 WMSetSliderValue(panel->rgbRedS, panel->color.rgb.red);
3389 WMSetSliderValue(panel->rgbGreenS, panel->color.rgb.green);
3390 WMSetSliderValue(panel->rgbBlueS, panel->color.rgb.blue);
3392 switch (panel->rgbState) {
3393 case RGBdec:
3394 format = "%d";
3395 break;
3396 case RGBhex:
3397 format = "%0X";
3398 break;
3401 sprintf(tmp, format, panel->color.rgb.red);
3402 WMSetTextFieldText(panel->rgbRedT, tmp);
3403 sprintf(tmp, format, panel->color.rgb.green);
3404 WMSetTextFieldText(panel->rgbGreenT, tmp);
3405 sprintf(tmp, format, panel->color.rgb.blue);
3406 WMSetTextFieldText(panel->rgbBlueT, tmp);
3409 static void cmykInit(W_ColorPanel * panel)
3411 int value[3];
3412 char tmp[4];
3414 if (panel->color.set != cpRGB)
3415 convertCPColor(&panel->color);
3417 value[0] = rint((255 - panel->color.rgb.red) / 2.55);
3418 value[1] = rint((255 - panel->color.rgb.green) / 2.55);
3419 value[2] = rint((255 - panel->color.rgb.blue) / 2.55);
3421 WMSetSliderValue(panel->cmykCyanS, value[0]);
3422 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3423 WMSetSliderValue(panel->cmykYellowS, value[2]);
3424 WMSetSliderValue(panel->cmykBlackS, 0);
3426 sprintf(tmp, "%d", value[0]);
3427 WMSetTextFieldText(panel->cmykCyanT, tmp);
3428 sprintf(tmp, "%d", value[1]);
3429 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3430 sprintf(tmp, "%d", value[2]);
3431 WMSetTextFieldText(panel->cmykYellowT, tmp);
3432 WMSetTextFieldText(panel->cmykBlackT, "0");
3435 static void hsbInit(W_ColorPanel * panel)
3437 int value[3];
3438 char tmp[4];
3440 if (panel->color.set != cpHSV)
3441 convertCPColor(&panel->color);
3443 value[0] = panel->color.hsv.hue;
3444 value[1] = rint(panel->color.hsv.saturation / 2.55);
3445 value[2] = rint(panel->color.hsv.value / 2.55);
3447 WMSetSliderValue(panel->hsbHueS, value[0]);
3448 WMSetSliderValue(panel->hsbSaturationS, value[1]);
3449 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
3451 sprintf(tmp, "%d", value[0]);
3452 WMSetTextFieldText(panel->hsbHueT, tmp);
3453 sprintf(tmp, "%d", value[1]);
3454 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3455 sprintf(tmp, "%d", value[2]);
3456 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3458 hsbUpdateBrightnessGradient(panel);
3459 hsbUpdateSaturationGradient(panel);
3460 hsbUpdateHueGradient(panel);
3463 /************************** Common utility functions ************************/
3465 static char *generateNewFilename(const char *curName)
3467 int n;
3468 char c;
3469 int baseLen;
3470 const char *ptr;
3471 char *newName;
3473 assert(curName);
3475 ptr = curName;
3477 if (((ptr = strrchr(ptr, '{')) == 0) || sscanf(ptr, "{%i}%c", &n, &c) != 1)
3478 return wstrconcat(curName, " {1}");
3480 baseLen = ptr - curName - 1;
3482 newName = wmalloc(baseLen + 16);
3483 strncpy(newName, curName, baseLen);
3485 snprintf(&newName[baseLen], 16, " {%i}", n + 1);
3487 return newName;
3490 static void convertCPColor(CPColor * color)
3492 unsigned short old_hue = 0;
3494 switch (color->set) {
3495 case cpNone:
3496 wwarning(_("Color Panel: Color unspecified"));
3497 return;
3498 case cpRGB:
3499 old_hue = color->hsv.hue;
3500 RRGBtoHSV(&(color->rgb), &(color->hsv));
3502 /* In black the hue is undefined, and may change by conversion
3503 * Same for white. */
3504 if (((color->rgb.red == 0) &&
3505 (color->rgb.green == 0) &&
3506 (color->rgb.blue == 0)) ||
3507 ((color->rgb.red == 0) && (color->rgb.green == 0) && (color->rgb.blue == 255))
3509 color->hsv.hue = old_hue;
3510 break;
3511 case cpHSV:
3512 RHSVtoRGB(&(color->hsv), &(color->rgb));
3513 break;
3517 static RColor ulongToRColor(WMScreen * scr, unsigned long value)
3519 RColor color;
3520 XColor *xcolor = NULL;
3522 xcolor = wmalloc(sizeof(XColor));
3523 xcolor->pixel = value;
3524 XQueryColor(scr->display, scr->rcontext->cmap, xcolor);
3526 color.red = xcolor->red >> 8;
3527 color.green = xcolor->green >> 8;
3528 color.blue = xcolor->blue >> 8;
3529 color.alpha = 0;
3531 wfree(xcolor);
3533 return color;
3536 static unsigned char getShift(unsigned char value)
3538 unsigned char i = -1;
3540 if (value == 0)
3541 return 0;
3543 while (value) {
3544 value >>= 1;
3545 i++;
3548 return i;