Switch file ops to stdio
[wmaker-crm.git] / WINGs / wcolorpanel.c
blob6a6ebd050a7a92815b546b16861cbbdb5fd7f59a
1 /*
2 * ColorPanel for WINGs
4 * by ]d : Original idea and basic initial code
5 * Pascal Hofstee : Code for wheeldrawing and calculating
6 * colors from it.
7 * Primary coder of this Color Panel.
8 * Alban Hertroys : Optimizations for algorithms for color-
9 * wheel. Also custom ColorPalettes and
10 * magnifying glass. Secondary coder ;)
11 * Alfredo K. Kojima : For pointing out memory-allocation
12 * problems and similair code-issues
13 * Marco van Hylckama-Vlieg : For once again doing the artwork ;-)
17 /* TODO:
18 * - Look at further optimization of colorWheel matrix calculation.
19 * It appears to be rather symmetric in angles of 60 degrees,
20 * while it is optimized in angles of 90 degrees.
21 * - Custom color-lists and custom colors in custom color-lists.
22 * - Stored colors
23 * - Resizing
26 #include "wconfig.h"
27 #include "WINGsP.h"
28 #include "rgb.h"
30 #include <errno.h>
31 #include <math.h>
32 #include <unistd.h>
33 #include <ctype.h>
34 #include <fcntl.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <dirent.h>
39 #define RETRY( x ) do { \
40 x; \
41 } while (errno == EINTR);
43 /* BUG There's something fishy with shaped windows */
44 /* Whithout shape extension the magnified image is completely broken -Dan */
45 #if 0
46 # ifdef SHAPE
47 # define SHAPE_WAS_DEFINED
48 # undef SHAPE
49 # endif
50 #endif
52 #ifdef SHAPE
53 # include <X11/extensions/shape.h>
54 #endif
56 char *WMColorPanelColorChangedNotification = "WMColorPanelColorChangedNotification";
59 * Bitmaps for magnifying glass cursor
62 /* Cursor */
63 #define Cursor_x_hot 11
64 #define Cursor_y_hot 11
65 #define Cursor_width 32
66 #define Cursor_height 32
67 static unsigned char Cursor_bits[] = {
68 0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
69 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
70 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
71 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
72 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
73 0x00, 0x08, 0x00, 0x50, 0x00, 0x10, 0x00, 0x88, 0x00, 0x20, 0x00, 0x5c, 0x01, 0xc0, 0x81,
74 0x3b, 0x02, 0x00, 0x7e, 0x70, 0x05, 0x00, 0x00, 0xe0, 0x08, 0x00, 0x00, 0xc0, 0x15, 0x00,
75 0x00, 0x80, 0x23, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x5c,
76 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x70
79 /* Cursor shape-mask */
80 #define Cursor_shape_width 32
81 #define Cursor_shape_height 32
82 static unsigned char Cursor_shape_bits[] = {
83 0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
84 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
85 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
86 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
87 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
88 0x00, 0x08, 0x00, 0x70, 0x00, 0x10, 0x00, 0xf8, 0x00, 0x20, 0x00, 0xfc, 0x01, 0xc0, 0x81,
89 0xfb, 0x03, 0x00, 0x7e, 0xf0, 0x07, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xc0, 0x1f, 0x00,
90 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xfc,
91 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x70
94 /* Clip-mask for magnified pixels */
95 #define Cursor_mask_width 24
96 #define Cursor_mask_height 24
97 static unsigned char Cursor_mask_bits[] = {
98 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0xff, 0x07,
99 0xf0, 0xff, 0x0f, 0xf8, 0xff, 0x1f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f,
100 0xfc, 0xff, 0x3f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f,
101 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfc, 0xff, 0x3f,
102 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xf8, 0xff, 0x1f, 0xf0, 0xff, 0x0f,
103 0xe0, 0xff, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00
106 typedef struct MovingView {
107 WMView *view; /* The view this is all about */
108 XImage *image; /* What's under the view */
109 XImage *dirtyRect; /* Storage of overlapped image area */
110 Pixmap magPix; /* Magnified part of pixmap */
111 RColor color; /* Color of a pixel in the image */
112 int x, y; /* Position of view */
113 } MovingView;
115 typedef struct CPColor {
116 RColor rgb; /* The RGB values of the color */
117 RHSVColor hsv; /* The HSV values of the color */
118 enum { /* Which one was last set ? */
119 cpNone,
120 cpRGB,
121 cpHSV
122 } set;
123 } CPColor;
125 typedef struct WheelMatrix {
126 unsigned int width, height; /* Size of the colorwheel */
127 unsigned char *data[3]; /* Wheel data (R,G,B) */
128 unsigned char values[256]; /* Precalculated values R,G & B = 0-255 */
129 } wheelMatrix;
131 typedef struct W_ColorPanel {
132 WMWindow *win;
133 WMFont *font8;
134 WMFont *font12;
135 void *clientData;
136 WMAction2 *action;
138 /* Common Stuff */
139 WMColorWell *colorWell;
140 WMButton *magnifyBtn;
141 WMButton *wheelBtn;
142 WMButton *slidersBtn;
143 WMButton *customPaletteBtn;
144 WMButton *colorListBtn;
146 /* Magnifying Glass */
147 MovingView *magnifyGlass;
149 /* ColorWheel Panel */
150 WMFrame *wheelFrm;
151 WMSlider *wheelBrightnessS;
152 WMView *wheelView;
154 /* Slider Panels */
155 WMFrame *slidersFrm;
156 WMFrame *seperatorFrm;
157 WMButton *grayBtn;
158 WMButton *rgbBtn;
159 WMButton *cmykBtn;
160 WMButton *hsbBtn;
161 /* Gray Scale Panel */
162 WMFrame *grayFrm;
163 WMLabel *grayMinL;
164 WMLabel *grayMaxL;
165 WMSlider *grayBrightnessS;
166 WMTextField *grayBrightnessT;
167 WMButton *grayPresetBtn[7];
169 /* RGB Panel */
170 WMFrame *rgbFrm;
171 WMLabel *rgbMinL;
172 WMLabel *rgbMaxL;
173 WMSlider *rgbRedS;
174 WMSlider *rgbGreenS;
175 WMSlider *rgbBlueS;
176 WMTextField *rgbRedT;
177 WMTextField *rgbGreenT;
178 WMTextField *rgbBlueT;
180 /* CMYK Panel */
181 WMFrame *cmykFrm;
182 WMLabel *cmykMinL;
183 WMLabel *cmykMaxL;
184 WMSlider *cmykCyanS;
185 WMSlider *cmykMagentaS;
186 WMSlider *cmykYellowS;
187 WMSlider *cmykBlackS;
188 WMTextField *cmykCyanT;
189 WMTextField *cmykMagentaT;
190 WMTextField *cmykYellowT;
191 WMTextField *cmykBlackT;
193 /* HSB Panel */
194 WMFrame *hsbFrm;
195 WMSlider *hsbHueS;
196 WMSlider *hsbSaturationS;
197 WMSlider *hsbBrightnessS;
198 WMTextField *hsbHueT;
199 WMTextField *hsbSaturationT;
200 WMTextField *hsbBrightnessT;
202 /* Custom Palette Panel */
203 WMFrame *customPaletteFrm;
204 WMPopUpButton *customPaletteHistoryBtn;
205 WMFrame *customPaletteContentFrm;
206 WMPopUpButton *customPaletteMenuBtn;
207 WMView *customPaletteContentView;
209 /* Color List Panel */
210 WMFrame *colorListFrm;
211 WMPopUpButton *colorListHistoryBtn;
212 WMList *colorListContentLst;
213 WMPopUpButton *colorListColorMenuBtn;
214 WMPopUpButton *colorListListMenuBtn;
216 /* Look-Up Tables and Images */
217 wheelMatrix *wheelMtrx;
218 Pixmap wheelImg;
219 Pixmap selectionImg;
220 Pixmap selectionBackImg;
221 RImage *customPaletteImg;
222 char *lastBrowseDir;
224 /* Common Data Fields */
225 CPColor color; /* Current color */
226 WMColorPanelMode mode; /* Current color selection mode */
227 WMColorPanelMode slidersmode; /* Current color sel. mode sliders panel */
228 WMColorPanelMode lastChanged; /* Panel that last changed the color */
229 int colx, coly; /* (x,y) of sel.-marker in WheelMode */
230 int palx, paly; /* (x,y) of sel.-marker in
231 CustomPaletteMode */
232 double palXRatio, palYRatio; /* Ratios in x & y between
233 original and scaled
234 palettesize */
235 int currentPalette;
236 char *configurationPath;
238 struct {
239 unsigned int continuous:1;
240 unsigned int dragging:1;
241 } flags;
242 } W_ColorPanel;
244 enum {
245 CPmenuNewFromFile,
246 CPmenuRename,
247 CPmenuRemove,
248 CPmenuCopy,
249 CPmenuNewFromClipboard
250 } customPaletteMenuItem;
252 enum {
253 CLmenuAdd,
254 CLmenuRename,
255 CLmenuRemove
256 } colorListMenuItem;
258 #define PWIDTH 194
259 #define PHEIGHT 266
260 #define colorWheelSize 150
261 #define customPaletteWidth 182
262 #define customPaletteHeight 106
263 #define knobThickness 8
265 #define SPECTRUM_WIDTH 511
266 #define SPECTRUM_HEIGHT 360
268 #define COLORWHEEL_PART 1
269 #define CUSTOMPALETTE_PART 2
270 #define BUFSIZE 1024
272 #define MAX_LENGTH 1024
274 #ifndef M_PI
275 #define M_PI 3.14159265358979323846
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 FILE *src, *dst;
3347 size_t nread, nwritten;
3348 char *dstpath;
3349 char buf[BUFSIZE];
3351 RETRY( src = fopen(srcFile, "rb") )
3352 if (src == NULL) {
3353 wsyserror(_("Could not open %s"), srcFile);
3354 return -1;
3357 dstpath = wstrconcat(toPath, destFile);
3358 RETRY( dst = fopen(dstpath, "wb") )
3359 if (dst == NULL) {
3360 wsyserror(_("Could not create %s"), dstpath);
3361 wfree(dstpath);
3362 RETRY( fclose(src) )
3363 return -1;
3366 do {
3367 RETRY( nread = fread(buf, 1, sizeof(buf), src) )
3368 if (ferror(src))
3369 break;
3371 RETRY( nwritten = fwrite(buf, 1, nread, dst) )
3372 if (ferror(dst) || feof(src))
3373 break;
3375 } while (1);
3377 if (ferror(src) || ferror(dst))
3378 unlink(dstpath);
3380 RETRY( fclose(src) )
3381 fsync(fileno(dst));
3382 RETRY( fclose(dst) )
3384 wfree(dstpath);
3385 return 0;
3388 char *generateNewFilename(char *curName)
3390 int n;
3391 char c;
3392 int baseLen;
3393 char *ptr;
3394 char *newName;
3396 assert(curName);
3398 ptr = curName;
3400 if (((ptr = strrchr(ptr, '{')) == 0) || sscanf(ptr, "{%i}%c", &n, &c) != 1)
3401 return wstrconcat(curName, " {1}");
3403 baseLen = ptr - curName - 1;
3405 newName = wmalloc(baseLen + 16);
3406 strncpy(newName, curName, baseLen);
3407 newName[baseLen] = 0;
3409 sprintf(&newName[baseLen], " {%i}", n + 1);
3411 return newName;
3414 void convertCPColor(CPColor * color)
3416 unsigned short old_hue = 0;
3418 switch (color->set) {
3419 case cpNone:
3420 wwarning(_("Color Panel: Color unspecified"));
3421 return;
3422 case cpRGB:
3423 old_hue = color->hsv.hue;
3424 RRGBtoHSV(&(color->rgb), &(color->hsv));
3426 /* In black the hue is undefined, and may change by conversion
3427 * Same for white. */
3428 if (((color->rgb.red == 0) &&
3429 (color->rgb.green == 0) &&
3430 (color->rgb.blue == 0)) ||
3431 ((color->rgb.red == 0) && (color->rgb.green == 0) && (color->rgb.blue == 255))
3433 color->hsv.hue = old_hue;
3434 break;
3435 case cpHSV:
3436 RHSVtoRGB(&(color->hsv), &(color->rgb));
3437 break;
3441 #define ABS_SHIFT(val, shift) \
3442 (((shift) > 0) ? (val) >> (shift) : (val) << -(shift))
3444 RColor ulongToRColor(WMScreen * scr, unsigned long value)
3446 RColor color;
3447 XColor *xcolor = NULL;
3449 if (!(xcolor = wmalloc(sizeof(XColor)))) {
3450 wwarning(_("Color Panel: Could not allocate memory"));
3451 color.red = 0;
3452 color.green = 0;
3453 color.blue = 0;
3454 color.alpha = 0;
3455 return color;
3458 xcolor->pixel = value;
3459 XQueryColor(scr->display, scr->rcontext->cmap, xcolor);
3461 color.red = xcolor->red >> 8;
3462 color.green = xcolor->green >> 8;
3463 color.blue = xcolor->blue >> 8;
3464 color.alpha = 0;
3466 wfree(xcolor);
3468 return color;
3471 unsigned char getShift(unsigned char value)
3473 unsigned char i = -1;
3475 if (value == 0)
3476 return 0;
3478 while (value) {
3479 value >>= 1;
3480 i++;
3483 return i;
3486 #ifdef SHAPE_WAS_DEFINED
3487 #undef SHAPE_WAS_DEFINED
3488 #define SHAPE
3489 #endif