Mac OS X-style window cycling.
[wmaker-crm.git] / WINGs / wcolorpanel.c
blob8612e5e754d6e5c169104c5a3354695636c170db
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"
29 #include <math.h>
30 #include <unistd.h>
31 #include <ctype.h>
32 #include <fcntl.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <dirent.h>
36 #include <errno.h>
38 /* BUG There's something fishy with shaped windows */
39 /* Whithout shape extension the magnified image is completely broken -Dan */
40 #if 0
41 # ifdef SHAPE
42 # define SHAPE_WAS_DEFINED
43 # undef SHAPE
44 # endif
45 #endif
47 #ifdef SHAPE
48 # include <X11/extensions/shape.h>
49 #endif
51 char *WMColorPanelColorChangedNotification = "WMColorPanelColorChangedNotification";
54 * Bitmaps for magnifying glass cursor
57 /* Cursor */
58 #define Cursor_x_hot 11
59 #define Cursor_y_hot 11
60 #define Cursor_width 32
61 #define Cursor_height 32
62 static unsigned char Cursor_bits[] = {
63 0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
64 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
65 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
66 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
67 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
68 0x00, 0x08, 0x00, 0x50, 0x00, 0x10, 0x00, 0x88, 0x00, 0x20, 0x00, 0x5c, 0x01, 0xc0, 0x81,
69 0x3b, 0x02, 0x00, 0x7e, 0x70, 0x05, 0x00, 0x00, 0xe0, 0x08, 0x00, 0x00, 0xc0, 0x15, 0x00,
70 0x00, 0x80, 0x23, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x5c,
71 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x70
74 /* Cursor shape-mask */
75 #define Cursor_shape_width 32
76 #define Cursor_shape_height 32
77 static unsigned char Cursor_shape_bits[] = {
78 0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
79 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
80 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
81 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
82 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
83 0x00, 0x08, 0x00, 0x70, 0x00, 0x10, 0x00, 0xf8, 0x00, 0x20, 0x00, 0xfc, 0x01, 0xc0, 0x81,
84 0xfb, 0x03, 0x00, 0x7e, 0xf0, 0x07, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xc0, 0x1f, 0x00,
85 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xfc,
86 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x70
89 /* Clip-mask for magnified pixels */
90 #define Cursor_mask_width 24
91 #define Cursor_mask_height 24
92 static unsigned char Cursor_mask_bits[] = {
93 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0xff, 0x07,
94 0xf0, 0xff, 0x0f, 0xf8, 0xff, 0x1f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f,
95 0xfc, 0xff, 0x3f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f,
96 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfc, 0xff, 0x3f,
97 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xf8, 0xff, 0x1f, 0xf0, 0xff, 0x0f,
98 0xe0, 0xff, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00
101 typedef struct MovingView {
102 WMView *view; /* The view this is all about */
103 XImage *image; /* What's under the view */
104 XImage *dirtyRect; /* Storage of overlapped image area */
105 Pixmap magPix; /* Magnified part of pixmap */
106 RColor color; /* Color of a pixel in the image */
107 int x, y; /* Position of view */
108 } MovingView;
110 typedef struct CPColor {
111 RColor rgb; /* The RGB values of the color */
112 RHSVColor hsv; /* The HSV values of the color */
113 enum { /* Which one was last set ? */
114 cpNone,
115 cpRGB,
116 cpHSV
117 } set;
118 } CPColor;
120 typedef struct WheelMatrix {
121 unsigned int width, height; /* Size of the colorwheel */
122 unsigned char *data[3]; /* Wheel data (R,G,B) */
123 unsigned char values[256]; /* Precalculated values R,G & B = 0-255 */
124 } wheelMatrix;
126 typedef struct W_ColorPanel {
127 WMWindow *win;
128 WMFont *font8;
129 WMFont *font12;
130 void *clientData;
131 WMAction2 *action;
133 /* Common Stuff */
134 WMColorWell *colorWell;
135 WMButton *magnifyBtn;
136 WMButton *wheelBtn;
137 WMButton *slidersBtn;
138 WMButton *customPaletteBtn;
139 WMButton *colorListBtn;
141 /* Magnifying Glass */
142 MovingView *magnifyGlass;
144 /* ColorWheel Panel */
145 WMFrame *wheelFrm;
146 WMSlider *wheelBrightnessS;
147 WMView *wheelView;
149 /* Slider Panels */
150 WMFrame *slidersFrm;
151 WMFrame *seperatorFrm;
152 WMButton *grayBtn;
153 WMButton *rgbBtn;
154 WMButton *cmykBtn;
155 WMButton *hsbBtn;
156 /* Gray Scale Panel */
157 WMFrame *grayFrm;
158 WMLabel *grayMinL;
159 WMLabel *grayMaxL;
160 WMSlider *grayBrightnessS;
161 WMTextField *grayBrightnessT;
162 WMButton *grayPresetBtn[7];
164 /* RGB Panel */
165 WMFrame *rgbFrm;
166 WMLabel *rgbMinL;
167 WMLabel *rgbMaxL;
168 WMSlider *rgbRedS;
169 WMSlider *rgbGreenS;
170 WMSlider *rgbBlueS;
171 WMTextField *rgbRedT;
172 WMTextField *rgbGreenT;
173 WMTextField *rgbBlueT;
175 /* CMYK Panel */
176 WMFrame *cmykFrm;
177 WMLabel *cmykMinL;
178 WMLabel *cmykMaxL;
179 WMSlider *cmykCyanS;
180 WMSlider *cmykMagentaS;
181 WMSlider *cmykYellowS;
182 WMSlider *cmykBlackS;
183 WMTextField *cmykCyanT;
184 WMTextField *cmykMagentaT;
185 WMTextField *cmykYellowT;
186 WMTextField *cmykBlackT;
188 /* HSB Panel */
189 WMFrame *hsbFrm;
190 WMSlider *hsbHueS;
191 WMSlider *hsbSaturationS;
192 WMSlider *hsbBrightnessS;
193 WMTextField *hsbHueT;
194 WMTextField *hsbSaturationT;
195 WMTextField *hsbBrightnessT;
197 /* Custom Palette Panel */
198 WMFrame *customPaletteFrm;
199 WMPopUpButton *customPaletteHistoryBtn;
200 WMFrame *customPaletteContentFrm;
201 WMPopUpButton *customPaletteMenuBtn;
202 WMView *customPaletteContentView;
204 /* Color List Panel */
205 WMFrame *colorListFrm;
206 WMPopUpButton *colorListHistoryBtn;
207 WMList *colorListContentLst;
208 WMPopUpButton *colorListColorMenuBtn;
209 WMPopUpButton *colorListListMenuBtn;
211 /* Look-Up Tables and Images */
212 wheelMatrix *wheelMtrx;
213 Pixmap wheelImg;
214 Pixmap selectionImg;
215 Pixmap selectionBackImg;
216 RImage *customPaletteImg;
217 char *lastBrowseDir;
219 /* Common Data Fields */
220 CPColor color; /* Current color */
221 WMColorPanelMode mode; /* Current color selection mode */
222 WMColorPanelMode slidersmode; /* Current color sel. mode sliders panel */
223 WMColorPanelMode lastChanged; /* Panel that last changed the color */
224 int colx, coly; /* (x,y) of sel.-marker in WheelMode */
225 int palx, paly; /* (x,y) of sel.-marker in
226 CustomPaletteMode */
227 double palXRatio, palYRatio; /* Ratios in x & y between
228 original and scaled
229 palettesize */
230 int currentPalette;
231 char *configurationPath;
233 struct {
234 unsigned int continuous:1;
235 unsigned int dragging:1;
236 } flags;
237 } W_ColorPanel;
239 enum {
240 CPmenuNewFromFile,
241 CPmenuRename,
242 CPmenuRemove,
243 CPmenuCopy,
244 CPmenuNewFromClipboard
245 } customPaletteMenuItem;
247 enum {
248 CLmenuAdd,
249 CLmenuRename,
250 CLmenuRemove
251 } colorListMenuItem;
253 #define PWIDTH 194
254 #define PHEIGHT 266
255 #define colorWheelSize 150
256 #define customPaletteWidth 182
257 #define customPaletteHeight 106
258 #define knobThickness 8
260 #define SPECTRUM_WIDTH 511
261 #define SPECTRUM_HEIGHT 360
263 #define COLORWHEEL_PART 1
264 #define CUSTOMPALETTE_PART 2
265 #define BUFSIZE 1024
267 #define MAX_LENGTH 1024
269 #ifndef M_PI
270 #define M_PI 3.14159265358979323846
271 #endif
273 /* Silly hack for Windows systems with cygwin */
274 #ifndef O_BINARY
275 # define O_BINARY 0
276 #endif
278 static int fetchFile(char *toPath, char *imageSrcFile, char *imageDestFileName);
279 char *generateNewFilename(char *curName);
280 void convertCPColor(CPColor * color);
281 RColor ulongToRColor(WMScreen * scr, unsigned long value);
282 unsigned char getShift(unsigned char value);
284 static void modeButtonCallback(WMWidget * w, void *data);
285 static int getPickerPart(W_ColorPanel * panel, int x, int y);
286 static void readConfiguration(W_ColorPanel * panel);
287 static void readXColors(W_ColorPanel * panel);
289 static void closeWindowCallback(WMWidget * w, void *data);
291 static Cursor magnifyGrabPointer(W_ColorPanel * panel);
292 static WMPoint magnifyInitialize(W_ColorPanel * panel);
293 static void magnifyPutCursor(WMWidget * w, void *data);
294 static Pixmap magnifyCreatePixmap(WMColorPanel * panel);
295 static void magnifyGetImageStored(W_ColorPanel * panel, int x1, int y1, int x2, int y2);
296 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h);
298 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height);
299 static void wheelDestroyMatrix(wheelMatrix * matrix);
300 static void wheelInitMatrix(W_ColorPanel * panel);
301 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue);
302 static void wheelRender(W_ColorPanel * panel);
303 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs);
304 static void wheelPaint(W_ColorPanel * panel);
306 static void wheelHandleEvents(XEvent * event, void *data);
307 static void wheelHandleActionEvents(XEvent * event, void *data);
308 static void wheelBrightnessSliderCallback(WMWidget * w, void *data);
309 static void wheelUpdateSelection(W_ColorPanel * panel);
310 static void wheelUndrawSelection(W_ColorPanel * panel);
312 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y);
313 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
314 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel);
315 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor);
317 static void grayBrightnessSliderCallback(WMWidget * w, void *data);
318 static void grayPresetButtonCallback(WMWidget * w, void *data);
319 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification);
321 static void rgbSliderCallback(WMWidget * w, void *data);
322 static void rgbTextFieldCallback(void *observerData, WMNotification * notification);
324 static void cmykSliderCallback(WMWidget * w, void *data);
325 static void cmykTextFieldCallback(void *observerData, WMNotification * notification);
327 static void hsbSliderCallback(WMWidget * w, void *data);
328 static void hsbTextFieldCallback(void *observerData, WMNotification * notification);
329 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel);
330 static void hsbUpdateSaturationGradient(W_ColorPanel * panel);
331 static void hsbUpdateHueGradient(W_ColorPanel * panel);
333 static void customRenderSpectrum(W_ColorPanel * panel);
334 static void customSetPalette(W_ColorPanel * panel);
335 static void customPaletteHandleEvents(XEvent * event, void *data);
336 static void customPaletteHandleActionEvents(XEvent * event, void *data);
337 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y);
338 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
339 static void customPaletteMenuCallback(WMWidget * w, void *data);
340 static void customPaletteHistoryCallback(WMWidget * w, void *data);
342 static void customPaletteMenuNewFromFile(W_ColorPanel * panel);
343 static void customPaletteMenuRename(W_ColorPanel * panel);
344 static void customPaletteMenuRemove(W_ColorPanel * panel);
346 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect);
347 static void colorListSelect(WMWidget * w, void *data);
348 static void colorListColorMenuCallback(WMWidget * w, void *data);
349 static void colorListListMenuCallback(WMWidget * w, void *data);
350 static void colorListListMenuNew(W_ColorPanel * panel);
352 static void wheelInit(W_ColorPanel * panel);
353 static void grayInit(W_ColorPanel * panel);
354 static void rgbInit(W_ColorPanel * panel);
355 static void cmykInit(W_ColorPanel * panel);
356 static void hsbInit(W_ColorPanel * panel);
358 void WMSetColorPanelAction(WMColorPanel * panel, WMAction2 * action, void *data)
360 panel->action = action;
361 panel->clientData = data;
364 static WMColorPanel *makeColorPanel(WMScreen * scrPtr, char *name)
366 WMColorPanel *panel;
367 RImage *image;
368 WMPixmap *pixmap;
369 RColor from;
370 RColor to;
371 WMColor *textcolor, *graybuttoncolor;
372 int i;
373 GC bgc = WMColorGC(scrPtr->black);
374 GC wgc = WMColorGC(scrPtr->white);
376 panel = wmalloc(sizeof(WMColorPanel));
377 memset(panel, 0, sizeof(WMColorPanel));
379 panel->color.rgb.red = 0;
380 panel->color.rgb.green = 0;
381 panel->color.rgb.blue = 0;
382 panel->color.hsv.hue = 0;
383 panel->color.hsv.saturation = 0;
384 panel->color.hsv.value = 0;
385 panel->color.set = cpNone; /* Color has not been set yet */
387 panel->font8 = WMSystemFontOfSize(scrPtr, 8);
388 panel->font12 = WMSystemFontOfSize(scrPtr, 12);
390 panel->win = WMCreateWindowWithStyle(scrPtr, name,
391 WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
392 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
393 WMSetWindowTitle(panel->win, _("Colors"));
394 WMSetWindowCloseAction(panel->win, closeWindowCallback, panel);
396 /* Set Default ColorPanel Mode(s) */
397 panel->mode = WMWheelModeColorPanel;
398 panel->lastChanged = 0;
399 panel->slidersmode = WMRGBModeColorPanel;
400 panel->configurationPath = wstrconcat(wusergnusteppath(), "/Library/Colors/");
402 /* Some General Purpose Widgets */
403 panel->colorWell = WMCreateColorWell(panel->win);
404 WMResizeWidget(panel->colorWell, 134, 36);
405 WSetColorWellBordered(panel->colorWell, False);
406 WMMoveWidget(panel->colorWell, 56, 4);
408 panel->magnifyBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
409 WMResizeWidget(panel->magnifyBtn, 46, 36);
410 WMMoveWidget(panel->magnifyBtn, 6, 4);
411 WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
412 WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
413 WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
415 panel->wheelBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
416 WMResizeWidget(panel->wheelBtn, 46, 32);
417 WMMoveWidget(panel->wheelBtn, 6, 44);
418 WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
419 WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
420 WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
422 panel->slidersBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
423 WMResizeWidget(panel->slidersBtn, 46, 32);
424 WMMoveWidget(panel->slidersBtn, 52, 44);
425 WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
426 WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
427 WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
429 panel->customPaletteBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
430 WMResizeWidget(panel->customPaletteBtn, 46, 32);
431 WMMoveWidget(panel->customPaletteBtn, 98, 44);
432 WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
433 WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
434 WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
436 panel->colorListBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
437 WMResizeWidget(panel->colorListBtn, 46, 32);
438 WMMoveWidget(panel->colorListBtn, 144, 44);
439 WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
440 WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
441 WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
443 /* Let's Group some of them together */
444 WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
445 WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
446 WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
448 /* Widgets for the ColorWheel Panel */
449 panel->wheelFrm = WMCreateFrame(panel->win);
450 WMSetFrameRelief(panel->wheelFrm, WRFlat);
451 WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
452 WMMoveWidget(panel->wheelFrm, 5, 80);
454 panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
455 /* XXX Can we create a view ? */
456 W_ResizeView(panel->wheelView, colorWheelSize + 4, colorWheelSize + 4);
457 W_MoveView(panel->wheelView, 0, 0);
459 /* Create an event handler to handle expose/click events in ColorWheel */
460 WMCreateEventHandler(panel->wheelView,
461 ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
462 LeaveWindowMask | ButtonMotionMask, wheelHandleActionEvents, panel);
464 WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents, panel);
466 panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
467 WMResizeWidget(panel->wheelBrightnessS, 16, 153);
468 WMMoveWidget(panel->wheelBrightnessS, 5 + colorWheelSize + 14, 1);
469 WMSetSliderMinValue(panel->wheelBrightnessS, 0);
470 WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
471 WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback, panel);
472 WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
474 panel->wheelMtrx = wheelCreateMatrix(colorWheelSize + 4, colorWheelSize + 4);
475 wheelInitMatrix(panel);
477 /* Widgets for the Slider Panels */
478 panel->slidersFrm = WMCreateFrame(panel->win);
479 WMSetFrameRelief(panel->slidersFrm, WRFlat);
480 WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
481 WMMoveWidget(panel->slidersFrm, 4, 80);
483 panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
484 WMSetFrameRelief(panel->seperatorFrm, WRPushed);
485 WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
486 WMMoveWidget(panel->seperatorFrm, 0, 1);
488 panel->grayBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
489 WMResizeWidget(panel->grayBtn, 46, 24);
490 WMMoveWidget(panel->grayBtn, 1, 8);
491 WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
492 WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
493 WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
495 panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
496 WMResizeWidget(panel->rgbBtn, 46, 24);
497 WMMoveWidget(panel->rgbBtn, 47, 8);
498 WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
499 WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
500 WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
502 panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
503 WMResizeWidget(panel->cmykBtn, 46, 24);
504 WMMoveWidget(panel->cmykBtn, 93, 8);
505 WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
506 WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
507 WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
509 panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
510 WMResizeWidget(panel->hsbBtn, 46, 24);
511 WMMoveWidget(panel->hsbBtn, 139, 8);
512 WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
513 WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
514 WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
516 /* Let's Group the Slider Panel Buttons Together */
517 WMGroupButtons(panel->grayBtn, panel->rgbBtn);
518 WMGroupButtons(panel->grayBtn, panel->cmykBtn);
519 WMGroupButtons(panel->grayBtn, panel->hsbBtn);
521 textcolor = WMDarkGrayColor(scrPtr);
523 /* Widgets for GrayScale Panel */
524 panel->grayFrm = WMCreateFrame(panel->slidersFrm);
525 WMSetFrameRelief(panel->grayFrm, WRFlat);
526 WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
527 WMMoveWidget(panel->grayFrm, 0, 34);
529 panel->grayMinL = WMCreateLabel(panel->grayFrm);
530 WMResizeWidget(panel->grayMinL, 20, 10);
531 WMMoveWidget(panel->grayMinL, 2, 2);
532 WMSetLabelText(panel->grayMinL, "0");
533 WMSetLabelTextAlignment(panel->grayMinL, WALeft);
534 WMSetLabelTextColor(panel->grayMinL, textcolor);
535 WMSetLabelFont(panel->grayMinL, panel->font8);
537 panel->grayMaxL = WMCreateLabel(panel->grayFrm);
538 WMResizeWidget(panel->grayMaxL, 40, 10);
539 WMMoveWidget(panel->grayMaxL, 104, 2);
540 WMSetLabelText(panel->grayMaxL, "100");
541 WMSetLabelTextAlignment(panel->grayMaxL, WARight);
542 WMSetLabelTextColor(panel->grayMaxL, textcolor);
543 WMSetLabelFont(panel->grayMaxL, panel->font8);
545 panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
546 WMResizeWidget(panel->grayBrightnessS, 141, 16);
547 WMMoveWidget(panel->grayBrightnessS, 2, 14);
548 WMSetSliderMinValue(panel->grayBrightnessS, 0);
549 WMSetSliderMaxValue(panel->grayBrightnessS, 100);
550 WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
551 WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback, panel);
553 from.red = 0;
554 from.green = 0;
555 from.blue = 0;
557 to.red = 255;
558 to.green = 255;
559 to.blue = 255;
561 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
562 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
563 RReleaseImage(image);
565 if (pixmap)
566 W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap,
567 panel->font12, 2, 0, 100, WALeft, scrPtr->white,
568 False, _("Brightness"), strlen(_("Brightness")));
569 else
570 wwarning(_("Color Panel: Could not allocate memory"));
572 WMSetSliderImage(panel->grayBrightnessS, pixmap);
573 WMReleasePixmap(pixmap);
575 panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
576 WMResizeWidget(panel->grayBrightnessT, 40, 18);
577 WMMoveWidget(panel->grayBrightnessT, 146, 13);
578 WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
579 WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel,
580 WMTextDidEndEditingNotification, panel->grayBrightnessT);
582 for (i = 0; i < 7; i++) {
583 pixmap = WMCreatePixmap(scrPtr, 13, 13, scrPtr->depth, False);
585 graybuttoncolor = WMCreateRGBColor(scrPtr, (255 / 6) * i << 8,
586 (255 / 6) * i << 8, (255 / 6) * i << 8, True);
587 WMPaintColorSwatch(graybuttoncolor, pixmap->pixmap, 0, 0, 15, 15);
588 WMReleaseColor(graybuttoncolor);
590 panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
591 WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
592 WMMoveWidget(panel->grayPresetBtn[i], 2 + (i * 20), 34);
593 WMSetButtonAction(panel->grayPresetBtn[i], grayPresetButtonCallback, panel);
594 WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
595 WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
596 WMReleasePixmap(pixmap);
600 /* End of GrayScale Panel */
602 /* Widgets for RGB Panel */
603 panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
604 WMSetFrameRelief(panel->rgbFrm, WRFlat);
605 WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
606 WMMoveWidget(panel->rgbFrm, 0, 34);
608 panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
609 WMResizeWidget(panel->rgbMinL, 20, 10);
610 WMMoveWidget(panel->rgbMinL, 2, 2);
611 WMSetLabelText(panel->rgbMinL, "0");
612 WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
613 WMSetLabelTextColor(panel->rgbMinL, textcolor);
614 WMSetLabelFont(panel->rgbMinL, panel->font8);
616 panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
617 WMResizeWidget(panel->rgbMaxL, 40, 10);
618 WMMoveWidget(panel->rgbMaxL, 104, 2);
619 WMSetLabelText(panel->rgbMaxL, "255");
620 WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
621 WMSetLabelTextColor(panel->rgbMaxL, textcolor);
622 WMSetLabelFont(panel->rgbMaxL, panel->font8);
624 panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
625 WMResizeWidget(panel->rgbRedS, 141, 16);
626 WMMoveWidget(panel->rgbRedS, 2, 14);
627 WMSetSliderMinValue(panel->rgbRedS, 0);
628 WMSetSliderMaxValue(panel->rgbRedS, 255);
629 WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
630 WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
632 to.red = 255;
633 to.green = 0;
634 to.blue = 0;
636 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
637 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
638 RReleaseImage(image);
640 if (pixmap)
641 W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12,
642 2, 0, 100, WALeft, scrPtr->white, False, _("Red"), strlen(_("Red")));
643 else
644 wwarning(_("Color Panel: Could not allocate memory"));
646 WMSetSliderImage(panel->rgbRedS, pixmap);
647 WMReleasePixmap(pixmap);
649 panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
650 WMResizeWidget(panel->rgbRedT, 40, 18);
651 WMMoveWidget(panel->rgbRedT, 146, 13);
652 WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
653 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbRedT);
655 panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
656 WMResizeWidget(panel->rgbGreenS, 141, 16);
657 WMMoveWidget(panel->rgbGreenS, 2, 36);
658 WMSetSliderMinValue(panel->rgbGreenS, 0);
659 WMSetSliderMaxValue(panel->rgbGreenS, 255);
660 WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
661 WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
663 to.red = 0;
664 to.green = 255;
665 to.blue = 0;
667 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
668 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
669 RReleaseImage(image);
671 if (pixmap)
672 W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12,
673 2, 0, 100, WALeft, scrPtr->white, False, _("Green"), strlen(_("Green")));
674 else
675 wwarning(_("Color Panel: Could not allocate memory"));
677 WMSetSliderImage(panel->rgbGreenS, pixmap);
678 WMReleasePixmap(pixmap);
680 panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
681 WMResizeWidget(panel->rgbGreenT, 40, 18);
682 WMMoveWidget(panel->rgbGreenT, 146, 35);
683 WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
684 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbGreenT);
686 panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
687 WMResizeWidget(panel->rgbBlueS, 141, 16);
688 WMMoveWidget(panel->rgbBlueS, 2, 58);
689 WMSetSliderMinValue(panel->rgbBlueS, 0);
690 WMSetSliderMaxValue(panel->rgbBlueS, 255);
691 WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
692 WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
694 to.red = 0;
695 to.green = 0;
696 to.blue = 255;
698 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
699 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
700 RReleaseImage(image);
702 if (pixmap)
703 W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12,
704 2, 0, 100, WALeft, scrPtr->white, False, _("Blue"), strlen(_("Blue")));
705 else
706 wwarning(_("Color Panel: Could not allocate memory"));
708 WMSetSliderImage(panel->rgbBlueS, pixmap);
709 WMReleasePixmap(pixmap);
711 panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
712 WMResizeWidget(panel->rgbBlueT, 40, 18);
713 WMMoveWidget(panel->rgbBlueT, 146, 57);
714 WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
715 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbBlueT);
716 /* End of RGB Panel */
718 /* Widgets for CMYK Panel */
719 panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
720 WMSetFrameRelief(panel->cmykFrm, WRFlat);
721 WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
722 WMMoveWidget(panel->cmykFrm, 0, 34);
724 panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
725 WMResizeWidget(panel->cmykMinL, 20, 10);
726 WMMoveWidget(panel->cmykMinL, 2, 2);
727 WMSetLabelText(panel->cmykMinL, "0");
728 WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
729 WMSetLabelTextColor(panel->cmykMinL, textcolor);
730 WMSetLabelFont(panel->cmykMinL, panel->font8);
732 panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
733 WMResizeWidget(panel->cmykMaxL, 40, 10);
734 WMMoveWidget(panel->cmykMaxL, 104, 2);
735 WMSetLabelText(panel->cmykMaxL, "100");
736 WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
737 WMSetLabelTextColor(panel->cmykMaxL, textcolor);
738 WMSetLabelFont(panel->cmykMaxL, panel->font8);
740 panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
741 WMResizeWidget(panel->cmykCyanS, 141, 16);
742 WMMoveWidget(panel->cmykCyanS, 2, 14);
743 WMSetSliderMinValue(panel->cmykCyanS, 0);
744 WMSetSliderMaxValue(panel->cmykCyanS, 100);
745 WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
746 WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
748 from.red = 255;
749 from.green = 255;
750 from.blue = 255;
752 to.red = 0;
753 to.green = 255;
754 to.blue = 255;
756 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
757 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
758 RReleaseImage(image);
760 if (pixmap)
761 W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12,
762 2, 0, 100, WALeft, scrPtr->black, False, _("Cyan"), strlen(_("Cyan")));
763 else
764 wwarning(_("Color Panel: Could not allocate memory"));
766 WMSetSliderImage(panel->cmykCyanS, pixmap);
767 WMReleasePixmap(pixmap);
769 panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
770 WMResizeWidget(panel->cmykCyanT, 40, 18);
771 WMMoveWidget(panel->cmykCyanT, 146, 13);
772 WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
773 WMAddNotificationObserver(cmykTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->cmykCyanT);
775 panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
776 WMResizeWidget(panel->cmykMagentaS, 141, 16);
777 WMMoveWidget(panel->cmykMagentaS, 2, 36);
778 WMSetSliderMinValue(panel->cmykMagentaS, 0);
779 WMSetSliderMaxValue(panel->cmykMagentaS, 100);
780 WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
781 WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
783 to.red = 255;
784 to.green = 0;
785 to.blue = 255;
787 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
788 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
789 RReleaseImage(image);
791 if (pixmap)
792 W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12,
793 2, 0, 100, WALeft, scrPtr->black, False, _("Magenta"), strlen(_("Magenta")));
794 else
795 wwarning(_("Color Panel: Could not allocate memory"));
797 WMSetSliderImage(panel->cmykMagentaS, pixmap);
798 WMReleasePixmap(pixmap);
800 panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
801 WMResizeWidget(panel->cmykMagentaT, 40, 18);
802 WMMoveWidget(panel->cmykMagentaT, 146, 35);
803 WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
804 WMAddNotificationObserver(cmykTextFieldCallback, panel,
805 WMTextDidEndEditingNotification, panel->cmykMagentaT);
807 panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
808 WMResizeWidget(panel->cmykYellowS, 141, 16);
809 WMMoveWidget(panel->cmykYellowS, 2, 58);
810 WMSetSliderMinValue(panel->cmykYellowS, 0);
811 WMSetSliderMaxValue(panel->cmykYellowS, 100);
812 WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
813 WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
815 to.red = 255;
816 to.green = 255;
817 to.blue = 0;
819 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
820 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
821 RReleaseImage(image);
823 if (pixmap)
824 W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12,
825 2, 0, 100, WALeft, scrPtr->black, False, _("Yellow"), strlen(_("Yellow")));
826 else
827 wwarning(_("Color Panel: Could not allocate memory"));
829 WMSetSliderImage(panel->cmykYellowS, pixmap);
830 WMReleasePixmap(pixmap);
832 panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
833 WMResizeWidget(panel->cmykYellowT, 40, 18);
834 WMMoveWidget(panel->cmykYellowT, 146, 57);
835 WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
836 WMAddNotificationObserver(cmykTextFieldCallback, panel,
837 WMTextDidEndEditingNotification, panel->cmykYellowT);
839 panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
840 WMResizeWidget(panel->cmykBlackS, 141, 16);
841 WMMoveWidget(panel->cmykBlackS, 2, 80);
842 WMSetSliderMinValue(panel->cmykBlackS, 0);
843 WMSetSliderMaxValue(panel->cmykBlackS, 100);
844 WMSetSliderValue(panel->cmykBlackS, 0);
845 WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
846 WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
848 to.red = 0;
849 to.green = 0;
850 to.blue = 0;
852 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
853 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
854 RReleaseImage(image);
856 if (pixmap)
857 W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12,
858 2, 0, 100, WALeft, scrPtr->black, False, _("Black"), strlen(_("Black")));
859 else
860 wwarning(_("Color Panel: Could not allocate memory"));
862 WMSetSliderImage(panel->cmykBlackS, pixmap);
863 WMReleasePixmap(pixmap);
865 panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
866 WMResizeWidget(panel->cmykBlackT, 40, 18);
867 WMMoveWidget(panel->cmykBlackT, 146, 79);
868 WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
869 WMAddNotificationObserver(cmykTextFieldCallback, panel,
870 WMTextDidEndEditingNotification, panel->cmykBlackT);
871 /* End of CMYK Panel */
873 /* Widgets for HSB Panel */
874 panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
875 WMSetFrameRelief(panel->hsbFrm, WRFlat);
876 WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
877 WMMoveWidget(panel->hsbFrm, 0, 34);
879 panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
880 WMResizeWidget(panel->hsbHueS, 141, 16);
881 WMMoveWidget(panel->hsbHueS, 2, 14);
882 WMSetSliderMinValue(panel->hsbHueS, 0);
883 WMSetSliderMaxValue(panel->hsbHueS, 359);
884 WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
885 WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
887 panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
888 WMResizeWidget(panel->hsbHueT, 40, 18);
889 WMMoveWidget(panel->hsbHueT, 146, 13);
890 WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
891 WMAddNotificationObserver(hsbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->hsbHueT);
893 panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
894 WMResizeWidget(panel->hsbSaturationS, 141, 16);
895 WMMoveWidget(panel->hsbSaturationS, 2, 36);
896 WMSetSliderMinValue(panel->hsbSaturationS, 0);
897 WMSetSliderMaxValue(panel->hsbSaturationS, 100);
898 WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
899 WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
901 panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
902 WMResizeWidget(panel->hsbSaturationT, 40, 18);
903 WMMoveWidget(panel->hsbSaturationT, 146, 35);
904 WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
905 WMAddNotificationObserver(hsbTextFieldCallback, panel,
906 WMTextDidEndEditingNotification, panel->hsbSaturationT);
908 panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
909 WMResizeWidget(panel->hsbBrightnessS, 141, 16);
910 WMMoveWidget(panel->hsbBrightnessS, 2, 58);
911 WMSetSliderMinValue(panel->hsbBrightnessS, 0);
912 WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
913 WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
914 WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
916 panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
917 WMResizeWidget(panel->hsbBrightnessT, 40, 18);
918 WMMoveWidget(panel->hsbBrightnessT, 146, 57);
919 WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
920 WMAddNotificationObserver(hsbTextFieldCallback, panel,
921 WMTextDidEndEditingNotification, panel->hsbBrightnessT);
922 /* End of HSB Panel */
924 WMReleaseColor(textcolor);
926 /* Widgets for the CustomPalette Panel */
927 panel->customPaletteFrm = WMCreateFrame(panel->win);
928 WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
929 WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
930 WMMoveWidget(panel->customPaletteFrm, 5, 80);
932 panel->customPaletteHistoryBtn = WMCreatePopUpButton(panel->customPaletteFrm);
933 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, _("Spectrum"));
934 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
935 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1);
936 WMSetPopUpButtonAction(panel->customPaletteHistoryBtn, customPaletteHistoryCallback, panel);
937 WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
938 WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
940 panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
941 WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
942 WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
943 WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
945 panel->customPaletteContentView = W_CreateView(W_VIEW(panel->customPaletteContentFrm));
946 /* XXX Test if we can create a view */
947 W_ResizeView(panel->customPaletteContentView, customPaletteWidth, customPaletteHeight);
948 W_MoveView(panel->customPaletteContentView, 2, 2);
950 /* Create event handler to handle expose/click events in CustomPalette */
951 WMCreateEventHandler(panel->customPaletteContentView,
952 ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
953 ButtonMotionMask, customPaletteHandleActionEvents, panel);
955 WMCreateEventHandler(panel->customPaletteContentView, ExposureMask, customPaletteHandleEvents, panel);
957 panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
958 WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
959 WMSetPopUpButtonText(panel->customPaletteMenuBtn, _("Palette"));
960 WMSetPopUpButtonAction(panel->customPaletteMenuBtn, customPaletteMenuCallback, panel);
961 WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
962 WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
964 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from File..."));
965 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Rename..."));
966 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Remove"));
967 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Copy"));
968 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from Clipboard"));
970 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, 0);
971 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, 0);
972 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuCopy, 0);
973 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuNewFromClipboard, 0);
975 customRenderSpectrum(panel);
976 panel->currentPalette = 0;
977 panel->palx = customPaletteWidth / 2;
978 panel->paly = customPaletteHeight / 2;
980 /* Widgets for the ColorList Panel */
981 panel->colorListFrm = WMCreateFrame(panel->win);
982 WMSetFrameRelief(panel->colorListFrm, WRFlat);
983 WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
984 WMMoveWidget(panel->colorListFrm, 5, 80);
986 panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
987 WMAddPopUpButtonItem(panel->colorListHistoryBtn, _("X11-Colors"));
988 WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn,
989 WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn) - 1);
990 /* WMSetPopUpButtonAction(panel->colorListHistoryBtn,
991 * colorListHistoryCallback, panel); */
992 WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
993 WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
995 panel->colorListContentLst = WMCreateList(panel->colorListFrm);
996 WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
997 WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
998 WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
999 WMMoveWidget(panel->colorListContentLst, 0, 23);
1000 WMHangData(panel->colorListContentLst, panel);
1002 panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1003 WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
1004 WMSetPopUpButtonText(panel->colorListColorMenuBtn, _("Color"));
1005 WMSetPopUpButtonAction(panel->colorListColorMenuBtn, colorListColorMenuCallback, panel);
1006 WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16) / 2, 20);
1007 WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
1009 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Add..."));
1010 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Rename..."));
1011 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Remove"));
1013 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuAdd, 0);
1014 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRename, 0);
1015 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRemove, 0);
1017 panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1018 WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
1019 WMSetPopUpButtonText(panel->colorListListMenuBtn, _("List"));
1020 WMSetPopUpButtonAction(panel->colorListListMenuBtn, colorListListMenuCallback, panel);
1021 WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2, 20);
1022 WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2 + 8, PHEIGHT - 130);
1024 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("New..."));
1025 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Rename..."));
1026 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Remove"));
1028 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuAdd, 0);
1029 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
1030 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
1032 WMRealizeWidget(panel->win);
1033 WMMapSubwidgets(panel->win);
1035 WMMapSubwidgets(panel->wheelFrm);
1036 WMMapSubwidgets(panel->slidersFrm);
1037 WMMapSubwidgets(panel->grayFrm);
1038 WMMapSubwidgets(panel->rgbFrm);
1039 WMMapSubwidgets(panel->cmykFrm);
1040 WMMapSubwidgets(panel->hsbFrm);
1041 WMMapSubwidgets(panel->customPaletteFrm);
1042 WMMapSubwidgets(panel->customPaletteContentFrm);
1043 WMMapSubwidgets(panel->colorListFrm);
1045 /* Pixmap to indicate selection positions
1046 * wheelframe MUST be mapped.
1048 panel->selectionImg = XCreatePixmap(scrPtr->display, WMWidgetXID(panel->win), 4, 4, scrPtr->depth);
1049 XFillRectangle(scrPtr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1050 XFillRectangle(scrPtr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1052 readConfiguration(panel);
1053 readXColors(panel);
1055 return panel;
1058 WMColorPanel *WMGetColorPanel(WMScreen * scrPtr)
1060 WMColorPanel *panel;
1062 if (scrPtr->sharedColorPanel)
1063 return scrPtr->sharedColorPanel;
1065 panel = makeColorPanel(scrPtr, "colorPanel");
1067 scrPtr->sharedColorPanel = panel;
1069 return panel;
1072 void WMFreeColorPanel(WMColorPanel * panel)
1074 W_Screen *scr = WMWidgetScreen(panel->win);
1076 if (panel == scr->sharedColorPanel) {
1077 scr->sharedColorPanel = NULL;
1080 if (!panel)
1081 return;
1083 WMRemoveNotificationObserver(panel);
1084 WMUnmapWidget(panel->win);
1086 /* fonts */
1087 WMReleaseFont(panel->font8);
1088 WMReleaseFont(panel->font12);
1090 /* pixmaps */
1091 wheelDestroyMatrix(panel->wheelMtrx);
1092 if (panel->wheelImg)
1093 XFreePixmap(scr->display, panel->wheelImg);
1094 if (panel->selectionImg)
1095 XFreePixmap(scr->display, panel->selectionImg);
1096 if (panel->selectionBackImg)
1097 XFreePixmap(scr->display, panel->selectionBackImg);
1098 RReleaseImage(panel->customPaletteImg);
1100 /* structs */
1101 if (panel->lastBrowseDir)
1102 wfree(panel->lastBrowseDir);
1103 if (panel->configurationPath)
1104 wfree(panel->configurationPath);
1106 WMDestroyWidget(panel->win);
1108 wfree(panel);
1111 void WMCloseColorPanel(WMColorPanel * panel)
1113 WMFreeColorPanel(panel);
1116 void WMShowColorPanel(WMColorPanel * panel)
1118 WMScreen *scr = WMWidgetScreen(panel->win);
1119 WMColor *white = WMWhiteColor(scr);
1121 if (panel->color.set == cpNone)
1122 WMSetColorPanelColor(panel, white);
1123 WMReleaseColor(white);
1125 if (panel->mode != WMWheelModeColorPanel)
1126 WMPerformButtonClick(panel->wheelBtn);
1128 WMMapWidget(panel->win);
1131 static void closeWindowCallback(WMWidget * w, void *data)
1133 W_ColorPanel *panel = (W_ColorPanel *) data;
1135 WMCloseColorPanel(panel);
1138 static void readConfiguration(W_ColorPanel * panel)
1140 /* XXX Doesn't take care of "invalid" files */
1142 DIR *dPtr;
1143 struct dirent *dp;
1144 struct stat stat_buf;
1145 int item;
1147 if (stat(panel->configurationPath, &stat_buf) != 0) {
1148 if (mkdir(panel->configurationPath, S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH) != 0) {
1149 wsyserror(_("Color Panel: Could not create directory %s needed"
1150 " to store configurations"), panel->configurationPath);
1151 WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
1152 WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
1153 WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
1154 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1155 _("File Error"),
1156 _("Could not create ColorPanel configuration directory"),
1157 _("OK"), NULL, NULL);
1159 return;
1162 if (!(dPtr = opendir(panel->configurationPath))) {
1163 wwarning("%s: %s", _("Color Panel: Could not find file"), panel->configurationPath);
1164 return;
1167 while ((dp = readdir(dPtr)) != NULL) {
1168 unsigned int perm_mask;
1169 char *path = wstrconcat(panel->configurationPath,
1170 dp->d_name);
1172 if (dp->d_name[0] != '.') {
1173 item = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
1174 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
1176 perm_mask = (access(path, R_OK) == 0);
1177 WMSetPopUpButtonItemEnabled(panel->customPaletteHistoryBtn, item, perm_mask);
1179 wfree(path);
1181 closedir(dPtr);
1184 static void readXColors(W_ColorPanel * panel)
1186 WMListItem *item;
1187 RGBColor *entry;
1189 for (entry = rgbColors; entry->name != NULL; entry++) {
1190 item = WMAddListItem(panel->colorListContentLst, entry->name);
1191 item->clientData = (void *)&(entry->color);
1195 void WMSetColorPanelPickerMode(WMColorPanel * panel, WMColorPanelMode mode)
1197 W_Screen *scr = WMWidgetScreen(panel->win);
1199 if (mode != WMWheelModeColorPanel) {
1200 WMUnmapWidget(panel->wheelFrm);
1201 if (panel->selectionBackImg) {
1202 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1203 panel->selectionBackImg = None;
1206 if (mode != WMGrayModeColorPanel)
1207 WMUnmapWidget(panel->grayFrm);
1208 if (mode != WMRGBModeColorPanel)
1209 WMUnmapWidget(panel->rgbFrm);
1210 if (mode != WMCMYKModeColorPanel)
1211 WMUnmapWidget(panel->cmykFrm);
1212 if (mode != WMHSBModeColorPanel)
1213 WMUnmapWidget(panel->hsbFrm);
1214 if (mode != WMCustomPaletteModeColorPanel) {
1215 WMUnmapWidget(panel->customPaletteFrm);
1216 if (panel->selectionBackImg) {
1217 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1218 panel->selectionBackImg = None;
1221 if (mode != WMColorListModeColorPanel)
1222 WMUnmapWidget(panel->colorListFrm);
1223 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
1224 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1225 WMUnmapWidget(panel->slidersFrm);
1226 else
1227 panel->slidersmode = mode;
1229 if (mode == WMWheelModeColorPanel) {
1230 WMMapWidget(panel->wheelFrm);
1231 WMSetButtonSelected(panel->wheelBtn, True);
1232 if (panel->lastChanged != WMWheelModeColorPanel)
1233 wheelInit(panel);
1234 wheelRender(panel);
1235 wheelPaint(panel);
1236 } else if (mode == WMGrayModeColorPanel) {
1237 WMMapWidget(panel->slidersFrm);
1238 WMSetButtonSelected(panel->slidersBtn, True);
1239 WMMapWidget(panel->grayFrm);
1240 WMSetButtonSelected(panel->grayBtn, True);
1241 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1242 if (panel->lastChanged != WMGrayModeColorPanel)
1243 grayInit(panel);
1244 } else if (mode == WMRGBModeColorPanel) {
1245 WMMapWidget(panel->slidersFrm);
1246 WMSetButtonSelected(panel->slidersBtn, True);
1247 WMMapWidget(panel->rgbFrm);
1248 WMSetButtonSelected(panel->rgbBtn, True);
1249 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1250 if (panel->lastChanged != WMRGBModeColorPanel)
1251 rgbInit(panel);
1252 } else if (mode == WMCMYKModeColorPanel) {
1253 WMMapWidget(panel->slidersFrm);
1254 WMSetButtonSelected(panel->slidersBtn, True);
1255 WMMapWidget(panel->cmykFrm);
1256 WMSetButtonSelected(panel->cmykBtn, True);
1257 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1258 if (panel->lastChanged != WMCMYKModeColorPanel)
1259 cmykInit(panel);
1260 } else if (mode == WMHSBModeColorPanel) {
1261 WMMapWidget(panel->slidersFrm);
1262 WMSetButtonSelected(panel->slidersBtn, True);
1263 WMMapWidget(panel->hsbFrm);
1264 WMSetButtonSelected(panel->hsbBtn, True);
1265 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1266 if (panel->lastChanged != WMHSBModeColorPanel)
1267 hsbInit(panel);
1268 } else if (mode == WMCustomPaletteModeColorPanel) {
1269 WMMapWidget(panel->customPaletteFrm);
1270 WMSetButtonSelected(panel->customPaletteBtn, True);
1271 customSetPalette(panel);
1272 } else if (mode == WMColorListModeColorPanel) {
1273 WMMapWidget(panel->colorListFrm);
1274 WMSetButtonSelected(panel->colorListBtn, True);
1277 panel->mode = mode;
1280 WMColor *WMGetColorPanelColor(WMColorPanel * panel)
1282 return WMGetColorWellColor(panel->colorWell);
1285 void WMSetColorPanelColor(WMColorPanel * panel, WMColor * color)
1287 WMSetColorWellColor(panel->colorWell, color);
1289 panel->color.rgb.red = color->color.red >> 8;
1290 panel->color.rgb.green = color->color.green >> 8;
1291 panel->color.rgb.blue = color->color.blue >> 8;
1292 panel->color.set = cpRGB;
1294 if (panel->mode == panel->lastChanged)
1295 panel->lastChanged = 0;
1297 WMSetColorPanelPickerMode(panel, panel->mode);
1300 static void updateSwatch(WMColorPanel * panel, CPColor color)
1302 WMScreen *scr = WMWidgetScreen(panel->win);
1303 WMColor *wellcolor;
1305 if (color.set != cpRGB)
1306 convertCPColor(&color);
1308 panel->color = color;
1310 wellcolor = WMCreateRGBColor(scr, color.rgb.red << 8, color.rgb.green << 8, color.rgb.blue << 8, True);
1312 WMSetColorWellColor(panel->colorWell, wellcolor);
1313 WMReleaseColor(wellcolor);
1315 if (!panel->flags.dragging || panel->flags.continuous) {
1316 if (panel->action)
1317 (*panel->action) (panel, panel->clientData);
1319 WMPostNotificationName(WMColorPanelColorChangedNotification, panel, NULL);
1323 static void modeButtonCallback(WMWidget * w, void *data)
1325 W_ColorPanel *panel = (W_ColorPanel *) (data);
1327 if (w == panel->wheelBtn)
1328 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1329 else if (w == panel->slidersBtn)
1330 WMSetColorPanelPickerMode(panel, panel->slidersmode);
1331 else if (w == panel->customPaletteBtn)
1332 WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
1333 else if (w == panel->colorListBtn)
1334 WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
1335 else if (w == panel->grayBtn)
1336 WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
1337 else if (w == panel->rgbBtn)
1338 WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
1339 else if (w == panel->cmykBtn)
1340 WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
1341 else if (w == panel->hsbBtn)
1342 WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
1345 /****************** Magnifying Cursor Functions *******************/
1347 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h)
1349 int x0 = 0, y0 = 0, w0 = w, h0 = h;
1350 const int displayWidth = DisplayWidth(scr->display, scr->screen),
1351 displayHeight = DisplayHeight(scr->display, scr->screen);
1353 if (!(image && image->data)) {
1354 /* The image in panel->magnifyGlass->image does not exist yet.
1355 * Grab one from the screen (not beyond) and use it from now on.
1357 if (!(image = XGetImage(scr->display, scr->rootWin,
1358 x - Cursor_x_hot, y - Cursor_y_hot, w, h, AllPlanes, ZPixmap)))
1359 wwarning(_("Color Panel: X failed request"));
1361 return image;
1364 /* Coordinate correction for back pixmap
1365 * if magnifying glass is at screen-borders
1368 /* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
1369 * Hatched area is beyond screen border.
1371 * |<-Cursor_x_hot->|
1372 * ________________|_____
1373 * |/ / / / / / /| | |
1374 * | / / / / / / |(x,y) |
1375 * |/_/_/_/_/_/_/|________|
1376 * |<----x0----->|<--w0-->|
1380 /* Figure 2: Shifting of rectangle-to-grab at bottom/right
1381 * screen borders
1382 * Hatched area is beyond screen border
1384 * |<-Cursor_x_hot->|
1385 * ________________|_______________
1386 * | | | / / / / / /|
1387 * | (x,y)|/ / / / / / |
1388 * |___________________|_/_/_/_/_/_/|
1389 * |<-------w0-------->| |
1390 * |<---------------w--|----------->|
1391 * | |
1392 * x0 Displaywidth-1
1395 if (x < Cursor_x_hot) { /* see fig. 1 */
1396 x0 = Cursor_x_hot - x;
1397 w0 = w - x0;
1400 if (displayWidth - 1 < x - Cursor_x_hot + w) { /* see fig. 2 */
1401 w0 = (displayWidth) - (x - Cursor_x_hot);
1404 if (y < Cursor_y_hot) { /* see fig. 1 */
1405 y0 = Cursor_y_hot - y;
1406 h0 = h - y0;
1409 if (displayHeight - 1 < y - Cursor_y_hot + h) { /* see fig. 2 */
1410 h0 = (displayHeight) - (y - Cursor_y_hot);
1412 /* end of coordinate correction */
1414 /* Grab an image from the screen, clipped if necessary,
1415 * and put it in the existing panel->magnifyGlass->image
1416 * with the corresponding clipping offset.
1418 if (!XGetSubImage(scr->display, scr->rootWin,
1419 x - Cursor_x_hot + x0, y - Cursor_y_hot + y0, w0, h0, AllPlanes, ZPixmap, image, x0, y0))
1420 wwarning(_("Color Panel: X failed request"));
1422 return NULL;
1425 static void magnifyGetImageStored(WMColorPanel * panel, int x1, int y1, int x2, int y2)
1427 /* (x1, y1) = topleft corner of existing rectangle
1428 * (x2, y2) = topleft corner of new position
1431 W_Screen *scr = WMWidgetScreen(panel->win);
1432 int xa = 0, ya = 0, xb = 0, yb = 0;
1433 int width, height;
1434 const int dx = abs(x2 - x1), dy = abs(y2 - y1);
1435 XImage *image;
1436 const int x_min = Cursor_x_hot,
1437 y_min = Cursor_y_hot,
1438 x_max = DisplayWidth(scr->display, scr->screen) - 1 -
1439 (Cursor_mask_width - Cursor_x_hot),
1440 y_max = DisplayHeight(scr->display, scr->screen) - 1 - (Cursor_mask_height - Cursor_y_hot);
1442 if ((dx == 0) && (dy == 0) && panel->magnifyGlass->image)
1443 return; /* No movement */
1445 if (x1 < x2)
1446 xa = dx;
1447 else
1448 xb = dx;
1450 if (y1 < y2)
1451 ya = dy;
1452 else
1453 yb = dy;
1455 width = Cursor_mask_width - dx;
1456 height = Cursor_mask_height - dy;
1458 /* If the traversed distance is larger than the size of the magnifying
1459 * glass contents, there is no need to do dirty rectangles. A whole new
1460 * rectangle can be grabbed (unless that rectangle falls partially
1461 * off screen).
1462 * Destroying the image and setting it to NULL will achieve that later on.
1464 * Of course, grabbing an XImage beyond the borders of the screen will
1465 * cause trouble, this is considdered a special case. Part of the screen
1466 * is grabbed, but there is no need for dirty rectangles.
1468 if ((width <= 0) || (height <= 0)) {
1469 if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
1470 if (panel->magnifyGlass->image)
1471 XDestroyImage(panel->magnifyGlass->image);
1472 panel->magnifyGlass->image = NULL;
1474 } else {
1475 if (panel->magnifyGlass->image) {
1476 /* Get dirty rectangle from panel->magnifyGlass->image */
1477 panel->magnifyGlass->dirtyRect =
1478 XSubImage(panel->magnifyGlass->image, xa, ya, width, height);
1479 if (!panel->magnifyGlass->dirtyRect) {
1480 wwarning(_("Color Panel: X failed request"));
1481 return; /* X returned a NULL from XSubImage */
1486 /* Get image from screen */
1487 image = magnifyGetImage(scr, panel->magnifyGlass->image, x2, y2, Cursor_mask_width, Cursor_mask_height);
1488 if (image) { /* Only reassign if a *new* image was grabbed */
1489 panel->magnifyGlass->image = image;
1490 return;
1493 /* Copy previously stored rectangle on covered part of image */
1494 if (panel->magnifyGlass->image && panel->magnifyGlass->dirtyRect) {
1495 int old_height;
1497 /* "width" and "height" are used as coordinates here,
1498 * and run from [0...width-1] and [0...height-1] respectively.
1500 width--;
1501 height--;
1502 old_height = height;
1504 for (; width >= 0; width--)
1505 for (height = old_height; height >= 0; height--)
1506 XPutPixel(panel->magnifyGlass->image, xb + width, yb + height,
1507 XGetPixel(panel->magnifyGlass->dirtyRect, width, height));
1508 XDestroyImage(panel->magnifyGlass->dirtyRect);
1509 panel->magnifyGlass->dirtyRect = NULL;
1512 return;
1515 static Pixmap magnifyCreatePixmap(WMColorPanel * panel)
1517 W_Screen *scr = WMWidgetScreen(panel->win);
1518 int u, v;
1519 #ifndef SHAPE
1520 Pixmap pixmap;
1521 #endif
1522 unsigned long color;
1524 if (!panel->magnifyGlass->image)
1525 return None;
1527 if (!panel->magnifyGlass->magPix)
1528 return None;
1531 * Copy an area of only 5x5 pixels from the center of the image.
1533 for (u = 0; u < 5; u++) {
1534 for (v = 0; v < 5; v++) {
1535 color = XGetPixel(panel->magnifyGlass->image, u + 9, v + 9);
1537 XSetForeground(scr->display, scr->copyGC, color);
1539 if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
1540 panel->magnifyGlass->color = ulongToRColor(scr, color);
1542 /* The center square must eventually be centered around the
1543 * hotspot. The image needs shifting to achieve this. The amount of
1544 * shifting is (Cursor_mask_width/2 - 2 * square_size) = 11-10 = 1
1545 * _ _ _ _ _
1546 * |_|_|_|_|_|
1547 * ^------- center of center square == Cursor_x_hot
1549 XFillRectangle(scr->display, panel->magnifyGlass->magPix,
1550 scr->copyGC,
1551 u * 5 + (u == 0 ? 0 : -1), v * 5 + (v == 0 ? 0 : -1),
1552 (u == 0 ? 4 : 5), (v == 0 ? 4 : 5));
1556 #ifdef SHAPE
1557 return panel->magnifyGlass->magPix;
1558 #else
1559 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width, Cursor_mask_height, scr->depth);
1560 if (!pixmap)
1561 return None;
1563 XPutImage(scr->display, pixmap, scr->copyGC, panel->magnifyGlass->image,
1564 0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
1566 /* Copy the magnified pixmap, with the clip mask, to background pixmap */
1567 XCopyArea(scr->display, panel->magnifyGlass->magPix, pixmap,
1568 scr->clipGC, 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
1569 /* (2,2) puts center pixel on center of glass */
1571 return pixmap;
1572 #endif
1576 static WMView *magnifyCreateView(W_ColorPanel * panel)
1578 W_Screen *scr = WMWidgetScreen(panel->win);
1579 WMView *magView;
1581 magView = W_CreateTopView(scr);
1582 if (!magView)
1583 return NULL;
1585 magView->self = panel->win;
1586 magView->flags.topLevel = 1;
1587 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1588 magView->attribs.override_redirect = True;
1589 magView->attribs.save_under = True;
1591 W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
1593 W_RealizeView(magView);
1595 return magView;
1598 static Cursor magnifyGrabPointer(W_ColorPanel * panel)
1600 W_Screen *scr = WMWidgetScreen(panel->win);
1601 Pixmap magPixmap, magPixmap2;
1602 Cursor magCursor;
1603 XColor fgColor = { 0, 0, 0, 0, DoRed | DoGreen | DoBlue };
1604 XColor bgColor = { 0, 0xbf00, 0xa000, 0x5000, DoRed | DoGreen | DoBlue };
1606 /* Cursor creation stuff */
1607 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1608 (char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
1609 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1610 (char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
1612 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1613 &fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
1615 XFreePixmap(scr->display, magPixmap);
1616 XFreePixmap(scr->display, magPixmap2);
1618 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1620 /* Set up Pointer */
1621 XGrabPointer(scr->display, panel->magnifyGlass->view->window, True,
1622 PointerMotionMask | ButtonPressMask,
1623 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1625 return magCursor;
1628 static WMPoint magnifyInitialize(W_ColorPanel * panel)
1630 W_Screen *scr = WMWidgetScreen(panel->win);
1631 int x, y, u, v;
1632 unsigned int mask;
1633 Pixmap pixmap, clip_mask;
1634 WMPoint point;
1635 Window root_return, child_return;
1637 clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1638 (char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1639 1, 0, 1);
1640 panel->magnifyGlass->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
1641 5 * 5 - 1, 5 * 5 - 1, scr->depth);
1643 XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return, &x, &y, &u, &v, &mask);
1645 panel->magnifyGlass->image = NULL;
1647 /* Clipmask to make magnified view-contents circular */
1648 #ifdef SHAPE
1649 XShapeCombineMask(scr->display, WMViewXID(panel->magnifyGlass->view),
1650 ShapeBounding, 0, 0, clip_mask, ShapeSet);
1651 #else
1652 /* Clip circle in glass cursor */
1653 XSetClipMask(scr->display, scr->clipGC, clip_mask);
1654 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1655 #endif
1657 XFreePixmap(scr->display, clip_mask);
1659 /* Draw initial magnifying glass contents */
1660 magnifyGetImageStored(panel, x, y, x, y);
1662 pixmap = magnifyCreatePixmap(panel);
1663 XSetWindowBackgroundPixmap(scr->display, WMViewXID(panel->magnifyGlass->view), pixmap);
1664 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1665 XFlush(scr->display);
1667 #ifndef SHAPE
1668 XFreePixmap(scr->display, pixmap);
1669 #endif
1671 point.x = x;
1672 point.y = y;
1674 return point;
1677 static void magnifyPutCursor(WMWidget * w, void *data)
1679 W_ColorPanel *panel = (W_ColorPanel *) (data);
1680 W_Screen *scr = WMWidgetScreen(panel->win);
1681 Cursor magCursor;
1682 Pixmap pixmap;
1683 XEvent event;
1684 WMPoint initialPosition;
1686 /* Destroy wheelBackImg, so it'll update properly */
1687 if (panel->selectionBackImg) {
1688 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1689 panel->selectionBackImg = None;
1692 /* Create magnifying glass */
1693 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1694 panel->magnifyGlass->view = magnifyCreateView(panel);
1695 if (!panel->magnifyGlass->view)
1696 return;
1698 initialPosition = magnifyInitialize(panel);
1699 panel->magnifyGlass->x = initialPosition.x;
1700 panel->magnifyGlass->y = initialPosition.y;
1702 W_MoveView(panel->magnifyGlass->view,
1703 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1704 W_MapView(panel->magnifyGlass->view);
1706 magCursor = magnifyGrabPointer(panel);
1708 while (panel->magnifyGlass->image) {
1709 WMNextEvent(scr->display, &event);
1711 /* Pack motion events */
1712 while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
1715 switch (event.type) {
1716 case ButtonPress:
1717 XDestroyImage(panel->magnifyGlass->image);
1718 panel->magnifyGlass->image = NULL;
1720 if (event.xbutton.button == Button1) {
1721 panel->color.rgb = panel->magnifyGlass->color;
1722 panel->color.set = cpRGB;
1723 updateSwatch(panel, panel->color);
1725 switch (panel->mode) {
1726 case WMWheelModeColorPanel:
1727 wheelInit(panel);
1728 wheelRender(panel);
1729 wheelPaint(panel);
1730 break;
1731 case WMGrayModeColorPanel:
1732 grayInit(panel);
1733 break;
1734 case WMRGBModeColorPanel:
1735 rgbInit(panel);
1736 break;
1737 case WMCMYKModeColorPanel:
1738 cmykInit(panel);
1739 break;
1740 case WMHSBModeColorPanel:
1741 hsbInit(panel);
1742 break;
1743 default:
1744 break;
1746 panel->lastChanged = panel->mode;
1748 WMSetButtonSelected(panel->magnifyBtn, False);
1749 break;
1751 case MotionNotify:
1752 while (XPending(event.xmotion.display)) {
1753 XEvent ev;
1754 XPeekEvent(event.xmotion.display, &ev);
1755 if (ev.type == MotionNotify)
1756 XNextEvent(event.xmotion.display, &event);
1757 else
1758 break;
1761 /* Get a "dirty rectangle" */
1762 magnifyGetImageStored(panel,
1763 panel->magnifyGlass->x, panel->magnifyGlass->y,
1764 event.xmotion.x_root, event.xmotion.y_root);
1766 /* Update coordinates */
1767 panel->magnifyGlass->x = event.xmotion.x_root;
1768 panel->magnifyGlass->y = event.xmotion.y_root;
1770 /* Move view */
1771 W_MoveView(panel->magnifyGlass->view,
1772 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1774 /* Put new image (with magn.) in view */
1775 pixmap = magnifyCreatePixmap(panel);
1776 if (pixmap != None) {
1777 /* Change the window background */
1778 XSetWindowBackgroundPixmap(scr->display,
1779 WMViewXID(panel->magnifyGlass->view), pixmap);
1780 /* Force an Expose (handled by X) */
1781 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1782 /* Synchronize the event queue, so the Expose is handled NOW */
1783 XFlush(scr->display);
1784 #ifndef SHAPE
1785 XFreePixmap(scr->display, pixmap);
1786 #endif
1788 break;
1790 /* Try XQueryPointer for this !!! It returns windows that the pointer
1791 * is over. Note: We found this solving the invisible donkey cap bug
1793 #if 0 /* As it is impossible to make this work in all cases,
1794 * we consider it confusing. Therefore we disabled it.
1796 case FocusOut: /* fall through */
1797 case FocusIn:
1799 * Color Panel window (panel->win) lost or received focus.
1800 * We need to update the pixmap in the magnifying glass.
1802 * BUG Doesn't work with focus switches between two windows
1803 * if none of them is the color panel.
1805 XUngrabPointer(scr->display, CurrentTime);
1806 W_UnmapView(panel->magnifyGlass->view);
1808 magnifyInitialize(panel);
1810 W_MapView(panel->magnifyGlass->view);
1811 XGrabPointer(scr->display, panel->magnifyGlass->view->window,
1812 True, PointerMotionMask | ButtonPressMask,
1813 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1814 break;
1815 #endif
1816 default:
1817 WMHandleEvent(&event);
1818 break;
1819 } /* of switch */
1822 XUngrabPointer(scr->display, CurrentTime);
1823 XFreeCursor(scr->display, magCursor);
1825 XFreePixmap(scr->display, panel->magnifyGlass->magPix);
1826 panel->magnifyGlass->magPix = None;
1828 W_UnmapView(panel->magnifyGlass->view);
1829 W_DestroyView(panel->magnifyGlass->view);
1830 panel->magnifyGlass->view = NULL;
1832 wfree(panel->magnifyGlass);
1835 /****************** ColorWheel Functions ************************/
1837 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height)
1839 wheelMatrix *matrix = NULL;
1840 int i;
1842 assert((width > 0) && (height > 0));
1844 matrix = wmalloc(sizeof(wheelMatrix));
1845 memset(matrix, 0, sizeof(wheelMatrix));
1846 matrix->width = width;
1847 matrix->height = height;
1849 for (i = 0; i < 3; i++) {
1850 matrix->data[i] = wmalloc(width * height * sizeof(unsigned char));
1853 return matrix;
1856 static void wheelDestroyMatrix(wheelMatrix * matrix)
1858 int i;
1860 if (!matrix)
1861 return;
1863 for (i = 0; i < 3; i++) {
1864 if (matrix->data[i])
1865 wfree(matrix->data[i]);
1867 wfree(matrix);
1870 static void wheelInitMatrix(W_ColorPanel * panel)
1872 int i;
1873 int x, y;
1874 unsigned char *rp, *gp, *bp;
1875 CPColor cpColor;
1876 long ofs[4];
1877 int xcor, ycor;
1878 unsigned short sat;
1879 int dhue[4];
1880 const int cw_halfsize = (colorWheelSize + 4) / 2,
1881 cw_sqsize = (colorWheelSize + 4) * (colorWheelSize + 4), uchar_shift = getShift(sizeof(unsigned char));
1883 if (!panel->wheelMtrx)
1884 return;
1886 cpColor.hsv.value = 255;
1887 cpColor.set = cpHSV;
1889 ofs[0] = -1;
1890 ofs[1] = -(colorWheelSize + 4);
1892 /* offsets are counterclockwise (in triangles).
1894 * ofs[0] ---->
1895 * _______________________________________
1896 * [1] |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| o
1897 * s |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| f
1898 * f |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| s
1899 * o | | | | | | | | | | | | | | | | | | | | | [3]
1901 * <---- ofs[2]
1902 * ____
1903 * |\ /| <-- triangles
1904 * | \/ |
1905 * | /\ |
1906 * |/__\|
1909 for (y = 0; y < cw_halfsize; y++) {
1910 for (x = y; x < (colorWheelSize + 4 - y); x++) {
1911 /* (xcor, ycor) is (x,y) relative to center of matrix */
1912 xcor = 2 * x - 4 - colorWheelSize;
1913 ycor = 2 * y - 4 - colorWheelSize;
1915 /* RColor.saturation is unsigned char and will wrap after 255 */
1916 sat = rint(255.0 * sqrt(xcor * xcor + ycor * ycor) / colorWheelSize);
1918 cpColor.hsv.saturation = (unsigned char)sat;
1920 ofs[0]++; /* top quarter of matrix */
1921 ofs[1] += colorWheelSize + 4; /* left quarter */
1922 ofs[2] = cw_sqsize - 1 - ofs[0]; /* bottom quarter */
1923 ofs[3] = cw_sqsize - 1 - ofs[1]; /* right quarter */
1925 if (sat < 256) {
1926 if (xcor != 0)
1927 dhue[0] = rint(atan((double)ycor / (double)xcor) *
1928 (180.0 / M_PI)) + (xcor < 0 ? 180.0 : 0.0);
1929 else
1930 dhue[0] = 270;
1932 dhue[0] = 360 - dhue[0]; /* Reverse direction of ColorWheel */
1933 dhue[1] = 270 - dhue[0] + (dhue[0] > 270 ? 360 : 0);
1934 dhue[2] = dhue[0] - 180 + (dhue[0] < 180 ? 360 : 0);
1935 dhue[3] = 90 - dhue[0] + (dhue[0] > 90 ? 360 : 0);
1937 for (i = 0; i < 4; i++) {
1938 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1939 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1940 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1942 cpColor.hsv.hue = dhue[i];
1943 convertCPColor(&cpColor);
1945 *rp = (unsigned char)(cpColor.rgb.red);
1946 *gp = (unsigned char)(cpColor.rgb.green);
1947 *bp = (unsigned char)(cpColor.rgb.blue);
1949 } else {
1950 for (i = 0; i < 4; i++) {
1951 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1952 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1953 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1955 *rp = (unsigned char)0;
1956 *gp = (unsigned char)0;
1957 *bp = (unsigned char)0;
1962 ofs[0] += 2 * y + 1;
1963 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2 * y);
1967 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue)
1969 unsigned int i;
1970 unsigned int v;
1972 for (i = 0; i < 256; i++) {
1973 /* We divide by 128 in advance, and check whether that number divides
1974 * by 2 properly. If not, we add one to round the number correctly
1976 v = (i * maxvalue) >> 7;
1977 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + (v & 0x01));
1981 static void wheelRender(W_ColorPanel * panel)
1983 W_Screen *scr = WMWidgetScreen(panel->win);
1984 int x, y;
1985 RImage *image;
1986 unsigned char *ptr;
1987 RColor gray;
1988 unsigned long ofs = 0;
1989 /*unsigned char shift = getShift(sizeof(unsigned char)); */
1991 image = RCreateImage(colorWheelSize + 4, colorWheelSize + 4, True);
1992 if (!image) {
1993 wwarning(_("Color Panel: Could not allocate memory"));
1994 return;
1997 ptr = image->data;
1999 /* TODO Make this transparent istead of gray */
2000 gray.red = gray.blue = 0xae;
2001 gray.green = 0xaa;
2003 for (y = 0; y < colorWheelSize + 4; y++) {
2004 for (x = 0; x < colorWheelSize + 4; x++) {
2005 if (wheelInsideColorWheel(panel, ofs)) {
2006 *(ptr++) =
2007 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]]);
2008 *(ptr++) =
2009 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]]);
2010 *(ptr++) =
2011 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]]);
2012 *(ptr++) = 0;
2013 } else {
2014 *(ptr++) = (unsigned char)(gray.red);
2015 *(ptr++) = (unsigned char)(gray.green);
2016 *(ptr++) = (unsigned char)(gray.blue);
2017 *(ptr++) = 255;
2019 ofs++;
2023 if (panel->wheelImg)
2024 XFreePixmap(scr->display, panel->wheelImg);
2026 RConvertImage(scr->rcontext, image, &panel->wheelImg);
2027 RReleaseImage(image);
2029 /* Check if backimage exists. If it doesn't, allocate and fill it */
2030 if (!panel->selectionBackImg) {
2031 panel->selectionBackImg = XCreatePixmap(scr->display,
2032 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
2033 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2034 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2035 /* -2 is hot spot correction */
2039 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs)
2041 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
2042 (panel->wheelMtrx->data[1][ofs] != 0) && (panel->wheelMtrx->data[2][ofs] != 0));
2045 static void wheelPaint(W_ColorPanel * panel)
2047 W_Screen *scr = WMWidgetScreen(panel->win);
2049 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
2050 scr->copyGC, 0, 0, colorWheelSize + 4, colorWheelSize + 4, 0, 0);
2052 /* Draw selection image */
2053 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2054 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2057 static void wheelHandleEvents(XEvent * event, void *data)
2059 W_ColorPanel *panel = (W_ColorPanel *) data;
2061 switch (event->type) {
2062 case Expose:
2063 if (event->xexpose.count != 0) /* TODO Improve */
2064 break;
2065 wheelPaint(panel);
2066 break;
2070 static void wheelHandleActionEvents(XEvent * event, void *data)
2072 W_ColorPanel *panel = (W_ColorPanel *) data;
2074 switch (event->type) {
2075 case ButtonPress:
2076 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) == COLORWHEEL_PART) {
2078 panel->lastChanged = WMWheelModeColorPanel;
2079 panel->flags.dragging = 1;
2081 wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
2083 break;
2085 case ButtonRelease:
2086 panel->flags.dragging = 0;
2087 if (!panel->flags.continuous) {
2088 if (panel->action)
2089 (*panel->action) (panel, panel->clientData);
2091 break;
2093 case MotionNotify:
2094 if (panel->flags.dragging) {
2095 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) == COLORWHEEL_PART) {
2096 wheelPositionSelection(panel, event->xmotion.x, event->xmotion.y);
2097 } else
2098 wheelPositionSelectionOutBounds(panel, event->xmotion.x, event->xmotion.y);
2100 break;
2104 static int getPickerPart(W_ColorPanel * panel, int x, int y)
2106 int lx, ly;
2107 unsigned long ofs;
2109 lx = x;
2110 ly = y;
2112 if (panel->mode == WMWheelModeColorPanel) {
2113 if ((lx >= 2) && (lx <= 2 + colorWheelSize) && (ly >= 2) && (ly <= 2 + colorWheelSize)) {
2115 ofs = ly * panel->wheelMtrx->width + lx;
2117 if (wheelInsideColorWheel(panel, ofs))
2118 return COLORWHEEL_PART;
2122 if (panel->mode == WMCustomPaletteModeColorPanel) {
2123 if ((lx >= 2) && (lx < customPaletteWidth - 2) && (ly >= 2) && (ly < customPaletteHeight - 2)) {
2124 return CUSTOMPALETTE_PART;
2128 return 0;
2131 static void wheelBrightnessSliderCallback(WMWidget * w, void *data)
2133 int value;
2135 W_ColorPanel *panel = (W_ColorPanel *) data;
2137 value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2139 wheelCalculateValues(panel, value);
2141 if (panel->color.set == cpRGB) {
2142 convertCPColor(&panel->color);
2143 panel->color.set = cpHSV;
2146 panel->color.hsv.value = value;
2148 wheelRender(panel);
2149 wheelPaint(panel);
2150 wheelUpdateSelection(panel);
2153 static void wheelUpdateSelection(W_ColorPanel * panel)
2155 W_Screen *scr = WMWidgetScreen(panel->win);
2157 updateSwatch(panel, panel->color);
2158 panel->lastChanged = WMWheelModeColorPanel;
2160 /* Redraw color selector (and make a backup of the part it will cover) */
2161 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2162 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2163 /* "-2" is correction for hotspot location */
2164 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2165 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2166 /* see above */
2169 static void wheelUndrawSelection(W_ColorPanel * panel)
2171 W_Screen *scr = WMWidgetScreen(panel->win);
2173 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
2174 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2175 /* see above */
2178 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y)
2180 unsigned long ofs = (y * panel->wheelMtrx->width) + x;
2182 panel->color.rgb.red = panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]];
2184 panel->color.rgb.green = panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]];
2186 panel->color.rgb.blue = panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]];
2187 panel->color.set = cpRGB;
2189 wheelUndrawSelection(panel);
2191 panel->colx = x;
2192 panel->coly = y;
2194 wheelUpdateSelection(panel);
2195 wheelUpdateBrightnessGradientFromLocation(panel);
2198 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2200 int hue;
2201 int xcor, ycor;
2202 CPColor cpColor;
2204 xcor = x * 2 - colorWheelSize - 4;
2205 ycor = y * 2 - colorWheelSize - 4;
2207 panel->color.hsv.saturation = 255;
2208 panel->color.hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2210 if (xcor != 0)
2211 hue = rint(atan(-(double)ycor / (double)xcor) * (180.0 / M_PI));
2212 else {
2213 if (ycor < 0)
2214 hue = 90;
2215 else
2216 hue = 270;
2219 if (xcor < 0)
2220 hue += 180;
2222 if ((xcor > 0) && (ycor > 0))
2223 hue += 360;
2225 panel->color.hsv.hue = hue;
2226 panel->color.set = cpHSV;
2227 convertCPColor(&panel->color);
2229 wheelUndrawSelection(panel);
2231 panel->colx = 2 + rint((colorWheelSize * (1.0 + cos(panel->color.hsv.hue * (M_PI / 180.0)))) / 2.0);
2232 /* "+2" because of "colorWheelSize + 4" */
2233 panel->coly = 2 + rint((colorWheelSize * (1.0 + sin(-panel->color.hsv.hue * (M_PI / 180.0)))) / 2.0);
2235 wheelUpdateSelection(panel);
2236 cpColor = panel->color;
2237 wheelUpdateBrightnessGradient(panel, cpColor);
2240 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel)
2242 CPColor from;
2243 unsigned long ofs;
2245 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2247 from.rgb.red = panel->wheelMtrx->data[0][ofs];
2248 from.rgb.green = panel->wheelMtrx->data[1][ofs];
2249 from.rgb.blue = panel->wheelMtrx->data[2][ofs];
2250 from.set = cpRGB;
2252 wheelUpdateBrightnessGradient(panel, from);
2255 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor)
2257 RColor to;
2258 RImage *sliderImg;
2259 WMPixmap *sliderPxmp;
2261 to.red = to.green = to.blue = 0;
2263 if (topColor.set == cpHSV)
2264 convertCPColor(&topColor);
2266 sliderImg = RRenderGradient(16, 153, &(topColor.rgb), &to, RGRD_VERTICAL);
2267 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win), sliderImg, 0);
2268 RReleaseImage(sliderImg);
2269 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
2270 WMReleasePixmap(sliderPxmp);
2273 /****************** Grayscale Panel Functions ***************/
2275 static void grayBrightnessSliderCallback(WMWidget * w, void *data)
2277 CPColor cpColor;
2278 int value;
2279 char tmp[4];
2280 W_ColorPanel *panel = (W_ColorPanel *) data;
2282 value = WMGetSliderValue(panel->grayBrightnessS);
2284 sprintf(tmp, "%d", value);
2286 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2287 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint(2.55 * value);
2288 cpColor.set = cpRGB;
2290 updateSwatch(panel, cpColor);
2291 panel->lastChanged = WMGrayModeColorPanel;
2294 static void grayPresetButtonCallback(WMWidget * w, void *data)
2296 CPColor cpColor;
2297 char tmp[4];
2298 int value;
2299 int i = 0;
2300 W_ColorPanel *panel = (W_ColorPanel *) data;
2302 while (i < 7) {
2303 if (w == panel->grayPresetBtn[i])
2304 break;
2305 i++;
2308 value = rint((100.0 * i) / 6.0);
2309 sprintf(tmp, "%d", value);
2311 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2312 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * i) / 6.0);
2313 cpColor.set = cpRGB;
2315 WMSetSliderValue(panel->grayBrightnessS, rint((100.0 * i) / 6.0));
2317 updateSwatch(panel, cpColor);
2318 panel->lastChanged = WMGrayModeColorPanel;
2321 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification)
2323 CPColor cpColor;
2324 char tmp[4];
2325 int value;
2326 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2328 value = atoi(WMGetTextFieldText(panel->grayBrightnessT));
2329 if (value > 100)
2330 value = 100;
2331 if (value < 0)
2332 value = 0;
2334 sprintf(tmp, "%d", value);
2335 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2336 WMSetSliderValue(panel->grayBrightnessS, value);
2338 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * value) / 100.0);
2339 cpColor.set = cpRGB;
2341 updateSwatch(panel, cpColor);
2342 panel->lastChanged = WMGrayModeColorPanel;
2345 /******************* RGB Panel Functions *****************/
2347 static void rgbSliderCallback(WMWidget * w, void *data)
2349 CPColor cpColor;
2350 int value[3];
2351 char tmp[4];
2352 W_ColorPanel *panel = (W_ColorPanel *) data;
2354 value[0] = WMGetSliderValue(panel->rgbRedS);
2355 value[1] = WMGetSliderValue(panel->rgbGreenS);
2356 value[2] = WMGetSliderValue(panel->rgbBlueS);
2358 sprintf(tmp, "%d", value[0]);
2359 WMSetTextFieldText(panel->rgbRedT, tmp);
2360 sprintf(tmp, "%d", value[1]);
2361 WMSetTextFieldText(panel->rgbGreenT, tmp);
2362 sprintf(tmp, "%d", value[2]);
2363 WMSetTextFieldText(panel->rgbBlueT, tmp);
2365 cpColor.rgb.red = value[0];
2366 cpColor.rgb.green = value[1];
2367 cpColor.rgb.blue = value[2];
2368 cpColor.set = cpRGB;
2370 updateSwatch(panel, cpColor);
2371 panel->lastChanged = WMRGBModeColorPanel;
2374 static void rgbTextFieldCallback(void *observerData, WMNotification * notification)
2376 CPColor cpColor;
2377 int value[3];
2378 char tmp[4];
2379 int n;
2380 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2382 value[0] = atoi(WMGetTextFieldText(panel->rgbRedT));
2383 value[1] = atoi(WMGetTextFieldText(panel->rgbGreenT));
2384 value[2] = atoi(WMGetTextFieldText(panel->rgbBlueT));
2386 for (n = 0; n < 3; n++) {
2387 if (value[n] > 255)
2388 value[n] = 255;
2389 if (value[n] < 0)
2390 value[n] = 0;
2393 sprintf(tmp, "%d", value[0]);
2394 WMSetTextFieldText(panel->rgbRedT, tmp);
2395 sprintf(tmp, "%d", value[1]);
2396 WMSetTextFieldText(panel->rgbGreenT, tmp);
2397 sprintf(tmp, "%d", value[2]);
2398 WMSetTextFieldText(panel->rgbBlueT, tmp);
2400 WMSetSliderValue(panel->rgbRedS, value[0]);
2401 WMSetSliderValue(panel->rgbGreenS, value[1]);
2402 WMSetSliderValue(panel->rgbBlueS, value[2]);
2404 cpColor.rgb.red = value[0];
2405 cpColor.rgb.green = value[1];
2406 cpColor.rgb.blue = value[2];
2407 cpColor.set = cpRGB;
2409 updateSwatch(panel, cpColor);
2410 panel->lastChanged = WMRGBModeColorPanel;
2413 /******************* CMYK Panel Functions *****************/
2415 static void cmykSliderCallback(WMWidget * w, void *data)
2417 CPColor cpColor;
2418 int value[4];
2419 char tmp[4];
2420 W_ColorPanel *panel = (W_ColorPanel *) data;
2421 double scale;
2423 value[0] = WMGetSliderValue(panel->cmykCyanS);
2424 value[1] = WMGetSliderValue(panel->cmykMagentaS);
2425 value[2] = WMGetSliderValue(panel->cmykYellowS);
2426 value[3] = WMGetSliderValue(panel->cmykBlackS);
2428 sprintf(tmp, "%d", value[0]);
2429 WMSetTextFieldText(panel->cmykCyanT, tmp);
2430 sprintf(tmp, "%d", value[1]);
2431 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2432 sprintf(tmp, "%d", value[2]);
2433 WMSetTextFieldText(panel->cmykYellowT, tmp);
2434 sprintf(tmp, "%d", value[3]);
2435 WMSetTextFieldText(panel->cmykBlackT, tmp);
2437 scale = 2.55 * (1.0 - (value[3] / 100.0));
2438 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2439 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2440 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2441 cpColor.set = cpRGB;
2443 updateSwatch(panel, cpColor);
2444 panel->lastChanged = WMCMYKModeColorPanel;
2447 static void cmykTextFieldCallback(void *observerData, WMNotification * notification)
2449 CPColor cpColor;
2450 int value[4];
2451 char tmp[4];
2452 int n;
2453 double scale;
2454 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2456 value[0] = atoi(WMGetTextFieldText(panel->cmykCyanT));
2457 value[1] = atoi(WMGetTextFieldText(panel->cmykMagentaT));
2458 value[2] = atoi(WMGetTextFieldText(panel->cmykYellowT));
2459 value[3] = atoi(WMGetTextFieldText(panel->cmykBlackT));
2461 for (n = 0; n < 4; n++) {
2462 if (value[n] > 100)
2463 value[n] = 100;
2464 if (value[n] < 0)
2465 value[n] = 0;
2468 sprintf(tmp, "%d", value[0]);
2469 WMSetTextFieldText(panel->cmykCyanT, tmp);
2471 sprintf(tmp, "%d", value[1]);
2472 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2474 sprintf(tmp, "%d", value[2]);
2475 WMSetTextFieldText(panel->cmykYellowT, tmp);
2477 sprintf(tmp, "%d", value[3]);
2478 WMSetTextFieldText(panel->cmykBlackT, tmp);
2480 WMSetSliderValue(panel->cmykCyanS, value[0]);
2481 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2482 WMSetSliderValue(panel->cmykYellowS, value[2]);
2483 WMSetSliderValue(panel->cmykBlackS, value[3]);
2485 scale = 2.55 * (1.0 - (value[3] / 100.0));
2486 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2487 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2488 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2489 cpColor.set = cpRGB;
2491 updateSwatch(panel, cpColor);
2492 panel->lastChanged = WMCMYKModeColorPanel;
2495 /********************** HSB Panel Functions ***********************/
2497 static void hsbSliderCallback(WMWidget * w, void *data)
2499 CPColor cpColor;
2500 int value[3];
2501 char tmp[4];
2502 W_ColorPanel *panel = (W_ColorPanel *) data;
2504 value[0] = WMGetSliderValue(panel->hsbHueS);
2505 value[1] = WMGetSliderValue(panel->hsbSaturationS);
2506 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
2508 sprintf(tmp, "%d", value[0]);
2509 WMSetTextFieldText(panel->hsbHueT, tmp);
2510 sprintf(tmp, "%d", value[1]);
2511 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2512 sprintf(tmp, "%d", value[2]);
2513 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2515 cpColor.hsv.hue = value[0];
2516 cpColor.hsv.saturation = value[1] * 2.55;
2517 cpColor.hsv.value = value[2] * 2.55;
2518 cpColor.set = cpHSV;
2520 convertCPColor(&cpColor);
2522 panel->lastChanged = WMHSBModeColorPanel;
2523 updateSwatch(panel, cpColor);
2525 if (w != panel->hsbBrightnessS)
2526 hsbUpdateBrightnessGradient(panel);
2527 if (w != panel->hsbSaturationS)
2528 hsbUpdateSaturationGradient(panel);
2529 if (w != panel->hsbHueS)
2530 hsbUpdateHueGradient(panel);
2533 static void hsbTextFieldCallback(void *observerData, WMNotification * notification)
2535 CPColor cpColor;
2536 int value[3];
2537 char tmp[4];
2538 int n;
2539 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2541 value[0] = atoi(WMGetTextFieldText(panel->hsbHueT));
2542 value[1] = atoi(WMGetTextFieldText(panel->hsbSaturationT));
2543 value[2] = atoi(WMGetTextFieldText(panel->hsbBrightnessT));
2545 if (value[0] > 359)
2546 value[0] = 359;
2547 if (value[0] < 0)
2548 value[0] = 0;
2550 for (n = 1; n < 3; n++) {
2551 if (value[n] > 100)
2552 value[n] = 100;
2553 if (value[n] < 0)
2554 value[n] = 0;
2557 sprintf(tmp, "%d", value[0]);
2558 WMSetTextFieldText(panel->hsbHueT, tmp);
2559 sprintf(tmp, "%d", value[1]);
2560 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2561 sprintf(tmp, "%d", value[2]);
2562 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2564 WMSetSliderValue(panel->hsbHueS, value[0]);
2565 WMSetSliderValue(panel->hsbSaturationS, value[1]);
2566 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
2568 cpColor.hsv.hue = value[0];
2569 cpColor.hsv.saturation = value[1] * 2.55;
2570 cpColor.hsv.value = value[2] * 2.55;
2571 cpColor.set = cpHSV;
2573 convertCPColor(&cpColor);
2575 panel->lastChanged = WMHSBModeColorPanel;
2576 updateSwatch(panel, cpColor);
2578 hsbUpdateBrightnessGradient(panel);
2579 hsbUpdateSaturationGradient(panel);
2580 hsbUpdateHueGradient(panel);
2583 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel)
2585 W_Screen *scr = WMWidgetScreen(panel->win);
2586 RColor from;
2587 CPColor to;
2588 RImage *sliderImg;
2589 WMPixmap *sliderPxmp;
2591 from.red = from.green = from.blue = 0;
2592 to.hsv = panel->color.hsv;
2593 to.hsv.value = 255;
2594 to.set = cpHSV;
2596 convertCPColor(&to);
2598 sliderImg = RRenderGradient(141, 16, &from, &(to.rgb), RGRD_HORIZONTAL);
2599 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2600 RReleaseImage(sliderImg);
2602 if (sliderPxmp)
2603 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
2604 panel->font12, 2, 0, 100, WALeft, scr->white,
2605 False, _("Brightness"), strlen(_("Brightness")));
2606 else
2607 wwarning(_("Color Panel: Could not allocate memory"));
2609 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
2610 WMReleasePixmap(sliderPxmp);
2613 static void hsbUpdateSaturationGradient(W_ColorPanel * panel)
2615 W_Screen *scr = WMWidgetScreen(panel->win);
2616 CPColor from;
2617 CPColor to;
2618 RImage *sliderImg;
2619 WMPixmap *sliderPxmp;
2621 from.hsv = panel->color.hsv;
2622 from.hsv.saturation = 0;
2623 from.set = cpHSV;
2624 convertCPColor(&from);
2626 to.hsv = panel->color.hsv;
2627 to.hsv.saturation = 255;
2628 to.set = cpHSV;
2629 convertCPColor(&to);
2631 sliderImg = RRenderGradient(141, 16, &(from.rgb), &(to.rgb), RGRD_HORIZONTAL);
2632 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2633 RReleaseImage(sliderImg);
2635 if (sliderPxmp)
2636 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2637 panel->font12, 2, 0, 100, WALeft,
2638 from.hsv.value < 128 ? scr->white : scr->black, False,
2639 _("Saturation"), strlen(_("Saturation")));
2640 else
2641 wwarning(_("Color Panel: Could not allocate memory"));
2643 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
2644 WMReleasePixmap(sliderPxmp);
2647 static void hsbUpdateHueGradient(W_ColorPanel * panel)
2649 W_Screen *scr = WMWidgetScreen(panel->win);
2650 RColor **colors = NULL;
2651 RHSVColor hsvcolor;
2652 RImage *sliderImg;
2653 WMPixmap *sliderPxmp;
2654 int i;
2656 hsvcolor = panel->color.hsv;
2658 colors = wmalloc(sizeof(RColor *) * (8));
2659 for (i = 0; i < 7; i++) {
2660 hsvcolor.hue = (360 * i) / 6;
2661 colors[i] = wmalloc(sizeof(RColor));
2662 RHSVtoRGB(&hsvcolor, colors[i]);
2664 colors[7] = NULL;
2666 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2667 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2668 RReleaseImage(sliderImg);
2670 if (sliderPxmp)
2671 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2672 panel->font12, 2, 0, 100, WALeft,
2673 hsvcolor.value < 128 ? scr->white : scr->black, False, _("Hue"), strlen(_("Hue")));
2674 else
2675 wwarning(_("Color Panel: Could not allocate memory"));
2677 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2678 WMReleasePixmap(sliderPxmp);
2680 for (i = 0; i < 7; i++)
2681 wfree(colors[i]);
2683 wfree(colors);
2686 /*************** Custom Palette Functions ****************/
2688 static void customRenderSpectrum(W_ColorPanel * panel)
2690 RImage *spectrum;
2691 int x, y;
2692 unsigned char *ptr;
2693 CPColor cpColor;
2695 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, False);
2697 ptr = spectrum->data;
2699 for (y = 0; y < SPECTRUM_HEIGHT; y++) {
2700 cpColor.hsv.hue = y;
2701 cpColor.hsv.saturation = 0;
2702 cpColor.hsv.value = 255;
2703 cpColor.set = cpHSV;
2705 for (x = 0; x < SPECTRUM_WIDTH; x++) {
2706 convertCPColor(&cpColor);
2708 *(ptr++) = (unsigned char)cpColor.rgb.red;
2709 *(ptr++) = (unsigned char)cpColor.rgb.green;
2710 *(ptr++) = (unsigned char)cpColor.rgb.blue;
2712 if (x < (SPECTRUM_WIDTH / 2))
2713 cpColor.hsv.saturation++;
2715 if (x > (SPECTRUM_WIDTH / 2))
2716 cpColor.hsv.value--;
2719 if (panel->customPaletteImg) {
2720 RReleaseImage(panel->customPaletteImg);
2721 panel->customPaletteImg = NULL;
2723 panel->customPaletteImg = spectrum;
2726 static void customSetPalette(W_ColorPanel * panel)
2728 W_Screen *scr = WMWidgetScreen(panel->win);
2729 RImage *scaledImg;
2730 Pixmap image;
2731 int item;
2733 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth, customPaletteHeight, scr->depth);
2734 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth, customPaletteHeight);
2735 RConvertImage(scr->rcontext, scaledImg, &image);
2736 RReleaseImage(scaledImg);
2738 XCopyArea(scr->display, image, panel->customPaletteContentView->window,
2739 scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2741 /* Check backimage exists. If it doesn't, allocate and fill it */
2742 if (!panel->selectionBackImg) {
2743 panel->selectionBackImg = XCreatePixmap(scr->display,
2744 panel->customPaletteContentView->window, 4, 4, scr->depth);
2747 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
2748 panel->palx - 2, panel->paly - 2, 4, 4, 0, 0);
2749 XCopyArea(scr->display, panel->selectionImg,
2750 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2751 panel->palx - 2, panel->paly - 2);
2752 XFreePixmap(scr->display, image);
2754 panel->palXRatio = (double)(panel->customPaletteImg->width) / (double)(customPaletteWidth);
2755 panel->palYRatio = (double)(panel->customPaletteImg->height) / (double)(customPaletteHeight);
2757 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
2760 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y)
2762 W_Screen *scr = WMWidgetScreen(panel->win);
2763 unsigned long ofs;
2765 /* undraw selection */
2766 XCopyArea(scr->display, panel->selectionBackImg,
2767 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2768 panel->palx - 2, panel->paly - 2);
2770 panel->palx = x;
2771 panel->paly = y;
2773 ofs = (rint(x * panel->palXRatio) + rint(y * panel->palYRatio) * panel->customPaletteImg->width) * 3;
2775 panel->color.rgb.red = panel->customPaletteImg->data[ofs];
2776 panel->color.rgb.green = panel->customPaletteImg->data[ofs + 1];
2777 panel->color.rgb.blue = panel->customPaletteImg->data[ofs + 2];
2778 panel->color.set = cpRGB;
2780 updateSwatch(panel, panel->color);
2781 panel->lastChanged = WMCustomPaletteModeColorPanel;
2783 /* Redraw color selector (and make a backup of the part it will cover) */
2784 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 */
2785 XCopyArea(scr->display, panel->selectionImg, panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4, panel->palx - 2, panel->paly - 2); /* see above */
2788 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2790 if (x < 2)
2791 x = 2;
2792 if (y < 2)
2793 y = 2;
2794 if (x >= customPaletteWidth)
2795 x = customPaletteWidth - 2;
2796 if (y >= customPaletteHeight)
2797 y = customPaletteHeight - 2;
2799 customPalettePositionSelection(panel, x, y);
2802 static void customPaletteHandleEvents(XEvent * event, void *data)
2804 W_ColorPanel *panel = (W_ColorPanel *) data;
2806 switch (event->type) {
2807 case Expose:
2808 if (event->xexpose.count != 0) /* TODO Improve. */
2809 break;
2810 customSetPalette(panel);
2811 break;
2815 static void customPaletteHandleActionEvents(XEvent * event, void *data)
2817 W_ColorPanel *panel = (W_ColorPanel *) data;
2818 int x, y;
2820 switch (event->type) {
2821 case ButtonPress:
2822 x = event->xbutton.x;
2823 y = event->xbutton.y;
2825 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2826 panel->flags.dragging = 1;
2827 customPalettePositionSelection(panel, x, y);
2829 break;
2831 case ButtonRelease:
2832 panel->flags.dragging = 0;
2833 if (!panel->flags.continuous) {
2834 if (panel->action)
2835 (*panel->action) (panel, panel->clientData);
2837 break;
2839 case MotionNotify:
2840 x = event->xmotion.x;
2841 y = event->xmotion.y;
2843 if (panel->flags.dragging) {
2844 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2845 customPalettePositionSelection(panel, x, y);
2846 } else
2847 customPalettePositionSelectionOutBounds(panel, x, y);
2849 break;
2853 static void customPaletteMenuCallback(WMWidget * w, void *data)
2855 W_ColorPanel *panel = (W_ColorPanel *) data;
2856 int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
2858 switch (item) {
2859 case CPmenuNewFromFile:
2860 customPaletteMenuNewFromFile(panel);
2861 break;
2862 case CPmenuRename:
2863 customPaletteMenuRename(panel);
2864 break;
2865 case CPmenuRemove:
2866 customPaletteMenuRemove(panel);
2867 break;
2868 case CPmenuCopy:
2869 break;
2870 case CPmenuNewFromClipboard:
2871 break;
2875 static void customPaletteMenuNewFromFile(W_ColorPanel * panel)
2877 W_Screen *scr = WMWidgetScreen(panel->win);
2878 WMOpenPanel *browseP;
2879 char *filepath;
2880 char *filename = NULL;
2881 char *spath;
2882 char *tmp;
2883 int i;
2884 RImage *tmpImg = NULL;
2886 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir, "\0") == 0))
2887 spath = wexpandpath(wgethomedir());
2888 else
2889 spath = wexpandpath(panel->lastBrowseDir);
2891 browseP = WMGetOpenPanel(scr);
2892 WMSetFilePanelCanChooseDirectories(browseP, 0);
2893 WMSetFilePanelCanChooseFiles(browseP, 1);
2895 /* Get a filename */
2896 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
2897 _("Open Palette"), RSupportedFileFormats())) {
2898 filepath = WMGetFilePanelFileName(browseP);
2900 /* Get seperation position between path and filename */
2901 i = strrchr(filepath, '/') - filepath + 1;
2902 if (i > strlen(filepath))
2903 i = strlen(filepath);
2905 /* Store last browsed path */
2906 if (panel->lastBrowseDir)
2907 wfree(panel->lastBrowseDir);
2908 panel->lastBrowseDir = wmalloc((i + 1) * sizeof(char));
2909 strncpy(panel->lastBrowseDir, filepath, i);
2910 panel->lastBrowseDir[i] = '\0';
2912 /* Get filename from path */
2913 filename = wstrdup(filepath + i);
2915 /* Check for duplicate files, and rename it if there are any */
2916 tmp = wstrconcat(panel->configurationPath, filename);
2917 while (access(tmp, F_OK) == 0) {
2918 char *newName;
2920 wfree(tmp);
2922 newName = generateNewFilename(filename);
2923 wfree(filename);
2924 filename = newName;
2926 tmp = wstrconcat(panel->configurationPath, filename);
2928 wfree(tmp);
2930 /* Copy image to $(gnustepdir)/Library/Colors/ &
2931 * Add filename to history menu */
2932 if (fetchFile(panel->configurationPath, filepath, filename) == 0) {
2934 /* filepath is a "local" path now the file has been copied */
2935 wfree(filepath);
2936 filepath = wstrconcat(panel->configurationPath, filename);
2938 /* load the image & add menu entries */
2939 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
2940 if (tmpImg) {
2941 if (panel->customPaletteImg)
2942 RReleaseImage(panel->customPaletteImg);
2943 panel->customPaletteImg = tmpImg;
2945 customSetPalette(panel);
2946 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
2948 panel->currentPalette =
2949 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1;
2951 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
2952 panel->currentPalette);
2954 } else {
2955 tmp = wstrconcat(panel->configurationPath, filename);
2957 i = remove(tmp); /* Delete the file, it doesn't belong here */
2958 WMRunAlertPanel(scr, panel->win, _("File Error"),
2959 _("Invalid file format !"), _("OK"), NULL, NULL);
2960 if (i != 0) {
2961 wsyserror(_("can't remove file %s"), tmp);
2962 WMRunAlertPanel(scr, panel->win, _("File Error"),
2963 _("Couldn't remove file from Configuration Directory !"),
2964 _("OK"), NULL, NULL);
2966 wfree(tmp);
2968 wfree(filepath);
2969 wfree(filename);
2971 WMFreeFilePanel(browseP);
2973 wfree(spath);
2976 static void customPaletteMenuRename(W_ColorPanel * panel)
2978 W_Screen *scr = WMWidgetScreen(panel->win);
2979 char *toName = NULL;
2980 char *fromName;
2981 char *toPath, *fromPath;
2982 int item;
2983 int index;
2985 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
2986 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
2988 toName = WMRunInputPanel(scr, panel->win, _("Rename"), _("Rename palette to:"),
2989 fromName, _("OK"), _("Cancel"));
2991 if (toName) {
2993 /* As some people do certain stupid things... */
2994 if (strcmp(toName, fromName) == 0) {
2995 wfree(toName);
2996 return;
2999 /* For normal people */
3000 fromPath = wstrconcat(panel->configurationPath, fromName);
3001 toPath = wstrconcat(panel->configurationPath, toName);
3003 if (access(toPath, F_OK) == 0) {
3004 /* Careful, this palette exists already */
3005 if (WMRunAlertPanel(scr, panel->win, _("Warning"),
3006 _("Palette already exists !\n\nOverwrite ?"), _("No"), _("Yes"),
3007 NULL) == 1) {
3008 /* "No" = 0, "Yes" = 1 */
3009 int items = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
3011 remove(toPath);
3013 /* Remove from History list too */
3014 index = 1;
3015 while ((index < items)
3017 (strcmp(WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, index), toName)
3018 != 0))
3019 index++;
3021 if (index < items) {
3022 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, index);
3023 if (index < item)
3024 item--;
3027 } else {
3028 wfree(fromPath);
3029 wfree(toName);
3030 wfree(toPath);
3032 return;
3036 if (rename(fromPath, toPath) != 0)
3037 wsyserror(_("Couldn't rename palette %s to %s\n"), fromName, toName);
3038 else {
3039 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3040 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item, toName);
3042 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
3044 wfree(fromPath);
3045 wfree(toPath);
3046 wfree(toName);
3050 static void customPaletteMenuRemove(W_ColorPanel * panel)
3052 W_Screen *scr = WMWidgetScreen(panel->win);
3053 char *text;
3054 char *tmp;
3055 int choice;
3056 int item;
3058 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3060 tmp = wstrconcat(_("This will permanently remove the palette "),
3061 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3062 text = wstrconcat(tmp, _(".\n\nAre you sure you want to remove this palette ?"));
3063 wfree(tmp);
3065 choice = WMRunAlertPanel(scr, panel->win, _("Remove"), text, _("Yes"), _("No"), NULL);
3066 /* returns 0 (= "Yes") or 1 (="No") */
3067 wfree(text);
3069 if (choice == 0) {
3071 tmp = wstrconcat(panel->configurationPath,
3072 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3074 if (remove(tmp) == 0) {
3075 /* item-1 always exists */
3076 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3078 customPaletteHistoryCallback(panel->customPaletteHistoryBtn, panel);
3079 customSetPalette(panel);
3081 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3083 } else {
3084 wsyserror(_("Couldn't remove palette %s\n"), tmp);
3087 wfree(tmp);
3091 static void customPaletteHistoryCallback(WMWidget * w, void *data)
3093 W_ColorPanel *panel = (W_ColorPanel *) data;
3094 W_Screen *scr = WMWidgetScreen(panel->win);
3095 int item;
3096 char *filename;
3097 RImage *tmp = NULL;
3098 unsigned char perm_mask;
3100 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3101 if (item == panel->currentPalette)
3102 return;
3104 if (item == 0) {
3105 customRenderSpectrum(panel);
3107 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, False);
3108 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, False);
3109 } else {
3110 /* Load file from configpath */
3111 filename = wstrconcat(panel->configurationPath,
3112 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3114 /* If the file corresponding to the item does not exist,
3115 * remove it from the history list and select the next one.
3117 perm_mask = (access(filename, F_OK) == 0);
3118 if (!perm_mask) {
3119 /* File does not exist */
3120 wfree(filename);
3121 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3122 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3123 customPaletteHistoryCallback(w, data);
3124 return;
3127 /* Get the image */
3128 tmp = RLoadImage(scr->rcontext, filename, 0);
3129 if (tmp) {
3130 if (panel->customPaletteImg) {
3131 RReleaseImage(panel->customPaletteImg);
3132 panel->customPaletteImg = NULL;
3134 panel->customPaletteImg = tmp;
3137 /* If the image is not writable, don't allow removing/renaming */
3138 perm_mask = (access(filename, W_OK) == 0);
3139 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, perm_mask);
3140 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, perm_mask);
3142 wfree(filename);
3144 customSetPalette(panel);
3146 panel->currentPalette = item;
3149 /************************* ColorList Panel Functions **********************/
3151 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect)
3153 WMScreen *scr = WMWidgetScreen(lPtr);
3154 Display *dpy = WMScreenDisplay(scr);
3155 WMView *view = W_VIEW(lPtr);
3156 RColor *color = (RColor *) WMGetListItem(lPtr, index)->clientData;
3157 W_ColorPanel *panel = WMGetHangedData(lPtr);
3158 int width, height, x, y;
3159 WMColor *fillColor;
3161 width = rect->size.width;
3162 height = rect->size.height;
3163 x = rect->pos.x;
3164 y = rect->pos.y;
3166 if (state & WLDSSelected)
3167 XFillRectangle(dpy, d, WMColorGC(scr->white), x, y, width, height);
3168 else
3169 XFillRectangle(dpy, d, WMColorGC(view->backColor), x, y, width, height);
3171 fillColor = WMCreateRGBColor(scr, color->red << 8, color->green << 8, color->blue << 8, True);
3173 XFillRectangle(dpy, d, WMColorGC(fillColor), x, y, 15, height);
3174 WMReleaseColor(fillColor);
3176 WMDrawString(scr, d, scr->black, panel->font12, x + 18, y, text, strlen(text));
3179 static void colorListSelect(WMWidget * w, void *data)
3181 W_ColorPanel *panel = (W_ColorPanel *) data;
3182 CPColor cpColor;
3184 cpColor.rgb = *((RColor *) WMGetListSelectedItem(w)->clientData);
3185 cpColor.set = cpRGB;
3187 panel->lastChanged = WMColorListModeColorPanel;
3188 updateSwatch(panel, cpColor);
3191 static void colorListColorMenuCallback(WMWidget * w, void *data)
3193 W_ColorPanel *panel = (W_ColorPanel *) data;
3194 int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
3196 switch (item) {
3197 case CLmenuAdd:
3198 break;
3199 case CLmenuRename:
3200 break;
3201 case CLmenuRemove:
3202 break;
3206 static void colorListListMenuCallback(WMWidget * w, void *data)
3208 W_ColorPanel *panel = (W_ColorPanel *) data;
3209 int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
3211 switch (item) {
3212 case CLmenuAdd:
3213 /* New Color List */
3214 colorListListMenuNew(panel);
3215 break;
3216 case CLmenuRename:
3217 break;
3218 case CLmenuRemove:
3219 break;
3223 static void colorListListMenuNew(W_ColorPanel * panel)
3228 /*************** Panel Initialisation Functions *****************/
3230 static void wheelInit(W_ColorPanel * panel)
3232 CPColor cpColor;
3234 if (panel->color.set != cpHSV)
3235 convertCPColor(&panel->color);
3237 WMSetSliderValue(panel->wheelBrightnessS, 255 - panel->color.hsv.value);
3239 panel->colx = 2 + rint((colorWheelSize / 2.0) *
3240 (1 + (panel->color.hsv.saturation / 255.0) *
3241 cos(panel->color.hsv.hue * M_PI / 180.0)));
3242 panel->coly = 2 + rint((colorWheelSize / 2.0) *
3243 (1 + (panel->color.hsv.saturation / 255.0) *
3244 sin(-panel->color.hsv.hue * M_PI / 180.0)));
3246 wheelCalculateValues(panel, panel->color.hsv.value);
3248 cpColor = panel->color;
3249 cpColor.hsv.value = 255;
3250 cpColor.set = cpHSV;
3251 wheelUpdateBrightnessGradient(panel, cpColor);
3254 static void grayInit(W_ColorPanel * panel)
3256 int value;
3257 char tmp[4];
3259 if (panel->color.set != cpHSV)
3260 convertCPColor(&panel->color);
3262 value = rint(panel->color.hsv.value / 2.55);
3263 WMSetSliderValue(panel->grayBrightnessS, value);
3265 sprintf(tmp, "%d", value);
3266 WMSetTextFieldText(panel->grayBrightnessT, tmp);
3269 static void rgbInit(W_ColorPanel * panel)
3271 char tmp[4];
3273 if (panel->color.set != cpRGB)
3274 convertCPColor(&panel->color);
3276 WMSetSliderValue(panel->rgbRedS, panel->color.rgb.red);
3277 WMSetSliderValue(panel->rgbGreenS, panel->color.rgb.green);
3278 WMSetSliderValue(panel->rgbBlueS, panel->color.rgb.blue);
3280 sprintf(tmp, "%d", panel->color.rgb.red);
3281 WMSetTextFieldText(panel->rgbRedT, tmp);
3282 sprintf(tmp, "%d", panel->color.rgb.green);
3283 WMSetTextFieldText(panel->rgbGreenT, tmp);
3284 sprintf(tmp, "%d", panel->color.rgb.blue);
3285 WMSetTextFieldText(panel->rgbBlueT, tmp);
3288 static void cmykInit(W_ColorPanel * panel)
3290 int value[3];
3291 char tmp[4];
3293 if (panel->color.set != cpRGB)
3294 convertCPColor(&panel->color);
3296 value[0] = rint((255 - panel->color.rgb.red) / 2.55);
3297 value[1] = rint((255 - panel->color.rgb.green) / 2.55);
3298 value[2] = rint((255 - panel->color.rgb.blue) / 2.55);
3300 WMSetSliderValue(panel->cmykCyanS, value[0]);
3301 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3302 WMSetSliderValue(panel->cmykYellowS, value[2]);
3303 WMSetSliderValue(panel->cmykBlackS, 0);
3305 sprintf(tmp, "%d", value[0]);
3306 WMSetTextFieldText(panel->cmykCyanT, tmp);
3307 sprintf(tmp, "%d", value[1]);
3308 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3309 sprintf(tmp, "%d", value[2]);
3310 WMSetTextFieldText(panel->cmykYellowT, tmp);
3311 WMSetTextFieldText(panel->cmykBlackT, "0");
3314 static void hsbInit(W_ColorPanel * panel)
3316 int value[3];
3317 char tmp[4];
3319 if (panel->color.set != cpHSV)
3320 convertCPColor(&panel->color);
3322 value[0] = panel->color.hsv.hue;
3323 value[1] = rint(panel->color.hsv.saturation / 2.55);
3324 value[2] = rint(panel->color.hsv.value / 2.55);
3326 WMSetSliderValue(panel->hsbHueS, value[0]);
3327 WMSetSliderValue(panel->hsbSaturationS, value[1]);
3328 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
3330 sprintf(tmp, "%d", value[0]);
3331 WMSetTextFieldText(panel->hsbHueT, tmp);
3332 sprintf(tmp, "%d", value[1]);
3333 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3334 sprintf(tmp, "%d", value[2]);
3335 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3337 hsbUpdateBrightnessGradient(panel);
3338 hsbUpdateSaturationGradient(panel);
3339 hsbUpdateHueGradient(panel);
3342 /************************** Common utility functions ************************/
3344 static int fetchFile(char *toPath, char *srcFile, char *destFile)
3346 int src, dest;
3347 int n;
3348 char *tmp;
3349 char buf[BUFSIZE];
3351 if ((src = open(srcFile, O_RDONLY | O_BINARY)) == 0) {
3352 wsyserror(_("Could not open %s"), srcFile);
3353 return -1;
3356 tmp = wstrconcat(toPath, destFile);
3357 if ((dest = open(tmp, O_RDWR | O_CREAT | O_BINARY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))
3358 == 0) {
3359 wsyserror(_("Could not create %s"), tmp);
3360 wfree(tmp);
3361 return -1;
3363 wfree(tmp);
3365 /* Copy the file */
3366 while ((n = read(src, buf, BUFSIZE)) > 0) {
3367 if (write(dest, buf, n) != n) {
3368 wsyserror(_("Write error on file %s"), destFile);
3369 return -1;
3373 return 0;
3376 char *generateNewFilename(char *curName)
3378 int n;
3379 char c;
3380 int baseLen;
3381 char *ptr;
3382 char *newName;
3384 assert(curName);
3386 ptr = curName;
3388 if (((ptr = strrchr(ptr, '{')) == 0) || sscanf(ptr, "{%i}%c", &n, &c) != 1)
3389 return wstrconcat(curName, " {1}");
3391 baseLen = ptr - curName - 1;
3393 newName = wmalloc(baseLen + 16);
3394 strncpy(newName, curName, baseLen);
3395 newName[baseLen] = 0;
3397 sprintf(&newName[baseLen], " {%i}", n + 1);
3399 return newName;
3402 void convertCPColor(CPColor * color)
3404 unsigned short old_hue = 0;
3406 switch (color->set) {
3407 case cpNone:
3408 wwarning(_("Color Panel: Color unspecified"));
3409 return;
3410 case cpRGB:
3411 old_hue = color->hsv.hue;
3412 RRGBtoHSV(&(color->rgb), &(color->hsv));
3414 /* In black the hue is undefined, and may change by conversion
3415 * Same for white. */
3416 if (((color->rgb.red == 0) &&
3417 (color->rgb.green == 0) &&
3418 (color->rgb.blue == 0)) ||
3419 ((color->rgb.red == 0) && (color->rgb.green == 0) && (color->rgb.blue == 255))
3421 color->hsv.hue = old_hue;
3422 break;
3423 case cpHSV:
3424 RHSVtoRGB(&(color->hsv), &(color->rgb));
3425 break;
3429 #define ABS_SHIFT(val, shift) \
3430 (((shift) > 0) ? (val) >> (shift) : (val) << -(shift))
3432 RColor ulongToRColor(WMScreen * scr, unsigned long value)
3434 RColor color;
3435 XColor *xcolor = NULL;
3437 if (!(xcolor = wmalloc(sizeof(XColor)))) {
3438 wwarning(_("Color Panel: Could not allocate memory"));
3439 color.red = 0;
3440 color.green = 0;
3441 color.blue = 0;
3442 color.alpha = 0;
3443 return color;
3446 xcolor->pixel = value;
3447 XQueryColor(scr->display, scr->rcontext->cmap, xcolor);
3449 color.red = xcolor->red >> 8;
3450 color.green = xcolor->green >> 8;
3451 color.blue = xcolor->blue >> 8;
3452 color.alpha = 0;
3454 wfree(xcolor);
3456 return color;
3459 unsigned char getShift(unsigned char value)
3461 unsigned char i = -1;
3463 if (value == 0)
3464 return 0;
3466 while (value) {
3467 value >>= 1;
3468 i++;
3471 return i;
3474 #ifdef SHAPE_WAS_DEFINED
3475 #undef SHAPE_WAS_DEFINED
3476 #define SHAPE
3477 #endif