wmaker: Reduce wakeups to zero
[wmaker-crm.git] / WINGs / wcolorpanel.c
blob58d0f01e70c0c295de951bcc68d842540a99b02c
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 ;-)
18 /* TODO:
19 * - Look at further optimization of colorWheel matrix calculation.
20 * It appears to be rather symmetric in angles of 60 degrees,
21 * while it is optimized in angles of 90 degrees.
22 * - Custom color-lists and custom colors in custom color-lists.
23 * - Stored colors
24 * - Resizing
27 #include "wconfig.h"
28 #include "WINGsP.h"
29 #include "rgb.h"
30 #include <math.h>
31 #include <unistd.h>
32 #include <ctype.h>
33 #include <fcntl.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <dirent.h>
37 #include <errno.h>
39 /* BUG There's something fishy with shaped windows */
40 /* Whithout shape extension the magnified image is completely broken -Dan */
41 #if 0
42 # ifdef SHAPE
43 # define SHAPE_WAS_DEFINED
44 # undef SHAPE
45 # endif
46 #endif
49 #ifdef SHAPE
50 # include <X11/extensions/shape.h>
51 #endif
54 char *WMColorPanelColorChangedNotification = "WMColorPanelColorChangedNotification";
58 * Bitmaps for magnifying glass cursor
61 /* Cursor */
62 #define Cursor_x_hot 11
63 #define Cursor_y_hot 11
64 #define Cursor_width 32
65 #define Cursor_height 32
66 static unsigned char Cursor_bits[] = {
67 0x00,0x7e,0x00,0x00,0xc0,0x81,0x03,0x00,0x20,0x00,0x04,0x00,0x10,0x00,0x08,
68 0x00,0x08,0x00,0x10,0x00,0x04,0x00,0x20,0x00,0x02,0x00,0x40,0x00,0x02,0x00,
69 0x40,0x00,0x02,0x00,0x40,0x00,0x01,0x42,0x80,0x00,0x01,0x24,0x80,0x00,0x01,
70 0x00,0x80,0x00,0x01,0x00,0x80,0x00,0x01,0x24,0x80,0x00,0x01,0x42,0x80,0x00,
71 0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x04,0x00,0x20,
72 0x00,0x08,0x00,0x50,0x00,0x10,0x00,0x88,0x00,0x20,0x00,0x5c,0x01,0xc0,0x81,
73 0x3b,0x02,0x00,0x7e,0x70,0x05,0x00,0x00,0xe0,0x08,0x00,0x00,0xc0,0x15,0x00,
74 0x00,0x80,0x23,0x00,0x00,0x00,0x57,0x00,0x00,0x00,0x8e,0x00,0x00,0x00,0x5c,
75 0x00,0x00,0x00,0xb8,0x00,0x00,0x00,0x70};
77 /* Cursor shape-mask */
78 #define Cursor_shape_width 32
79 #define Cursor_shape_height 32
80 static unsigned char Cursor_shape_bits[] = {
81 0x00,0x7e,0x00,0x00,0xc0,0x81,0x03,0x00,0x20,0x00,0x04,0x00,0x10,0x00,0x08,
82 0x00,0x08,0x00,0x10,0x00,0x04,0x00,0x20,0x00,0x02,0x00,0x40,0x00,0x02,0x00,
83 0x40,0x00,0x02,0x00,0x40,0x00,0x01,0x42,0x80,0x00,0x01,0x24,0x80,0x00,0x01,
84 0x00,0x80,0x00,0x01,0x00,0x80,0x00,0x01,0x24,0x80,0x00,0x01,0x42,0x80,0x00,
85 0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x04,0x00,0x20,
86 0x00,0x08,0x00,0x70,0x00,0x10,0x00,0xf8,0x00,0x20,0x00,0xfc,0x01,0xc0,0x81,
87 0xfb,0x03,0x00,0x7e,0xf0,0x07,0x00,0x00,0xe0,0x0f,0x00,0x00,0xc0,0x1f,0x00,
88 0x00,0x80,0x3f,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0xfc,
89 0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x70};
91 /* Clip-mask for magnified pixels */
92 #define Cursor_mask_width 24
93 #define Cursor_mask_height 24
94 static unsigned char Cursor_mask_bits[] = {
95 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0xff, 0x07,
96 0xf0, 0xff, 0x0f, 0xf8, 0xff, 0x1f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f,
97 0xfc, 0xff, 0x3f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f,
98 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfc, 0xff, 0x3f,
99 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xf8, 0xff, 0x1f, 0xf0, 0xff, 0x0f,
100 0xe0, 0xff, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00};
103 typedef struct MovingView {
104 WMView *view; /* The view this is all about */
105 XImage *image; /* What's under the view */
106 XImage *dirtyRect; /* Storage of overlapped image area */
107 Pixmap magPix; /* Magnified part of pixmap */
108 RColor color; /* Color of a pixel in the image */
109 int x, y; /* Position of view */
110 } MovingView;
112 typedef struct CPColor {
113 RColor rgb; /* The RGB values of the color */
114 RHSVColor hsv; /* The HSV values of the color */
115 enum { /* Which one was last set ? */
116 cpNone,
117 cpRGB,
118 cpHSV
119 } set;
120 } CPColor;
123 typedef struct WheelMatrix {
124 unsigned int width, height; /* Size of the colorwheel */
125 unsigned char *data[3]; /* Wheel data (R,G,B) */
126 unsigned char values[256]; /* Precalculated values R,G & B = 0-255 */
127 } wheelMatrix;
129 typedef struct W_ColorPanel {
130 WMWindow *win;
131 WMFont *font8;
132 WMFont *font12;
133 void *clientData;
134 WMAction2 *action;
136 /* Common Stuff */
137 WMColorWell *colorWell;
138 WMButton *magnifyBtn;
139 WMButton *wheelBtn;
140 WMButton *slidersBtn;
141 WMButton *customPaletteBtn;
142 WMButton *colorListBtn;
144 /* Magnifying Glass */
145 MovingView *magnifyGlass;
147 /* ColorWheel Panel */
148 WMFrame *wheelFrm;
149 WMSlider *wheelBrightnessS;
150 WMView *wheelView;
152 /* Slider Panels */
153 WMFrame *slidersFrm;
154 WMFrame *seperatorFrm;
155 WMButton *grayBtn;
156 WMButton *rgbBtn;
157 WMButton *cmykBtn;
158 WMButton *hsbBtn;
159 /* Gray Scale Panel */
160 WMFrame *grayFrm;
161 WMLabel *grayMinL;
162 WMLabel *grayMaxL;
163 WMSlider *grayBrightnessS;
164 WMTextField *grayBrightnessT;
165 WMButton *grayPresetBtn[7];
167 /* RGB Panel */
168 WMFrame *rgbFrm;
169 WMLabel *rgbMinL;
170 WMLabel *rgbMaxL;
171 WMSlider *rgbRedS;
172 WMSlider *rgbGreenS;
173 WMSlider *rgbBlueS;
174 WMTextField *rgbRedT;
175 WMTextField *rgbGreenT;
176 WMTextField *rgbBlueT;
178 /* CMYK Panel */
179 WMFrame *cmykFrm;
180 WMLabel *cmykMinL;
181 WMLabel *cmykMaxL;
182 WMSlider *cmykCyanS;
183 WMSlider *cmykMagentaS;
184 WMSlider *cmykYellowS;
185 WMSlider *cmykBlackS;
186 WMTextField *cmykCyanT;
187 WMTextField *cmykMagentaT;
188 WMTextField *cmykYellowT;
189 WMTextField *cmykBlackT;
191 /* HSB Panel */
192 WMFrame *hsbFrm;
193 WMSlider *hsbHueS;
194 WMSlider *hsbSaturationS;
195 WMSlider *hsbBrightnessS;
196 WMTextField *hsbHueT;
197 WMTextField *hsbSaturationT;
198 WMTextField *hsbBrightnessT;
200 /* Custom Palette Panel*/
201 WMFrame *customPaletteFrm;
202 WMPopUpButton *customPaletteHistoryBtn;
203 WMFrame *customPaletteContentFrm;
204 WMPopUpButton *customPaletteMenuBtn;
205 WMView *customPaletteContentView;
207 /* Color List Panel */
208 WMFrame *colorListFrm;
209 WMPopUpButton *colorListHistoryBtn;
210 WMList *colorListContentLst;
211 WMPopUpButton *colorListColorMenuBtn;
212 WMPopUpButton *colorListListMenuBtn;
214 /* Look-Up Tables and Images */
215 wheelMatrix *wheelMtrx;
216 Pixmap wheelImg;
217 Pixmap selectionImg;
218 Pixmap selectionBackImg;
219 RImage *customPaletteImg;
220 char *lastBrowseDir;
222 /* Common Data Fields */
223 CPColor color; /* Current color */
224 WMColorPanelMode mode; /* Current color selection mode */
225 WMColorPanelMode slidersmode; /* Current color sel. mode sliders panel */
226 WMColorPanelMode lastChanged; /* Panel that last changed the color */
227 int colx, coly; /* (x,y) of sel.-marker in WheelMode */
228 int palx, paly; /* (x,y) of sel.-marker in
229 CustomPaletteMode */
230 double palXRatio, palYRatio; /* Ratios in x & y between
231 original and scaled
232 palettesize */
233 int currentPalette;
234 char *configurationPath;
236 struct {
237 unsigned int continuous:1;
238 unsigned int dragging:1;
239 } flags;
240 } W_ColorPanel;
242 enum {
243 CPmenuNewFromFile,
244 CPmenuRename,
245 CPmenuRemove,
246 CPmenuCopy,
247 CPmenuNewFromClipboard
248 } customPaletteMenuItem;
250 enum {
251 CLmenuAdd,
252 CLmenuRename,
253 CLmenuRemove
254 } colorListMenuItem;
257 #define PWIDTH 194
258 #define PHEIGHT 266
259 #define colorWheelSize 150
260 #define customPaletteWidth 182
261 #define customPaletteHeight 106
262 #define knobThickness 8
264 #define SPECTRUM_WIDTH 511
265 #define SPECTRUM_HEIGHT 360
267 #define COLORWHEEL_PART 1
268 #define CUSTOMPALETTE_PART 2
269 #define BUFSIZE 1024
271 #define MAX_LENGTH 1024
274 #ifndef M_PI
275 #define M_PI 3.14159265358979323846
276 #endif
278 /* Silly hack for Windows systems with cygwin */
279 #ifndef O_BINARY
280 # define O_BINARY 0
281 #endif
283 static int fetchFile(char* toPath, char *imageSrcFile,
284 char *imageDestFileName);
285 char *generateNewFilename(char *curName);
286 void convertCPColor(CPColor *color);
287 RColor ulongToRColor(WMScreen *scr, unsigned long value);
288 unsigned char getShift(unsigned char value);
290 static void modeButtonCallback(WMWidget *w, void *data);
291 static int getPickerPart(W_ColorPanel *panel, int x, int y);
292 static void readConfiguration(W_ColorPanel *panel);
293 static void readXColors(W_ColorPanel *panel);
295 static void closeWindowCallback(WMWidget *w, void *data);
297 static Cursor magnifyGrabPointer(W_ColorPanel *panel);
298 static WMPoint magnifyInitialize(W_ColorPanel *panel);
299 static void magnifyPutCursor(WMWidget *w, void *data);
300 static Pixmap magnifyCreatePixmap(WMColorPanel *panel);
301 static void magnifyGetImageStored(W_ColorPanel *panel, int x1, int y1,
302 int x2, int y2);
303 static XImage* magnifyGetImage(WMScreen *scr, XImage *image, int x, int y,
304 int w, int h);
306 static wheelMatrix* wheelCreateMatrix(unsigned int width , unsigned int height);
307 static void wheelDestroyMatrix(wheelMatrix *matrix);
308 static void wheelInitMatrix(W_ColorPanel *panel);
309 static void wheelCalculateValues(W_ColorPanel *panel, int maxvalue);
310 static void wheelRender(W_ColorPanel *panel);
311 static Bool wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs);
312 static void wheelPaint(W_ColorPanel *panel);
314 static void wheelHandleEvents(XEvent *event, void *data);
315 static void wheelHandleActionEvents(XEvent *event, void *data);
316 static void wheelBrightnessSliderCallback(WMWidget *w, void *data);
317 static void wheelUpdateSelection(W_ColorPanel *panel);
318 static void wheelUndrawSelection(W_ColorPanel *panel);
320 static void wheelPositionSelection(W_ColorPanel *panel, int x, int y);
321 static void wheelPositionSelectionOutBounds(W_ColorPanel *panel, int x, int y);
322 static void wheelUpdateBrightnessGradientFromLocation (W_ColorPanel *panel);
323 static void wheelUpdateBrightnessGradient(W_ColorPanel *panel, CPColor topColor);
325 static void grayBrightnessSliderCallback(WMWidget *w, void *data);
326 static void grayPresetButtonCallback(WMWidget *w, void *data);
327 static void grayBrightnessTextFieldCallback(void *observerData,
328 WMNotification *notification);
330 static void rgbSliderCallback(WMWidget *w, void *data);
331 static void rgbTextFieldCallback(void *observerData,
332 WMNotification *notification);
334 static void cmykSliderCallback(WMWidget *w, void *data);
335 static void cmykTextFieldCallback(void *observerData,
336 WMNotification *notification);
338 static void hsbSliderCallback(WMWidget *w, void *data);
339 static void hsbTextFieldCallback(void *observerData,
340 WMNotification *notification);
341 static void hsbUpdateBrightnessGradient(W_ColorPanel *panel);
342 static void hsbUpdateSaturationGradient(W_ColorPanel *panel);
343 static void hsbUpdateHueGradient(W_ColorPanel *panel);
345 static void customRenderSpectrum(W_ColorPanel *panel);
346 static void customSetPalette(W_ColorPanel *panel);
347 static void customPaletteHandleEvents(XEvent *event, void *data);
348 static void customPaletteHandleActionEvents(XEvent *event, void *data);
349 static void customPalettePositionSelection(W_ColorPanel *panel, int x, int y);
350 static void customPalettePositionSelectionOutBounds(W_ColorPanel *panel,
351 int x, int y);
352 static void customPaletteMenuCallback(WMWidget *w, void *data);
353 static void customPaletteHistoryCallback(WMWidget *w, void *data);
355 static void customPaletteMenuNewFromFile(W_ColorPanel *panel);
356 static void customPaletteMenuRename(W_ColorPanel *panel);
357 static void customPaletteMenuRemove(W_ColorPanel *panel);
359 static void colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text,
360 int state, WMRect *rect);
361 static void colorListSelect(WMWidget *w, void *data);
362 static void colorListColorMenuCallback(WMWidget *w, void *data);
363 static void colorListListMenuCallback(WMWidget *w, void *data);
364 static void colorListListMenuNew(W_ColorPanel *panel);
366 static void wheelInit(W_ColorPanel *panel);
367 static void grayInit(W_ColorPanel *panel);
368 static void rgbInit(W_ColorPanel *panel);
369 static void cmykInit(W_ColorPanel *panel);
370 static void hsbInit(W_ColorPanel *panel);
374 void
375 WMSetColorPanelAction(WMColorPanel *panel, WMAction2 *action, void *data)
377 panel->action = action;
378 panel->clientData = data;
381 static WMColorPanel*
382 makeColorPanel(WMScreen *scrPtr, char *name)
384 WMColorPanel *panel;
385 RImage *image;
386 WMPixmap *pixmap;
387 RColor from;
388 RColor to;
389 WMColor *textcolor, *graybuttoncolor;
390 int i;
391 GC bgc = WMColorGC(scrPtr->black);
392 GC wgc = WMColorGC(scrPtr->white);
395 panel = wmalloc(sizeof(WMColorPanel));
396 memset(panel, 0, sizeof(WMColorPanel));
398 panel->color.rgb.red = 0;
399 panel->color.rgb.green = 0;
400 panel->color.rgb.blue = 0;
401 panel->color.hsv.hue = 0;
402 panel->color.hsv.saturation = 0;
403 panel->color.hsv.value = 0;
404 panel->color.set = cpNone; /* Color has not been set yet */
406 panel->font8 = WMSystemFontOfSize(scrPtr, 8);
407 panel->font12 = WMSystemFontOfSize(scrPtr, 12);
409 panel->win = WMCreateWindowWithStyle(scrPtr, name,
410 WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
411 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
412 WMSetWindowTitle(panel->win, _("Colors"));
413 WMSetWindowCloseAction(panel->win, closeWindowCallback, panel);
416 /* Set Default ColorPanel Mode(s) */
417 panel->mode = WMWheelModeColorPanel;
418 panel->lastChanged = 0;
419 panel->slidersmode = WMRGBModeColorPanel;
420 panel->configurationPath = wstrconcat(wusergnusteppath(),
421 "/Library/Colors/");
423 /* Some General Purpose Widgets */
424 panel->colorWell = WMCreateColorWell(panel->win);
425 WMResizeWidget(panel->colorWell, 134, 36);
426 WSetColorWellBordered(panel->colorWell, False);
427 WMMoveWidget(panel->colorWell, 56, 4);
429 panel->magnifyBtn = WMCreateCustomButton(panel->win,
430 WBBStateLightMask|WBBStateChangeMask);
431 WMResizeWidget(panel->magnifyBtn, 46, 36);
432 WMMoveWidget(panel->magnifyBtn, 6,4);
433 WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
434 WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
435 WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
437 panel->wheelBtn = WMCreateCustomButton(panel->win,
438 WBBStateLightMask|WBBStateChangeMask);
439 WMResizeWidget(panel->wheelBtn, 46, 32);
440 WMMoveWidget(panel->wheelBtn, 6, 44);
441 WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
442 WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
443 WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
445 panel->slidersBtn = WMCreateCustomButton(panel->win,
446 WBBStateLightMask|WBBStateChangeMask);
447 WMResizeWidget(panel->slidersBtn, 46, 32);
448 WMMoveWidget(panel->slidersBtn, 52, 44);
449 WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
450 WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
451 WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
453 panel->customPaletteBtn = WMCreateCustomButton(panel->win,
454 WBBStateLightMask|WBBStateChangeMask);
455 WMResizeWidget(panel->customPaletteBtn, 46, 32);
456 WMMoveWidget(panel->customPaletteBtn, 98, 44);
457 WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
458 WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
459 WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
461 panel->colorListBtn = WMCreateCustomButton(panel->win,
462 WBBStateLightMask|WBBStateChangeMask);
463 WMResizeWidget(panel->colorListBtn, 46, 32);
464 WMMoveWidget(panel->colorListBtn, 144, 44);
465 WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
466 WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
467 WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
469 /* Let's Group some of them together */
470 WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
471 WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
472 WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
474 /* Widgets for the ColorWheel Panel */
475 panel->wheelFrm = WMCreateFrame(panel->win);
476 WMSetFrameRelief(panel->wheelFrm, WRFlat);
477 WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
478 WMMoveWidget(panel->wheelFrm, 5, 80);
480 panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
481 /* XXX Can we create a view ? */
482 W_ResizeView(panel->wheelView, colorWheelSize+4, colorWheelSize+4);
483 W_MoveView(panel->wheelView, 0, 0);
485 /* Create an event handler to handle expose/click events in ColorWheel */
486 WMCreateEventHandler(panel->wheelView,
487 ButtonPressMask|ButtonReleaseMask|EnterWindowMask|
488 LeaveWindowMask|ButtonMotionMask, wheelHandleActionEvents, panel);
490 WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents,
491 panel);
493 panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
494 WMResizeWidget(panel->wheelBrightnessS, 16, 153);
495 WMMoveWidget(panel->wheelBrightnessS, 5+colorWheelSize+14, 1);
496 WMSetSliderMinValue(panel->wheelBrightnessS, 0);
497 WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
498 WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback,
499 panel);
500 WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
502 panel->wheelMtrx = wheelCreateMatrix(colorWheelSize+4, colorWheelSize+4);
503 wheelInitMatrix(panel);
506 /* Widgets for the Slider Panels */
507 panel->slidersFrm = WMCreateFrame(panel->win);
508 WMSetFrameRelief(panel->slidersFrm, WRFlat);
509 WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
510 WMMoveWidget(panel->slidersFrm, 4, 80);
512 panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
513 WMSetFrameRelief(panel->seperatorFrm, WRPushed);
514 WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
515 WMMoveWidget(panel->seperatorFrm, 0, 1);
517 panel->grayBtn = WMCreateCustomButton(panel->slidersFrm,
518 WBBStateLightMask|WBBStateChangeMask);
519 WMResizeWidget(panel->grayBtn, 46, 24);
520 WMMoveWidget(panel->grayBtn, 1, 8);
521 WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
522 WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
523 WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
525 panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm,
526 WBBStateLightMask|WBBStateChangeMask);
527 WMResizeWidget(panel->rgbBtn, 46, 24);
528 WMMoveWidget(panel->rgbBtn, 47, 8);
529 WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
530 WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
531 WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
533 panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm,
534 WBBStateLightMask|WBBStateChangeMask);
535 WMResizeWidget(panel->cmykBtn, 46, 24);
536 WMMoveWidget(panel->cmykBtn, 93, 8);
537 WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
538 WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
539 WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
541 panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm,
542 WBBStateLightMask|WBBStateChangeMask);
543 WMResizeWidget(panel->hsbBtn, 46, 24);
544 WMMoveWidget(panel->hsbBtn, 139, 8);
545 WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
546 WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
547 WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
549 /* Let's Group the Slider Panel Buttons Together */
550 WMGroupButtons(panel->grayBtn, panel->rgbBtn);
551 WMGroupButtons(panel->grayBtn, panel->cmykBtn);
552 WMGroupButtons(panel->grayBtn, panel->hsbBtn);
554 textcolor = WMDarkGrayColor(scrPtr);
556 /* Widgets for GrayScale Panel */
557 panel->grayFrm = WMCreateFrame(panel->slidersFrm);
558 WMSetFrameRelief(panel->grayFrm, WRFlat);
559 WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
560 WMMoveWidget(panel->grayFrm, 0, 34);
562 panel->grayMinL = WMCreateLabel(panel->grayFrm);
563 WMResizeWidget(panel->grayMinL, 20, 10);
564 WMMoveWidget(panel->grayMinL, 2, 2);
565 WMSetLabelText(panel->grayMinL, "0");
566 WMSetLabelTextAlignment(panel->grayMinL, WALeft);
567 WMSetLabelTextColor(panel->grayMinL, textcolor);
568 WMSetLabelFont(panel->grayMinL, panel->font8);
570 panel->grayMaxL = WMCreateLabel(panel->grayFrm);
571 WMResizeWidget(panel->grayMaxL, 40, 10);
572 WMMoveWidget(panel->grayMaxL, 104, 2);
573 WMSetLabelText(panel->grayMaxL, "100");
574 WMSetLabelTextAlignment(panel->grayMaxL, WARight);
575 WMSetLabelTextColor(panel->grayMaxL, textcolor);
576 WMSetLabelFont(panel->grayMaxL, panel->font8);
578 panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
579 WMResizeWidget(panel->grayBrightnessS, 141, 16);
580 WMMoveWidget(panel->grayBrightnessS, 2, 14);
581 WMSetSliderMinValue(panel->grayBrightnessS, 0);
582 WMSetSliderMaxValue(panel->grayBrightnessS, 100);
583 WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
584 WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback,
585 panel);
587 from.red = 0;
588 from.green = 0;
589 from.blue = 0;
591 to.red = 255;
592 to.green = 255;
593 to.blue = 255;
595 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
596 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
597 RReleaseImage(image);
599 if (pixmap)
600 W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap,
601 panel->font12, 2, 0, 100, WALeft, scrPtr->white,
602 False, _("Brightness"), strlen(_("Brightness")));
603 else
604 wwarning(_("Color Panel: Could not allocate memory"));
606 WMSetSliderImage(panel->grayBrightnessS, pixmap);
607 WMReleasePixmap(pixmap);
609 panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
610 WMResizeWidget(panel->grayBrightnessT, 40, 18);
611 WMMoveWidget(panel->grayBrightnessT, 146, 13);
612 WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
613 WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel,
614 WMTextDidEndEditingNotification, panel->grayBrightnessT);
616 for (i=0; i < 7; i++) {
617 pixmap = WMCreatePixmap(scrPtr, 13, 13, scrPtr->depth, False);
619 graybuttoncolor = WMCreateRGBColor(scrPtr, (255/6)*i << 8,
620 (255/6)*i << 8, (255/6)*i << 8, True);
621 WMPaintColorSwatch(graybuttoncolor, pixmap->pixmap, 0, 0, 15, 15);
622 WMReleaseColor(graybuttoncolor);
624 panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
625 WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
626 WMMoveWidget(panel->grayPresetBtn[i], 2+(i*20), 34);
627 WMSetButtonAction(panel->grayPresetBtn[i],
628 grayPresetButtonCallback, panel);
629 WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
630 WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
631 WMReleasePixmap(pixmap);
635 /* End of GrayScale Panel */
637 /* Widgets for RGB Panel */
638 panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
639 WMSetFrameRelief(panel->rgbFrm, WRFlat);
640 WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
641 WMMoveWidget(panel->rgbFrm, 0, 34);
643 panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
644 WMResizeWidget(panel->rgbMinL, 20, 10);
645 WMMoveWidget(panel->rgbMinL, 2, 2);
646 WMSetLabelText(panel->rgbMinL, "0");
647 WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
648 WMSetLabelTextColor(panel->rgbMinL, textcolor);
649 WMSetLabelFont(panel->rgbMinL, panel->font8);
651 panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
652 WMResizeWidget(panel->rgbMaxL, 40, 10);
653 WMMoveWidget(panel->rgbMaxL, 104, 2);
654 WMSetLabelText(panel->rgbMaxL, "255");
655 WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
656 WMSetLabelTextColor(panel->rgbMaxL, textcolor);
657 WMSetLabelFont(panel->rgbMaxL, panel->font8);
659 panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
660 WMResizeWidget(panel->rgbRedS, 141, 16);
661 WMMoveWidget(panel->rgbRedS, 2, 14);
662 WMSetSliderMinValue(panel->rgbRedS, 0);
663 WMSetSliderMaxValue(panel->rgbRedS, 255);
664 WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
665 WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
667 to.red = 255;
668 to.green = 0;
669 to.blue = 0;
671 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
672 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
673 RReleaseImage(image);
675 if (pixmap)
676 W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12,
677 2, 0, 100, WALeft, scrPtr->white, False, _("Red"),
678 strlen(_("Red")));
679 else
680 wwarning(_("Color Panel: Could not allocate memory"));
682 WMSetSliderImage(panel->rgbRedS, pixmap);
683 WMReleasePixmap(pixmap);
685 panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
686 WMResizeWidget(panel->rgbRedT, 40, 18);
687 WMMoveWidget(panel->rgbRedT, 146, 13);
688 WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
689 WMAddNotificationObserver(rgbTextFieldCallback, panel,
690 WMTextDidEndEditingNotification, panel->rgbRedT);
692 panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
693 WMResizeWidget(panel->rgbGreenS, 141, 16);
694 WMMoveWidget(panel->rgbGreenS, 2, 36);
695 WMSetSliderMinValue(panel->rgbGreenS, 0);
696 WMSetSliderMaxValue(panel->rgbGreenS, 255);
697 WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
698 WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
700 to.red = 0;
701 to.green = 255;
702 to.blue = 0;
704 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
705 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
706 RReleaseImage(image);
708 if (pixmap)
709 W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12,
710 2, 0, 100, WALeft, scrPtr->white, False, _("Green"),
711 strlen(_("Green")));
712 else
713 wwarning(_("Color Panel: Could not allocate memory"));
715 WMSetSliderImage(panel->rgbGreenS, pixmap);
716 WMReleasePixmap(pixmap);
718 panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
719 WMResizeWidget(panel->rgbGreenT, 40, 18);
720 WMMoveWidget(panel->rgbGreenT, 146, 35);
721 WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
722 WMAddNotificationObserver(rgbTextFieldCallback, panel,
723 WMTextDidEndEditingNotification, panel->rgbGreenT);
726 panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
727 WMResizeWidget(panel->rgbBlueS, 141, 16);
728 WMMoveWidget(panel->rgbBlueS, 2, 58);
729 WMSetSliderMinValue(panel->rgbBlueS, 0);
730 WMSetSliderMaxValue(panel->rgbBlueS, 255);
731 WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
732 WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
734 to.red = 0;
735 to.green = 0;
736 to.blue = 255;
738 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
739 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
740 RReleaseImage(image);
742 if (pixmap)
743 W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12,
744 2, 0, 100, WALeft, scrPtr->white, False, _("Blue"),
745 strlen(_("Blue")));
746 else
747 wwarning(_("Color Panel: Could not allocate memory"));
749 WMSetSliderImage(panel->rgbBlueS, pixmap);
750 WMReleasePixmap(pixmap);
752 panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
753 WMResizeWidget(panel->rgbBlueT, 40, 18);
754 WMMoveWidget(panel->rgbBlueT, 146, 57);
755 WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
756 WMAddNotificationObserver(rgbTextFieldCallback, panel,
757 WMTextDidEndEditingNotification, panel->rgbBlueT);
758 /* End of RGB Panel */
760 /* Widgets for CMYK Panel */
761 panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
762 WMSetFrameRelief(panel->cmykFrm, WRFlat);
763 WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
764 WMMoveWidget(panel->cmykFrm, 0, 34);
766 panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
767 WMResizeWidget(panel->cmykMinL, 20, 10);
768 WMMoveWidget(panel->cmykMinL, 2, 2);
769 WMSetLabelText(panel->cmykMinL, "0");
770 WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
771 WMSetLabelTextColor(panel->cmykMinL, textcolor);
772 WMSetLabelFont(panel->cmykMinL, panel->font8);
774 panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
775 WMResizeWidget(panel->cmykMaxL, 40, 10);
776 WMMoveWidget(panel->cmykMaxL, 104, 2);
777 WMSetLabelText(panel->cmykMaxL, "100");
778 WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
779 WMSetLabelTextColor(panel->cmykMaxL, textcolor);
780 WMSetLabelFont(panel->cmykMaxL, panel->font8);
782 panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
783 WMResizeWidget(panel->cmykCyanS, 141, 16);
784 WMMoveWidget(panel->cmykCyanS, 2, 14);
785 WMSetSliderMinValue(panel->cmykCyanS, 0);
786 WMSetSliderMaxValue(panel->cmykCyanS, 100);
787 WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
788 WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
790 from.red = 255;
791 from.green = 255;
792 from.blue = 255;
794 to.red = 0;
795 to.green = 255;
796 to.blue = 255;
798 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
799 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
800 RReleaseImage(image);
802 if (pixmap)
803 W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12,
804 2, 0, 100, WALeft, scrPtr->black, False, _("Cyan"),
805 strlen(_("Cyan")));
806 else
807 wwarning(_("Color Panel: Could not allocate memory"));
809 WMSetSliderImage(panel->cmykCyanS, pixmap);
810 WMReleasePixmap(pixmap);
812 panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
813 WMResizeWidget(panel->cmykCyanT, 40, 18);
814 WMMoveWidget(panel->cmykCyanT, 146, 13);
815 WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
816 WMAddNotificationObserver(cmykTextFieldCallback, panel,
817 WMTextDidEndEditingNotification, panel->cmykCyanT);
820 panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
821 WMResizeWidget(panel->cmykMagentaS, 141, 16);
822 WMMoveWidget(panel->cmykMagentaS, 2, 36);
823 WMSetSliderMinValue(panel->cmykMagentaS, 0);
824 WMSetSliderMaxValue(panel->cmykMagentaS, 100);
825 WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
826 WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
828 to.red = 255;
829 to.green = 0;
830 to.blue = 255;
832 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
833 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
834 RReleaseImage(image);
836 if (pixmap)
837 W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12,
838 2, 0, 100, WALeft, scrPtr->black, False, _("Magenta"),
839 strlen(_("Magenta")));
840 else
841 wwarning(_("Color Panel: Could not allocate memory"));
843 WMSetSliderImage(panel->cmykMagentaS, pixmap);
844 WMReleasePixmap(pixmap);
846 panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
847 WMResizeWidget(panel->cmykMagentaT, 40, 18);
848 WMMoveWidget(panel->cmykMagentaT, 146, 35);
849 WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
850 WMAddNotificationObserver(cmykTextFieldCallback, panel,
851 WMTextDidEndEditingNotification, panel->cmykMagentaT);
854 panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
855 WMResizeWidget(panel->cmykYellowS, 141, 16);
856 WMMoveWidget(panel->cmykYellowS, 2, 58);
857 WMSetSliderMinValue(panel->cmykYellowS, 0);
858 WMSetSliderMaxValue(panel->cmykYellowS, 100);
859 WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
860 WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
862 to.red = 255;
863 to.green = 255;
864 to.blue = 0;
866 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
867 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
868 RReleaseImage(image);
870 if (pixmap)
871 W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12,
872 2, 0, 100, WALeft, scrPtr->black, False, _("Yellow"),
873 strlen(_("Yellow")));
874 else
875 wwarning(_("Color Panel: Could not allocate memory"));
877 WMSetSliderImage(panel->cmykYellowS, pixmap);
878 WMReleasePixmap(pixmap);
880 panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
881 WMResizeWidget(panel->cmykYellowT, 40, 18);
882 WMMoveWidget(panel->cmykYellowT, 146, 57);
883 WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
884 WMAddNotificationObserver(cmykTextFieldCallback, panel,
885 WMTextDidEndEditingNotification, panel->cmykYellowT);
888 panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
889 WMResizeWidget(panel->cmykBlackS, 141, 16);
890 WMMoveWidget(panel->cmykBlackS, 2, 80);
891 WMSetSliderMinValue(panel->cmykBlackS, 0);
892 WMSetSliderMaxValue(panel->cmykBlackS, 100);
893 WMSetSliderValue(panel->cmykBlackS, 0);
894 WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
895 WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
897 to.red = 0;
898 to.green = 0;
899 to.blue = 0;
901 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
902 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
903 RReleaseImage(image);
905 if (pixmap)
906 W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12,
907 2, 0, 100, WALeft, scrPtr->black, False, _("Black"),
908 strlen(_("Black")));
909 else
910 wwarning(_("Color Panel: Could not allocate memory"));
912 WMSetSliderImage(panel->cmykBlackS, pixmap);
913 WMReleasePixmap(pixmap);
915 panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
916 WMResizeWidget(panel->cmykBlackT, 40, 18);
917 WMMoveWidget(panel->cmykBlackT, 146, 79);
918 WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
919 WMAddNotificationObserver(cmykTextFieldCallback, panel,
920 WMTextDidEndEditingNotification, panel->cmykBlackT);
921 /* End of CMYK Panel */
923 /* Widgets for HSB Panel */
924 panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
925 WMSetFrameRelief(panel->hsbFrm, WRFlat);
926 WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
927 WMMoveWidget(panel->hsbFrm, 0, 34);
929 panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
930 WMResizeWidget(panel->hsbHueS, 141, 16);
931 WMMoveWidget(panel->hsbHueS, 2, 14);
932 WMSetSliderMinValue(panel->hsbHueS, 0);
933 WMSetSliderMaxValue(panel->hsbHueS, 359);
934 WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
935 WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
937 panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
938 WMResizeWidget(panel->hsbHueT, 40, 18);
939 WMMoveWidget(panel->hsbHueT, 146, 13);
940 WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
941 WMAddNotificationObserver(hsbTextFieldCallback, panel,
942 WMTextDidEndEditingNotification, panel->hsbHueT);
945 panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
946 WMResizeWidget(panel->hsbSaturationS, 141, 16);
947 WMMoveWidget(panel->hsbSaturationS, 2, 36);
948 WMSetSliderMinValue(panel->hsbSaturationS, 0);
949 WMSetSliderMaxValue(panel->hsbSaturationS, 100);
950 WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
951 WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
953 panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
954 WMResizeWidget(panel->hsbSaturationT, 40, 18);
955 WMMoveWidget(panel->hsbSaturationT, 146, 35);
956 WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
957 WMAddNotificationObserver(hsbTextFieldCallback, panel,
958 WMTextDidEndEditingNotification, panel->hsbSaturationT);
961 panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
962 WMResizeWidget(panel->hsbBrightnessS, 141, 16);
963 WMMoveWidget(panel->hsbBrightnessS, 2, 58);
964 WMSetSliderMinValue(panel->hsbBrightnessS, 0);
965 WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
966 WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
967 WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
969 panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
970 WMResizeWidget(panel->hsbBrightnessT, 40, 18);
971 WMMoveWidget(panel->hsbBrightnessT, 146, 57);
972 WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
973 WMAddNotificationObserver(hsbTextFieldCallback, panel,
974 WMTextDidEndEditingNotification, panel->hsbBrightnessT);
975 /* End of HSB Panel */
978 WMReleaseColor(textcolor);
980 /* Widgets for the CustomPalette Panel */
981 panel->customPaletteFrm = WMCreateFrame(panel->win);
982 WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
983 WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
984 WMMoveWidget(panel->customPaletteFrm, 5, 80);
986 panel->customPaletteHistoryBtn = WMCreatePopUpButton(
987 panel->customPaletteFrm);
988 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, _("Spectrum"));
989 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
990 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn)-1);
991 WMSetPopUpButtonAction(panel->customPaletteHistoryBtn,
992 customPaletteHistoryCallback, panel);
993 WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
994 WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
996 panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
997 WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
998 WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
999 WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
1001 panel->customPaletteContentView = W_CreateView(
1002 W_VIEW(panel->customPaletteContentFrm));
1003 /* XXX Test if we can create a view */
1004 W_ResizeView(panel->customPaletteContentView, customPaletteWidth,
1005 customPaletteHeight);
1006 W_MoveView(panel->customPaletteContentView, 2, 2);
1008 /* Create event handler to handle expose/click events in CustomPalette */
1009 WMCreateEventHandler(panel->customPaletteContentView,
1010 ButtonPressMask|ButtonReleaseMask|EnterWindowMask| LeaveWindowMask |
1011 ButtonMotionMask, customPaletteHandleActionEvents, panel);
1013 WMCreateEventHandler(panel->customPaletteContentView, ExposureMask,
1014 customPaletteHandleEvents, panel);
1016 panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
1017 WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
1018 WMSetPopUpButtonText(panel->customPaletteMenuBtn, _("Palette"));
1019 WMSetPopUpButtonAction(panel->customPaletteMenuBtn,
1020 customPaletteMenuCallback, panel);
1021 WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
1022 WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
1024 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from File..."));
1025 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Rename..."));
1026 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Remove"));
1027 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Copy"));
1028 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from Clipboard"));
1030 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, 0);
1031 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, 0);
1032 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuCopy, 0);
1033 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn,
1034 CPmenuNewFromClipboard, 0);
1036 customRenderSpectrum(panel);
1037 panel->currentPalette = 0;
1038 panel->palx = customPaletteWidth/2;
1039 panel->paly = customPaletteHeight/2;
1042 /* Widgets for the ColorList Panel */
1043 panel->colorListFrm = WMCreateFrame(panel->win);
1044 WMSetFrameRelief(panel->colorListFrm, WRFlat);
1045 WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
1046 WMMoveWidget(panel->colorListFrm, 5, 80);
1048 panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
1049 WMAddPopUpButtonItem(panel->colorListHistoryBtn, _("X11-Colors"));
1050 WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn,
1051 WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn)-1);
1052 /* WMSetPopUpButtonAction(panel->colorListHistoryBtn,
1053 * colorListHistoryCallback, panel); */
1054 WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
1055 WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
1057 panel->colorListContentLst = WMCreateList(panel->colorListFrm);
1058 WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
1059 WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
1060 WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
1061 WMMoveWidget(panel->colorListContentLst, 0, 23);
1062 WMHangData(panel->colorListContentLst, panel);
1064 panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1065 WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
1066 WMSetPopUpButtonText(panel->colorListColorMenuBtn, _("Color"));
1067 WMSetPopUpButtonAction(panel->colorListColorMenuBtn,
1068 colorListColorMenuCallback, panel);
1069 WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16)/2, 20);
1070 WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
1072 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Add..."));
1073 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Rename..."));
1074 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Remove"));
1076 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuAdd, 0);
1077 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRename, 0);
1078 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRemove, 0);
1080 panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1081 WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
1082 WMSetPopUpButtonText(panel->colorListListMenuBtn, _("List"));
1083 WMSetPopUpButtonAction(panel->colorListListMenuBtn,
1084 colorListListMenuCallback, panel);
1085 WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16)/2, 20);
1086 WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16)/2 + 8,
1087 PHEIGHT - 130);
1089 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("New..."));
1090 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Rename..."));
1091 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Remove"));
1093 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuAdd, 0);
1094 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
1095 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
1097 WMRealizeWidget(panel->win);
1098 WMMapSubwidgets(panel->win);
1100 WMMapSubwidgets(panel->wheelFrm);
1101 WMMapSubwidgets(panel->slidersFrm);
1102 WMMapSubwidgets(panel->grayFrm);
1103 WMMapSubwidgets(panel->rgbFrm);
1104 WMMapSubwidgets(panel->cmykFrm);
1105 WMMapSubwidgets(panel->hsbFrm);
1106 WMMapSubwidgets(panel->customPaletteFrm);
1107 WMMapSubwidgets(panel->customPaletteContentFrm);
1108 WMMapSubwidgets(panel->colorListFrm);
1110 /* Pixmap to indicate selection positions
1111 * wheelframe MUST be mapped.
1113 panel->selectionImg = XCreatePixmap(scrPtr->display,
1114 WMWidgetXID(panel->win), 4, 4, scrPtr->depth);
1115 XFillRectangle(scrPtr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1116 XFillRectangle(scrPtr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1118 readConfiguration(panel);
1119 readXColors(panel);
1121 return panel;
1125 WMColorPanel*
1126 WMGetColorPanel(WMScreen *scrPtr)
1128 WMColorPanel *panel;
1130 if (scrPtr->sharedColorPanel)
1131 return scrPtr->sharedColorPanel;
1133 panel = makeColorPanel(scrPtr, "colorPanel");
1135 scrPtr->sharedColorPanel = panel;
1137 return panel;
1141 void
1142 WMFreeColorPanel(WMColorPanel *panel)
1144 W_Screen *scr = WMWidgetScreen(panel->win);
1146 if (panel == scr->sharedColorPanel) {
1147 scr->sharedColorPanel = NULL;
1150 if (!panel)
1151 return;
1153 WMRemoveNotificationObserver(panel);
1154 WMUnmapWidget(panel->win);
1156 /* fonts */
1157 WMReleaseFont(panel->font8);
1158 WMReleaseFont(panel->font12);
1160 /* pixmaps */
1161 wheelDestroyMatrix(panel->wheelMtrx);
1162 if (panel->wheelImg)
1163 XFreePixmap(scr->display, panel->wheelImg);
1164 if (panel->selectionImg)
1165 XFreePixmap(scr->display, panel->selectionImg);
1166 if (panel->selectionBackImg)
1167 XFreePixmap(scr->display, panel->selectionBackImg);
1168 RReleaseImage(panel->customPaletteImg);
1170 /* structs */
1171 if (panel->lastBrowseDir)
1172 wfree(panel->lastBrowseDir);
1173 if (panel->configurationPath)
1174 wfree(panel->configurationPath);
1176 WMDestroyWidget(panel->win);
1178 wfree(panel);
1182 void
1183 WMCloseColorPanel(WMColorPanel *panel)
1185 WMFreeColorPanel(panel);
1189 void
1190 WMShowColorPanel(WMColorPanel *panel)
1192 WMScreen *scr = WMWidgetScreen(panel->win);
1193 WMColor *white = WMWhiteColor(scr);
1195 if (panel->color.set == cpNone)
1196 WMSetColorPanelColor(panel, white);
1197 WMReleaseColor(white);
1199 if (panel->mode != WMWheelModeColorPanel)
1200 WMPerformButtonClick(panel->wheelBtn);
1202 WMMapWidget(panel->win);
1206 static void
1207 closeWindowCallback(WMWidget *w, void *data)
1209 W_ColorPanel *panel = (W_ColorPanel*)data;
1211 WMCloseColorPanel(panel);
1215 static void
1216 readConfiguration(W_ColorPanel *panel)
1218 /* XXX Doesn't take care of "invalid" files */
1220 DIR *dPtr;
1221 struct dirent *dp;
1222 struct stat stat_buf;
1223 int item;
1225 if (stat(panel->configurationPath, &stat_buf)!=0) {
1226 if (mkdir(panel->configurationPath,
1227 S_IRWXU|S_IRGRP|S_IROTH|S_IXGRP|S_IXOTH)!=0) {
1228 wsyserror(_("Color Panel: Could not create directory %s needed"
1229 " to store configurations"), panel->configurationPath);
1230 WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
1231 WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
1232 WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
1233 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1234 _("File Error"),
1235 _("Could not create ColorPanel configuration directory"),
1236 _("OK"), NULL, NULL);
1238 return;
1241 if (!(dPtr = opendir(panel->configurationPath))) {
1242 wwarning(_("Color Panel: Could not find file"), "%s", panel->configurationPath);
1243 return;
1246 while ((dp = readdir(dPtr)) != NULL) {
1247 unsigned int perm_mask;
1248 char *path = wstrconcat(panel->configurationPath,
1249 dp->d_name);
1251 if (dp->d_name[0] != '.') {
1252 item = WMGetPopUpButtonNumberOfItems(
1253 panel->customPaletteHistoryBtn);
1254 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
1256 perm_mask = (access(path, R_OK) == 0);
1257 WMSetPopUpButtonItemEnabled(panel->customPaletteHistoryBtn,
1258 item, perm_mask);
1260 wfree(path);
1262 closedir(dPtr);
1266 static void
1267 readXColors(W_ColorPanel *panel)
1269 WMListItem *item;
1270 RGBColor *entry;
1272 for (entry=rgbColors; entry->name!=NULL; entry++) {
1273 item = WMAddListItem(panel->colorListContentLst, entry->name);
1274 item->clientData = (void *)&(entry->color);
1279 void
1280 WMSetColorPanelPickerMode(WMColorPanel *panel, WMColorPanelMode mode)
1282 W_Screen *scr = WMWidgetScreen(panel->win);
1284 if (mode != WMWheelModeColorPanel) {
1285 WMUnmapWidget(panel->wheelFrm);
1286 if (panel->selectionBackImg) {
1287 XFreePixmap(WMWidgetScreen(panel->win)->display,
1288 panel->selectionBackImg);
1289 panel->selectionBackImg = None;
1292 if (mode != WMGrayModeColorPanel)
1293 WMUnmapWidget(panel->grayFrm);
1294 if (mode != WMRGBModeColorPanel)
1295 WMUnmapWidget(panel->rgbFrm);
1296 if (mode != WMCMYKModeColorPanel)
1297 WMUnmapWidget(panel->cmykFrm);
1298 if (mode != WMHSBModeColorPanel)
1299 WMUnmapWidget(panel->hsbFrm);
1300 if (mode != WMCustomPaletteModeColorPanel) {
1301 WMUnmapWidget(panel->customPaletteFrm);
1302 if (panel->selectionBackImg) {
1303 XFreePixmap(WMWidgetScreen(panel->win)->display,
1304 panel->selectionBackImg);
1305 panel->selectionBackImg = None;
1308 if (mode != WMColorListModeColorPanel)
1309 WMUnmapWidget(panel->colorListFrm);
1310 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
1311 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1312 WMUnmapWidget(panel->slidersFrm);
1313 else
1314 panel->slidersmode = mode;
1316 if (mode == WMWheelModeColorPanel) {
1317 WMMapWidget(panel->wheelFrm);
1318 WMSetButtonSelected(panel->wheelBtn, True);
1319 if (panel->lastChanged != WMWheelModeColorPanel)
1320 wheelInit(panel);
1321 wheelRender(panel);
1322 wheelPaint(panel);
1323 } else if (mode == WMGrayModeColorPanel) {
1324 WMMapWidget(panel->slidersFrm);
1325 WMSetButtonSelected(panel->slidersBtn, True);
1326 WMMapWidget(panel->grayFrm);
1327 WMSetButtonSelected(panel->grayBtn, True);
1328 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1329 if (panel->lastChanged != WMGrayModeColorPanel)
1330 grayInit(panel);
1331 } else if (mode == WMRGBModeColorPanel) {
1332 WMMapWidget(panel->slidersFrm);
1333 WMSetButtonSelected(panel->slidersBtn, True);
1334 WMMapWidget(panel->rgbFrm);
1335 WMSetButtonSelected(panel->rgbBtn, True);
1336 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1337 if (panel->lastChanged != WMRGBModeColorPanel)
1338 rgbInit(panel);
1339 } else if (mode == WMCMYKModeColorPanel) {
1340 WMMapWidget(panel->slidersFrm);
1341 WMSetButtonSelected(panel->slidersBtn, True);
1342 WMMapWidget(panel->cmykFrm);
1343 WMSetButtonSelected(panel->cmykBtn, True);
1344 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1345 if (panel->lastChanged != WMCMYKModeColorPanel)
1346 cmykInit(panel);
1347 } else if (mode == WMHSBModeColorPanel) {
1348 WMMapWidget(panel->slidersFrm);
1349 WMSetButtonSelected(panel->slidersBtn, True);
1350 WMMapWidget(panel->hsbFrm);
1351 WMSetButtonSelected(panel->hsbBtn, True);
1352 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1353 if (panel->lastChanged != WMHSBModeColorPanel)
1354 hsbInit(panel);
1355 } else if (mode == WMCustomPaletteModeColorPanel) {
1356 WMMapWidget(panel->customPaletteFrm);
1357 WMSetButtonSelected(panel->customPaletteBtn, True);
1358 customSetPalette(panel);
1359 } else if (mode == WMColorListModeColorPanel) {
1360 WMMapWidget(panel->colorListFrm);
1361 WMSetButtonSelected(panel->colorListBtn, True);
1364 panel->mode = mode;
1368 WMColor*
1369 WMGetColorPanelColor(WMColorPanel *panel)
1371 return WMGetColorWellColor(panel->colorWell);
1375 void
1376 WMSetColorPanelColor(WMColorPanel *panel, WMColor *color)
1378 WMSetColorWellColor(panel->colorWell, color);
1380 panel->color.rgb.red = color->color.red >> 8;
1381 panel->color.rgb.green = color->color.green >> 8;
1382 panel->color.rgb.blue = color->color.blue >> 8;
1383 panel->color.set = cpRGB;
1385 if (panel->mode == panel->lastChanged)
1386 panel->lastChanged = 0;
1388 WMSetColorPanelPickerMode(panel, panel->mode);
1392 static void
1393 updateSwatch(WMColorPanel *panel, CPColor color)
1395 WMScreen *scr = WMWidgetScreen(panel->win);
1396 WMColor *wellcolor;
1398 if (color.set != cpRGB)
1399 convertCPColor(&color);
1401 panel->color = color;
1403 wellcolor = WMCreateRGBColor(scr, color.rgb.red << 8,
1404 color.rgb.green << 8,
1405 color.rgb.blue << 8, True);
1407 WMSetColorWellColor(panel->colorWell, wellcolor);
1408 WMReleaseColor(wellcolor);
1410 if (!panel->flags.dragging || panel->flags.continuous) {
1411 if (panel->action)
1412 (*panel->action)(panel, panel->clientData);
1414 WMPostNotificationName(WMColorPanelColorChangedNotification, panel,
1415 NULL);
1419 static void
1420 modeButtonCallback(WMWidget *w, void *data)
1422 W_ColorPanel *panel = (W_ColorPanel*)(data);
1424 if (w == panel->wheelBtn)
1425 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1426 else if (w == panel->slidersBtn)
1427 WMSetColorPanelPickerMode(panel, panel->slidersmode);
1428 else if (w == panel->customPaletteBtn)
1429 WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
1430 else if (w == panel->colorListBtn)
1431 WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
1432 else if (w == panel->grayBtn)
1433 WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
1434 else if (w == panel->rgbBtn)
1435 WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
1436 else if (w == panel->cmykBtn)
1437 WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
1438 else if (w == panel->hsbBtn)
1439 WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
1443 /****************** Magnifying Cursor Functions *******************/
1445 static XImage*
1446 magnifyGetImage(WMScreen *scr, XImage *image, int x, int y, int w, int h)
1448 int x0 = 0, y0 = 0, w0 = w, h0 = h;
1449 const int displayWidth = DisplayWidth(scr->display, scr->screen),
1450 displayHeight = DisplayHeight(scr->display, scr->screen);
1452 if (!(image && image->data)) {
1453 /* The image in panel->magnifyGlass->image does not exist yet.
1454 * Grab one from the screen (not beyond) and use it from now on.
1456 if (!(image = XGetImage(scr->display, scr->rootWin,
1457 x - Cursor_x_hot,
1458 y - Cursor_y_hot,
1459 w, h, AllPlanes, ZPixmap)))
1460 wwarning(_("Color Panel: X failed request"));
1462 return image;
1465 /* Coordinate correction for back pixmap
1466 * if magnifying glass is at screen-borders
1469 /* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
1470 * Hatched area is beyond screen border.
1472 * |<-Cursor_x_hot->|
1473 * ________________|_____
1474 * |/ / / / / / /| | |
1475 * | / / / / / / |(x,y) |
1476 * |/_/_/_/_/_/_/|________|
1477 * |<----x0----->|<--w0-->|
1481 /* Figure 2: Shifting of rectangle-to-grab at bottom/right
1482 * screen borders
1483 * Hatched area is beyond screen border
1485 * |<-Cursor_x_hot->|
1486 * ________________|_______________
1487 * | | | / / / / / /|
1488 * | (x,y)|/ / / / / / |
1489 * |___________________|_/_/_/_/_/_/|
1490 * |<-------w0-------->| |
1491 * |<---------------w--|----------->|
1492 * | |
1493 * x0 Displaywidth-1
1496 if (x < Cursor_x_hot) { /* see fig. 1 */
1497 x0 = Cursor_x_hot - x;
1498 w0 = w - x0;
1501 if (displayWidth -1 < x - Cursor_x_hot + w) { /* see fig. 2 */
1502 w0 = (displayWidth) - (x - Cursor_x_hot);
1505 if (y < Cursor_y_hot) { /* see fig. 1 */
1506 y0 = Cursor_y_hot - y;
1507 h0 = h - y0;
1510 if (displayHeight -1 < y - Cursor_y_hot + h) { /* see fig. 2 */
1511 h0 = (displayHeight) - (y - Cursor_y_hot);
1513 /* end of coordinate correction */
1516 /* Grab an image from the screen, clipped if necessary,
1517 * and put it in the existing panel->magnifyGlass->image
1518 * with the corresponding clipping offset.
1520 if (!XGetSubImage(scr->display, scr->rootWin,
1521 x - Cursor_x_hot + x0,
1522 y - Cursor_y_hot + y0,
1523 w0, h0, AllPlanes, ZPixmap,
1524 image, x0, y0))
1525 wwarning(_("Color Panel: X failed request"));
1527 return NULL;
1531 static void
1532 magnifyGetImageStored(WMColorPanel *panel, int x1, int y1, int x2, int y2)
1534 /* (x1, y1) = topleft corner of existing rectangle
1535 * (x2, y2) = topleft corner of new position
1538 W_Screen *scr = WMWidgetScreen(panel->win);
1539 int xa = 0, ya = 0, xb = 0, yb = 0;
1540 int width, height;
1541 const int dx = abs(x2 - x1),
1542 dy = abs(y2 - y1);
1543 XImage *image;
1544 const int x_min = Cursor_x_hot,
1545 y_min = Cursor_y_hot,
1546 x_max = DisplayWidth(scr->display, scr->screen) -1 -
1547 (Cursor_mask_width - Cursor_x_hot),
1548 y_max = DisplayHeight(scr->display, scr->screen) -1 -
1549 (Cursor_mask_height - Cursor_y_hot);
1551 if ((dx == 0) && (dy == 0) && panel->magnifyGlass->image)
1552 return; /* No movement */
1554 if (x1 < x2)
1555 xa = dx;
1556 else
1557 xb = dx;
1559 if (y1 < y2)
1560 ya = dy;
1561 else
1562 yb = dy;
1564 width = Cursor_mask_width - dx;
1565 height = Cursor_mask_height - dy;
1567 /* If the traversed distance is larger than the size of the magnifying
1568 * glass contents, there is no need to do dirty rectangles. A whole new
1569 * rectangle can be grabbed (unless that rectangle falls partially
1570 * off screen).
1571 * Destroying the image and setting it to NULL will achieve that later on.
1573 * Of course, grabbing an XImage beyond the borders of the screen will
1574 * cause trouble, this is considdered a special case. Part of the screen
1575 * is grabbed, but there is no need for dirty rectangles.
1577 if ((width <= 0) || (height <= 0)) {
1578 if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
1579 if (panel->magnifyGlass->image)
1580 XDestroyImage(panel->magnifyGlass->image);
1581 panel->magnifyGlass->image = NULL;
1583 } else {
1584 if (panel->magnifyGlass->image) {
1585 /* Get dirty rectangle from panel->magnifyGlass->image */
1586 panel->magnifyGlass->dirtyRect =
1587 XSubImage(panel->magnifyGlass->image, xa, ya, width, height);
1588 if (!panel->magnifyGlass->dirtyRect) {
1589 wwarning(_("Color Panel: X failed request"));
1590 return; /* X returned a NULL from XSubImage */
1595 /* Get image from screen */
1596 image = magnifyGetImage(scr, panel->magnifyGlass->image, x2, y2,
1597 Cursor_mask_width, Cursor_mask_height);
1598 if (image) { /* Only reassign if a *new* image was grabbed */
1599 panel->magnifyGlass->image = image;
1600 return;
1603 /* Copy previously stored rectangle on covered part of image */
1604 if (panel->magnifyGlass->image && panel->magnifyGlass->dirtyRect) {
1605 int old_height;
1607 /* "width" and "height" are used as coordinates here,
1608 * and run from [0...width-1] and [0...height-1] respectively.
1610 width--;
1611 height--;
1612 old_height = height;
1614 for (; width >= 0; width--)
1615 for (height = old_height; height >= 0; height--)
1616 XPutPixel(panel->magnifyGlass->image, xb + width, yb + height,
1617 XGetPixel(panel->magnifyGlass->dirtyRect, width, height));
1618 XDestroyImage(panel->magnifyGlass->dirtyRect);
1619 panel->magnifyGlass->dirtyRect = NULL;
1622 return;
1626 static Pixmap
1627 magnifyCreatePixmap(WMColorPanel *panel)
1629 W_Screen *scr = WMWidgetScreen(panel->win);
1630 int u, v;
1631 #ifndef SHAPE
1632 Pixmap pixmap;
1633 #endif
1634 unsigned long color;
1636 if (!panel->magnifyGlass->image)
1637 return None;
1639 if (!panel->magnifyGlass->magPix)
1640 return None;
1643 * Copy an area of only 5x5 pixels from the center of the image.
1645 for (u = 0; u < 5; u++) {
1646 for (v = 0; v < 5; v++) {
1647 color = XGetPixel(panel->magnifyGlass->image, u + 9, v + 9);
1649 XSetForeground(scr->display, scr->copyGC, color);
1651 if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
1652 panel->magnifyGlass->color = ulongToRColor(scr, color);
1654 /* The center square must eventually be centered around the
1655 * hotspot. The image needs shifting to achieve this. The amount of
1656 * shifting is (Cursor_mask_width/2 - 2 * square_size) = 11-10 = 1
1657 * _ _ _ _ _
1658 * |_|_|_|_|_|
1659 * ^------- center of center square == Cursor_x_hot
1661 XFillRectangle(scr->display, panel->magnifyGlass->magPix,
1662 scr->copyGC,
1663 u * 5 + (u == 0 ? 0 : -1), v * 5 + (v == 0 ? 0 : -1),
1664 (u == 0 ? 4 : 5), (v == 0 ? 4 : 5));
1668 #ifdef SHAPE
1669 return panel->magnifyGlass->magPix;
1670 #else
1671 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width,
1672 Cursor_mask_height, scr->depth);
1673 if (!pixmap)
1674 return None;
1676 XPutImage(scr->display, pixmap, scr->copyGC, panel->magnifyGlass->image,
1677 0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
1679 /* Copy the magnified pixmap, with the clip mask, to background pixmap */
1680 XCopyArea(scr->display, panel->magnifyGlass->magPix, pixmap,
1681 scr->clipGC, 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
1682 /* (2,2) puts center pixel on center of glass */
1684 return pixmap;
1685 #endif
1690 static WMView*
1691 magnifyCreateView(W_ColorPanel *panel)
1693 W_Screen *scr = WMWidgetScreen(panel->win);
1694 WMView *magView;
1696 magView = W_CreateTopView(scr);
1697 if (!magView)
1698 return NULL;
1700 magView->self = panel->win;
1701 magView->flags.topLevel = 1;
1702 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1703 magView->attribs.override_redirect = True;
1704 magView->attribs.save_under = True;
1706 W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
1708 W_RealizeView(magView);
1710 return magView;
1714 static Cursor
1715 magnifyGrabPointer(W_ColorPanel *panel)
1717 W_Screen *scr = WMWidgetScreen(panel->win);
1718 Pixmap magPixmap, magPixmap2;
1719 Cursor magCursor;
1720 XColor fgColor = {0, 0,0,0, DoRed|DoGreen|DoBlue};
1721 XColor bgColor = {0, 0xbf00, 0xa000, 0x5000, DoRed|DoGreen|DoBlue};
1723 /* Cursor creation stuff */
1724 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1725 (char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
1726 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1727 (char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
1729 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1730 &fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
1732 XFreePixmap(scr->display, magPixmap);
1733 XFreePixmap(scr->display, magPixmap2);
1735 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1737 /* Set up Pointer */
1738 XGrabPointer (scr->display, panel->magnifyGlass->view->window, True,
1739 PointerMotionMask | ButtonPressMask,
1740 GrabModeAsync, GrabModeAsync,
1741 scr->rootWin, magCursor, CurrentTime);
1743 return magCursor;
1747 static WMPoint
1748 magnifyInitialize(W_ColorPanel *panel)
1750 W_Screen *scr = WMWidgetScreen(panel->win);
1751 int x, y, u, v;
1752 unsigned int mask;
1753 Pixmap pixmap, clip_mask;
1754 WMPoint point;
1755 Window root_return, child_return;
1757 clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1758 (char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1759 1, 0, 1);
1760 panel->magnifyGlass->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
1761 5*5 -1, 5*5 -1, scr->depth);
1763 XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return,
1764 &x, &y, &u, &v, &mask);
1766 panel->magnifyGlass->image = NULL;
1768 /* Clipmask to make magnified view-contents circular */
1769 #ifdef SHAPE
1770 XShapeCombineMask(scr->display, WMViewXID(panel->magnifyGlass->view),
1771 ShapeBounding, 0, 0, clip_mask, ShapeSet);
1772 #else
1773 /* Clip circle in glass cursor */
1774 XSetClipMask(scr->display, scr->clipGC, clip_mask);
1775 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1776 #endif
1778 XFreePixmap(scr->display, clip_mask);
1780 /* Draw initial magnifying glass contents */
1781 magnifyGetImageStored(panel, x, y, x, y);
1783 pixmap = magnifyCreatePixmap(panel);
1784 XSetWindowBackgroundPixmap(scr->display,
1785 WMViewXID(panel->magnifyGlass->view),
1786 pixmap);
1787 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1788 XFlush(scr->display);
1790 #ifndef SHAPE
1791 XFreePixmap(scr->display, pixmap);
1792 #endif
1794 point.x = x;
1795 point.y = y;
1797 return point;
1801 static void
1802 magnifyPutCursor(WMWidget *w, void *data)
1804 W_ColorPanel *panel = (W_ColorPanel*)(data);
1805 W_Screen *scr = WMWidgetScreen(panel->win);
1806 Cursor magCursor;
1807 Pixmap pixmap;
1808 XEvent event;
1809 WMPoint initialPosition;
1811 /* Destroy wheelBackImg, so it'll update properly */
1812 if (panel->selectionBackImg) {
1813 XFreePixmap(WMWidgetScreen(panel->win)->display,
1814 panel->selectionBackImg);
1815 panel->selectionBackImg = None;
1818 /* Create magnifying glass */
1819 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1820 panel->magnifyGlass->view = magnifyCreateView(panel);
1821 if (!panel->magnifyGlass->view)
1822 return;
1824 initialPosition = magnifyInitialize(panel);
1825 panel->magnifyGlass->x = initialPosition.x;
1826 panel->magnifyGlass->y = initialPosition.y;
1828 W_MoveView(panel->magnifyGlass->view,
1829 panel->magnifyGlass->x - Cursor_x_hot,
1830 panel->magnifyGlass->y - Cursor_y_hot);
1831 W_MapView(panel->magnifyGlass->view);
1833 magCursor = magnifyGrabPointer(panel);
1835 while (panel->magnifyGlass->image)
1837 WMNextEvent(scr->display, &event);
1839 /* Pack motion events */
1840 while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
1843 switch (event.type)
1845 case ButtonPress:
1846 XDestroyImage(panel->magnifyGlass->image);
1847 panel->magnifyGlass->image = NULL;
1849 if (event.xbutton.button == Button1) {
1850 panel->color.rgb = panel->magnifyGlass->color;
1851 panel->color.set = cpRGB;
1852 updateSwatch(panel, panel->color);
1854 switch (panel->mode) {
1855 case WMWheelModeColorPanel:
1856 wheelInit(panel);
1857 wheelRender(panel);
1858 wheelPaint(panel);
1859 break;
1860 case WMGrayModeColorPanel:
1861 grayInit(panel);
1862 break;
1863 case WMRGBModeColorPanel:
1864 rgbInit(panel);
1865 break;
1866 case WMCMYKModeColorPanel:
1867 cmykInit(panel);
1868 break;
1869 case WMHSBModeColorPanel:
1870 hsbInit(panel);
1871 break;
1872 default:
1873 break;
1875 panel->lastChanged = panel->mode;
1877 WMSetButtonSelected(panel->magnifyBtn, False);
1878 break;
1880 case MotionNotify:
1881 while (XPending(event.xmotion.display)) {
1882 XEvent ev;
1883 XPeekEvent(event.xmotion.display, &ev);
1884 if (ev.type == MotionNotify)
1885 XNextEvent(event.xmotion.display, &event);
1886 else
1887 break;
1890 /* Get a "dirty rectangle" */
1891 magnifyGetImageStored( panel,
1892 panel->magnifyGlass->x, panel->magnifyGlass->y,
1893 event.xmotion.x_root, event.xmotion.y_root);
1895 /* Update coordinates */
1896 panel->magnifyGlass->x = event.xmotion.x_root;
1897 panel->magnifyGlass->y = event.xmotion.y_root;
1899 /* Move view */
1900 W_MoveView(panel->magnifyGlass->view,
1901 panel->magnifyGlass->x - Cursor_x_hot,
1902 panel->magnifyGlass->y - Cursor_y_hot);
1904 /* Put new image (with magn.) in view */
1905 pixmap = magnifyCreatePixmap(panel);
1906 if (pixmap != None) {
1907 /* Change the window background */
1908 XSetWindowBackgroundPixmap(scr->display,
1909 WMViewXID(panel->magnifyGlass->view), pixmap);
1910 /* Force an Expose (handled by X) */
1911 XClearWindow(scr->display,
1912 WMViewXID(panel->magnifyGlass->view));
1913 /* Synchronize the event queue, so the Expose is handled NOW */
1914 XFlush(scr->display);
1915 #ifndef SHAPE
1916 XFreePixmap(scr->display, pixmap);
1917 #endif
1919 break;
1921 /* Try XQueryPointer for this !!! It returns windows that the pointer
1922 * is over. Note: We found this solving the invisible donkey cap bug
1924 #if 0 /* As it is impossible to make this work in all cases,
1925 * we consider it confusing. Therefore we disabled it.
1927 case FocusOut: /* fall through */
1928 case FocusIn:
1930 * Color Panel window (panel->win) lost or received focus.
1931 * We need to update the pixmap in the magnifying glass.
1933 * BUG Doesn't work with focus switches between two windows
1934 * if none of them is the color panel.
1936 XUngrabPointer(scr->display, CurrentTime);
1937 W_UnmapView(panel->magnifyGlass->view);
1939 magnifyInitialize(panel);
1941 W_MapView(panel->magnifyGlass->view);
1942 XGrabPointer (scr->display, panel->magnifyGlass->view->window,
1943 True, PointerMotionMask | ButtonPressMask,
1944 GrabModeAsync, GrabModeAsync,
1945 scr->rootWin, magCursor, CurrentTime);
1946 break;
1947 #endif
1948 default:
1949 WMHandleEvent(&event);
1950 break;
1951 } /* of switch */
1954 XUngrabPointer(scr->display, CurrentTime);
1955 XFreeCursor(scr->display, magCursor);
1957 XFreePixmap(scr->display, panel->magnifyGlass->magPix);
1958 panel->magnifyGlass->magPix = None;
1960 W_UnmapView(panel->magnifyGlass->view);
1961 W_DestroyView(panel->magnifyGlass->view);
1962 panel->magnifyGlass->view = NULL;
1964 wfree(panel->magnifyGlass);
1969 /****************** ColorWheel Functions ************************/
1971 static wheelMatrix*
1972 wheelCreateMatrix(unsigned int width, unsigned int height)
1974 wheelMatrix *matrix = NULL;
1975 int i;
1977 assert((width > 0) && (height > 0));
1979 matrix = wmalloc(sizeof(wheelMatrix));
1980 memset(matrix, 0, sizeof(wheelMatrix));
1981 matrix->width = width;
1982 matrix->height = height;
1984 for (i = 0; i < 3; i++) {
1985 matrix->data[i] = wmalloc(width*height*sizeof(unsigned char));
1988 return matrix;
1992 static void
1993 wheelDestroyMatrix(wheelMatrix *matrix)
1995 int i;
1997 if (!matrix)
1998 return;
2000 for (i = 0; i < 3; i++) {
2001 if (matrix->data[i])
2002 wfree(matrix->data[i]);
2004 wfree(matrix);
2008 static void
2009 wheelInitMatrix(W_ColorPanel *panel)
2011 int i;
2012 int x,y;
2013 unsigned char *rp, *gp, *bp;
2014 CPColor cpColor;
2015 long ofs[4];
2016 int xcor, ycor;
2017 unsigned short sat;
2018 int dhue[4];
2019 const int cw_halfsize = (colorWheelSize + 4)/2,
2020 cw_sqsize = (colorWheelSize +4) * (colorWheelSize +4),
2021 uchar_shift = getShift(sizeof(unsigned char));
2023 if (!panel->wheelMtrx)
2024 return;
2026 cpColor.hsv.value = 255;
2027 cpColor.set = cpHSV;
2029 ofs[0] = -1;
2030 ofs[1] = -(colorWheelSize + 4);
2032 /* offsets are counterclockwise (in triangles).
2034 * ofs[0] ---->
2035 * _______________________________________
2036 * [1] |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| o
2037 * s |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| f
2038 * f |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| s
2039 * o | | | | | | | | | | | | | | | | | | | | | [3]
2041 * <---- ofs[2]
2042 * ____
2043 * |\ /| <-- triangles
2044 * | \/ |
2045 * | /\ |
2046 * |/__\|
2049 for (y = 0; y < cw_halfsize; y++) {
2050 for (x = y; x < (colorWheelSize+4-y); x++) {
2051 /* (xcor, ycor) is (x,y) relative to center of matrix */
2052 xcor = 2 * x - 4 - colorWheelSize;
2053 ycor = 2 * y - 4 - colorWheelSize;
2055 /* RColor.saturation is unsigned char and will wrap after 255 */
2056 sat = rint(255.0 * sqrt(xcor*xcor + ycor*ycor) / colorWheelSize);
2058 cpColor.hsv.saturation = (unsigned char)sat;
2060 ofs[0]++; /* top quarter of matrix*/
2061 ofs[1] += colorWheelSize + 4; /* left quarter */
2062 ofs[2] = cw_sqsize - 1 - ofs[0]; /* bottom quarter */
2063 ofs[3] = cw_sqsize - 1 - ofs[1]; /* right quarter */
2065 if (sat < 256) {
2066 if (xcor != 0)
2067 dhue[0] = rint(atan((double)ycor / (double)xcor) *
2068 (180.0 / M_PI)) + (xcor < 0 ? 180.0 : 0.0);
2069 else
2070 dhue[0] = 270;
2072 dhue[0] = 360 - dhue[0]; /* Reverse direction of ColorWheel */
2073 dhue[1] = 270 - dhue[0] + (dhue[0] > 270 ? 360 : 0);
2074 dhue[2] = dhue[0] - 180 + (dhue[0] < 180 ? 360 : 0);
2075 dhue[3] = 90 - dhue[0] + (dhue[0] > 90 ? 360 : 0);
2077 for (i = 0; i < 4; i++) {
2078 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
2079 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
2080 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
2082 cpColor.hsv.hue = dhue[i];
2083 convertCPColor(&cpColor);
2085 *rp = (unsigned char)(cpColor.rgb.red);
2086 *gp = (unsigned char)(cpColor.rgb.green);
2087 *bp = (unsigned char)(cpColor.rgb.blue);
2090 else {
2091 for (i = 0; i < 4; i++) {
2092 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
2093 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
2094 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
2096 *rp = (unsigned char)0;
2097 *gp = (unsigned char)0;
2098 *bp = (unsigned char)0;
2103 ofs[0] += 2*y+1;
2104 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2*y);
2109 static void
2110 wheelCalculateValues(W_ColorPanel *panel, int maxvalue)
2112 unsigned int i;
2113 unsigned int v;
2115 for (i = 0; i < 256; i++) {
2116 /* We divide by 128 in advance, and check whether that number divides
2117 * by 2 properly. If not, we add one to round the number correctly
2119 v = (i*maxvalue) >> 7;
2120 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) +(v & 0x01));
2125 static void
2126 wheelRender(W_ColorPanel *panel)
2128 W_Screen *scr = WMWidgetScreen(panel->win);
2129 int x,y;
2130 RImage *image;
2131 unsigned char *ptr;
2132 RColor gray;
2133 unsigned long ofs = 0;
2134 /*unsigned char shift = getShift(sizeof(unsigned char));*/
2136 image = RCreateImage(colorWheelSize+4, colorWheelSize+4, True);
2137 if (!image) {
2138 wwarning(_("Color Panel: Could not allocate memory"));
2139 return;
2142 ptr = image->data;
2144 /* TODO Make this transparent istead of gray */
2145 gray.red = gray.blue = 0xae; gray.green = 0xaa;
2147 for (y = 0; y < colorWheelSize+4; y++) {
2148 for (x = 0; x < colorWheelSize+4; x++) {
2149 if (wheelInsideColorWheel(panel, ofs)) {
2150 *(ptr++) = (unsigned char)(panel->wheelMtrx->values[
2151 panel->wheelMtrx->data[0][ofs] ]);
2152 *(ptr++) = (unsigned char)(panel->wheelMtrx->values[
2153 panel->wheelMtrx->data[1][ofs] ]);
2154 *(ptr++) = (unsigned char)(panel->wheelMtrx->values[
2155 panel->wheelMtrx->data[2][ofs] ]);
2156 *(ptr++) = 0;
2158 else {
2159 *(ptr++) = (unsigned char)(gray.red);
2160 *(ptr++) = (unsigned char)(gray.green);
2161 *(ptr++) = (unsigned char)(gray.blue);
2162 *(ptr++) = 255;
2164 ofs++;
2168 if (panel->wheelImg)
2169 XFreePixmap(scr->display, panel->wheelImg);
2171 RConvertImage(scr->rcontext, image, &panel->wheelImg);
2172 RReleaseImage(image);
2174 /* Check if backimage exists. If it doesn't, allocate and fill it */
2175 if (!panel->selectionBackImg) {
2176 panel->selectionBackImg = XCreatePixmap(scr->display,
2177 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
2178 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2179 scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0);
2180 /* -2 is hot spot correction */
2185 static Bool
2186 wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs)
2188 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
2189 (panel->wheelMtrx->data[1][ofs] != 0) &&
2190 (panel->wheelMtrx->data[2][ofs] != 0));
2194 static void
2195 wheelPaint (W_ColorPanel *panel)
2197 W_Screen *scr = WMWidgetScreen(panel->win);
2199 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
2200 scr->copyGC, 0, 0, colorWheelSize+4, colorWheelSize+4, 0, 0);
2202 /* Draw selection image */
2203 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2204 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2208 static void
2209 wheelHandleEvents(XEvent *event, void *data)
2211 W_ColorPanel *panel = (W_ColorPanel*)data;
2213 switch (event->type) {
2214 case Expose:
2215 if (event->xexpose.count != 0) /* TODO Improve */
2216 break;
2217 wheelPaint(panel);
2218 break;
2223 static void
2224 wheelHandleActionEvents(XEvent *event, void *data)
2226 W_ColorPanel *panel = (W_ColorPanel*)data;
2228 switch (event->type) {
2229 case ButtonPress:
2230 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) ==
2231 COLORWHEEL_PART) {
2233 panel->lastChanged = WMWheelModeColorPanel;
2234 panel->flags.dragging = 1;
2236 wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
2238 break;
2240 case ButtonRelease:
2241 panel->flags.dragging = 0;
2242 if (!panel->flags.continuous) {
2243 if (panel->action)
2244 (*panel->action)(panel, panel->clientData);
2246 break;
2248 case MotionNotify:
2249 if (panel->flags.dragging) {
2250 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) ==
2251 COLORWHEEL_PART) {
2252 wheelPositionSelection(panel, event->xmotion.x,
2253 event->xmotion.y);
2255 else
2256 wheelPositionSelectionOutBounds(panel, event->xmotion.x,
2257 event->xmotion.y);
2259 break;
2264 static int
2265 getPickerPart(W_ColorPanel *panel, int x, int y)
2267 int lx, ly;
2268 unsigned long ofs;
2270 lx = x;
2271 ly = y;
2273 if (panel->mode == WMWheelModeColorPanel) {
2274 if ((lx >= 2) && (lx <= 2+colorWheelSize) && (ly >= 2) &&
2275 (ly <= 2+colorWheelSize)) {
2277 ofs = ly*panel->wheelMtrx->width+lx;
2279 if (wheelInsideColorWheel(panel, ofs))
2280 return COLORWHEEL_PART;
2284 if (panel->mode == WMCustomPaletteModeColorPanel) {
2285 if ((lx >= 2) && (lx < customPaletteWidth-2) && (ly >= 2) &&
2286 (ly < customPaletteHeight-2)) {
2287 return CUSTOMPALETTE_PART;
2291 return 0;
2295 static void
2296 wheelBrightnessSliderCallback(WMWidget *w, void *data)
2298 int value;
2300 W_ColorPanel *panel = (W_ColorPanel*)data;
2302 value = 255-WMGetSliderValue(panel->wheelBrightnessS);
2304 wheelCalculateValues(panel, value);
2306 if (panel->color.set == cpRGB) {
2307 convertCPColor(&panel->color);
2308 panel->color.set = cpHSV;
2311 panel->color.hsv.value = value;
2313 wheelRender(panel);
2314 wheelPaint(panel);
2315 wheelUpdateSelection(panel);
2319 static void
2320 wheelUpdateSelection(W_ColorPanel *panel)
2322 W_Screen *scr = WMWidgetScreen(panel->win);
2324 updateSwatch(panel, panel->color);
2325 panel->lastChanged = WMWheelModeColorPanel;
2327 /* Redraw color selector (and make a backup of the part it will cover) */
2328 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2329 scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0);
2330 /* "-2" is correction for hotspot location */
2331 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2332 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2333 /* see above */
2337 static void
2338 wheelUndrawSelection(W_ColorPanel *panel)
2340 W_Screen *scr = WMWidgetScreen(panel->win);
2342 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
2343 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2344 /* see above */
2347 static void
2348 wheelPositionSelection(W_ColorPanel *panel, int x, int y)
2350 unsigned long ofs = (y * panel->wheelMtrx->width)+ x;
2352 panel->color.rgb.red = panel->wheelMtrx->values[
2353 panel->wheelMtrx->data[0][ofs] ];
2355 panel->color.rgb.green = panel->wheelMtrx->values[
2356 panel->wheelMtrx->data[1][ofs] ];
2358 panel->color.rgb.blue = panel->wheelMtrx->values[
2359 panel->wheelMtrx->data[2][ofs] ];
2360 panel->color.set = cpRGB;
2362 wheelUndrawSelection(panel);
2364 panel->colx = x;
2365 panel->coly = y;
2367 wheelUpdateSelection(panel);
2368 wheelUpdateBrightnessGradientFromLocation(panel);
2371 static void
2372 wheelPositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
2374 int hue;
2375 int xcor, ycor;
2376 CPColor cpColor;
2378 xcor = x * 2 - colorWheelSize - 4;
2379 ycor = y * 2 - colorWheelSize - 4;
2381 panel->color.hsv.saturation = 255;
2382 panel->color.hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2384 if (xcor != 0)
2385 hue = rint(atan(- (double)ycor / (double)xcor) * (180.0/M_PI));
2386 else {
2387 if (ycor < 0)
2388 hue = 90;
2389 else
2390 hue = 270;
2393 if (xcor < 0)
2394 hue += 180;
2396 if ((xcor > 0) && (ycor > 0))
2397 hue += 360;
2399 panel->color.hsv.hue = hue;
2400 panel->color.set = cpHSV;
2401 convertCPColor(&panel->color);
2403 wheelUndrawSelection(panel);
2405 panel->colx = 2 + rint((colorWheelSize * (1.0 +
2406 cos( panel->color.hsv.hue * (M_PI/180.0) ))) / 2.0);
2407 /* "+2" because of "colorWheelSize + 4" */
2408 panel->coly = 2 + rint((colorWheelSize * (1.0 +
2409 sin(- panel->color.hsv.hue * (M_PI/180.0) ))) / 2.0);
2411 wheelUpdateSelection(panel);
2412 cpColor = panel->color;
2413 wheelUpdateBrightnessGradient(panel, cpColor);
2416 static void
2417 wheelUpdateBrightnessGradientFromLocation(W_ColorPanel *panel)
2419 CPColor from;
2420 unsigned long ofs;
2422 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2424 from.rgb.red = panel->wheelMtrx->data[0][ofs];
2425 from.rgb.green = panel->wheelMtrx->data[1][ofs];
2426 from.rgb.blue = panel->wheelMtrx->data[2][ofs];
2427 from.set = cpRGB;
2429 wheelUpdateBrightnessGradient(panel, from);
2432 static void
2433 wheelUpdateBrightnessGradient(W_ColorPanel *panel, CPColor topColor)
2435 RColor to;
2436 RImage *sliderImg;
2437 WMPixmap *sliderPxmp;
2439 to.red = to.green = to.blue = 0;
2441 if (topColor.set == cpHSV)
2442 convertCPColor(&topColor);
2444 sliderImg = RRenderGradient(16, 153, &(topColor.rgb), &to, RGRD_VERTICAL);
2445 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win),
2446 sliderImg, 0);
2447 RReleaseImage(sliderImg);
2448 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
2449 WMReleasePixmap(sliderPxmp);
2452 /****************** Grayscale Panel Functions ***************/
2454 static void
2455 grayBrightnessSliderCallback(WMWidget *w, void *data)
2457 CPColor cpColor;
2458 int value;
2459 char tmp[4];
2460 W_ColorPanel *panel = (W_ColorPanel*)data;
2462 value = WMGetSliderValue(panel->grayBrightnessS);
2464 sprintf(tmp, "%d", value);
2466 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2467 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint(2.55*value);
2468 cpColor.set = cpRGB;
2470 updateSwatch(panel, cpColor);
2471 panel->lastChanged = WMGrayModeColorPanel;
2474 static void
2475 grayPresetButtonCallback(WMWidget *w, void *data)
2477 CPColor cpColor;
2478 char tmp[4];
2479 int value;
2480 int i=0;
2481 W_ColorPanel *panel = (W_ColorPanel*)data;
2483 while (i < 7) {
2484 if (w == panel->grayPresetBtn[i])
2485 break;
2486 i++;
2489 value = rint((100.0*i)/6.0);
2490 sprintf(tmp, "%d", value);
2492 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2493 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue =
2494 rint((255.0*i)/6.0);
2495 cpColor.set = cpRGB;
2497 WMSetSliderValue(panel->grayBrightnessS, rint((100.0*i)/6.0));
2499 updateSwatch(panel, cpColor);
2500 panel->lastChanged = WMGrayModeColorPanel;
2503 static void
2504 grayBrightnessTextFieldCallback(void *observerData,
2505 WMNotification *notification)
2507 CPColor cpColor;
2508 char tmp[4];
2509 int value;
2510 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2512 value = atoi(WMGetTextFieldText(panel->grayBrightnessT));
2513 if (value > 100)
2514 value = 100;
2515 if (value < 0)
2516 value = 0;
2518 sprintf(tmp, "%d", value);
2519 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2520 WMSetSliderValue(panel->grayBrightnessS, value);
2522 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue =
2523 rint((255.0*value)/100.0);
2524 cpColor.set = cpRGB;
2526 updateSwatch(panel, cpColor);
2527 panel->lastChanged = WMGrayModeColorPanel;
2530 /******************* RGB Panel Functions *****************/
2532 static void
2533 rgbSliderCallback(WMWidget *w, void *data)
2535 CPColor cpColor;
2536 int value[3];
2537 char tmp[4];
2538 W_ColorPanel *panel = (W_ColorPanel*)data;
2540 value[0] = WMGetSliderValue(panel->rgbRedS);
2541 value[1] = WMGetSliderValue(panel->rgbGreenS);
2542 value[2] = WMGetSliderValue(panel->rgbBlueS);
2544 sprintf(tmp, "%d", value[0]);
2545 WMSetTextFieldText(panel->rgbRedT, tmp);
2546 sprintf(tmp, "%d", value[1]);
2547 WMSetTextFieldText(panel->rgbGreenT, tmp);
2548 sprintf(tmp, "%d", value[2]);
2549 WMSetTextFieldText(panel->rgbBlueT, tmp);
2551 cpColor.rgb.red = value[0];
2552 cpColor.rgb.green = value[1];
2553 cpColor.rgb.blue = value[2];
2554 cpColor.set = cpRGB;
2556 updateSwatch(panel, cpColor);
2557 panel->lastChanged = WMRGBModeColorPanel;
2560 static void
2561 rgbTextFieldCallback(void *observerData, WMNotification *notification)
2563 CPColor cpColor;
2564 int value[3];
2565 char tmp[4];
2566 int n;
2567 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2569 value[0] = atoi(WMGetTextFieldText(panel->rgbRedT));
2570 value[1] = atoi(WMGetTextFieldText(panel->rgbGreenT));
2571 value[2] = atoi(WMGetTextFieldText(panel->rgbBlueT));
2573 for (n=0; n < 3; n++) {
2574 if (value[n] > 255)
2575 value[n] = 255;
2576 if (value[n] < 0)
2577 value[n] = 0;
2580 sprintf(tmp, "%d", value[0]);
2581 WMSetTextFieldText(panel->rgbRedT, tmp);
2582 sprintf(tmp, "%d", value[1]);
2583 WMSetTextFieldText(panel->rgbGreenT, tmp);
2584 sprintf(tmp, "%d", value[2]);
2585 WMSetTextFieldText(panel->rgbBlueT, tmp);
2587 WMSetSliderValue(panel->rgbRedS, value[0]);
2588 WMSetSliderValue(panel->rgbGreenS, value[1]);
2589 WMSetSliderValue(panel->rgbBlueS, value[2]);
2591 cpColor.rgb.red = value[0];
2592 cpColor.rgb.green = value[1];
2593 cpColor.rgb.blue = value[2];
2594 cpColor.set = cpRGB;
2596 updateSwatch(panel, cpColor);
2597 panel->lastChanged = WMRGBModeColorPanel;
2601 /******************* CMYK Panel Functions *****************/
2603 static void
2604 cmykSliderCallback(WMWidget *w, void *data)
2606 CPColor cpColor;
2607 int value[4];
2608 char tmp[4];
2609 W_ColorPanel *panel = (W_ColorPanel*)data;
2610 double scale;
2612 value[0] = WMGetSliderValue(panel->cmykCyanS);
2613 value[1] = WMGetSliderValue(panel->cmykMagentaS);
2614 value[2] = WMGetSliderValue(panel->cmykYellowS);
2615 value[3] = WMGetSliderValue(panel->cmykBlackS);
2617 sprintf(tmp, "%d", value[0]);
2618 WMSetTextFieldText(panel->cmykCyanT, tmp);
2619 sprintf(tmp, "%d", value[1]);
2620 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2621 sprintf(tmp, "%d", value[2]);
2622 WMSetTextFieldText(panel->cmykYellowT, tmp);
2623 sprintf(tmp, "%d", value[3]);
2624 WMSetTextFieldText(panel->cmykBlackT, tmp);
2626 scale = 2.55 * (1.0 - (value[3] / 100.0));
2627 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2628 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2629 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2630 cpColor.set = cpRGB;
2632 updateSwatch(panel, cpColor);
2633 panel->lastChanged = WMCMYKModeColorPanel;
2636 static void
2637 cmykTextFieldCallback(void *observerData, WMNotification *notification)
2639 CPColor cpColor;
2640 int value[4];
2641 char tmp[4];
2642 int n;
2643 double scale;
2644 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2646 value[0] = atoi(WMGetTextFieldText(panel->cmykCyanT));
2647 value[1] = atoi(WMGetTextFieldText(panel->cmykMagentaT));
2648 value[2] = atoi(WMGetTextFieldText(panel->cmykYellowT));
2649 value[3] = atoi(WMGetTextFieldText(panel->cmykBlackT));
2651 for (n=0; n < 4; n++) {
2652 if (value[n] > 100)
2653 value[n] = 100;
2654 if (value[n] < 0)
2655 value[n] = 0;
2658 sprintf(tmp, "%d", value[0]);
2659 WMSetTextFieldText(panel->cmykCyanT, tmp);
2661 sprintf(tmp, "%d", value[1]);
2662 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2664 sprintf(tmp, "%d", value[2]);
2665 WMSetTextFieldText(panel->cmykYellowT, tmp);
2667 sprintf(tmp, "%d", value[3]);
2668 WMSetTextFieldText(panel->cmykBlackT, tmp);
2670 WMSetSliderValue(panel->cmykCyanS, value[0]);
2671 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2672 WMSetSliderValue(panel->cmykYellowS, value[2]);
2673 WMSetSliderValue(panel->cmykBlackS, value[3]);
2675 scale = 2.55 * (1.0 - (value[3] / 100.0));
2676 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2677 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2678 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2679 cpColor.set = cpRGB;
2681 updateSwatch(panel, cpColor);
2682 panel->lastChanged = WMCMYKModeColorPanel;
2685 /********************** HSB Panel Functions ***********************/
2687 static void
2688 hsbSliderCallback(WMWidget *w, void *data)
2690 CPColor cpColor;
2691 int value[3];
2692 char tmp[4];
2693 W_ColorPanel *panel = (W_ColorPanel*)data;
2695 value[0] = WMGetSliderValue(panel->hsbHueS);
2696 value[1] = WMGetSliderValue(panel->hsbSaturationS);
2697 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
2699 sprintf(tmp, "%d", value[0]);
2700 WMSetTextFieldText(panel->hsbHueT, tmp);
2701 sprintf(tmp, "%d", value[1]);
2702 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2703 sprintf(tmp, "%d", value[2]);
2704 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2706 cpColor.hsv.hue = value[0];
2707 cpColor.hsv.saturation = value[1]*2.55;
2708 cpColor.hsv.value = value[2]*2.55;
2709 cpColor.set = cpHSV;
2711 convertCPColor(&cpColor);
2713 panel->lastChanged = WMHSBModeColorPanel;
2714 updateSwatch(panel, cpColor);
2716 if (w != panel->hsbBrightnessS)
2717 hsbUpdateBrightnessGradient(panel);
2718 if (w != panel->hsbSaturationS)
2719 hsbUpdateSaturationGradient(panel);
2720 if (w != panel->hsbHueS)
2721 hsbUpdateHueGradient(panel);
2724 static void
2725 hsbTextFieldCallback(void *observerData, WMNotification *notification)
2727 CPColor cpColor;
2728 int value[3];
2729 char tmp[4];
2730 int n;
2731 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2733 value[0] = atoi(WMGetTextFieldText(panel->hsbHueT));
2734 value[1] = atoi(WMGetTextFieldText(panel->hsbSaturationT));
2735 value[2] = atoi(WMGetTextFieldText(panel->hsbBrightnessT));
2737 if (value[0] > 359)
2738 value[0] = 359;
2739 if (value[0] < 0)
2740 value[0] = 0;
2742 for (n=1; n < 3; n++) {
2743 if (value[n] > 100)
2744 value[n] = 100;
2745 if (value[n] < 0)
2746 value[n] = 0;
2749 sprintf(tmp, "%d", value[0]);
2750 WMSetTextFieldText(panel->hsbHueT, tmp);
2751 sprintf(tmp, "%d", value[1]);
2752 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2753 sprintf(tmp, "%d", value[2]);
2754 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2756 WMSetSliderValue(panel->hsbHueS, value[0]);
2757 WMSetSliderValue(panel->hsbSaturationS, value[1]);
2758 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
2760 cpColor.hsv.hue = value[0];
2761 cpColor.hsv.saturation = value[1]*2.55;
2762 cpColor.hsv.value = value[2]*2.55;
2763 cpColor.set = cpHSV;
2765 convertCPColor(&cpColor);
2767 panel->lastChanged = WMHSBModeColorPanel;
2768 updateSwatch(panel, cpColor);
2770 hsbUpdateBrightnessGradient(panel);
2771 hsbUpdateSaturationGradient(panel);
2772 hsbUpdateHueGradient(panel);
2775 static void
2776 hsbUpdateBrightnessGradient(W_ColorPanel *panel)
2778 W_Screen *scr = WMWidgetScreen(panel->win);
2779 RColor from;
2780 CPColor to;
2781 RImage *sliderImg;
2782 WMPixmap *sliderPxmp;
2784 from.red = from.green = from.blue = 0;
2785 to.hsv = panel->color.hsv;
2786 to.hsv.value = 255;
2787 to.set = cpHSV;
2789 convertCPColor(&to);
2791 sliderImg = RRenderGradient(141, 16, &from, &(to.rgb), RGRD_HORIZONTAL);
2792 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2793 RReleaseImage(sliderImg);
2795 if (sliderPxmp)
2796 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
2797 panel->font12, 2, 0, 100, WALeft, scr->white,
2798 False, _("Brightness"), strlen(_("Brightness")));
2799 else
2800 wwarning(_("Color Panel: Could not allocate memory"));
2802 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
2803 WMReleasePixmap(sliderPxmp);
2806 static void
2807 hsbUpdateSaturationGradient(W_ColorPanel *panel)
2809 W_Screen *scr = WMWidgetScreen(panel->win);
2810 CPColor from;
2811 CPColor to;
2812 RImage *sliderImg;
2813 WMPixmap *sliderPxmp;
2815 from.hsv = panel->color.hsv;
2816 from.hsv.saturation = 0;
2817 from.set = cpHSV;
2818 convertCPColor(&from);
2820 to.hsv = panel->color.hsv;
2821 to.hsv.saturation = 255;
2822 to.set = cpHSV;
2823 convertCPColor(&to);
2825 sliderImg = RRenderGradient(141, 16, &(from.rgb), &(to.rgb),
2826 RGRD_HORIZONTAL);
2827 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2828 RReleaseImage(sliderImg);
2830 if (sliderPxmp)
2831 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2832 panel->font12, 2, 0, 100, WALeft,
2833 from.hsv.value < 128 ? scr->white : scr->black, False,
2834 _("Saturation"), strlen(_("Saturation")));
2835 else
2836 wwarning(_("Color Panel: Could not allocate memory"));
2838 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
2839 WMReleasePixmap(sliderPxmp);
2842 static void
2843 hsbUpdateHueGradient(W_ColorPanel *panel)
2845 W_Screen *scr = WMWidgetScreen(panel->win);
2846 RColor **colors = NULL;
2847 RHSVColor hsvcolor;
2848 RImage *sliderImg;
2849 WMPixmap *sliderPxmp;
2850 int i;
2852 hsvcolor = panel->color.hsv;
2854 colors = wmalloc(sizeof(RColor*)*(8));
2855 for (i=0; i<7; i++) {
2856 hsvcolor.hue = (360*i)/6;
2857 colors[i] = wmalloc(sizeof(RColor));
2858 RHSVtoRGB(&hsvcolor, colors[i]);
2860 colors[7] = NULL;
2862 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2863 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2864 RReleaseImage(sliderImg);
2866 if (sliderPxmp)
2867 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2868 panel->font12, 2, 0, 100, WALeft,
2869 hsvcolor.value < 128 ? scr->white : scr->black, False,
2870 _("Hue"), strlen(_("Hue")));
2871 else
2872 wwarning(_("Color Panel: Could not allocate memory"));
2874 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2875 WMReleasePixmap(sliderPxmp);
2877 for (i=0; i<7; i++)
2878 wfree(colors[i]);
2880 wfree(colors);
2883 /*************** Custom Palette Functions ****************/
2885 static void
2886 customRenderSpectrum(W_ColorPanel *panel)
2888 RImage *spectrum;
2889 int x,y;
2890 unsigned char *ptr;
2891 CPColor cpColor;
2893 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, False);
2895 ptr = spectrum->data;
2897 for (y = 0; y < SPECTRUM_HEIGHT; y++) {
2898 cpColor.hsv.hue = y;
2899 cpColor.hsv.saturation = 0;
2900 cpColor.hsv.value = 255;
2901 cpColor.set = cpHSV;
2903 for (x = 0; x < SPECTRUM_WIDTH; x++) {
2904 convertCPColor(&cpColor);
2906 *(ptr++) = (unsigned char)cpColor.rgb.red;
2907 *(ptr++) = (unsigned char)cpColor.rgb.green;
2908 *(ptr++) = (unsigned char)cpColor.rgb.blue;
2910 if (x < (SPECTRUM_WIDTH/2))
2911 cpColor.hsv.saturation++;
2913 if (x > (SPECTRUM_WIDTH/2))
2914 cpColor.hsv.value--;
2917 if (panel->customPaletteImg) {
2918 RReleaseImage(panel->customPaletteImg);
2919 panel->customPaletteImg = NULL;
2921 panel->customPaletteImg = spectrum;
2926 static void
2927 customSetPalette(W_ColorPanel *panel)
2929 W_Screen *scr = WMWidgetScreen(panel->win);
2930 RImage *scaledImg;
2931 Pixmap image;
2932 int item;
2934 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth,
2935 customPaletteHeight, scr->depth);
2936 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth,
2937 customPaletteHeight);
2938 RConvertImage(scr->rcontext, scaledImg, &image);
2939 RReleaseImage(scaledImg);
2941 XCopyArea(scr->display, image, panel->customPaletteContentView->window,
2942 scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2944 /* Check backimage exists. If it doesn't, allocate and fill it */
2945 if (!panel->selectionBackImg) {
2946 panel->selectionBackImg = XCreatePixmap(scr->display,
2947 panel->customPaletteContentView->window, 4, 4, scr->depth);
2950 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
2951 panel->palx-2, panel->paly-2, 4, 4, 0, 0);
2952 XCopyArea(scr->display, panel->selectionImg,
2953 panel->customPaletteContentView->window, scr->copyGC, 0 , 0, 4, 4,
2954 panel->palx-2, panel->paly-2);
2955 XFreePixmap(scr->display, image);
2957 panel->palXRatio = (double)(panel->customPaletteImg->width) /
2958 (double)(customPaletteWidth);
2959 panel->palYRatio = (double)(panel->customPaletteImg->height) /
2960 (double)(customPaletteHeight);
2962 item = WMGetPopUpButtonSelectedItem (panel->customPaletteHistoryBtn);
2966 static void
2967 customPalettePositionSelection(W_ColorPanel *panel, int x, int y)
2969 W_Screen *scr = WMWidgetScreen(panel->win);
2970 unsigned long ofs;
2973 /* undraw selection */
2974 XCopyArea(scr->display, panel->selectionBackImg,
2975 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2976 panel->palx-2, panel->paly-2);
2978 panel->palx = x;
2979 panel->paly = y;
2981 ofs = (rint(x * panel->palXRatio) + rint(y * panel->palYRatio) *
2982 panel->customPaletteImg->width) * 3;
2984 panel->color.rgb.red = panel->customPaletteImg->data[ofs];
2985 panel->color.rgb.green = panel->customPaletteImg->data[ofs+1];
2986 panel->color.rgb.blue = panel->customPaletteImg->data[ofs+2];
2987 panel->color.set = cpRGB;
2989 updateSwatch(panel, panel->color);
2990 panel->lastChanged = WMCustomPaletteModeColorPanel;
2992 /* Redraw color selector (and make a backup of the part it will cover) */
2993 XCopyArea(scr->display, panel->customPaletteContentView->window,
2994 panel->selectionBackImg, scr->copyGC, panel->palx-2, panel->paly-2,
2995 4, 4, 0, 0); /* "-2" is correction for hotspot location */
2996 XCopyArea(scr->display, panel->selectionImg,
2997 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2998 panel->palx-2, panel->paly-2); /* see above */
3002 static void
3003 customPalettePositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
3005 if (x < 2)
3006 x = 2;
3007 if (y < 2)
3008 y = 2;
3009 if (x >= customPaletteWidth)
3010 x = customPaletteWidth -2;
3011 if (y >= customPaletteHeight)
3012 y = customPaletteHeight -2;
3014 customPalettePositionSelection(panel, x, y);
3018 static void
3019 customPaletteHandleEvents(XEvent *event, void *data)
3021 W_ColorPanel *panel = (W_ColorPanel*)data;
3023 switch (event->type) {
3024 case Expose:
3025 if (event->xexpose.count != 0) /* TODO Improve. */
3026 break;
3027 customSetPalette(panel);
3028 break;
3032 static void
3033 customPaletteHandleActionEvents(XEvent *event, void *data)
3035 W_ColorPanel *panel = (W_ColorPanel*)data;
3036 int x, y;
3038 switch (event->type) {
3039 case ButtonPress:
3040 x = event->xbutton.x;
3041 y = event->xbutton.y;
3043 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
3044 panel->flags.dragging = 1;
3045 customPalettePositionSelection(panel, x, y);
3047 break;
3049 case ButtonRelease:
3050 panel->flags.dragging = 0;
3051 if (!panel->flags.continuous) {
3052 if (panel->action)
3053 (*panel->action)(panel, panel->clientData);
3055 break;
3057 case MotionNotify:
3058 x = event->xmotion.x;
3059 y = event->xmotion.y;
3061 if (panel->flags.dragging) {
3062 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
3063 customPalettePositionSelection(panel, x, y);
3065 else
3066 customPalettePositionSelectionOutBounds(panel, x, y);
3068 break;
3073 static void
3074 customPaletteMenuCallback(WMWidget *w, void *data)
3076 W_ColorPanel *panel = (W_ColorPanel*)data;
3077 int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
3079 switch (item) {
3080 case CPmenuNewFromFile:
3081 customPaletteMenuNewFromFile(panel);
3082 break;
3083 case CPmenuRename:
3084 customPaletteMenuRename(panel);
3085 break;
3086 case CPmenuRemove:
3087 customPaletteMenuRemove(panel);
3088 break;
3089 case CPmenuCopy:
3090 break;
3091 case CPmenuNewFromClipboard:
3092 break;
3097 static void
3098 customPaletteMenuNewFromFile(W_ColorPanel *panel)
3100 W_Screen *scr = WMWidgetScreen(panel->win);
3101 WMOpenPanel *browseP;
3102 char *filepath;
3103 char *filename = NULL;
3104 char *spath;
3105 char *tmp;
3106 int i;
3107 RImage *tmpImg = NULL;
3109 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir,"\0") == 0))
3110 spath = wexpandpath(wgethomedir());
3111 else
3112 spath = wexpandpath(panel->lastBrowseDir);
3114 browseP = WMGetOpenPanel(scr);
3115 WMSetFilePanelCanChooseDirectories(browseP, 0);
3116 WMSetFilePanelCanChooseFiles(browseP, 1);
3118 /* Get a filename */
3119 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
3120 _("Open Palette"), RSupportedFileFormats()) ) {
3121 filepath = WMGetFilePanelFileName(browseP);
3123 /* Get seperation position between path and filename */
3124 i = strrchr(filepath, '/') - filepath + 1;
3125 if (i > strlen(filepath))
3126 i = strlen(filepath);
3128 /* Store last browsed path */
3129 if (panel->lastBrowseDir)
3130 wfree(panel->lastBrowseDir);
3131 panel->lastBrowseDir = wmalloc((i+1)*sizeof(char));
3132 strncpy(panel->lastBrowseDir, filepath, i);
3133 panel->lastBrowseDir[i] = '\0';
3135 /* Get filename from path */
3136 filename = wstrdup(filepath + i);
3138 /* Check for duplicate files, and rename it if there are any */
3139 tmp = wstrconcat(panel->configurationPath, filename);
3140 while (access (tmp, F_OK) == 0) {
3141 char *newName;
3143 wfree(tmp);
3145 newName = generateNewFilename(filename);
3146 wfree(filename);
3147 filename = newName;
3149 tmp = wstrconcat(panel->configurationPath, filename);
3151 wfree(tmp);
3153 /* Copy image to $(gnustepdir)/Library/Colors/ &
3154 * Add filename to history menu */
3155 if (fetchFile (panel->configurationPath, filepath, filename) == 0) {
3157 /* filepath is a "local" path now the file has been copied */
3158 wfree(filepath);
3159 filepath = wstrconcat(panel->configurationPath, filename);
3161 /* load the image & add menu entries */
3162 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
3163 if (tmpImg) {
3164 if (panel->customPaletteImg)
3165 RReleaseImage(panel->customPaletteImg);
3166 panel->customPaletteImg = tmpImg;
3168 customSetPalette(panel);
3169 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
3171 panel->currentPalette = WMGetPopUpButtonNumberOfItems(
3172 panel->customPaletteHistoryBtn)-1;
3174 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3175 panel->currentPalette);
3177 } else {
3178 tmp = wstrconcat(panel->configurationPath, filename);
3180 i = remove(tmp); /* Delete the file, it doesn't belong here */
3181 WMRunAlertPanel(scr, panel->win, _("File Error"),
3182 _("Invalid file format !"), _("OK"), NULL, NULL);
3183 if (i != 0) {
3184 wsyserror(_("can't remove file %s"), tmp);
3185 WMRunAlertPanel(scr, panel->win, _("File Error"),
3186 _("Couldn't remove file from Configuration Directory !"),
3187 _("OK"), NULL, NULL);
3189 wfree(tmp);
3191 wfree(filepath);
3192 wfree(filename);
3194 WMFreeFilePanel(browseP);
3196 wfree(spath);
3200 static void
3201 customPaletteMenuRename(W_ColorPanel *panel)
3203 W_Screen *scr = WMWidgetScreen(panel->win);
3204 char *toName = NULL;
3205 char *fromName;
3206 char *toPath, *fromPath;
3207 int item;
3208 int index;
3210 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3211 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
3213 toName = WMRunInputPanel(scr, panel->win, _("Rename"), _("Rename palette to:"),
3214 fromName, _("OK"), _("Cancel"));
3216 if (toName) {
3218 /* As some people do certain stupid things... */
3219 if (strcmp(toName, fromName) == 0) {
3220 wfree(toName);
3221 return;
3224 /* For normal people */
3225 fromPath = wstrconcat(panel->configurationPath, fromName);
3226 toPath = wstrconcat(panel->configurationPath, toName);
3228 if (access (toPath, F_OK) == 0) {
3229 /* Careful, this palette exists already */
3230 if (WMRunAlertPanel(scr, panel->win, _("Warning"),
3231 _("Palette already exists !\n\nOverwrite ?"), _("No"), _("Yes"),
3232 NULL) == 1) {
3233 /* "No" = 0, "Yes" = 1 */
3234 int items = WMGetPopUpButtonNumberOfItems(
3235 panel->customPaletteHistoryBtn);
3237 remove(toPath);
3239 /* Remove from History list too */
3240 index = 1;
3241 while ((index < items) && (strcmp(WMGetPopUpButtonItem(
3242 panel->customPaletteHistoryBtn, index),
3243 toName) != 0 ))
3244 index++;
3246 if (index < items) {
3247 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn,
3248 index);
3249 if (index < item)
3250 item--;
3253 } else {
3254 wfree(fromPath);
3255 wfree(toName);
3256 wfree(toPath);
3258 return;
3262 if ( rename(fromPath, toPath) != 0)
3263 wsyserror(_("Couldn't rename palette %s to %s\n"), fromName, toName);
3264 else {
3265 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3266 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item,
3267 toName);
3269 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
3271 wfree(fromPath);
3272 wfree(toPath);
3273 wfree(toName);
3278 static void
3279 customPaletteMenuRemove(W_ColorPanel *panel)
3281 W_Screen *scr = WMWidgetScreen(panel->win);
3282 char *text;
3283 char *tmp;
3284 int choice;
3285 int item;
3287 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3289 tmp = wstrconcat( _("This will permanently remove the palette "),
3290 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
3291 text = wstrconcat( tmp,
3292 _(".\n\nAre you sure you want to remove this palette ?"));
3293 wfree(tmp);
3295 choice = WMRunAlertPanel(scr, panel->win, _("Remove"), text, _("Yes"), _("No"),
3296 NULL);
3297 /* returns 0 (= "Yes") or 1 (="No") */
3298 wfree(text);
3300 if (choice == 0) {
3302 tmp = wstrconcat(panel->configurationPath,
3303 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
3305 if ( remove(tmp) == 0) {
3306 /* item-1 always exists */
3307 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3308 item-1);
3310 customPaletteHistoryCallback(panel->customPaletteHistoryBtn,
3311 panel);
3312 customSetPalette(panel);
3314 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3316 } else {
3317 wsyserror(_("Couldn't remove palette %s\n"), tmp);
3320 wfree(tmp);
3325 static void
3326 customPaletteHistoryCallback(WMWidget *w, void *data)
3328 W_ColorPanel *panel = (W_ColorPanel*)data;
3329 W_Screen *scr = WMWidgetScreen(panel->win);
3330 int item;
3331 char *filename;
3332 RImage *tmp = NULL;
3333 unsigned char perm_mask;
3335 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3336 if (item == panel->currentPalette)
3337 return;
3339 if (item == 0) {
3340 customRenderSpectrum(panel);
3342 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename,
3343 False );
3344 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove,
3345 False );
3346 } else {
3347 /* Load file from configpath */
3348 filename = wstrconcat( panel->configurationPath,
3349 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item) );
3351 /* If the file corresponding to the item does not exist,
3352 * remove it from the history list and select the next one.
3354 perm_mask = (access(filename, F_OK) == 0);
3355 if (!perm_mask) {
3356 /* File does not exist */
3357 wfree(filename);
3358 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3359 item-1);
3360 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3361 customPaletteHistoryCallback(w, data);
3362 return;
3365 /* Get the image */
3366 tmp = RLoadImage(scr->rcontext, filename, 0);
3367 if (tmp) {
3368 if (panel->customPaletteImg) {
3369 RReleaseImage(panel->customPaletteImg);
3370 panel->customPaletteImg = NULL;
3372 panel->customPaletteImg = tmp;
3375 /* If the image is not writable, don't allow removing/renaming */
3376 perm_mask = (access(filename, W_OK) == 0);
3377 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename,
3378 perm_mask);
3379 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove,
3380 perm_mask);
3382 wfree(filename);
3384 customSetPalette(panel);
3386 panel->currentPalette = item;
3389 /************************* ColorList Panel Functions **********************/
3391 static void
3392 colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text,
3393 int state, WMRect *rect)
3395 WMScreen *scr = WMWidgetScreen(lPtr);
3396 Display *dpy = WMScreenDisplay(scr);
3397 WMView *view = W_VIEW(lPtr);
3398 RColor *color = (RColor *)WMGetListItem(lPtr, index)->clientData;
3399 W_ColorPanel *panel = WMGetHangedData(lPtr);
3400 int width, height, x, y;
3401 WMColor *fillColor;
3403 width = rect->size.width;
3404 height = rect->size.height;
3405 x = rect->pos.x;
3406 y = rect->pos.y;
3408 if (state & WLDSSelected)
3409 XFillRectangle(dpy, d, WMColorGC(scr->white), x, y, width, height);
3410 else
3411 XFillRectangle(dpy, d, WMColorGC(view->backColor), x, y, width, height);
3413 fillColor = WMCreateRGBColor(scr, color->red<<8, color->green<<8,
3414 color->blue<<8, True);
3416 XFillRectangle(dpy, d, WMColorGC(fillColor), x, y, 15, height);
3417 WMReleaseColor(fillColor);
3419 WMDrawString(scr, d, scr->black, panel->font12, x+18, y, text, strlen(text));
3423 static void
3424 colorListSelect(WMWidget *w, void *data)
3426 W_ColorPanel *panel = (W_ColorPanel *)data;
3427 CPColor cpColor;
3429 cpColor.rgb = *((RColor *)WMGetListSelectedItem(w)->clientData);
3430 cpColor.set = cpRGB;
3432 panel->lastChanged = WMColorListModeColorPanel;
3433 updateSwatch(panel, cpColor);
3437 static void
3438 colorListColorMenuCallback(WMWidget *w, void *data)
3440 W_ColorPanel *panel = (W_ColorPanel *)data;
3441 int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
3443 switch (item) {
3444 case CLmenuAdd:
3445 break;
3446 case CLmenuRename:
3447 break;
3448 case CLmenuRemove:
3449 break;
3454 static void
3455 colorListListMenuCallback(WMWidget *w, void *data)
3457 W_ColorPanel *panel = (W_ColorPanel *)data;
3458 int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
3460 switch (item) {
3461 case CLmenuAdd:
3462 /* New Color List */
3463 colorListListMenuNew(panel);
3464 break;
3465 case CLmenuRename:
3466 break;
3467 case CLmenuRemove:
3468 break;
3473 static void
3474 colorListListMenuNew(W_ColorPanel *panel)
3480 /*************** Panel Initialisation Functions *****************/
3482 static void
3483 wheelInit(W_ColorPanel *panel)
3485 CPColor cpColor;
3487 if (panel->color.set != cpHSV)
3488 convertCPColor(&panel->color);
3490 WMSetSliderValue(panel->wheelBrightnessS, 255 - panel->color.hsv.value);
3492 panel->colx = 2 + rint((colorWheelSize / 2.0) *
3493 (1 + ( panel->color.hsv.saturation/255.0) *
3494 cos( panel->color.hsv.hue * M_PI/180.0)));
3495 panel->coly = 2 + rint((colorWheelSize / 2.0) *
3496 (1 + ( panel->color.hsv.saturation/255.0) *
3497 sin(- panel->color.hsv.hue*M_PI/180.0)));
3499 wheelCalculateValues(panel, panel->color.hsv.value);
3501 cpColor = panel->color;
3502 cpColor.hsv.value = 255;
3503 cpColor.set = cpHSV;
3504 wheelUpdateBrightnessGradient(panel, cpColor);
3508 static void
3509 grayInit(W_ColorPanel *panel)
3511 int value;
3512 char tmp[4];
3514 if (panel->color.set != cpHSV)
3515 convertCPColor(&panel->color);
3517 value = rint(panel->color.hsv.value/2.55);
3518 WMSetSliderValue(panel->grayBrightnessS, value);
3520 sprintf(tmp, "%d", value);
3521 WMSetTextFieldText(panel->grayBrightnessT, tmp);
3525 static void
3526 rgbInit(W_ColorPanel *panel)
3528 char tmp[4];
3530 if (panel->color.set != cpRGB)
3531 convertCPColor(&panel->color);
3533 WMSetSliderValue(panel->rgbRedS, panel->color.rgb.red);
3534 WMSetSliderValue(panel->rgbGreenS, panel->color.rgb.green);
3535 WMSetSliderValue(panel->rgbBlueS, panel->color.rgb.blue);
3537 sprintf(tmp, "%d", panel->color.rgb.red);
3538 WMSetTextFieldText(panel->rgbRedT, tmp);
3539 sprintf(tmp, "%d", panel->color.rgb.green);
3540 WMSetTextFieldText(panel->rgbGreenT, tmp);
3541 sprintf(tmp, "%d", panel->color.rgb.blue);
3542 WMSetTextFieldText(panel->rgbBlueT, tmp);
3546 static void
3547 cmykInit(W_ColorPanel *panel)
3549 int value[3];
3550 char tmp[4];
3552 if (panel->color.set != cpRGB)
3553 convertCPColor(&panel->color);
3555 value[0] = rint((255-panel->color.rgb.red)/2.55);
3556 value[1] = rint((255-panel->color.rgb.green)/2.55);
3557 value[2] = rint((255-panel->color.rgb.blue)/2.55);
3559 WMSetSliderValue(panel->cmykCyanS, value[0]);
3560 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3561 WMSetSliderValue(panel->cmykYellowS, value[2]);
3562 WMSetSliderValue(panel->cmykBlackS, 0);
3564 sprintf(tmp, "%d", value[0]);
3565 WMSetTextFieldText(panel->cmykCyanT, tmp);
3566 sprintf(tmp, "%d", value[1]);
3567 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3568 sprintf(tmp, "%d", value[2]);
3569 WMSetTextFieldText(panel->cmykYellowT, tmp);
3570 WMSetTextFieldText(panel->cmykBlackT, "0");
3574 static void
3575 hsbInit(W_ColorPanel *panel)
3577 int value[3];
3578 char tmp[4];
3580 if (panel->color.set != cpHSV)
3581 convertCPColor(&panel->color);
3583 value[0] = panel->color.hsv.hue;
3584 value[1] = rint(panel->color.hsv.saturation/2.55);
3585 value[2] = rint(panel->color.hsv.value/2.55);
3587 WMSetSliderValue(panel->hsbHueS,value[0]);
3588 WMSetSliderValue(panel->hsbSaturationS,value[1]);
3589 WMSetSliderValue(panel->hsbBrightnessS,value[2]);
3591 sprintf(tmp, "%d", value[0]);
3592 WMSetTextFieldText(panel->hsbHueT, tmp);
3593 sprintf(tmp, "%d", value[1]);
3594 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3595 sprintf(tmp, "%d", value[2]);
3596 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3598 hsbUpdateBrightnessGradient(panel);
3599 hsbUpdateSaturationGradient(panel);
3600 hsbUpdateHueGradient(panel);
3605 /************************** Common utility functions ************************/
3607 static int
3608 fetchFile(char *toPath, char *srcFile, char *destFile)
3610 int src, dest;
3611 int n;
3612 char *tmp;
3613 char buf[BUFSIZE];
3615 if ((src = open(srcFile, O_RDONLY|O_BINARY)) == 0) {
3616 wsyserror(_("Could not open %s"), srcFile);
3617 return -1;
3620 tmp = wstrconcat(toPath, destFile);
3621 if ((dest = open( tmp, O_RDWR|O_CREAT|O_BINARY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH))
3622 == 0) {
3623 wsyserror(_("Could not create %s"), tmp);
3624 wfree(tmp);
3625 return -1;
3627 wfree(tmp);
3630 /* Copy the file */
3631 while ((n = read(src, buf, BUFSIZE)) > 0)
3633 if (write (dest, buf, n) != n) {
3634 wsyserror(_("Write error on file %s"), destFile);
3635 return -1;
3639 return 0;
3643 char*
3644 generateNewFilename(char *curName)
3646 int n;
3647 char c;
3648 int baseLen;
3649 char *ptr;
3650 char *newName;
3653 assert(curName);
3655 ptr = curName;
3657 if (((ptr = strrchr(ptr, '{'))==0) || sscanf(ptr, "{%i}%c", &n, &c)!=1)
3658 return wstrconcat(curName, " {1}");
3660 baseLen = ptr - curName -1;
3662 newName = wmalloc(baseLen + 16);
3663 strncpy(newName, curName, baseLen);
3664 newName[baseLen] = 0;
3666 sprintf(&newName[baseLen], " {%i}", n+1);
3668 return newName;
3672 void
3673 convertCPColor(CPColor *color)
3675 unsigned short old_hue = 0;
3677 switch (color->set) {
3678 case cpNone:
3679 wwarning(_("Color Panel: Color unspecified"));
3680 return;
3681 case cpRGB:
3682 old_hue = color->hsv.hue;
3683 RRGBtoHSV(&(color->rgb), &(color->hsv));
3685 /* In black the hue is undefined, and may change by conversion
3686 * Same for white. */
3687 if (
3688 ((color->rgb.red == 0) &&
3689 (color->rgb.green == 0) &&
3690 (color->rgb.blue == 0)) ||
3691 ((color->rgb.red == 0) &&
3692 (color->rgb.green == 0) &&
3693 (color->rgb.blue == 255))
3695 color->hsv.hue = old_hue;
3696 break;
3697 case cpHSV:
3698 RHSVtoRGB(&(color->hsv), &(color->rgb));
3699 break;
3704 #define ABS_SHIFT(val, shift) \
3705 (((shift) > 0) ? (val) >> (shift) : (val) << -(shift))
3707 RColor
3708 ulongToRColor(WMScreen *scr, unsigned long value)
3710 RColor color;
3711 XColor *xcolor = NULL;
3713 if (!(xcolor = wmalloc(sizeof(XColor)) )) {
3714 wwarning(_("Color Panel: Could not allocate memory"));
3715 color.red = 0;
3716 color.green = 0;
3717 color.blue = 0;
3718 return color;
3721 xcolor->pixel = value;
3722 XQueryColor(scr->display, scr->rcontext->cmap, xcolor);
3724 color.red = xcolor->red >> 8;
3725 color.green = xcolor->green >> 8;
3726 color.blue = xcolor->blue >> 8;
3728 wfree(xcolor);
3730 return color;
3734 unsigned char
3735 getShift(unsigned char value)
3737 unsigned char i = -1;
3739 if (value == 0)
3740 return 0;
3742 while (value) {
3743 value >>= 1;
3744 i++;
3747 return i;
3752 #ifdef SHAPE_WAS_DEFINED
3753 #undef SHAPE_WAS_DEFINED
3754 #define SHAPE
3755 #endif