added color editing and title justification to appearance section
[wmaker-crm.git] / WINGs / wcolorpanel.c
blob661b618d96f6900501263e1660863e71c9a448ae
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);
1293 panel->mode = mode;
1296 void
1297 WMSetColorPanelColor(WMColorPanel *panel, WMColor *color)
1299 WMScreen *scr = WMWidgetScreen(panel->win);
1300 RHSVColor hsvcolor;
1301 RColor intcolor;
1302 GC bgc = WMColorGC(scr->black);
1303 GC wgc = WMColorGC(scr->white);
1304 int originalHue;
1306 WMSetColorWellColor(panel->colorWell, color);
1308 intcolor.red = color->color.red >> 8;
1309 intcolor.green = color->color.green >> 8;
1310 intcolor.blue = color->color.blue >> 8;
1312 panel->color = intcolor;
1313 panel->colorSet = True;
1315 /* If color was set by HSB-Panel do not convert back to hsv */
1316 if (panel->lastChanged != WMHSBModeColorPanel) {
1318 /* if color is black, hue is undetermined, so it must be restored */
1319 if ((panel->color.red == 0) &&
1320 (panel->color.green == 0) &&
1321 (panel->color.blue == 0) &&
1322 (panel->hsvcolor.hue <= 359))
1324 originalHue = panel->hsvcolor.hue;
1325 RRGBtoHSV(&panel->color, &panel->hsvcolor);
1326 panel->hsvcolor.hue = originalHue;
1327 } else {
1328 RRGBtoHSV(&panel->color, &panel->hsvcolor);
1332 panel->wheelMtrx = wheelInitMatrix(panel); /* Needs to be done After Color is set */
1334 /* Maybe put this in a sub-function ... Initialising selected images */
1335 RRGBtoHSV(&intcolor, &hsvcolor);
1336 panel->colx = 2 + rint((colorWheelSize / 2.0) * (1 +
1337 (hsvcolor.saturation/255.0) * cos( hsvcolor.hue*M_PI/180.0)));
1338 panel->coly = 2 + rint((colorWheelSize / 2.0) * (1 +
1339 (hsvcolor.saturation/255.0) * sin(-hsvcolor.hue*M_PI/180.0)));
1340 wheelUpdateBrightnessGradientFromHSV(panel, hsvcolor);
1341 WMSetSliderValue(panel->wheelBrightnessS, 255 - hsvcolor.value);
1343 panel->selectionImg = XCreatePixmap(scr->display,
1344 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
1345 XFillRectangle(scr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1346 XFillRectangle(scr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1347 /* End of initialisation section */
1349 panel->palx = customPaletteWidth/2;
1350 panel->paly = customPaletteHeight/2;
1352 WMSetColorPanelPickerMode(panel, panel->mode);
1356 static void
1357 updateSwatch(WMColorPanel *panel, RColor color)
1359 WMScreen *scr = WMWidgetScreen(panel->win);
1360 WMColor *wellcolor;
1361 int originalHue;
1363 wellcolor = WMCreateRGBColor(scr, color.red << 8, color.green << 8,
1364 color.blue << 8, True);
1366 WMSetColorWellColor(panel->colorWell, wellcolor);
1367 WMReleaseColor(wellcolor);
1369 panel->color = color;
1371 /* If color was set by HSB-Panel do not convert back to hsv */
1372 if (panel->lastChanged != WMHSBModeColorPanel) {
1374 /* if color is black, hue is undetermined, so it must be restored */
1375 if ((panel->color.red == 0) &&
1376 (panel->color.green == 0) &&
1377 (panel->color.blue == 0) &&
1378 (panel->hsvcolor.hue <= 359))
1380 originalHue = panel->hsvcolor.hue;
1381 RRGBtoHSV(&panel->color, &panel->hsvcolor);
1382 panel->hsvcolor.hue = originalHue;
1383 } else {
1384 RRGBtoHSV(&panel->color, &panel->hsvcolor);
1388 if (!panel->flags.dragging || panel->flags.continuous) {
1389 if (panel->action)
1390 (*panel->action)(panel, panel->clientData);
1392 WMPostNotificationName(WMColorPanelColorChangedNotification, panel,
1393 NULL);
1397 static void
1398 modeButtonCallback(WMWidget *w, void *data)
1400 W_ColorPanel *panel = (W_ColorPanel*)(data);
1402 if (w == panel->wheelBtn)
1403 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1404 else if (w == panel->slidersBtn)
1405 WMSetColorPanelPickerMode(panel, panel->slidersmode);
1406 else if (w == panel->customPaletteBtn)
1407 WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
1408 else if (w == panel->colorListBtn)
1409 WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
1410 else if (w == panel->grayBtn)
1411 WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
1412 else if (w == panel->rgbBtn)
1413 WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
1414 else if (w == panel->cmykBtn)
1415 WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
1416 else if (w == panel->hsbBtn)
1417 WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
1421 /****************** Magnifying Cursor Functions *******************/
1422 static Pixmap
1423 magnifyGetImage(WMScreen *scr, int x, int y)
1425 XImage *image;
1426 Pixmap pixmap;
1427 int x0, y0, w0, h0;
1428 int displayWidth = DisplayWidth(scr->display, scr->screen);
1429 int displayHeight = DisplayHeight(scr->display, scr->screen);
1430 const int half_mask_width = (Cursor_mask_width +1)/2;
1431 const int half_mask_height = (Cursor_mask_height +1)/2;
1433 /* Coordinate correction for back pixmap
1434 * if magnifying glass is at screen-borders */
1435 x0 = 0; y0 = 0; w0 = Cursor_mask_width; h0 = Cursor_mask_height;
1437 if (x < half_mask_width) {
1438 if (x < 0) x = 0;
1439 x0 = half_mask_width - x;
1440 w0 = Cursor_mask_width - x0;
1443 if (x > displayWidth - half_mask_width) {
1444 if (x > displayWidth) x = displayWidth;
1445 w0 = Cursor_mask_width - (half_mask_width - (displayWidth - x));
1448 if (y < half_mask_height) {
1449 if (y < 0) y = 0;
1450 y0 = half_mask_height - y;
1451 h0 = Cursor_mask_height - y0;
1454 if (y > displayHeight - half_mask_height) {
1455 if (y > displayHeight) y = displayHeight;
1456 h0 = Cursor_mask_height - (half_mask_height - (displayHeight - y));
1458 /* end of coordinate correction */
1460 image = XGetImage(scr->display, scr->rootWin, x + x0 - Cursor_x_hot,
1461 y + y0 - Cursor_y_hot, w0, h0, AllPlanes, ZPixmap);
1463 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width,
1464 Cursor_mask_height, scr->depth);
1465 XPutImage(scr->display, pixmap, scr->copyGC, image, 0, 0, x0, y0, w0, h0);
1466 XDestroyImage(image);
1468 return pixmap;
1472 static Pixmap
1473 magnifyGetStorePixmap(WMColorPanel *panel, int x1, int y1, int x2, int y2)
1476 * (x1, y1) = topleft corner of existing rectangle
1477 * (x2, y2) = topleft corner of new position
1480 W_Screen *scr = WMWidgetScreen(panel->win);
1481 Pixmap pixmap;
1482 int xa, ya, xb, yb, w, h;
1484 if (x1 < x2) {
1485 xa = x2 - x1;
1486 xb = 0;
1487 } else {
1488 xa = 0;
1489 xb = x1 - x2;
1492 if (y1 < y2) {
1493 ya = y2 - y1;
1494 yb = 0;
1495 } else {
1496 ya = 0;
1497 yb = y1 - y2;
1500 w = Cursor_mask_width - abs(x1-x2);
1501 h = Cursor_mask_height - abs(y1-y2);
1503 /* Get pixmap from screen */
1504 pixmap = magnifyGetImage(scr, x2, y2);
1506 /* Copy previously stored pixmap on covered part of above pixmap */
1507 if (panel->magnifyGlass->valid)
1509 XCopyArea(scr->display, panel->magnifyGlass->pixmap, pixmap,
1510 scr->copyGC, xa, ya, w, h, xb, yb);
1512 /* Free it, so we can reuse it */
1513 XFreePixmap(scr->display, panel->magnifyGlass->pixmap);
1516 return pixmap;
1520 static Pixmap
1521 magnifyCreatePixmap(WMColorPanel *panel)
1523 W_Screen *scr = WMWidgetScreen(panel->win);
1524 int u, v;
1525 int i, j;
1526 int ofs;
1527 Pixmap magPix;
1528 Pixmap backPix;
1529 RImage *pixelImg;
1530 const int half_mask_width = Cursor_mask_width/2;
1531 const int half_mask_height = Cursor_mask_height/2;
1535 * Get image
1538 /* Rectangle that's going to be the background */
1539 backPix = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width,
1540 Cursor_mask_height , scr->depth);
1541 XCopyArea(scr->display, panel->magnifyGlass->pixmap, backPix, scr->copyGC,
1542 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
1545 * Magnify image
1548 magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width +2,
1549 Cursor_mask_height +2, scr->depth);
1551 for (u=0; u<5+1; u++) /* Copy an area of 5x5 pixels from the center */
1552 for (v=0; v<5+1; v++)
1553 for (i=u*5; i < (u+1)*5; i++) /* magnify it 5 times */
1554 for (j=v*5; j < (v+1)*5; j++)
1555 XCopyArea(scr->display, backPix, magPix, scr->copyGC,
1556 u +9, v +9, 1, 1, i, j);
1558 /* Get color under hotspot */
1559 ofs = half_mask_width + half_mask_height * Cursor_mask_width;
1560 pixelImg = RCreateImageFromDrawable(scr->rcontext, backPix, backPix);
1561 panel->magnifyGlass->color.red = pixelImg->data[0][ofs];
1562 panel->magnifyGlass->color.green = pixelImg->data[1][ofs];
1563 panel->magnifyGlass->color.blue = pixelImg->data[2][ofs];
1564 RDestroyImage(pixelImg);
1566 /* Copy the magnified pixmap, with the clip mask, to background pixmap */
1567 XSetClipMask(scr->display, scr->clipGC, panel->magnifyGlass->mask);
1568 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1570 XCopyArea(scr->display, magPix, backPix, scr->clipGC, 2, 2,
1571 Cursor_mask_width, Cursor_mask_height, 0, 0);
1572 /* (2,2) puts center pixel on center of glass */
1574 XFreePixmap(scr->display, magPix);
1576 return backPix;
1580 static WMView*
1581 magnifyCreateView(W_ColorPanel *panel)
1583 W_Screen *scr = WMWidgetScreen(panel->win);
1584 WMView *magView;
1586 magView = W_CreateTopView(scr);
1588 W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
1590 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1591 magView->attribs.event_mask = StructureNotifyMask;
1592 magView->attribs.override_redirect = True;
1593 magView->attribs.save_under = True;
1595 W_RealizeView(magView);
1597 return magView;
1601 static Cursor
1602 magnifyGrabPointer(W_ColorPanel *panel)
1604 W_Screen *scr = WMWidgetScreen(panel->win);
1605 Pixmap magPixmap, magPixmap2;
1606 Cursor magCursor;
1607 XColor fgColor = {0, 0,0,0, DoRed|DoGreen|DoBlue};
1608 XColor bgColor = {0, 0xbf00, 0xa000, 0x5000, DoRed|DoGreen|DoBlue};
1610 /* Cursor creation stuff */
1611 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1612 Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
1613 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1614 Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
1616 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1617 &fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
1619 XFreePixmap(scr->display, magPixmap);
1620 XFreePixmap(scr->display, magPixmap2);
1622 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1624 /* Set up Pointer */
1625 XGrabPointer (scr->display, panel->magnifyGlass->view->window, True,
1626 PointerMotionMask | ButtonPressMask,
1627 GrabModeAsync, GrabModeAsync,
1628 scr->rootWin, magCursor, CurrentTime);
1630 return magCursor;
1634 static WMPoint
1635 magnifyInitialize(W_ColorPanel *panel)
1637 W_Screen *scr = WMWidgetScreen(panel->win);
1638 int x, y, u, v;
1639 unsigned int mask;
1640 Pixmap pixmap;
1641 WMPoint point;
1643 XQueryPointer(scr->display, scr->rootWin, &scr->rootWin,
1644 &W_VIEW(panel->win)->window, &x, &y, &u, &v, &mask);
1647 /* Clipmask to make magnified view-contents circular */
1648 panel->magnifyGlass->mask = XCreatePixmapFromBitmapData(scr->display,
1649 W_DRAWABLE(scr), Cursor_mask_bits,
1650 Cursor_mask_width, Cursor_mask_height, 1, 0, 1);
1652 /* Draw initial magnified part */
1653 panel->magnifyGlass->valid = False;
1654 /* also free's magnifyGlass->pixmap */
1655 panel->magnifyGlass->pixmap = magnifyGetStorePixmap(panel, x, y, x, y);
1656 panel->magnifyGlass->valid = True;
1658 pixmap = magnifyCreatePixmap(panel);
1660 XSetWindowBackgroundPixmap(scr->display, panel->magnifyGlass->view->window,
1661 pixmap);
1662 XClearWindow(scr->display, panel->magnifyGlass->view->window);
1663 XFlush(scr->display);
1665 XFreePixmap(scr->display, pixmap);
1667 point.x = x;
1668 point.y = y;
1670 return point;
1674 static void
1675 magnifyPutCursor(WMWidget *w, void *data)
1677 W_ColorPanel *panel = (W_ColorPanel*)(data);
1678 W_Screen *scr = WMWidgetScreen(panel->win);
1679 Cursor magCursor;
1680 int x, y;
1681 Pixmap pixmap;
1682 XEvent event;
1683 WMPoint initialPosition;
1685 /* Destroy wheelBackImg, so it'll update properly */
1686 if (panel->selectionBackImg) {
1687 XFreePixmap(WMWidgetScreen(panel->win)->display,
1688 panel->selectionBackImg);
1689 panel->selectionBackImg = None;
1692 /* Create magnifying glass */
1693 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1694 panel->magnifyGlass->view = magnifyCreateView(panel);
1696 initialPosition = magnifyInitialize(panel);
1697 x = initialPosition.x;
1698 y = initialPosition.y;
1700 W_MoveView(panel->magnifyGlass->view,
1701 x - Cursor_x_hot +1,
1702 y - Cursor_y_hot +1);
1703 W_MapView(panel->magnifyGlass->view);
1705 magCursor = magnifyGrabPointer(panel);
1707 while(panel->magnifyGlass->valid)
1709 WMNextEvent(scr->display, &event);
1710 while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
1713 switch (event.type)
1715 case ButtonPress:
1716 if (event.xbutton.button == Button1) {
1717 updateSwatch(panel, panel->magnifyGlass->color);
1719 switch (panel->mode) {
1720 case WMWheelModeColorPanel:
1721 wheelInit(panel);
1722 wheelRender(panel);
1723 wheelPaint(panel);
1724 break;
1725 case WMGrayModeColorPanel:
1726 grayInit(panel);
1727 break;
1728 case WMRGBModeColorPanel:
1729 rgbInit(panel);
1730 break;
1731 case WMCMYKModeColorPanel:
1732 cmykInit(panel);
1733 break;
1734 case WMHSBModeColorPanel:
1735 hsbInit(panel);
1736 break;
1737 default:
1738 break;
1740 panel->lastChanged = panel->mode;
1741 panel->magnifyGlass->valid = False;
1742 WMSetButtonSelected(panel->magnifyBtn, False);
1743 break;
1745 case MotionNotify:
1746 /* Get a "dirty rectangle" */
1747 panel->magnifyGlass->pixmap = magnifyGetStorePixmap(
1748 panel, x+1, y+1,
1749 event.xmotion.x_root+1, event.xmotion.y_root+1);
1750 /* also free's magnifyGlass->pixmap */
1752 /* Update coordinates */
1753 x = event.xmotion.x_root;
1754 y = event.xmotion.y_root;
1756 /* Move view */
1757 W_MoveView(panel->magnifyGlass->view, x - Cursor_x_hot +1,
1758 y - Cursor_y_hot +1);
1760 /* Put new image (with magn.) in view */
1761 pixmap = magnifyCreatePixmap(panel);
1762 XSetWindowBackgroundPixmap(scr->display,
1763 panel->magnifyGlass->view->window, pixmap);
1764 XClearWindow(scr->display, panel->magnifyGlass->view->window);
1766 XFreePixmap(scr->display, pixmap);
1767 break;
1769 case FocusOut: /* fall through */
1770 case FocusIn:
1772 * Color Panel window (panel->win) lost or received focus.
1773 * We need to update the pixmap in the magnifying glass.
1775 XUngrabPointer(scr->display, CurrentTime);
1776 W_UnmapView(panel->magnifyGlass->view);
1778 magnifyInitialize(panel);
1780 W_MapView(panel->magnifyGlass->view);
1781 XGrabPointer (scr->display,
1782 panel->magnifyGlass->view->window,
1783 True,
1784 PointerMotionMask | ButtonPressMask,
1785 GrabModeAsync,
1786 GrabModeAsync,
1787 scr->rootWin,
1788 magCursor,
1789 CurrentTime);
1790 break;
1792 default:
1793 WMHandleEvent(&event);
1794 break;
1795 } /* of switch */
1797 panel->magnifyGlass->valid = False;
1799 XUngrabPointer(scr->display, CurrentTime);
1800 XFreeCursor(scr->display, magCursor);
1801 W_DestroyView(panel->magnifyGlass->view);
1803 XFreePixmap(scr->display, panel->magnifyGlass->mask);
1804 panel->magnifyGlass->mask = None;
1806 XFreePixmap(scr->display, panel->magnifyGlass->pixmap);
1807 panel->magnifyGlass->pixmap = None;
1809 free(panel->magnifyGlass);
1814 /****************** WheelMatrix Functions ************************/
1816 static wheelMatrix*
1817 wheelCreateMatrix(unsigned int width, unsigned int height)
1819 wheelMatrix *matrix = NULL;
1820 int i;
1822 assert((width > 0) && (height > 0));
1824 matrix = malloc(sizeof(wheelMatrix));
1825 if (!matrix) {
1826 RErrorCode = RERR_NOMEMORY;
1827 return NULL;
1830 memset(matrix, 0, sizeof(wheelMatrix));
1831 matrix->width = width;
1832 matrix->height = height;
1833 for (i = 0; i < 3; i++) {
1834 matrix->data[i] = malloc(width*height*sizeof(unsigned char));
1835 if (!matrix->data[i])
1836 goto error;
1839 return matrix;
1841 error:
1842 for (i = 0; i < 3; i++) {
1843 if (matrix->data[i])
1844 free(matrix->data[i]);
1846 if (matrix)
1847 free(matrix);
1848 RErrorCode = RERR_NOMEMORY;
1849 return NULL;
1853 static void
1854 wheelDestroyMatrix(wheelMatrix *matrix)
1856 int i;
1858 assert (matrix!=NULL);
1860 for (i = 0; i < 3; i++) {
1861 if (matrix->data[i])
1862 free(matrix->data[i]);
1864 free(matrix);
1868 static wheelMatrix*
1869 wheelInitMatrix(W_ColorPanel *panel)
1871 int i;
1872 int x,y;
1873 wheelMatrix *matrix;
1874 unsigned char *rp, *gp, *bp;
1875 RHSVColor cur_hsv;
1876 RColor cur_rgb;
1877 long ofs[4];
1878 float hue;
1879 int sat;
1880 float xcor, ycor;
1881 int dhue[4];
1883 matrix = wheelCreateMatrix(colorWheelSize+4, colorWheelSize+4);
1884 if (!matrix)
1885 return NULL;
1887 RRGBtoHSV(&panel->color, &cur_hsv);
1889 for (i = 0; i < 256; i++)
1890 matrix->values[i] = (unsigned char)(rint(i*cur_hsv.value/255));
1892 cur_hsv.value = 255;
1894 ofs[0] = -1;
1895 ofs[1] = -(colorWheelSize + 4);
1896 /* ofs[2] = 0; superfluous
1897 ofs[3] = 0;
1899 for (y = 0; y < (colorWheelSize+4)/2; y++) {
1900 for (x = y; x < (colorWheelSize+4-y); x++) {
1901 xcor = ((float)(2.0*x - 4.0) / colorWheelSize) - 1;
1902 ycor = ((float)(2.0*y - 4.0) / colorWheelSize) - 1;
1904 sat = rint(255.0 * sqrt((xcor*xcor) + (ycor*ycor)));
1908 /* offsets are counterclockwise (in triangles) */
1910 /* top quarter */
1911 if (y < (colorWheelSize+4)/2)
1912 ofs[0]++;
1914 /* left quarter */
1915 ofs[1] += colorWheelSize + 4;
1917 /* bottom quarter */
1918 ofs[2] = (colorWheelSize + 4) * (colorWheelSize + 4) - 1 - ofs[0];
1920 /* right quarter */
1921 ofs[3] = (colorWheelSize + 4) * (colorWheelSize + 4) - 1 - ofs[1];
1923 if (sat < 256) {
1924 cur_hsv.saturation = (unsigned char)sat;
1926 if (xcor != 0)
1927 hue = atan(ycor/xcor);
1928 else {
1929 if (ycor > 0)
1930 hue = M_PI * 0.5;
1931 else
1932 hue = M_PI * 1.5;
1935 if (xcor < 0)
1936 hue += M_PI;
1937 if ((xcor > 0) && (ycor < 0))
1938 hue += M_PI * 2.0;
1940 hue = -hue; /* Reverse direction of ColorWheel */
1942 if (hue < 0)
1943 hue += M_PI * 2.0;
1945 dhue[0] = (hue*360) / (M_PI * 2.0);
1947 for (i = 0; i < 4; i++) {
1949 if (i > 0)
1950 dhue[i] = (dhue[i-1] + 90) % 360;
1952 if ((i == 1) || (i == 3))
1953 dhue[i] = 360 - dhue[i];
1955 if (i == 2)
1956 dhue[i] = 360 - dhue[i] + 180;
1958 rp = matrix->data[0] + (ofs[i] * sizeof(unsigned char));
1959 gp = matrix->data[1] + (ofs[i] * sizeof(unsigned char));
1960 bp = matrix->data[2] + (ofs[i] * sizeof(unsigned char));
1962 cur_hsv.hue = dhue[i];
1963 RHSVtoRGB(&cur_hsv, &cur_rgb);
1965 *rp = (unsigned char)(cur_rgb.red);
1966 *gp = (unsigned char)(cur_rgb.green);
1967 *bp = (unsigned char)(cur_rgb.blue);
1970 else {
1971 for (i = 0; i < 4; i++) {
1972 rp = matrix->data[0] + (ofs[i] * sizeof(unsigned char));
1973 gp = matrix->data[1] + (ofs[i] * sizeof(unsigned char));
1974 bp = matrix->data[2] + (ofs[i] * sizeof(unsigned char));
1976 *rp = (unsigned char)(0);
1977 *gp = (unsigned char)(0);
1978 *bp = (unsigned char)(0);
1982 if (y < (colorWheelSize+4)/2)
1983 ofs[0] += 2*y+1;
1985 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2*y);
1988 return matrix;
1991 /****************** ColorWheel Functions *******************/
1993 static void
1994 wheelRender(W_ColorPanel *panel)
1996 W_Screen *scr = WMWidgetScreen(panel->win);
1997 int x,y;
1998 RImage *image;
1999 unsigned char *rp, *gp, *bp;
2000 RColor gray;
2001 unsigned long ofs;
2003 image = RCreateImage(colorWheelSize+4, colorWheelSize+4, False);
2004 if (!image)
2005 return;
2007 gray.red = gray.green = gray.blue = 0xaa;
2009 for (x = 0; x < colorWheelSize+4; x++) {
2010 for (y = 0; y < colorWheelSize+4; y++) {
2012 ofs = (y * image->width) + x;
2013 rp = image->data[0] + ofs;
2014 gp = image->data[1] + ofs;
2015 bp = image->data[2] + ofs;
2017 if (wheelInsideColorWheel(panel, ofs)) {
2018 *rp = (unsigned int)(panel->wheelMtrx->values[
2019 panel->wheelMtrx->data[0][ofs] ]);
2020 *gp = (unsigned int)(panel->wheelMtrx->values[
2021 panel->wheelMtrx->data[1][ofs] ]);
2022 *bp = (unsigned int)(panel->wheelMtrx->values[
2023 panel->wheelMtrx->data[2][ofs] ]);
2025 else {
2026 *rp = (unsigned char)(gray.red);
2027 *gp = (unsigned char)(gray.green);
2028 *bp = (unsigned char)(gray.blue);
2033 if (panel->wheelImg)
2034 XFreePixmap(scr->display, panel->wheelImg);
2036 panel->wheelImg = XCreatePixmap(scr->display, W_DRAWABLE(scr),
2037 colorWheelSize+4, colorWheelSize+4, scr->depth);
2038 RConvertImage(scr->rcontext, image, &panel->wheelImg);
2040 /* Check if backimage exists. If it doesn't, allocate and fill it */
2041 if (!panel->selectionBackImg) {
2042 panel->selectionBackImg = XCreatePixmap(scr->display,
2043 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
2044 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2045 scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0);
2046 /* -2 is hot spot correction */
2049 RDestroyImage(image);
2052 static Bool
2053 wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs)
2055 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
2056 (panel->wheelMtrx->data[1][ofs] != 0) &&
2057 (panel->wheelMtrx->data[2][ofs] != 0));
2060 static void
2061 wheelPaint (W_ColorPanel *panel)
2063 W_Screen *scr = WMWidgetScreen(panel->win);
2065 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
2066 scr->copyGC, 0, 0, colorWheelSize+4, colorWheelSize+4, 0, 0);
2068 /* Draw selection image */
2069 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2070 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2073 static void
2074 wheelHandleEvents(XEvent *event, void *data)
2076 W_ColorPanel *panel = (W_ColorPanel*)data;
2078 switch (event->type) {
2079 case Expose:
2080 if (event->xexpose.count != 0)
2081 break;
2082 wheelPaint(panel);
2083 break;
2087 static void
2088 wheelHandleActionEvents(XEvent *event, void *data)
2090 W_ColorPanel *panel = (W_ColorPanel*)data;
2092 switch (event->type) {
2093 case ButtonPress:
2094 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) ==
2095 COLORWHEEL_PART) {
2096 panel->flags.dragging = 1;
2097 wheelPositionSelection(panel, event->xbutton.x,
2098 event->xbutton.y);
2100 break;
2102 case ButtonRelease:
2103 panel->flags.dragging = 0;
2104 if (!panel->flags.continuous) {
2105 if (panel->action)
2106 (*panel->action)(panel->action, panel->clientData);
2108 break;
2110 case MotionNotify:
2111 if (panel->flags.dragging) {
2112 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) ==
2113 COLORWHEEL_PART) {
2114 wheelPositionSelection(panel, event->xmotion.x,
2115 event->xmotion.y);
2117 else
2118 wheelPositionSelectionOutBounds(panel, event->xmotion.x,
2119 event->xmotion.y);
2121 break;
2126 static int
2127 getPickerPart(W_ColorPanel *panel, int x, int y)
2129 int lx, ly;
2130 unsigned long ofs;
2132 lx = x;
2133 ly = y;
2135 if (panel->mode == WMWheelModeColorPanel) {
2136 if ((lx >= 2) && (lx <= 2+colorWheelSize) && (ly >= 2) &&
2137 (ly <= 2+colorWheelSize)) {
2139 ofs = ly*panel->wheelMtrx->width+lx;
2141 if (wheelInsideColorWheel(panel, ofs))
2142 return COLORWHEEL_PART;
2146 if (panel->mode == WMCustomPaletteModeColorPanel) {
2147 if ((lx >= 2) && (lx < customPaletteWidth-2) && (ly >= 2) &&
2148 (ly < customPaletteHeight-2)) {
2149 return CUSTOMPALETTE_PART;
2153 return 0;
2157 static void
2158 wheelBrightnessSliderCallback(WMWidget *w, void *data)
2160 int i;
2161 unsigned int v;
2162 int value;
2163 unsigned long ofs;
2164 RColor cur_rgb;
2166 W_ColorPanel *panel = (W_ColorPanel*)data;
2168 value = 255-WMGetSliderValue(panel->wheelBrightnessS);
2170 for (i = 0; i < 256; i++) {
2171 /* We divide by 128 in advance, and check whether that number divides
2172 * by 2 properly. If not, we add one to round the number correctly
2174 v = (i*value) >> 7;
2175 #ifdef EASTEREGG
2176 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + v);
2177 #else
2178 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) +(v & 0x01));
2179 #endif
2182 ofs = (panel->coly * panel->wheelMtrx->width) + panel->colx;
2184 if (!wheelInsideColorWheel(panel, ofs)) {
2185 panel->hsvcolor.saturation = 255;
2186 panel->hsvcolor.value = value;
2187 RHSVtoRGB(&panel->hsvcolor, &cur_rgb);
2189 panel->color = cur_rgb;
2191 else {
2192 panel->color.red = panel->wheelMtrx->values[
2193 panel->wheelMtrx->data[0][ofs] ];
2194 panel->color.green = panel->wheelMtrx->values[
2195 panel->wheelMtrx->data[1][ofs] ];
2196 panel->color.blue = panel->wheelMtrx->values[
2197 panel->wheelMtrx->data[2][ofs] ];
2200 wheelRender(panel);
2201 wheelPaint(panel);
2202 wheelUpdateSelection(panel);
2206 static void
2207 wheelUpdateSelection(W_ColorPanel *panel)
2209 W_Screen *scr = WMWidgetScreen(panel->win);
2211 updateSwatch(panel, panel->color);
2212 panel->lastChanged = WMWheelModeColorPanel;
2214 /* Redraw color selector (and make a backup of the part it will cover) */
2215 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2216 scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0);
2217 /* "-2" is correction for hotspot location */
2218 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2219 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2220 /* see above */
2223 static void
2224 wheelUndrawSelection(W_ColorPanel *panel)
2226 W_Screen *scr = WMWidgetScreen(panel->win);
2228 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
2229 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2230 /* see above */
2233 static void
2234 wheelPositionSelection(W_ColorPanel *panel, int x, int y)
2236 unsigned long ofs = (y * panel->wheelMtrx->width)+ x;
2239 panel->color.red = panel->wheelMtrx->values[
2240 panel->wheelMtrx->data[0][ofs] ];
2241 panel->color.green = panel->wheelMtrx->values[
2242 panel->wheelMtrx->data[1][ofs] ];
2243 panel->color.blue = panel->wheelMtrx->values[
2244 panel->wheelMtrx->data[2][ofs] ];
2246 wheelUndrawSelection(panel);
2248 panel->colx = x;
2249 panel->coly = y;
2251 wheelUpdateSelection(panel);
2252 wheelUpdateBrightnessGradientFromLocation(panel);
2255 static void
2256 wheelPositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
2258 RHSVColor cur_hsv;
2259 float hue;
2260 float xcor, ycor;
2262 xcor = ((x*2.0) / (colorWheelSize+4)) - 1.0;
2263 ycor = ((y*2.0) / (colorWheelSize+4)) - 1.0;
2265 cur_hsv.saturation = 255;
2266 cur_hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2268 if (xcor != 0)
2269 hue = atan(ycor/xcor);
2270 else {
2271 if (ycor > 0)
2272 hue = M_PI * 0.5;
2273 else
2274 hue = M_PI * 1.5;
2277 if (xcor < 0)
2278 hue += M_PI;
2279 if ((xcor > 0) && (ycor < 0))
2280 hue += M_PI * 2.0;
2282 hue = -hue;
2284 if (hue < 0)
2285 hue += M_PI * 2.0;
2287 cur_hsv.hue = (hue*180.0)/(M_PI);
2288 RHSVtoRGB(&cur_hsv, &panel->color);
2290 wheelUndrawSelection(panel);
2292 panel->colx = 2 + rint((colorWheelSize * (1.0 +
2293 cos( cur_hsv.hue*M_PI/180))) /2.0);
2294 /* "+2" because of "colorWheelSize + 4" */
2295 panel->coly = 2 + rint((colorWheelSize * (1.0 +
2296 sin(-cur_hsv.hue*M_PI/180))) /2.0);
2298 wheelUpdateSelection(panel);
2299 wheelUpdateBrightnessGradientFromHSV(panel, cur_hsv);
2302 static void
2303 wheelUpdateBrightnessGradientFromHSV(W_ColorPanel *panel, RHSVColor topColor)
2305 RColor from;
2307 /* Update Brightness-Slider */
2308 topColor.value = 255;
2309 RHSVtoRGB(&topColor, &from);
2311 wheelUpdateBrightnessGradient(panel, from);
2314 static void
2315 wheelUpdateBrightnessGradientFromLocation(W_ColorPanel *panel)
2317 RColor from;
2318 unsigned long ofs;
2320 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2322 from.red = panel->wheelMtrx->data[0][ofs];
2323 from.green = panel->wheelMtrx->data[1][ofs];
2324 from.blue = panel->wheelMtrx->data[2][ofs];
2326 wheelUpdateBrightnessGradient(panel, from);
2329 static void
2330 wheelUpdateBrightnessGradient(W_ColorPanel *panel, RColor topColor)
2332 RColor to;
2333 RImage *sliderImg;
2334 WMPixmap *sliderPxmp;
2336 to.red = to.green = to.blue = 0;
2338 sliderImg = RRenderGradient(16, 153, &topColor, &to, RGRD_VERTICAL);
2339 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win),
2340 sliderImg, 0);
2341 RDestroyImage(sliderImg);
2342 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
2343 WMReleasePixmap(sliderPxmp);
2346 /****************** Grayscale Panel Functions ***************/
2348 static void
2349 grayBrightnessSliderCallback(WMWidget *w, void *data)
2351 RColor color;
2352 int value;
2353 char tmp[4];
2355 W_ColorPanel *panel = (W_ColorPanel*)data;
2357 value = WMGetSliderValue(panel->grayBrightnessS);
2359 sprintf(tmp, "%d", value);
2361 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2362 color.red = color.green = color.blue = rint(2.55*value);
2364 updateSwatch(panel, color);
2365 panel->lastChanged = WMGrayModeColorPanel;
2368 static void
2369 grayPresetButtonCallback(WMWidget *w, void *data)
2371 RColor color;
2372 char tmp[4];
2373 int value;
2374 int i=0;
2376 W_ColorPanel *panel = (W_ColorPanel*)data;
2378 while (i < 7) {
2379 if (w == panel->grayPresetBtn[i])
2380 break;
2381 i++;
2384 value = rint(100.0/6.0*i);
2385 sprintf(tmp, "%d", value);
2387 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2388 color.red = color.green = color.blue = rint(255.0*i/6.0);
2390 WMSetSliderValue(panel->grayBrightnessS, rint(100.0*i/6.0));
2392 updateSwatch(panel, color);
2393 panel->lastChanged = WMGrayModeColorPanel;
2396 static void
2397 grayBrightnessTextFieldCallback(void *observerData,
2398 WMNotification *notification)
2400 RColor color;
2401 char tmp[4];
2402 int value;
2403 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2405 value = atoi(WMGetTextFieldText(panel->grayBrightnessT));
2406 if (value > 100)
2407 value = 100;
2408 if (value < 0)
2409 value = 0;
2411 sprintf(tmp, "%d", value);
2412 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2413 WMSetSliderValue(panel->grayBrightnessS, value);
2415 color.red = color.green = color.blue = rint(255.0*value/100.0);
2416 updateSwatch(panel, color);
2417 panel->lastChanged = WMGrayModeColorPanel;
2420 /******************* RGB Panel Functions *****************/
2422 static void
2423 rgbSliderCallback(WMWidget *w, void *data)
2425 RColor color;
2426 int value[3];
2427 char tmp[4];
2429 W_ColorPanel *panel = (W_ColorPanel*)data;
2431 value[0] = WMGetSliderValue(panel->rgbRedS);
2432 value[1] = WMGetSliderValue(panel->rgbGreenS);
2433 value[2] = WMGetSliderValue(panel->rgbBlueS);
2435 sprintf(tmp, "%d", value[0]);
2436 WMSetTextFieldText(panel->rgbRedT, tmp);
2437 sprintf(tmp, "%d", value[1]);
2438 WMSetTextFieldText(panel->rgbGreenT, tmp);
2439 sprintf(tmp, "%d", value[2]);
2440 WMSetTextFieldText(panel->rgbBlueT, tmp);
2442 color.red = value[0];
2443 color.green = value[1];
2444 color.blue = value[2];
2446 updateSwatch(panel, color);
2447 panel->lastChanged = WMRGBModeColorPanel;
2450 static void
2451 rgbTextFieldCallback(void *observerData, WMNotification *notification)
2453 RColor color;
2454 int value[3];
2455 char tmp[4];
2456 int n;
2457 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2459 value[0] = atoi(WMGetTextFieldText(panel->rgbRedT));
2460 value[1] = atoi(WMGetTextFieldText(panel->rgbGreenT));
2461 value[2] = atoi(WMGetTextFieldText(panel->rgbBlueT));
2463 for (n=0; n < 3; n++) {
2464 if (value[n] > 255)
2465 value[n] = 255;
2466 if (value[n] < 0)
2467 value[n] = 0;
2470 sprintf(tmp, "%d", value[0]);
2471 WMSetTextFieldText(panel->rgbRedT, tmp);
2472 sprintf(tmp, "%d", value[1]);
2473 WMSetTextFieldText(panel->rgbGreenT, tmp);
2474 sprintf(tmp, "%d", value[2]);
2475 WMSetTextFieldText(panel->rgbBlueT, tmp);
2477 WMSetSliderValue(panel->rgbRedS, value[0]);
2478 WMSetSliderValue(panel->rgbGreenS, value[1]);
2479 WMSetSliderValue(panel->rgbBlueS, value[2]);
2481 color.red = value[0];
2482 color.green = value[1];
2483 color.blue = value[2];
2485 updateSwatch(panel, color);
2486 panel->lastChanged = WMRGBModeColorPanel;
2490 /******************* CMYK Panel Functions *****************/
2492 static void
2493 cmykSliderCallback(WMWidget *w, void *data)
2495 RColor color;
2496 int value[4];
2497 char tmp[4];
2499 W_ColorPanel *panel = (W_ColorPanel*)data;
2501 value[0] = WMGetSliderValue(panel->cmykCyanS);
2502 value[1] = WMGetSliderValue(panel->cmykMagentaS);
2503 value[2] = WMGetSliderValue(panel->cmykYellowS);
2504 value[3] = WMGetSliderValue(panel->cmykBlackS);
2506 sprintf(tmp, "%d", value[0]);
2507 WMSetTextFieldText(panel->cmykCyanT, tmp);
2508 sprintf(tmp, "%d", value[1]);
2509 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2510 sprintf(tmp, "%d", value[2]);
2511 WMSetTextFieldText(panel->cmykYellowT, tmp);
2512 sprintf(tmp, "%d", value[3]);
2513 WMSetTextFieldText(panel->cmykBlackT, tmp);
2515 color.red = rint((255.0 - (value[0] * 2.55)) * (1.0 - (value[3] / 100.0)));
2516 color.green = rint((255.0 - (value[1] * 2.55)) * (1.0 - (value[3]/100.0)));
2517 color.blue = rint((255.0 - (value[2] * 2.55)) * (1.0 - (value[3] /100.0)));
2519 updateSwatch(panel, color);
2520 panel->lastChanged = WMCMYKModeColorPanel;
2523 static void
2524 cmykTextFieldCallback(void *observerData, WMNotification *notification)
2526 RColor color;
2527 int value[4];
2528 char tmp[4];
2529 int n;
2530 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2532 value[0] = atoi(WMGetTextFieldText(panel->cmykCyanT));
2533 value[1] = atoi(WMGetTextFieldText(panel->cmykMagentaT));
2534 value[2] = atoi(WMGetTextFieldText(panel->cmykYellowT));
2535 value[3] = atoi(WMGetTextFieldText(panel->cmykBlackT));
2537 for (n=0; n < 4; n++) {
2538 if (value[n] > 100)
2539 value[n] = 100;
2540 if (value[n] < 0)
2541 value[n] = 0;
2544 sprintf(tmp, "%d", value[0]);
2545 WMSetTextFieldText(panel->cmykCyanT, tmp);
2546 sprintf(tmp, "%d", value[1]);
2547 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2548 sprintf(tmp, "%d", value[2]);
2549 WMSetTextFieldText(panel->cmykYellowT, tmp);
2550 sprintf(tmp, "%d", value[3]);
2551 WMSetTextFieldText(panel->cmykBlackT, tmp);
2553 WMSetSliderValue(panel->cmykCyanS, value[0]);
2554 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2555 WMSetSliderValue(panel->cmykYellowS, value[2]);
2556 WMSetSliderValue(panel->cmykBlackS, value[3]);
2558 color.red = rint((255.0 - (value[0] * 2.55)) * (1.0 - (value[3] / 100.0)));
2559 color.green = rint((255.0 - (value[1] * 2.55)) * (1.0 - (value[3]/100.0)));
2560 color.blue = rint((255.0 - (value[2] * 2.55)) * (1.0 - (value[3] /100.0)));
2562 updateSwatch(panel, color);
2563 panel->lastChanged = WMCMYKModeColorPanel;
2566 /********************** HSB Panel Functions ***********************/
2568 static void
2569 hsbSliderCallback(WMWidget *w, void *data)
2571 RColor color;
2572 int value[3];
2573 char tmp[4];
2575 W_ColorPanel *panel = (W_ColorPanel*)data;
2577 value[0] = WMGetSliderValue(panel->hsbHueS);
2578 value[1] = WMGetSliderValue(panel->hsbSaturationS);
2579 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
2581 sprintf(tmp, "%d", value[0]);
2582 WMSetTextFieldText(panel->hsbHueT, tmp);
2583 sprintf(tmp, "%d", value[1]);
2584 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2585 sprintf(tmp, "%d", value[2]);
2586 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2588 panel->hsvcolor.hue = value[0];
2589 panel->hsvcolor.saturation = value[1]*2.55;
2590 panel->hsvcolor.value = value[2]*2.55;
2592 RHSVtoRGB(&panel->hsvcolor, &color);
2594 panel->lastChanged = WMHSBModeColorPanel;
2595 updateSwatch(panel, color);
2597 if (w != panel->hsbBrightnessS)
2598 hsbUpdateBrightnessGradient(panel);
2599 if (w != panel->hsbSaturationS)
2600 hsbUpdateSaturationGradient(panel);
2601 if (w != panel->hsbHueS)
2602 hsbUpdateHueGradient(panel);
2605 static void
2606 hsbTextFieldCallback(void *observerData, WMNotification *notification)
2608 RColor color;
2609 int value[3];
2610 char tmp[4];
2611 int n;
2612 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2614 value[0] = atoi(WMGetTextFieldText(panel->hsbHueT));
2615 value[1] = atoi(WMGetTextFieldText(panel->hsbSaturationT));
2616 value[2] = atoi(WMGetTextFieldText(panel->hsbBrightnessT));
2618 if (value[0] > 359)
2619 value[0] = 359;
2620 if (value[0] < 0)
2621 value[0] = 0;
2623 for (n=1; n < 3; n++) {
2624 if (value[n] > 100)
2625 value[n] = 100;
2626 if (value[n] < 0)
2627 value[n] = 0;
2630 sprintf(tmp, "%d", value[0]);
2631 WMSetTextFieldText(panel->hsbHueT, tmp);
2632 sprintf(tmp, "%d", value[1]);
2633 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2634 sprintf(tmp, "%d", value[2]);
2635 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2637 WMSetSliderValue(panel->hsbHueS, value[0]);
2638 WMSetSliderValue(panel->hsbSaturationS, value[1]);
2639 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
2641 panel->hsvcolor.hue = value[0];
2642 panel->hsvcolor.saturation = value[1]*2.55;
2643 panel->hsvcolor.value = value[2]*2.55;
2645 RHSVtoRGB(&panel->hsvcolor, &color);
2647 panel->lastChanged = WMHSBModeColorPanel;
2648 updateSwatch(panel, color);
2650 hsbUpdateBrightnessGradient(panel);
2651 hsbUpdateSaturationGradient(panel);
2652 hsbUpdateHueGradient(panel);
2655 static void
2656 hsbUpdateBrightnessGradient(W_ColorPanel *panel)
2658 W_Screen *scr = WMWidgetScreen(panel->win);
2659 RColor from;
2660 RColor to;
2661 RHSVColor hsvcolor;
2662 RImage *sliderImg;
2663 WMPixmap *sliderPxmp;
2665 from.red = from.green = from.blue = 0;
2666 hsvcolor = panel->hsvcolor;
2667 hsvcolor.value = 255;
2669 RHSVtoRGB(&hsvcolor, &to);
2671 sliderImg = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
2672 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2673 RDestroyImage(sliderImg);
2674 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
2675 panel->font12, 2, 0, 100, WALeft, WMColorGC(scr->white), False,
2676 "Brightness", strlen("Brightness"));
2677 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
2678 WMReleasePixmap(sliderPxmp);
2681 static void
2682 hsbUpdateSaturationGradient(W_ColorPanel *panel)
2684 W_Screen *scr = WMWidgetScreen(panel->win);
2685 RColor from;
2686 RColor to;
2687 RHSVColor hsvcolor;
2688 RImage *sliderImg;
2689 WMPixmap *sliderPxmp;
2691 hsvcolor = panel->hsvcolor;
2692 hsvcolor.saturation = 0;
2693 RHSVtoRGB(&hsvcolor, &from);
2695 hsvcolor.saturation = 255;
2696 RHSVtoRGB(&hsvcolor, &to);
2698 sliderImg = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
2699 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2700 RDestroyImage(sliderImg);
2701 if (hsvcolor.value < 128)
2702 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2703 panel->font12, 2, 0, 100, WALeft, WMColorGC(scr->white), False,
2704 "Saturation", strlen("Saturation"));
2705 else
2706 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2707 panel->font12, 2, 0, 100, WALeft, WMColorGC(scr->black), False,
2708 "Saturation", strlen("Saturation"));
2710 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
2711 WMReleasePixmap(sliderPxmp);
2714 static void
2715 hsbUpdateHueGradient(W_ColorPanel *panel)
2717 W_Screen *scr = WMWidgetScreen(panel->win);
2718 RColor **colors = NULL;
2719 RHSVColor hsvcolor;
2720 RImage *sliderImg;
2721 WMPixmap *sliderPxmp;
2722 int i;
2724 hsvcolor = panel->hsvcolor;
2726 colors = malloc(sizeof(RColor*)*(8));
2727 for (i=0; i<7; i++) {
2728 hsvcolor.hue = (360*i)/6;
2729 colors[i] = malloc(sizeof(RColor));
2730 RHSVtoRGB(&hsvcolor, colors[i]);
2732 colors[7] = NULL;
2734 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2735 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2736 RDestroyImage(sliderImg);
2737 if (hsvcolor.value < 128)
2738 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2739 panel->font12, 2, 0, 100, WALeft, WMColorGC(scr->white), False,
2740 "Hue", strlen("Hue"));
2741 else
2742 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2743 panel->font12, 2, 0, 100, WALeft, WMColorGC(scr->black), False,
2744 "Hue", strlen("Hue"));
2746 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2747 WMReleasePixmap(sliderPxmp);
2749 for (i=0; i<7; i++) {
2750 if (colors[i])
2751 free(colors[i]);
2753 if (colors)
2754 free(colors);
2757 /*************** Custom Palette Functions ****************/
2759 static void
2760 customRenderSpectrum(W_ColorPanel *panel)
2762 RImage *spectrum;
2763 int hue, sat, val;
2764 int x,y;
2765 unsigned long ofs;
2766 unsigned char *rp, *gp, *bp;
2767 RColor color;
2768 RHSVColor cur_hsv;
2770 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, 0);
2772 for (y=0; y<360; y++) {
2773 val = 255;
2774 sat = 0;
2775 hue = y;
2776 for (x=0; x<511; x++) {
2777 ofs = (y * 511) + x;
2779 cur_hsv.hue = hue;
2780 cur_hsv.saturation = sat;
2781 cur_hsv.value = val;
2783 RHSVtoRGB (&cur_hsv, &color);
2785 rp = spectrum->data[0] + ofs;
2786 gp = spectrum->data[1] + ofs;
2787 bp = spectrum->data[2] + ofs;
2789 *rp = (unsigned char)color.red;
2790 *gp = (unsigned char)color.green;
2791 *bp = (unsigned char)color.blue;
2793 if (x<255)
2794 sat++;
2796 if (x>255)
2797 val--;
2800 if (panel->customPaletteImg) {
2801 RDestroyImage(panel->customPaletteImg);
2802 panel->customPaletteImg = NULL;
2804 panel->customPaletteImg = spectrum;
2809 static void
2810 customSetPalette(W_ColorPanel *panel)
2812 W_Screen *scr = WMWidgetScreen(panel->win);
2813 RImage *scaledImg;
2814 Pixmap image;
2815 int item;
2817 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth,
2818 customPaletteHeight, scr->depth);
2820 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth,
2821 customPaletteHeight);
2822 RConvertImage(scr->rcontext, scaledImg, &image);
2823 RDestroyImage(scaledImg);
2825 XCopyArea(scr->display, image, panel->customPaletteContentView->window,
2826 scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2828 /* Check backimage exists. If it doesn't, allocate and fill it */
2829 if (!panel->selectionBackImg) {
2830 panel->selectionBackImg = XCreatePixmap(scr->display,
2831 panel->customPaletteContentView->window, 4, 4, scr->depth);
2834 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
2835 panel->palx-2, panel->paly-2, 4, 4, 0, 0);
2836 XCopyArea(scr->display, panel->selectionImg,
2837 panel->customPaletteContentView->window, scr->copyGC, 0 , 0, 4, 4,
2838 panel->palx-2, panel->paly-2);
2839 XFreePixmap(scr->display, image);
2841 panel->palXRatio = (float)(panel->customPaletteImg->width) /
2842 (float)(customPaletteWidth);
2843 panel->palYRatio = (float)(panel->customPaletteImg->height) /
2844 (float)(customPaletteHeight);
2846 item = WMGetPopUpButtonSelectedItem (panel->customPaletteHistoryBtn);
2848 /* if palette != "Spectrum", we are allowed to rename and remove it */
2849 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename,
2850 (item > 0) );
2851 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove,
2852 (item > 0) );
2856 static void
2857 customPalettePositionSelection(W_ColorPanel *panel, int x, int y)
2859 W_Screen *scr = WMWidgetScreen(panel->win);
2860 unsigned long ofs;
2863 /* undraw selection */
2864 XCopyArea(scr->display, panel->selectionBackImg,
2865 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2866 panel->palx-2, panel->paly-2);
2868 panel->palx = x;
2869 panel->paly = y;
2871 ofs = rint(x * panel->palXRatio) + rint(y * panel->palYRatio) *
2872 panel->customPaletteImg->width;
2874 panel->color.red = panel->customPaletteImg->data[0][ofs];
2875 panel->color.green = panel->customPaletteImg->data[1][ofs];
2876 panel->color.blue = panel->customPaletteImg->data[2][ofs];
2878 updateSwatch(panel, panel->color);
2879 panel->lastChanged = WMCustomPaletteModeColorPanel;
2881 /* Redraw color selector (and make a backup of the part it will cover) */
2882 XCopyArea(scr->display, panel->customPaletteContentView->window,
2883 panel->selectionBackImg, scr->copyGC, panel->palx-2, panel->paly-2,
2884 4, 4, 0, 0); /* "-2" is correction for hotspot location */
2885 XCopyArea(scr->display, panel->selectionImg,
2886 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2887 panel->palx-2, panel->paly-2); /* see above */
2891 static void
2892 customPalettePositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
2894 if (x < 2)
2895 x = 2;
2896 if (y < 2)
2897 y = 2;
2898 if (x >= customPaletteWidth)
2899 x = customPaletteWidth -2;
2900 if (y >= customPaletteHeight)
2901 y = customPaletteHeight -2;
2903 customPalettePositionSelection(panel, x, y);
2907 static void
2908 customPaletteHandleEvents(XEvent *event, void *data)
2910 W_ColorPanel *panel = (W_ColorPanel*)data;
2912 switch (event->type) {
2913 case Expose:
2914 if (event->xexpose.count != 0)
2915 break;
2916 customSetPalette(panel);
2917 break;
2921 static void
2922 customPaletteHandleActionEvents(XEvent *event, void *data)
2924 W_ColorPanel *panel = (W_ColorPanel*)data;
2925 int x, y;
2927 switch (event->type) {
2928 case ButtonPress:
2929 x = event->xbutton.x;
2930 y = event->xbutton.y;
2932 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2933 panel->flags.dragging = 1;
2934 customPalettePositionSelection(panel, x, y);
2936 break;
2938 case ButtonRelease:
2939 panel->flags.dragging = 0;
2940 if (!panel->flags.continuous) {
2941 if (panel->action)
2942 (*panel->action)(panel->action, panel->clientData);
2944 break;
2946 case MotionNotify:
2947 x = event->xmotion.x;
2948 y = event->xmotion.y;
2950 if (panel->flags.dragging) {
2951 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2952 customPalettePositionSelection(panel, x, y);
2954 else
2955 customPalettePositionSelectionOutBounds(panel, x, y);
2957 break;
2962 static void
2963 customPaletteMenuCallback(WMWidget *w, void *data)
2965 W_ColorPanel *panel = (W_ColorPanel*)data;
2966 int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
2968 switch (item) {
2969 case CPmenuNewFromFile:
2970 customPaletteMenuNewFromFile(panel);
2971 break;
2972 case CPmenuRename:
2973 customPaletteMenuRename(panel);
2974 break;
2975 case CPmenuRemove:
2976 customPaletteMenuRemove(panel);
2977 break;
2978 case CPmenuCopy:
2979 break;
2980 case CPmenuNewFromClipboard:
2981 break;
2986 static void
2987 customPaletteMenuNewFromFile(W_ColorPanel *panel)
2989 W_Screen *scr = WMWidgetScreen(panel->win);
2990 WMOpenPanel *browseP;
2991 char *filepath;
2992 char *filename = NULL;
2993 char *spath;
2994 char *tmp;
2995 int i;
2996 RImage *tmpImg = NULL;
2998 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir,"\0") == 0))
2999 spath = wexpandpath(wgethomedir());
3000 else
3001 spath = wexpandpath(panel->lastBrowseDir);
3003 browseP = WMGetOpenPanel(scr);
3004 WMSetFilePanelCanChooseDirectories(browseP, 0);
3005 WMSetFilePanelCanChooseFiles(browseP, 1);
3007 /* Get a filename */
3008 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
3009 "Open Palette",
3010 RSupportedFileFormats()) ) {
3011 filepath = WMGetFilePanelFileName(browseP);
3013 /* Get seperation position between path and filename */
3014 i = strrchr(filepath, '/') - filepath + 1;
3015 if (i > strlen(filepath))
3016 i = strlen(filepath);
3018 /* Store last browsed path */
3019 if (panel->lastBrowseDir)
3020 free(panel->lastBrowseDir);
3021 panel->lastBrowseDir = wmalloc((i+1)*sizeof(char));
3022 strncpy(panel->lastBrowseDir, filepath, i);
3023 panel->lastBrowseDir[i] = '\0';
3025 /* Get filename from path */
3026 filename = wstrdup(filepath + i);
3028 /* Check for duplicate files, and rename it if there are any */
3029 tmp = wstrappend(panel->configurationPath, filename);
3030 while (access (tmp, F_OK) == 0) {
3031 char *newName;
3033 free(tmp);
3035 newName = generateNewFilename(filename);
3036 free(filename);
3037 filename = newName;
3039 tmp = wstrappend(panel->configurationPath, filename);
3041 free(tmp);
3043 /* Copy image to $(gnustepdir)/Library/Colors/ &
3044 * Add filename to history menu */
3045 if (fetchFile (panel->configurationPath, filepath, filename) == 0) {
3047 /* filepath is a "local" path now the file has been copied */
3048 free(filepath);
3049 filepath = wstrappend(panel->configurationPath, filename);
3051 /* load the image & add menu entries */
3052 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
3053 if (tmpImg) {
3054 if (panel->customPaletteImg)
3055 RDestroyImage(panel->customPaletteImg);
3056 panel->customPaletteImg = tmpImg;
3058 customSetPalette(panel);
3059 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
3061 panel->currentPalette = WMGetPopUpButtonNumberOfItems(
3062 panel->customPaletteHistoryBtn)-1;
3064 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3065 panel->currentPalette);
3068 else
3070 tmp = wstrappend(panel->configurationPath, filename);
3072 i = remove(tmp); /* Delete the file, it doesn't belong here */
3073 WMRunAlertPanel(scr, panel->win, "File Error",
3074 "Invalid file format !", "OK", NULL, NULL);
3075 if (i != 0) {
3076 wsyserror("can't remove file %s", tmp);
3077 WMRunAlertPanel(scr, panel->win, "File Error",
3078 "Couldn't remove file from Configuration Directory !",
3079 "OK", NULL, NULL);
3081 free(tmp);
3083 free(filepath);
3084 free(filename);
3086 WMFreeFilePanel(browseP);
3088 free(spath);
3092 static void
3093 customPaletteMenuRename(W_ColorPanel *panel)
3095 W_Screen *scr = WMWidgetScreen(panel->win);
3096 char *toName = NULL;
3097 char *fromName;
3098 char *toPath, *fromPath;
3099 int item;
3100 int index;
3102 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3103 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
3105 toName = WMRunInputPanel(scr, panel->win, "Rename", "Rename palette to:",
3106 fromName, "OK", "Cancel");
3108 if (toName) {
3110 /* As some people do certain stupid things... */
3111 if (strcmp(toName, fromName) == 0) {
3112 free(toName);
3113 return;
3116 /* For normal people */
3117 fromPath = wstrappend(panel->configurationPath, fromName);
3118 toPath = wstrappend(panel->configurationPath, toName);
3120 if (access (toPath, F_OK) == 0) {
3121 /* Careful, this palette exists already */
3122 if (WMRunAlertPanel(scr, panel->win, "Warning",
3123 "Palette already exists !\n\nOverwrite ?", "No", "Yes",
3124 NULL) == 1) {
3125 /* "No" = 0, "Yes" = 1 */
3126 int items = WMGetPopUpButtonNumberOfItems(
3127 panel->customPaletteHistoryBtn);
3129 remove(toPath);
3131 /* Remove from History list too */
3132 index = 1;
3133 while ((index < items) && (strcmp(WMGetPopUpButtonItem(
3134 panel->customPaletteHistoryBtn, index),
3135 toName) != 0 ))
3136 index++;
3138 if (index < items) {
3139 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn,
3140 index);
3141 if (index < item)
3142 item--;
3145 } else {
3146 free(fromPath);
3147 free(toName);
3148 free(toPath);
3150 return;
3154 if ( rename(fromPath, toPath) != 0)
3155 wsyserror("Couldn't rename palette %s to %s\n", fromName, toName);
3156 else {
3157 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3158 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item,
3159 toName);
3161 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
3163 free(fromPath);
3164 free(toPath);
3165 free(toName);
3170 static void
3171 customPaletteMenuRemove(W_ColorPanel *panel)
3173 W_Screen *scr = WMWidgetScreen(panel->win);
3174 char *text;
3175 char *tmp;
3176 int choice;
3177 int item;
3179 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3181 tmp = wstrappend( "This will permanently remove the palette ",
3182 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
3183 text = wstrappend( tmp, ".\n\nAre you sure you want to remove this"
3184 " palette ?");
3185 free(tmp);
3187 choice = WMRunAlertPanel(scr, panel->win, NULL, text, "Yes", "No", NULL);
3188 /* returns 0 (= "Yes") or 1 (="No") */
3189 free(text);
3191 if (choice == 0) {
3193 tmp = wstrappend(panel->configurationPath,
3194 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
3196 if ( remove(tmp) != 0)
3197 wsyserror("Couldn't remove palette %s\n", tmp);
3198 free(tmp);
3200 /* item -1 always exists */
3201 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item-1);
3203 customPaletteHistoryCallback(panel->customPaletteHistoryBtn, panel);
3204 customSetPalette(panel);
3206 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3211 static void
3212 customPaletteHistoryCallback(WMWidget *w, void *data)
3214 W_ColorPanel *panel = (W_ColorPanel*)data;
3215 W_Screen *scr = WMWidgetScreen(panel->win);
3216 int item;
3217 char *filename;
3218 RImage *tmp = NULL;
3220 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3221 if (item == panel->currentPalette)
3222 return;
3224 if (item == 0)
3225 customRenderSpectrum(panel);
3226 else {
3227 /* Load file from configpath */
3228 filename = wstrappend( panel->configurationPath,
3229 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item) );
3231 /* XXX To do: Check existence of file and remove it from the history
3232 * if it doesn't exist */
3234 tmp = RLoadImage(scr->rcontext, filename, 0);
3235 if (tmp) {
3236 if (panel->customPaletteImg) {
3237 RDestroyImage(panel->customPaletteImg);
3238 panel->customPaletteImg = NULL;
3240 panel->customPaletteImg = tmp;
3242 free(filename);
3244 customSetPalette(panel);
3246 panel->currentPalette = item;
3250 /*************** Panel Initialisation Functions *****************/
3252 static void
3253 wheelInit(W_ColorPanel *panel)
3255 RHSVColor cur_hsv;
3256 int i;
3257 int v;
3259 RRGBtoHSV(&panel->color, &cur_hsv);
3261 WMSetSliderValue(panel->wheelBrightnessS, 255-cur_hsv.value);
3262 wheelUpdateBrightnessGradientFromHSV(panel, cur_hsv);
3264 panel->colx = 2 + rint((colorWheelSize / 2.0) * (1 + (
3265 cur_hsv.saturation/255.0) * cos( cur_hsv.hue*M_PI/180.0)));
3266 panel->coly = 2 + rint((colorWheelSize / 2.0) * (1 + (
3267 cur_hsv.saturation/255.0) * sin(-cur_hsv.hue*M_PI/180.0)));
3269 for (i = 0; i < 256; i++) {
3270 /* We divide by 128 in advance, and check whether that number divides
3271 * by 2 properly. If not, we add one to round the number correctly
3273 v = (i*cur_hsv.value) >> 7;
3274 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + (v & 1));
3278 static void
3279 grayInit(W_ColorPanel *panel)
3281 RHSVColor cur_hsv;
3282 int value;
3283 char tmp[4];
3285 RRGBtoHSV(&panel->color, &cur_hsv);
3287 value = rint(cur_hsv.value/2.55);
3288 WMSetSliderValue(panel->grayBrightnessS, value);
3290 sprintf(tmp, "%d", value);
3291 WMSetTextFieldText(panel->grayBrightnessT, tmp);
3294 static void
3295 rgbInit(W_ColorPanel *panel)
3297 char tmp[4];
3299 WMSetSliderValue(panel->rgbRedS,panel->color.red);
3300 WMSetSliderValue(panel->rgbGreenS,panel->color.green);
3301 WMSetSliderValue(panel->rgbBlueS,panel->color.blue);
3303 sprintf(tmp, "%d", panel->color.red);
3304 WMSetTextFieldText(panel->rgbRedT, tmp);
3305 sprintf(tmp, "%d", panel->color.green);
3306 WMSetTextFieldText(panel->rgbGreenT, tmp);
3307 sprintf(tmp, "%d", panel->color.blue);
3308 WMSetTextFieldText(panel->rgbBlueT, tmp);
3311 static void
3312 cmykInit(W_ColorPanel *panel)
3314 int value[3];
3315 char tmp[4];
3317 value[0] = rint((255-panel->color.red)/2.55);
3318 value[1] = rint((255-panel->color.green)/2.55);
3319 value[2] = rint((255-panel->color.blue)/2.55);
3321 WMSetSliderValue(panel->cmykCyanS, value[0]);
3322 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3323 WMSetSliderValue(panel->cmykYellowS, value[2]);
3324 WMSetSliderValue(panel->cmykBlackS, 0);
3326 sprintf(tmp, "%d", value[0]);
3327 WMSetTextFieldText(panel->cmykCyanT, tmp);
3328 sprintf(tmp, "%d", value[1]);
3329 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3330 sprintf(tmp, "%d", value[2]);
3331 WMSetTextFieldText(panel->cmykYellowT, tmp);
3332 WMSetTextFieldText(panel->cmykBlackT, "0");
3335 static void
3336 hsbInit(W_ColorPanel *panel)
3338 int value[3];
3339 char tmp[4];
3341 value[0] = panel->hsvcolor.hue;
3342 value[1] = rint(panel->hsvcolor.saturation/2.55);
3343 value[2] = rint(panel->hsvcolor.value/2.55);
3345 WMSetSliderValue(panel->hsbHueS,value[0]);
3346 WMSetSliderValue(panel->hsbSaturationS,value[1]);
3347 WMSetSliderValue(panel->hsbBrightnessS,value[2]);
3349 sprintf(tmp, "%d", value[0]);
3350 WMSetTextFieldText(panel->hsbHueT, tmp);
3351 sprintf(tmp, "%d", value[1]);
3352 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3353 sprintf(tmp, "%d", value[2]);
3354 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3356 hsbUpdateBrightnessGradient(panel);
3357 hsbUpdateSaturationGradient(panel);
3358 hsbUpdateHueGradient(panel);
3364 /************************* ColorList Panel Functions **********************/
3366 static void
3367 colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text,
3368 int state, WMRect *rect)
3370 int width, height, x, y;
3371 RColor color = *((RColor *)WMGetListItem(lPtr, index)->clientData);
3372 WMScreen *scr = WMWidgetScreen(lPtr);
3373 Display *dpy = WMScreenDisplay(scr);
3374 W_ColorPanel *panel = WMGetHangedData(lPtr);
3375 WMColor *white = WMWhiteColor(scr);
3376 WMColor *black = WMBlackColor(scr);
3377 WMColor *fillColor;
3379 width = rect->size.width;
3380 height = rect->size.height;
3381 x = rect->pos.x;
3382 y = rect->pos.y;
3384 if (state & WLDSSelected)
3385 WMPaintColorSwatch(white, d, x +15, y, width -15, height);
3386 else
3387 XClearArea(dpy, d, x +15, y, width -15, height, False);
3389 fillColor = WMCreateRGBColor(scr, color.red*256, color.green*256,
3390 color.blue*256, False);
3392 WMSetColorInGC(fillColor, WMColorGC(fillColor));
3393 WMPaintColorSwatch(fillColor, d, x, y, 15, 15);
3394 WMReleaseColor(fillColor);
3396 WMDrawString(scr, d, WMColorGC(black), panel->font12, x+18, y, text,
3397 strlen(text));
3399 WMReleaseColor(white);
3400 WMReleaseColor(black);
3404 static void
3405 colorListSelect(WMWidget *w, void *data)
3407 W_ColorPanel *panel = (W_ColorPanel *)data;
3408 RColor color = *((RColor *)WMGetListSelectedItem(w)->clientData);
3410 panel->lastChanged = WMColorListModeColorPanel;
3411 updateSwatch(panel, color);
3415 static void
3416 colorListColorMenuCallback(WMWidget *w, void *data)
3418 W_ColorPanel *panel = (W_ColorPanel *)data;
3419 int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
3421 switch (item) {
3422 case CLmenuAdd:
3423 break;
3424 case CLmenuRename:
3425 break;
3426 case CLmenuRemove:
3427 break;
3432 static void
3433 colorListListMenuCallback(WMWidget *w, void *data)
3435 W_ColorPanel *panel = (W_ColorPanel *)data;
3436 int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
3438 switch (item) {
3439 case CLmenuAdd:
3440 /* New Color List */
3441 colorListListMenuNew(panel);
3442 break;
3443 case CLmenuRename:
3444 break;
3445 case CLmenuRemove:
3446 break;
3451 static void
3452 colorListListMenuNew(W_ColorPanel *panel)
3458 /************************** Common utility functions ************************/
3460 static int
3461 fetchFile(char *toPath, char *srcFile, char *destFile)
3463 int src, dest;
3464 int n;
3465 char *tmp;
3466 char buf[BUFSIZE];
3468 if ((src = open(srcFile, O_RDONLY)) == 0) {
3469 wsyserror("Could not open %s", srcFile);
3470 return -1;
3473 tmp = wstrappend(toPath, destFile);
3474 if ((dest = open( tmp, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH))
3475 == 0) {
3476 wsyserror("Could not create %s", tmp);
3477 free(tmp);
3478 return -1;
3480 free(tmp);
3483 /* Copy the file */
3484 while ((n = read(src, buf, BUFSIZE)) > 0)
3486 if (write (dest, buf, n) != n) {
3487 wsyserror("Write error on file %s", destFile);
3488 return -1;
3492 return 0;
3496 char*
3497 generateNewFilename(char *curName)
3499 int n;
3500 char c;
3501 int baseLen;
3502 char *ptr;
3503 char *newName;
3506 assert(curName);
3508 ptr = curName;
3510 if (
3511 ((ptr = strrchr(ptr, '{')) == 0) ||
3512 sscanf(ptr, "{%i}%c", &n, &c) != 1
3514 return wstrappend(curName, " {1}");
3516 baseLen = ptr - curName -1;
3518 newName = wmalloc(baseLen + 16);
3519 strncpy(newName, curName, baseLen);
3520 newName[baseLen] = 0;
3522 sprintf(&newName[baseLen], " {%i}", n+1);
3524 return newName;