added colorwell updating through colorpanel
[wmaker-crm.git] / WINGs / wcolorpanel.c
blob293a93d152b2fd85df74dc10863bae850663fa50
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 ;-)
15 * small note: Tabstop size = 4
20 /* BUGS:
21 * For some reason after using the magnifying glass, the windowlist
22 * of the color-panel (panel->view->screen) becomes 0x0. This
23 * results in a core-dump of testcolorpanel, and in 3 times
24 * "WPrefs in free(): warning: chunk is already free." with WPrefs.
27 /* TODO:
28 * - Custom color-lists and custom colors in custom colo-lists.
29 * - Stored colors
30 * - Resizing
34 #include "WINGsP.h"
35 #include <math.h>
36 #include <unistd.h>
37 #include <ctype.h>
38 #include <fcntl.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <dirent.h>
42 #include <errno.h>
45 #ifndef PATH_MAX
46 # define PATH_MAX 1024
47 #endif
50 char *WMColorPanelColorChangedNotification = "WMColorPanelColorChangedNotification";
54 * Bitmaps for magnifying glass cursor
57 /* Cursor */
58 #define Cursor_x_hot 11
59 #define Cursor_y_hot 11
60 #define Cursor_width 32
61 #define Cursor_height 32
62 static unsigned char Cursor_bits[] = {
63 0x00,0x7e,0x00,0x00,0xc0,0x81,0x03,0x00,0x20,0x00,0x04,0x00,0x10,0x00,0x08,
64 0x00,0x08,0x00,0x10,0x00,0x04,0x00,0x20,0x00,0x02,0x00,0x40,0x00,0x02,0x00,
65 0x40,0x00,0x02,0x00,0x40,0x00,0x01,0x42,0x80,0x00,0x01,0x24,0x80,0x00,0x01,
66 0x00,0x80,0x00,0x01,0x00,0x80,0x00,0x01,0x24,0x80,0x00,0x01,0x42,0x80,0x00,
67 0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x04,0x00,0x20,
68 0x00,0x08,0x00,0x50,0x00,0x10,0x00,0x88,0x00,0x20,0x00,0x5c,0x01,0xc0,0x81,
69 0x3b,0x02,0x00,0x7e,0x70,0x05,0x00,0x00,0xe0,0x08,0x00,0x00,0xc0,0x15,0x00,
70 0x00,0x80,0x23,0x00,0x00,0x00,0x57,0x00,0x00,0x00,0x8e,0x00,0x00,0x00,0x5c,
71 0x00,0x00,0x00,0xb8,0x00,0x00,0x00,0x70};
73 /* Cursor shape-mask */
74 #define Cursor_shape_width 32
75 #define Cursor_shape_height 32
76 static unsigned char Cursor_shape_bits[] = {
77 0x00,0x7e,0x00,0x00,0xc0,0x81,0x03,0x00,0x20,0x00,0x04,0x00,0x10,0x00,0x08,
78 0x00,0x08,0x00,0x10,0x00,0x04,0x00,0x20,0x00,0x02,0x00,0x40,0x00,0x02,0x00,
79 0x40,0x00,0x02,0x00,0x40,0x00,0x01,0x42,0x80,0x00,0x01,0x24,0x80,0x00,0x01,
80 0x00,0x80,0x00,0x01,0x00,0x80,0x00,0x01,0x24,0x80,0x00,0x01,0x42,0x80,0x00,
81 0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x04,0x00,0x20,
82 0x00,0x08,0x00,0x70,0x00,0x10,0x00,0xf8,0x00,0x20,0x00,0xfc,0x01,0xc0,0x81,
83 0xfb,0x03,0x00,0x7e,0xf0,0x07,0x00,0x00,0xe0,0x0f,0x00,0x00,0xc0,0x1f,0x00,
84 0x00,0x80,0x3f,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0xfc,
85 0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x70};
87 /* Clip-mask for magnified pixels */
88 #define Cursor_mask_width 22
89 #define Cursor_mask_height 22
90 static unsigned char Cursor_mask_bits[] = {
91 0x00,0x3f,0x00,0xe0,0xff,0x01,0xf0,0xff,0x03,0xf8,0xff,0x07,0xfc,0xff,0x0f,
92 0xfe,0xff,0x1f,0xfe,0xff,0x1f,0xfe,0xff,0x1f,0xff,0xff,0x3f,0xff,0xff,0x3f,
93 0xff,0xff,0x3f,0xff,0xff,0x3f,0xff,0xff,0x3f,0xff,0xff,0x3f,0xfe,0xff,0x1f,
94 0xfe,0xff,0x1f,0xfe,0xff,0x1f,0xfc,0xff,0x0f,0xf8,0xff,0x07,0xf0,0xff,0x03,
95 0xe0,0xff,0x01,0x00,0x3f,0x00};
98 typedef struct MovingView {
99 WMView *view; /* The view this is all about */
100 Pixmap pixmap; /* What's under the view */
101 Pixmap mask; /* Pixmap mask for view-contents */
102 int valid; /* Are contents still valid ? */
103 RColor color; /* Color of a pixel in the image */
104 } MovingView;
106 typedef struct WheelMatrix {
107 unsigned int width, height; /* Size of the colorwheel */
108 unsigned char *data[3]; /* Wheel data (R,G,B) */
109 unsigned char values[256]; /* Precalculated values R,G & B = 0-255 */
110 } wheelMatrix;
112 typedef struct W_ColorPanel {
113 WMWindow *win;
114 WMFont *font8;
115 WMFont *font12;
117 void *clientData;
118 WMAction2 *action;
120 /* Common Stuff */
121 WMColorWell *colorWell;
122 WMButton *magnifyBtn;
123 WMButton *wheelBtn;
124 WMButton *slidersBtn;
125 WMButton *customPaletteBtn;
126 WMButton *colorListBtn;
128 /* Magnifying Glass */
129 MovingView *magnifyGlass;
131 /* ColorWheel Panel */
132 WMFrame *wheelFrm;
133 WMSlider *wheelBrightnessS;
134 WMView *wheelView;
136 /* Slider Panels */
137 WMFrame *slidersFrm;
138 WMFrame *seperatorFrm;
139 WMButton *grayBtn;
140 WMButton *rgbBtn;
141 WMButton *cmykBtn;
142 WMButton *hsbBtn;
143 /* Gray Scale Panel */
144 WMFrame *grayFrm;
145 WMLabel *grayMinL;
146 WMLabel *grayMaxL;
147 WMSlider *grayBrightnessS;
148 WMTextField *grayBrightnessT;
149 WMButton *grayPresetBtn[7];
151 /* RGB Panel */
152 WMFrame *rgbFrm;
153 WMLabel *rgbMinL;
154 WMLabel *rgbMaxL;
155 WMSlider *rgbRedS;
156 WMSlider *rgbGreenS;
157 WMSlider *rgbBlueS;
158 WMTextField *rgbRedT;
159 WMTextField *rgbGreenT;
160 WMTextField *rgbBlueT;
162 /* CMYK Panel */
163 WMFrame *cmykFrm;
164 WMLabel *cmykMinL;
165 WMLabel *cmykMaxL;
166 WMSlider *cmykCyanS;
167 WMSlider *cmykMagentaS;
168 WMSlider *cmykYellowS;
169 WMSlider *cmykBlackS;
170 WMTextField *cmykCyanT;
171 WMTextField *cmykMagentaT;
172 WMTextField *cmykYellowT;
173 WMTextField *cmykBlackT;
175 /* HSB Panel */
176 WMFrame *hsbFrm;
177 WMSlider *hsbHueS;
178 WMSlider *hsbSaturationS;
179 WMSlider *hsbBrightnessS;
180 WMTextField *hsbHueT;
181 WMTextField *hsbSaturationT;
182 WMTextField *hsbBrightnessT;
184 /* Custom Palette Panel*/
185 WMFrame *customPaletteFrm;
186 WMPopUpButton *customPaletteHistoryBtn;
187 WMFrame *customPaletteContentFrm;
188 WMPopUpButton *customPaletteMenuBtn;
189 WMView *customPaletteContentView;
191 /* Color List Panel */
192 WMFrame *colorListFrm;
193 WMPopUpButton *colorListHistoryBtn;
194 WMList *colorListContentLst;
195 WMPopUpButton *colorListColorMenuBtn;
196 WMPopUpButton *colorListListMenuBtn;
198 /* Look-Up Tables and Images */
199 wheelMatrix *wheelMtrx;
200 Pixmap wheelImg;
201 Pixmap selectionImg;
202 Pixmap selectionBackImg;
203 RImage *customPaletteImg;
204 char *lastBrowseDir;
206 /* Common Data Fields */
207 RColor color; /* Current color */
208 Bool colorSet; /* Is color already set ? */
209 RHSVColor hsvcolor; /* Backup HSV Color */
210 WMColorPanelMode mode; /* Current color selection mode */
211 WMColorPanelMode slidersmode;/* Current color sel. mode sliders panel */
212 WMColorPanelMode lastChanged;/* Panel that last changed the color */
213 int colx, coly; /* (x,y) of sel.-marker in WheelMode */
214 int palx, paly; /* (x,y) of sel.-marker in
215 CustomPaletteMode */
216 float palXRatio, palYRatio; /* Ratios in x & y between
217 original and scaled
218 palettesize */
219 int currentPalette;
220 char *configurationPath;
222 struct {
223 unsigned int continuous:1;
225 unsigned int dragging:1;
226 } flags;
227 } W_ColorPanel;
229 enum {
230 CPmenuNewFromFile,
231 CPmenuRename,
232 CPmenuRemove,
233 CPmenuCopy,
234 CPmenuNewFromClipboard
235 } customPaletteMenuItem;
237 enum {
238 CLmenuAdd,
239 CLmenuRename,
240 CLmenuRemove
241 } colorListMenuItem;
244 #define PWIDTH 194
245 #define PHEIGHT 266
246 #define colorWheelSize 150
247 #define customPaletteWidth 182
248 #define customPaletteHeight 106
249 #define knobThickness 8
251 #define SPECTRUM_WIDTH 511
252 #define SPECTRUM_HEIGHT 360
254 #define COLORWHEEL_PART 1
255 #define CUSTOMPALETTE_PART 2
256 #define BUFSIZE 1024
258 #undef EASTEREGG
260 #define RGBTXT "/usr/X11R6/lib/X11/rgb.txt"
261 #define MAX_LENGTH 1024
263 static int fetchFile(char* toPath, char *imageSrcFile,
264 char *imageDestFileName);
265 char *generateNewFilename(char *curName);
267 static void modeButtonCallback(WMWidget *w, void *data);
268 static int getPickerPart(W_ColorPanel *panel, int x, int y);
269 static void readConfiguration(W_ColorPanel *panel);
270 static void readXColors(W_ColorPanel *panel);
272 static void closeWindowCallback(WMWidget *w, void *data);
274 static Cursor magnifyGrabPointer(W_ColorPanel *panel);
275 static WMPoint magnifyInitialize(W_ColorPanel *panel);
276 static void magnifyPutCursor(WMWidget *w, void *data);
277 static Pixmap magnifyCreatePixmap(WMColorPanel *panel);
278 static Pixmap magnifyGetStorePixmap(W_ColorPanel *panel, int x1, int y1,
279 int x2, int y2);
280 static Pixmap magnifyGetImage(WMScreen *scr, int x, int y);
282 static wheelMatrix* wheelCreateMatrix(unsigned int width , unsigned int height);
283 static void wheelDestroyMatrix(wheelMatrix *matrix);
284 static wheelMatrix* wheelInitMatrix(W_ColorPanel *panel);
285 static void wheelRender(W_ColorPanel *panel);
286 static Bool wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs);
287 static void wheelPaint(W_ColorPanel *panel);
289 static void wheelHandleEvents(XEvent *event, void *data);
290 static void wheelHandleActionEvents(XEvent *event, void *data);
291 static void wheelBrightnessSliderCallback(WMWidget *w, void *data);
292 static void wheelUpdateSelection(W_ColorPanel *panel);
293 static void wheelUndrawSelection(W_ColorPanel *panel);
295 static void wheelPositionSelection(W_ColorPanel *panel, int x, int y);
296 static void wheelPositionSelectionOutBounds(W_ColorPanel *panel, int x, int y);
297 static void wheelUpdateBrightnessGradientFromHSV (W_ColorPanel *panel,
298 RHSVColor topColor);
299 static void wheelUpdateBrightnessGradientFromLocation (W_ColorPanel *panel);
300 static void wheelUpdateBrightnessGradient(W_ColorPanel *panel, RColor topColor);
302 static void grayBrightnessSliderCallback(WMWidget *w, void *data);
303 static void grayPresetButtonCallback(WMWidget *w, void *data);
304 static void grayBrightnessTextFieldCallback(void *observerData,
305 WMNotification *notification);
307 static void rgbSliderCallback(WMWidget *w, void *data);
308 static void rgbTextFieldCallback(void *observerData,
309 WMNotification *notification);
311 static void cmykSliderCallback(WMWidget *w, void *data);
312 static void cmykTextFieldCallback(void *observerData,
313 WMNotification *notification);
315 static void hsbSliderCallback(WMWidget *w, void *data);
316 static void hsbTextFieldCallback(void *observerData,
317 WMNotification *notification);
318 static void hsbUpdateBrightnessGradient(W_ColorPanel *panel);
319 static void hsbUpdateSaturationGradient(W_ColorPanel *panel);
320 static void hsbUpdateHueGradient(W_ColorPanel *panel);
322 static void customRenderSpectrum(W_ColorPanel *panel);
323 static void customSetPalette(W_ColorPanel *panel);
324 static void customPaletteHandleEvents(XEvent *event, void *data);
325 static void customPaletteHandleActionEvents(XEvent *event, void *data);
326 static void customPalettePositionSelection(W_ColorPanel *panel, int x, int y);
327 static void customPalettePositionSelectionOutBounds(W_ColorPanel *panel,
328 int x, int y);
329 static void customPaletteMenuCallback(WMWidget *w, void *data);
330 static void customPaletteHistoryCallback(WMWidget *w, void *data);
332 static void customPaletteMenuNewFromFile(W_ColorPanel *panel);
333 static void customPaletteMenuRename(W_ColorPanel *panel);
334 static void customPaletteMenuRemove(W_ColorPanel *panel);
336 static void colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text,
337 int state, WMRect *rect);
338 static void colorListSelect(WMWidget *w, void *data);
339 static void colorListColorMenuCallback(WMWidget *w, void *data);
340 static void colorListListMenuCallback(WMWidget *w, void *data);
341 static void colorListListMenuNew(W_ColorPanel *panel);
343 static void wheelInit(W_ColorPanel *panel);
344 static void grayInit(W_ColorPanel *panel);
345 static void rgbInit(W_ColorPanel *panel);
346 static void cmykInit(W_ColorPanel *panel);
347 static void hsbInit(W_ColorPanel *panel);
351 void
352 WMSetColorPanelAction(WMColorPanel *panel, WMAction2 *action, void *data)
354 panel->action = action;
355 panel->clientData = data;
358 static WMColorPanel*
359 makeColorPanel(WMScreen *scrPtr, char *name)
361 WMColorPanel *panel;
362 RImage *image;
363 WMPixmap *pixmap;
364 RColor from;
365 RColor to;
366 WMColor *textcolor;
367 int i;
368 int x,y;
371 panel = wmalloc(sizeof(WMColorPanel));
372 memset(panel, 0, sizeof(WMColorPanel));
374 panel->colorSet = False; /* Color has not been set yet */
376 panel->font8 = WMSystemFontOfSize(scrPtr, 8);
377 panel->font12 = WMSystemFontOfSize(scrPtr, 12);
379 panel->win = WMCreateWindowWithStyle(scrPtr, name,
380 WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
381 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
382 WMSetWindowTitle(panel->win, "Colors");
383 WMSetWindowCloseAction(panel->win, closeWindowCallback, panel);
386 /* Set Default ColorPanel Mode(s) */
387 panel->mode = WMWheelModeColorPanel;
388 panel->lastChanged = WMWheelModeColorPanel;
389 panel->slidersmode = WMRGBModeColorPanel;
390 panel->configurationPath = wstrappend(wusergnusteppath(),
391 "/Library/Colors/");
393 /* Some General Purpose Widgets */
394 panel->colorWell = WMCreateColorWell(panel->win);
395 WMResizeWidget(panel->colorWell, 134, 36);
396 WSetColorWellBordered(panel->colorWell, False);
397 WMMoveWidget(panel->colorWell, 56, 4);
399 panel->magnifyBtn = WMCreateCustomButton(panel->win,
400 WBBStateLightMask|WBBStateChangeMask);
401 WMResizeWidget(panel->magnifyBtn, 46, 36);
402 WMMoveWidget(panel->magnifyBtn, 6,4);
403 WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
404 WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
405 WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
407 panel->wheelBtn = WMCreateCustomButton(panel->win,
408 WBBStateLightMask|WBBStateChangeMask);
409 WMResizeWidget(panel->wheelBtn, 46, 32);
410 WMMoveWidget(panel->wheelBtn, 6, 44);
411 WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
412 WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
413 WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
415 panel->slidersBtn = WMCreateCustomButton(panel->win,
416 WBBStateLightMask|WBBStateChangeMask);
417 WMResizeWidget(panel->slidersBtn, 46, 32);
418 WMMoveWidget(panel->slidersBtn, 52, 44);
419 WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
420 WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
421 WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
423 panel->customPaletteBtn = WMCreateCustomButton(panel->win,
424 WBBStateLightMask|WBBStateChangeMask);
425 WMResizeWidget(panel->customPaletteBtn, 46, 32);
426 WMMoveWidget(panel->customPaletteBtn, 98, 44);
427 WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
428 WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
429 WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
431 panel->colorListBtn = WMCreateCustomButton(panel->win,
432 WBBStateLightMask|WBBStateChangeMask);
433 WMResizeWidget(panel->colorListBtn, 46, 32);
434 WMMoveWidget(panel->colorListBtn, 144, 44);
435 WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
436 WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
437 WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
439 /* Let's Group some of them together */
440 WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
441 WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
442 WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
444 /* Widgets for the ColorWheel Panel */
445 panel->wheelFrm = WMCreateFrame(panel->win);
446 WMSetFrameRelief(panel->wheelFrm, WRFlat);
447 WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
448 WMMoveWidget(panel->wheelFrm, 5, 80);
450 panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
451 /* XXX Can we create a view ? */
452 W_ResizeView(panel->wheelView, colorWheelSize+4, colorWheelSize+4);
453 W_MoveView(panel->wheelView, 0, 0);
455 /* Create an event handler to handle expose/click events in ColorWheel */
456 WMCreateEventHandler(panel->wheelView,
457 ButtonPressMask|ButtonReleaseMask|EnterWindowMask|
458 LeaveWindowMask|ButtonMotionMask, wheelHandleActionEvents, panel);
460 WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents,
461 panel);
463 panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
464 WMResizeWidget(panel->wheelBrightnessS, 16, 153);
465 WMMoveWidget(panel->wheelBrightnessS, 5+colorWheelSize+14, 1);
466 WMSetSliderMinValue(panel->wheelBrightnessS, 0);
467 WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
468 WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback,
469 panel);
470 WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
473 /* Widgets for the Slider Panels */
474 panel->slidersFrm = WMCreateFrame(panel->win);
475 WMSetFrameRelief(panel->slidersFrm, WRFlat);
476 WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
477 WMMoveWidget(panel->slidersFrm, 4, 80);
479 panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
480 WMSetFrameRelief(panel->seperatorFrm, WRPushed);
481 WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
482 WMMoveWidget(panel->seperatorFrm, 0, 1);
484 panel->grayBtn = WMCreateCustomButton(panel->slidersFrm,
485 WBBStateLightMask|WBBStateChangeMask);
486 WMResizeWidget(panel->grayBtn, 46, 24);
487 WMMoveWidget(panel->grayBtn, 1, 8);
488 WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
489 WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
490 WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
492 panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm,
493 WBBStateLightMask|WBBStateChangeMask);
494 WMResizeWidget(panel->rgbBtn, 46, 24);
495 WMMoveWidget(panel->rgbBtn, 47, 8);
496 WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
497 WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
498 WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
500 panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm,
501 WBBStateLightMask|WBBStateChangeMask);
502 WMResizeWidget(panel->cmykBtn, 46, 24);
503 WMMoveWidget(panel->cmykBtn, 93, 8);
504 WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
505 WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
506 WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
508 panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm,
509 WBBStateLightMask|WBBStateChangeMask);
510 WMResizeWidget(panel->hsbBtn, 46, 24);
511 WMMoveWidget(panel->hsbBtn, 139, 8);
512 WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
513 WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
514 WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
516 /* Let's Group the Slider Panel Buttons Together */
517 WMGroupButtons(panel->grayBtn, panel->rgbBtn);
518 WMGroupButtons(panel->grayBtn, panel->cmykBtn);
519 WMGroupButtons(panel->grayBtn, panel->hsbBtn);
521 textcolor = WMDarkGrayColor(scrPtr);
523 /* Widgets for GrayScale Panel */
524 panel->grayFrm = WMCreateFrame(panel->slidersFrm);
525 WMSetFrameRelief(panel->grayFrm, WRFlat);
526 WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
527 WMMoveWidget(panel->grayFrm, 0, 34);
529 panel->grayMinL = WMCreateLabel(panel->grayFrm);
530 WMResizeWidget(panel->grayMinL, 20, 10);
531 WMMoveWidget(panel->grayMinL, 2, 2);
532 WMSetLabelText(panel->grayMinL, "0");
533 WMSetLabelTextAlignment(panel->grayMinL, WALeft);
534 WMSetLabelTextColor(panel->grayMinL, textcolor);
535 WMSetLabelFont(panel->grayMinL, panel->font8);
537 panel->grayMaxL = WMCreateLabel(panel->grayFrm);
538 WMResizeWidget(panel->grayMaxL, 40, 10);
539 WMMoveWidget(panel->grayMaxL, 104, 2);
540 WMSetLabelText(panel->grayMaxL, "100");
541 WMSetLabelTextAlignment(panel->grayMaxL, WARight);
542 WMSetLabelTextColor(panel->grayMaxL, textcolor);
543 WMSetLabelFont(panel->grayMaxL, panel->font8);
545 panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
546 WMResizeWidget(panel->grayBrightnessS, 141, 16);
547 WMMoveWidget(panel->grayBrightnessS, 2, 14);
548 WMSetSliderMinValue(panel->grayBrightnessS, 0);
549 WMSetSliderMaxValue(panel->grayBrightnessS, 100);
550 WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
551 WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback,
552 panel);
554 from.red = 0;
555 from.green = 0;
556 from.blue = 0;
558 to.red = 255;
559 to.green = 255;
560 to.blue = 255;
562 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
563 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
564 RDestroyImage(image);
565 W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap,
566 panel->font12, 2, 0, 100, WALeft, WMColorGC(scrPtr->white),
567 False, "Brightness", strlen("Brightness"));
568 WMSetSliderImage(panel->grayBrightnessS, pixmap);
569 WMReleasePixmap(pixmap);
571 panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
572 WMResizeWidget(panel->grayBrightnessT, 40, 18);
573 WMMoveWidget(panel->grayBrightnessT, 146, 13);
574 WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
575 WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel,
576 WMTextDidEndEditingNotification, panel->grayBrightnessT);
578 image = RCreateImage(13,13,False);
579 for (i=0; i < 7; i++) {
580 for (x=0; x < 13; x++) {
581 for (y=0; y < 13; y++) {
582 image->data[0][y*13+x] = 255/6*i;
583 image->data[1][y*13+x] = 255/6*i;
584 image->data[2][y*13+x] = 255/6*i;
587 panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
588 WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
589 WMMoveWidget(panel->grayPresetBtn[i], 2+(i*20), 34);
590 WMSetButtonAction(panel->grayPresetBtn[i],
591 grayPresetButtonCallback, panel);
592 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
593 WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
594 WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
595 WMReleasePixmap(pixmap);
597 RDestroyImage(image);
598 /* End of GrayScale Panel */
600 /* Widgets for RGB Panel */
601 panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
602 WMSetFrameRelief(panel->rgbFrm, WRFlat);
603 WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
604 WMMoveWidget(panel->rgbFrm, 0, 34);
606 panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
607 WMResizeWidget(panel->rgbMinL, 20, 10);
608 WMMoveWidget(panel->rgbMinL, 2, 2);
609 WMSetLabelText(panel->rgbMinL, "0");
610 WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
611 WMSetLabelTextColor(panel->rgbMinL, textcolor);
612 WMSetLabelFont(panel->rgbMinL, panel->font8);
614 panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
615 WMResizeWidget(panel->rgbMaxL, 40, 10);
616 WMMoveWidget(panel->rgbMaxL, 104, 2);
617 WMSetLabelText(panel->rgbMaxL, "255");
618 WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
619 WMSetLabelTextColor(panel->rgbMaxL, textcolor);
620 WMSetLabelFont(panel->rgbMaxL, panel->font8);
622 panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
623 WMResizeWidget(panel->rgbRedS, 141, 16);
624 WMMoveWidget(panel->rgbRedS, 2, 14);
625 WMSetSliderMinValue(panel->rgbRedS, 0);
626 WMSetSliderMaxValue(panel->rgbRedS, 255);
627 WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
628 WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
630 to.red = 255;
631 to.green = 0;
632 to.blue = 0;
634 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
635 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
636 W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12,
637 2, 0, 100, WALeft, WMColorGC(scrPtr->white), False, "Red",
638 strlen("Red"));
639 RDestroyImage(image);
640 WMSetSliderImage(panel->rgbRedS, pixmap);
641 WMReleasePixmap(pixmap);
643 panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
644 WMResizeWidget(panel->rgbRedT, 40, 18);
645 WMMoveWidget(panel->rgbRedT, 146, 13);
646 WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
647 WMAddNotificationObserver(rgbTextFieldCallback, panel,
648 WMTextDidEndEditingNotification, panel->rgbRedT);
651 panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
652 WMResizeWidget(panel->rgbGreenS, 141, 16);
653 WMMoveWidget(panel->rgbGreenS, 2, 36);
654 WMSetSliderMinValue(panel->rgbGreenS, 0);
655 WMSetSliderMaxValue(panel->rgbGreenS, 255);
656 WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
657 WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
659 to.red = 0;
660 to.green = 255;
661 to.blue = 0;
663 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
664 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
665 W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12,
666 2, 0, 100, WALeft, WMColorGC(scrPtr->white), False, "Green",
667 strlen("Green"));
668 RDestroyImage(image);
669 WMSetSliderImage(panel->rgbGreenS, pixmap);
670 WMReleasePixmap(pixmap);
672 panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
673 WMResizeWidget(panel->rgbGreenT, 40, 18);
674 WMMoveWidget(panel->rgbGreenT, 146, 35);
675 WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
676 WMAddNotificationObserver(rgbTextFieldCallback, panel,
677 WMTextDidEndEditingNotification, panel->rgbGreenT);
680 panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
681 WMResizeWidget(panel->rgbBlueS, 141, 16);
682 WMMoveWidget(panel->rgbBlueS, 2, 58);
683 WMSetSliderMinValue(panel->rgbBlueS, 0);
684 WMSetSliderMaxValue(panel->rgbBlueS, 255);
685 WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
686 WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
688 to.red = 0;
689 to.green = 0;
690 to.blue = 255;
692 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
693 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
694 W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12,
695 2, 0, 100, WALeft, WMColorGC(scrPtr->white), False, "Blue",
696 strlen("Blue"));
697 RDestroyImage(image);
698 WMSetSliderImage(panel->rgbBlueS, pixmap);
699 WMReleasePixmap(pixmap);
701 panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
702 WMResizeWidget(panel->rgbBlueT, 40, 18);
703 WMMoveWidget(panel->rgbBlueT, 146, 57);
704 WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
705 WMAddNotificationObserver(rgbTextFieldCallback, panel,
706 WMTextDidEndEditingNotification, panel->rgbBlueT);
707 /* End of RGB Panel */
709 /* Widgets for CMYK Panel */
710 panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
711 WMSetFrameRelief(panel->cmykFrm, WRFlat);
712 WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
713 WMMoveWidget(panel->cmykFrm, 0, 34);
715 panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
716 WMResizeWidget(panel->cmykMinL, 20, 10);
717 WMMoveWidget(panel->cmykMinL, 2, 2);
718 WMSetLabelText(panel->cmykMinL, "0");
719 WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
720 WMSetLabelTextColor(panel->cmykMinL, textcolor);
721 WMSetLabelFont(panel->cmykMinL, panel->font8);
723 panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
724 WMResizeWidget(panel->cmykMaxL, 40, 10);
725 WMMoveWidget(panel->cmykMaxL, 104, 2);
726 WMSetLabelText(panel->cmykMaxL, "100");
727 WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
728 WMSetLabelTextColor(panel->cmykMaxL, textcolor);
729 WMSetLabelFont(panel->cmykMaxL, panel->font8);
731 panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
732 WMResizeWidget(panel->cmykCyanS, 141, 16);
733 WMMoveWidget(panel->cmykCyanS, 2, 14);
734 WMSetSliderMinValue(panel->cmykCyanS, 0);
735 WMSetSliderMaxValue(panel->cmykCyanS, 100);
736 WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
737 WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
739 from.red = 255;
740 from.green = 255;
741 from.blue = 255;
743 to.red = 0;
744 to.green = 255;
745 to.blue = 255;
747 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
748 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
749 W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12,
750 2, 0, 100, WALeft, WMColorGC(scrPtr->black), False, "Cyan",
751 strlen("Cyan"));
752 RDestroyImage(image);
753 WMSetSliderImage(panel->cmykCyanS, pixmap);
754 WMReleasePixmap(pixmap);
756 panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
757 WMResizeWidget(panel->cmykCyanT, 40, 18);
758 WMMoveWidget(panel->cmykCyanT, 146, 13);
759 WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
760 WMAddNotificationObserver(cmykTextFieldCallback, panel,
761 WMTextDidEndEditingNotification, panel->cmykCyanT);
764 panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
765 WMResizeWidget(panel->cmykMagentaS, 141, 16);
766 WMMoveWidget(panel->cmykMagentaS, 2, 36);
767 WMSetSliderMinValue(panel->cmykMagentaS, 0);
768 WMSetSliderMaxValue(panel->cmykMagentaS, 100);
769 WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
770 WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
772 to.red = 255;
773 to.green = 0;
774 to.blue = 255;
776 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
777 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
778 W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12,
779 2, 0, 100, WALeft, WMColorGC(scrPtr->black), False, "Magenta",
780 strlen("Magenta"));
781 RDestroyImage(image);
782 WMSetSliderImage(panel->cmykMagentaS, pixmap);
783 WMReleasePixmap(pixmap);
785 panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
786 WMResizeWidget(panel->cmykMagentaT, 40, 18);
787 WMMoveWidget(panel->cmykMagentaT, 146, 35);
788 WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
789 WMAddNotificationObserver(cmykTextFieldCallback, panel,
790 WMTextDidEndEditingNotification, panel->cmykMagentaT);
793 panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
794 WMResizeWidget(panel->cmykYellowS, 141, 16);
795 WMMoveWidget(panel->cmykYellowS, 2, 58);
796 WMSetSliderMinValue(panel->cmykYellowS, 0);
797 WMSetSliderMaxValue(panel->cmykYellowS, 100);
798 WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
799 WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
801 to.red = 255;
802 to.green = 255;
803 to.blue = 0;
805 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
806 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
807 W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12,
808 2, 0, 100, WALeft, WMColorGC(scrPtr->black), False, "Yellow",
809 strlen("Yellow"));
810 RDestroyImage(image);
811 WMSetSliderImage(panel->cmykYellowS, pixmap);
812 WMReleasePixmap(pixmap);
814 panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
815 WMResizeWidget(panel->cmykYellowT, 40, 18);
816 WMMoveWidget(panel->cmykYellowT, 146, 57);
817 WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
818 WMAddNotificationObserver(cmykTextFieldCallback, panel,
819 WMTextDidEndEditingNotification, panel->cmykYellowT);
822 panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
823 WMResizeWidget(panel->cmykBlackS, 141, 16);
824 WMMoveWidget(panel->cmykBlackS, 2, 80);
825 WMSetSliderMinValue(panel->cmykBlackS, 0);
826 WMSetSliderMaxValue(panel->cmykBlackS, 100);
827 WMSetSliderValue(panel->cmykBlackS, 0);
828 WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
829 WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
831 to.red = 0;
832 to.green = 0;
833 to.blue = 0;
835 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
836 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
837 W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12,
838 2, 0, 100, WALeft, WMColorGC(scrPtr->black), False, "Black",
839 strlen("Black"));
840 RDestroyImage(image);
841 WMSetSliderImage(panel->cmykBlackS, pixmap);
842 WMReleasePixmap(pixmap);
844 panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
845 WMResizeWidget(panel->cmykBlackT, 40, 18);
846 WMMoveWidget(panel->cmykBlackT, 146, 79);
847 WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
848 WMAddNotificationObserver(cmykTextFieldCallback, panel,
849 WMTextDidEndEditingNotification, panel->cmykBlackT);
850 /* End of CMYK Panel */
852 /* Widgets for HSB Panel */
853 panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
854 WMSetFrameRelief(panel->hsbFrm, WRFlat);
855 WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
856 WMMoveWidget(panel->hsbFrm, 0, 34);
858 panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
859 WMResizeWidget(panel->hsbHueS, 141, 16);
860 WMMoveWidget(panel->hsbHueS, 2, 14);
861 WMSetSliderMinValue(panel->hsbHueS, 0);
862 WMSetSliderMaxValue(panel->hsbHueS, 359);
863 WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
864 WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
866 panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
867 WMResizeWidget(panel->hsbHueT, 40, 18);
868 WMMoveWidget(panel->hsbHueT, 146, 13);
869 WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
870 WMAddNotificationObserver(hsbTextFieldCallback, panel,
871 WMTextDidEndEditingNotification, panel->hsbHueT);
874 panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
875 WMResizeWidget(panel->hsbSaturationS, 141, 16);
876 WMMoveWidget(panel->hsbSaturationS, 2, 36);
877 WMSetSliderMinValue(panel->hsbSaturationS, 0);
878 WMSetSliderMaxValue(panel->hsbSaturationS, 100);
879 WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
880 WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
882 panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
883 WMResizeWidget(panel->hsbSaturationT, 40, 18);
884 WMMoveWidget(panel->hsbSaturationT, 146, 35);
885 WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
886 WMAddNotificationObserver(hsbTextFieldCallback, panel,
887 WMTextDidEndEditingNotification, panel->hsbSaturationT);
890 panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
891 WMResizeWidget(panel->hsbBrightnessS, 141, 16);
892 WMMoveWidget(panel->hsbBrightnessS, 2, 58);
893 WMSetSliderMinValue(panel->hsbBrightnessS, 0);
894 WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
895 WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
896 WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
898 panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
899 WMResizeWidget(panel->hsbBrightnessT, 40, 18);
900 WMMoveWidget(panel->hsbBrightnessT, 146, 57);
901 WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
902 WMAddNotificationObserver(hsbTextFieldCallback, panel,
903 WMTextDidEndEditingNotification, panel->hsbBrightnessT);
904 /* End of HSB Panel */
907 WMReleaseColor(textcolor);
909 /* Widgets for the CustomPalette Panel */
910 panel->customPaletteFrm = WMCreateFrame(panel->win);
911 WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
912 WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
913 WMMoveWidget(panel->customPaletteFrm, 5, 80);
915 panel->customPaletteHistoryBtn = WMCreatePopUpButton(
916 panel->customPaletteFrm);
917 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, "Spectrum");
918 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
919 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn)-1);
920 WMSetPopUpButtonAction(panel->customPaletteHistoryBtn,
921 customPaletteHistoryCallback, panel);
922 WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
923 WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
925 panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
926 WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
927 WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
928 WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
930 panel->customPaletteContentView = W_CreateView(
931 W_VIEW(panel->customPaletteContentFrm));
932 /* XXX Can we create a view ? */
933 W_ResizeView(panel->customPaletteContentView, customPaletteWidth,
934 customPaletteHeight);
935 W_MoveView(panel->customPaletteContentView, 2, 2);
937 /* Create event handler to handle expose/click events in CustomPalette */
938 WMCreateEventHandler(panel->customPaletteContentView,
939 ButtonPressMask|ButtonReleaseMask|EnterWindowMask|
940 LeaveWindowMask|ButtonMotionMask, customPaletteHandleActionEvents,
941 panel);
943 WMCreateEventHandler(panel->customPaletteContentView, ExposureMask,
944 customPaletteHandleEvents, panel);
946 panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
947 WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
948 WMSetPopUpButtonText(panel->customPaletteMenuBtn, "Palette");
949 WMSetPopUpButtonAction(panel->customPaletteMenuBtn,
950 customPaletteMenuCallback, panel);
951 WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
952 WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
954 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "New from File...");
955 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "Rename...");
956 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "Remove");
957 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "Copy");
958 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "New from Clipboard");
960 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, 0);
961 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, 0);
962 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuCopy, 0);
963 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn,
964 CPmenuNewFromClipboard, 0);
966 customRenderSpectrum(panel);
967 panel->currentPalette = 0;
970 /* Widgets for the ColorList Panel */
971 panel->colorListFrm = WMCreateFrame(panel->win);
972 WMSetFrameRelief(panel->colorListFrm, WRFlat);
973 WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
974 WMMoveWidget(panel->colorListFrm, 5, 80);
976 panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
977 WMAddPopUpButtonItem(panel->colorListHistoryBtn, "X11-Colors");
978 WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn,
979 WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn)-1);
980 /* WMSetPopUpButtonAction(panel->colorListHistoryBtn,
981 * colorListHistoryCallback, panel); */
982 WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
983 WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
985 panel->colorListContentLst = WMCreateList(panel->colorListFrm);
986 WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
987 WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
988 WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
989 WMMoveWidget(panel->colorListContentLst, 0, 23);
990 WMHangData(panel->colorListContentLst, panel);
992 panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
993 WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
994 WMSetPopUpButtonText(panel->colorListColorMenuBtn, "Color");
995 WMSetPopUpButtonAction(panel->colorListColorMenuBtn,
996 colorListColorMenuCallback, panel);
997 WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16)/2, 20);
998 WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
1000 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, "Add...");
1001 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, "Rename...");
1002 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, "Remove");
1004 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuAdd, 0);
1005 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRename, 0);
1006 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRemove, 0);
1008 panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1009 WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
1010 WMSetPopUpButtonText(panel->colorListListMenuBtn, "List");
1011 WMSetPopUpButtonAction(panel->colorListListMenuBtn,
1012 colorListListMenuCallback, panel);
1013 WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16)/2, 20);
1014 WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16)/2 + 8,
1015 PHEIGHT - 130);
1017 WMAddPopUpButtonItem(panel->colorListListMenuBtn, "New...");
1018 WMAddPopUpButtonItem(panel->colorListListMenuBtn, "Rename...");
1019 WMAddPopUpButtonItem(panel->colorListListMenuBtn, "Remove");
1021 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
1022 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
1024 WMRealizeWidget(panel->win);
1025 WMMapSubwidgets(panel->win);
1027 WMMapSubwidgets(panel->wheelFrm);
1028 WMMapSubwidgets(panel->slidersFrm);
1029 WMMapSubwidgets(panel->grayFrm);
1030 WMMapSubwidgets(panel->rgbFrm);
1031 WMMapSubwidgets(panel->cmykFrm);
1032 WMMapSubwidgets(panel->hsbFrm);
1033 WMMapSubwidgets(panel->customPaletteFrm);
1034 WMMapSubwidgets(panel->customPaletteContentFrm);
1035 WMMapSubwidgets(panel->colorListFrm);
1037 readConfiguration(panel);
1038 readXColors(panel);
1040 return panel;
1044 WMColorPanel*
1045 WMGetColorPanel(WMScreen *scrPtr)
1047 WMColorPanel *panel;
1049 if (scrPtr->sharedColorPanel)
1050 return scrPtr->sharedColorPanel;
1052 panel = makeColorPanel(scrPtr, "colorPanel");
1054 scrPtr->sharedColorPanel = panel;
1056 return panel;
1060 void
1061 WMFreeColorPanel(WMColorPanel *panel)
1063 W_Screen *scr = WMWidgetScreen(panel->win);
1065 if (panel == scr->sharedColorPanel) {
1066 scr->sharedColorPanel = NULL;
1069 WMRemoveNotificationObserver(panel);
1071 WMUnmapWidget(panel->win);
1072 WMDestroyWidget(panel->win);
1074 /* fonts */
1075 if (panel->font8)
1076 WMReleaseFont(panel->font8);
1077 if (panel->font12)
1078 WMReleaseFont(panel->font12);
1080 /* pixmaps */
1081 if (panel->wheelMtrx)
1082 wheelDestroyMatrix(panel->wheelMtrx);
1083 if (panel->wheelImg)
1084 XFreePixmap(scr->display, panel->wheelImg);
1085 if (panel->selectionImg)
1086 XFreePixmap(scr->display, panel->selectionImg);
1087 if (panel->selectionBackImg)
1088 XFreePixmap(scr->display, panel->selectionBackImg);
1089 if (panel->customPaletteImg)
1090 RDestroyImage(panel->customPaletteImg);
1092 /* structs */
1093 if (panel->lastBrowseDir)
1094 free(panel->lastBrowseDir);
1095 if (panel->configurationPath)
1096 free(panel->configurationPath);
1098 free(panel);
1102 void
1103 WMCloseColorPanel(WMColorPanel *panel)
1105 WMCloseWindow(panel->win);
1106 WMFreeColorPanel(panel);
1110 void
1111 WMShowColorPanel(WMColorPanel *panel)
1113 WMScreen *scr = WMWidgetScreen(panel->win);
1114 WMColor *white = WMWhiteColor(scr);
1116 if (!panel->colorSet )
1117 WMSetColorPanelColor(panel, white);
1118 WMReleaseColor(white);
1120 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1121 wheelInit(panel);
1123 WMMapWidget(panel->win);
1127 static void
1128 closeWindowCallback(WMWidget *w, void *data)
1130 W_ColorPanel *panel = (W_ColorPanel*)data;
1132 WMCloseColorPanel(panel);
1136 static void
1137 readConfiguration(W_ColorPanel *panel)
1139 /* XXX Doesn't take care of "invalid" files */
1141 DIR *dPtr;
1142 struct dirent *dp;
1143 struct stat stat_buf;
1146 if (stat(panel->configurationPath, &stat_buf)!=0) {
1147 if (mkdir(panel->configurationPath,
1148 S_IRWXU|S_IRGRP|S_IROTH|S_IXGRP|S_IXOTH)!=0) {
1149 wsyserror("ColorPanel could not create directory %s needed"
1150 " to store configurations", panel->configurationPath);
1151 WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
1152 WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
1153 WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
1154 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1155 "File Error", "Could not create ColorPanel configuration"
1156 " directory", "OK", NULL, NULL);
1158 return;
1161 dPtr = opendir(panel->configurationPath);
1162 while ((dp = readdir(dPtr)) != NULL) {
1163 if (dp->d_name[0] != '.')
1164 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
1166 (void)closedir(dPtr);
1170 static void
1171 readXColors(W_ColorPanel *panel)
1173 struct stat stat_buf;
1174 FILE *rgbtxt;
1175 char line[MAX_LENGTH];
1176 int red, green, blue;
1177 char name[48];
1178 RColor *color;
1179 WMListItem *item;
1181 if (stat(RGBTXT, &stat_buf) != 0) {
1182 wwarning("Cannot find file %s", RGBTXT);
1183 return;
1185 else {
1186 rgbtxt = fopen(RGBTXT, "r");
1187 if (rgbtxt) {
1188 while (fgets(line, MAX_LENGTH, rgbtxt)) {
1189 if (sscanf(line, "%d%d%d %[^\n]", &red, &green, &blue, name)) {
1190 color = wmalloc(sizeof(RColor));
1191 color->red = (unsigned char)red;
1192 color->green = (unsigned char)green;
1193 color->blue = (unsigned char)blue;
1194 item = WMAddListItem(panel->colorListContentLst, name);
1195 item->clientData = (void *)color;
1198 fclose(rgbtxt);
1200 else {
1201 wsyserror("Unable to open file %s for reading", RGBTXT);
1207 void
1208 WMSetColorPanelPickerMode(WMColorPanel *panel, WMColorPanelMode mode)
1210 W_Screen *scr = WMWidgetScreen(panel->win);
1212 if (mode != WMWheelModeColorPanel) {
1213 WMUnmapWidget(panel->wheelFrm);
1214 if (panel->selectionBackImg) {
1215 XFreePixmap(WMWidgetScreen(panel->win)->display,
1216 panel->selectionBackImg);
1217 panel->selectionBackImg = None;
1220 if (mode != WMGrayModeColorPanel)
1221 WMUnmapWidget(panel->grayFrm);
1222 if (mode != WMRGBModeColorPanel)
1223 WMUnmapWidget(panel->rgbFrm);
1224 if (mode != WMCMYKModeColorPanel)
1225 WMUnmapWidget(panel->cmykFrm);
1226 if (mode != WMHSBModeColorPanel)
1227 WMUnmapWidget(panel->hsbFrm);
1228 if (mode != WMCustomPaletteModeColorPanel) {
1229 WMUnmapWidget(panel->customPaletteFrm);
1230 if (panel->selectionBackImg) {
1231 XFreePixmap(WMWidgetScreen(panel->win)->display,
1232 panel->selectionBackImg);
1233 panel->selectionBackImg = None;
1236 if (mode != WMColorListModeColorPanel)
1237 WMUnmapWidget(panel->colorListFrm);
1238 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
1239 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1240 WMUnmapWidget(panel->slidersFrm);
1241 else
1242 panel->slidersmode = mode;
1244 if (mode == WMWheelModeColorPanel) {
1245 WMMapWidget(panel->wheelFrm);
1246 WMSetButtonSelected(panel->wheelBtn, True);
1247 if (panel->lastChanged != WMWheelModeColorPanel)
1248 wheelInit(panel);
1249 wheelRender(panel);
1250 wheelPaint(panel);
1251 } else if (mode == WMGrayModeColorPanel) {
1252 WMMapWidget(panel->slidersFrm);
1253 WMSetButtonSelected(panel->slidersBtn, True);
1254 WMMapWidget(panel->grayFrm);
1255 WMSetButtonSelected(panel->grayBtn, True);
1256 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1257 if (panel->lastChanged != WMGrayModeColorPanel)
1258 grayInit(panel);
1259 } else if (mode == WMRGBModeColorPanel) {
1260 WMMapWidget(panel->slidersFrm);
1261 WMSetButtonSelected(panel->slidersBtn, True);
1262 WMMapWidget(panel->rgbFrm);
1263 WMSetButtonSelected(panel->rgbBtn, True);
1264 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1265 if (panel->lastChanged != WMRGBModeColorPanel)
1266 rgbInit(panel);
1267 } else if (mode == WMCMYKModeColorPanel) {
1268 WMMapWidget(panel->slidersFrm);
1269 WMSetButtonSelected(panel->slidersBtn, True);
1270 WMMapWidget(panel->cmykFrm);
1271 WMSetButtonSelected(panel->cmykBtn, True);
1272 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1273 if (panel->lastChanged != WMCMYKModeColorPanel)
1274 cmykInit(panel);
1275 } else if (mode == WMHSBModeColorPanel) {
1276 WMMapWidget(panel->slidersFrm);
1277 WMSetButtonSelected(panel->slidersBtn, True);
1278 WMMapWidget(panel->hsbFrm);
1279 WMSetButtonSelected(panel->hsbBtn, True);
1280 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1281 if (panel->lastChanged != WMHSBModeColorPanel)
1282 hsbInit(panel);
1283 } else if (mode == WMCustomPaletteModeColorPanel) {
1284 WMMapWidget(panel->customPaletteFrm);
1285 WMSetButtonSelected(panel->customPaletteBtn, True);
1286 customSetPalette(panel);
1287 } else if (mode == WMColorListModeColorPanel) {
1288 WMMapWidget(panel->colorListFrm);
1289 WMSetButtonSelected(panel->colorListBtn, True);
1292 panel->mode = mode;
1296 WMColor*
1297 WMGetColorPanelColor(WMColorPanel *panel)
1299 return WMGetColorWellColor(panel->colorWell);
1303 void
1304 WMSetColorPanelColor(WMColorPanel *panel, WMColor *color)
1306 WMScreen *scr = WMWidgetScreen(panel->win);
1307 RHSVColor hsvcolor;
1308 RColor intcolor;
1309 GC bgc = WMColorGC(scr->black);
1310 GC wgc = WMColorGC(scr->white);
1311 int originalHue;
1313 WMSetColorWellColor(panel->colorWell, color);
1315 intcolor.red = color->color.red >> 8;
1316 intcolor.green = color->color.green >> 8;
1317 intcolor.blue = color->color.blue >> 8;
1319 panel->color = intcolor;
1320 panel->colorSet = True;
1322 /* If color was set by HSB-Panel do not convert back to hsv */
1323 if (panel->lastChanged != WMHSBModeColorPanel) {
1325 /* if color is black, hue is undetermined, so it must be restored */
1326 if ((panel->color.red == 0) &&
1327 (panel->color.green == 0) &&
1328 (panel->color.blue == 0) &&
1329 (panel->hsvcolor.hue <= 359))
1331 originalHue = panel->hsvcolor.hue;
1332 RRGBtoHSV(&panel->color, &panel->hsvcolor);
1333 panel->hsvcolor.hue = originalHue;
1334 } else {
1335 RRGBtoHSV(&panel->color, &panel->hsvcolor);
1339 panel->wheelMtrx = wheelInitMatrix(panel); /* Needs to be done After Color is set */
1341 /* Maybe put this in a sub-function ... Initialising selected images */
1342 RRGBtoHSV(&intcolor, &hsvcolor);
1343 panel->colx = 2 + rint((colorWheelSize / 2.0) * (1 +
1344 (hsvcolor.saturation/255.0) * cos( hsvcolor.hue*M_PI/180.0)));
1345 panel->coly = 2 + rint((colorWheelSize / 2.0) * (1 +
1346 (hsvcolor.saturation/255.0) * sin(-hsvcolor.hue*M_PI/180.0)));
1347 wheelUpdateBrightnessGradientFromHSV(panel, hsvcolor);
1348 WMSetSliderValue(panel->wheelBrightnessS, 255 - hsvcolor.value);
1350 panel->selectionImg = XCreatePixmap(scr->display,
1351 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
1352 XFillRectangle(scr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1353 XFillRectangle(scr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1354 /* End of initialisation section */
1356 panel->palx = customPaletteWidth/2;
1357 panel->paly = customPaletteHeight/2;
1359 WMSetColorPanelPickerMode(panel, panel->mode);
1363 static void
1364 updateSwatch(WMColorPanel *panel, RColor color)
1366 WMScreen *scr = WMWidgetScreen(panel->win);
1367 WMColor *wellcolor;
1368 int originalHue;
1370 wellcolor = WMCreateRGBColor(scr, color.red << 8, color.green << 8,
1371 color.blue << 8, True);
1373 WMSetColorWellColor(panel->colorWell, wellcolor);
1374 WMReleaseColor(wellcolor);
1376 panel->color = color;
1378 /* If color was set by HSB-Panel do not convert back to hsv */
1379 if (panel->lastChanged != WMHSBModeColorPanel) {
1381 /* if color is black, hue is undetermined, so it must be restored */
1382 if ((panel->color.red == 0) &&
1383 (panel->color.green == 0) &&
1384 (panel->color.blue == 0) &&
1385 (panel->hsvcolor.hue <= 359))
1387 originalHue = panel->hsvcolor.hue;
1388 RRGBtoHSV(&panel->color, &panel->hsvcolor);
1389 panel->hsvcolor.hue = originalHue;
1390 } else {
1391 RRGBtoHSV(&panel->color, &panel->hsvcolor);
1395 if (!panel->flags.dragging || panel->flags.continuous) {
1396 if (panel->action)
1397 (*panel->action)(panel, panel->clientData);
1399 WMPostNotificationName(WMColorPanelColorChangedNotification, panel,
1400 NULL);
1404 static void
1405 modeButtonCallback(WMWidget *w, void *data)
1407 W_ColorPanel *panel = (W_ColorPanel*)(data);
1409 if (w == panel->wheelBtn)
1410 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1411 else if (w == panel->slidersBtn)
1412 WMSetColorPanelPickerMode(panel, panel->slidersmode);
1413 else if (w == panel->customPaletteBtn)
1414 WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
1415 else if (w == panel->colorListBtn)
1416 WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
1417 else if (w == panel->grayBtn)
1418 WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
1419 else if (w == panel->rgbBtn)
1420 WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
1421 else if (w == panel->cmykBtn)
1422 WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
1423 else if (w == panel->hsbBtn)
1424 WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
1428 /****************** Magnifying Cursor Functions *******************/
1429 static Pixmap
1430 magnifyGetImage(WMScreen *scr, int x, int y)
1432 XImage *image;
1433 Pixmap pixmap;
1434 int x0, y0, w0, h0;
1435 int displayWidth = DisplayWidth(scr->display, scr->screen);
1436 int displayHeight = DisplayHeight(scr->display, scr->screen);
1437 const int half_mask_width = (Cursor_mask_width +1)/2;
1438 const int half_mask_height = (Cursor_mask_height +1)/2;
1440 /* Coordinate correction for back pixmap
1441 * if magnifying glass is at screen-borders */
1442 x0 = 0; y0 = 0; w0 = Cursor_mask_width; h0 = Cursor_mask_height;
1444 if (x < half_mask_width) {
1445 if (x < 0) x = 0;
1446 x0 = half_mask_width - x;
1447 w0 = Cursor_mask_width - x0;
1450 if (x > displayWidth - half_mask_width) {
1451 if (x > displayWidth) x = displayWidth;
1452 w0 = Cursor_mask_width - (half_mask_width - (displayWidth - x));
1455 if (y < half_mask_height) {
1456 if (y < 0) y = 0;
1457 y0 = half_mask_height - y;
1458 h0 = Cursor_mask_height - y0;
1461 if (y > displayHeight - half_mask_height) {
1462 if (y > displayHeight) y = displayHeight;
1463 h0 = Cursor_mask_height - (half_mask_height - (displayHeight - y));
1465 /* end of coordinate correction */
1467 image = XGetImage(scr->display, scr->rootWin, x + x0 - Cursor_x_hot,
1468 y + y0 - Cursor_y_hot, w0, h0, AllPlanes, ZPixmap);
1470 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width,
1471 Cursor_mask_height, scr->depth);
1472 XPutImage(scr->display, pixmap, scr->copyGC, image, 0, 0, x0, y0, w0, h0);
1473 XDestroyImage(image);
1475 return pixmap;
1479 static Pixmap
1480 magnifyGetStorePixmap(WMColorPanel *panel, int x1, int y1, int x2, int y2)
1483 * (x1, y1) = topleft corner of existing rectangle
1484 * (x2, y2) = topleft corner of new position
1487 W_Screen *scr = WMWidgetScreen(panel->win);
1488 Pixmap pixmap;
1489 int xa, ya, xb, yb, w, h;
1491 if (x1 < x2) {
1492 xa = x2 - x1;
1493 xb = 0;
1494 } else {
1495 xa = 0;
1496 xb = x1 - x2;
1499 if (y1 < y2) {
1500 ya = y2 - y1;
1501 yb = 0;
1502 } else {
1503 ya = 0;
1504 yb = y1 - y2;
1507 w = Cursor_mask_width - abs(x1-x2);
1508 h = Cursor_mask_height - abs(y1-y2);
1510 /* Get pixmap from screen */
1511 pixmap = magnifyGetImage(scr, x2, y2);
1513 /* Copy previously stored pixmap on covered part of above pixmap */
1514 if (panel->magnifyGlass->valid)
1516 XCopyArea(scr->display, panel->magnifyGlass->pixmap, pixmap,
1517 scr->copyGC, xa, ya, w, h, xb, yb);
1519 /* Free it, so we can reuse it */
1520 XFreePixmap(scr->display, panel->magnifyGlass->pixmap);
1523 return pixmap;
1527 static Pixmap
1528 magnifyCreatePixmap(WMColorPanel *panel)
1530 W_Screen *scr = WMWidgetScreen(panel->win);
1531 int u, v;
1532 int i, j;
1533 int ofs;
1534 Pixmap magPix;
1535 Pixmap backPix;
1536 RImage *pixelImg;
1537 const int half_mask_width = Cursor_mask_width/2;
1538 const int half_mask_height = Cursor_mask_height/2;
1542 * Get image
1545 /* Rectangle that's going to be the background */
1546 backPix = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width,
1547 Cursor_mask_height , scr->depth);
1548 XCopyArea(scr->display, panel->magnifyGlass->pixmap, backPix, scr->copyGC,
1549 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
1552 * Magnify image
1555 magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width +2,
1556 Cursor_mask_height +2, scr->depth);
1558 for (u=0; u<5+1; u++) /* Copy an area of 5x5 pixels from the center */
1559 for (v=0; v<5+1; v++)
1560 for (i=u*5; i < (u+1)*5; i++) /* magnify it 5 times */
1561 for (j=v*5; j < (v+1)*5; j++)
1562 XCopyArea(scr->display, backPix, magPix, scr->copyGC,
1563 u +9, v +9, 1, 1, i, j);
1565 /* Get color under hotspot */
1566 ofs = half_mask_width + half_mask_height * Cursor_mask_width;
1567 pixelImg = RCreateImageFromDrawable(scr->rcontext, backPix, backPix);
1568 panel->magnifyGlass->color.red = pixelImg->data[0][ofs];
1569 panel->magnifyGlass->color.green = pixelImg->data[1][ofs];
1570 panel->magnifyGlass->color.blue = pixelImg->data[2][ofs];
1571 RDestroyImage(pixelImg);
1573 /* Copy the magnified pixmap, with the clip mask, to background pixmap */
1574 XSetClipMask(scr->display, scr->clipGC, panel->magnifyGlass->mask);
1575 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1577 XCopyArea(scr->display, magPix, backPix, scr->clipGC, 2, 2,
1578 Cursor_mask_width, Cursor_mask_height, 0, 0);
1579 /* (2,2) puts center pixel on center of glass */
1581 XFreePixmap(scr->display, magPix);
1583 return backPix;
1587 static WMView*
1588 magnifyCreateView(W_ColorPanel *panel)
1590 W_Screen *scr = WMWidgetScreen(panel->win);
1591 WMView *magView;
1593 magView = W_CreateTopView(scr);
1595 W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
1597 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1598 magView->attribs.event_mask = StructureNotifyMask;
1599 magView->attribs.override_redirect = True;
1600 magView->attribs.save_under = True;
1602 W_RealizeView(magView);
1604 return magView;
1608 static Cursor
1609 magnifyGrabPointer(W_ColorPanel *panel)
1611 W_Screen *scr = WMWidgetScreen(panel->win);
1612 Pixmap magPixmap, magPixmap2;
1613 Cursor magCursor;
1614 XColor fgColor = {0, 0,0,0, DoRed|DoGreen|DoBlue};
1615 XColor bgColor = {0, 0xbf00, 0xa000, 0x5000, DoRed|DoGreen|DoBlue};
1617 /* Cursor creation stuff */
1618 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1619 Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
1620 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1621 Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
1623 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1624 &fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
1626 XFreePixmap(scr->display, magPixmap);
1627 XFreePixmap(scr->display, magPixmap2);
1629 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1631 /* Set up Pointer */
1632 XGrabPointer (scr->display, panel->magnifyGlass->view->window, True,
1633 PointerMotionMask | ButtonPressMask,
1634 GrabModeAsync, GrabModeAsync,
1635 scr->rootWin, magCursor, CurrentTime);
1637 return magCursor;
1641 static WMPoint
1642 magnifyInitialize(W_ColorPanel *panel)
1644 W_Screen *scr = WMWidgetScreen(panel->win);
1645 int x, y, u, v;
1646 unsigned int mask;
1647 Pixmap pixmap;
1648 WMPoint point;
1650 XQueryPointer(scr->display, scr->rootWin, &scr->rootWin,
1651 &W_VIEW(panel->win)->window, &x, &y, &u, &v, &mask);
1654 /* Clipmask to make magnified view-contents circular */
1655 panel->magnifyGlass->mask = XCreatePixmapFromBitmapData(scr->display,
1656 W_DRAWABLE(scr), Cursor_mask_bits,
1657 Cursor_mask_width, Cursor_mask_height, 1, 0, 1);
1659 /* Draw initial magnified part */
1660 panel->magnifyGlass->valid = False;
1661 /* also free's magnifyGlass->pixmap */
1662 panel->magnifyGlass->pixmap = magnifyGetStorePixmap(panel, x, y, x, y);
1663 panel->magnifyGlass->valid = True;
1665 pixmap = magnifyCreatePixmap(panel);
1667 XSetWindowBackgroundPixmap(scr->display, panel->magnifyGlass->view->window,
1668 pixmap);
1669 XClearWindow(scr->display, panel->magnifyGlass->view->window);
1670 XFlush(scr->display);
1672 XFreePixmap(scr->display, pixmap);
1674 point.x = x;
1675 point.y = y;
1677 return point;
1681 static void
1682 magnifyPutCursor(WMWidget *w, void *data)
1684 W_ColorPanel *panel = (W_ColorPanel*)(data);
1685 W_Screen *scr = WMWidgetScreen(panel->win);
1686 Cursor magCursor;
1687 int x, y;
1688 Pixmap pixmap;
1689 XEvent event;
1690 WMPoint initialPosition;
1692 /* Destroy wheelBackImg, so it'll update properly */
1693 if (panel->selectionBackImg) {
1694 XFreePixmap(WMWidgetScreen(panel->win)->display,
1695 panel->selectionBackImg);
1696 panel->selectionBackImg = None;
1699 /* Create magnifying glass */
1700 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1701 panel->magnifyGlass->view = magnifyCreateView(panel);
1703 initialPosition = magnifyInitialize(panel);
1704 x = initialPosition.x;
1705 y = initialPosition.y;
1707 W_MoveView(panel->magnifyGlass->view,
1708 x - Cursor_x_hot +1,
1709 y - Cursor_y_hot +1);
1710 W_MapView(panel->magnifyGlass->view);
1712 magCursor = magnifyGrabPointer(panel);
1714 while(panel->magnifyGlass->valid)
1716 WMNextEvent(scr->display, &event);
1717 while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
1720 switch (event.type)
1722 case ButtonPress:
1723 if (event.xbutton.button == Button1) {
1724 updateSwatch(panel, panel->magnifyGlass->color);
1726 switch (panel->mode) {
1727 case WMWheelModeColorPanel:
1728 wheelInit(panel);
1729 wheelRender(panel);
1730 wheelPaint(panel);
1731 break;
1732 case WMGrayModeColorPanel:
1733 grayInit(panel);
1734 break;
1735 case WMRGBModeColorPanel:
1736 rgbInit(panel);
1737 break;
1738 case WMCMYKModeColorPanel:
1739 cmykInit(panel);
1740 break;
1741 case WMHSBModeColorPanel:
1742 hsbInit(panel);
1743 break;
1744 default:
1745 break;
1747 panel->lastChanged = panel->mode;
1748 panel->magnifyGlass->valid = False;
1749 WMSetButtonSelected(panel->magnifyBtn, False);
1750 break;
1752 case MotionNotify:
1753 /* Get a "dirty rectangle" */
1754 panel->magnifyGlass->pixmap = magnifyGetStorePixmap(
1755 panel, x+1, y+1,
1756 event.xmotion.x_root+1, event.xmotion.y_root+1);
1757 /* also free's magnifyGlass->pixmap */
1759 /* Update coordinates */
1760 x = event.xmotion.x_root;
1761 y = event.xmotion.y_root;
1763 /* Move view */
1764 W_MoveView(panel->magnifyGlass->view, x - Cursor_x_hot +1,
1765 y - Cursor_y_hot +1);
1767 /* Put new image (with magn.) in view */
1768 pixmap = magnifyCreatePixmap(panel);
1769 XSetWindowBackgroundPixmap(scr->display,
1770 panel->magnifyGlass->view->window, pixmap);
1771 XClearWindow(scr->display, panel->magnifyGlass->view->window);
1773 XFreePixmap(scr->display, pixmap);
1774 break;
1776 case FocusOut: /* fall through */
1777 case FocusIn:
1779 * Color Panel window (panel->win) lost or received focus.
1780 * We need to update the pixmap in the magnifying glass.
1782 XUngrabPointer(scr->display, CurrentTime);
1783 W_UnmapView(panel->magnifyGlass->view);
1785 magnifyInitialize(panel);
1787 W_MapView(panel->magnifyGlass->view);
1788 XGrabPointer (scr->display,
1789 panel->magnifyGlass->view->window,
1790 True,
1791 PointerMotionMask | ButtonPressMask,
1792 GrabModeAsync,
1793 GrabModeAsync,
1794 scr->rootWin,
1795 magCursor,
1796 CurrentTime);
1797 break;
1799 default:
1800 WMHandleEvent(&event);
1801 break;
1802 } /* of switch */
1804 panel->magnifyGlass->valid = False;
1806 XUngrabPointer(scr->display, CurrentTime);
1807 XFreeCursor(scr->display, magCursor);
1808 W_DestroyView(panel->magnifyGlass->view);
1810 XFreePixmap(scr->display, panel->magnifyGlass->mask);
1811 panel->magnifyGlass->mask = None;
1813 XFreePixmap(scr->display, panel->magnifyGlass->pixmap);
1814 panel->magnifyGlass->pixmap = None;
1816 free(panel->magnifyGlass);
1821 /****************** WheelMatrix Functions ************************/
1823 static wheelMatrix*
1824 wheelCreateMatrix(unsigned int width, unsigned int height)
1826 wheelMatrix *matrix = NULL;
1827 int i;
1829 assert((width > 0) && (height > 0));
1831 matrix = malloc(sizeof(wheelMatrix));
1832 if (!matrix) {
1833 RErrorCode = RERR_NOMEMORY;
1834 return NULL;
1837 memset(matrix, 0, sizeof(wheelMatrix));
1838 matrix->width = width;
1839 matrix->height = height;
1840 for (i = 0; i < 3; i++) {
1841 matrix->data[i] = malloc(width*height*sizeof(unsigned char));
1842 if (!matrix->data[i])
1843 goto error;
1846 return matrix;
1848 error:
1849 for (i = 0; i < 3; i++) {
1850 if (matrix->data[i])
1851 free(matrix->data[i]);
1853 if (matrix)
1854 free(matrix);
1855 RErrorCode = RERR_NOMEMORY;
1856 return NULL;
1860 static void
1861 wheelDestroyMatrix(wheelMatrix *matrix)
1863 int i;
1865 assert (matrix!=NULL);
1867 for (i = 0; i < 3; i++) {
1868 if (matrix->data[i])
1869 free(matrix->data[i]);
1871 free(matrix);
1875 static wheelMatrix*
1876 wheelInitMatrix(W_ColorPanel *panel)
1878 int i;
1879 int x,y;
1880 wheelMatrix *matrix;
1881 unsigned char *rp, *gp, *bp;
1882 RHSVColor cur_hsv;
1883 RColor cur_rgb;
1884 long ofs[4];
1885 float hue;
1886 int sat;
1887 float xcor, ycor;
1888 int dhue[4];
1890 matrix = wheelCreateMatrix(colorWheelSize+4, colorWheelSize+4);
1891 if (!matrix)
1892 return NULL;
1894 RRGBtoHSV(&panel->color, &cur_hsv);
1896 for (i = 0; i < 256; i++)
1897 matrix->values[i] = (unsigned char)(rint(i*cur_hsv.value/255));
1899 cur_hsv.value = 255;
1901 ofs[0] = -1;
1902 ofs[1] = -(colorWheelSize + 4);
1903 /* ofs[2] = 0; superfluous
1904 ofs[3] = 0;
1906 for (y = 0; y < (colorWheelSize+4)/2; y++) {
1907 for (x = y; x < (colorWheelSize+4-y); x++) {
1908 xcor = ((float)(2.0*x - 4.0) / colorWheelSize) - 1;
1909 ycor = ((float)(2.0*y - 4.0) / colorWheelSize) - 1;
1911 sat = rint(255.0 * sqrt((xcor*xcor) + (ycor*ycor)));
1915 /* offsets are counterclockwise (in triangles) */
1917 /* top quarter */
1918 if (y < (colorWheelSize+4)/2)
1919 ofs[0]++;
1921 /* left quarter */
1922 ofs[1] += colorWheelSize + 4;
1924 /* bottom quarter */
1925 ofs[2] = (colorWheelSize + 4) * (colorWheelSize + 4) - 1 - ofs[0];
1927 /* right quarter */
1928 ofs[3] = (colorWheelSize + 4) * (colorWheelSize + 4) - 1 - ofs[1];
1930 if (sat < 256) {
1931 cur_hsv.saturation = (unsigned char)sat;
1933 if (xcor != 0)
1934 hue = atan(ycor/xcor);
1935 else {
1936 if (ycor > 0)
1937 hue = M_PI * 0.5;
1938 else
1939 hue = M_PI * 1.5;
1942 if (xcor < 0)
1943 hue += M_PI;
1944 if ((xcor > 0) && (ycor < 0))
1945 hue += M_PI * 2.0;
1947 hue = -hue; /* Reverse direction of ColorWheel */
1949 if (hue < 0)
1950 hue += M_PI * 2.0;
1952 dhue[0] = (hue*360) / (M_PI * 2.0);
1954 for (i = 0; i < 4; i++) {
1956 if (i > 0)
1957 dhue[i] = (dhue[i-1] + 90) % 360;
1959 if ((i == 1) || (i == 3))
1960 dhue[i] = 360 - dhue[i];
1962 if (i == 2)
1963 dhue[i] = 360 - dhue[i] + 180;
1965 rp = matrix->data[0] + (ofs[i] * sizeof(unsigned char));
1966 gp = matrix->data[1] + (ofs[i] * sizeof(unsigned char));
1967 bp = matrix->data[2] + (ofs[i] * sizeof(unsigned char));
1969 cur_hsv.hue = dhue[i];
1970 RHSVtoRGB(&cur_hsv, &cur_rgb);
1972 *rp = (unsigned char)(cur_rgb.red);
1973 *gp = (unsigned char)(cur_rgb.green);
1974 *bp = (unsigned char)(cur_rgb.blue);
1977 else {
1978 for (i = 0; i < 4; i++) {
1979 rp = matrix->data[0] + (ofs[i] * sizeof(unsigned char));
1980 gp = matrix->data[1] + (ofs[i] * sizeof(unsigned char));
1981 bp = matrix->data[2] + (ofs[i] * sizeof(unsigned char));
1983 *rp = (unsigned char)(0);
1984 *gp = (unsigned char)(0);
1985 *bp = (unsigned char)(0);
1989 if (y < (colorWheelSize+4)/2)
1990 ofs[0] += 2*y+1;
1992 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2*y);
1995 return matrix;
1998 /****************** ColorWheel Functions *******************/
2000 static void
2001 wheelRender(W_ColorPanel *panel)
2003 W_Screen *scr = WMWidgetScreen(panel->win);
2004 int x,y;
2005 RImage *image;
2006 unsigned char *rp, *gp, *bp;
2007 RColor gray;
2008 unsigned long ofs;
2010 image = RCreateImage(colorWheelSize+4, colorWheelSize+4, False);
2011 if (!image)
2012 return;
2014 gray.red = gray.green = gray.blue = 0xaa;
2016 for (x = 0; x < colorWheelSize+4; x++) {
2017 for (y = 0; y < colorWheelSize+4; y++) {
2019 ofs = (y * image->width) + x;
2020 rp = image->data[0] + ofs;
2021 gp = image->data[1] + ofs;
2022 bp = image->data[2] + ofs;
2024 if (wheelInsideColorWheel(panel, ofs)) {
2025 *rp = (unsigned int)(panel->wheelMtrx->values[
2026 panel->wheelMtrx->data[0][ofs] ]);
2027 *gp = (unsigned int)(panel->wheelMtrx->values[
2028 panel->wheelMtrx->data[1][ofs] ]);
2029 *bp = (unsigned int)(panel->wheelMtrx->values[
2030 panel->wheelMtrx->data[2][ofs] ]);
2032 else {
2033 *rp = (unsigned char)(gray.red);
2034 *gp = (unsigned char)(gray.green);
2035 *bp = (unsigned char)(gray.blue);
2040 if (panel->wheelImg)
2041 XFreePixmap(scr->display, panel->wheelImg);
2043 panel->wheelImg = XCreatePixmap(scr->display, W_DRAWABLE(scr),
2044 colorWheelSize+4, colorWheelSize+4, scr->depth);
2045 RConvertImage(scr->rcontext, image, &panel->wheelImg);
2047 /* Check if backimage exists. If it doesn't, allocate and fill it */
2048 if (!panel->selectionBackImg) {
2049 panel->selectionBackImg = XCreatePixmap(scr->display,
2050 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
2051 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2052 scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0);
2053 /* -2 is hot spot correction */
2056 RDestroyImage(image);
2059 static Bool
2060 wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs)
2062 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
2063 (panel->wheelMtrx->data[1][ofs] != 0) &&
2064 (panel->wheelMtrx->data[2][ofs] != 0));
2067 static void
2068 wheelPaint (W_ColorPanel *panel)
2070 W_Screen *scr = WMWidgetScreen(panel->win);
2072 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
2073 scr->copyGC, 0, 0, colorWheelSize+4, colorWheelSize+4, 0, 0);
2075 /* Draw selection image */
2076 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2077 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2080 static void
2081 wheelHandleEvents(XEvent *event, void *data)
2083 W_ColorPanel *panel = (W_ColorPanel*)data;
2085 switch (event->type) {
2086 case Expose:
2087 if (event->xexpose.count != 0)
2088 break;
2089 wheelPaint(panel);
2090 break;
2094 static void
2095 wheelHandleActionEvents(XEvent *event, void *data)
2097 W_ColorPanel *panel = (W_ColorPanel*)data;
2099 switch (event->type) {
2100 case ButtonPress:
2101 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) ==
2102 COLORWHEEL_PART) {
2103 panel->flags.dragging = 1;
2104 wheelPositionSelection(panel, event->xbutton.x,
2105 event->xbutton.y);
2107 break;
2109 case ButtonRelease:
2110 panel->flags.dragging = 0;
2111 if (!panel->flags.continuous) {
2112 if (panel->action)
2113 (*panel->action)(panel->action, panel->clientData);
2115 break;
2117 case MotionNotify:
2118 if (panel->flags.dragging) {
2119 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) ==
2120 COLORWHEEL_PART) {
2121 wheelPositionSelection(panel, event->xmotion.x,
2122 event->xmotion.y);
2124 else
2125 wheelPositionSelectionOutBounds(panel, event->xmotion.x,
2126 event->xmotion.y);
2128 break;
2133 static int
2134 getPickerPart(W_ColorPanel *panel, int x, int y)
2136 int lx, ly;
2137 unsigned long ofs;
2139 lx = x;
2140 ly = y;
2142 if (panel->mode == WMWheelModeColorPanel) {
2143 if ((lx >= 2) && (lx <= 2+colorWheelSize) && (ly >= 2) &&
2144 (ly <= 2+colorWheelSize)) {
2146 ofs = ly*panel->wheelMtrx->width+lx;
2148 if (wheelInsideColorWheel(panel, ofs))
2149 return COLORWHEEL_PART;
2153 if (panel->mode == WMCustomPaletteModeColorPanel) {
2154 if ((lx >= 2) && (lx < customPaletteWidth-2) && (ly >= 2) &&
2155 (ly < customPaletteHeight-2)) {
2156 return CUSTOMPALETTE_PART;
2160 return 0;
2164 static void
2165 wheelBrightnessSliderCallback(WMWidget *w, void *data)
2167 int i;
2168 unsigned int v;
2169 int value;
2170 unsigned long ofs;
2171 RColor cur_rgb;
2173 W_ColorPanel *panel = (W_ColorPanel*)data;
2175 value = 255-WMGetSliderValue(panel->wheelBrightnessS);
2177 for (i = 0; i < 256; i++) {
2178 /* We divide by 128 in advance, and check whether that number divides
2179 * by 2 properly. If not, we add one to round the number correctly
2181 v = (i*value) >> 7;
2182 #ifdef EASTEREGG
2183 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + v);
2184 #else
2185 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) +(v & 0x01));
2186 #endif
2189 ofs = (panel->coly * panel->wheelMtrx->width) + panel->colx;
2191 if (!wheelInsideColorWheel(panel, ofs)) {
2192 panel->hsvcolor.saturation = 255;
2193 panel->hsvcolor.value = value;
2194 RHSVtoRGB(&panel->hsvcolor, &cur_rgb);
2196 panel->color = cur_rgb;
2198 else {
2199 panel->color.red = panel->wheelMtrx->values[
2200 panel->wheelMtrx->data[0][ofs] ];
2201 panel->color.green = panel->wheelMtrx->values[
2202 panel->wheelMtrx->data[1][ofs] ];
2203 panel->color.blue = panel->wheelMtrx->values[
2204 panel->wheelMtrx->data[2][ofs] ];
2207 wheelRender(panel);
2208 wheelPaint(panel);
2209 wheelUpdateSelection(panel);
2213 static void
2214 wheelUpdateSelection(W_ColorPanel *panel)
2216 W_Screen *scr = WMWidgetScreen(panel->win);
2218 updateSwatch(panel, panel->color);
2219 panel->lastChanged = WMWheelModeColorPanel;
2221 /* Redraw color selector (and make a backup of the part it will cover) */
2222 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2223 scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0);
2224 /* "-2" is correction for hotspot location */
2225 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2226 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2227 /* see above */
2230 static void
2231 wheelUndrawSelection(W_ColorPanel *panel)
2233 W_Screen *scr = WMWidgetScreen(panel->win);
2235 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
2236 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2237 /* see above */
2240 static void
2241 wheelPositionSelection(W_ColorPanel *panel, int x, int y)
2243 unsigned long ofs = (y * panel->wheelMtrx->width)+ x;
2246 panel->color.red = panel->wheelMtrx->values[
2247 panel->wheelMtrx->data[0][ofs] ];
2248 panel->color.green = panel->wheelMtrx->values[
2249 panel->wheelMtrx->data[1][ofs] ];
2250 panel->color.blue = panel->wheelMtrx->values[
2251 panel->wheelMtrx->data[2][ofs] ];
2253 wheelUndrawSelection(panel);
2255 panel->colx = x;
2256 panel->coly = y;
2258 wheelUpdateSelection(panel);
2259 wheelUpdateBrightnessGradientFromLocation(panel);
2262 static void
2263 wheelPositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
2265 RHSVColor cur_hsv;
2266 float hue;
2267 float xcor, ycor;
2269 xcor = ((x*2.0) / (colorWheelSize+4)) - 1.0;
2270 ycor = ((y*2.0) / (colorWheelSize+4)) - 1.0;
2272 cur_hsv.saturation = 255;
2273 cur_hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2275 if (xcor != 0)
2276 hue = atan(ycor/xcor);
2277 else {
2278 if (ycor > 0)
2279 hue = M_PI * 0.5;
2280 else
2281 hue = M_PI * 1.5;
2284 if (xcor < 0)
2285 hue += M_PI;
2286 if ((xcor > 0) && (ycor < 0))
2287 hue += M_PI * 2.0;
2289 hue = -hue;
2291 if (hue < 0)
2292 hue += M_PI * 2.0;
2294 cur_hsv.hue = (hue*180.0)/(M_PI);
2295 RHSVtoRGB(&cur_hsv, &panel->color);
2297 wheelUndrawSelection(panel);
2299 panel->colx = 2 + rint((colorWheelSize * (1.0 +
2300 cos( cur_hsv.hue*M_PI/180))) /2.0);
2301 /* "+2" because of "colorWheelSize + 4" */
2302 panel->coly = 2 + rint((colorWheelSize * (1.0 +
2303 sin(-cur_hsv.hue*M_PI/180))) /2.0);
2305 wheelUpdateSelection(panel);
2306 wheelUpdateBrightnessGradientFromHSV(panel, cur_hsv);
2309 static void
2310 wheelUpdateBrightnessGradientFromHSV(W_ColorPanel *panel, RHSVColor topColor)
2312 RColor from;
2314 /* Update Brightness-Slider */
2315 topColor.value = 255;
2316 RHSVtoRGB(&topColor, &from);
2318 wheelUpdateBrightnessGradient(panel, from);
2321 static void
2322 wheelUpdateBrightnessGradientFromLocation(W_ColorPanel *panel)
2324 RColor from;
2325 unsigned long ofs;
2327 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2329 from.red = panel->wheelMtrx->data[0][ofs];
2330 from.green = panel->wheelMtrx->data[1][ofs];
2331 from.blue = panel->wheelMtrx->data[2][ofs];
2333 wheelUpdateBrightnessGradient(panel, from);
2336 static void
2337 wheelUpdateBrightnessGradient(W_ColorPanel *panel, RColor topColor)
2339 RColor to;
2340 RImage *sliderImg;
2341 WMPixmap *sliderPxmp;
2343 to.red = to.green = to.blue = 0;
2345 sliderImg = RRenderGradient(16, 153, &topColor, &to, RGRD_VERTICAL);
2346 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win),
2347 sliderImg, 0);
2348 RDestroyImage(sliderImg);
2349 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
2350 WMReleasePixmap(sliderPxmp);
2353 /****************** Grayscale Panel Functions ***************/
2355 static void
2356 grayBrightnessSliderCallback(WMWidget *w, void *data)
2358 RColor color;
2359 int value;
2360 char tmp[4];
2362 W_ColorPanel *panel = (W_ColorPanel*)data;
2364 value = WMGetSliderValue(panel->grayBrightnessS);
2366 sprintf(tmp, "%d", value);
2368 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2369 color.red = color.green = color.blue = rint(2.55*value);
2371 updateSwatch(panel, color);
2372 panel->lastChanged = WMGrayModeColorPanel;
2375 static void
2376 grayPresetButtonCallback(WMWidget *w, void *data)
2378 RColor color;
2379 char tmp[4];
2380 int value;
2381 int i=0;
2383 W_ColorPanel *panel = (W_ColorPanel*)data;
2385 while (i < 7) {
2386 if (w == panel->grayPresetBtn[i])
2387 break;
2388 i++;
2391 value = rint(100.0/6.0*i);
2392 sprintf(tmp, "%d", value);
2394 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2395 color.red = color.green = color.blue = rint(255.0*i/6.0);
2397 WMSetSliderValue(panel->grayBrightnessS, rint(100.0*i/6.0));
2399 updateSwatch(panel, color);
2400 panel->lastChanged = WMGrayModeColorPanel;
2403 static void
2404 grayBrightnessTextFieldCallback(void *observerData,
2405 WMNotification *notification)
2407 RColor color;
2408 char tmp[4];
2409 int value;
2410 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2412 value = atoi(WMGetTextFieldText(panel->grayBrightnessT));
2413 if (value > 100)
2414 value = 100;
2415 if (value < 0)
2416 value = 0;
2418 sprintf(tmp, "%d", value);
2419 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2420 WMSetSliderValue(panel->grayBrightnessS, value);
2422 color.red = color.green = color.blue = rint(255.0*value/100.0);
2423 updateSwatch(panel, color);
2424 panel->lastChanged = WMGrayModeColorPanel;
2427 /******************* RGB Panel Functions *****************/
2429 static void
2430 rgbSliderCallback(WMWidget *w, void *data)
2432 RColor color;
2433 int value[3];
2434 char tmp[4];
2436 W_ColorPanel *panel = (W_ColorPanel*)data;
2438 value[0] = WMGetSliderValue(panel->rgbRedS);
2439 value[1] = WMGetSliderValue(panel->rgbGreenS);
2440 value[2] = WMGetSliderValue(panel->rgbBlueS);
2442 sprintf(tmp, "%d", value[0]);
2443 WMSetTextFieldText(panel->rgbRedT, tmp);
2444 sprintf(tmp, "%d", value[1]);
2445 WMSetTextFieldText(panel->rgbGreenT, tmp);
2446 sprintf(tmp, "%d", value[2]);
2447 WMSetTextFieldText(panel->rgbBlueT, tmp);
2449 color.red = value[0];
2450 color.green = value[1];
2451 color.blue = value[2];
2453 updateSwatch(panel, color);
2454 panel->lastChanged = WMRGBModeColorPanel;
2457 static void
2458 rgbTextFieldCallback(void *observerData, WMNotification *notification)
2460 RColor color;
2461 int value[3];
2462 char tmp[4];
2463 int n;
2464 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2466 value[0] = atoi(WMGetTextFieldText(panel->rgbRedT));
2467 value[1] = atoi(WMGetTextFieldText(panel->rgbGreenT));
2468 value[2] = atoi(WMGetTextFieldText(panel->rgbBlueT));
2470 for (n=0; n < 3; n++) {
2471 if (value[n] > 255)
2472 value[n] = 255;
2473 if (value[n] < 0)
2474 value[n] = 0;
2477 sprintf(tmp, "%d", value[0]);
2478 WMSetTextFieldText(panel->rgbRedT, tmp);
2479 sprintf(tmp, "%d", value[1]);
2480 WMSetTextFieldText(panel->rgbGreenT, tmp);
2481 sprintf(tmp, "%d", value[2]);
2482 WMSetTextFieldText(panel->rgbBlueT, tmp);
2484 WMSetSliderValue(panel->rgbRedS, value[0]);
2485 WMSetSliderValue(panel->rgbGreenS, value[1]);
2486 WMSetSliderValue(panel->rgbBlueS, value[2]);
2488 color.red = value[0];
2489 color.green = value[1];
2490 color.blue = value[2];
2492 updateSwatch(panel, color);
2493 panel->lastChanged = WMRGBModeColorPanel;
2497 /******************* CMYK Panel Functions *****************/
2499 static void
2500 cmykSliderCallback(WMWidget *w, void *data)
2502 RColor color;
2503 int value[4];
2504 char tmp[4];
2506 W_ColorPanel *panel = (W_ColorPanel*)data;
2508 value[0] = WMGetSliderValue(panel->cmykCyanS);
2509 value[1] = WMGetSliderValue(panel->cmykMagentaS);
2510 value[2] = WMGetSliderValue(panel->cmykYellowS);
2511 value[3] = WMGetSliderValue(panel->cmykBlackS);
2513 sprintf(tmp, "%d", value[0]);
2514 WMSetTextFieldText(panel->cmykCyanT, tmp);
2515 sprintf(tmp, "%d", value[1]);
2516 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2517 sprintf(tmp, "%d", value[2]);
2518 WMSetTextFieldText(panel->cmykYellowT, tmp);
2519 sprintf(tmp, "%d", value[3]);
2520 WMSetTextFieldText(panel->cmykBlackT, tmp);
2522 color.red = rint((255.0 - (value[0] * 2.55)) * (1.0 - (value[3] / 100.0)));
2523 color.green = rint((255.0 - (value[1] * 2.55)) * (1.0 - (value[3]/100.0)));
2524 color.blue = rint((255.0 - (value[2] * 2.55)) * (1.0 - (value[3] /100.0)));
2526 updateSwatch(panel, color);
2527 panel->lastChanged = WMCMYKModeColorPanel;
2530 static void
2531 cmykTextFieldCallback(void *observerData, WMNotification *notification)
2533 RColor color;
2534 int value[4];
2535 char tmp[4];
2536 int n;
2537 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2539 value[0] = atoi(WMGetTextFieldText(panel->cmykCyanT));
2540 value[1] = atoi(WMGetTextFieldText(panel->cmykMagentaT));
2541 value[2] = atoi(WMGetTextFieldText(panel->cmykYellowT));
2542 value[3] = atoi(WMGetTextFieldText(panel->cmykBlackT));
2544 for (n=0; n < 4; n++) {
2545 if (value[n] > 100)
2546 value[n] = 100;
2547 if (value[n] < 0)
2548 value[n] = 0;
2551 sprintf(tmp, "%d", value[0]);
2552 WMSetTextFieldText(panel->cmykCyanT, tmp);
2553 sprintf(tmp, "%d", value[1]);
2554 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2555 sprintf(tmp, "%d", value[2]);
2556 WMSetTextFieldText(panel->cmykYellowT, tmp);
2557 sprintf(tmp, "%d", value[3]);
2558 WMSetTextFieldText(panel->cmykBlackT, tmp);
2560 WMSetSliderValue(panel->cmykCyanS, value[0]);
2561 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2562 WMSetSliderValue(panel->cmykYellowS, value[2]);
2563 WMSetSliderValue(panel->cmykBlackS, value[3]);
2565 color.red = rint((255.0 - (value[0] * 2.55)) * (1.0 - (value[3] / 100.0)));
2566 color.green = rint((255.0 - (value[1] * 2.55)) * (1.0 - (value[3]/100.0)));
2567 color.blue = rint((255.0 - (value[2] * 2.55)) * (1.0 - (value[3] /100.0)));
2569 updateSwatch(panel, color);
2570 panel->lastChanged = WMCMYKModeColorPanel;
2573 /********************** HSB Panel Functions ***********************/
2575 static void
2576 hsbSliderCallback(WMWidget *w, void *data)
2578 RColor color;
2579 int value[3];
2580 char tmp[4];
2582 W_ColorPanel *panel = (W_ColorPanel*)data;
2584 value[0] = WMGetSliderValue(panel->hsbHueS);
2585 value[1] = WMGetSliderValue(panel->hsbSaturationS);
2586 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
2588 sprintf(tmp, "%d", value[0]);
2589 WMSetTextFieldText(panel->hsbHueT, tmp);
2590 sprintf(tmp, "%d", value[1]);
2591 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2592 sprintf(tmp, "%d", value[2]);
2593 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2595 panel->hsvcolor.hue = value[0];
2596 panel->hsvcolor.saturation = value[1]*2.55;
2597 panel->hsvcolor.value = value[2]*2.55;
2599 RHSVtoRGB(&panel->hsvcolor, &color);
2601 panel->lastChanged = WMHSBModeColorPanel;
2602 updateSwatch(panel, color);
2604 if (w != panel->hsbBrightnessS)
2605 hsbUpdateBrightnessGradient(panel);
2606 if (w != panel->hsbSaturationS)
2607 hsbUpdateSaturationGradient(panel);
2608 if (w != panel->hsbHueS)
2609 hsbUpdateHueGradient(panel);
2612 static void
2613 hsbTextFieldCallback(void *observerData, WMNotification *notification)
2615 RColor color;
2616 int value[3];
2617 char tmp[4];
2618 int n;
2619 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2621 value[0] = atoi(WMGetTextFieldText(panel->hsbHueT));
2622 value[1] = atoi(WMGetTextFieldText(panel->hsbSaturationT));
2623 value[2] = atoi(WMGetTextFieldText(panel->hsbBrightnessT));
2625 if (value[0] > 359)
2626 value[0] = 359;
2627 if (value[0] < 0)
2628 value[0] = 0;
2630 for (n=1; n < 3; n++) {
2631 if (value[n] > 100)
2632 value[n] = 100;
2633 if (value[n] < 0)
2634 value[n] = 0;
2637 sprintf(tmp, "%d", value[0]);
2638 WMSetTextFieldText(panel->hsbHueT, tmp);
2639 sprintf(tmp, "%d", value[1]);
2640 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2641 sprintf(tmp, "%d", value[2]);
2642 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2644 WMSetSliderValue(panel->hsbHueS, value[0]);
2645 WMSetSliderValue(panel->hsbSaturationS, value[1]);
2646 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
2648 panel->hsvcolor.hue = value[0];
2649 panel->hsvcolor.saturation = value[1]*2.55;
2650 panel->hsvcolor.value = value[2]*2.55;
2652 RHSVtoRGB(&panel->hsvcolor, &color);
2654 panel->lastChanged = WMHSBModeColorPanel;
2655 updateSwatch(panel, color);
2657 hsbUpdateBrightnessGradient(panel);
2658 hsbUpdateSaturationGradient(panel);
2659 hsbUpdateHueGradient(panel);
2662 static void
2663 hsbUpdateBrightnessGradient(W_ColorPanel *panel)
2665 W_Screen *scr = WMWidgetScreen(panel->win);
2666 RColor from;
2667 RColor to;
2668 RHSVColor hsvcolor;
2669 RImage *sliderImg;
2670 WMPixmap *sliderPxmp;
2672 from.red = from.green = from.blue = 0;
2673 hsvcolor = panel->hsvcolor;
2674 hsvcolor.value = 255;
2676 RHSVtoRGB(&hsvcolor, &to);
2678 sliderImg = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
2679 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2680 RDestroyImage(sliderImg);
2681 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
2682 panel->font12, 2, 0, 100, WALeft, WMColorGC(scr->white), False,
2683 "Brightness", strlen("Brightness"));
2684 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
2685 WMReleasePixmap(sliderPxmp);
2688 static void
2689 hsbUpdateSaturationGradient(W_ColorPanel *panel)
2691 W_Screen *scr = WMWidgetScreen(panel->win);
2692 RColor from;
2693 RColor to;
2694 RHSVColor hsvcolor;
2695 RImage *sliderImg;
2696 WMPixmap *sliderPxmp;
2698 hsvcolor = panel->hsvcolor;
2699 hsvcolor.saturation = 0;
2700 RHSVtoRGB(&hsvcolor, &from);
2702 hsvcolor.saturation = 255;
2703 RHSVtoRGB(&hsvcolor, &to);
2705 sliderImg = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
2706 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2707 RDestroyImage(sliderImg);
2708 if (hsvcolor.value < 128)
2709 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2710 panel->font12, 2, 0, 100, WALeft, WMColorGC(scr->white), False,
2711 "Saturation", strlen("Saturation"));
2712 else
2713 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2714 panel->font12, 2, 0, 100, WALeft, WMColorGC(scr->black), False,
2715 "Saturation", strlen("Saturation"));
2717 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
2718 WMReleasePixmap(sliderPxmp);
2721 static void
2722 hsbUpdateHueGradient(W_ColorPanel *panel)
2724 W_Screen *scr = WMWidgetScreen(panel->win);
2725 RColor **colors = NULL;
2726 RHSVColor hsvcolor;
2727 RImage *sliderImg;
2728 WMPixmap *sliderPxmp;
2729 int i;
2731 hsvcolor = panel->hsvcolor;
2733 colors = malloc(sizeof(RColor*)*(8));
2734 for (i=0; i<7; i++) {
2735 hsvcolor.hue = (360*i)/6;
2736 colors[i] = malloc(sizeof(RColor));
2737 RHSVtoRGB(&hsvcolor, colors[i]);
2739 colors[7] = NULL;
2741 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2742 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2743 RDestroyImage(sliderImg);
2744 if (hsvcolor.value < 128)
2745 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2746 panel->font12, 2, 0, 100, WALeft, WMColorGC(scr->white), False,
2747 "Hue", strlen("Hue"));
2748 else
2749 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2750 panel->font12, 2, 0, 100, WALeft, WMColorGC(scr->black), False,
2751 "Hue", strlen("Hue"));
2753 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2754 WMReleasePixmap(sliderPxmp);
2756 for (i=0; i<7; i++) {
2757 if (colors[i])
2758 free(colors[i]);
2760 if (colors)
2761 free(colors);
2764 /*************** Custom Palette Functions ****************/
2766 static void
2767 customRenderSpectrum(W_ColorPanel *panel)
2769 RImage *spectrum;
2770 int hue, sat, val;
2771 int x,y;
2772 unsigned long ofs;
2773 unsigned char *rp, *gp, *bp;
2774 RColor color;
2775 RHSVColor cur_hsv;
2777 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, 0);
2779 for (y=0; y<360; y++) {
2780 val = 255;
2781 sat = 0;
2782 hue = y;
2783 for (x=0; x<511; x++) {
2784 ofs = (y * 511) + x;
2786 cur_hsv.hue = hue;
2787 cur_hsv.saturation = sat;
2788 cur_hsv.value = val;
2790 RHSVtoRGB (&cur_hsv, &color);
2792 rp = spectrum->data[0] + ofs;
2793 gp = spectrum->data[1] + ofs;
2794 bp = spectrum->data[2] + ofs;
2796 *rp = (unsigned char)color.red;
2797 *gp = (unsigned char)color.green;
2798 *bp = (unsigned char)color.blue;
2800 if (x<255)
2801 sat++;
2803 if (x>255)
2804 val--;
2807 if (panel->customPaletteImg) {
2808 RDestroyImage(panel->customPaletteImg);
2809 panel->customPaletteImg = NULL;
2811 panel->customPaletteImg = spectrum;
2816 static void
2817 customSetPalette(W_ColorPanel *panel)
2819 W_Screen *scr = WMWidgetScreen(panel->win);
2820 RImage *scaledImg;
2821 Pixmap image;
2822 int item;
2824 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth,
2825 customPaletteHeight, scr->depth);
2827 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth,
2828 customPaletteHeight);
2829 RConvertImage(scr->rcontext, scaledImg, &image);
2830 RDestroyImage(scaledImg);
2832 XCopyArea(scr->display, image, panel->customPaletteContentView->window,
2833 scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2835 /* Check backimage exists. If it doesn't, allocate and fill it */
2836 if (!panel->selectionBackImg) {
2837 panel->selectionBackImg = XCreatePixmap(scr->display,
2838 panel->customPaletteContentView->window, 4, 4, scr->depth);
2841 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
2842 panel->palx-2, panel->paly-2, 4, 4, 0, 0);
2843 XCopyArea(scr->display, panel->selectionImg,
2844 panel->customPaletteContentView->window, scr->copyGC, 0 , 0, 4, 4,
2845 panel->palx-2, panel->paly-2);
2846 XFreePixmap(scr->display, image);
2848 panel->palXRatio = (float)(panel->customPaletteImg->width) /
2849 (float)(customPaletteWidth);
2850 panel->palYRatio = (float)(panel->customPaletteImg->height) /
2851 (float)(customPaletteHeight);
2853 item = WMGetPopUpButtonSelectedItem (panel->customPaletteHistoryBtn);
2855 /* if palette != "Spectrum", we are allowed to rename and remove it */
2856 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename,
2857 (item > 0) );
2858 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove,
2859 (item > 0) );
2863 static void
2864 customPalettePositionSelection(W_ColorPanel *panel, int x, int y)
2866 W_Screen *scr = WMWidgetScreen(panel->win);
2867 unsigned long ofs;
2870 /* undraw selection */
2871 XCopyArea(scr->display, panel->selectionBackImg,
2872 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2873 panel->palx-2, panel->paly-2);
2875 panel->palx = x;
2876 panel->paly = y;
2878 ofs = rint(x * panel->palXRatio) + rint(y * panel->palYRatio) *
2879 panel->customPaletteImg->width;
2881 panel->color.red = panel->customPaletteImg->data[0][ofs];
2882 panel->color.green = panel->customPaletteImg->data[1][ofs];
2883 panel->color.blue = panel->customPaletteImg->data[2][ofs];
2885 updateSwatch(panel, panel->color);
2886 panel->lastChanged = WMCustomPaletteModeColorPanel;
2888 /* Redraw color selector (and make a backup of the part it will cover) */
2889 XCopyArea(scr->display, panel->customPaletteContentView->window,
2890 panel->selectionBackImg, scr->copyGC, panel->palx-2, panel->paly-2,
2891 4, 4, 0, 0); /* "-2" is correction for hotspot location */
2892 XCopyArea(scr->display, panel->selectionImg,
2893 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2894 panel->palx-2, panel->paly-2); /* see above */
2898 static void
2899 customPalettePositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
2901 if (x < 2)
2902 x = 2;
2903 if (y < 2)
2904 y = 2;
2905 if (x >= customPaletteWidth)
2906 x = customPaletteWidth -2;
2907 if (y >= customPaletteHeight)
2908 y = customPaletteHeight -2;
2910 customPalettePositionSelection(panel, x, y);
2914 static void
2915 customPaletteHandleEvents(XEvent *event, void *data)
2917 W_ColorPanel *panel = (W_ColorPanel*)data;
2919 switch (event->type) {
2920 case Expose:
2921 if (event->xexpose.count != 0)
2922 break;
2923 customSetPalette(panel);
2924 break;
2928 static void
2929 customPaletteHandleActionEvents(XEvent *event, void *data)
2931 W_ColorPanel *panel = (W_ColorPanel*)data;
2932 int x, y;
2934 switch (event->type) {
2935 case ButtonPress:
2936 x = event->xbutton.x;
2937 y = event->xbutton.y;
2939 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2940 panel->flags.dragging = 1;
2941 customPalettePositionSelection(panel, x, y);
2943 break;
2945 case ButtonRelease:
2946 panel->flags.dragging = 0;
2947 if (!panel->flags.continuous) {
2948 if (panel->action)
2949 (*panel->action)(panel->action, panel->clientData);
2951 break;
2953 case MotionNotify:
2954 x = event->xmotion.x;
2955 y = event->xmotion.y;
2957 if (panel->flags.dragging) {
2958 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2959 customPalettePositionSelection(panel, x, y);
2961 else
2962 customPalettePositionSelectionOutBounds(panel, x, y);
2964 break;
2969 static void
2970 customPaletteMenuCallback(WMWidget *w, void *data)
2972 W_ColorPanel *panel = (W_ColorPanel*)data;
2973 int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
2975 switch (item) {
2976 case CPmenuNewFromFile:
2977 customPaletteMenuNewFromFile(panel);
2978 break;
2979 case CPmenuRename:
2980 customPaletteMenuRename(panel);
2981 break;
2982 case CPmenuRemove:
2983 customPaletteMenuRemove(panel);
2984 break;
2985 case CPmenuCopy:
2986 break;
2987 case CPmenuNewFromClipboard:
2988 break;
2993 static void
2994 customPaletteMenuNewFromFile(W_ColorPanel *panel)
2996 W_Screen *scr = WMWidgetScreen(panel->win);
2997 WMOpenPanel *browseP;
2998 char *filepath;
2999 char *filename = NULL;
3000 char *spath;
3001 char *tmp;
3002 int i;
3003 RImage *tmpImg = NULL;
3005 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir,"\0") == 0))
3006 spath = wexpandpath(wgethomedir());
3007 else
3008 spath = wexpandpath(panel->lastBrowseDir);
3010 browseP = WMGetOpenPanel(scr);
3011 WMSetFilePanelCanChooseDirectories(browseP, 0);
3012 WMSetFilePanelCanChooseFiles(browseP, 1);
3014 /* Get a filename */
3015 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
3016 "Open Palette",
3017 RSupportedFileFormats()) ) {
3018 filepath = WMGetFilePanelFileName(browseP);
3020 /* Get seperation position between path and filename */
3021 i = strrchr(filepath, '/') - filepath + 1;
3022 if (i > strlen(filepath))
3023 i = strlen(filepath);
3025 /* Store last browsed path */
3026 if (panel->lastBrowseDir)
3027 free(panel->lastBrowseDir);
3028 panel->lastBrowseDir = wmalloc((i+1)*sizeof(char));
3029 strncpy(panel->lastBrowseDir, filepath, i);
3030 panel->lastBrowseDir[i] = '\0';
3032 /* Get filename from path */
3033 filename = wstrdup(filepath + i);
3035 /* Check for duplicate files, and rename it if there are any */
3036 tmp = wstrappend(panel->configurationPath, filename);
3037 while (access (tmp, F_OK) == 0) {
3038 char *newName;
3040 free(tmp);
3042 newName = generateNewFilename(filename);
3043 free(filename);
3044 filename = newName;
3046 tmp = wstrappend(panel->configurationPath, filename);
3048 free(tmp);
3050 /* Copy image to $(gnustepdir)/Library/Colors/ &
3051 * Add filename to history menu */
3052 if (fetchFile (panel->configurationPath, filepath, filename) == 0) {
3054 /* filepath is a "local" path now the file has been copied */
3055 free(filepath);
3056 filepath = wstrappend(panel->configurationPath, filename);
3058 /* load the image & add menu entries */
3059 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
3060 if (tmpImg) {
3061 if (panel->customPaletteImg)
3062 RDestroyImage(panel->customPaletteImg);
3063 panel->customPaletteImg = tmpImg;
3065 customSetPalette(panel);
3066 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
3068 panel->currentPalette = WMGetPopUpButtonNumberOfItems(
3069 panel->customPaletteHistoryBtn)-1;
3071 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3072 panel->currentPalette);
3075 else
3077 tmp = wstrappend(panel->configurationPath, filename);
3079 i = remove(tmp); /* Delete the file, it doesn't belong here */
3080 WMRunAlertPanel(scr, panel->win, "File Error",
3081 "Invalid file format !", "OK", NULL, NULL);
3082 if (i != 0) {
3083 wsyserror("can't remove file %s", tmp);
3084 WMRunAlertPanel(scr, panel->win, "File Error",
3085 "Couldn't remove file from Configuration Directory !",
3086 "OK", NULL, NULL);
3088 free(tmp);
3090 free(filepath);
3091 free(filename);
3093 WMFreeFilePanel(browseP);
3095 free(spath);
3099 static void
3100 customPaletteMenuRename(W_ColorPanel *panel)
3102 W_Screen *scr = WMWidgetScreen(panel->win);
3103 char *toName = NULL;
3104 char *fromName;
3105 char *toPath, *fromPath;
3106 int item;
3107 int index;
3109 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3110 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
3112 toName = WMRunInputPanel(scr, panel->win, "Rename", "Rename palette to:",
3113 fromName, "OK", "Cancel");
3115 if (toName) {
3117 /* As some people do certain stupid things... */
3118 if (strcmp(toName, fromName) == 0) {
3119 free(toName);
3120 return;
3123 /* For normal people */
3124 fromPath = wstrappend(panel->configurationPath, fromName);
3125 toPath = wstrappend(panel->configurationPath, toName);
3127 if (access (toPath, F_OK) == 0) {
3128 /* Careful, this palette exists already */
3129 if (WMRunAlertPanel(scr, panel->win, "Warning",
3130 "Palette already exists !\n\nOverwrite ?", "No", "Yes",
3131 NULL) == 1) {
3132 /* "No" = 0, "Yes" = 1 */
3133 int items = WMGetPopUpButtonNumberOfItems(
3134 panel->customPaletteHistoryBtn);
3136 remove(toPath);
3138 /* Remove from History list too */
3139 index = 1;
3140 while ((index < items) && (strcmp(WMGetPopUpButtonItem(
3141 panel->customPaletteHistoryBtn, index),
3142 toName) != 0 ))
3143 index++;
3145 if (index < items) {
3146 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn,
3147 index);
3148 if (index < item)
3149 item--;
3152 } else {
3153 free(fromPath);
3154 free(toName);
3155 free(toPath);
3157 return;
3161 if ( rename(fromPath, toPath) != 0)
3162 wsyserror("Couldn't rename palette %s to %s\n", fromName, toName);
3163 else {
3164 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3165 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item,
3166 toName);
3168 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
3170 free(fromPath);
3171 free(toPath);
3172 free(toName);
3177 static void
3178 customPaletteMenuRemove(W_ColorPanel *panel)
3180 W_Screen *scr = WMWidgetScreen(panel->win);
3181 char *text;
3182 char *tmp;
3183 int choice;
3184 int item;
3186 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3188 tmp = wstrappend( "This will permanently remove the palette ",
3189 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
3190 text = wstrappend( tmp, ".\n\nAre you sure you want to remove this"
3191 " palette ?");
3192 free(tmp);
3194 choice = WMRunAlertPanel(scr, panel->win, NULL, text, "Yes", "No", NULL);
3195 /* returns 0 (= "Yes") or 1 (="No") */
3196 free(text);
3198 if (choice == 0) {
3200 tmp = wstrappend(panel->configurationPath,
3201 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
3203 if ( remove(tmp) != 0)
3204 wsyserror("Couldn't remove palette %s\n", tmp);
3205 free(tmp);
3207 /* item -1 always exists */
3208 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item-1);
3210 customPaletteHistoryCallback(panel->customPaletteHistoryBtn, panel);
3211 customSetPalette(panel);
3213 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3218 static void
3219 customPaletteHistoryCallback(WMWidget *w, void *data)
3221 W_ColorPanel *panel = (W_ColorPanel*)data;
3222 W_Screen *scr = WMWidgetScreen(panel->win);
3223 int item;
3224 char *filename;
3225 RImage *tmp = NULL;
3227 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3228 if (item == panel->currentPalette)
3229 return;
3231 if (item == 0)
3232 customRenderSpectrum(panel);
3233 else {
3234 /* Load file from configpath */
3235 filename = wstrappend( panel->configurationPath,
3236 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item) );
3238 /* XXX To do: Check existence of file and remove it from the history
3239 * if it doesn't exist */
3241 tmp = RLoadImage(scr->rcontext, filename, 0);
3242 if (tmp) {
3243 if (panel->customPaletteImg) {
3244 RDestroyImage(panel->customPaletteImg);
3245 panel->customPaletteImg = NULL;
3247 panel->customPaletteImg = tmp;
3249 free(filename);
3251 customSetPalette(panel);
3253 panel->currentPalette = item;
3257 /*************** Panel Initialisation Functions *****************/
3259 static void
3260 wheelInit(W_ColorPanel *panel)
3262 RHSVColor cur_hsv;
3263 int i;
3264 int v;
3266 RRGBtoHSV(&panel->color, &cur_hsv);
3268 WMSetSliderValue(panel->wheelBrightnessS, 255-cur_hsv.value);
3269 wheelUpdateBrightnessGradientFromHSV(panel, cur_hsv);
3271 panel->colx = 2 + rint((colorWheelSize / 2.0) * (1 + (
3272 cur_hsv.saturation/255.0) * cos( cur_hsv.hue*M_PI/180.0)));
3273 panel->coly = 2 + rint((colorWheelSize / 2.0) * (1 + (
3274 cur_hsv.saturation/255.0) * sin(-cur_hsv.hue*M_PI/180.0)));
3276 for (i = 0; i < 256; i++) {
3277 /* We divide by 128 in advance, and check whether that number divides
3278 * by 2 properly. If not, we add one to round the number correctly
3280 v = (i*cur_hsv.value) >> 7;
3281 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + (v & 1));
3285 static void
3286 grayInit(W_ColorPanel *panel)
3288 RHSVColor cur_hsv;
3289 int value;
3290 char tmp[4];
3292 RRGBtoHSV(&panel->color, &cur_hsv);
3294 value = rint(cur_hsv.value/2.55);
3295 WMSetSliderValue(panel->grayBrightnessS, value);
3297 sprintf(tmp, "%d", value);
3298 WMSetTextFieldText(panel->grayBrightnessT, tmp);
3301 static void
3302 rgbInit(W_ColorPanel *panel)
3304 char tmp[4];
3306 WMSetSliderValue(panel->rgbRedS,panel->color.red);
3307 WMSetSliderValue(panel->rgbGreenS,panel->color.green);
3308 WMSetSliderValue(panel->rgbBlueS,panel->color.blue);
3310 sprintf(tmp, "%d", panel->color.red);
3311 WMSetTextFieldText(panel->rgbRedT, tmp);
3312 sprintf(tmp, "%d", panel->color.green);
3313 WMSetTextFieldText(panel->rgbGreenT, tmp);
3314 sprintf(tmp, "%d", panel->color.blue);
3315 WMSetTextFieldText(panel->rgbBlueT, tmp);
3318 static void
3319 cmykInit(W_ColorPanel *panel)
3321 int value[3];
3322 char tmp[4];
3324 value[0] = rint((255-panel->color.red)/2.55);
3325 value[1] = rint((255-panel->color.green)/2.55);
3326 value[2] = rint((255-panel->color.blue)/2.55);
3328 WMSetSliderValue(panel->cmykCyanS, value[0]);
3329 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3330 WMSetSliderValue(panel->cmykYellowS, value[2]);
3331 WMSetSliderValue(panel->cmykBlackS, 0);
3333 sprintf(tmp, "%d", value[0]);
3334 WMSetTextFieldText(panel->cmykCyanT, tmp);
3335 sprintf(tmp, "%d", value[1]);
3336 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3337 sprintf(tmp, "%d", value[2]);
3338 WMSetTextFieldText(panel->cmykYellowT, tmp);
3339 WMSetTextFieldText(panel->cmykBlackT, "0");
3342 static void
3343 hsbInit(W_ColorPanel *panel)
3345 int value[3];
3346 char tmp[4];
3348 value[0] = panel->hsvcolor.hue;
3349 value[1] = rint(panel->hsvcolor.saturation/2.55);
3350 value[2] = rint(panel->hsvcolor.value/2.55);
3352 WMSetSliderValue(panel->hsbHueS,value[0]);
3353 WMSetSliderValue(panel->hsbSaturationS,value[1]);
3354 WMSetSliderValue(panel->hsbBrightnessS,value[2]);
3356 sprintf(tmp, "%d", value[0]);
3357 WMSetTextFieldText(panel->hsbHueT, tmp);
3358 sprintf(tmp, "%d", value[1]);
3359 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3360 sprintf(tmp, "%d", value[2]);
3361 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3363 hsbUpdateBrightnessGradient(panel);
3364 hsbUpdateSaturationGradient(panel);
3365 hsbUpdateHueGradient(panel);
3371 /************************* ColorList Panel Functions **********************/
3373 static void
3374 colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text,
3375 int state, WMRect *rect)
3377 int width, height, x, y;
3378 RColor color = *((RColor *)WMGetListItem(lPtr, index)->clientData);
3379 WMScreen *scr = WMWidgetScreen(lPtr);
3380 Display *dpy = WMScreenDisplay(scr);
3381 W_ColorPanel *panel = WMGetHangedData(lPtr);
3382 WMColor *white = WMWhiteColor(scr);
3383 WMColor *black = WMBlackColor(scr);
3384 WMColor *fillColor;
3386 width = rect->size.width;
3387 height = rect->size.height;
3388 x = rect->pos.x;
3389 y = rect->pos.y;
3391 if (state & WLDSSelected)
3392 WMPaintColorSwatch(white, d, x +15, y, width -15, height);
3393 else
3394 XClearArea(dpy, d, x +15, y, width -15, height, False);
3396 fillColor = WMCreateRGBColor(scr, color.red*256, color.green*256,
3397 color.blue*256, False);
3399 WMSetColorInGC(fillColor, WMColorGC(fillColor));
3400 WMPaintColorSwatch(fillColor, d, x, y, 15, 15);
3401 WMReleaseColor(fillColor);
3403 WMDrawString(scr, d, WMColorGC(black), panel->font12, x+18, y, text,
3404 strlen(text));
3406 WMReleaseColor(white);
3407 WMReleaseColor(black);
3411 static void
3412 colorListSelect(WMWidget *w, void *data)
3414 W_ColorPanel *panel = (W_ColorPanel *)data;
3415 RColor color = *((RColor *)WMGetListSelectedItem(w)->clientData);
3417 panel->lastChanged = WMColorListModeColorPanel;
3418 updateSwatch(panel, color);
3422 static void
3423 colorListColorMenuCallback(WMWidget *w, void *data)
3425 W_ColorPanel *panel = (W_ColorPanel *)data;
3426 int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
3428 switch (item) {
3429 case CLmenuAdd:
3430 break;
3431 case CLmenuRename:
3432 break;
3433 case CLmenuRemove:
3434 break;
3439 static void
3440 colorListListMenuCallback(WMWidget *w, void *data)
3442 W_ColorPanel *panel = (W_ColorPanel *)data;
3443 int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
3445 switch (item) {
3446 case CLmenuAdd:
3447 /* New Color List */
3448 colorListListMenuNew(panel);
3449 break;
3450 case CLmenuRename:
3451 break;
3452 case CLmenuRemove:
3453 break;
3458 static void
3459 colorListListMenuNew(W_ColorPanel *panel)
3465 /************************** Common utility functions ************************/
3467 static int
3468 fetchFile(char *toPath, char *srcFile, char *destFile)
3470 int src, dest;
3471 int n;
3472 char *tmp;
3473 char buf[BUFSIZE];
3475 if ((src = open(srcFile, O_RDONLY)) == 0) {
3476 wsyserror("Could not open %s", srcFile);
3477 return -1;
3480 tmp = wstrappend(toPath, destFile);
3481 if ((dest = open( tmp, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH))
3482 == 0) {
3483 wsyserror("Could not create %s", tmp);
3484 free(tmp);
3485 return -1;
3487 free(tmp);
3490 /* Copy the file */
3491 while ((n = read(src, buf, BUFSIZE)) > 0)
3493 if (write (dest, buf, n) != n) {
3494 wsyserror("Write error on file %s", destFile);
3495 return -1;
3499 return 0;
3503 char*
3504 generateNewFilename(char *curName)
3506 int n;
3507 char c;
3508 int baseLen;
3509 char *ptr;
3510 char *newName;
3513 assert(curName);
3515 ptr = curName;
3517 if (
3518 ((ptr = strrchr(ptr, '{')) == 0) ||
3519 sscanf(ptr, "{%i}%c", &n, &c) != 1
3521 return wstrappend(curName, " {1}");
3523 baseLen = ptr - curName -1;
3525 newName = wmalloc(baseLen + 16);
3526 strncpy(newName, curName, baseLen);
3527 newName[baseLen] = 0;
3529 sprintf(&newName[baseLen], " {%i}", n+1);
3531 return newName;