- Updated WINGs/NEWS with info about hw the API changed how how things
[wmaker-crm.git] / WINGs / wcolorpanel.c
blob97712dccc25a7f4e0c30d79178cabf37b0bc78e2
1 /*
2 * ColorPanel for WINGs
4 * by ]d : Original idea and basic initial code
5 * Pascal Hofstee : Code for wheeldrawing and calculating
6 * colors from it.
7 * Primary coder of this Color Panel.
8 * Alban Hertroys : Optimizations for algorithms for color-
9 * wheel. Also custom ColorPalettes and
10 * magnifying glass. Secondary coder ;)
11 * Alfredo K. Kojima : For pointing out memory-allocation
12 * problems and similair code-issues
13 * Marco van Hylckama-Vlieg : For once again doing the artwork ;-)
18 /* TODO:
19 * - Look at further optimization of colorWheel matrix calculation.
20 * It appears to be rather symmetric in angles of 60 degrees,
21 * while it is optimized in angles of 90 degrees.
22 * - Custom color-lists and custom colors in custom color-lists.
23 * - Stored colors
24 * - Resizing
27 #include "wconfig.h"
28 #include "WINGsP.h"
29 #include <math.h>
30 #include <unistd.h>
31 #include <ctype.h>
32 #include <fcntl.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <dirent.h>
36 #include <errno.h>
38 /* BUG There's something fishy with shaped windows */
39 #if 1
40 #ifdef SHAPE
41 #define SHAPE_WAS_DEFINED
42 #undef SHAPE
43 #endif
44 #endif
47 #ifdef SHAPE
48 #include <X11/extensions/shape.h>
49 #endif
52 #ifndef PATH_MAX
53 # define PATH_MAX 1024
54 #endif
57 char *WMColorPanelColorChangedNotification = "WMColorPanelColorChangedNotification";
61 * Bitmaps for magnifying glass cursor
64 /* Cursor */
65 #define Cursor_x_hot 11
66 #define Cursor_y_hot 11
67 #define Cursor_width 32
68 #define Cursor_height 32
69 static unsigned char Cursor_bits[] = {
70 0x00,0x7e,0x00,0x00,0xc0,0x81,0x03,0x00,0x20,0x00,0x04,0x00,0x10,0x00,0x08,
71 0x00,0x08,0x00,0x10,0x00,0x04,0x00,0x20,0x00,0x02,0x00,0x40,0x00,0x02,0x00,
72 0x40,0x00,0x02,0x00,0x40,0x00,0x01,0x42,0x80,0x00,0x01,0x24,0x80,0x00,0x01,
73 0x00,0x80,0x00,0x01,0x00,0x80,0x00,0x01,0x24,0x80,0x00,0x01,0x42,0x80,0x00,
74 0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x04,0x00,0x20,
75 0x00,0x08,0x00,0x50,0x00,0x10,0x00,0x88,0x00,0x20,0x00,0x5c,0x01,0xc0,0x81,
76 0x3b,0x02,0x00,0x7e,0x70,0x05,0x00,0x00,0xe0,0x08,0x00,0x00,0xc0,0x15,0x00,
77 0x00,0x80,0x23,0x00,0x00,0x00,0x57,0x00,0x00,0x00,0x8e,0x00,0x00,0x00,0x5c,
78 0x00,0x00,0x00,0xb8,0x00,0x00,0x00,0x70};
80 /* Cursor shape-mask */
81 #define Cursor_shape_width 32
82 #define Cursor_shape_height 32
83 static unsigned char Cursor_shape_bits[] = {
84 0x00,0x7e,0x00,0x00,0xc0,0x81,0x03,0x00,0x20,0x00,0x04,0x00,0x10,0x00,0x08,
85 0x00,0x08,0x00,0x10,0x00,0x04,0x00,0x20,0x00,0x02,0x00,0x40,0x00,0x02,0x00,
86 0x40,0x00,0x02,0x00,0x40,0x00,0x01,0x42,0x80,0x00,0x01,0x24,0x80,0x00,0x01,
87 0x00,0x80,0x00,0x01,0x00,0x80,0x00,0x01,0x24,0x80,0x00,0x01,0x42,0x80,0x00,
88 0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x04,0x00,0x20,
89 0x00,0x08,0x00,0x70,0x00,0x10,0x00,0xf8,0x00,0x20,0x00,0xfc,0x01,0xc0,0x81,
90 0xfb,0x03,0x00,0x7e,0xf0,0x07,0x00,0x00,0xe0,0x0f,0x00,0x00,0xc0,0x1f,0x00,
91 0x00,0x80,0x3f,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0xfc,
92 0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x70};
94 /* Clip-mask for magnified pixels */
95 #define Cursor_mask_width 24
96 #define Cursor_mask_height 24
97 static unsigned char Cursor_mask_bits[] = {
98 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0xff, 0x07,
99 0xf0, 0xff, 0x0f, 0xf8, 0xff, 0x1f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f,
100 0xfc, 0xff, 0x3f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f,
101 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfc, 0xff, 0x3f,
102 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xf8, 0xff, 0x1f, 0xf0, 0xff, 0x0f,
103 0xe0, 0xff, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00};
106 typedef struct MovingView {
107 WMView *view; /* The view this is all about */
108 XImage *image; /* What's under the view */
109 XImage *dirtyRect; /* Storage of overlapped image area */
110 Pixmap magPix; /* Magnified part of pixmap */
111 RColor color; /* Color of a pixel in the image */
112 int x, y; /* Position of view */
113 } MovingView;
115 typedef struct CPColor {
116 RColor rgb; /* The RGB values of the color */
117 RHSVColor hsv; /* The HSV values of the color */
118 enum { /* Which one was last set ? */
119 cpNone,
120 cpRGB,
121 cpHSV
122 } set;
123 } CPColor;
126 typedef struct WheelMatrix {
127 unsigned int width, height; /* Size of the colorwheel */
128 unsigned char *data[3]; /* Wheel data (R,G,B) */
129 unsigned char values[256]; /* Precalculated values R,G & B = 0-255 */
130 } wheelMatrix;
132 typedef struct W_ColorPanel {
133 WMWindow *win;
134 WMFont *font8;
135 WMFont *font12;
136 void *clientData;
137 WMAction2 *action;
139 /* Common Stuff */
140 WMColorWell *colorWell;
141 WMButton *magnifyBtn;
142 WMButton *wheelBtn;
143 WMButton *slidersBtn;
144 WMButton *customPaletteBtn;
145 WMButton *colorListBtn;
147 /* Magnifying Glass */
148 MovingView *magnifyGlass;
150 /* ColorWheel Panel */
151 WMFrame *wheelFrm;
152 WMSlider *wheelBrightnessS;
153 WMView *wheelView;
155 /* Slider Panels */
156 WMFrame *slidersFrm;
157 WMFrame *seperatorFrm;
158 WMButton *grayBtn;
159 WMButton *rgbBtn;
160 WMButton *cmykBtn;
161 WMButton *hsbBtn;
162 /* Gray Scale Panel */
163 WMFrame *grayFrm;
164 WMLabel *grayMinL;
165 WMLabel *grayMaxL;
166 WMSlider *grayBrightnessS;
167 WMTextField *grayBrightnessT;
168 WMButton *grayPresetBtn[7];
170 /* RGB Panel */
171 WMFrame *rgbFrm;
172 WMLabel *rgbMinL;
173 WMLabel *rgbMaxL;
174 WMSlider *rgbRedS;
175 WMSlider *rgbGreenS;
176 WMSlider *rgbBlueS;
177 WMTextField *rgbRedT;
178 WMTextField *rgbGreenT;
179 WMTextField *rgbBlueT;
181 /* CMYK Panel */
182 WMFrame *cmykFrm;
183 WMLabel *cmykMinL;
184 WMLabel *cmykMaxL;
185 WMSlider *cmykCyanS;
186 WMSlider *cmykMagentaS;
187 WMSlider *cmykYellowS;
188 WMSlider *cmykBlackS;
189 WMTextField *cmykCyanT;
190 WMTextField *cmykMagentaT;
191 WMTextField *cmykYellowT;
192 WMTextField *cmykBlackT;
194 /* HSB Panel */
195 WMFrame *hsbFrm;
196 WMSlider *hsbHueS;
197 WMSlider *hsbSaturationS;
198 WMSlider *hsbBrightnessS;
199 WMTextField *hsbHueT;
200 WMTextField *hsbSaturationT;
201 WMTextField *hsbBrightnessT;
203 /* Custom Palette Panel*/
204 WMFrame *customPaletteFrm;
205 WMPopUpButton *customPaletteHistoryBtn;
206 WMFrame *customPaletteContentFrm;
207 WMPopUpButton *customPaletteMenuBtn;
208 WMView *customPaletteContentView;
210 /* Color List Panel */
211 WMFrame *colorListFrm;
212 WMPopUpButton *colorListHistoryBtn;
213 WMList *colorListContentLst;
214 WMPopUpButton *colorListColorMenuBtn;
215 WMPopUpButton *colorListListMenuBtn;
217 /* Look-Up Tables and Images */
218 wheelMatrix *wheelMtrx;
219 Pixmap wheelImg;
220 Pixmap selectionImg;
221 Pixmap selectionBackImg;
222 RImage *customPaletteImg;
223 char *lastBrowseDir;
225 /* Common Data Fields */
226 CPColor color; /* Current color */
227 WMColorPanelMode mode; /* Current color selection mode */
228 WMColorPanelMode slidersmode; /* Current color sel. mode sliders panel */
229 WMColorPanelMode lastChanged; /* Panel that last changed the color */
230 int colx, coly; /* (x,y) of sel.-marker in WheelMode */
231 int palx, paly; /* (x,y) of sel.-marker in
232 CustomPaletteMode */
233 double palXRatio, palYRatio; /* Ratios in x & y between
234 original and scaled
235 palettesize */
236 int currentPalette;
237 char *configurationPath;
239 struct {
240 unsigned int continuous:1;
241 unsigned int dragging:1;
242 } flags;
243 } W_ColorPanel;
245 enum {
246 CPmenuNewFromFile,
247 CPmenuRename,
248 CPmenuRemove,
249 CPmenuCopy,
250 CPmenuNewFromClipboard
251 } customPaletteMenuItem;
253 enum {
254 CLmenuAdd,
255 CLmenuRename,
256 CLmenuRemove
257 } colorListMenuItem;
260 #define PWIDTH 194
261 #define PHEIGHT 266
262 #define colorWheelSize 150
263 #define customPaletteWidth 182
264 #define customPaletteHeight 106
265 #define knobThickness 8
267 #define SPECTRUM_WIDTH 511
268 #define SPECTRUM_HEIGHT 360
270 #define COLORWHEEL_PART 1
271 #define CUSTOMPALETTE_PART 2
272 #define BUFSIZE 1024
274 #ifndef RGBTXT
275 #define RGBTXT "/usr/X11R6/lib/X11/rgb.txt"
276 #endif
278 #define MAX_LENGTH 1024
281 #ifndef M_PI
282 #define M_PI 3.14159265358979323846
283 #endif
285 /* Silly hack for Windows systems with cygwin */
286 #ifndef O_BINARY
287 # define O_BINARY 0
288 #endif
290 static int fetchFile(char* toPath, char *imageSrcFile,
291 char *imageDestFileName);
292 char *generateNewFilename(char *curName);
293 void convertCPColor(CPColor *color);
294 RColor ulongToRColor(WMScreen *scr, unsigned long value);
295 unsigned char getShift(unsigned char value);
297 static void modeButtonCallback(WMWidget *w, void *data);
298 static int getPickerPart(W_ColorPanel *panel, int x, int y);
299 static void readConfiguration(W_ColorPanel *panel);
300 static void readXColors(W_ColorPanel *panel);
302 static void closeWindowCallback(WMWidget *w, void *data);
304 static Cursor magnifyGrabPointer(W_ColorPanel *panel);
305 static WMPoint magnifyInitialize(W_ColorPanel *panel);
306 static void magnifyPutCursor(WMWidget *w, void *data);
307 static Pixmap magnifyCreatePixmap(WMColorPanel *panel);
308 static void magnifyGetImageStored(W_ColorPanel *panel, int x1, int y1,
309 int x2, int y2);
310 static XImage* magnifyGetImage(WMScreen *scr, XImage *image, int x, int y,
311 int w, int h);
313 static wheelMatrix* wheelCreateMatrix(unsigned int width , unsigned int height);
314 static void wheelDestroyMatrix(wheelMatrix *matrix);
315 static void wheelInitMatrix(W_ColorPanel *panel);
316 static void wheelCalculateValues(W_ColorPanel *panel, int maxvalue);
317 static void wheelRender(W_ColorPanel *panel);
318 static Bool wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs);
319 static void wheelPaint(W_ColorPanel *panel);
321 static void wheelHandleEvents(XEvent *event, void *data);
322 static void wheelHandleActionEvents(XEvent *event, void *data);
323 static void wheelBrightnessSliderCallback(WMWidget *w, void *data);
324 static void wheelUpdateSelection(W_ColorPanel *panel);
325 static void wheelUndrawSelection(W_ColorPanel *panel);
327 static void wheelPositionSelection(W_ColorPanel *panel, int x, int y);
328 static void wheelPositionSelectionOutBounds(W_ColorPanel *panel, int x, int y);
329 static void wheelUpdateBrightnessGradientFromLocation (W_ColorPanel *panel);
330 static void wheelUpdateBrightnessGradient(W_ColorPanel *panel, CPColor topColor);
332 static void grayBrightnessSliderCallback(WMWidget *w, void *data);
333 static void grayPresetButtonCallback(WMWidget *w, void *data);
334 static void grayBrightnessTextFieldCallback(void *observerData,
335 WMNotification *notification);
337 static void rgbSliderCallback(WMWidget *w, void *data);
338 static void rgbTextFieldCallback(void *observerData,
339 WMNotification *notification);
341 static void cmykSliderCallback(WMWidget *w, void *data);
342 static void cmykTextFieldCallback(void *observerData,
343 WMNotification *notification);
345 static void hsbSliderCallback(WMWidget *w, void *data);
346 static void hsbTextFieldCallback(void *observerData,
347 WMNotification *notification);
348 static void hsbUpdateBrightnessGradient(W_ColorPanel *panel);
349 static void hsbUpdateSaturationGradient(W_ColorPanel *panel);
350 static void hsbUpdateHueGradient(W_ColorPanel *panel);
352 static void customRenderSpectrum(W_ColorPanel *panel);
353 static void customSetPalette(W_ColorPanel *panel);
354 static void customPaletteHandleEvents(XEvent *event, void *data);
355 static void customPaletteHandleActionEvents(XEvent *event, void *data);
356 static void customPalettePositionSelection(W_ColorPanel *panel, int x, int y);
357 static void customPalettePositionSelectionOutBounds(W_ColorPanel *panel,
358 int x, int y);
359 static void customPaletteMenuCallback(WMWidget *w, void *data);
360 static void customPaletteHistoryCallback(WMWidget *w, void *data);
362 static void customPaletteMenuNewFromFile(W_ColorPanel *panel);
363 static void customPaletteMenuRename(W_ColorPanel *panel);
364 static void customPaletteMenuRemove(W_ColorPanel *panel);
366 static void colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text,
367 int state, WMRect *rect);
368 static void colorListSelect(WMWidget *w, void *data);
369 static void colorListColorMenuCallback(WMWidget *w, void *data);
370 static void colorListListMenuCallback(WMWidget *w, void *data);
371 static void colorListListMenuNew(W_ColorPanel *panel);
373 static void wheelInit(W_ColorPanel *panel);
374 static void grayInit(W_ColorPanel *panel);
375 static void rgbInit(W_ColorPanel *panel);
376 static void cmykInit(W_ColorPanel *panel);
377 static void hsbInit(W_ColorPanel *panel);
381 void
382 WMSetColorPanelAction(WMColorPanel *panel, WMAction2 *action, void *data)
384 panel->action = action;
385 panel->clientData = data;
388 static WMColorPanel*
389 makeColorPanel(WMScreen *scrPtr, char *name)
391 WMColorPanel *panel;
392 RImage *image;
393 WMPixmap *pixmap;
394 RColor from;
395 RColor to;
396 WMColor *textcolor, *graybuttoncolor;
397 int i;
398 GC bgc = WMColorGC(scrPtr->black);
399 GC wgc = WMColorGC(scrPtr->white);
402 panel = wmalloc(sizeof(WMColorPanel));
403 memset(panel, 0, sizeof(WMColorPanel));
405 panel->color.rgb.red = 0;
406 panel->color.rgb.green = 0;
407 panel->color.rgb.blue = 0;
408 panel->color.hsv.hue = 0;
409 panel->color.hsv.saturation = 0;
410 panel->color.hsv.value = 0;
411 panel->color.set = cpNone; /* Color has not been set yet */
413 panel->font8 = WMSystemFontOfSize(scrPtr, 8);
414 panel->font12 = WMSystemFontOfSize(scrPtr, 12);
416 panel->win = WMCreateWindowWithStyle(scrPtr, name,
417 WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
418 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
419 WMSetWindowTitle(panel->win, _("Colors"));
420 WMSetWindowCloseAction(panel->win, closeWindowCallback, panel);
423 /* Set Default ColorPanel Mode(s) */
424 panel->mode = WMWheelModeColorPanel;
425 panel->lastChanged = 0;
426 panel->slidersmode = WMRGBModeColorPanel;
427 panel->configurationPath = wstrconcat(wusergnusteppath(),
428 "/Library/Colors/");
430 /* Some General Purpose Widgets */
431 panel->colorWell = WMCreateColorWell(panel->win);
432 WMResizeWidget(panel->colorWell, 134, 36);
433 WSetColorWellBordered(panel->colorWell, False);
434 WMMoveWidget(panel->colorWell, 56, 4);
436 panel->magnifyBtn = WMCreateCustomButton(panel->win,
437 WBBStateLightMask|WBBStateChangeMask);
438 WMResizeWidget(panel->magnifyBtn, 46, 36);
439 WMMoveWidget(panel->magnifyBtn, 6,4);
440 WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
441 WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
442 WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
444 panel->wheelBtn = WMCreateCustomButton(panel->win,
445 WBBStateLightMask|WBBStateChangeMask);
446 WMResizeWidget(panel->wheelBtn, 46, 32);
447 WMMoveWidget(panel->wheelBtn, 6, 44);
448 WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
449 WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
450 WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
452 panel->slidersBtn = WMCreateCustomButton(panel->win,
453 WBBStateLightMask|WBBStateChangeMask);
454 WMResizeWidget(panel->slidersBtn, 46, 32);
455 WMMoveWidget(panel->slidersBtn, 52, 44);
456 WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
457 WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
458 WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
460 panel->customPaletteBtn = WMCreateCustomButton(panel->win,
461 WBBStateLightMask|WBBStateChangeMask);
462 WMResizeWidget(panel->customPaletteBtn, 46, 32);
463 WMMoveWidget(panel->customPaletteBtn, 98, 44);
464 WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
465 WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
466 WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
468 panel->colorListBtn = WMCreateCustomButton(panel->win,
469 WBBStateLightMask|WBBStateChangeMask);
470 WMResizeWidget(panel->colorListBtn, 46, 32);
471 WMMoveWidget(panel->colorListBtn, 144, 44);
472 WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
473 WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
474 WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
476 /* Let's Group some of them together */
477 WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
478 WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
479 WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
481 /* Widgets for the ColorWheel Panel */
482 panel->wheelFrm = WMCreateFrame(panel->win);
483 WMSetFrameRelief(panel->wheelFrm, WRFlat);
484 WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
485 WMMoveWidget(panel->wheelFrm, 5, 80);
487 panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
488 /* XXX Can we create a view ? */
489 W_ResizeView(panel->wheelView, colorWheelSize+4, colorWheelSize+4);
490 W_MoveView(panel->wheelView, 0, 0);
492 /* Create an event handler to handle expose/click events in ColorWheel */
493 WMCreateEventHandler(panel->wheelView,
494 ButtonPressMask|ButtonReleaseMask|EnterWindowMask|
495 LeaveWindowMask|ButtonMotionMask, wheelHandleActionEvents, panel);
497 WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents,
498 panel);
500 panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
501 WMResizeWidget(panel->wheelBrightnessS, 16, 153);
502 WMMoveWidget(panel->wheelBrightnessS, 5+colorWheelSize+14, 1);
503 WMSetSliderMinValue(panel->wheelBrightnessS, 0);
504 WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
505 WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback,
506 panel);
507 WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
509 panel->wheelMtrx = wheelCreateMatrix(colorWheelSize+4, colorWheelSize+4);
510 wheelInitMatrix(panel);
513 /* Widgets for the Slider Panels */
514 panel->slidersFrm = WMCreateFrame(panel->win);
515 WMSetFrameRelief(panel->slidersFrm, WRFlat);
516 WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
517 WMMoveWidget(panel->slidersFrm, 4, 80);
519 panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
520 WMSetFrameRelief(panel->seperatorFrm, WRPushed);
521 WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
522 WMMoveWidget(panel->seperatorFrm, 0, 1);
524 panel->grayBtn = WMCreateCustomButton(panel->slidersFrm,
525 WBBStateLightMask|WBBStateChangeMask);
526 WMResizeWidget(panel->grayBtn, 46, 24);
527 WMMoveWidget(panel->grayBtn, 1, 8);
528 WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
529 WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
530 WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
532 panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm,
533 WBBStateLightMask|WBBStateChangeMask);
534 WMResizeWidget(panel->rgbBtn, 46, 24);
535 WMMoveWidget(panel->rgbBtn, 47, 8);
536 WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
537 WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
538 WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
540 panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm,
541 WBBStateLightMask|WBBStateChangeMask);
542 WMResizeWidget(panel->cmykBtn, 46, 24);
543 WMMoveWidget(panel->cmykBtn, 93, 8);
544 WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
545 WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
546 WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
548 panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm,
549 WBBStateLightMask|WBBStateChangeMask);
550 WMResizeWidget(panel->hsbBtn, 46, 24);
551 WMMoveWidget(panel->hsbBtn, 139, 8);
552 WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
553 WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
554 WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
556 /* Let's Group the Slider Panel Buttons Together */
557 WMGroupButtons(panel->grayBtn, panel->rgbBtn);
558 WMGroupButtons(panel->grayBtn, panel->cmykBtn);
559 WMGroupButtons(panel->grayBtn, panel->hsbBtn);
561 textcolor = WMDarkGrayColor(scrPtr);
563 /* Widgets for GrayScale Panel */
564 panel->grayFrm = WMCreateFrame(panel->slidersFrm);
565 WMSetFrameRelief(panel->grayFrm, WRFlat);
566 WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
567 WMMoveWidget(panel->grayFrm, 0, 34);
569 panel->grayMinL = WMCreateLabel(panel->grayFrm);
570 WMResizeWidget(panel->grayMinL, 20, 10);
571 WMMoveWidget(panel->grayMinL, 2, 2);
572 WMSetLabelText(panel->grayMinL, "0");
573 WMSetLabelTextAlignment(panel->grayMinL, WALeft);
574 WMSetLabelTextColor(panel->grayMinL, textcolor);
575 WMSetLabelFont(panel->grayMinL, panel->font8);
577 panel->grayMaxL = WMCreateLabel(panel->grayFrm);
578 WMResizeWidget(panel->grayMaxL, 40, 10);
579 WMMoveWidget(panel->grayMaxL, 104, 2);
580 WMSetLabelText(panel->grayMaxL, "100");
581 WMSetLabelTextAlignment(panel->grayMaxL, WARight);
582 WMSetLabelTextColor(panel->grayMaxL, textcolor);
583 WMSetLabelFont(panel->grayMaxL, panel->font8);
585 panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
586 WMResizeWidget(panel->grayBrightnessS, 141, 16);
587 WMMoveWidget(panel->grayBrightnessS, 2, 14);
588 WMSetSliderMinValue(panel->grayBrightnessS, 0);
589 WMSetSliderMaxValue(panel->grayBrightnessS, 100);
590 WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
591 WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback,
592 panel);
594 from.red = 0;
595 from.green = 0;
596 from.blue = 0;
598 to.red = 255;
599 to.green = 255;
600 to.blue = 255;
602 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
603 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
604 RReleaseImage(image);
606 if (pixmap)
607 W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap,
608 panel->font12, 2, 0, 100, WALeft, scrPtr->white,
609 False, _("Brightness"), strlen(_("Brightness")));
610 else
611 wwarning(_("Color Panel: Could not allocate memory"));
613 WMSetSliderImage(panel->grayBrightnessS, pixmap);
614 WMReleasePixmap(pixmap);
616 panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
617 WMResizeWidget(panel->grayBrightnessT, 40, 18);
618 WMMoveWidget(panel->grayBrightnessT, 146, 13);
619 WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
620 WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel,
621 WMTextDidEndEditingNotification, panel->grayBrightnessT);
623 for (i=0; i < 7; i++) {
624 pixmap = WMCreatePixmap(scrPtr, 13, 13, scrPtr->depth, False);
626 graybuttoncolor = WMCreateRGBColor(scrPtr, (255/6)*i << 8,
627 (255/6)*i << 8, (255/6)*i << 8, True);
628 WMPaintColorSwatch(graybuttoncolor, pixmap->pixmap, 0, 0, 15, 15);
629 WMReleaseColor(graybuttoncolor);
631 panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
632 WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
633 WMMoveWidget(panel->grayPresetBtn[i], 2+(i*20), 34);
634 WMSetButtonAction(panel->grayPresetBtn[i],
635 grayPresetButtonCallback, panel);
636 WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
637 WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
638 WMReleasePixmap(pixmap);
642 /* End of GrayScale Panel */
644 /* Widgets for RGB Panel */
645 panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
646 WMSetFrameRelief(panel->rgbFrm, WRFlat);
647 WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
648 WMMoveWidget(panel->rgbFrm, 0, 34);
650 panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
651 WMResizeWidget(panel->rgbMinL, 20, 10);
652 WMMoveWidget(panel->rgbMinL, 2, 2);
653 WMSetLabelText(panel->rgbMinL, "0");
654 WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
655 WMSetLabelTextColor(panel->rgbMinL, textcolor);
656 WMSetLabelFont(panel->rgbMinL, panel->font8);
658 panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
659 WMResizeWidget(panel->rgbMaxL, 40, 10);
660 WMMoveWidget(panel->rgbMaxL, 104, 2);
661 WMSetLabelText(panel->rgbMaxL, "255");
662 WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
663 WMSetLabelTextColor(panel->rgbMaxL, textcolor);
664 WMSetLabelFont(panel->rgbMaxL, panel->font8);
666 panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
667 WMResizeWidget(panel->rgbRedS, 141, 16);
668 WMMoveWidget(panel->rgbRedS, 2, 14);
669 WMSetSliderMinValue(panel->rgbRedS, 0);
670 WMSetSliderMaxValue(panel->rgbRedS, 255);
671 WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
672 WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
674 to.red = 255;
675 to.green = 0;
676 to.blue = 0;
678 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
679 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
680 RReleaseImage(image);
682 if (pixmap)
683 W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12,
684 2, 0, 100, WALeft, scrPtr->white, False, _("Red"),
685 strlen(_("Red")));
686 else
687 wwarning(_("Color Panel: Could not allocate memory"));
689 WMSetSliderImage(panel->rgbRedS, pixmap);
690 WMReleasePixmap(pixmap);
692 panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
693 WMResizeWidget(panel->rgbRedT, 40, 18);
694 WMMoveWidget(panel->rgbRedT, 146, 13);
695 WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
696 WMAddNotificationObserver(rgbTextFieldCallback, panel,
697 WMTextDidEndEditingNotification, panel->rgbRedT);
699 panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
700 WMResizeWidget(panel->rgbGreenS, 141, 16);
701 WMMoveWidget(panel->rgbGreenS, 2, 36);
702 WMSetSliderMinValue(panel->rgbGreenS, 0);
703 WMSetSliderMaxValue(panel->rgbGreenS, 255);
704 WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
705 WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
707 to.red = 0;
708 to.green = 255;
709 to.blue = 0;
711 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
712 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
713 RReleaseImage(image);
715 if (pixmap)
716 W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12,
717 2, 0, 100, WALeft, scrPtr->white, False, _("Green"),
718 strlen(_("Green")));
719 else
720 wwarning(_("Color Panel: Could not allocate memory"));
722 WMSetSliderImage(panel->rgbGreenS, pixmap);
723 WMReleasePixmap(pixmap);
725 panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
726 WMResizeWidget(panel->rgbGreenT, 40, 18);
727 WMMoveWidget(panel->rgbGreenT, 146, 35);
728 WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
729 WMAddNotificationObserver(rgbTextFieldCallback, panel,
730 WMTextDidEndEditingNotification, panel->rgbGreenT);
733 panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
734 WMResizeWidget(panel->rgbBlueS, 141, 16);
735 WMMoveWidget(panel->rgbBlueS, 2, 58);
736 WMSetSliderMinValue(panel->rgbBlueS, 0);
737 WMSetSliderMaxValue(panel->rgbBlueS, 255);
738 WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
739 WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
741 to.red = 0;
742 to.green = 0;
743 to.blue = 255;
745 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
746 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
747 RReleaseImage(image);
749 if (pixmap)
750 W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12,
751 2, 0, 100, WALeft, scrPtr->white, False, _("Blue"),
752 strlen(_("Blue")));
753 else
754 wwarning(_("Color Panel: Could not allocate memory"));
756 WMSetSliderImage(panel->rgbBlueS, pixmap);
757 WMReleasePixmap(pixmap);
759 panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
760 WMResizeWidget(panel->rgbBlueT, 40, 18);
761 WMMoveWidget(panel->rgbBlueT, 146, 57);
762 WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
763 WMAddNotificationObserver(rgbTextFieldCallback, panel,
764 WMTextDidEndEditingNotification, panel->rgbBlueT);
765 /* End of RGB Panel */
767 /* Widgets for CMYK Panel */
768 panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
769 WMSetFrameRelief(panel->cmykFrm, WRFlat);
770 WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
771 WMMoveWidget(panel->cmykFrm, 0, 34);
773 panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
774 WMResizeWidget(panel->cmykMinL, 20, 10);
775 WMMoveWidget(panel->cmykMinL, 2, 2);
776 WMSetLabelText(panel->cmykMinL, "0");
777 WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
778 WMSetLabelTextColor(panel->cmykMinL, textcolor);
779 WMSetLabelFont(panel->cmykMinL, panel->font8);
781 panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
782 WMResizeWidget(panel->cmykMaxL, 40, 10);
783 WMMoveWidget(panel->cmykMaxL, 104, 2);
784 WMSetLabelText(panel->cmykMaxL, "100");
785 WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
786 WMSetLabelTextColor(panel->cmykMaxL, textcolor);
787 WMSetLabelFont(panel->cmykMaxL, panel->font8);
789 panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
790 WMResizeWidget(panel->cmykCyanS, 141, 16);
791 WMMoveWidget(panel->cmykCyanS, 2, 14);
792 WMSetSliderMinValue(panel->cmykCyanS, 0);
793 WMSetSliderMaxValue(panel->cmykCyanS, 100);
794 WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
795 WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
797 from.red = 255;
798 from.green = 255;
799 from.blue = 255;
801 to.red = 0;
802 to.green = 255;
803 to.blue = 255;
805 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
806 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
807 RReleaseImage(image);
809 if (pixmap)
810 W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12,
811 2, 0, 100, WALeft, scrPtr->black, False, _("Cyan"),
812 strlen(_("Cyan")));
813 else
814 wwarning(_("Color Panel: Could not allocate memory"));
816 WMSetSliderImage(panel->cmykCyanS, pixmap);
817 WMReleasePixmap(pixmap);
819 panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
820 WMResizeWidget(panel->cmykCyanT, 40, 18);
821 WMMoveWidget(panel->cmykCyanT, 146, 13);
822 WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
823 WMAddNotificationObserver(cmykTextFieldCallback, panel,
824 WMTextDidEndEditingNotification, panel->cmykCyanT);
827 panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
828 WMResizeWidget(panel->cmykMagentaS, 141, 16);
829 WMMoveWidget(panel->cmykMagentaS, 2, 36);
830 WMSetSliderMinValue(panel->cmykMagentaS, 0);
831 WMSetSliderMaxValue(panel->cmykMagentaS, 100);
832 WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
833 WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
835 to.red = 255;
836 to.green = 0;
837 to.blue = 255;
839 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
840 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
841 RReleaseImage(image);
843 if (pixmap)
844 W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12,
845 2, 0, 100, WALeft, scrPtr->black, False, _("Magenta"),
846 strlen(_("Magenta")));
847 else
848 wwarning(_("Color Panel: Could not allocate memory"));
850 WMSetSliderImage(panel->cmykMagentaS, pixmap);
851 WMReleasePixmap(pixmap);
853 panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
854 WMResizeWidget(panel->cmykMagentaT, 40, 18);
855 WMMoveWidget(panel->cmykMagentaT, 146, 35);
856 WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
857 WMAddNotificationObserver(cmykTextFieldCallback, panel,
858 WMTextDidEndEditingNotification, panel->cmykMagentaT);
861 panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
862 WMResizeWidget(panel->cmykYellowS, 141, 16);
863 WMMoveWidget(panel->cmykYellowS, 2, 58);
864 WMSetSliderMinValue(panel->cmykYellowS, 0);
865 WMSetSliderMaxValue(panel->cmykYellowS, 100);
866 WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
867 WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
869 to.red = 255;
870 to.green = 255;
871 to.blue = 0;
873 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
874 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
875 RReleaseImage(image);
877 if (pixmap)
878 W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12,
879 2, 0, 100, WALeft, scrPtr->black, False, _("Yellow"),
880 strlen(_("Yellow")));
881 else
882 wwarning(_("Color Panel: Could not allocate memory"));
884 WMSetSliderImage(panel->cmykYellowS, pixmap);
885 WMReleasePixmap(pixmap);
887 panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
888 WMResizeWidget(panel->cmykYellowT, 40, 18);
889 WMMoveWidget(panel->cmykYellowT, 146, 57);
890 WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
891 WMAddNotificationObserver(cmykTextFieldCallback, panel,
892 WMTextDidEndEditingNotification, panel->cmykYellowT);
895 panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
896 WMResizeWidget(panel->cmykBlackS, 141, 16);
897 WMMoveWidget(panel->cmykBlackS, 2, 80);
898 WMSetSliderMinValue(panel->cmykBlackS, 0);
899 WMSetSliderMaxValue(panel->cmykBlackS, 100);
900 WMSetSliderValue(panel->cmykBlackS, 0);
901 WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
902 WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
904 to.red = 0;
905 to.green = 0;
906 to.blue = 0;
908 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
909 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
910 RReleaseImage(image);
912 if (pixmap)
913 W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12,
914 2, 0, 100, WALeft, scrPtr->black, False, _("Black"),
915 strlen(_("Black")));
916 else
917 wwarning(_("Color Panel: Could not allocate memory"));
919 WMSetSliderImage(panel->cmykBlackS, pixmap);
920 WMReleasePixmap(pixmap);
922 panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
923 WMResizeWidget(panel->cmykBlackT, 40, 18);
924 WMMoveWidget(panel->cmykBlackT, 146, 79);
925 WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
926 WMAddNotificationObserver(cmykTextFieldCallback, panel,
927 WMTextDidEndEditingNotification, panel->cmykBlackT);
928 /* End of CMYK Panel */
930 /* Widgets for HSB Panel */
931 panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
932 WMSetFrameRelief(panel->hsbFrm, WRFlat);
933 WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
934 WMMoveWidget(panel->hsbFrm, 0, 34);
936 panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
937 WMResizeWidget(panel->hsbHueS, 141, 16);
938 WMMoveWidget(panel->hsbHueS, 2, 14);
939 WMSetSliderMinValue(panel->hsbHueS, 0);
940 WMSetSliderMaxValue(panel->hsbHueS, 359);
941 WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
942 WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
944 panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
945 WMResizeWidget(panel->hsbHueT, 40, 18);
946 WMMoveWidget(panel->hsbHueT, 146, 13);
947 WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
948 WMAddNotificationObserver(hsbTextFieldCallback, panel,
949 WMTextDidEndEditingNotification, panel->hsbHueT);
952 panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
953 WMResizeWidget(panel->hsbSaturationS, 141, 16);
954 WMMoveWidget(panel->hsbSaturationS, 2, 36);
955 WMSetSliderMinValue(panel->hsbSaturationS, 0);
956 WMSetSliderMaxValue(panel->hsbSaturationS, 100);
957 WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
958 WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
960 panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
961 WMResizeWidget(panel->hsbSaturationT, 40, 18);
962 WMMoveWidget(panel->hsbSaturationT, 146, 35);
963 WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
964 WMAddNotificationObserver(hsbTextFieldCallback, panel,
965 WMTextDidEndEditingNotification, panel->hsbSaturationT);
968 panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
969 WMResizeWidget(panel->hsbBrightnessS, 141, 16);
970 WMMoveWidget(panel->hsbBrightnessS, 2, 58);
971 WMSetSliderMinValue(panel->hsbBrightnessS, 0);
972 WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
973 WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
974 WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
976 panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
977 WMResizeWidget(panel->hsbBrightnessT, 40, 18);
978 WMMoveWidget(panel->hsbBrightnessT, 146, 57);
979 WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
980 WMAddNotificationObserver(hsbTextFieldCallback, panel,
981 WMTextDidEndEditingNotification, panel->hsbBrightnessT);
982 /* End of HSB Panel */
985 WMReleaseColor(textcolor);
987 /* Widgets for the CustomPalette Panel */
988 panel->customPaletteFrm = WMCreateFrame(panel->win);
989 WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
990 WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
991 WMMoveWidget(panel->customPaletteFrm, 5, 80);
993 panel->customPaletteHistoryBtn = WMCreatePopUpButton(
994 panel->customPaletteFrm);
995 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, _("Spectrum"));
996 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
997 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn)-1);
998 WMSetPopUpButtonAction(panel->customPaletteHistoryBtn,
999 customPaletteHistoryCallback, panel);
1000 WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
1001 WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
1003 panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
1004 WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
1005 WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
1006 WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
1008 panel->customPaletteContentView = W_CreateView(
1009 W_VIEW(panel->customPaletteContentFrm));
1010 /* XXX Test if we can create a view */
1011 W_ResizeView(panel->customPaletteContentView, customPaletteWidth,
1012 customPaletteHeight);
1013 W_MoveView(panel->customPaletteContentView, 2, 2);
1015 /* Create event handler to handle expose/click events in CustomPalette */
1016 WMCreateEventHandler(panel->customPaletteContentView,
1017 ButtonPressMask|ButtonReleaseMask|EnterWindowMask| LeaveWindowMask |
1018 ButtonMotionMask, customPaletteHandleActionEvents, panel);
1020 WMCreateEventHandler(panel->customPaletteContentView, ExposureMask,
1021 customPaletteHandleEvents, panel);
1023 panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
1024 WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
1025 WMSetPopUpButtonText(panel->customPaletteMenuBtn, _("Palette"));
1026 WMSetPopUpButtonAction(panel->customPaletteMenuBtn,
1027 customPaletteMenuCallback, panel);
1028 WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
1029 WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
1031 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from File..."));
1032 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Rename..."));
1033 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Remove"));
1034 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Copy"));
1035 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from Clipboard"));
1037 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, 0);
1038 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, 0);
1039 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuCopy, 0);
1040 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn,
1041 CPmenuNewFromClipboard, 0);
1043 customRenderSpectrum(panel);
1044 panel->currentPalette = 0;
1045 panel->palx = customPaletteWidth/2;
1046 panel->paly = customPaletteHeight/2;
1049 /* Widgets for the ColorList Panel */
1050 panel->colorListFrm = WMCreateFrame(panel->win);
1051 WMSetFrameRelief(panel->colorListFrm, WRFlat);
1052 WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
1053 WMMoveWidget(panel->colorListFrm, 5, 80);
1055 panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
1056 WMAddPopUpButtonItem(panel->colorListHistoryBtn, _("X11-Colors"));
1057 WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn,
1058 WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn)-1);
1059 /* WMSetPopUpButtonAction(panel->colorListHistoryBtn,
1060 * colorListHistoryCallback, panel); */
1061 WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
1062 WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
1064 panel->colorListContentLst = WMCreateList(panel->colorListFrm);
1065 WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
1066 WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
1067 WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
1068 WMMoveWidget(panel->colorListContentLst, 0, 23);
1069 WMHangData(panel->colorListContentLst, panel);
1071 panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1072 WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
1073 WMSetPopUpButtonText(panel->colorListColorMenuBtn, _("Color"));
1074 WMSetPopUpButtonAction(panel->colorListColorMenuBtn,
1075 colorListColorMenuCallback, panel);
1076 WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16)/2, 20);
1077 WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
1079 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Add..."));
1080 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Rename..."));
1081 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Remove"));
1083 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuAdd, 0);
1084 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRename, 0);
1085 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRemove, 0);
1087 panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1088 WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
1089 WMSetPopUpButtonText(panel->colorListListMenuBtn, _("List"));
1090 WMSetPopUpButtonAction(panel->colorListListMenuBtn,
1091 colorListListMenuCallback, panel);
1092 WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16)/2, 20);
1093 WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16)/2 + 8,
1094 PHEIGHT - 130);
1096 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("New..."));
1097 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Rename..."));
1098 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Remove"));
1100 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuAdd, 0);
1101 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
1102 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
1104 WMRealizeWidget(panel->win);
1105 WMMapSubwidgets(panel->win);
1107 WMMapSubwidgets(panel->wheelFrm);
1108 WMMapSubwidgets(panel->slidersFrm);
1109 WMMapSubwidgets(panel->grayFrm);
1110 WMMapSubwidgets(panel->rgbFrm);
1111 WMMapSubwidgets(panel->cmykFrm);
1112 WMMapSubwidgets(panel->hsbFrm);
1113 WMMapSubwidgets(panel->customPaletteFrm);
1114 WMMapSubwidgets(panel->customPaletteContentFrm);
1115 WMMapSubwidgets(panel->colorListFrm);
1117 /* Pixmap to indicate selection positions
1118 * wheelframe MUST be mapped.
1120 panel->selectionImg = XCreatePixmap(scrPtr->display,
1121 WMWidgetXID(panel->win), 4, 4, scrPtr->depth);
1122 XFillRectangle(scrPtr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1123 XFillRectangle(scrPtr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1125 readConfiguration(panel);
1126 readXColors(panel);
1128 return panel;
1132 WMColorPanel*
1133 WMGetColorPanel(WMScreen *scrPtr)
1135 WMColorPanel *panel;
1137 if (scrPtr->sharedColorPanel)
1138 return scrPtr->sharedColorPanel;
1140 panel = makeColorPanel(scrPtr, "colorPanel");
1142 scrPtr->sharedColorPanel = panel;
1144 return panel;
1148 void
1149 WMFreeColorPanel(WMColorPanel *panel)
1151 W_Screen *scr = WMWidgetScreen(panel->win);
1153 if (panel == scr->sharedColorPanel) {
1154 scr->sharedColorPanel = NULL;
1157 if (!panel)
1158 return;
1160 WMRemoveNotificationObserver(panel);
1161 WMUnmapWidget(panel->win);
1163 /* fonts */
1164 WMReleaseFont(panel->font8);
1165 WMReleaseFont(panel->font12);
1167 /* pixmaps */
1168 wheelDestroyMatrix(panel->wheelMtrx);
1169 if (panel->wheelImg)
1170 XFreePixmap(scr->display, panel->wheelImg);
1171 if (panel->selectionImg)
1172 XFreePixmap(scr->display, panel->selectionImg);
1173 if (panel->selectionBackImg)
1174 XFreePixmap(scr->display, panel->selectionBackImg);
1175 RReleaseImage(panel->customPaletteImg);
1177 /* structs */
1178 if (panel->lastBrowseDir)
1179 wfree(panel->lastBrowseDir);
1180 if (panel->configurationPath)
1181 wfree(panel->configurationPath);
1183 WMDestroyWidget(panel->win);
1185 wfree(panel);
1189 void
1190 WMCloseColorPanel(WMColorPanel *panel)
1192 WMFreeColorPanel(panel);
1196 void
1197 WMShowColorPanel(WMColorPanel *panel)
1199 WMScreen *scr = WMWidgetScreen(panel->win);
1200 WMColor *white = WMWhiteColor(scr);
1202 if (panel->color.set == cpNone)
1203 WMSetColorPanelColor(panel, white);
1204 WMReleaseColor(white);
1206 if (panel->mode != WMWheelModeColorPanel)
1207 WMPerformButtonClick(panel->wheelBtn);
1209 WMMapWidget(panel->win);
1213 static void
1214 closeWindowCallback(WMWidget *w, void *data)
1216 W_ColorPanel *panel = (W_ColorPanel*)data;
1218 WMCloseColorPanel(panel);
1222 static void
1223 readConfiguration(W_ColorPanel *panel)
1225 /* XXX Doesn't take care of "invalid" files */
1227 DIR *dPtr;
1228 struct dirent *dp;
1229 struct stat stat_buf;
1230 int item;
1232 if (stat(panel->configurationPath, &stat_buf)!=0) {
1233 if (mkdir(panel->configurationPath,
1234 S_IRWXU|S_IRGRP|S_IROTH|S_IXGRP|S_IXOTH)!=0) {
1235 wsyserror(_("Color Panel: Could not create directory %s needed"
1236 " to store configurations"), panel->configurationPath);
1237 WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
1238 WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
1239 WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
1240 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1241 _("File Error"),
1242 _("Could not create ColorPanel configuration directory"),
1243 _("OK"), NULL, NULL);
1245 return;
1248 if (!(dPtr = opendir(panel->configurationPath))) {
1249 wwarning(_("Color Panel: Could not find file"), "%s", panel->configurationPath);
1250 return;
1253 while ((dp = readdir(dPtr)) != NULL) {
1254 unsigned int perm_mask;
1255 char *path = wstrconcat(panel->configurationPath,
1256 dp->d_name);
1258 if (dp->d_name[0] != '.') {
1259 item = WMGetPopUpButtonNumberOfItems(
1260 panel->customPaletteHistoryBtn);
1261 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
1263 perm_mask = (access(path, R_OK) == 0);
1264 WMSetPopUpButtonItemEnabled(panel->customPaletteHistoryBtn,
1265 item, perm_mask);
1267 wfree(path);
1269 (void)closedir(dPtr);
1273 static void
1274 readXColors(W_ColorPanel *panel)
1276 struct stat stat_buf;
1277 FILE *rgbtxt;
1278 char line[MAX_LENGTH];
1279 int red, green, blue;
1280 char name[48];
1281 RColor *color;
1282 WMListItem *item;
1284 if (stat(RGBTXT, &stat_buf) != 0) {
1285 wsyserror(_("Color Panel: Could not find file"), " %s", RGBTXT);
1286 return;
1288 else {
1289 if ((rgbtxt = fopen(RGBTXT, "rb"))) {
1290 while (fgets(line, MAX_LENGTH, rgbtxt)) {
1291 if (sscanf(line, "%d%d%d %[^\n]", &red, &green, &blue, name)) {
1292 color = wmalloc(sizeof(RColor));
1293 color->red = (unsigned char)red;
1294 color->green = (unsigned char)green;
1295 color->blue = (unsigned char)blue;
1296 item = WMAddListItem(panel->colorListContentLst, name);
1297 item->clientData = (void *)color;
1300 fclose(rgbtxt);
1302 else {
1303 wsyserror(_("Color Panel: Could not find file"), "%s", RGBTXT);
1309 void
1310 WMSetColorPanelPickerMode(WMColorPanel *panel, WMColorPanelMode mode)
1312 W_Screen *scr = WMWidgetScreen(panel->win);
1314 if (mode != WMWheelModeColorPanel) {
1315 WMUnmapWidget(panel->wheelFrm);
1316 if (panel->selectionBackImg) {
1317 XFreePixmap(WMWidgetScreen(panel->win)->display,
1318 panel->selectionBackImg);
1319 panel->selectionBackImg = None;
1322 if (mode != WMGrayModeColorPanel)
1323 WMUnmapWidget(panel->grayFrm);
1324 if (mode != WMRGBModeColorPanel)
1325 WMUnmapWidget(panel->rgbFrm);
1326 if (mode != WMCMYKModeColorPanel)
1327 WMUnmapWidget(panel->cmykFrm);
1328 if (mode != WMHSBModeColorPanel)
1329 WMUnmapWidget(panel->hsbFrm);
1330 if (mode != WMCustomPaletteModeColorPanel) {
1331 WMUnmapWidget(panel->customPaletteFrm);
1332 if (panel->selectionBackImg) {
1333 XFreePixmap(WMWidgetScreen(panel->win)->display,
1334 panel->selectionBackImg);
1335 panel->selectionBackImg = None;
1338 if (mode != WMColorListModeColorPanel)
1339 WMUnmapWidget(panel->colorListFrm);
1340 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
1341 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1342 WMUnmapWidget(panel->slidersFrm);
1343 else
1344 panel->slidersmode = mode;
1346 if (mode == WMWheelModeColorPanel) {
1347 WMMapWidget(panel->wheelFrm);
1348 WMSetButtonSelected(panel->wheelBtn, True);
1349 if (panel->lastChanged != WMWheelModeColorPanel)
1350 wheelInit(panel);
1351 wheelRender(panel);
1352 wheelPaint(panel);
1353 } else if (mode == WMGrayModeColorPanel) {
1354 WMMapWidget(panel->slidersFrm);
1355 WMSetButtonSelected(panel->slidersBtn, True);
1356 WMMapWidget(panel->grayFrm);
1357 WMSetButtonSelected(panel->grayBtn, True);
1358 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1359 if (panel->lastChanged != WMGrayModeColorPanel)
1360 grayInit(panel);
1361 } else if (mode == WMRGBModeColorPanel) {
1362 WMMapWidget(panel->slidersFrm);
1363 WMSetButtonSelected(panel->slidersBtn, True);
1364 WMMapWidget(panel->rgbFrm);
1365 WMSetButtonSelected(panel->rgbBtn, True);
1366 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1367 if (panel->lastChanged != WMRGBModeColorPanel)
1368 rgbInit(panel);
1369 } else if (mode == WMCMYKModeColorPanel) {
1370 WMMapWidget(panel->slidersFrm);
1371 WMSetButtonSelected(panel->slidersBtn, True);
1372 WMMapWidget(panel->cmykFrm);
1373 WMSetButtonSelected(panel->cmykBtn, True);
1374 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1375 if (panel->lastChanged != WMCMYKModeColorPanel)
1376 cmykInit(panel);
1377 } else if (mode == WMHSBModeColorPanel) {
1378 WMMapWidget(panel->slidersFrm);
1379 WMSetButtonSelected(panel->slidersBtn, True);
1380 WMMapWidget(panel->hsbFrm);
1381 WMSetButtonSelected(panel->hsbBtn, True);
1382 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1383 if (panel->lastChanged != WMHSBModeColorPanel)
1384 hsbInit(panel);
1385 } else if (mode == WMCustomPaletteModeColorPanel) {
1386 WMMapWidget(panel->customPaletteFrm);
1387 WMSetButtonSelected(panel->customPaletteBtn, True);
1388 customSetPalette(panel);
1389 } else if (mode == WMColorListModeColorPanel) {
1390 WMMapWidget(panel->colorListFrm);
1391 WMSetButtonSelected(panel->colorListBtn, True);
1394 panel->mode = mode;
1398 WMColor*
1399 WMGetColorPanelColor(WMColorPanel *panel)
1401 return WMGetColorWellColor(panel->colorWell);
1405 void
1406 WMSetColorPanelColor(WMColorPanel *panel, WMColor *color)
1408 WMSetColorWellColor(panel->colorWell, color);
1410 panel->color.rgb.red = color->color.red >> 8;
1411 panel->color.rgb.green = color->color.green >> 8;
1412 panel->color.rgb.blue = color->color.blue >> 8;
1413 panel->color.set = cpRGB;
1415 if (panel->mode == panel->lastChanged)
1416 panel->lastChanged = 0;
1418 WMSetColorPanelPickerMode(panel, panel->mode);
1422 static void
1423 updateSwatch(WMColorPanel *panel, CPColor color)
1425 WMScreen *scr = WMWidgetScreen(panel->win);
1426 WMColor *wellcolor;
1428 if (color.set != cpRGB)
1429 convertCPColor(&color);
1431 panel->color = color;
1433 wellcolor = WMCreateRGBColor(scr, color.rgb.red << 8,
1434 color.rgb.green << 8,
1435 color.rgb.blue << 8, True);
1437 WMSetColorWellColor(panel->colorWell, wellcolor);
1438 WMReleaseColor(wellcolor);
1440 if (!panel->flags.dragging || panel->flags.continuous) {
1441 if (panel->action)
1442 (*panel->action)(panel, panel->clientData);
1444 WMPostNotificationName(WMColorPanelColorChangedNotification, panel,
1445 NULL);
1449 static void
1450 modeButtonCallback(WMWidget *w, void *data)
1452 W_ColorPanel *panel = (W_ColorPanel*)(data);
1454 if (w == panel->wheelBtn)
1455 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1456 else if (w == panel->slidersBtn)
1457 WMSetColorPanelPickerMode(panel, panel->slidersmode);
1458 else if (w == panel->customPaletteBtn)
1459 WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
1460 else if (w == panel->colorListBtn)
1461 WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
1462 else if (w == panel->grayBtn)
1463 WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
1464 else if (w == panel->rgbBtn)
1465 WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
1466 else if (w == panel->cmykBtn)
1467 WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
1468 else if (w == panel->hsbBtn)
1469 WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
1473 /****************** Magnifying Cursor Functions *******************/
1475 static XImage*
1476 magnifyGetImage(WMScreen *scr, XImage *image, int x, int y, int w, int h)
1478 int x0 = 0, y0 = 0, w0 = w, h0 = h;
1479 const int displayWidth = DisplayWidth(scr->display, scr->screen),
1480 displayHeight = DisplayHeight(scr->display, scr->screen);
1482 if (!(image && image->data)) {
1483 /* The image in panel->magnifyGlass->image does not exist yet.
1484 * Grab one from the screen (not beyond) and use it from now on.
1486 if (!(image = XGetImage(scr->display, scr->rootWin,
1487 x - Cursor_x_hot,
1488 y - Cursor_y_hot,
1489 w, h, AllPlanes, ZPixmap)))
1490 wwarning(_("Color Panel: X failed request"));
1492 return image;
1495 /* Coordinate correction for back pixmap
1496 * if magnifying glass is at screen-borders
1499 /* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
1500 * Hatched area is beyond screen border.
1502 * |<-Cursor_x_hot->|
1503 * ________________|_____
1504 * |/ / / / / / /| | |
1505 * | / / / / / / |(x,y) |
1506 * |/_/_/_/_/_/_/|________|
1507 * |<----x0----->|<--w0-->|
1511 /* Figure 2: Shifting of rectangle-to-grab at bottom/right
1512 * screen borders
1513 * Hatched area is beyond screen border
1515 * |<-Cursor_x_hot->|
1516 * ________________|_______________
1517 * | | | / / / / / /|
1518 * | (x,y)|/ / / / / / |
1519 * |___________________|_/_/_/_/_/_/|
1520 * |<-------w0-------->| |
1521 * |<---------------w--|----------->|
1522 * | |
1523 * x0 Displaywidth-1
1526 if (x < Cursor_x_hot) { /* see fig. 1 */
1527 x0 = Cursor_x_hot - x;
1528 w0 = w - x0;
1531 if (displayWidth -1 < x - Cursor_x_hot + w) { /* see fig. 2 */
1532 w0 = (displayWidth) - (x - Cursor_x_hot);
1535 if (y < Cursor_y_hot) { /* see fig. 1 */
1536 y0 = Cursor_y_hot - y;
1537 h0 = h - y0;
1540 if (displayHeight -1 < y - Cursor_y_hot + h) { /* see fig. 2 */
1541 h0 = (displayHeight) - (y - Cursor_y_hot);
1543 /* end of coordinate correction */
1546 /* Grab an image from the screen, clipped if necessary,
1547 * and put it in the existing panel->magnifyGlass->image
1548 * with the corresponding clipping offset.
1550 if (!XGetSubImage(scr->display, scr->rootWin,
1551 x - Cursor_x_hot + x0,
1552 y - Cursor_y_hot + y0,
1553 w0, h0, AllPlanes, ZPixmap,
1554 image, x0, y0))
1555 wwarning(_("Color Panel: X failed request"));
1557 return NULL;
1561 static void
1562 magnifyGetImageStored(WMColorPanel *panel, int x1, int y1, int x2, int y2)
1564 /* (x1, y1) = topleft corner of existing rectangle
1565 * (x2, y2) = topleft corner of new position
1568 W_Screen *scr = WMWidgetScreen(panel->win);
1569 int xa = 0, ya = 0, xb = 0, yb = 0;
1570 int width, height;
1571 const int dx = abs(x2 - x1),
1572 dy = abs(y2 - y1);
1573 XImage *image;
1574 const int x_min = Cursor_x_hot,
1575 y_min = Cursor_y_hot,
1576 x_max = DisplayWidth(scr->display, scr->screen) -1 -
1577 (Cursor_mask_width - Cursor_x_hot),
1578 y_max = DisplayHeight(scr->display, scr->screen) -1 -
1579 (Cursor_mask_height - Cursor_y_hot);
1581 if ((dx == 0) && (dy == 0) && panel->magnifyGlass->image)
1582 return; /* No movement */
1584 if (x1 < x2)
1585 xa = dx;
1586 else
1587 xb = dx;
1589 if (y1 < y2)
1590 ya = dy;
1591 else
1592 yb = dy;
1594 width = Cursor_mask_width - dx;
1595 height = Cursor_mask_height - dy;
1597 /* If the traversed distance is larger than the size of the magnifying
1598 * glass contents, there is no need to do dirty rectangles. A whole new
1599 * rectangle can be grabbed (unless that rectangle falls partially
1600 * off screen).
1601 * Destroying the image and setting it to NULL will achieve that later on.
1603 * Of course, grabbing an XImage beyond the borders of the screen will
1604 * cause trouble, this is considdered a special case. Part of the screen
1605 * is grabbed, but there is no need for dirty rectangles.
1607 if ((width <= 0) || (height <= 0)) {
1608 if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
1609 if (panel->magnifyGlass->image)
1610 XDestroyImage(panel->magnifyGlass->image);
1611 panel->magnifyGlass->image = NULL;
1613 } else {
1614 if (panel->magnifyGlass->image) {
1615 /* Get dirty rectangle from panel->magnifyGlass->image */
1616 panel->magnifyGlass->dirtyRect =
1617 XSubImage(panel->magnifyGlass->image, xa, ya, width, height);
1618 if (!panel->magnifyGlass->dirtyRect) {
1619 wwarning(_("Color Panel: X failed request"));
1620 return; /* X returned a NULL from XSubImage */
1625 /* Get image from screen */
1626 image = magnifyGetImage(scr, panel->magnifyGlass->image, x2, y2,
1627 Cursor_mask_width, Cursor_mask_height);
1628 if (image) { /* Only reassign if a *new* image was grabbed */
1629 panel->magnifyGlass->image = image;
1630 return;
1633 /* Copy previously stored rectangle on covered part of image */
1634 if (panel->magnifyGlass->image && panel->magnifyGlass->dirtyRect) {
1635 int old_height;
1637 /* "width" and "height" are used as coordinates here,
1638 * and run from [0...width-1] and [0...height-1] respectively.
1640 width--;
1641 height--;
1642 old_height = height;
1644 for (; width >= 0; width--)
1645 for (height = old_height; height >= 0; height--)
1646 XPutPixel(panel->magnifyGlass->image, xb + width, yb + height,
1647 XGetPixel(panel->magnifyGlass->dirtyRect, width, height));
1648 XDestroyImage(panel->magnifyGlass->dirtyRect);
1649 panel->magnifyGlass->dirtyRect = NULL;
1652 return;
1656 static Pixmap
1657 magnifyCreatePixmap(WMColorPanel *panel)
1659 W_Screen *scr = WMWidgetScreen(panel->win);
1660 int u, v;
1661 #ifndef SHAPE
1662 Pixmap pixmap;
1663 #endif
1664 unsigned long color;
1666 if (!panel->magnifyGlass->image)
1667 return None;
1669 if (!panel->magnifyGlass->magPix)
1670 return None;
1673 * Copy an area of only 5x5 pixels from the center of the image.
1675 for (u = 0; u < 5; u++) {
1676 for (v = 0; v < 5; v++) {
1677 color = XGetPixel(panel->magnifyGlass->image, u + 9, v + 9);
1679 XSetForeground(scr->display, scr->copyGC, color);
1681 if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
1682 panel->magnifyGlass->color = ulongToRColor(scr, color);
1684 /* The center square must eventually be centered around the
1685 * hotspot. The image needs shifting to achieve this. The amount of
1686 * shifting is (Cursor_mask_width/2 - 2 * square_size) = 11-10 = 1
1687 * _ _ _ _ _
1688 * |_|_|_|_|_|
1689 * ^------- center of center square == Cursor_x_hot
1691 XFillRectangle(scr->display, panel->magnifyGlass->magPix,
1692 scr->copyGC,
1693 u * 5 + (u == 0 ? 0 : -1), v * 5 + (v == 0 ? 0 : -1),
1694 (u == 0 ? 4 : 5), (v == 0 ? 4 : 5));
1698 #ifdef SHAPE
1699 return panel->magnifyGlass->magPix;
1700 #else
1701 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width,
1702 Cursor_mask_height, scr->depth);
1703 if (!pixmap)
1704 return None;
1706 XPutImage(scr->display, pixmap, scr->copyGC, panel->magnifyGlass->image,
1707 0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
1709 /* Copy the magnified pixmap, with the clip mask, to background pixmap */
1710 XCopyArea(scr->display, panel->magnifyGlass->magPix, pixmap,
1711 scr->clipGC, 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
1712 /* (2,2) puts center pixel on center of glass */
1714 return pixmap;
1715 #endif
1720 static WMView*
1721 magnifyCreateView(W_ColorPanel *panel)
1723 W_Screen *scr = WMWidgetScreen(panel->win);
1724 WMView *magView;
1726 magView = W_CreateTopView(scr);
1727 if (!magView)
1728 return NULL;
1730 magView->self = panel->win;
1731 magView->flags.topLevel = 1;
1732 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1733 magView->attribs.override_redirect = True;
1734 magView->attribs.save_under = True;
1736 W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
1738 W_RealizeView(magView);
1740 return magView;
1744 static Cursor
1745 magnifyGrabPointer(W_ColorPanel *panel)
1747 W_Screen *scr = WMWidgetScreen(panel->win);
1748 Pixmap magPixmap, magPixmap2;
1749 Cursor magCursor;
1750 XColor fgColor = {0, 0,0,0, DoRed|DoGreen|DoBlue};
1751 XColor bgColor = {0, 0xbf00, 0xa000, 0x5000, DoRed|DoGreen|DoBlue};
1753 /* Cursor creation stuff */
1754 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1755 (char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
1756 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1757 (char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
1759 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1760 &fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
1762 XFreePixmap(scr->display, magPixmap);
1763 XFreePixmap(scr->display, magPixmap2);
1765 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1767 /* Set up Pointer */
1768 XGrabPointer (scr->display, panel->magnifyGlass->view->window, True,
1769 PointerMotionMask | ButtonPressMask,
1770 GrabModeAsync, GrabModeAsync,
1771 scr->rootWin, magCursor, CurrentTime);
1773 return magCursor;
1777 static WMPoint
1778 magnifyInitialize(W_ColorPanel *panel)
1780 W_Screen *scr = WMWidgetScreen(panel->win);
1781 int x, y, u, v;
1782 unsigned int mask;
1783 Pixmap pixmap, clip_mask;
1784 WMPoint point;
1785 Window root_return, child_return;
1787 clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1788 (char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1789 1, 0, 1);
1790 panel->magnifyGlass->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
1791 5*5 -1, 5*5 -1, scr->depth);
1793 XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return,
1794 &x, &y, &u, &v, &mask);
1796 panel->magnifyGlass->image = NULL;
1798 /* Clipmask to make magnified view-contents circular */
1799 #ifdef SHAPE
1800 XShapeCombineMask(scr->display, WMViewXID(panel->magnifyGlass->view),
1801 ShapeBounding, 0, 0, clip_mask, ShapeSet);
1802 #else
1803 /* Clip circle in glass cursor */
1804 XSetClipMask(scr->display, scr->clipGC, clip_mask);
1805 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1806 #endif
1808 XFreePixmap(scr->display, clip_mask);
1810 /* Draw initial magnifying glass contents */
1811 magnifyGetImageStored(panel, x, y, x, y);
1813 pixmap = magnifyCreatePixmap(panel);
1814 XSetWindowBackgroundPixmap(scr->display,
1815 WMViewXID(panel->magnifyGlass->view),
1816 pixmap);
1817 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1818 XFlush(scr->display);
1820 #ifndef SHAPE
1821 XFreePixmap(scr->display, pixmap);
1822 #endif
1824 point.x = x;
1825 point.y = y;
1827 return point;
1831 static void
1832 magnifyPutCursor(WMWidget *w, void *data)
1834 W_ColorPanel *panel = (W_ColorPanel*)(data);
1835 W_Screen *scr = WMWidgetScreen(panel->win);
1836 Cursor magCursor;
1837 Pixmap pixmap;
1838 XEvent event;
1839 WMPoint initialPosition;
1841 /* Destroy wheelBackImg, so it'll update properly */
1842 if (panel->selectionBackImg) {
1843 XFreePixmap(WMWidgetScreen(panel->win)->display,
1844 panel->selectionBackImg);
1845 panel->selectionBackImg = None;
1848 /* Create magnifying glass */
1849 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1850 panel->magnifyGlass->view = magnifyCreateView(panel);
1851 if (!panel->magnifyGlass->view)
1852 return;
1854 initialPosition = magnifyInitialize(panel);
1855 panel->magnifyGlass->x = initialPosition.x;
1856 panel->magnifyGlass->y = initialPosition.y;
1858 W_MoveView(panel->magnifyGlass->view,
1859 panel->magnifyGlass->x - Cursor_x_hot,
1860 panel->magnifyGlass->y - Cursor_y_hot);
1861 W_MapView(panel->magnifyGlass->view);
1863 magCursor = magnifyGrabPointer(panel);
1865 while (panel->magnifyGlass->image)
1867 WMNextEvent(scr->display, &event);
1869 /* Pack motion events */
1870 while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
1873 switch (event.type)
1875 case ButtonPress:
1876 XDestroyImage(panel->magnifyGlass->image);
1877 panel->magnifyGlass->image = NULL;
1879 if (event.xbutton.button == Button1) {
1880 panel->color.rgb = panel->magnifyGlass->color;
1881 panel->color.set = cpRGB;
1882 updateSwatch(panel, panel->color);
1884 switch (panel->mode) {
1885 case WMWheelModeColorPanel:
1886 wheelInit(panel);
1887 wheelRender(panel);
1888 wheelPaint(panel);
1889 break;
1890 case WMGrayModeColorPanel:
1891 grayInit(panel);
1892 break;
1893 case WMRGBModeColorPanel:
1894 rgbInit(panel);
1895 break;
1896 case WMCMYKModeColorPanel:
1897 cmykInit(panel);
1898 break;
1899 case WMHSBModeColorPanel:
1900 hsbInit(panel);
1901 break;
1902 default:
1903 break;
1905 panel->lastChanged = panel->mode;
1907 WMSetButtonSelected(panel->magnifyBtn, False);
1908 break;
1910 case MotionNotify:
1911 while (XPending(event.xmotion.display)) {
1912 XEvent ev;
1913 XPeekEvent(event.xmotion.display, &ev);
1914 if (ev.type == MotionNotify)
1915 XNextEvent(event.xmotion.display, &event);
1916 else
1917 break;
1920 /* Get a "dirty rectangle" */
1921 magnifyGetImageStored( panel,
1922 panel->magnifyGlass->x, panel->magnifyGlass->y,
1923 event.xmotion.x_root, event.xmotion.y_root);
1925 /* Update coordinates */
1926 panel->magnifyGlass->x = event.xmotion.x_root;
1927 panel->magnifyGlass->y = event.xmotion.y_root;
1929 /* Move view */
1930 W_MoveView(panel->magnifyGlass->view,
1931 panel->magnifyGlass->x - Cursor_x_hot,
1932 panel->magnifyGlass->y - Cursor_y_hot);
1934 /* Put new image (with magn.) in view */
1935 pixmap = magnifyCreatePixmap(panel);
1936 if (pixmap != None) {
1937 /* Change the window background */
1938 XSetWindowBackgroundPixmap(scr->display,
1939 WMViewXID(panel->magnifyGlass->view), pixmap);
1940 /* Force an Expose (handled by X) */
1941 XClearWindow(scr->display,
1942 WMViewXID(panel->magnifyGlass->view));
1943 /* Synchronize the event queue, so the Expose is handled NOW */
1944 XFlush(scr->display);
1945 #ifndef SHAPE
1946 XFreePixmap(scr->display, pixmap);
1947 #endif
1949 break;
1951 /* Try XQueryPointer for this !!! It returns windows that the pointer
1952 * is over. Note: We found this solving the invisible donkey cap bug
1954 #if 0 /* As it is impossible to make this work in all cases,
1955 * we consider it confusing. Therefore we disabled it.
1957 case FocusOut: /* fall through */
1958 case FocusIn:
1960 * Color Panel window (panel->win) lost or received focus.
1961 * We need to update the pixmap in the magnifying glass.
1963 * BUG Doesn't work with focus switches between two windows
1964 * if none of them is the color panel.
1966 XUngrabPointer(scr->display, CurrentTime);
1967 W_UnmapView(panel->magnifyGlass->view);
1969 magnifyInitialize(panel);
1971 W_MapView(panel->magnifyGlass->view);
1972 XGrabPointer (scr->display, panel->magnifyGlass->view->window,
1973 True, PointerMotionMask | ButtonPressMask,
1974 GrabModeAsync, GrabModeAsync,
1975 scr->rootWin, magCursor, CurrentTime);
1976 break;
1977 #endif
1978 default:
1979 WMHandleEvent(&event);
1980 break;
1981 } /* of switch */
1984 XUngrabPointer(scr->display, CurrentTime);
1985 XFreeCursor(scr->display, magCursor);
1987 XFreePixmap(scr->display, panel->magnifyGlass->magPix);
1988 panel->magnifyGlass->magPix = None;
1990 W_UnmapView(panel->magnifyGlass->view);
1991 W_DestroyView(panel->magnifyGlass->view);
1992 panel->magnifyGlass->view = NULL;
1994 wfree(panel->magnifyGlass);
1999 /****************** ColorWheel Functions ************************/
2001 static wheelMatrix*
2002 wheelCreateMatrix(unsigned int width, unsigned int height)
2004 wheelMatrix *matrix = NULL;
2005 int i;
2007 assert((width > 0) && (height > 0));
2009 matrix = wmalloc(sizeof(wheelMatrix));
2010 memset(matrix, 0, sizeof(wheelMatrix));
2011 matrix->width = width;
2012 matrix->height = height;
2014 for (i = 0; i < 3; i++) {
2015 matrix->data[i] = wmalloc(width*height*sizeof(unsigned char));
2018 return matrix;
2022 static void
2023 wheelDestroyMatrix(wheelMatrix *matrix)
2025 int i;
2027 if (!matrix)
2028 return;
2030 for (i = 0; i < 3; i++) {
2031 if (matrix->data[i])
2032 wfree(matrix->data[i]);
2034 wfree(matrix);
2038 static void
2039 wheelInitMatrix(W_ColorPanel *panel)
2041 int i;
2042 int x,y;
2043 unsigned char *rp, *gp, *bp;
2044 CPColor cpColor;
2045 long ofs[4];
2046 int xcor, ycor;
2047 unsigned short sat;
2048 int dhue[4];
2049 const int cw_halfsize = (colorWheelSize + 4)/2,
2050 cw_sqsize = (colorWheelSize +4) * (colorWheelSize +4),
2051 uchar_shift = getShift(sizeof(unsigned char));
2053 if (!panel->wheelMtrx)
2054 return;
2056 cpColor.hsv.value = 255;
2057 cpColor.set = cpHSV;
2059 ofs[0] = -1;
2060 ofs[1] = -(colorWheelSize + 4);
2062 /* offsets are counterclockwise (in triangles).
2064 * ofs[0] ---->
2065 * _______________________________________
2066 * [1] |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| o
2067 * s |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| f
2068 * f |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| s
2069 * o | | | | | | | | | | | | | | | | | | | | | [3]
2071 * <---- ofs[2]
2072 * ____
2073 * |\ /| <-- triangles
2074 * | \/ |
2075 * | /\ |
2076 * |/__\|
2079 for (y = 0; y < cw_halfsize; y++) {
2080 for (x = y; x < (colorWheelSize+4-y); x++) {
2081 /* (xcor, ycor) is (x,y) relative to center of matrix */
2082 xcor = 2 * x - 4 - colorWheelSize;
2083 ycor = 2 * y - 4 - colorWheelSize;
2085 /* RColor.saturation is unsigned char and will wrap after 255 */
2086 sat = rint(255.0 * sqrt(xcor*xcor + ycor*ycor) / colorWheelSize);
2088 cpColor.hsv.saturation = (unsigned char)sat;
2090 ofs[0]++; /* top quarter of matrix*/
2091 ofs[1] += colorWheelSize + 4; /* left quarter */
2092 ofs[2] = cw_sqsize - 1 - ofs[0]; /* bottom quarter */
2093 ofs[3] = cw_sqsize - 1 - ofs[1]; /* right quarter */
2095 if (sat < 256) {
2096 if (xcor != 0)
2097 dhue[0] = rint(atan((double)ycor / (double)xcor) *
2098 (180.0 / M_PI)) + (xcor < 0 ? 180.0 : 0.0);
2099 else
2100 dhue[0] = 270;
2102 dhue[0] = 360 - dhue[0]; /* Reverse direction of ColorWheel */
2103 dhue[1] = 270 - dhue[0] + (dhue[0] > 270 ? 360 : 0);
2104 dhue[2] = dhue[0] - 180 + (dhue[0] < 180 ? 360 : 0);
2105 dhue[3] = 90 - dhue[0] + (dhue[0] > 90 ? 360 : 0);
2107 for (i = 0; i < 4; i++) {
2108 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
2109 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
2110 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
2112 cpColor.hsv.hue = dhue[i];
2113 convertCPColor(&cpColor);
2115 *rp = (unsigned char)(cpColor.rgb.red);
2116 *gp = (unsigned char)(cpColor.rgb.green);
2117 *bp = (unsigned char)(cpColor.rgb.blue);
2120 else {
2121 for (i = 0; i < 4; i++) {
2122 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
2123 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
2124 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
2126 *rp = (unsigned char)0;
2127 *gp = (unsigned char)0;
2128 *bp = (unsigned char)0;
2133 ofs[0] += 2*y+1;
2134 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2*y);
2139 static void
2140 wheelCalculateValues(W_ColorPanel *panel, int maxvalue)
2142 unsigned int i;
2143 unsigned int v;
2145 for (i = 0; i < 256; i++) {
2146 /* We divide by 128 in advance, and check whether that number divides
2147 * by 2 properly. If not, we add one to round the number correctly
2149 v = (i*maxvalue) >> 7;
2150 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) +(v & 0x01));
2155 static void
2156 wheelRender(W_ColorPanel *panel)
2158 W_Screen *scr = WMWidgetScreen(panel->win);
2159 int x,y;
2160 RImage *image;
2161 unsigned char *ptr;
2162 RColor gray;
2163 unsigned long ofs = 0;
2164 /*unsigned char shift = getShift(sizeof(unsigned char));*/
2166 image = RCreateImage(colorWheelSize+4, colorWheelSize+4, True);
2167 if (!image) {
2168 wwarning(_("Color Panel: Could not allocate memory"));
2169 return;
2172 ptr = image->data;
2174 /* TODO Make this transparent istead of gray */
2175 gray.red = gray.blue = 0xae; gray.green = 0xaa;
2177 for (y = 0; y < colorWheelSize+4; y++) {
2178 for (x = 0; x < colorWheelSize+4; x++) {
2179 if (wheelInsideColorWheel(panel, ofs)) {
2180 *(ptr++) = (unsigned char)(panel->wheelMtrx->values[
2181 panel->wheelMtrx->data[0][ofs] ]);
2182 *(ptr++) = (unsigned char)(panel->wheelMtrx->values[
2183 panel->wheelMtrx->data[1][ofs] ]);
2184 *(ptr++) = (unsigned char)(panel->wheelMtrx->values[
2185 panel->wheelMtrx->data[2][ofs] ]);
2186 *(ptr++) = 0;
2188 else {
2189 *(ptr++) = (unsigned char)(gray.red);
2190 *(ptr++) = (unsigned char)(gray.green);
2191 *(ptr++) = (unsigned char)(gray.blue);
2192 *(ptr++) = 255;
2194 ofs++;
2198 if (panel->wheelImg)
2199 XFreePixmap(scr->display, panel->wheelImg);
2201 RConvertImage(scr->rcontext, image, &panel->wheelImg);
2202 RReleaseImage(image);
2204 /* Check if backimage exists. If it doesn't, allocate and fill it */
2205 if (!panel->selectionBackImg) {
2206 panel->selectionBackImg = XCreatePixmap(scr->display,
2207 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
2208 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2209 scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0);
2210 /* -2 is hot spot correction */
2215 static Bool
2216 wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs)
2218 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
2219 (panel->wheelMtrx->data[1][ofs] != 0) &&
2220 (panel->wheelMtrx->data[2][ofs] != 0));
2224 static void
2225 wheelPaint (W_ColorPanel *panel)
2227 W_Screen *scr = WMWidgetScreen(panel->win);
2229 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
2230 scr->copyGC, 0, 0, colorWheelSize+4, colorWheelSize+4, 0, 0);
2232 /* Draw selection image */
2233 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2234 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2238 static void
2239 wheelHandleEvents(XEvent *event, void *data)
2241 W_ColorPanel *panel = (W_ColorPanel*)data;
2243 switch (event->type) {
2244 case Expose:
2245 if (event->xexpose.count != 0) /* TODO Improve */
2246 break;
2247 wheelPaint(panel);
2248 break;
2253 static void
2254 wheelHandleActionEvents(XEvent *event, void *data)
2256 W_ColorPanel *panel = (W_ColorPanel*)data;
2258 switch (event->type) {
2259 case ButtonPress:
2260 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) ==
2261 COLORWHEEL_PART) {
2263 panel->lastChanged = WMWheelModeColorPanel;
2264 panel->flags.dragging = 1;
2266 wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
2268 break;
2270 case ButtonRelease:
2271 panel->flags.dragging = 0;
2272 if (!panel->flags.continuous) {
2273 if (panel->action)
2274 (*panel->action)(panel, panel->clientData);
2276 break;
2278 case MotionNotify:
2279 if (panel->flags.dragging) {
2280 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) ==
2281 COLORWHEEL_PART) {
2282 wheelPositionSelection(panel, event->xmotion.x,
2283 event->xmotion.y);
2285 else
2286 wheelPositionSelectionOutBounds(panel, event->xmotion.x,
2287 event->xmotion.y);
2289 break;
2294 static int
2295 getPickerPart(W_ColorPanel *panel, int x, int y)
2297 int lx, ly;
2298 unsigned long ofs;
2300 lx = x;
2301 ly = y;
2303 if (panel->mode == WMWheelModeColorPanel) {
2304 if ((lx >= 2) && (lx <= 2+colorWheelSize) && (ly >= 2) &&
2305 (ly <= 2+colorWheelSize)) {
2307 ofs = ly*panel->wheelMtrx->width+lx;
2309 if (wheelInsideColorWheel(panel, ofs))
2310 return COLORWHEEL_PART;
2314 if (panel->mode == WMCustomPaletteModeColorPanel) {
2315 if ((lx >= 2) && (lx < customPaletteWidth-2) && (ly >= 2) &&
2316 (ly < customPaletteHeight-2)) {
2317 return CUSTOMPALETTE_PART;
2321 return 0;
2325 static void
2326 wheelBrightnessSliderCallback(WMWidget *w, void *data)
2328 int value;
2330 W_ColorPanel *panel = (W_ColorPanel*)data;
2332 value = 255-WMGetSliderValue(panel->wheelBrightnessS);
2334 wheelCalculateValues(panel, value);
2336 if (panel->color.set == cpRGB) {
2337 convertCPColor(&panel->color);
2338 panel->color.set = cpHSV;
2341 panel->color.hsv.value = value;
2343 wheelRender(panel);
2344 wheelPaint(panel);
2345 wheelUpdateSelection(panel);
2349 static void
2350 wheelUpdateSelection(W_ColorPanel *panel)
2352 W_Screen *scr = WMWidgetScreen(panel->win);
2354 updateSwatch(panel, panel->color);
2355 panel->lastChanged = WMWheelModeColorPanel;
2357 /* Redraw color selector (and make a backup of the part it will cover) */
2358 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2359 scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0);
2360 /* "-2" is correction for hotspot location */
2361 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2362 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2363 /* see above */
2367 static void
2368 wheelUndrawSelection(W_ColorPanel *panel)
2370 W_Screen *scr = WMWidgetScreen(panel->win);
2372 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
2373 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2374 /* see above */
2377 static void
2378 wheelPositionSelection(W_ColorPanel *panel, int x, int y)
2380 unsigned long ofs = (y * panel->wheelMtrx->width)+ x;
2382 panel->color.rgb.red = panel->wheelMtrx->values[
2383 panel->wheelMtrx->data[0][ofs] ];
2385 panel->color.rgb.green = panel->wheelMtrx->values[
2386 panel->wheelMtrx->data[1][ofs] ];
2388 panel->color.rgb.blue = panel->wheelMtrx->values[
2389 panel->wheelMtrx->data[2][ofs] ];
2390 panel->color.set = cpRGB;
2392 wheelUndrawSelection(panel);
2394 panel->colx = x;
2395 panel->coly = y;
2397 wheelUpdateSelection(panel);
2398 wheelUpdateBrightnessGradientFromLocation(panel);
2401 static void
2402 wheelPositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
2404 int hue;
2405 int xcor, ycor;
2406 CPColor cpColor;
2408 xcor = x * 2 - colorWheelSize - 4;
2409 ycor = y * 2 - colorWheelSize - 4;
2411 panel->color.hsv.saturation = 255;
2412 panel->color.hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2414 if (xcor != 0)
2415 hue = rint(atan(- (double)ycor / (double)xcor) * (180.0/M_PI));
2416 else {
2417 if (ycor < 0)
2418 hue = 90;
2419 else
2420 hue = 270;
2423 if (xcor < 0)
2424 hue += 180;
2426 if ((xcor > 0) && (ycor > 0))
2427 hue += 360;
2429 panel->color.hsv.hue = hue;
2430 panel->color.set = cpHSV;
2431 convertCPColor(&panel->color);
2433 wheelUndrawSelection(panel);
2435 panel->colx = 2 + rint((colorWheelSize * (1.0 +
2436 cos( panel->color.hsv.hue * (M_PI/180.0) ))) / 2.0);
2437 /* "+2" because of "colorWheelSize + 4" */
2438 panel->coly = 2 + rint((colorWheelSize * (1.0 +
2439 sin(- panel->color.hsv.hue * (M_PI/180.0) ))) / 2.0);
2441 wheelUpdateSelection(panel);
2442 cpColor = panel->color;
2443 wheelUpdateBrightnessGradient(panel, cpColor);
2446 static void
2447 wheelUpdateBrightnessGradientFromLocation(W_ColorPanel *panel)
2449 CPColor from;
2450 unsigned long ofs;
2452 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2454 from.rgb.red = panel->wheelMtrx->data[0][ofs];
2455 from.rgb.green = panel->wheelMtrx->data[1][ofs];
2456 from.rgb.blue = panel->wheelMtrx->data[2][ofs];
2457 from.set = cpRGB;
2459 wheelUpdateBrightnessGradient(panel, from);
2462 static void
2463 wheelUpdateBrightnessGradient(W_ColorPanel *panel, CPColor topColor)
2465 RColor to;
2466 RImage *sliderImg;
2467 WMPixmap *sliderPxmp;
2469 to.red = to.green = to.blue = 0;
2471 if (topColor.set == cpHSV)
2472 convertCPColor(&topColor);
2474 sliderImg = RRenderGradient(16, 153, &(topColor.rgb), &to, RGRD_VERTICAL);
2475 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win),
2476 sliderImg, 0);
2477 RReleaseImage(sliderImg);
2478 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
2479 WMReleasePixmap(sliderPxmp);
2482 /****************** Grayscale Panel Functions ***************/
2484 static void
2485 grayBrightnessSliderCallback(WMWidget *w, void *data)
2487 CPColor cpColor;
2488 int value;
2489 char tmp[4];
2490 W_ColorPanel *panel = (W_ColorPanel*)data;
2492 value = WMGetSliderValue(panel->grayBrightnessS);
2494 sprintf(tmp, "%d", value);
2496 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2497 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint(2.55*value);
2498 cpColor.set = cpRGB;
2500 updateSwatch(panel, cpColor);
2501 panel->lastChanged = WMGrayModeColorPanel;
2504 static void
2505 grayPresetButtonCallback(WMWidget *w, void *data)
2507 CPColor cpColor;
2508 char tmp[4];
2509 int value;
2510 int i=0;
2511 W_ColorPanel *panel = (W_ColorPanel*)data;
2513 while (i < 7) {
2514 if (w == panel->grayPresetBtn[i])
2515 break;
2516 i++;
2519 value = rint((100.0*i)/6.0);
2520 sprintf(tmp, "%d", value);
2522 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2523 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue =
2524 rint((255.0*i)/6.0);
2525 cpColor.set = cpRGB;
2527 WMSetSliderValue(panel->grayBrightnessS, rint((100.0*i)/6.0));
2529 updateSwatch(panel, cpColor);
2530 panel->lastChanged = WMGrayModeColorPanel;
2533 static void
2534 grayBrightnessTextFieldCallback(void *observerData,
2535 WMNotification *notification)
2537 CPColor cpColor;
2538 char tmp[4];
2539 int value;
2540 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2542 value = atoi(WMGetTextFieldText(panel->grayBrightnessT));
2543 if (value > 100)
2544 value = 100;
2545 if (value < 0)
2546 value = 0;
2548 sprintf(tmp, "%d", value);
2549 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2550 WMSetSliderValue(panel->grayBrightnessS, value);
2552 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue =
2553 rint((255.0*value)/100.0);
2554 cpColor.set = cpRGB;
2556 updateSwatch(panel, cpColor);
2557 panel->lastChanged = WMGrayModeColorPanel;
2560 /******************* RGB Panel Functions *****************/
2562 static void
2563 rgbSliderCallback(WMWidget *w, void *data)
2565 CPColor cpColor;
2566 int value[3];
2567 char tmp[4];
2568 W_ColorPanel *panel = (W_ColorPanel*)data;
2570 value[0] = WMGetSliderValue(panel->rgbRedS);
2571 value[1] = WMGetSliderValue(panel->rgbGreenS);
2572 value[2] = WMGetSliderValue(panel->rgbBlueS);
2574 sprintf(tmp, "%d", value[0]);
2575 WMSetTextFieldText(panel->rgbRedT, tmp);
2576 sprintf(tmp, "%d", value[1]);
2577 WMSetTextFieldText(panel->rgbGreenT, tmp);
2578 sprintf(tmp, "%d", value[2]);
2579 WMSetTextFieldText(panel->rgbBlueT, tmp);
2581 cpColor.rgb.red = value[0];
2582 cpColor.rgb.green = value[1];
2583 cpColor.rgb.blue = value[2];
2584 cpColor.set = cpRGB;
2586 updateSwatch(panel, cpColor);
2587 panel->lastChanged = WMRGBModeColorPanel;
2590 static void
2591 rgbTextFieldCallback(void *observerData, WMNotification *notification)
2593 CPColor cpColor;
2594 int value[3];
2595 char tmp[4];
2596 int n;
2597 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2599 value[0] = atoi(WMGetTextFieldText(panel->rgbRedT));
2600 value[1] = atoi(WMGetTextFieldText(panel->rgbGreenT));
2601 value[2] = atoi(WMGetTextFieldText(panel->rgbBlueT));
2603 for (n=0; n < 3; n++) {
2604 if (value[n] > 255)
2605 value[n] = 255;
2606 if (value[n] < 0)
2607 value[n] = 0;
2610 sprintf(tmp, "%d", value[0]);
2611 WMSetTextFieldText(panel->rgbRedT, tmp);
2612 sprintf(tmp, "%d", value[1]);
2613 WMSetTextFieldText(panel->rgbGreenT, tmp);
2614 sprintf(tmp, "%d", value[2]);
2615 WMSetTextFieldText(panel->rgbBlueT, tmp);
2617 WMSetSliderValue(panel->rgbRedS, value[0]);
2618 WMSetSliderValue(panel->rgbGreenS, value[1]);
2619 WMSetSliderValue(panel->rgbBlueS, value[2]);
2621 cpColor.rgb.red = value[0];
2622 cpColor.rgb.green = value[1];
2623 cpColor.rgb.blue = value[2];
2624 cpColor.set = cpRGB;
2626 updateSwatch(panel, cpColor);
2627 panel->lastChanged = WMRGBModeColorPanel;
2631 /******************* CMYK Panel Functions *****************/
2633 static void
2634 cmykSliderCallback(WMWidget *w, void *data)
2636 CPColor cpColor;
2637 int value[4];
2638 char tmp[4];
2639 W_ColorPanel *panel = (W_ColorPanel*)data;
2640 double scale;
2642 value[0] = WMGetSliderValue(panel->cmykCyanS);
2643 value[1] = WMGetSliderValue(panel->cmykMagentaS);
2644 value[2] = WMGetSliderValue(panel->cmykYellowS);
2645 value[3] = WMGetSliderValue(panel->cmykBlackS);
2647 sprintf(tmp, "%d", value[0]);
2648 WMSetTextFieldText(panel->cmykCyanT, tmp);
2649 sprintf(tmp, "%d", value[1]);
2650 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2651 sprintf(tmp, "%d", value[2]);
2652 WMSetTextFieldText(panel->cmykYellowT, tmp);
2653 sprintf(tmp, "%d", value[3]);
2654 WMSetTextFieldText(panel->cmykBlackT, tmp);
2656 scale = 2.55 * (1.0 - (value[3] / 100.0));
2657 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2658 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2659 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2660 cpColor.set = cpRGB;
2662 updateSwatch(panel, cpColor);
2663 panel->lastChanged = WMCMYKModeColorPanel;
2666 static void
2667 cmykTextFieldCallback(void *observerData, WMNotification *notification)
2669 CPColor cpColor;
2670 int value[4];
2671 char tmp[4];
2672 int n;
2673 double scale;
2674 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2676 value[0] = atoi(WMGetTextFieldText(panel->cmykCyanT));
2677 value[1] = atoi(WMGetTextFieldText(panel->cmykMagentaT));
2678 value[2] = atoi(WMGetTextFieldText(panel->cmykYellowT));
2679 value[3] = atoi(WMGetTextFieldText(panel->cmykBlackT));
2681 for (n=0; n < 4; n++) {
2682 if (value[n] > 100)
2683 value[n] = 100;
2684 if (value[n] < 0)
2685 value[n] = 0;
2688 sprintf(tmp, "%d", value[0]);
2689 WMSetTextFieldText(panel->cmykCyanT, tmp);
2691 sprintf(tmp, "%d", value[1]);
2692 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2694 sprintf(tmp, "%d", value[2]);
2695 WMSetTextFieldText(panel->cmykYellowT, tmp);
2697 sprintf(tmp, "%d", value[3]);
2698 WMSetTextFieldText(panel->cmykBlackT, tmp);
2700 WMSetSliderValue(panel->cmykCyanS, value[0]);
2701 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2702 WMSetSliderValue(panel->cmykYellowS, value[2]);
2703 WMSetSliderValue(panel->cmykBlackS, value[3]);
2705 scale = 2.55 * (1.0 - (value[3] / 100.0));
2706 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2707 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2708 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2709 cpColor.set = cpRGB;
2711 updateSwatch(panel, cpColor);
2712 panel->lastChanged = WMCMYKModeColorPanel;
2715 /********************** HSB Panel Functions ***********************/
2717 static void
2718 hsbSliderCallback(WMWidget *w, void *data)
2720 CPColor cpColor;
2721 int value[3];
2722 char tmp[4];
2723 W_ColorPanel *panel = (W_ColorPanel*)data;
2725 value[0] = WMGetSliderValue(panel->hsbHueS);
2726 value[1] = WMGetSliderValue(panel->hsbSaturationS);
2727 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
2729 sprintf(tmp, "%d", value[0]);
2730 WMSetTextFieldText(panel->hsbHueT, tmp);
2731 sprintf(tmp, "%d", value[1]);
2732 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2733 sprintf(tmp, "%d", value[2]);
2734 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2736 cpColor.hsv.hue = value[0];
2737 cpColor.hsv.saturation = value[1]*2.55;
2738 cpColor.hsv.value = value[2]*2.55;
2739 cpColor.set = cpHSV;
2741 convertCPColor(&cpColor);
2743 panel->lastChanged = WMHSBModeColorPanel;
2744 updateSwatch(panel, cpColor);
2746 if (w != panel->hsbBrightnessS)
2747 hsbUpdateBrightnessGradient(panel);
2748 if (w != panel->hsbSaturationS)
2749 hsbUpdateSaturationGradient(panel);
2750 if (w != panel->hsbHueS)
2751 hsbUpdateHueGradient(panel);
2754 static void
2755 hsbTextFieldCallback(void *observerData, WMNotification *notification)
2757 CPColor cpColor;
2758 int value[3];
2759 char tmp[4];
2760 int n;
2761 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2763 value[0] = atoi(WMGetTextFieldText(panel->hsbHueT));
2764 value[1] = atoi(WMGetTextFieldText(panel->hsbSaturationT));
2765 value[2] = atoi(WMGetTextFieldText(panel->hsbBrightnessT));
2767 if (value[0] > 359)
2768 value[0] = 359;
2769 if (value[0] < 0)
2770 value[0] = 0;
2772 for (n=1; n < 3; n++) {
2773 if (value[n] > 100)
2774 value[n] = 100;
2775 if (value[n] < 0)
2776 value[n] = 0;
2779 sprintf(tmp, "%d", value[0]);
2780 WMSetTextFieldText(panel->hsbHueT, tmp);
2781 sprintf(tmp, "%d", value[1]);
2782 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2783 sprintf(tmp, "%d", value[2]);
2784 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2786 WMSetSliderValue(panel->hsbHueS, value[0]);
2787 WMSetSliderValue(panel->hsbSaturationS, value[1]);
2788 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
2790 cpColor.hsv.hue = value[0];
2791 cpColor.hsv.saturation = value[1]*2.55;
2792 cpColor.hsv.value = value[2]*2.55;
2793 cpColor.set = cpHSV;
2795 convertCPColor(&cpColor);
2797 panel->lastChanged = WMHSBModeColorPanel;
2798 updateSwatch(panel, cpColor);
2800 hsbUpdateBrightnessGradient(panel);
2801 hsbUpdateSaturationGradient(panel);
2802 hsbUpdateHueGradient(panel);
2805 static void
2806 hsbUpdateBrightnessGradient(W_ColorPanel *panel)
2808 W_Screen *scr = WMWidgetScreen(panel->win);
2809 RColor from;
2810 CPColor to;
2811 RImage *sliderImg;
2812 WMPixmap *sliderPxmp;
2814 from.red = from.green = from.blue = 0;
2815 to.hsv = panel->color.hsv;
2816 to.hsv.value = 255;
2817 to.set = cpHSV;
2819 convertCPColor(&to);
2821 sliderImg = RRenderGradient(141, 16, &from, &(to.rgb), RGRD_HORIZONTAL);
2822 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2823 RReleaseImage(sliderImg);
2825 if (sliderPxmp)
2826 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
2827 panel->font12, 2, 0, 100, WALeft, scr->white,
2828 False, _("Brightness"), strlen(_("Brightness")));
2829 else
2830 wwarning(_("Color Panel: Could not allocate memory"));
2832 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
2833 WMReleasePixmap(sliderPxmp);
2836 static void
2837 hsbUpdateSaturationGradient(W_ColorPanel *panel)
2839 W_Screen *scr = WMWidgetScreen(panel->win);
2840 CPColor from;
2841 CPColor to;
2842 RImage *sliderImg;
2843 WMPixmap *sliderPxmp;
2845 from.hsv = panel->color.hsv;
2846 from.hsv.saturation = 0;
2847 from.set = cpHSV;
2848 convertCPColor(&from);
2850 to.hsv = panel->color.hsv;
2851 to.hsv.saturation = 255;
2852 to.set = cpHSV;
2853 convertCPColor(&to);
2855 sliderImg = RRenderGradient(141, 16, &(from.rgb), &(to.rgb),
2856 RGRD_HORIZONTAL);
2857 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2858 RReleaseImage(sliderImg);
2860 if (sliderPxmp)
2861 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2862 panel->font12, 2, 0, 100, WALeft,
2863 from.hsv.value < 128 ? scr->white : scr->black, False,
2864 _("Saturation"), strlen(_("Saturation")));
2865 else
2866 wwarning(_("Color Panel: Could not allocate memory"));
2868 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
2869 WMReleasePixmap(sliderPxmp);
2872 static void
2873 hsbUpdateHueGradient(W_ColorPanel *panel)
2875 W_Screen *scr = WMWidgetScreen(panel->win);
2876 RColor **colors = NULL;
2877 RHSVColor hsvcolor;
2878 RImage *sliderImg;
2879 WMPixmap *sliderPxmp;
2880 int i;
2882 hsvcolor = panel->color.hsv;
2884 colors = wmalloc(sizeof(RColor*)*(8));
2885 for (i=0; i<7; i++) {
2886 hsvcolor.hue = (360*i)/6;
2887 colors[i] = wmalloc(sizeof(RColor));
2888 RHSVtoRGB(&hsvcolor, colors[i]);
2890 colors[7] = NULL;
2892 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2893 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2894 RReleaseImage(sliderImg);
2896 if (sliderPxmp)
2897 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2898 panel->font12, 2, 0, 100, WALeft,
2899 hsvcolor.value < 128 ? scr->white : scr->black, False,
2900 _("Hue"), strlen(_("Hue")));
2901 else
2902 wwarning(_("Color Panel: Could not allocate memory"));
2904 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2905 WMReleasePixmap(sliderPxmp);
2907 for (i=0; i<7; i++)
2908 wfree(colors[i]);
2910 wfree(colors);
2913 /*************** Custom Palette Functions ****************/
2915 static void
2916 customRenderSpectrum(W_ColorPanel *panel)
2918 RImage *spectrum;
2919 int x,y;
2920 unsigned char *ptr;
2921 CPColor cpColor;
2923 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, False);
2925 ptr = spectrum->data;
2927 for (y = 0; y < SPECTRUM_HEIGHT; y++) {
2928 cpColor.hsv.hue = y;
2929 cpColor.hsv.saturation = 0;
2930 cpColor.hsv.value = 255;
2931 cpColor.set = cpHSV;
2933 for (x = 0; x < SPECTRUM_WIDTH; x++) {
2934 convertCPColor(&cpColor);
2936 *(ptr++) = (unsigned char)cpColor.rgb.red;
2937 *(ptr++) = (unsigned char)cpColor.rgb.green;
2938 *(ptr++) = (unsigned char)cpColor.rgb.blue;
2940 if (x < (SPECTRUM_WIDTH/2))
2941 cpColor.hsv.saturation++;
2943 if (x > (SPECTRUM_WIDTH/2))
2944 cpColor.hsv.value--;
2947 if (panel->customPaletteImg) {
2948 RReleaseImage(panel->customPaletteImg);
2949 panel->customPaletteImg = NULL;
2951 panel->customPaletteImg = spectrum;
2956 static void
2957 customSetPalette(W_ColorPanel *panel)
2959 W_Screen *scr = WMWidgetScreen(panel->win);
2960 RImage *scaledImg;
2961 Pixmap image;
2962 int item;
2964 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth,
2965 customPaletteHeight, scr->depth);
2966 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth,
2967 customPaletteHeight);
2968 RConvertImage(scr->rcontext, scaledImg, &image);
2969 RReleaseImage(scaledImg);
2971 XCopyArea(scr->display, image, panel->customPaletteContentView->window,
2972 scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2974 /* Check backimage exists. If it doesn't, allocate and fill it */
2975 if (!panel->selectionBackImg) {
2976 panel->selectionBackImg = XCreatePixmap(scr->display,
2977 panel->customPaletteContentView->window, 4, 4, scr->depth);
2980 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
2981 panel->palx-2, panel->paly-2, 4, 4, 0, 0);
2982 XCopyArea(scr->display, panel->selectionImg,
2983 panel->customPaletteContentView->window, scr->copyGC, 0 , 0, 4, 4,
2984 panel->palx-2, panel->paly-2);
2985 XFreePixmap(scr->display, image);
2987 panel->palXRatio = (double)(panel->customPaletteImg->width) /
2988 (double)(customPaletteWidth);
2989 panel->palYRatio = (double)(panel->customPaletteImg->height) /
2990 (double)(customPaletteHeight);
2992 item = WMGetPopUpButtonSelectedItem (panel->customPaletteHistoryBtn);
2996 static void
2997 customPalettePositionSelection(W_ColorPanel *panel, int x, int y)
2999 W_Screen *scr = WMWidgetScreen(panel->win);
3000 unsigned long ofs;
3003 /* undraw selection */
3004 XCopyArea(scr->display, panel->selectionBackImg,
3005 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
3006 panel->palx-2, panel->paly-2);
3008 panel->palx = x;
3009 panel->paly = y;
3011 ofs = (rint(x * panel->palXRatio) + rint(y * panel->palYRatio) *
3012 panel->customPaletteImg->width) * 3;
3014 panel->color.rgb.red = panel->customPaletteImg->data[ofs];
3015 panel->color.rgb.green = panel->customPaletteImg->data[ofs+1];
3016 panel->color.rgb.blue = panel->customPaletteImg->data[ofs+2];
3017 panel->color.set = cpRGB;
3019 updateSwatch(panel, panel->color);
3020 panel->lastChanged = WMCustomPaletteModeColorPanel;
3022 /* Redraw color selector (and make a backup of the part it will cover) */
3023 XCopyArea(scr->display, panel->customPaletteContentView->window,
3024 panel->selectionBackImg, scr->copyGC, panel->palx-2, panel->paly-2,
3025 4, 4, 0, 0); /* "-2" is correction for hotspot location */
3026 XCopyArea(scr->display, panel->selectionImg,
3027 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
3028 panel->palx-2, panel->paly-2); /* see above */
3032 static void
3033 customPalettePositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
3035 if (x < 2)
3036 x = 2;
3037 if (y < 2)
3038 y = 2;
3039 if (x >= customPaletteWidth)
3040 x = customPaletteWidth -2;
3041 if (y >= customPaletteHeight)
3042 y = customPaletteHeight -2;
3044 customPalettePositionSelection(panel, x, y);
3048 static void
3049 customPaletteHandleEvents(XEvent *event, void *data)
3051 W_ColorPanel *panel = (W_ColorPanel*)data;
3053 switch (event->type) {
3054 case Expose:
3055 if (event->xexpose.count != 0) /* TODO Improve. */
3056 break;
3057 customSetPalette(panel);
3058 break;
3062 static void
3063 customPaletteHandleActionEvents(XEvent *event, void *data)
3065 W_ColorPanel *panel = (W_ColorPanel*)data;
3066 int x, y;
3068 switch (event->type) {
3069 case ButtonPress:
3070 x = event->xbutton.x;
3071 y = event->xbutton.y;
3073 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
3074 panel->flags.dragging = 1;
3075 customPalettePositionSelection(panel, x, y);
3077 break;
3079 case ButtonRelease:
3080 panel->flags.dragging = 0;
3081 if (!panel->flags.continuous) {
3082 if (panel->action)
3083 (*panel->action)(panel, panel->clientData);
3085 break;
3087 case MotionNotify:
3088 x = event->xmotion.x;
3089 y = event->xmotion.y;
3091 if (panel->flags.dragging) {
3092 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
3093 customPalettePositionSelection(panel, x, y);
3095 else
3096 customPalettePositionSelectionOutBounds(panel, x, y);
3098 break;
3103 static void
3104 customPaletteMenuCallback(WMWidget *w, void *data)
3106 W_ColorPanel *panel = (W_ColorPanel*)data;
3107 int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
3109 switch (item) {
3110 case CPmenuNewFromFile:
3111 customPaletteMenuNewFromFile(panel);
3112 break;
3113 case CPmenuRename:
3114 customPaletteMenuRename(panel);
3115 break;
3116 case CPmenuRemove:
3117 customPaletteMenuRemove(panel);
3118 break;
3119 case CPmenuCopy:
3120 break;
3121 case CPmenuNewFromClipboard:
3122 break;
3127 static void
3128 customPaletteMenuNewFromFile(W_ColorPanel *panel)
3130 W_Screen *scr = WMWidgetScreen(panel->win);
3131 WMOpenPanel *browseP;
3132 char *filepath;
3133 char *filename = NULL;
3134 char *spath;
3135 char *tmp;
3136 int i;
3137 RImage *tmpImg = NULL;
3139 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir,"\0") == 0))
3140 spath = wexpandpath(wgethomedir());
3141 else
3142 spath = wexpandpath(panel->lastBrowseDir);
3144 browseP = WMGetOpenPanel(scr);
3145 WMSetFilePanelCanChooseDirectories(browseP, 0);
3146 WMSetFilePanelCanChooseFiles(browseP, 1);
3148 /* Get a filename */
3149 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
3150 _("Open Palette"), RSupportedFileFormats()) ) {
3151 filepath = WMGetFilePanelFileName(browseP);
3153 /* Get seperation position between path and filename */
3154 i = strrchr(filepath, '/') - filepath + 1;
3155 if (i > strlen(filepath))
3156 i = strlen(filepath);
3158 /* Store last browsed path */
3159 if (panel->lastBrowseDir)
3160 wfree(panel->lastBrowseDir);
3161 panel->lastBrowseDir = wmalloc((i+1)*sizeof(char));
3162 strncpy(panel->lastBrowseDir, filepath, i);
3163 panel->lastBrowseDir[i] = '\0';
3165 /* Get filename from path */
3166 filename = wstrdup(filepath + i);
3168 /* Check for duplicate files, and rename it if there are any */
3169 tmp = wstrconcat(panel->configurationPath, filename);
3170 while (access (tmp, F_OK) == 0) {
3171 char *newName;
3173 wfree(tmp);
3175 newName = generateNewFilename(filename);
3176 wfree(filename);
3177 filename = newName;
3179 tmp = wstrconcat(panel->configurationPath, filename);
3181 wfree(tmp);
3183 /* Copy image to $(gnustepdir)/Library/Colors/ &
3184 * Add filename to history menu */
3185 if (fetchFile (panel->configurationPath, filepath, filename) == 0) {
3187 /* filepath is a "local" path now the file has been copied */
3188 wfree(filepath);
3189 filepath = wstrconcat(panel->configurationPath, filename);
3191 /* load the image & add menu entries */
3192 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
3193 if (tmpImg) {
3194 if (panel->customPaletteImg)
3195 RReleaseImage(panel->customPaletteImg);
3196 panel->customPaletteImg = tmpImg;
3198 customSetPalette(panel);
3199 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
3201 panel->currentPalette = WMGetPopUpButtonNumberOfItems(
3202 panel->customPaletteHistoryBtn)-1;
3204 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3205 panel->currentPalette);
3207 } else {
3208 tmp = wstrconcat(panel->configurationPath, filename);
3210 i = remove(tmp); /* Delete the file, it doesn't belong here */
3211 WMRunAlertPanel(scr, panel->win, _("File Error"),
3212 _("Invalid file format !"), _("OK"), NULL, NULL);
3213 if (i != 0) {
3214 wsyserror(_("can't remove file %s"), tmp);
3215 WMRunAlertPanel(scr, panel->win, _("File Error"),
3216 _("Couldn't remove file from Configuration Directory !"),
3217 _("OK"), NULL, NULL);
3219 wfree(tmp);
3221 wfree(filepath);
3222 wfree(filename);
3224 WMFreeFilePanel(browseP);
3226 wfree(spath);
3230 static void
3231 customPaletteMenuRename(W_ColorPanel *panel)
3233 W_Screen *scr = WMWidgetScreen(panel->win);
3234 char *toName = NULL;
3235 char *fromName;
3236 char *toPath, *fromPath;
3237 int item;
3238 int index;
3240 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3241 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
3243 toName = WMRunInputPanel(scr, panel->win, _("Rename"), _("Rename palette to:"),
3244 fromName, _("OK"), _("Cancel"));
3246 if (toName) {
3248 /* As some people do certain stupid things... */
3249 if (strcmp(toName, fromName) == 0) {
3250 wfree(toName);
3251 return;
3254 /* For normal people */
3255 fromPath = wstrconcat(panel->configurationPath, fromName);
3256 toPath = wstrconcat(panel->configurationPath, toName);
3258 if (access (toPath, F_OK) == 0) {
3259 /* Careful, this palette exists already */
3260 if (WMRunAlertPanel(scr, panel->win, _("Warning"),
3261 _("Palette already exists !\n\nOverwrite ?"), _("No"), _("Yes"),
3262 NULL) == 1) {
3263 /* "No" = 0, "Yes" = 1 */
3264 int items = WMGetPopUpButtonNumberOfItems(
3265 panel->customPaletteHistoryBtn);
3267 remove(toPath);
3269 /* Remove from History list too */
3270 index = 1;
3271 while ((index < items) && (strcmp(WMGetPopUpButtonItem(
3272 panel->customPaletteHistoryBtn, index),
3273 toName) != 0 ))
3274 index++;
3276 if (index < items) {
3277 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn,
3278 index);
3279 if (index < item)
3280 item--;
3283 } else {
3284 wfree(fromPath);
3285 wfree(toName);
3286 wfree(toPath);
3288 return;
3292 if ( rename(fromPath, toPath) != 0)
3293 wsyserror(_("Couldn't rename palette %s to %s\n"), fromName, toName);
3294 else {
3295 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3296 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item,
3297 toName);
3299 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
3301 wfree(fromPath);
3302 wfree(toPath);
3303 wfree(toName);
3308 static void
3309 customPaletteMenuRemove(W_ColorPanel *panel)
3311 W_Screen *scr = WMWidgetScreen(panel->win);
3312 char *text;
3313 char *tmp;
3314 int choice;
3315 int item;
3317 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3319 tmp = wstrconcat( _("This will permanently remove the palette "),
3320 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
3321 text = wstrconcat( tmp,
3322 _(".\n\nAre you sure you want to remove this palette ?"));
3323 wfree(tmp);
3325 choice = WMRunAlertPanel(scr, panel->win, _("Remove"), text, _("Yes"), _("No"),
3326 NULL);
3327 /* returns 0 (= "Yes") or 1 (="No") */
3328 wfree(text);
3330 if (choice == 0) {
3332 tmp = wstrconcat(panel->configurationPath,
3333 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
3335 if ( remove(tmp) == 0) {
3336 /* item-1 always exists */
3337 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3338 item-1);
3340 customPaletteHistoryCallback(panel->customPaletteHistoryBtn,
3341 panel);
3342 customSetPalette(panel);
3344 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3346 } else {
3347 wsyserror(_("Couldn't remove palette %s\n"), tmp);
3350 wfree(tmp);
3355 static void
3356 customPaletteHistoryCallback(WMWidget *w, void *data)
3358 W_ColorPanel *panel = (W_ColorPanel*)data;
3359 W_Screen *scr = WMWidgetScreen(panel->win);
3360 int item;
3361 char *filename;
3362 RImage *tmp = NULL;
3363 unsigned char perm_mask;
3365 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3366 if (item == panel->currentPalette)
3367 return;
3369 if (item == 0) {
3370 customRenderSpectrum(panel);
3372 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename,
3373 False );
3374 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove,
3375 False );
3376 } else {
3377 /* Load file from configpath */
3378 filename = wstrconcat( panel->configurationPath,
3379 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item) );
3381 /* If the file corresponding to the item does not exist,
3382 * remove it from the history list and select the next one.
3384 perm_mask = (access(filename, F_OK) == 0);
3385 if (!perm_mask) {
3386 /* File does not exist */
3387 wfree(filename);
3388 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3389 item-1);
3390 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3391 customPaletteHistoryCallback(w, data);
3392 return;
3395 /* Get the image */
3396 tmp = RLoadImage(scr->rcontext, filename, 0);
3397 if (tmp) {
3398 if (panel->customPaletteImg) {
3399 RReleaseImage(panel->customPaletteImg);
3400 panel->customPaletteImg = NULL;
3402 panel->customPaletteImg = tmp;
3405 /* If the image is not writable, don't allow removing/renaming */
3406 perm_mask = (access(filename, W_OK) == 0);
3407 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename,
3408 perm_mask);
3409 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove,
3410 perm_mask);
3412 wfree(filename);
3414 customSetPalette(panel);
3416 panel->currentPalette = item;
3419 /************************* ColorList Panel Functions **********************/
3421 static void
3422 colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text,
3423 int state, WMRect *rect)
3425 WMScreen *scr = WMWidgetScreen(lPtr);
3426 Display *dpy = WMScreenDisplay(scr);
3427 WMView *view = W_VIEW(lPtr);
3428 RColor color = *((RColor *)WMGetListItem(lPtr, index)->clientData);
3429 W_ColorPanel *panel = WMGetHangedData(lPtr);
3430 int width, height, x, y;
3431 WMColor *fillColor;
3433 width = rect->size.width;
3434 height = rect->size.height;
3435 x = rect->pos.x;
3436 y = rect->pos.y;
3438 if (state & WLDSSelected)
3439 XFillRectangle(dpy, d, WMColorGC(scr->white), x, y, width, height);
3440 else
3441 XFillRectangle(dpy, d, WMColorGC(view->backColor), x, y, width, height);
3443 fillColor = WMCreateRGBColor(scr, color.red<<8, color.green<<8,
3444 color.blue<<8, True);
3446 XFillRectangle(dpy, d, WMColorGC(fillColor), x, y, 15, height);
3447 WMReleaseColor(fillColor);
3449 WMDrawString(scr, d, scr->black, panel->font12, x+18, y, text, strlen(text));
3453 static void
3454 colorListSelect(WMWidget *w, void *data)
3456 W_ColorPanel *panel = (W_ColorPanel *)data;
3457 CPColor cpColor;
3459 cpColor.rgb = *((RColor *)WMGetListSelectedItem(w)->clientData);
3460 cpColor.set = cpRGB;
3462 panel->lastChanged = WMColorListModeColorPanel;
3463 updateSwatch(panel, cpColor);
3467 static void
3468 colorListColorMenuCallback(WMWidget *w, void *data)
3470 W_ColorPanel *panel = (W_ColorPanel *)data;
3471 int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
3473 switch (item) {
3474 case CLmenuAdd:
3475 break;
3476 case CLmenuRename:
3477 break;
3478 case CLmenuRemove:
3479 break;
3484 static void
3485 colorListListMenuCallback(WMWidget *w, void *data)
3487 W_ColorPanel *panel = (W_ColorPanel *)data;
3488 int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
3490 switch (item) {
3491 case CLmenuAdd:
3492 /* New Color List */
3493 colorListListMenuNew(panel);
3494 break;
3495 case CLmenuRename:
3496 break;
3497 case CLmenuRemove:
3498 break;
3503 static void
3504 colorListListMenuNew(W_ColorPanel *panel)
3510 /*************** Panel Initialisation Functions *****************/
3512 static void
3513 wheelInit(W_ColorPanel *panel)
3515 CPColor cpColor;
3517 if (panel->color.set != cpHSV)
3518 convertCPColor(&panel->color);
3520 WMSetSliderValue(panel->wheelBrightnessS, 255 - panel->color.hsv.value);
3522 panel->colx = 2 + rint((colorWheelSize / 2.0) *
3523 (1 + ( panel->color.hsv.saturation/255.0) *
3524 cos( panel->color.hsv.hue * M_PI/180.0)));
3525 panel->coly = 2 + rint((colorWheelSize / 2.0) *
3526 (1 + ( panel->color.hsv.saturation/255.0) *
3527 sin(- panel->color.hsv.hue*M_PI/180.0)));
3529 wheelCalculateValues(panel, panel->color.hsv.value);
3531 cpColor = panel->color;
3532 cpColor.hsv.value = 255;
3533 cpColor.set = cpHSV;
3534 wheelUpdateBrightnessGradient(panel, cpColor);
3538 static void
3539 grayInit(W_ColorPanel *panel)
3541 int value;
3542 char tmp[4];
3544 if (panel->color.set != cpHSV)
3545 convertCPColor(&panel->color);
3547 value = rint(panel->color.hsv.value/2.55);
3548 WMSetSliderValue(panel->grayBrightnessS, value);
3550 sprintf(tmp, "%d", value);
3551 WMSetTextFieldText(panel->grayBrightnessT, tmp);
3555 static void
3556 rgbInit(W_ColorPanel *panel)
3558 char tmp[4];
3560 if (panel->color.set != cpRGB)
3561 convertCPColor(&panel->color);
3563 WMSetSliderValue(panel->rgbRedS, panel->color.rgb.red);
3564 WMSetSliderValue(panel->rgbGreenS, panel->color.rgb.green);
3565 WMSetSliderValue(panel->rgbBlueS, panel->color.rgb.blue);
3567 sprintf(tmp, "%d", panel->color.rgb.red);
3568 WMSetTextFieldText(panel->rgbRedT, tmp);
3569 sprintf(tmp, "%d", panel->color.rgb.green);
3570 WMSetTextFieldText(panel->rgbGreenT, tmp);
3571 sprintf(tmp, "%d", panel->color.rgb.blue);
3572 WMSetTextFieldText(panel->rgbBlueT, tmp);
3576 static void
3577 cmykInit(W_ColorPanel *panel)
3579 int value[3];
3580 char tmp[4];
3582 if (panel->color.set != cpRGB)
3583 convertCPColor(&panel->color);
3585 value[0] = rint((255-panel->color.rgb.red)/2.55);
3586 value[1] = rint((255-panel->color.rgb.green)/2.55);
3587 value[2] = rint((255-panel->color.rgb.blue)/2.55);
3589 WMSetSliderValue(panel->cmykCyanS, value[0]);
3590 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3591 WMSetSliderValue(panel->cmykYellowS, value[2]);
3592 WMSetSliderValue(panel->cmykBlackS, 0);
3594 sprintf(tmp, "%d", value[0]);
3595 WMSetTextFieldText(panel->cmykCyanT, tmp);
3596 sprintf(tmp, "%d", value[1]);
3597 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3598 sprintf(tmp, "%d", value[2]);
3599 WMSetTextFieldText(panel->cmykYellowT, tmp);
3600 WMSetTextFieldText(panel->cmykBlackT, "0");
3604 static void
3605 hsbInit(W_ColorPanel *panel)
3607 int value[3];
3608 char tmp[4];
3610 if (panel->color.set != cpHSV)
3611 convertCPColor(&panel->color);
3613 value[0] = panel->color.hsv.hue;
3614 value[1] = rint(panel->color.hsv.saturation/2.55);
3615 value[2] = rint(panel->color.hsv.value/2.55);
3617 WMSetSliderValue(panel->hsbHueS,value[0]);
3618 WMSetSliderValue(panel->hsbSaturationS,value[1]);
3619 WMSetSliderValue(panel->hsbBrightnessS,value[2]);
3621 sprintf(tmp, "%d", value[0]);
3622 WMSetTextFieldText(panel->hsbHueT, tmp);
3623 sprintf(tmp, "%d", value[1]);
3624 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3625 sprintf(tmp, "%d", value[2]);
3626 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3628 hsbUpdateBrightnessGradient(panel);
3629 hsbUpdateSaturationGradient(panel);
3630 hsbUpdateHueGradient(panel);
3635 /************************** Common utility functions ************************/
3637 static int
3638 fetchFile(char *toPath, char *srcFile, char *destFile)
3640 int src, dest;
3641 int n;
3642 char *tmp;
3643 char buf[BUFSIZE];
3645 if ((src = open(srcFile, O_RDONLY|O_BINARY)) == 0) {
3646 wsyserror(_("Could not open %s"), srcFile);
3647 return -1;
3650 tmp = wstrconcat(toPath, destFile);
3651 if ((dest = open( tmp, O_RDWR|O_CREAT|O_BINARY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH))
3652 == 0) {
3653 wsyserror(_("Could not create %s"), tmp);
3654 wfree(tmp);
3655 return -1;
3657 wfree(tmp);
3660 /* Copy the file */
3661 while ((n = read(src, buf, BUFSIZE)) > 0)
3663 if (write (dest, buf, n) != n) {
3664 wsyserror(_("Write error on file %s"), destFile);
3665 return -1;
3669 return 0;
3673 char*
3674 generateNewFilename(char *curName)
3676 int n;
3677 char c;
3678 int baseLen;
3679 char *ptr;
3680 char *newName;
3683 assert(curName);
3685 ptr = curName;
3687 if (((ptr = strrchr(ptr, '{'))==0) || sscanf(ptr, "{%i}%c", &n, &c)!=1)
3688 return wstrconcat(curName, " {1}");
3690 baseLen = ptr - curName -1;
3692 newName = wmalloc(baseLen + 16);
3693 strncpy(newName, curName, baseLen);
3694 newName[baseLen] = 0;
3696 sprintf(&newName[baseLen], " {%i}", n+1);
3698 return newName;
3702 void
3703 convertCPColor(CPColor *color)
3705 unsigned short old_hue = 0;
3707 switch (color->set) {
3708 case cpNone:
3709 wwarning(_("Color Panel: Color unspecified"));
3710 return;
3711 case cpRGB:
3712 old_hue = color->hsv.hue;
3713 RRGBtoHSV(&(color->rgb), &(color->hsv));
3715 /* In black the hue is undefined, and may change by conversion
3716 * Same for white. */
3717 if (
3718 ((color->rgb.red == 0) &&
3719 (color->rgb.green == 0) &&
3720 (color->rgb.blue == 0)) ||
3721 ((color->rgb.red == 0) &&
3722 (color->rgb.green == 0) &&
3723 (color->rgb.blue == 255))
3725 color->hsv.hue = old_hue;
3726 break;
3727 case cpHSV:
3728 RHSVtoRGB(&(color->hsv), &(color->rgb));
3729 break;
3734 #define ABS_SHIFT(val, shift) \
3735 (((shift) > 0) ? (val) >> (shift) : (val) << -(shift))
3737 RColor
3738 ulongToRColor(WMScreen *scr, unsigned long value)
3740 RColor color;
3741 XColor *xcolor = NULL;
3743 if (!(xcolor = wmalloc(sizeof(XColor)) )) {
3744 wwarning(_("Color Panel: Could not allocate memory"));
3745 color.red = 0;
3746 color.green = 0;
3747 color.blue = 0;
3748 return color;
3751 xcolor->pixel = value;
3752 XQueryColor(scr->display, scr->rcontext->cmap, xcolor);
3754 color.red = xcolor->red >> 8;
3755 color.green = xcolor->green >> 8;
3756 color.blue = xcolor->blue >> 8;
3758 wfree(xcolor);
3760 return color;
3764 unsigned char
3765 getShift(unsigned char value)
3767 unsigned char i = -1;
3769 if (value == 0)
3770 return 0;
3772 while (value) {
3773 value >>= 1;
3774 i++;
3777 return i;
3782 #ifdef SHAPE_WAS_DEFINED
3783 #undef SHAPE_WAS_DEFINED
3784 #define SHAPE
3785 #endif