added notification in colorpanel
[wmaker-crm.git] / WINGs / wcolorwell.c
blob4a28407e8aa17a3bdbd95187d5854cc78b6c6c3c
5 #include "WINGsP.h"
8 char *WMColorWellDidChangeNotification = "WMColorWellDidChangeNotification";
11 typedef struct W_ColorWell {
12 W_Class widgetClass;
13 WMView *view;
15 WMView *colorView;
17 WMColor *color;
19 WMAction *action;
20 void *clientData;
22 WMPoint ipoint;
24 struct {
25 unsigned int active:1;
26 unsigned int bordered:1;
27 } flags;
28 } ColorWell;
30 static char *_ColorWellActivatedNotification = "_ColorWellActivatedNotification";
34 static void destroyColorWell(ColorWell *cPtr);
35 static void paintColorWell(ColorWell *cPtr);
37 static void handleEvents(XEvent *event, void *data);
39 static void handleDragEvents(XEvent *event, void *data);
41 static void handleActionEvents(XEvent *event, void *data);
43 static void resizeColorWell();
47 W_ViewProcedureTable _ColorWellViewProcedures = {
48 NULL,
49 resizeColorWell,
50 NULL
54 #if 0
55 static WMDragSourceProcs dragProcs = {
58 #endif
60 #define DEFAULT_WIDTH 60
61 #define DEFAULT_HEIGHT 30
62 #define DEFAULT_BORDER_WIDTH 6
64 #define MIN_WIDTH 16
65 #define MIN_HEIGHT 8
69 static void
70 colorChangedObserver(void *data, WMNotification *notification)
73 WMColorPanel *panel = (WMColorPanel*)WMGetNotificationObject(notification);
74 WMColorWell *cPtr = (WMColorWell*)data;
75 WMColor *color;
77 if (!cPtr->flags.active)
78 return;
80 color = WMGetColorPanelColor(panel);
82 WMSetColorWellColor(cPtr, color);*/
87 static void
88 updateColorCallback(void *self, void *data)
91 WMColorPanel *panel = (WMColorPanel*)self;
92 WMColorWell *cPtr = (ColorWell*)data;
93 WMColor *color;
95 color = WMGetColorPanelColor(panel);
96 WMSetColorWellColor(cPtr, color);*/
101 static void
102 activatedObserver(void *data, WMNotification *notification)
105 WMColorWell *cPtr = (WMColorWell*)data;
107 if (!cPtr->flags.active || WMGetNotificationObject(notification) == cPtr)
108 return;
110 W_SetViewBackgroundColor(cPtr->view, WMWidgetScreen(cPtr)->gray);
111 paintColorWell(cPtr);
113 cPtr->flags.active = 0;
119 WMColorWell*
120 WMCreateColorWell(WMWidget *parent)
122 ColorWell *cPtr;
124 cPtr = wmalloc(sizeof(ColorWell));
125 memset(cPtr, 0, sizeof(ColorWell));
127 cPtr->widgetClass = WC_ColorWell;
129 cPtr->view = W_CreateView(W_VIEW(parent));
130 if (!cPtr->view) {
131 free(cPtr);
132 return NULL;
134 cPtr->view->self = cPtr;
136 cPtr->colorView = W_CreateView(cPtr->view);
137 if (!cPtr->colorView) {
138 W_DestroyView(cPtr->view);
139 free(cPtr);
140 return NULL;
142 cPtr->colorView->self = cPtr;
144 WMCreateEventHandler(cPtr->view, ExposureMask|StructureNotifyMask
145 |ClientMessageMask, handleEvents, cPtr);
147 WMCreateEventHandler(cPtr->colorView, ExposureMask, handleEvents, cPtr);
149 WMCreateEventHandler(cPtr->colorView, ButtonPressMask|ButtonMotionMask
150 |EnterWindowMask, handleDragEvents, cPtr);
152 WMCreateEventHandler(cPtr->view, ButtonPressMask, handleActionEvents,
153 cPtr);
155 cPtr->colorView->flags.mapWhenRealized = 1;
157 cPtr->flags.bordered = 1;
159 resizeColorWell(cPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
161 WMAddNotificationObserver(activatedObserver, cPtr,
162 _ColorWellActivatedNotification, NULL);
164 cPtr->color = WMBlackColor(WMWidgetScreen(cPtr));
166 WMAddNotificationObserver(colorChangedObserver, cPtr,
167 WMColorPanelColorChangedNotification, NULL);
169 return cPtr;
173 void
174 WMSetColorWellColor(WMColorWell *cPtr, WMColor *color)
176 if (cPtr->color)
177 WMReleaseColor(cPtr->color);
179 cPtr->color = WMRetainColor(color);
181 if (cPtr->colorView->flags.realized && cPtr->colorView->flags.mapped)
182 paintColorWell(cPtr);
186 WMColor*
187 WMGetColorWellColor(WMColorWell *cPtr)
189 return cPtr->color;
193 void
194 WSetColorWellBordered(WMColorWell *cPtr, Bool flag)
196 if (cPtr->flags.bordered != flag) {
197 cPtr->flags.bordered = flag;
198 resizeColorWell(cPtr, cPtr->view->size.width, cPtr->view->size.height);
203 #define MIN(a,b) ((a) > (b) ? (b) : (a))
205 static void
206 resizeColorWell(WMColorWell *cPtr, unsigned int width, unsigned int height)
208 int bw;
210 if (cPtr->flags.bordered) {
212 if (width < MIN_WIDTH)
213 width = MIN_WIDTH;
214 if (height < MIN_HEIGHT)
215 height = MIN_HEIGHT;
217 bw = (int)((float)MIN(width, height)*0.24);
219 W_ResizeView(cPtr->view, width, height);
221 W_ResizeView(cPtr->colorView, width-2*bw, height-2*bw);
223 if (cPtr->colorView->pos.x!=bw || cPtr->colorView->pos.y!=bw)
224 W_MoveView(cPtr->colorView, bw, bw);
225 } else {
226 W_ResizeView(cPtr->view, width, height);
228 W_ResizeView(cPtr->colorView, width, height);
230 W_MoveView(cPtr->colorView, 0, 0);
235 static void
236 paintColorWell(ColorWell *cPtr)
238 W_Screen *scr = cPtr->view->screen;
240 W_DrawRelief(scr, cPtr->view->window, 0, 0, cPtr->view->size.width,
241 cPtr->view->size.height, WRRaised);
243 W_DrawRelief(scr, cPtr->colorView->window, 0, 0,
244 cPtr->colorView->size.width, cPtr->colorView->size.height,
245 WRSunken);
247 if (cPtr->color)
248 WMPaintColorSwatch(cPtr->color, cPtr->colorView->window,
249 2, 2, cPtr->colorView->size.width-4,
250 cPtr->colorView->size.height-4);
255 static void
256 handleEvents(XEvent *event, void *data)
258 ColorWell *cPtr = (ColorWell*)data;
260 CHECK_CLASS(data, WC_ColorWell);
263 switch (event->type) {
264 case Expose:
265 if (event->xexpose.count!=0)
266 break;
267 paintColorWell(cPtr);
268 break;
270 case DestroyNotify:
271 destroyColorWell(cPtr);
272 break;
278 static WMPixmap*
279 makeDragPixmap(WMColorWell *cPtr)
281 WMScreen *scr = cPtr->view->screen;
282 Pixmap pix;
284 pix = XCreatePixmap(scr->display, W_DRAWABLE(scr), 16, 16, scr->depth);
286 XFillRectangle(scr->display, pix, WMColorGC(cPtr->color), 0, 0, 15, 15);
288 XDrawRectangle(scr->display, pix, WMColorGC(scr->black), 0, 0, 15, 15);
290 return WMCreatePixmapFromXPixmaps(scr, pix, None, 16, 16, scr->depth);
294 static void
295 slideView(WMView *view, int srcX, int srcY, int dstX, int dstY)
297 double x, y, dx, dy;
298 int i;
300 srcX -= 8;
301 srcY -= 8;
302 dstX -= 8;
303 dstY -= 8;
305 x = srcX;
306 y = srcY;
308 dx = (double)(dstX-srcX)/20.0;
309 dy = (double)(dstY-srcY)/20.0;
311 for (i = 0; i < 20; i++) {
312 W_MoveView(view, x, y);
313 XFlush(view->screen->display);
315 x += dx;
316 y += dy;
321 static void
322 dragColor(ColorWell *cPtr, XEvent *event, WMPixmap *image)
324 WMView *dragView;
325 WMScreen *scr = cPtr->view->screen;
326 Display *dpy = scr->display;
327 XColor black = {0, 0,0,0, DoRed|DoGreen|DoBlue};
328 XColor green = {0x0045b045, 0x4500,0xb000,0x4500, DoRed|DoGreen|DoBlue};
329 XColor back = {0, 0xffff,0xffff,0xffff, DoRed|DoGreen|DoBlue};
330 Bool done = False;
331 WMColorWell *activeWell = NULL;
333 dragView = W_CreateTopView(scr);
335 W_ResizeView(dragView, 16, 16);
336 dragView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
337 dragView->attribs.event_mask = StructureNotifyMask;
338 dragView->attribs.override_redirect = True;
339 dragView->attribs.save_under = True;
341 W_MoveView(dragView, event->xmotion.x_root-8, event->xmotion.y_root-8);
343 W_RealizeView(dragView);
345 W_MapView(dragView);
347 XSetWindowBackgroundPixmap(dpy, dragView->window, WMGetPixmapXID(image));
348 XClearWindow(dpy, dragView->window);
351 XGrabPointer(dpy, dragView->window, True,
352 ButtonMotionMask|ButtonReleaseMask|EnterWindowMask,
353 GrabModeSync, GrabModeAsync,
354 scr->rootWin, scr->defaultCursor, CurrentTime);
356 while (!done) {
357 XEvent ev;
358 WMView *view;
360 XAllowEvents(dpy, SyncPointer, CurrentTime);
361 WMNextEvent(dpy, &ev);
363 switch (ev.type) {
364 case ButtonRelease:
365 if (activeWell != NULL) {
366 WMSetColorWellColor(activeWell, cPtr->color);
367 WMPostNotificationName(WMColorWellDidChangeNotification,
368 activeWell, NULL);
369 } else {
370 slideView(dragView, ev.xbutton.x_root, ev.xbutton.y_root,
371 event->xmotion.x_root, event->xmotion.y_root);
374 done = True;
375 break;
377 case EnterNotify:
378 view = W_GetViewForXWindow(dpy, ev.xcrossing.window);
380 if (view && view->self && W_CLASS(view->self) == WC_ColorWell
381 && view->self != activeWell && view->self != cPtr) {
383 activeWell = view->self;
384 XRecolorCursor(dpy, scr->defaultCursor, &green, &back);
385 } else if (view->self!=NULL && view->self != activeWell) {
386 XRecolorCursor(dpy, scr->defaultCursor, &black, &back);
387 activeWell = NULL;
389 break;
391 case MotionNotify:
392 W_MoveView(dragView, ev.xmotion.x_root-8, ev.xmotion.y_root-8);
393 break;
395 default:
396 WMHandleEvent(&ev);
397 break;
400 XUngrabPointer(dpy, CurrentTime);
401 XRecolorCursor(dpy, scr->defaultCursor, &black, &back);
403 W_DestroyView(dragView);
407 static void
408 handleDragEvents(XEvent *event, void *data)
410 WMColorWell *cPtr = (ColorWell*)data;
412 switch (event->type) {
413 case ButtonPress:
414 if (event->xbutton.button == Button1) {
415 cPtr->ipoint.x = event->xbutton.x;
416 cPtr->ipoint.y = event->xbutton.y;
418 break;
420 case MotionNotify:
421 if (event->xmotion.state & Button1Mask) {
422 if (abs(cPtr->ipoint.x - event->xmotion.x) > 4
423 || abs(cPtr->ipoint.y - event->xmotion.y) > 4) {
424 WMSize offs;
425 WMPixmap *pixmap;
427 offs.width = 2;
428 offs.height = 2;
429 pixmap = makeDragPixmap(cPtr);
432 WMDragImageFromView(cPtr->view, pixmap, cPtr->view->pos,
433 offs, event, True);
434 * */
436 dragColor(cPtr, event, pixmap);
438 WMReleasePixmap(pixmap);
441 break;
446 static void
447 handleActionEvents(XEvent *event, void *data)
449 WMColorWell *cPtr = (ColorWell*)data;
450 WMScreen *scr = WMWidgetScreen(cPtr);
451 WMColorPanel *cpanel;
453 if (cPtr->flags.active)
454 W_SetViewBackgroundColor(cPtr->view, scr->gray);
455 else
456 W_SetViewBackgroundColor(cPtr->view, scr->white);
457 paintColorWell(cPtr);
459 cPtr->flags.active ^= 1;
461 if (cPtr->flags.active) {
462 WMPostNotificationName(_ColorWellActivatedNotification, cPtr, NULL);
464 cpanel = WMGetColorPanel(scr);
466 WMSetColorPanelAction(cpanel, updateColorCallback, cPtr);
468 if (cPtr->color)
469 WMSetColorPanelColor(cpanel, cPtr->color);
470 WMShowColorPanel(cpanel);
474 static void
475 destroyColorWell(ColorWell *cPtr)
477 WMRemoveNotificationObserver(cPtr);
479 if (cPtr->color)
480 WMReleaseColor(cPtr->color);
482 free(cPtr);