Fixes from Alban and Pascal.
[wmaker-crm.git] / WINGs / wcolorpanel.c
blob4e4825cb98675386c5974ccfd7b4f8df20170546
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 120 degrees.
22 * - Custom color-lists and custom colors in custom colo-lists.
23 * - Stored colors
24 * - Resizing
27 #include "../src/config.h"
28 #include "WINGsP.h"
29 #include <math.h>
30 #include <unistd.h>
31 #include <ctype.h>
32 #include <fcntl.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <dirent.h>
36 #include <errno.h>
38 /* BUG There's something fishy with shaped windows */
39 #if 1
40 #ifdef SHAPE
41 #define SHAPE_WAS_DEFINED
42 #undef SHAPE
43 #endif
44 #endif
47 #ifdef SHAPE
48 #include <X11/extensions/shape.h>
49 #endif
52 #ifndef PATH_MAX
53 # define PATH_MAX 1024
54 #endif
57 char *WMColorPanelColorChangedNotification = "WMColorPanelColorChangedNotification";
61 * Bitmaps for magnifying glass cursor
64 /* Cursor */
65 #define Cursor_x_hot 11
66 #define Cursor_y_hot 11
67 #define Cursor_width 32
68 #define Cursor_height 32
69 static unsigned char Cursor_bits[] = {
70 0x00,0x7e,0x00,0x00,0xc0,0x81,0x03,0x00,0x20,0x00,0x04,0x00,0x10,0x00,0x08,
71 0x00,0x08,0x00,0x10,0x00,0x04,0x00,0x20,0x00,0x02,0x00,0x40,0x00,0x02,0x00,
72 0x40,0x00,0x02,0x00,0x40,0x00,0x01,0x42,0x80,0x00,0x01,0x24,0x80,0x00,0x01,
73 0x00,0x80,0x00,0x01,0x00,0x80,0x00,0x01,0x24,0x80,0x00,0x01,0x42,0x80,0x00,
74 0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x04,0x00,0x20,
75 0x00,0x08,0x00,0x50,0x00,0x10,0x00,0x88,0x00,0x20,0x00,0x5c,0x01,0xc0,0x81,
76 0x3b,0x02,0x00,0x7e,0x70,0x05,0x00,0x00,0xe0,0x08,0x00,0x00,0xc0,0x15,0x00,
77 0x00,0x80,0x23,0x00,0x00,0x00,0x57,0x00,0x00,0x00,0x8e,0x00,0x00,0x00,0x5c,
78 0x00,0x00,0x00,0xb8,0x00,0x00,0x00,0x70};
80 /* Cursor shape-mask */
81 #define Cursor_shape_width 32
82 #define Cursor_shape_height 32
83 static unsigned char Cursor_shape_bits[] = {
84 0x00,0x7e,0x00,0x00,0xc0,0x81,0x03,0x00,0x20,0x00,0x04,0x00,0x10,0x00,0x08,
85 0x00,0x08,0x00,0x10,0x00,0x04,0x00,0x20,0x00,0x02,0x00,0x40,0x00,0x02,0x00,
86 0x40,0x00,0x02,0x00,0x40,0x00,0x01,0x42,0x80,0x00,0x01,0x24,0x80,0x00,0x01,
87 0x00,0x80,0x00,0x01,0x00,0x80,0x00,0x01,0x24,0x80,0x00,0x01,0x42,0x80,0x00,
88 0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x04,0x00,0x20,
89 0x00,0x08,0x00,0x70,0x00,0x10,0x00,0xf8,0x00,0x20,0x00,0xfc,0x01,0xc0,0x81,
90 0xfb,0x03,0x00,0x7e,0xf0,0x07,0x00,0x00,0xe0,0x0f,0x00,0x00,0xc0,0x1f,0x00,
91 0x00,0x80,0x3f,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0xfc,
92 0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x70};
94 /* Clip-mask for magnified pixels */
95 #define Cursor_mask_width 24
96 #define Cursor_mask_height 24
97 static unsigned char Cursor_mask_bits[] = {
98 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0xff, 0x07,
99 0xf0, 0xff, 0x0f, 0xf8, 0xff, 0x1f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f,
100 0xfc, 0xff, 0x3f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f,
101 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfc, 0xff, 0x3f,
102 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xf8, 0xff, 0x1f, 0xf0, 0xff, 0x0f,
103 0xe0, 0xff, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00};
106 typedef struct MovingView {
107 WMView *view; /* The view this is all about */
108 XImage *image; /* What's under the view */
109 XImage *dirtyRect; /* Storage of overlapped image area */
110 Pixmap magPix; /* Magnified part of pixmap */
111 RColor color; /* Color of a pixel in the image */
112 } MovingView;
114 typedef struct WheelMatrix {
115 unsigned int width, height; /* Size of the colorwheel */
116 unsigned char *data[3]; /* Wheel data (R,G,B) */
117 unsigned char values[256]; /* Precalculated values R,G & B = 0-255 */
118 } wheelMatrix;
120 typedef struct W_ColorPanel {
121 WMWindow *win;
122 WMFont *font8;
123 WMFont *font12;
124 void *clientData;
125 WMAction2 *action;
127 /* Common Stuff */
128 WMColorWell *colorWell;
129 WMButton *magnifyBtn;
130 WMButton *wheelBtn;
131 WMButton *slidersBtn;
132 WMButton *customPaletteBtn;
133 WMButton *colorListBtn;
135 /* Magnifying Glass */
136 MovingView *magnifyGlass;
138 /* ColorWheel Panel */
139 WMFrame *wheelFrm;
140 WMSlider *wheelBrightnessS;
141 WMView *wheelView;
143 /* Slider Panels */
144 WMFrame *slidersFrm;
145 WMFrame *seperatorFrm;
146 WMButton *grayBtn;
147 WMButton *rgbBtn;
148 WMButton *cmykBtn;
149 WMButton *hsbBtn;
150 /* Gray Scale Panel */
151 WMFrame *grayFrm;
152 WMLabel *grayMinL;
153 WMLabel *grayMaxL;
154 WMSlider *grayBrightnessS;
155 WMTextField *grayBrightnessT;
156 WMButton *grayPresetBtn[7];
158 /* RGB Panel */
159 WMFrame *rgbFrm;
160 WMLabel *rgbMinL;
161 WMLabel *rgbMaxL;
162 WMSlider *rgbRedS;
163 WMSlider *rgbGreenS;
164 WMSlider *rgbBlueS;
165 WMTextField *rgbRedT;
166 WMTextField *rgbGreenT;
167 WMTextField *rgbBlueT;
169 /* CMYK Panel */
170 WMFrame *cmykFrm;
171 WMLabel *cmykMinL;
172 WMLabel *cmykMaxL;
173 WMSlider *cmykCyanS;
174 WMSlider *cmykMagentaS;
175 WMSlider *cmykYellowS;
176 WMSlider *cmykBlackS;
177 WMTextField *cmykCyanT;
178 WMTextField *cmykMagentaT;
179 WMTextField *cmykYellowT;
180 WMTextField *cmykBlackT;
182 /* HSB Panel */
183 WMFrame *hsbFrm;
184 WMSlider *hsbHueS;
185 WMSlider *hsbSaturationS;
186 WMSlider *hsbBrightnessS;
187 WMTextField *hsbHueT;
188 WMTextField *hsbSaturationT;
189 WMTextField *hsbBrightnessT;
191 /* Custom Palette Panel*/
192 WMFrame *customPaletteFrm;
193 WMPopUpButton *customPaletteHistoryBtn;
194 WMFrame *customPaletteContentFrm;
195 WMPopUpButton *customPaletteMenuBtn;
196 WMView *customPaletteContentView;
198 /* Color List Panel */
199 WMFrame *colorListFrm;
200 WMPopUpButton *colorListHistoryBtn;
201 WMList *colorListContentLst;
202 WMPopUpButton *colorListColorMenuBtn;
203 WMPopUpButton *colorListListMenuBtn;
205 /* Look-Up Tables and Images */
206 wheelMatrix *wheelMtrx;
207 Pixmap wheelImg;
208 Pixmap selectionImg;
209 Pixmap selectionBackImg;
210 RImage *customPaletteImg;
211 char *lastBrowseDir;
213 /* Common Data Fields */
214 RColor color; /* Current color */
215 Bool colorSet; /* Is color already set ? */
216 RHSVColor hsvcolor; /* Backup HSV Color */
217 WMColorPanelMode mode; /* Current color selection mode */
218 WMColorPanelMode slidersmode;/* Current color sel. mode sliders panel */
219 WMColorPanelMode lastChanged;/* Panel that last changed the color */
220 int colx, coly; /* (x,y) of sel.-marker in WheelMode */
221 int palx, paly; /* (x,y) of sel.-marker in
222 CustomPaletteMode */
223 float palXRatio, palYRatio; /* Ratios in x & y between
224 original and scaled
225 palettesize */
226 int currentPalette;
227 char *configurationPath;
229 struct {
230 unsigned int continuous:1;
231 unsigned int dragging:1;
232 } flags;
233 } W_ColorPanel;
235 enum {
236 CPmenuNewFromFile,
237 CPmenuRename,
238 CPmenuRemove,
239 CPmenuCopy,
240 CPmenuNewFromClipboard
241 } customPaletteMenuItem;
243 enum {
244 CLmenuAdd,
245 CLmenuRename,
246 CLmenuRemove
247 } colorListMenuItem;
250 #define PWIDTH 194
251 #define PHEIGHT 266
252 #define colorWheelSize 150
253 #define customPaletteWidth 182
254 #define customPaletteHeight 106
255 #define knobThickness 8
257 #define SPECTRUM_WIDTH 511
258 #define SPECTRUM_HEIGHT 360
260 #define COLORWHEEL_PART 1
261 #define CUSTOMPALETTE_PART 2
262 #define BUFSIZE 1024
264 #undef EASTEREGG
266 #ifndef RGBTXT
267 #define RGBTXT "/usr/X11R6/lib/X11/rgb.txt"
268 #endif
270 #define MAX_LENGTH 1024
272 static int fetchFile(char* toPath, char *imageSrcFile, char *imageDestFileName);
273 char *generateNewFilename(char *curName);
274 RColor ulongToRColor(WMScreen *scr, XImage *image, unsigned long value);
276 static void modeButtonCallback(WMWidget *w, void *data);
277 static int getPickerPart(W_ColorPanel *panel, int x, int y);
278 static void readConfiguration(W_ColorPanel *panel);
279 static void readXColors(W_ColorPanel *panel);
281 static void closeWindowCallback(WMWidget *w, void *data);
283 static Cursor magnifyGrabPointer(W_ColorPanel *panel);
284 static WMPoint magnifyInitialize(W_ColorPanel *panel);
285 static void magnifyPutCursor(WMWidget *w, void *data);
286 static Pixmap magnifyCreatePixmap(WMColorPanel *panel);
287 static void magnifyGetImageStored(W_ColorPanel *panel, int x1, int y1,
288 int x2, int y2);
289 static XImage* magnifyGetImage(WMScreen *scr, XImage *image, int x, int y,
290 int w, int h);
292 static wheelMatrix* wheelCreateMatrix(unsigned int width , unsigned int height);
293 static void wheelDestroyMatrix(wheelMatrix *matrix);
294 static wheelMatrix* wheelInitMatrix(W_ColorPanel *panel);
295 static void wheelRender(W_ColorPanel *panel);
296 static Bool wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs);
297 static void wheelPaint(W_ColorPanel *panel);
299 static void wheelHandleEvents(XEvent *event, void *data);
300 static void wheelHandleActionEvents(XEvent *event, void *data);
301 static void wheelBrightnessSliderCallback(WMWidget *w, void *data);
302 static void wheelUpdateSelection(W_ColorPanel *panel);
303 static void wheelUndrawSelection(W_ColorPanel *panel);
305 static void wheelPositionSelection(W_ColorPanel *panel, int x, int y);
306 static void wheelPositionSelectionOutBounds(W_ColorPanel *panel, int x, int y);
307 static void wheelUpdateBrightnessGradientFromHSV (W_ColorPanel *panel,
308 RHSVColor topColor);
309 static void wheelUpdateBrightnessGradientFromLocation (W_ColorPanel *panel);
310 static void wheelUpdateBrightnessGradient(W_ColorPanel *panel, RColor topColor);
312 static void grayBrightnessSliderCallback(WMWidget *w, void *data);
313 static void grayPresetButtonCallback(WMWidget *w, void *data);
314 static void grayBrightnessTextFieldCallback(void *observerData,
315 WMNotification *notification);
317 static void rgbSliderCallback(WMWidget *w, void *data);
318 static void rgbTextFieldCallback(void *observerData,
319 WMNotification *notification);
321 static void cmykSliderCallback(WMWidget *w, void *data);
322 static void cmykTextFieldCallback(void *observerData,
323 WMNotification *notification);
325 static void hsbSliderCallback(WMWidget *w, void *data);
326 static void hsbTextFieldCallback(void *observerData,
327 WMNotification *notification);
328 static void hsbUpdateBrightnessGradient(W_ColorPanel *panel);
329 static void hsbUpdateSaturationGradient(W_ColorPanel *panel);
330 static void hsbUpdateHueGradient(W_ColorPanel *panel);
332 static void customRenderSpectrum(W_ColorPanel *panel);
333 static void customSetPalette(W_ColorPanel *panel);
334 static void customPaletteHandleEvents(XEvent *event, void *data);
335 static void customPaletteHandleActionEvents(XEvent *event, void *data);
336 static void customPalettePositionSelection(W_ColorPanel *panel, int x, int y);
337 static void customPalettePositionSelectionOutBounds(W_ColorPanel *panel,
338 int x, int y);
339 static void customPaletteMenuCallback(WMWidget *w, void *data);
340 static void customPaletteHistoryCallback(WMWidget *w, void *data);
342 static void customPaletteMenuNewFromFile(W_ColorPanel *panel);
343 static void customPaletteMenuRename(W_ColorPanel *panel);
344 static void customPaletteMenuRemove(W_ColorPanel *panel);
346 static void colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text,
347 int state, WMRect *rect);
348 static void colorListSelect(WMWidget *w, void *data);
349 static void colorListColorMenuCallback(WMWidget *w, void *data);
350 static void colorListListMenuCallback(WMWidget *w, void *data);
351 static void colorListListMenuNew(W_ColorPanel *panel);
353 static void wheelInit(W_ColorPanel *panel);
354 static void grayInit(W_ColorPanel *panel);
355 static void rgbInit(W_ColorPanel *panel);
356 static void cmykInit(W_ColorPanel *panel);
357 static void hsbInit(W_ColorPanel *panel);
361 void
362 WMSetColorPanelAction(WMColorPanel *panel, WMAction2 *action, void *data)
364 panel->action = action;
365 panel->clientData = data;
368 static WMColorPanel*
369 makeColorPanel(WMScreen *scrPtr, char *name)
371 WMColorPanel *panel;
372 RImage *image;
373 WMPixmap *pixmap;
374 RColor from;
375 RColor to;
376 WMColor *textcolor;
377 int i;
378 int x,y;
381 panel = wmalloc(sizeof(WMColorPanel));
382 memset(panel, 0, sizeof(WMColorPanel));
384 panel->colorSet = False; /* Color has not been set yet */
386 panel->font8 = WMSystemFontOfSize(scrPtr, 8);
387 panel->font12 = WMSystemFontOfSize(scrPtr, 12);
389 panel->win = WMCreateWindowWithStyle(scrPtr, name,
390 WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
391 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
392 WMSetWindowTitle(panel->win, "Colors");
393 WMSetWindowCloseAction(panel->win, closeWindowCallback, panel);
396 /* Set Default ColorPanel Mode(s) */
397 panel->mode = WMWheelModeColorPanel;
398 panel->lastChanged = WMWheelModeColorPanel;
399 panel->slidersmode = WMRGBModeColorPanel;
400 panel->configurationPath = wstrappend(wusergnusteppath(),
401 "/Library/Colors/");
403 /* Some General Purpose Widgets */
404 panel->colorWell = WMCreateColorWell(panel->win);
405 WMResizeWidget(panel->colorWell, 134, 36);
406 WSetColorWellBordered(panel->colorWell, False);
407 WMMoveWidget(panel->colorWell, 56, 4);
409 panel->magnifyBtn = WMCreateCustomButton(panel->win,
410 WBBStateLightMask|WBBStateChangeMask);
411 WMResizeWidget(panel->magnifyBtn, 46, 36);
412 WMMoveWidget(panel->magnifyBtn, 6,4);
413 WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
414 WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
415 WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
417 panel->wheelBtn = WMCreateCustomButton(panel->win,
418 WBBStateLightMask|WBBStateChangeMask);
419 WMResizeWidget(panel->wheelBtn, 46, 32);
420 WMMoveWidget(panel->wheelBtn, 6, 44);
421 WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
422 WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
423 WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
425 panel->slidersBtn = WMCreateCustomButton(panel->win,
426 WBBStateLightMask|WBBStateChangeMask);
427 WMResizeWidget(panel->slidersBtn, 46, 32);
428 WMMoveWidget(panel->slidersBtn, 52, 44);
429 WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
430 WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
431 WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
433 panel->customPaletteBtn = WMCreateCustomButton(panel->win,
434 WBBStateLightMask|WBBStateChangeMask);
435 WMResizeWidget(panel->customPaletteBtn, 46, 32);
436 WMMoveWidget(panel->customPaletteBtn, 98, 44);
437 WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
438 WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
439 WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
441 panel->colorListBtn = WMCreateCustomButton(panel->win,
442 WBBStateLightMask|WBBStateChangeMask);
443 WMResizeWidget(panel->colorListBtn, 46, 32);
444 WMMoveWidget(panel->colorListBtn, 144, 44);
445 WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
446 WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
447 WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
449 /* Let's Group some of them together */
450 WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
451 WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
452 WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
454 /* Widgets for the ColorWheel Panel */
455 panel->wheelFrm = WMCreateFrame(panel->win);
456 WMSetFrameRelief(panel->wheelFrm, WRFlat);
457 WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
458 WMMoveWidget(panel->wheelFrm, 5, 80);
460 panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
461 /* XXX Can we create a view ? */
462 W_ResizeView(panel->wheelView, colorWheelSize+4, colorWheelSize+4);
463 W_MoveView(panel->wheelView, 0, 0);
465 /* Create an event handler to handle expose/click events in ColorWheel */
466 WMCreateEventHandler(panel->wheelView,
467 ButtonPressMask|ButtonReleaseMask|EnterWindowMask|
468 LeaveWindowMask|ButtonMotionMask, wheelHandleActionEvents, panel);
470 WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents,
471 panel);
473 panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
474 WMResizeWidget(panel->wheelBrightnessS, 16, 153);
475 WMMoveWidget(panel->wheelBrightnessS, 5+colorWheelSize+14, 1);
476 WMSetSliderMinValue(panel->wheelBrightnessS, 0);
477 WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
478 WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback,
479 panel);
480 WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
483 /* Widgets for the Slider Panels */
484 panel->slidersFrm = WMCreateFrame(panel->win);
485 WMSetFrameRelief(panel->slidersFrm, WRFlat);
486 WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
487 WMMoveWidget(panel->slidersFrm, 4, 80);
489 panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
490 WMSetFrameRelief(panel->seperatorFrm, WRPushed);
491 WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
492 WMMoveWidget(panel->seperatorFrm, 0, 1);
494 panel->grayBtn = WMCreateCustomButton(panel->slidersFrm,
495 WBBStateLightMask|WBBStateChangeMask);
496 WMResizeWidget(panel->grayBtn, 46, 24);
497 WMMoveWidget(panel->grayBtn, 1, 8);
498 WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
499 WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
500 WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
502 panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm,
503 WBBStateLightMask|WBBStateChangeMask);
504 WMResizeWidget(panel->rgbBtn, 46, 24);
505 WMMoveWidget(panel->rgbBtn, 47, 8);
506 WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
507 WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
508 WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
510 panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm,
511 WBBStateLightMask|WBBStateChangeMask);
512 WMResizeWidget(panel->cmykBtn, 46, 24);
513 WMMoveWidget(panel->cmykBtn, 93, 8);
514 WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
515 WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
516 WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
518 panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm,
519 WBBStateLightMask|WBBStateChangeMask);
520 WMResizeWidget(panel->hsbBtn, 46, 24);
521 WMMoveWidget(panel->hsbBtn, 139, 8);
522 WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
523 WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
524 WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
526 /* Let's Group the Slider Panel Buttons Together */
527 WMGroupButtons(panel->grayBtn, panel->rgbBtn);
528 WMGroupButtons(panel->grayBtn, panel->cmykBtn);
529 WMGroupButtons(panel->grayBtn, panel->hsbBtn);
531 textcolor = WMDarkGrayColor(scrPtr);
533 /* Widgets for GrayScale Panel */
534 panel->grayFrm = WMCreateFrame(panel->slidersFrm);
535 WMSetFrameRelief(panel->grayFrm, WRFlat);
536 WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
537 WMMoveWidget(panel->grayFrm, 0, 34);
539 panel->grayMinL = WMCreateLabel(panel->grayFrm);
540 WMResizeWidget(panel->grayMinL, 20, 10);
541 WMMoveWidget(panel->grayMinL, 2, 2);
542 WMSetLabelText(panel->grayMinL, "0");
543 WMSetLabelTextAlignment(panel->grayMinL, WALeft);
544 WMSetLabelTextColor(panel->grayMinL, textcolor);
545 WMSetLabelFont(panel->grayMinL, panel->font8);
547 panel->grayMaxL = WMCreateLabel(panel->grayFrm);
548 WMResizeWidget(panel->grayMaxL, 40, 10);
549 WMMoveWidget(panel->grayMaxL, 104, 2);
550 WMSetLabelText(panel->grayMaxL, "100");
551 WMSetLabelTextAlignment(panel->grayMaxL, WARight);
552 WMSetLabelTextColor(panel->grayMaxL, textcolor);
553 WMSetLabelFont(panel->grayMaxL, panel->font8);
555 panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
556 WMResizeWidget(panel->grayBrightnessS, 141, 16);
557 WMMoveWidget(panel->grayBrightnessS, 2, 14);
558 WMSetSliderMinValue(panel->grayBrightnessS, 0);
559 WMSetSliderMaxValue(panel->grayBrightnessS, 100);
560 WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
561 WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback,
562 panel);
564 from.red = 0;
565 from.green = 0;
566 from.blue = 0;
568 to.red = 255;
569 to.green = 255;
570 to.blue = 255;
572 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
573 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
574 RDestroyImage(image);
575 W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap,
576 panel->font12, 2, 0, 100, WALeft, WMColorGC(scrPtr->white),
577 False, "Brightness", strlen("Brightness"));
578 WMSetSliderImage(panel->grayBrightnessS, pixmap);
579 WMReleasePixmap(pixmap);
581 panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
582 WMResizeWidget(panel->grayBrightnessT, 40, 18);
583 WMMoveWidget(panel->grayBrightnessT, 146, 13);
584 WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
585 WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel,
586 WMTextDidEndEditingNotification, panel->grayBrightnessT);
588 image = RCreateImage(13,13,False);
589 for (i=0; i < 7; i++) {
590 for (x=0; x < 13; x++) {
591 for (y=0; y < 13; y++) {
592 image->data[0][y*13+x] = 255/6*i;
593 image->data[1][y*13+x] = 255/6*i;
594 image->data[2][y*13+x] = 255/6*i;
597 panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
598 WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
599 WMMoveWidget(panel->grayPresetBtn[i], 2+(i*20), 34);
600 WMSetButtonAction(panel->grayPresetBtn[i],
601 grayPresetButtonCallback, panel);
602 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
603 WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
604 WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
605 WMReleasePixmap(pixmap);
607 RDestroyImage(image);
608 /* End of GrayScale Panel */
610 /* Widgets for RGB Panel */
611 panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
612 WMSetFrameRelief(panel->rgbFrm, WRFlat);
613 WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
614 WMMoveWidget(panel->rgbFrm, 0, 34);
616 panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
617 WMResizeWidget(panel->rgbMinL, 20, 10);
618 WMMoveWidget(panel->rgbMinL, 2, 2);
619 WMSetLabelText(panel->rgbMinL, "0");
620 WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
621 WMSetLabelTextColor(panel->rgbMinL, textcolor);
622 WMSetLabelFont(panel->rgbMinL, panel->font8);
624 panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
625 WMResizeWidget(panel->rgbMaxL, 40, 10);
626 WMMoveWidget(panel->rgbMaxL, 104, 2);
627 WMSetLabelText(panel->rgbMaxL, "255");
628 WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
629 WMSetLabelTextColor(panel->rgbMaxL, textcolor);
630 WMSetLabelFont(panel->rgbMaxL, panel->font8);
632 panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
633 WMResizeWidget(panel->rgbRedS, 141, 16);
634 WMMoveWidget(panel->rgbRedS, 2, 14);
635 WMSetSliderMinValue(panel->rgbRedS, 0);
636 WMSetSliderMaxValue(panel->rgbRedS, 255);
637 WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
638 WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
640 to.red = 255;
641 to.green = 0;
642 to.blue = 0;
644 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
645 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
646 W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12, 2, 0,
647 100, WALeft, WMColorGC(scrPtr->white), False, "Red", strlen("Red"));
648 RDestroyImage(image);
649 WMSetSliderImage(panel->rgbRedS, pixmap);
650 WMReleasePixmap(pixmap);
652 panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
653 WMResizeWidget(panel->rgbRedT, 40, 18);
654 WMMoveWidget(panel->rgbRedT, 146, 13);
655 WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
656 WMAddNotificationObserver(rgbTextFieldCallback, panel,
657 WMTextDidEndEditingNotification, panel->rgbRedT);
659 panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
660 WMResizeWidget(panel->rgbGreenS, 141, 16);
661 WMMoveWidget(panel->rgbGreenS, 2, 36);
662 WMSetSliderMinValue(panel->rgbGreenS, 0);
663 WMSetSliderMaxValue(panel->rgbGreenS, 255);
664 WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
665 WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
667 to.red = 0;
668 to.green = 255;
669 to.blue = 0;
671 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
672 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
673 W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12, 2, 0,
674 100, WALeft, WMColorGC(scrPtr->white), False, "Green",
675 strlen("Green"));
676 RDestroyImage(image);
677 WMSetSliderImage(panel->rgbGreenS, pixmap);
678 WMReleasePixmap(pixmap);
680 panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
681 WMResizeWidget(panel->rgbGreenT, 40, 18);
682 WMMoveWidget(panel->rgbGreenT, 146, 35);
683 WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
684 WMAddNotificationObserver(rgbTextFieldCallback, panel,
685 WMTextDidEndEditingNotification, panel->rgbGreenT);
688 panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
689 WMResizeWidget(panel->rgbBlueS, 141, 16);
690 WMMoveWidget(panel->rgbBlueS, 2, 58);
691 WMSetSliderMinValue(panel->rgbBlueS, 0);
692 WMSetSliderMaxValue(panel->rgbBlueS, 255);
693 WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
694 WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
696 to.red = 0;
697 to.green = 0;
698 to.blue = 255;
700 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
701 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
702 W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12, 2, 0,
703 100, WALeft, WMColorGC(scrPtr->white), False, "Blue",
704 strlen("Blue"));
705 RDestroyImage(image);
706 WMSetSliderImage(panel->rgbBlueS, pixmap);
707 WMReleasePixmap(pixmap);
709 panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
710 WMResizeWidget(panel->rgbBlueT, 40, 18);
711 WMMoveWidget(panel->rgbBlueT, 146, 57);
712 WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
713 WMAddNotificationObserver(rgbTextFieldCallback, panel,
714 WMTextDidEndEditingNotification, panel->rgbBlueT);
715 /* End of RGB Panel */
717 /* Widgets for CMYK Panel */
718 panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
719 WMSetFrameRelief(panel->cmykFrm, WRFlat);
720 WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
721 WMMoveWidget(panel->cmykFrm, 0, 34);
723 panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
724 WMResizeWidget(panel->cmykMinL, 20, 10);
725 WMMoveWidget(panel->cmykMinL, 2, 2);
726 WMSetLabelText(panel->cmykMinL, "0");
727 WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
728 WMSetLabelTextColor(panel->cmykMinL, textcolor);
729 WMSetLabelFont(panel->cmykMinL, panel->font8);
731 panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
732 WMResizeWidget(panel->cmykMaxL, 40, 10);
733 WMMoveWidget(panel->cmykMaxL, 104, 2);
734 WMSetLabelText(panel->cmykMaxL, "100");
735 WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
736 WMSetLabelTextColor(panel->cmykMaxL, textcolor);
737 WMSetLabelFont(panel->cmykMaxL, panel->font8);
739 panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
740 WMResizeWidget(panel->cmykCyanS, 141, 16);
741 WMMoveWidget(panel->cmykCyanS, 2, 14);
742 WMSetSliderMinValue(panel->cmykCyanS, 0);
743 WMSetSliderMaxValue(panel->cmykCyanS, 100);
744 WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
745 WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
747 from.red = 255;
748 from.green = 255;
749 from.blue = 255;
751 to.red = 0;
752 to.green = 255;
753 to.blue = 255;
755 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
756 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
757 W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12, 2, 0,
758 100, WALeft, WMColorGC(scrPtr->black), False, "Cyan",
759 strlen("Cyan"));
760 RDestroyImage(image);
761 WMSetSliderImage(panel->cmykCyanS, pixmap);
762 WMReleasePixmap(pixmap);
764 panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
765 WMResizeWidget(panel->cmykCyanT, 40, 18);
766 WMMoveWidget(panel->cmykCyanT, 146, 13);
767 WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
768 WMAddNotificationObserver(cmykTextFieldCallback, panel,
769 WMTextDidEndEditingNotification, panel->cmykCyanT);
772 panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
773 WMResizeWidget(panel->cmykMagentaS, 141, 16);
774 WMMoveWidget(panel->cmykMagentaS, 2, 36);
775 WMSetSliderMinValue(panel->cmykMagentaS, 0);
776 WMSetSliderMaxValue(panel->cmykMagentaS, 100);
777 WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
778 WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
780 to.red = 255;
781 to.green = 0;
782 to.blue = 255;
784 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
785 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
786 W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12, 2,
787 0, 100, WALeft, WMColorGC(scrPtr->black), False, "Magenta",
788 strlen("Magenta"));
789 RDestroyImage(image);
790 WMSetSliderImage(panel->cmykMagentaS, pixmap);
791 WMReleasePixmap(pixmap);
793 panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
794 WMResizeWidget(panel->cmykMagentaT, 40, 18);
795 WMMoveWidget(panel->cmykMagentaT, 146, 35);
796 WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
797 WMAddNotificationObserver(cmykTextFieldCallback, panel,
798 WMTextDidEndEditingNotification, panel->cmykMagentaT);
801 panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
802 WMResizeWidget(panel->cmykYellowS, 141, 16);
803 WMMoveWidget(panel->cmykYellowS, 2, 58);
804 WMSetSliderMinValue(panel->cmykYellowS, 0);
805 WMSetSliderMaxValue(panel->cmykYellowS, 100);
806 WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
807 WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
809 to.red = 255;
810 to.green = 255;
811 to.blue = 0;
813 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
814 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
815 W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12, 2, 0,
816 100, WALeft, WMColorGC(scrPtr->black), False, "Yellow",
817 strlen("Yellow"));
818 RDestroyImage(image);
819 WMSetSliderImage(panel->cmykYellowS, pixmap);
820 WMReleasePixmap(pixmap);
822 panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
823 WMResizeWidget(panel->cmykYellowT, 40, 18);
824 WMMoveWidget(panel->cmykYellowT, 146, 57);
825 WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
826 WMAddNotificationObserver(cmykTextFieldCallback, panel,
827 WMTextDidEndEditingNotification, panel->cmykYellowT);
830 panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
831 WMResizeWidget(panel->cmykBlackS, 141, 16);
832 WMMoveWidget(panel->cmykBlackS, 2, 80);
833 WMSetSliderMinValue(panel->cmykBlackS, 0);
834 WMSetSliderMaxValue(panel->cmykBlackS, 100);
835 WMSetSliderValue(panel->cmykBlackS, 0);
836 WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
837 WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
839 to.red = 0;
840 to.green = 0;
841 to.blue = 0;
843 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
844 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
845 W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12, 2, 0,
846 100, WALeft, WMColorGC(scrPtr->black), False, "Black",
847 strlen("Black"));
848 RDestroyImage(image);
849 WMSetSliderImage(panel->cmykBlackS, pixmap);
850 WMReleasePixmap(pixmap);
852 panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
853 WMResizeWidget(panel->cmykBlackT, 40, 18);
854 WMMoveWidget(panel->cmykBlackT, 146, 79);
855 WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
856 WMAddNotificationObserver(cmykTextFieldCallback, panel,
857 WMTextDidEndEditingNotification, panel->cmykBlackT);
858 /* End of CMYK Panel */
860 /* Widgets for HSB Panel */
861 panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
862 WMSetFrameRelief(panel->hsbFrm, WRFlat);
863 WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
864 WMMoveWidget(panel->hsbFrm, 0, 34);
866 panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
867 WMResizeWidget(panel->hsbHueS, 141, 16);
868 WMMoveWidget(panel->hsbHueS, 2, 14);
869 WMSetSliderMinValue(panel->hsbHueS, 0);
870 WMSetSliderMaxValue(panel->hsbHueS, 359);
871 WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
872 WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
874 panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
875 WMResizeWidget(panel->hsbHueT, 40, 18);
876 WMMoveWidget(panel->hsbHueT, 146, 13);
877 WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
878 WMAddNotificationObserver(hsbTextFieldCallback, panel,
879 WMTextDidEndEditingNotification, panel->hsbHueT);
882 panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
883 WMResizeWidget(panel->hsbSaturationS, 141, 16);
884 WMMoveWidget(panel->hsbSaturationS, 2, 36);
885 WMSetSliderMinValue(panel->hsbSaturationS, 0);
886 WMSetSliderMaxValue(panel->hsbSaturationS, 100);
887 WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
888 WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
890 panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
891 WMResizeWidget(panel->hsbSaturationT, 40, 18);
892 WMMoveWidget(panel->hsbSaturationT, 146, 35);
893 WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
894 WMAddNotificationObserver(hsbTextFieldCallback, panel,
895 WMTextDidEndEditingNotification, panel->hsbSaturationT);
898 panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
899 WMResizeWidget(panel->hsbBrightnessS, 141, 16);
900 WMMoveWidget(panel->hsbBrightnessS, 2, 58);
901 WMSetSliderMinValue(panel->hsbBrightnessS, 0);
902 WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
903 WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
904 WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
906 panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
907 WMResizeWidget(panel->hsbBrightnessT, 40, 18);
908 WMMoveWidget(panel->hsbBrightnessT, 146, 57);
909 WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
910 WMAddNotificationObserver(hsbTextFieldCallback, panel,
911 WMTextDidEndEditingNotification, panel->hsbBrightnessT);
912 /* End of HSB Panel */
915 WMReleaseColor(textcolor);
917 /* Widgets for the CustomPalette Panel */
918 panel->customPaletteFrm = WMCreateFrame(panel->win);
919 WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
920 WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
921 WMMoveWidget(panel->customPaletteFrm, 5, 80);
923 panel->customPaletteHistoryBtn = WMCreatePopUpButton(
924 panel->customPaletteFrm);
925 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, "Spectrum");
926 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
927 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn)-1);
928 WMSetPopUpButtonAction(panel->customPaletteHistoryBtn,
929 customPaletteHistoryCallback, panel);
930 WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
931 WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
933 panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
934 WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
935 WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
936 WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
938 panel->customPaletteContentView = W_CreateView(
939 W_VIEW(panel->customPaletteContentFrm));
940 /* XXX Test if we can create a view */
941 W_ResizeView(panel->customPaletteContentView, customPaletteWidth,
942 customPaletteHeight);
943 W_MoveView(panel->customPaletteContentView, 2, 2);
945 /* Create event handler to handle expose/click events in CustomPalette */
946 WMCreateEventHandler(panel->customPaletteContentView,
947 ButtonPressMask|ButtonReleaseMask|EnterWindowMask| LeaveWindowMask |
948 ButtonMotionMask, customPaletteHandleActionEvents, panel);
950 WMCreateEventHandler(panel->customPaletteContentView, ExposureMask,
951 customPaletteHandleEvents, panel);
953 panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
954 WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
955 WMSetPopUpButtonText(panel->customPaletteMenuBtn, "Palette");
956 WMSetPopUpButtonAction(panel->customPaletteMenuBtn,
957 customPaletteMenuCallback, panel);
958 WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
959 WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
961 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "New from File...");
962 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "Rename...");
963 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "Remove");
964 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "Copy");
965 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "New from Clipboard");
967 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, 0);
968 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, 0);
969 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuCopy, 0);
970 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn,
971 CPmenuNewFromClipboard, 0);
973 customRenderSpectrum(panel);
974 panel->currentPalette = 0;
977 /* Widgets for the ColorList Panel */
978 panel->colorListFrm = WMCreateFrame(panel->win);
979 WMSetFrameRelief(panel->colorListFrm, WRFlat);
980 WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
981 WMMoveWidget(panel->colorListFrm, 5, 80);
983 panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
984 WMAddPopUpButtonItem(panel->colorListHistoryBtn, "X11-Colors");
985 WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn,
986 WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn)-1);
987 /* WMSetPopUpButtonAction(panel->colorListHistoryBtn,
988 * colorListHistoryCallback, panel); */
989 WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
990 WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
992 panel->colorListContentLst = WMCreateList(panel->colorListFrm);
993 WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
994 WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
995 WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
996 WMMoveWidget(panel->colorListContentLst, 0, 23);
997 WMHangData(panel->colorListContentLst, panel);
999 panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1000 WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
1001 WMSetPopUpButtonText(panel->colorListColorMenuBtn, "Color");
1002 WMSetPopUpButtonAction(panel->colorListColorMenuBtn,
1003 colorListColorMenuCallback, panel);
1004 WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16)/2, 20);
1005 WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
1007 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, "Add...");
1008 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, "Rename...");
1009 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, "Remove");
1011 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuAdd, 0);
1012 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRename, 0);
1013 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRemove, 0);
1015 panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1016 WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
1017 WMSetPopUpButtonText(panel->colorListListMenuBtn, "List");
1018 WMSetPopUpButtonAction(panel->colorListListMenuBtn,
1019 colorListListMenuCallback, panel);
1020 WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16)/2, 20);
1021 WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16)/2 + 8,
1022 PHEIGHT - 130);
1024 WMAddPopUpButtonItem(panel->colorListListMenuBtn, "New...");
1025 WMAddPopUpButtonItem(panel->colorListListMenuBtn, "Rename...");
1026 WMAddPopUpButtonItem(panel->colorListListMenuBtn, "Remove");
1028 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
1029 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
1031 WMRealizeWidget(panel->win);
1032 WMMapSubwidgets(panel->win);
1034 WMMapSubwidgets(panel->wheelFrm);
1035 WMMapSubwidgets(panel->slidersFrm);
1036 WMMapSubwidgets(panel->grayFrm);
1037 WMMapSubwidgets(panel->rgbFrm);
1038 WMMapSubwidgets(panel->cmykFrm);
1039 WMMapSubwidgets(panel->hsbFrm);
1040 WMMapSubwidgets(panel->customPaletteFrm);
1041 WMMapSubwidgets(panel->customPaletteContentFrm);
1042 WMMapSubwidgets(panel->colorListFrm);
1044 readConfiguration(panel);
1045 readXColors(panel);
1047 return panel;
1051 WMColorPanel*
1052 WMGetColorPanel(WMScreen *scrPtr)
1054 WMColorPanel *panel;
1056 if (scrPtr->sharedColorPanel)
1057 return scrPtr->sharedColorPanel;
1059 panel = makeColorPanel(scrPtr, "colorPanel");
1061 scrPtr->sharedColorPanel = panel;
1063 return panel;
1067 void
1068 WMFreeColorPanel(WMColorPanel *panel)
1070 W_Screen *scr = WMWidgetScreen(panel->win);
1072 if (panel == scr->sharedColorPanel) {
1073 scr->sharedColorPanel = NULL;
1076 WMRemoveNotificationObserver(panel);
1077 WMUnmapWidget(panel->win);
1079 /* fonts */
1080 if (panel->font8)
1081 WMReleaseFont(panel->font8);
1082 if (panel->font12)
1083 WMReleaseFont(panel->font12);
1085 /* pixmaps */
1086 if (panel->wheelMtrx)
1087 wheelDestroyMatrix(panel->wheelMtrx);
1088 if (panel->wheelImg)
1089 XFreePixmap(scr->display, panel->wheelImg);
1090 if (panel->selectionImg)
1091 XFreePixmap(scr->display, panel->selectionImg);
1092 if (panel->selectionBackImg)
1093 XFreePixmap(scr->display, panel->selectionBackImg);
1094 if (panel->customPaletteImg)
1095 RDestroyImage(panel->customPaletteImg);
1097 /* structs */
1098 if (panel->lastBrowseDir)
1099 wfree(panel->lastBrowseDir);
1100 if (panel->configurationPath)
1101 wfree(panel->configurationPath);
1103 WMDestroyWidget(panel->win);
1105 wfree(panel);
1109 void
1110 WMCloseColorPanel(WMColorPanel *panel)
1112 WMFreeColorPanel(panel);
1116 void
1117 WMShowColorPanel(WMColorPanel *panel)
1119 WMScreen *scr = WMWidgetScreen(panel->win);
1120 WMColor *white = WMWhiteColor(scr);
1122 if (!panel->colorSet )
1123 WMSetColorPanelColor(panel, white);
1124 WMReleaseColor(white);
1126 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1127 wheelInit(panel);
1129 WMMapWidget(panel->win);
1133 static void
1134 closeWindowCallback(WMWidget *w, void *data)
1136 W_ColorPanel *panel = (W_ColorPanel*)data;
1138 WMCloseColorPanel(panel);
1142 static void
1143 readConfiguration(W_ColorPanel *panel)
1145 /* XXX Doesn't take care of "invalid" files */
1147 DIR *dPtr;
1148 struct dirent *dp;
1149 struct stat stat_buf;
1152 if (stat(panel->configurationPath, &stat_buf)!=0) {
1153 if (mkdir(panel->configurationPath,
1154 S_IRWXU|S_IRGRP|S_IROTH|S_IXGRP|S_IXOTH)!=0) {
1155 wsyserror("ColorPanel could not create directory %s needed"
1156 " to store configurations", panel->configurationPath);
1157 WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
1158 WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
1159 WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
1160 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1161 "File Error",
1162 "Could not create ColorPanel configuration directory",
1163 "OK", NULL, NULL);
1165 return;
1168 dPtr = opendir(panel->configurationPath);
1169 while ((dp = readdir(dPtr)) != NULL) {
1170 if (dp->d_name[0] != '.')
1171 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
1173 (void)closedir(dPtr);
1177 static void
1178 readXColors(W_ColorPanel *panel)
1180 struct stat stat_buf;
1181 FILE *rgbtxt;
1182 char line[MAX_LENGTH];
1183 int red, green, blue;
1184 char name[48];
1185 RColor *color;
1186 WMListItem *item;
1188 if (stat(RGBTXT, &stat_buf) != 0) {
1189 wwarning("Cannot find file %s", RGBTXT);
1190 return;
1192 else {
1193 rgbtxt = fopen(RGBTXT, "r");
1194 if (rgbtxt) {
1195 while (fgets(line, MAX_LENGTH, rgbtxt)) {
1196 if (sscanf(line, "%d%d%d %[^\n]", &red, &green, &blue, name)) {
1197 color = wmalloc(sizeof(RColor));
1198 color->red = (unsigned char)red;
1199 color->green = (unsigned char)green;
1200 color->blue = (unsigned char)blue;
1201 item = WMAddListItem(panel->colorListContentLst, name);
1202 item->clientData = (void *)color;
1205 fclose(rgbtxt);
1207 else {
1208 wsyserror("Unable to open file %s for reading", RGBTXT);
1214 void
1215 WMSetColorPanelPickerMode(WMColorPanel *panel, WMColorPanelMode mode)
1217 W_Screen *scr = WMWidgetScreen(panel->win);
1219 if (mode != WMWheelModeColorPanel) {
1220 WMUnmapWidget(panel->wheelFrm);
1221 if (panel->selectionBackImg) {
1222 XFreePixmap(WMWidgetScreen(panel->win)->display,
1223 panel->selectionBackImg);
1224 panel->selectionBackImg = None;
1227 if (mode != WMGrayModeColorPanel)
1228 WMUnmapWidget(panel->grayFrm);
1229 if (mode != WMRGBModeColorPanel)
1230 WMUnmapWidget(panel->rgbFrm);
1231 if (mode != WMCMYKModeColorPanel)
1232 WMUnmapWidget(panel->cmykFrm);
1233 if (mode != WMHSBModeColorPanel)
1234 WMUnmapWidget(panel->hsbFrm);
1235 if (mode != WMCustomPaletteModeColorPanel) {
1236 WMUnmapWidget(panel->customPaletteFrm);
1237 if (panel->selectionBackImg) {
1238 XFreePixmap(WMWidgetScreen(panel->win)->display,
1239 panel->selectionBackImg);
1240 panel->selectionBackImg = None;
1243 if (mode != WMColorListModeColorPanel)
1244 WMUnmapWidget(panel->colorListFrm);
1245 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
1246 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1247 WMUnmapWidget(panel->slidersFrm);
1248 else
1249 panel->slidersmode = mode;
1251 if (mode == WMWheelModeColorPanel) {
1252 WMMapWidget(panel->wheelFrm);
1253 WMSetButtonSelected(panel->wheelBtn, True);
1254 if (panel->lastChanged != WMWheelModeColorPanel)
1255 wheelInit(panel);
1256 wheelRender(panel);
1257 wheelPaint(panel);
1258 } else if (mode == WMGrayModeColorPanel) {
1259 WMMapWidget(panel->slidersFrm);
1260 WMSetButtonSelected(panel->slidersBtn, True);
1261 WMMapWidget(panel->grayFrm);
1262 WMSetButtonSelected(panel->grayBtn, True);
1263 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1264 if (panel->lastChanged != WMGrayModeColorPanel)
1265 grayInit(panel);
1266 } else if (mode == WMRGBModeColorPanel) {
1267 WMMapWidget(panel->slidersFrm);
1268 WMSetButtonSelected(panel->slidersBtn, True);
1269 WMMapWidget(panel->rgbFrm);
1270 WMSetButtonSelected(panel->rgbBtn, True);
1271 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1272 if (panel->lastChanged != WMRGBModeColorPanel)
1273 rgbInit(panel);
1274 } else if (mode == WMCMYKModeColorPanel) {
1275 WMMapWidget(panel->slidersFrm);
1276 WMSetButtonSelected(panel->slidersBtn, True);
1277 WMMapWidget(panel->cmykFrm);
1278 WMSetButtonSelected(panel->cmykBtn, True);
1279 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1280 if (panel->lastChanged != WMCMYKModeColorPanel)
1281 cmykInit(panel);
1282 } else if (mode == WMHSBModeColorPanel) {
1283 WMMapWidget(panel->slidersFrm);
1284 WMSetButtonSelected(panel->slidersBtn, True);
1285 WMMapWidget(panel->hsbFrm);
1286 WMSetButtonSelected(panel->hsbBtn, True);
1287 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1288 if (panel->lastChanged != WMHSBModeColorPanel)
1289 hsbInit(panel);
1290 } else if (mode == WMCustomPaletteModeColorPanel) {
1291 WMMapWidget(panel->customPaletteFrm);
1292 WMSetButtonSelected(panel->customPaletteBtn, True);
1293 customSetPalette(panel);
1294 } else if (mode == WMColorListModeColorPanel) {
1295 WMMapWidget(panel->colorListFrm);
1296 WMSetButtonSelected(panel->colorListBtn, True);
1299 panel->mode = mode;
1303 WMColor*
1304 WMGetColorPanelColor(WMColorPanel *panel)
1306 return WMGetColorWellColor(panel->colorWell);
1310 void
1311 WMSetColorPanelColor(WMColorPanel *panel, WMColor *color)
1313 WMScreen *scr = WMWidgetScreen(panel->win);
1314 RHSVColor hsvcolor;
1315 RColor intcolor;
1316 GC bgc = WMColorGC(scr->black);
1317 GC wgc = WMColorGC(scr->white);
1318 int originalHue;
1320 WMSetColorWellColor(panel->colorWell, color);
1322 intcolor.red = color->color.red >> 8;
1323 intcolor.green = color->color.green >> 8;
1324 intcolor.blue = color->color.blue >> 8;
1326 panel->color = intcolor;
1327 panel->colorSet = True;
1329 /* If color was set by HSB-Panel do not convert back to hsv */
1330 if (panel->lastChanged != WMHSBModeColorPanel) {
1332 /* if color is black, hue is undetermined, so it must be restored */
1333 if ((panel->color.red == 0) &&
1334 (panel->color.green == 0) &&
1335 (panel->color.blue == 0) &&
1336 (panel->hsvcolor.hue <= 359))
1338 originalHue = panel->hsvcolor.hue;
1339 RRGBtoHSV(&panel->color, &panel->hsvcolor);
1340 panel->hsvcolor.hue = originalHue;
1341 } else {
1342 RRGBtoHSV(&panel->color, &panel->hsvcolor);
1346 panel->wheelMtrx = wheelInitMatrix(panel); /* Needs to be done After Color is set */
1348 /* Maybe put this in a sub-function ... Initialising selected images */
1349 RRGBtoHSV(&intcolor, &hsvcolor);
1350 panel->colx = 2 + rint((colorWheelSize / 2.0) * (1 +
1351 (hsvcolor.saturation/255.0) * cos( hsvcolor.hue*M_PI/180.0)));
1352 panel->coly = 2 + rint((colorWheelSize / 2.0) * (1 +
1353 (hsvcolor.saturation/255.0) * sin(-hsvcolor.hue*M_PI/180.0)));
1354 wheelUpdateBrightnessGradientFromHSV(panel, hsvcolor);
1355 WMSetSliderValue(panel->wheelBrightnessS, 255 - hsvcolor.value);
1357 panel->selectionImg = XCreatePixmap(scr->display,
1358 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
1359 XFillRectangle(scr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1360 XFillRectangle(scr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1361 /* End of initialisation section */
1363 panel->palx = customPaletteWidth/2;
1364 panel->paly = customPaletteHeight/2;
1366 WMSetColorPanelPickerMode(panel, panel->mode);
1370 static void
1371 updateSwatch(WMColorPanel *panel, RColor color)
1373 WMScreen *scr = WMWidgetScreen(panel->win);
1374 WMColor *wellcolor;
1375 int originalHue;
1377 wellcolor = WMCreateRGBColor(scr, color.red << 8, color.green << 8,
1378 color.blue << 8, True);
1380 WMSetColorWellColor(panel->colorWell, wellcolor);
1381 WMReleaseColor(wellcolor);
1383 panel->color = color;
1385 /* If color was set by HSB-Panel do not convert back to hsv */
1386 if (panel->lastChanged != WMHSBModeColorPanel) {
1388 /* if color is black, hue is undetermined, so it must be restored */
1389 if ((panel->color.red == 0) &&
1390 (panel->color.green == 0) &&
1391 (panel->color.blue == 0) &&
1392 (panel->hsvcolor.hue <= 359))
1394 originalHue = panel->hsvcolor.hue;
1395 RRGBtoHSV(&panel->color, &panel->hsvcolor);
1396 panel->hsvcolor.hue = originalHue;
1397 } else {
1398 RRGBtoHSV(&panel->color, &panel->hsvcolor);
1402 if (!panel->flags.dragging || panel->flags.continuous) {
1403 if (panel->action)
1404 (*panel->action)(panel, panel->clientData);
1406 WMPostNotificationName(WMColorPanelColorChangedNotification, panel,
1407 NULL);
1411 static void
1412 modeButtonCallback(WMWidget *w, void *data)
1414 W_ColorPanel *panel = (W_ColorPanel*)(data);
1416 if (w == panel->wheelBtn)
1417 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1418 else if (w == panel->slidersBtn)
1419 WMSetColorPanelPickerMode(panel, panel->slidersmode);
1420 else if (w == panel->customPaletteBtn)
1421 WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
1422 else if (w == panel->colorListBtn)
1423 WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
1424 else if (w == panel->grayBtn)
1425 WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
1426 else if (w == panel->rgbBtn)
1427 WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
1428 else if (w == panel->cmykBtn)
1429 WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
1430 else if (w == panel->hsbBtn)
1431 WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
1435 /****************** Magnifying Cursor Functions *******************/
1437 static XImage*
1438 magnifyGetImage(WMScreen *scr, XImage *image, int x, int y, int w, int h)
1440 int x0 = 0, y0 = 0, w0 = w, h0 = h;
1441 const int displayWidth = DisplayWidth(scr->display, scr->screen),
1442 displayHeight = DisplayHeight(scr->display, scr->screen);
1444 if (!(image && image->data)) {
1445 /* The image in panel->magnifyGlass->image does not exist yet.
1446 * Grab one from the screen (not beyond) and use it from now on.
1448 if (!(image = XGetImage(scr->display, scr->rootWin,
1449 x - Cursor_x_hot,
1450 y - Cursor_y_hot,
1451 w, h, AllPlanes, ZPixmap)))
1452 wwarning("ColorPanel: X said I cannot grab an image from screen.");
1454 return image;
1457 /* Coordinate correction for back pixmap
1458 * if magnifying glass is at screen-borders
1461 /* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
1462 * Hatched area is beyond screen border.
1464 * |<-Cursor_x_hot->|
1465 * ________________|_____
1466 * |/ / / / / / /| | |
1467 * | / / / / / / |(x,y) |
1468 * |/_/_/_/_/_/_/|________|
1469 * |<----x0----->|<--w0-->|
1473 /* Figure 2: Shifting of rectangle-to-grab at bottom/right
1474 * screen borders
1475 * Hatched area is beyond screen border
1477 * |<-Cursor_x_hot->|
1478 * ________________|_______________
1479 * | | | / / / / / /|
1480 * | (x,y)|/ / / / / / |
1481 * |___________________|_/_/_/_/_/_/|
1482 * |<-------w0-------->| |
1483 * |<---------------w--|----------->|
1484 * | |
1485 * x0 Displaywidth-1
1488 if (x < Cursor_x_hot) { /* see fig. 1 */
1489 x0 = Cursor_x_hot - x;
1490 w0 = w - x0;
1493 if (displayWidth -1 < x - Cursor_x_hot + w) { /* see fig. 2 */
1494 w0 = (displayWidth) - (x - Cursor_x_hot);
1497 if (y < Cursor_y_hot) { /* see fig. 1 */
1498 y0 = Cursor_y_hot - y;
1499 h0 = h - y0;
1502 if (displayHeight -1 < y - Cursor_y_hot + h) { /* see fig. 2 */
1503 h0 = (displayHeight) - (y - Cursor_y_hot);
1505 /* end of coordinate correction */
1508 /* Grab an image from the screen, clipped if necessary,
1509 * and put it in the existing panel->magnifyGlass->image
1510 * with the corresponding clipping offset.
1512 if (!XGetSubImage(scr->display, scr->rootWin,
1513 x - Cursor_x_hot + x0,
1514 y - Cursor_y_hot + y0,
1515 w0, h0, AllPlanes, ZPixmap,
1516 image, x0, y0))
1517 wwarning("ColorPanel: X said I cannot grab a subimage from screen.");
1519 return NULL;
1523 static void
1524 magnifyGetImageStored(WMColorPanel *panel, int x1, int y1, int x2, int y2)
1526 /* (x1, y1) = topleft corner of existing rectangle
1527 * (x2, y2) = topleft corner of new position
1530 W_Screen *scr = WMWidgetScreen(panel->win);
1531 int xa = 0, ya = 0, xb = 0, yb = 0;
1532 int width, height;
1533 const int dx = abs(x2 - x1),
1534 dy = abs(y2 - y1);
1535 XImage *image;
1536 const int x_min = Cursor_x_hot,
1537 y_min = Cursor_y_hot,
1538 x_max = DisplayWidth(scr->display, scr->screen) -1 -
1539 (Cursor_mask_width - Cursor_x_hot),
1540 y_max = DisplayHeight(scr->display, scr->screen) -1 -
1541 (Cursor_mask_height - Cursor_y_hot);
1543 if ((dx == 0) && (dy == 0) && panel->magnifyGlass->image)
1544 return; /* Eh, Captain, we didn't move...
1545 * but... eh... how did we get here? */
1547 if (x1 < x2)
1548 xa = dx;
1549 else
1550 xb = dx;
1552 if (y1 < y2)
1553 ya = dy;
1554 else
1555 yb = dy;
1557 width = Cursor_mask_width - dx;
1558 height = Cursor_mask_height - dy;
1560 /* If the traversed distance is larger than the size of the magnifying
1561 * glass contents, there is no need to do dirty rectangles. A whole new
1562 * rectangle can be grabbed, unless that rectangle falls partially
1563 * off screen.
1564 * Destroying the image and setting it to NULL will achieve that later on.
1566 * Of course, grabbing an XImage beyond the borders of the screen will
1567 * cause trouble, this is considdered a special case. Part of the screen
1568 * is grabbed, but there is no need for dirty rectangles.
1570 if ((width <= 0) || (height <= 0)) {
1571 if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
1572 if (panel->magnifyGlass->image)
1573 XDestroyImage(panel->magnifyGlass->image);
1574 panel->magnifyGlass->image = NULL;
1576 } else {
1577 if (panel->magnifyGlass->image) {
1578 /* Get dirty rectangle from panel->magnifyGlass->image */
1579 panel->magnifyGlass->dirtyRect =
1580 XSubImage(panel->magnifyGlass->image, xa, ya, width, height);
1581 if (!panel->magnifyGlass->dirtyRect) {
1582 wwarning("ColorPanel: X said I cannot get a dirty rectangle.");
1583 return; /* X returned a NULL from XSubImage */
1588 /* Get image from screen */
1589 image = magnifyGetImage(scr, panel->magnifyGlass->image, x2, y2,
1590 Cursor_mask_width, Cursor_mask_height);
1591 if (image) { /* Only reassign if a *new* image was grabbed */
1592 panel->magnifyGlass->image = image;
1593 return;
1596 /* Copy previously stored rectangle on covered part of image */
1597 if (panel->magnifyGlass->image && panel->magnifyGlass->dirtyRect) {
1598 int old_height;
1600 /* "width" and "height" are used as coordinates here,
1601 * and run from [0...width-1] and [0...height-1] respectively.
1603 width--;
1604 height--;
1605 old_height = height;
1607 for (; width >= 0; width--)
1608 for (height = old_height; height >= 0; height--)
1609 XPutPixel(panel->magnifyGlass->image, xb + width, yb + height,
1610 XGetPixel(panel->magnifyGlass->dirtyRect, width, height));
1611 XDestroyImage(panel->magnifyGlass->dirtyRect);
1612 panel->magnifyGlass->dirtyRect = NULL;
1615 return;
1619 static Pixmap
1620 magnifyCreatePixmap(WMColorPanel *panel)
1622 W_Screen *scr = WMWidgetScreen(panel->win);
1623 int u, v;
1624 Pixmap pixmap;
1625 unsigned long color;
1627 if (!panel->magnifyGlass->image)
1628 return None;
1630 if (!panel->magnifyGlass->magPix)
1631 return None;
1634 * Copy an area of only 5x5 pixels from the center of the image.
1636 for (u = 0; u < 5; u++) {
1637 for (v = 0; v < 5; v++) {
1638 color = XGetPixel(panel->magnifyGlass->image, u + 9, v + 9);
1640 XSetForeground(scr->display, scr->copyGC, color);
1642 if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
1643 panel->magnifyGlass->color = ulongToRColor(scr,
1644 panel->magnifyGlass->image, color);
1646 XFillRectangle(scr->display, panel->magnifyGlass->magPix,
1647 scr->copyGC, u * 5, v * 5, 5, 5);
1651 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width,
1652 Cursor_mask_height, scr->depth);
1653 if (!pixmap)
1654 return None;
1656 #ifndef SHAPE
1657 XPutImage(scr->display, pixmap, scr->copyGC, panel->magnifyGlass->image,
1658 0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
1659 #endif
1661 /* Copy the magnified pixmap, with the clip mask, to background pixmap */
1662 XCopyArea(scr->display, panel->magnifyGlass->magPix, pixmap,
1663 scr->clipGC, 1, 1, Cursor_mask_width, Cursor_mask_height, 0, 0);
1664 /* (2,2) puts center pixel on center of glass */
1666 return pixmap;
1670 static WMView*
1671 magnifyCreateView(W_ColorPanel *panel)
1673 W_Screen *scr = WMWidgetScreen(panel->win);
1674 WMView *magView;
1676 magView = W_CreateTopView(scr);
1677 if (!magView)
1678 return NULL;
1680 magView->self = panel->win;
1681 magView->flags.topLevel = 1;
1682 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1683 magView->attribs.override_redirect = True;
1684 magView->attribs.save_under = True;
1686 W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
1688 W_RealizeView(magView);
1690 return magView;
1694 static Cursor
1695 magnifyGrabPointer(W_ColorPanel *panel)
1697 W_Screen *scr = WMWidgetScreen(panel->win);
1698 Pixmap magPixmap, magPixmap2;
1699 Cursor magCursor;
1700 XColor fgColor = {0, 0,0,0, DoRed|DoGreen|DoBlue};
1701 XColor bgColor = {0, 0xbf00, 0xa000, 0x5000, DoRed|DoGreen|DoBlue};
1703 /* Cursor creation stuff */
1704 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1705 (char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
1706 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1707 (char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
1709 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1710 &fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
1712 XFreePixmap(scr->display, magPixmap);
1713 XFreePixmap(scr->display, magPixmap2);
1715 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1717 /* Set up Pointer */
1718 XGrabPointer (scr->display, panel->magnifyGlass->view->window, True,
1719 PointerMotionMask | ButtonPressMask,
1720 GrabModeAsync, GrabModeAsync,
1721 scr->rootWin, magCursor, CurrentTime);
1723 return magCursor;
1727 static WMPoint
1728 magnifyInitialize(W_ColorPanel *panel)
1730 W_Screen *scr = WMWidgetScreen(panel->win);
1731 unsigned int x, y, u, v;
1732 unsigned int mask;
1733 Pixmap pixmap, clip_mask;
1734 WMPoint point;
1735 Window root_return, child_return;
1737 clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1738 (char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1739 1, 0, 1);
1740 panel->magnifyGlass->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
1741 5*5, 5*5, scr->depth);
1743 XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return,
1744 &x, &y, &u, &v, &mask);
1746 panel->magnifyGlass->image = NULL;
1748 /* Clipmask to make magnified view-contents circular */
1750 #ifdef SHAPE
1751 XShapeCombineMask(scr->display, WMViewXID(panel->magnifyGlass->view),
1752 ShapeBounding, 0, 0, clip_mask, ShapeSet);
1753 #else
1754 /* Clip circle in glass cursor */
1755 XSetClipMask(scr->display, scr->clipGC, clip_mask);
1756 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1757 #endif
1759 XFreePixmap(scr->display, clip_mask);
1761 /* Draw initial magnifying glass contents */
1762 magnifyGetImageStored(panel, x, y, x, y);
1764 pixmap = magnifyCreatePixmap(panel);
1765 XSetWindowBackgroundPixmap(scr->display,
1766 panel->magnifyGlass->view->window,
1767 pixmap);
1768 XClearWindow(scr->display, panel->magnifyGlass->view->window);
1769 XFlush(scr->display);
1771 XFreePixmap(scr->display, pixmap);
1773 point.x = x;
1774 point.y = y;
1776 return point;
1780 static void
1781 magnifyPutCursor(WMWidget *w, void *data)
1783 W_ColorPanel *panel = (W_ColorPanel*)(data);
1784 W_Screen *scr = WMWidgetScreen(panel->win);
1785 Cursor magCursor;
1786 int x, y;
1787 Pixmap pixmap;
1788 XEvent event;
1789 WMPoint initialPosition;
1791 /* Destroy wheelBackImg, so it'll update properly */
1792 if (panel->selectionBackImg) {
1793 XFreePixmap(WMWidgetScreen(panel->win)->display,
1794 panel->selectionBackImg);
1795 panel->selectionBackImg = None;
1798 /* Create magnifying glass */
1799 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1800 panel->magnifyGlass->view = magnifyCreateView(panel);
1801 if (!panel->magnifyGlass->view)
1802 return;
1804 initialPosition = magnifyInitialize(panel);
1805 x = initialPosition.x;
1806 y = initialPosition.y;
1808 W_MoveView(panel->magnifyGlass->view,
1809 x - Cursor_x_hot,
1810 y - Cursor_y_hot);
1811 W_MapView(panel->magnifyGlass->view);
1813 magCursor = magnifyGrabPointer(panel);
1815 while (panel->magnifyGlass->image)
1817 WMNextEvent(scr->display, &event);
1819 /* Pack motion events */
1820 while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
1823 switch (event.type)
1825 case ButtonPress:
1826 XDestroyImage(panel->magnifyGlass->image);
1827 panel->magnifyGlass->image = NULL;
1829 if (event.xbutton.button == Button1) {
1830 updateSwatch(panel, panel->magnifyGlass->color);
1832 switch (panel->mode) {
1833 case WMWheelModeColorPanel:
1834 wheelInit(panel);
1835 wheelRender(panel);
1836 wheelPaint(panel);
1837 break;
1838 case WMGrayModeColorPanel:
1839 grayInit(panel);
1840 break;
1841 case WMRGBModeColorPanel:
1842 rgbInit(panel);
1843 break;
1844 case WMCMYKModeColorPanel:
1845 cmykInit(panel);
1846 break;
1847 case WMHSBModeColorPanel:
1848 hsbInit(panel);
1849 break;
1850 default:
1851 break;
1853 panel->lastChanged = panel->mode;
1855 WMSetButtonSelected(panel->magnifyBtn, False);
1856 break;
1858 case MotionNotify:
1859 /* Get a "dirty rectangle" */
1860 magnifyGetImageStored( panel, x, y,
1861 event.xmotion.x_root, event.xmotion.y_root);
1863 /* Update coordinates */
1864 x = event.xmotion.x_root;
1865 y = event.xmotion.y_root;
1867 /* Move view */
1868 W_MoveView(panel->magnifyGlass->view, x - Cursor_x_hot,
1869 y - Cursor_y_hot);
1871 /* Put new image (with magn.) in view */
1872 pixmap = magnifyCreatePixmap(panel);
1873 if (pixmap != None) {
1874 XSetWindowBackgroundPixmap(scr->display,
1875 panel->magnifyGlass->view->window, pixmap);
1876 XClearWindow(scr->display, panel->magnifyGlass->view->window);
1878 XFreePixmap(scr->display, pixmap);
1880 break;
1882 /* Try XQueryPointer for this !!! It returns windows that the pointer
1883 * is over. Note: We found this solving the invisible donkey cap bug
1885 #if 0 /* As it is impossible to make this work in all cases,
1886 * we consider it confusing. Therefore we disabled it.
1888 case FocusOut: /* fall through */
1889 case FocusIn:
1891 * Color Panel window (panel->win) lost or received focus.
1892 * We need to update the pixmap in the magnifying glass.
1894 * BUG Doesn't work with focus switches between two windows
1895 * if none of them is the color panel.
1897 XUngrabPointer(scr->display, CurrentTime);
1898 W_UnmapView(panel->magnifyGlass->view);
1900 magnifyInitialize(panel);
1902 W_MapView(panel->magnifyGlass->view);
1903 XGrabPointer (scr->display, panel->magnifyGlass->view->window,
1904 True, PointerMotionMask | ButtonPressMask,
1905 GrabModeAsync, GrabModeAsync,
1906 scr->rootWin, magCursor, CurrentTime);
1907 break;
1908 #endif
1909 default:
1910 WMHandleEvent(&event);
1911 break;
1912 } /* of switch */
1915 XUngrabPointer(scr->display, CurrentTime);
1916 XFreeCursor(scr->display, magCursor);
1918 XFreePixmap(scr->display, panel->magnifyGlass->magPix);
1919 panel->magnifyGlass->magPix = None;
1921 W_UnmapView(panel->magnifyGlass->view);
1922 W_DestroyView(panel->magnifyGlass->view);
1923 panel->magnifyGlass->view = NULL;
1925 wfree(panel->magnifyGlass);
1930 /****************** WheelMatrix Functions ************************/
1932 static wheelMatrix*
1933 wheelCreateMatrix(unsigned int width, unsigned int height)
1935 wheelMatrix *matrix = NULL;
1936 int i;
1938 assert((width > 0) && (height > 0));
1940 matrix = malloc(sizeof(wheelMatrix));
1941 if (!matrix) {
1942 RErrorCode = RERR_NOMEMORY;
1943 return NULL;
1946 memset(matrix, 0, sizeof(wheelMatrix));
1947 matrix->width = width;
1948 matrix->height = height;
1949 for (i = 0; i < 3; i++) {
1950 matrix->data[i] = malloc(width*height*sizeof(unsigned char));
1951 if (!matrix->data[i])
1952 goto error;
1955 return matrix;
1957 error:
1958 for (i = 0; i < 3; i++) {
1959 if (matrix->data[i])
1960 wfree(matrix->data[i]);
1962 if (matrix)
1963 wfree(matrix);
1964 RErrorCode = RERR_NOMEMORY;
1965 return NULL;
1969 static void
1970 wheelDestroyMatrix(wheelMatrix *matrix)
1972 int i;
1974 assert (matrix!=NULL);
1976 for (i = 0; i < 3; i++) {
1977 if (matrix->data[i])
1978 wfree(matrix->data[i]);
1980 wfree(matrix);
1984 static wheelMatrix*
1985 wheelInitMatrix(W_ColorPanel *panel)
1987 int i;
1988 int x,y;
1989 wheelMatrix *matrix;
1990 unsigned char *rp, *gp, *bp;
1991 RHSVColor cur_hsv;
1992 RColor cur_rgb;
1993 long ofs[4];
1994 float hue;
1995 int sat;
1996 float xcor, ycor;
1997 int dhue[4];
1999 matrix = wheelCreateMatrix(colorWheelSize+4, colorWheelSize+4);
2000 if (!matrix)
2001 return NULL;
2003 RRGBtoHSV(&panel->color, &cur_hsv);
2005 for (i = 0; i < 256; i++)
2006 matrix->values[i] = (unsigned char)(rint(i*cur_hsv.value/255));
2008 cur_hsv.value = 255;
2010 ofs[0] = -1;
2011 ofs[1] = -(colorWheelSize + 4);
2012 /* ofs[2] = 0; superfluous
2013 ofs[3] = 0;
2015 for (y = 0; y < (colorWheelSize+4)/2; y++) {
2016 for (x = y; x < (colorWheelSize+4-y); x++) {
2017 xcor = ((float)(2.0*x - 4.0) / colorWheelSize) - 1;
2018 ycor = ((float)(2.0*y - 4.0) / colorWheelSize) - 1;
2020 sat = rint(255.0 * sqrt((xcor*xcor) + (ycor*ycor)));
2024 /* offsets are counterclockwise (in triangles) */
2026 /* top quarter */
2027 if (y < (colorWheelSize+4)/2)
2028 ofs[0]++;
2030 /* left quarter */
2031 ofs[1] += colorWheelSize + 4;
2033 /* bottom quarter */
2034 ofs[2] = (colorWheelSize + 4) * (colorWheelSize + 4) - 1 - ofs[0];
2036 /* right quarter */
2037 ofs[3] = (colorWheelSize + 4) * (colorWheelSize + 4) - 1 - ofs[1];
2039 if (sat < 256) {
2040 cur_hsv.saturation = (unsigned char)sat;
2042 if (xcor != 0)
2043 hue = atan(ycor/xcor);
2044 else {
2045 if (ycor > 0)
2046 hue = M_PI * 0.5;
2047 else
2048 hue = M_PI * 1.5;
2051 if (xcor < 0)
2052 hue += M_PI;
2053 if ((xcor > 0) && (ycor < 0))
2054 hue += M_PI * 2.0;
2056 hue = -hue; /* Reverse direction of ColorWheel */
2058 if (hue < 0)
2059 hue += M_PI * 2.0;
2061 dhue[0] = (hue*360) / (M_PI * 2.0);
2063 for (i = 0; i < 4; i++) {
2065 if (i > 0)
2066 dhue[i] = (dhue[i-1] + 90) % 360;
2068 if ((i == 1) || (i == 3))
2069 dhue[i] = 360 - dhue[i];
2071 if (i == 2)
2072 dhue[i] = 360 - dhue[i] + 180;
2074 rp = matrix->data[0] + (ofs[i] * sizeof(unsigned char));
2075 gp = matrix->data[1] + (ofs[i] * sizeof(unsigned char));
2076 bp = matrix->data[2] + (ofs[i] * sizeof(unsigned char));
2078 cur_hsv.hue = dhue[i];
2079 RHSVtoRGB(&cur_hsv, &cur_rgb);
2081 *rp = (unsigned char)(cur_rgb.red);
2082 *gp = (unsigned char)(cur_rgb.green);
2083 *bp = (unsigned char)(cur_rgb.blue);
2086 else {
2087 for (i = 0; i < 4; i++) {
2088 rp = matrix->data[0] + (ofs[i] * sizeof(unsigned char));
2089 gp = matrix->data[1] + (ofs[i] * sizeof(unsigned char));
2090 bp = matrix->data[2] + (ofs[i] * sizeof(unsigned char));
2092 *rp = (unsigned char)(0);
2093 *gp = (unsigned char)(0);
2094 *bp = (unsigned char)(0);
2098 if (y < (colorWheelSize+4)/2)
2099 ofs[0] += 2*y+1;
2101 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2*y);
2104 return matrix;
2107 /****************** ColorWheel Functions *******************/
2109 static void
2110 wheelRender(W_ColorPanel *panel)
2112 W_Screen *scr = WMWidgetScreen(panel->win);
2113 int x,y;
2114 RImage *image;
2115 unsigned char *rp, *gp, *bp;
2116 RColor gray;
2117 unsigned long ofs;
2119 image = RCreateImage(colorWheelSize+4, colorWheelSize+4, False);
2120 if (!image)
2121 return;
2123 gray.red = gray.green = gray.blue = 0xaa;
2125 for (x = 0; x < colorWheelSize+4; x++) {
2126 for (y = 0; y < colorWheelSize+4; y++) {
2128 ofs = (y * image->width) + x;
2129 rp = image->data[0] + ofs;
2130 gp = image->data[1] + ofs;
2131 bp = image->data[2] + ofs;
2133 if (wheelInsideColorWheel(panel, ofs)) {
2134 *rp = (unsigned int)(panel->wheelMtrx->values[
2135 panel->wheelMtrx->data[0][ofs] ]);
2136 *gp = (unsigned int)(panel->wheelMtrx->values[
2137 panel->wheelMtrx->data[1][ofs] ]);
2138 *bp = (unsigned int)(panel->wheelMtrx->values[
2139 panel->wheelMtrx->data[2][ofs] ]);
2141 else {
2142 *rp = (unsigned char)(gray.red);
2143 *gp = (unsigned char)(gray.green);
2144 *bp = (unsigned char)(gray.blue);
2149 if (panel->wheelImg)
2150 XFreePixmap(scr->display, panel->wheelImg);
2152 panel->wheelImg = XCreatePixmap(scr->display, W_DRAWABLE(scr),
2153 colorWheelSize+4, colorWheelSize+4, scr->depth);
2154 RConvertImage(scr->rcontext, image, &panel->wheelImg);
2156 /* Check if backimage exists. If it doesn't, allocate and fill it */
2157 if (!panel->selectionBackImg) {
2158 panel->selectionBackImg = XCreatePixmap(scr->display,
2159 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
2160 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2161 scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0);
2162 /* -2 is hot spot correction */
2165 RDestroyImage(image);
2168 static Bool
2169 wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs)
2171 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
2172 (panel->wheelMtrx->data[1][ofs] != 0) &&
2173 (panel->wheelMtrx->data[2][ofs] != 0));
2176 static void
2177 wheelPaint (W_ColorPanel *panel)
2179 W_Screen *scr = WMWidgetScreen(panel->win);
2181 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
2182 scr->copyGC, 0, 0, colorWheelSize+4, colorWheelSize+4, 0, 0);
2184 /* Draw selection image */
2185 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2186 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2189 static void
2190 wheelHandleEvents(XEvent *event, void *data)
2192 W_ColorPanel *panel = (W_ColorPanel*)data;
2194 switch (event->type) {
2195 case Expose:
2196 if (event->xexpose.count != 0)
2197 break;
2198 wheelPaint(panel);
2199 break;
2203 static void
2204 wheelHandleActionEvents(XEvent *event, void *data)
2206 W_ColorPanel *panel = (W_ColorPanel*)data;
2208 switch (event->type) {
2209 case ButtonPress:
2210 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) ==
2211 COLORWHEEL_PART) {
2212 panel->flags.dragging = 1;
2213 wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
2215 break;
2217 case ButtonRelease:
2218 panel->flags.dragging = 0;
2219 if (!panel->flags.continuous) {
2220 if (panel->action)
2221 (*panel->action)(panel, panel->clientData);
2223 break;
2225 case MotionNotify:
2226 if (panel->flags.dragging) {
2227 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) ==
2228 COLORWHEEL_PART) {
2229 wheelPositionSelection(panel, event->xmotion.x,
2230 event->xmotion.y);
2232 else
2233 wheelPositionSelectionOutBounds(panel, event->xmotion.x,
2234 event->xmotion.y);
2236 break;
2241 static int
2242 getPickerPart(W_ColorPanel *panel, int x, int y)
2244 int lx, ly;
2245 unsigned long ofs;
2247 lx = x;
2248 ly = y;
2250 if (panel->mode == WMWheelModeColorPanel) {
2251 if ((lx >= 2) && (lx <= 2+colorWheelSize) && (ly >= 2) &&
2252 (ly <= 2+colorWheelSize)) {
2254 ofs = ly*panel->wheelMtrx->width+lx;
2256 if (wheelInsideColorWheel(panel, ofs))
2257 return COLORWHEEL_PART;
2261 if (panel->mode == WMCustomPaletteModeColorPanel) {
2262 if ((lx >= 2) && (lx < customPaletteWidth-2) && (ly >= 2) &&
2263 (ly < customPaletteHeight-2)) {
2264 return CUSTOMPALETTE_PART;
2268 return 0;
2272 static void
2273 wheelBrightnessSliderCallback(WMWidget *w, void *data)
2275 int i;
2276 unsigned int v;
2277 int value;
2278 unsigned long ofs;
2279 RColor cur_rgb;
2281 W_ColorPanel *panel = (W_ColorPanel*)data;
2283 value = 255-WMGetSliderValue(panel->wheelBrightnessS);
2285 for (i = 0; i < 256; i++) {
2286 /* We divide by 128 in advance, and check whether that number divides
2287 * by 2 properly. If not, we add one to round the number correctly
2289 v = (i*value) >> 7;
2290 #ifdef EASTEREGG
2291 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + v);
2292 #else
2293 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) +(v & 0x01));
2294 #endif
2297 ofs = (panel->coly * panel->wheelMtrx->width) + panel->colx;
2299 if (!wheelInsideColorWheel(panel, ofs)) {
2300 panel->hsvcolor.saturation = 255;
2301 panel->hsvcolor.value = value;
2302 RHSVtoRGB(&panel->hsvcolor, &cur_rgb);
2304 panel->color = cur_rgb;
2306 else {
2307 panel->color.red = panel->wheelMtrx->values[
2308 panel->wheelMtrx->data[0][ofs] ];
2309 panel->color.green = panel->wheelMtrx->values[
2310 panel->wheelMtrx->data[1][ofs] ];
2311 panel->color.blue = panel->wheelMtrx->values[
2312 panel->wheelMtrx->data[2][ofs] ];
2315 wheelRender(panel);
2316 wheelPaint(panel);
2317 wheelUpdateSelection(panel);
2321 static void
2322 wheelUpdateSelection(W_ColorPanel *panel)
2324 W_Screen *scr = WMWidgetScreen(panel->win);
2326 updateSwatch(panel, panel->color);
2327 panel->lastChanged = WMWheelModeColorPanel;
2329 /* Redraw color selector (and make a backup of the part it will cover) */
2330 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2331 scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0);
2332 /* "-2" is correction for hotspot location */
2333 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2334 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2335 /* see above */
2338 static void
2339 wheelUndrawSelection(W_ColorPanel *panel)
2341 W_Screen *scr = WMWidgetScreen(panel->win);
2343 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
2344 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2345 /* see above */
2348 static void
2349 wheelPositionSelection(W_ColorPanel *panel, int x, int y)
2351 unsigned long ofs = (y * panel->wheelMtrx->width)+ x;
2353 panel->color.red = panel->wheelMtrx->values[
2354 panel->wheelMtrx->data[0][ofs] ];
2356 panel->color.green = panel->wheelMtrx->values[
2357 panel->wheelMtrx->data[1][ofs] ];
2359 panel->color.blue = panel->wheelMtrx->values[
2360 panel->wheelMtrx->data[2][ofs] ];
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 RHSVColor cur_hsv;
2375 float hue;
2376 float xcor, ycor;
2378 xcor = ((x*2.0) / (colorWheelSize+4)) - 1.0;
2379 ycor = ((y*2.0) / (colorWheelSize+4)) - 1.0;
2381 cur_hsv.saturation = 255;
2382 cur_hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2384 if (xcor != 0)
2385 hue = atan(ycor/xcor);
2386 else {
2387 if (ycor > 0)
2388 hue = M_PI * 0.5;
2389 else
2390 hue = M_PI * 1.5;
2393 if (xcor < 0)
2394 hue += M_PI;
2395 if ((xcor > 0) && (ycor < 0))
2396 hue += M_PI * 2.0;
2398 hue = -hue;
2400 if (hue < 0)
2401 hue += M_PI * 2.0;
2403 cur_hsv.hue = (hue*180.0)/(M_PI);
2404 RHSVtoRGB(&cur_hsv, &panel->color);
2406 wheelUndrawSelection(panel);
2408 panel->colx = 2 + rint((colorWheelSize * (1.0 +
2409 cos( cur_hsv.hue*M_PI/180))) /2.0);
2410 /* "+2" because of "colorWheelSize + 4" */
2411 panel->coly = 2 + rint((colorWheelSize * (1.0 +
2412 sin(-cur_hsv.hue*M_PI/180))) /2.0);
2414 wheelUpdateSelection(panel);
2415 wheelUpdateBrightnessGradientFromHSV(panel, cur_hsv);
2418 static void
2419 wheelUpdateBrightnessGradientFromHSV(W_ColorPanel *panel, RHSVColor topColor)
2421 RColor from;
2423 /* Update Brightness-Slider */
2424 topColor.value = 255;
2425 RHSVtoRGB(&topColor, &from);
2427 wheelUpdateBrightnessGradient(panel, from);
2430 static void
2431 wheelUpdateBrightnessGradientFromLocation(W_ColorPanel *panel)
2433 RColor from;
2434 unsigned long ofs;
2436 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2438 from.red = panel->wheelMtrx->data[0][ofs];
2439 from.green = panel->wheelMtrx->data[1][ofs];
2440 from.blue = panel->wheelMtrx->data[2][ofs];
2442 wheelUpdateBrightnessGradient(panel, from);
2445 static void
2446 wheelUpdateBrightnessGradient(W_ColorPanel *panel, RColor topColor)
2448 RColor to;
2449 RImage *sliderImg;
2450 WMPixmap *sliderPxmp;
2452 to.red = to.green = to.blue = 0;
2454 sliderImg = RRenderGradient(16, 153, &topColor, &to, RGRD_VERTICAL);
2455 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win),
2456 sliderImg, 0);
2457 RDestroyImage(sliderImg);
2458 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
2459 WMReleasePixmap(sliderPxmp);
2462 /****************** Grayscale Panel Functions ***************/
2464 static void
2465 grayBrightnessSliderCallback(WMWidget *w, void *data)
2467 RColor color;
2468 int value;
2469 char tmp[4];
2470 W_ColorPanel *panel = (W_ColorPanel*)data;
2472 value = WMGetSliderValue(panel->grayBrightnessS);
2474 sprintf(tmp, "%d", value);
2476 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2477 color.red = color.green = color.blue = rint(2.55*value);
2479 updateSwatch(panel, color);
2480 panel->lastChanged = WMGrayModeColorPanel;
2483 static void
2484 grayPresetButtonCallback(WMWidget *w, void *data)
2486 RColor color;
2487 char tmp[4];
2488 int value;
2489 int i=0;
2490 W_ColorPanel *panel = (W_ColorPanel*)data;
2492 while (i < 7) {
2493 if (w == panel->grayPresetBtn[i])
2494 break;
2495 i++;
2498 value = rint(100.0/6.0*i);
2499 sprintf(tmp, "%d", value);
2501 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2502 color.red = color.green = color.blue = rint(255.0*i/6.0);
2504 WMSetSliderValue(panel->grayBrightnessS, rint(100.0*i/6.0));
2506 updateSwatch(panel, color);
2507 panel->lastChanged = WMGrayModeColorPanel;
2510 static void
2511 grayBrightnessTextFieldCallback(void *observerData,
2512 WMNotification *notification)
2514 RColor color;
2515 char tmp[4];
2516 int value;
2517 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2519 value = atoi(WMGetTextFieldText(panel->grayBrightnessT));
2520 if (value > 100)
2521 value = 100;
2522 if (value < 0)
2523 value = 0;
2525 sprintf(tmp, "%d", value);
2526 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2527 WMSetSliderValue(panel->grayBrightnessS, value);
2529 color.red = color.green = color.blue = rint(255.0*value/100.0);
2530 updateSwatch(panel, color);
2531 panel->lastChanged = WMGrayModeColorPanel;
2534 /******************* RGB Panel Functions *****************/
2536 static void
2537 rgbSliderCallback(WMWidget *w, void *data)
2539 RColor color;
2540 int value[3];
2541 char tmp[4];
2542 W_ColorPanel *panel = (W_ColorPanel*)data;
2544 value[0] = WMGetSliderValue(panel->rgbRedS);
2545 value[1] = WMGetSliderValue(panel->rgbGreenS);
2546 value[2] = WMGetSliderValue(panel->rgbBlueS);
2548 sprintf(tmp, "%d", value[0]);
2549 WMSetTextFieldText(panel->rgbRedT, tmp);
2550 sprintf(tmp, "%d", value[1]);
2551 WMSetTextFieldText(panel->rgbGreenT, tmp);
2552 sprintf(tmp, "%d", value[2]);
2553 WMSetTextFieldText(panel->rgbBlueT, tmp);
2555 color.red = value[0];
2556 color.green = value[1];
2557 color.blue = value[2];
2559 updateSwatch(panel, color);
2560 panel->lastChanged = WMRGBModeColorPanel;
2563 static void
2564 rgbTextFieldCallback(void *observerData, WMNotification *notification)
2566 RColor color;
2567 int value[3];
2568 char tmp[4];
2569 int n;
2570 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2572 value[0] = atoi(WMGetTextFieldText(panel->rgbRedT));
2573 value[1] = atoi(WMGetTextFieldText(panel->rgbGreenT));
2574 value[2] = atoi(WMGetTextFieldText(panel->rgbBlueT));
2576 for (n=0; n < 3; n++) {
2577 if (value[n] > 255)
2578 value[n] = 255;
2579 if (value[n] < 0)
2580 value[n] = 0;
2583 sprintf(tmp, "%d", value[0]);
2584 WMSetTextFieldText(panel->rgbRedT, tmp);
2585 sprintf(tmp, "%d", value[1]);
2586 WMSetTextFieldText(panel->rgbGreenT, tmp);
2587 sprintf(tmp, "%d", value[2]);
2588 WMSetTextFieldText(panel->rgbBlueT, tmp);
2590 WMSetSliderValue(panel->rgbRedS, value[0]);
2591 WMSetSliderValue(panel->rgbGreenS, value[1]);
2592 WMSetSliderValue(panel->rgbBlueS, value[2]);
2594 color.red = value[0];
2595 color.green = value[1];
2596 color.blue = value[2];
2598 updateSwatch(panel, color);
2599 panel->lastChanged = WMRGBModeColorPanel;
2603 /******************* CMYK Panel Functions *****************/
2605 static void
2606 cmykSliderCallback(WMWidget *w, void *data)
2608 RColor color;
2609 int value[4];
2610 char tmp[4];
2611 W_ColorPanel *panel = (W_ColorPanel*)data;
2613 value[0] = WMGetSliderValue(panel->cmykCyanS);
2614 value[1] = WMGetSliderValue(panel->cmykMagentaS);
2615 value[2] = WMGetSliderValue(panel->cmykYellowS);
2616 value[3] = WMGetSliderValue(panel->cmykBlackS);
2618 sprintf(tmp, "%d", value[0]);
2619 WMSetTextFieldText(panel->cmykCyanT, tmp);
2620 sprintf(tmp, "%d", value[1]);
2621 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2622 sprintf(tmp, "%d", value[2]);
2623 WMSetTextFieldText(panel->cmykYellowT, tmp);
2624 sprintf(tmp, "%d", value[3]);
2625 WMSetTextFieldText(panel->cmykBlackT, tmp);
2627 color.red = rint((255.0 - (value[0] * 2.55)) * (1.0 - (value[3] / 100.0)));
2628 color.green = rint((255.0 - (value[1] * 2.55)) * (1.0 - (value[3]/100.0)));
2629 color.blue = rint((255.0 - (value[2] * 2.55)) * (1.0 - (value[3] /100.0)));
2631 updateSwatch(panel, color);
2632 panel->lastChanged = WMCMYKModeColorPanel;
2635 static void
2636 cmykTextFieldCallback(void *observerData, WMNotification *notification)
2638 RColor color;
2639 int value[4];
2640 char tmp[4];
2641 int n;
2642 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2644 value[0] = atoi(WMGetTextFieldText(panel->cmykCyanT));
2645 value[1] = atoi(WMGetTextFieldText(panel->cmykMagentaT));
2646 value[2] = atoi(WMGetTextFieldText(panel->cmykYellowT));
2647 value[3] = atoi(WMGetTextFieldText(panel->cmykBlackT));
2649 for (n=0; n < 4; n++) {
2650 if (value[n] > 100)
2651 value[n] = 100;
2652 if (value[n] < 0)
2653 value[n] = 0;
2656 sprintf(tmp, "%d", value[0]);
2657 WMSetTextFieldText(panel->cmykCyanT, tmp);
2659 sprintf(tmp, "%d", value[1]);
2660 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2662 sprintf(tmp, "%d", value[2]);
2663 WMSetTextFieldText(panel->cmykYellowT, tmp);
2665 sprintf(tmp, "%d", value[3]);
2666 WMSetTextFieldText(panel->cmykBlackT, tmp);
2668 WMSetSliderValue(panel->cmykCyanS, value[0]);
2669 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2670 WMSetSliderValue(panel->cmykYellowS, value[2]);
2671 WMSetSliderValue(panel->cmykBlackS, value[3]);
2673 color.red = rint((255.0 - (value[0] * 2.55)) * (1.0 - (value[3] / 100.0)));
2674 color.green = rint((255.0 - (value[1] * 2.55)) * (1.0 - (value[3]/100.0)));
2675 color.blue = rint((255.0 - (value[2] * 2.55)) * (1.0 - (value[3] /100.0)));
2677 updateSwatch(panel, color);
2678 panel->lastChanged = WMCMYKModeColorPanel;
2681 /********************** HSB Panel Functions ***********************/
2683 static void
2684 hsbSliderCallback(WMWidget *w, void *data)
2686 RColor color;
2687 int value[3];
2688 char tmp[4];
2689 W_ColorPanel *panel = (W_ColorPanel*)data;
2691 value[0] = WMGetSliderValue(panel->hsbHueS);
2692 value[1] = WMGetSliderValue(panel->hsbSaturationS);
2693 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
2695 sprintf(tmp, "%d", value[0]);
2696 WMSetTextFieldText(panel->hsbHueT, tmp);
2697 sprintf(tmp, "%d", value[1]);
2698 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2699 sprintf(tmp, "%d", value[2]);
2700 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2702 panel->hsvcolor.hue = value[0];
2703 panel->hsvcolor.saturation = value[1]*2.55;
2704 panel->hsvcolor.value = value[2]*2.55;
2706 RHSVtoRGB(&panel->hsvcolor, &color);
2708 panel->lastChanged = WMHSBModeColorPanel;
2709 updateSwatch(panel, color);
2711 if (w != panel->hsbBrightnessS)
2712 hsbUpdateBrightnessGradient(panel);
2713 if (w != panel->hsbSaturationS)
2714 hsbUpdateSaturationGradient(panel);
2715 if (w != panel->hsbHueS)
2716 hsbUpdateHueGradient(panel);
2719 static void
2720 hsbTextFieldCallback(void *observerData, WMNotification *notification)
2722 RColor color;
2723 int value[3];
2724 char tmp[4];
2725 int n;
2726 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2728 value[0] = atoi(WMGetTextFieldText(panel->hsbHueT));
2729 value[1] = atoi(WMGetTextFieldText(panel->hsbSaturationT));
2730 value[2] = atoi(WMGetTextFieldText(panel->hsbBrightnessT));
2732 if (value[0] > 359)
2733 value[0] = 359;
2734 if (value[0] < 0)
2735 value[0] = 0;
2737 for (n=1; n < 3; n++) {
2738 if (value[n] > 100)
2739 value[n] = 100;
2740 if (value[n] < 0)
2741 value[n] = 0;
2744 sprintf(tmp, "%d", value[0]);
2745 WMSetTextFieldText(panel->hsbHueT, tmp);
2746 sprintf(tmp, "%d", value[1]);
2747 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2748 sprintf(tmp, "%d", value[2]);
2749 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2751 WMSetSliderValue(panel->hsbHueS, value[0]);
2752 WMSetSliderValue(panel->hsbSaturationS, value[1]);
2753 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
2755 panel->hsvcolor.hue = value[0];
2756 panel->hsvcolor.saturation = value[1]*2.55;
2757 panel->hsvcolor.value = value[2]*2.55;
2759 RHSVtoRGB(&panel->hsvcolor, &color);
2761 panel->lastChanged = WMHSBModeColorPanel;
2762 updateSwatch(panel, color);
2764 hsbUpdateBrightnessGradient(panel);
2765 hsbUpdateSaturationGradient(panel);
2766 hsbUpdateHueGradient(panel);
2769 static void
2770 hsbUpdateBrightnessGradient(W_ColorPanel *panel)
2772 W_Screen *scr = WMWidgetScreen(panel->win);
2773 RColor from;
2774 RColor to;
2775 RHSVColor hsvcolor;
2776 RImage *sliderImg;
2777 WMPixmap *sliderPxmp;
2779 from.red = from.green = from.blue = 0;
2780 hsvcolor = panel->hsvcolor;
2781 hsvcolor.value = 255;
2783 RHSVtoRGB(&hsvcolor, &to);
2785 sliderImg = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
2786 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2787 RDestroyImage(sliderImg);
2788 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
2789 panel->font12, 2, 0, 100, WALeft, WMColorGC(scr->white), False,
2790 "Brightness", strlen("Brightness"));
2791 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
2792 WMReleasePixmap(sliderPxmp);
2795 static void
2796 hsbUpdateSaturationGradient(W_ColorPanel *panel)
2798 W_Screen *scr = WMWidgetScreen(panel->win);
2799 RColor from;
2800 RColor to;
2801 RHSVColor hsvcolor;
2802 RImage *sliderImg;
2803 WMPixmap *sliderPxmp;
2805 hsvcolor = panel->hsvcolor;
2806 hsvcolor.saturation = 0;
2807 RHSVtoRGB(&hsvcolor, &from);
2809 hsvcolor.saturation = 255;
2810 RHSVtoRGB(&hsvcolor, &to);
2812 sliderImg = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
2813 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2814 RDestroyImage(sliderImg);
2815 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2816 panel->font12, 2, 0, 100, WALeft,
2817 WMColorGC(hsvcolor.value < 128 ? scr->white : scr->black), False,
2818 "Saturation", strlen("Saturation"));
2820 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
2821 WMReleasePixmap(sliderPxmp);
2824 static void
2825 hsbUpdateHueGradient(W_ColorPanel *panel)
2827 W_Screen *scr = WMWidgetScreen(panel->win);
2828 RColor **colors = NULL;
2829 RHSVColor hsvcolor;
2830 RImage *sliderImg;
2831 WMPixmap *sliderPxmp;
2832 int i;
2834 hsvcolor = panel->hsvcolor;
2836 colors = malloc(sizeof(RColor*)*(8));
2837 for (i=0; i<7; i++) {
2838 hsvcolor.hue = (360*i)/6;
2839 colors[i] = malloc(sizeof(RColor));
2840 RHSVtoRGB(&hsvcolor, colors[i]);
2842 colors[7] = NULL;
2844 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2845 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2846 RDestroyImage(sliderImg);
2847 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2848 panel->font12, 2, 0, 100, WALeft,
2849 WMColorGC(hsvcolor.value < 128 ? scr->white : scr->black), False,
2850 "Hue", strlen("Hue"));
2852 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2853 WMReleasePixmap(sliderPxmp);
2855 for (i=0; i<7; i++) {
2856 if (colors[i])
2857 wfree(colors[i]);
2859 if (colors)
2860 wfree(colors);
2863 /*************** Custom Palette Functions ****************/
2865 static void
2866 customRenderSpectrum(W_ColorPanel *panel)
2868 RImage *spectrum;
2869 int hue, sat, val;
2870 int x,y;
2871 unsigned long ofs;
2872 unsigned char *rp, *gp, *bp;
2873 RColor color;
2874 RHSVColor cur_hsv;
2876 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, 0);
2878 for (y=0; y<360; y++) {
2879 val = 255;
2880 sat = 0;
2881 hue = y;
2882 for (x=0; x<511; x++) {
2883 ofs = (y * 511) + x;
2885 cur_hsv.hue = hue;
2886 cur_hsv.saturation = sat;
2887 cur_hsv.value = val;
2889 RHSVtoRGB (&cur_hsv, &color);
2891 rp = spectrum->data[0] + ofs;
2892 gp = spectrum->data[1] + ofs;
2893 bp = spectrum->data[2] + ofs;
2895 *rp = (unsigned char)color.red;
2896 *gp = (unsigned char)color.green;
2897 *bp = (unsigned char)color.blue;
2899 if (x<255)
2900 sat++;
2902 if (x>255)
2903 val--;
2906 if (panel->customPaletteImg) {
2907 RDestroyImage(panel->customPaletteImg);
2908 panel->customPaletteImg = NULL;
2910 panel->customPaletteImg = spectrum;
2915 static void
2916 customSetPalette(W_ColorPanel *panel)
2918 W_Screen *scr = WMWidgetScreen(panel->win);
2919 RImage *scaledImg;
2920 Pixmap image;
2921 int item;
2923 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth,
2924 customPaletteHeight, scr->depth);
2926 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth,
2927 customPaletteHeight);
2928 RConvertImage(scr->rcontext, scaledImg, &image);
2929 RDestroyImage(scaledImg);
2931 XCopyArea(scr->display, image, panel->customPaletteContentView->window,
2932 scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2934 /* Check backimage exists. If it doesn't, allocate and fill it */
2935 if (!panel->selectionBackImg) {
2936 panel->selectionBackImg = XCreatePixmap(scr->display,
2937 panel->customPaletteContentView->window, 4, 4, scr->depth);
2940 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
2941 panel->palx-2, panel->paly-2, 4, 4, 0, 0);
2942 XCopyArea(scr->display, panel->selectionImg,
2943 panel->customPaletteContentView->window, scr->copyGC, 0 , 0, 4, 4,
2944 panel->palx-2, panel->paly-2);
2945 XFreePixmap(scr->display, image);
2947 panel->palXRatio = (float)(panel->customPaletteImg->width) /
2948 (float)(customPaletteWidth);
2949 panel->palYRatio = (float)(panel->customPaletteImg->height) /
2950 (float)(customPaletteHeight);
2952 item = WMGetPopUpButtonSelectedItem (panel->customPaletteHistoryBtn);
2954 /* if palette != "Spectrum", we are allowed to rename and remove it */
2955 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename,
2956 (item > 0) );
2957 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove,
2958 (item > 0) );
2962 static void
2963 customPalettePositionSelection(W_ColorPanel *panel, int x, int y)
2965 W_Screen *scr = WMWidgetScreen(panel->win);
2966 unsigned long ofs;
2969 /* undraw selection */
2970 XCopyArea(scr->display, panel->selectionBackImg,
2971 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2972 panel->palx-2, panel->paly-2);
2974 panel->palx = x;
2975 panel->paly = y;
2977 ofs = rint(x * panel->palXRatio) + rint(y * panel->palYRatio) *
2978 panel->customPaletteImg->width;
2980 panel->color.red = panel->customPaletteImg->data[0][ofs];
2981 panel->color.green = panel->customPaletteImg->data[1][ofs];
2982 panel->color.blue = panel->customPaletteImg->data[2][ofs];
2984 updateSwatch(panel, panel->color);
2985 panel->lastChanged = WMCustomPaletteModeColorPanel;
2987 /* Redraw color selector (and make a backup of the part it will cover) */
2988 XCopyArea(scr->display, panel->customPaletteContentView->window,
2989 panel->selectionBackImg, scr->copyGC, panel->palx-2, panel->paly-2,
2990 4, 4, 0, 0); /* "-2" is correction for hotspot location */
2991 XCopyArea(scr->display, panel->selectionImg,
2992 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2993 panel->palx-2, panel->paly-2); /* see above */
2997 static void
2998 customPalettePositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
3000 if (x < 2)
3001 x = 2;
3002 if (y < 2)
3003 y = 2;
3004 if (x >= customPaletteWidth)
3005 x = customPaletteWidth -2;
3006 if (y >= customPaletteHeight)
3007 y = customPaletteHeight -2;
3009 customPalettePositionSelection(panel, x, y);
3013 static void
3014 customPaletteHandleEvents(XEvent *event, void *data)
3016 W_ColorPanel *panel = (W_ColorPanel*)data;
3018 switch (event->type) {
3019 case Expose:
3020 if (event->xexpose.count != 0)
3021 break;
3022 customSetPalette(panel);
3023 break;
3027 static void
3028 customPaletteHandleActionEvents(XEvent *event, void *data)
3030 W_ColorPanel *panel = (W_ColorPanel*)data;
3031 int x, y;
3033 switch (event->type) {
3034 case ButtonPress:
3035 x = event->xbutton.x;
3036 y = event->xbutton.y;
3038 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
3039 panel->flags.dragging = 1;
3040 customPalettePositionSelection(panel, x, y);
3042 break;
3044 case ButtonRelease:
3045 panel->flags.dragging = 0;
3046 if (!panel->flags.continuous) {
3047 if (panel->action)
3048 (*panel->action)(panel, panel->clientData);
3050 break;
3052 case MotionNotify:
3053 x = event->xmotion.x;
3054 y = event->xmotion.y;
3056 if (panel->flags.dragging) {
3057 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
3058 customPalettePositionSelection(panel, x, y);
3060 else
3061 customPalettePositionSelectionOutBounds(panel, x, y);
3063 break;
3068 static void
3069 customPaletteMenuCallback(WMWidget *w, void *data)
3071 W_ColorPanel *panel = (W_ColorPanel*)data;
3072 int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
3074 switch (item) {
3075 case CPmenuNewFromFile:
3076 customPaletteMenuNewFromFile(panel);
3077 break;
3078 case CPmenuRename:
3079 customPaletteMenuRename(panel);
3080 break;
3081 case CPmenuRemove:
3082 customPaletteMenuRemove(panel);
3083 break;
3084 case CPmenuCopy:
3085 break;
3086 case CPmenuNewFromClipboard:
3087 break;
3092 static void
3093 customPaletteMenuNewFromFile(W_ColorPanel *panel)
3095 W_Screen *scr = WMWidgetScreen(panel->win);
3096 WMOpenPanel *browseP;
3097 char *filepath;
3098 char *filename = NULL;
3099 char *spath;
3100 char *tmp;
3101 int i;
3102 RImage *tmpImg = NULL;
3104 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir,"\0") == 0))
3105 spath = wexpandpath(wgethomedir());
3106 else
3107 spath = wexpandpath(panel->lastBrowseDir);
3109 browseP = WMGetOpenPanel(scr);
3110 WMSetFilePanelCanChooseDirectories(browseP, 0);
3111 WMSetFilePanelCanChooseFiles(browseP, 1);
3113 /* Get a filename */
3114 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
3115 "Open Palette", RSupportedFileFormats()) ) {
3116 filepath = WMGetFilePanelFileName(browseP);
3118 /* Get seperation position between path and filename */
3119 i = strrchr(filepath, '/') - filepath + 1;
3120 if (i > strlen(filepath))
3121 i = strlen(filepath);
3123 /* Store last browsed path */
3124 if (panel->lastBrowseDir)
3125 wfree(panel->lastBrowseDir);
3126 panel->lastBrowseDir = wmalloc((i+1)*sizeof(char));
3127 strncpy(panel->lastBrowseDir, filepath, i);
3128 panel->lastBrowseDir[i] = '\0';
3130 /* Get filename from path */
3131 filename = wstrdup(filepath + i);
3133 /* Check for duplicate files, and rename it if there are any */
3134 tmp = wstrappend(panel->configurationPath, filename);
3135 while (access (tmp, F_OK) == 0) {
3136 char *newName;
3138 wfree(tmp);
3140 newName = generateNewFilename(filename);
3141 wfree(filename);
3142 filename = newName;
3144 tmp = wstrappend(panel->configurationPath, filename);
3146 wfree(tmp);
3148 /* Copy image to $(gnustepdir)/Library/Colors/ &
3149 * Add filename to history menu */
3150 if (fetchFile (panel->configurationPath, filepath, filename) == 0) {
3152 /* filepath is a "local" path now the file has been copied */
3153 wfree(filepath);
3154 filepath = wstrappend(panel->configurationPath, filename);
3156 /* load the image & add menu entries */
3157 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
3158 if (tmpImg) {
3159 if (panel->customPaletteImg)
3160 RDestroyImage(panel->customPaletteImg);
3161 panel->customPaletteImg = tmpImg;
3163 customSetPalette(panel);
3164 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
3166 panel->currentPalette = WMGetPopUpButtonNumberOfItems(
3167 panel->customPaletteHistoryBtn)-1;
3169 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3170 panel->currentPalette);
3173 else
3175 tmp = wstrappend(panel->configurationPath, filename);
3177 i = remove(tmp); /* Delete the file, it doesn't belong here */
3178 WMRunAlertPanel(scr, panel->win, "File Error",
3179 "Invalid file format !", "OK", NULL, NULL);
3180 if (i != 0) {
3181 wsyserror("can't remove file %s", tmp);
3182 WMRunAlertPanel(scr, panel->win, "File Error",
3183 "Couldn't remove file from Configuration Directory !",
3184 "OK", NULL, NULL);
3186 wfree(tmp);
3188 wfree(filepath);
3189 wfree(filename);
3191 WMFreeFilePanel(browseP);
3193 wfree(spath);
3197 static void
3198 customPaletteMenuRename(W_ColorPanel *panel)
3200 W_Screen *scr = WMWidgetScreen(panel->win);
3201 char *toName = NULL;
3202 char *fromName;
3203 char *toPath, *fromPath;
3204 int item;
3205 int index;
3207 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3208 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
3210 toName = WMRunInputPanel(scr, panel->win, "Rename", "Rename palette to:",
3211 fromName, "OK", "Cancel");
3213 if (toName) {
3215 /* As some people do certain stupid things... */
3216 if (strcmp(toName, fromName) == 0) {
3217 wfree(toName);
3218 return;
3221 /* For normal people */
3222 fromPath = wstrappend(panel->configurationPath, fromName);
3223 toPath = wstrappend(panel->configurationPath, toName);
3225 if (access (toPath, F_OK) == 0) {
3226 /* Careful, this palette exists already */
3227 if (WMRunAlertPanel(scr, panel->win, "Warning",
3228 "Palette already exists !\n\nOverwrite ?", "No", "Yes",
3229 NULL) == 1) {
3230 /* "No" = 0, "Yes" = 1 */
3231 int items = WMGetPopUpButtonNumberOfItems(
3232 panel->customPaletteHistoryBtn);
3234 remove(toPath);
3236 /* Remove from History list too */
3237 index = 1;
3238 while ((index < items) && (strcmp(WMGetPopUpButtonItem(
3239 panel->customPaletteHistoryBtn, index),
3240 toName) != 0 ))
3241 index++;
3243 if (index < items) {
3244 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn,
3245 index);
3246 if (index < item)
3247 item--;
3250 } else {
3251 wfree(fromPath);
3252 wfree(toName);
3253 wfree(toPath);
3255 return;
3259 if ( rename(fromPath, toPath) != 0)
3260 wsyserror("Couldn't rename palette %s to %s\n", fromName, toName);
3261 else {
3262 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3263 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item,
3264 toName);
3266 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
3268 wfree(fromPath);
3269 wfree(toPath);
3270 wfree(toName);
3275 static void
3276 customPaletteMenuRemove(W_ColorPanel *panel)
3278 W_Screen *scr = WMWidgetScreen(panel->win);
3279 char *text;
3280 char *tmp;
3281 int choice;
3282 int item;
3284 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3286 tmp = wstrappend( "This will permanently remove the palette ",
3287 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
3288 text = wstrappend( tmp,
3289 ".\n\nAre you sure you want to remove this palette ?");
3290 wfree(tmp);
3292 choice = WMRunAlertPanel(scr, panel->win, NULL, text, "Yes", "No", NULL);
3293 /* returns 0 (= "Yes") or 1 (="No") */
3294 wfree(text);
3296 if (choice == 0) {
3298 tmp = wstrappend(panel->configurationPath,
3299 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
3301 if ( remove(tmp) != 0)
3302 wsyserror("Couldn't remove palette %s\n", tmp);
3303 wfree(tmp);
3305 /* item -1 always exists */
3306 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item-1);
3308 customPaletteHistoryCallback(panel->customPaletteHistoryBtn, panel);
3309 customSetPalette(panel);
3311 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3316 static void
3317 customPaletteHistoryCallback(WMWidget *w, void *data)
3319 W_ColorPanel *panel = (W_ColorPanel*)data;
3320 W_Screen *scr = WMWidgetScreen(panel->win);
3321 int item;
3322 char *filename;
3323 RImage *tmp = NULL;
3325 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3326 if (item == panel->currentPalette)
3327 return;
3329 if (item == 0)
3330 customRenderSpectrum(panel);
3331 else {
3332 /* Load file from configpath */
3333 filename = wstrappend( panel->configurationPath,
3334 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item) );
3336 /* XXX To do: Check existence of file and remove it from the history
3337 * if it doesn't exist */
3339 tmp = RLoadImage(scr->rcontext, filename, 0);
3340 if (tmp) {
3341 if (panel->customPaletteImg) {
3342 RDestroyImage(panel->customPaletteImg);
3343 panel->customPaletteImg = NULL;
3345 panel->customPaletteImg = tmp;
3347 wfree(filename);
3349 customSetPalette(panel);
3351 panel->currentPalette = item;
3355 /*************** Panel Initialisation Functions *****************/
3357 static void
3358 wheelInit(W_ColorPanel *panel)
3360 RHSVColor cur_hsv;
3361 int i;
3362 int v;
3364 RRGBtoHSV(&panel->color, &cur_hsv);
3366 WMSetSliderValue(panel->wheelBrightnessS, 255-cur_hsv.value);
3367 wheelUpdateBrightnessGradientFromHSV(panel, cur_hsv);
3369 panel->colx = 2 + rint((colorWheelSize / 2.0) * (1 + (
3370 cur_hsv.saturation/255.0) * cos( cur_hsv.hue*M_PI/180.0)));
3371 panel->coly = 2 + rint((colorWheelSize / 2.0) * (1 + (
3372 cur_hsv.saturation/255.0) * sin(-cur_hsv.hue*M_PI/180.0)));
3374 for (i = 0; i < 256; i++) {
3375 /* We divide by 128 in advance, and check whether that number divides
3376 * by 2 properly. If not, we add one to round the number correctly
3378 v = (i*cur_hsv.value) >> 7;
3379 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + (v & 1));
3383 static void
3384 grayInit(W_ColorPanel *panel)
3386 RHSVColor cur_hsv;
3387 int value;
3388 char tmp[4];
3390 RRGBtoHSV(&panel->color, &cur_hsv);
3392 value = rint(cur_hsv.value/2.55);
3393 WMSetSliderValue(panel->grayBrightnessS, value);
3395 sprintf(tmp, "%d", value);
3396 WMSetTextFieldText(panel->grayBrightnessT, tmp);
3399 static void
3400 rgbInit(W_ColorPanel *panel)
3402 char tmp[4];
3404 WMSetSliderValue(panel->rgbRedS,panel->color.red);
3405 WMSetSliderValue(panel->rgbGreenS,panel->color.green);
3406 WMSetSliderValue(panel->rgbBlueS,panel->color.blue);
3408 sprintf(tmp, "%d", panel->color.red);
3409 WMSetTextFieldText(panel->rgbRedT, tmp);
3410 sprintf(tmp, "%d", panel->color.green);
3411 WMSetTextFieldText(panel->rgbGreenT, tmp);
3412 sprintf(tmp, "%d", panel->color.blue);
3413 WMSetTextFieldText(panel->rgbBlueT, tmp);
3416 static void
3417 cmykInit(W_ColorPanel *panel)
3419 int value[3];
3420 char tmp[4];
3422 value[0] = rint((255-panel->color.red)/2.55);
3423 value[1] = rint((255-panel->color.green)/2.55);
3424 value[2] = rint((255-panel->color.blue)/2.55);
3426 WMSetSliderValue(panel->cmykCyanS, value[0]);
3427 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3428 WMSetSliderValue(panel->cmykYellowS, value[2]);
3429 WMSetSliderValue(panel->cmykBlackS, 0);
3431 sprintf(tmp, "%d", value[0]);
3432 WMSetTextFieldText(panel->cmykCyanT, tmp);
3433 sprintf(tmp, "%d", value[1]);
3434 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3435 sprintf(tmp, "%d", value[2]);
3436 WMSetTextFieldText(panel->cmykYellowT, tmp);
3437 WMSetTextFieldText(panel->cmykBlackT, "0");
3440 static void
3441 hsbInit(W_ColorPanel *panel)
3443 int value[3];
3444 char tmp[4];
3446 value[0] = panel->hsvcolor.hue;
3447 value[1] = rint(panel->hsvcolor.saturation/2.55);
3448 value[2] = rint(panel->hsvcolor.value/2.55);
3450 WMSetSliderValue(panel->hsbHueS,value[0]);
3451 WMSetSliderValue(panel->hsbSaturationS,value[1]);
3452 WMSetSliderValue(panel->hsbBrightnessS,value[2]);
3454 sprintf(tmp, "%d", value[0]);
3455 WMSetTextFieldText(panel->hsbHueT, tmp);
3456 sprintf(tmp, "%d", value[1]);
3457 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3458 sprintf(tmp, "%d", value[2]);
3459 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3461 hsbUpdateBrightnessGradient(panel);
3462 hsbUpdateSaturationGradient(panel);
3463 hsbUpdateHueGradient(panel);
3469 /************************* ColorList Panel Functions **********************/
3471 static void
3472 colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text,
3473 int state, WMRect *rect)
3475 int width, height, x, y;
3476 RColor color = *((RColor *)WMGetListItem(lPtr, index)->clientData);
3477 WMScreen *scr = WMWidgetScreen(lPtr);
3478 Display *dpy = WMScreenDisplay(scr);
3479 W_ColorPanel *panel = WMGetHangedData(lPtr);
3480 WMColor *white = WMWhiteColor(scr);
3481 WMColor *black = WMBlackColor(scr);
3482 WMColor *fillColor;
3484 width = rect->size.width;
3485 height = rect->size.height;
3486 x = rect->pos.x;
3487 y = rect->pos.y;
3489 if (state & WLDSSelected)
3490 WMPaintColorSwatch(white, d, x +15, y, width -15, height);
3491 else
3492 XClearArea(dpy, d, x +15, y, width -15, height, False);
3494 fillColor = WMCreateRGBColor(scr, color.red*256, color.green*256,
3495 color.blue*256, False);
3497 WMSetColorInGC(fillColor, WMColorGC(fillColor));
3498 WMPaintColorSwatch(fillColor, d, x, y, 15, 15);
3499 WMReleaseColor(fillColor);
3501 WMDrawString(scr, d, WMColorGC(black), panel->font12, x+18, y, text,
3502 strlen(text));
3504 WMReleaseColor(white);
3505 WMReleaseColor(black);
3509 static void
3510 colorListSelect(WMWidget *w, void *data)
3512 W_ColorPanel *panel = (W_ColorPanel *)data;
3513 RColor color = *((RColor *)WMGetListSelectedItem(w)->clientData);
3515 panel->lastChanged = WMColorListModeColorPanel;
3516 updateSwatch(panel, color);
3520 static void
3521 colorListColorMenuCallback(WMWidget *w, void *data)
3523 W_ColorPanel *panel = (W_ColorPanel *)data;
3524 int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
3526 switch (item) {
3527 case CLmenuAdd:
3528 break;
3529 case CLmenuRename:
3530 break;
3531 case CLmenuRemove:
3532 break;
3537 static void
3538 colorListListMenuCallback(WMWidget *w, void *data)
3540 W_ColorPanel *panel = (W_ColorPanel *)data;
3541 int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
3543 switch (item) {
3544 case CLmenuAdd:
3545 /* New Color List */
3546 colorListListMenuNew(panel);
3547 break;
3548 case CLmenuRename:
3549 break;
3550 case CLmenuRemove:
3551 break;
3556 static void
3557 colorListListMenuNew(W_ColorPanel *panel)
3563 /************************** Common utility functions ************************/
3565 static int
3566 fetchFile(char *toPath, char *srcFile, char *destFile)
3568 int src, dest;
3569 int n;
3570 char *tmp;
3571 char buf[BUFSIZE];
3573 if ((src = open(srcFile, O_RDONLY)) == 0) {
3574 wsyserror("Could not open %s", srcFile);
3575 return -1;
3578 tmp = wstrappend(toPath, destFile);
3579 if ((dest = open( tmp, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH))
3580 == 0) {
3581 wsyserror("Could not create %s", tmp);
3582 wfree(tmp);
3583 return -1;
3585 wfree(tmp);
3588 /* Copy the file */
3589 while ((n = read(src, buf, BUFSIZE)) > 0)
3591 if (write (dest, buf, n) != n) {
3592 wsyserror("Write error on file %s", destFile);
3593 return -1;
3597 return 0;
3601 char*
3602 generateNewFilename(char *curName)
3604 int n;
3605 char c;
3606 int baseLen;
3607 char *ptr;
3608 char *newName;
3611 assert(curName);
3613 ptr = curName;
3615 if (
3616 ((ptr = strrchr(ptr, '{')) == 0) ||
3617 sscanf(ptr, "{%i}%c", &n, &c) != 1
3619 return wstrappend(curName, " {1}");
3621 baseLen = ptr - curName -1;
3623 newName = wmalloc(baseLen + 16);
3624 strncpy(newName, curName, baseLen);
3625 newName[baseLen] = 0;
3627 sprintf(&newName[baseLen], " {%i}", n+1);
3629 return newName;
3633 static int
3634 get_shifts(unsigned long mask)
3636 int i=0;
3638 while (mask) {
3639 mask>>=1;
3640 i++;
3642 return i;
3646 RColor
3647 ulongToRColor(WMScreen *scr, XImage *image, unsigned long value)
3649 RColor color;
3650 int rmask, gmask, bmask;
3651 int rshift, gshift, bshift;
3653 if (scr->rcontext->depth == image->depth) {
3654 rmask = scr->rcontext->visual->red_mask;
3655 gmask = scr->rcontext->visual->green_mask;
3656 bmask = scr->rcontext->visual->blue_mask;
3657 } else {
3658 rmask = image->red_mask;
3659 gmask = image->green_mask;
3660 bmask = image->blue_mask;
3663 rshift = get_shifts(rmask) -8; /* -8 because otherwise the byte */
3664 gshift = get_shifts(gmask) -8; /* containing the color would be */
3665 bshift = get_shifts(bmask) -8; /* shifted over the edge. */
3667 color.red = (rshift > 0) ? (value & rmask) >> rshift :
3668 (value & rmask) << -rshift;
3669 color.green = (gshift > 0) ? (value & gmask) >> gshift :
3670 (value & gmask) << -gshift;
3671 color.blue = (bshift > 0) ? (value & bmask) >> bshift :
3672 (value & bmask) << -bshift;
3674 return color;
3677 #ifdef SHAPE_WAS_DEFINED
3678 #undef SHAPE_WAS_DEFINED
3679 #define SHAPE
3680 #endif