Fix periodic focus bug
[wmaker-crm.git] / WINGs / wcolorwell.c
blobd955463a1949ac473505cfedb38304c65323617b
5 #include "WINGsP.h"
7 #define XDND_COLOR_DATA_TYPE "application/X-color"
9 char *WMColorWellDidChangeNotification = "WMColorWellDidChangeNotification";
12 typedef struct W_ColorWell {
13 W_Class widgetClass;
14 WMView *view;
16 WMView *colorView;
18 WMColor *color;
20 WMAction *action;
21 void *clientData;
23 WMPoint ipoint;
25 struct {
26 unsigned int active:1;
27 unsigned int bordered:1;
28 } flags;
30 WMArray *xdndTypes;
31 } ColorWell;
33 static char *_ColorWellActivatedNotification = "_ColorWellActivatedNotification";
37 static void destroyColorWell(ColorWell *cPtr);
38 static void paintColorWell(ColorWell *cPtr);
40 static void handleEvents(XEvent *event, void *data);
42 static void handleDragEvents(XEvent *event, void *data);
44 static void handleActionEvents(XEvent *event, void *data);
46 static void willResizeColorWell();
50 W_ViewDelegate _ColorWellViewDelegate = {
51 NULL,
52 NULL,
53 NULL,
54 NULL,
55 willResizeColorWell
59 static WMArray* dropDataTypes(WMView *self);
60 static WMDragOperationType wantedDropOperation(WMView *self);
61 static Bool acceptDropOperation(WMView *self, WMDragOperationType operation);
62 static WMData* fetchDragData(WMView *self, char *type);
64 static WMDragSourceProcs _DragSourceProcs = {
65 dropDataTypes,
66 wantedDropOperation,
67 NULL,
68 acceptDropOperation,
69 NULL,
70 NULL,
71 fetchDragData
75 static WMArray* requiredDataTypes(WMView *self,
76 WMDragOperationType requestedOperation, WMArray *sourceDataTypes);
77 static WMDragOperationType allowedOperation(WMView *self,
78 WMDragOperationType requestedOperation, WMArray *sourceDataTypes);
79 static void performDragOperation(WMView *self, WMArray *dropDatas,
80 WMArray *operationsList, WMPoint* dropLocation);
82 static WMDragDestinationProcs _DragDestinationProcs = {
83 NULL,
84 requiredDataTypes,
85 allowedOperation,
86 NULL,
87 performDragOperation ,
88 NULL
92 #define DEFAULT_WIDTH 60
93 #define DEFAULT_HEIGHT 30
94 #define DEFAULT_BORDER_WIDTH 6
96 #define MIN_WIDTH 16
97 #define MIN_HEIGHT 8
101 static void
102 colorChangedObserver(void *data, WMNotification *notification)
104 WMColorPanel *panel = (WMColorPanel*)WMGetNotificationObject(notification);
105 WMColorWell *cPtr = (WMColorWell*)data;
106 WMColor *color;
108 if (!cPtr->flags.active)
109 return;
111 color = WMGetColorPanelColor(panel);
113 WMSetColorWellColor(cPtr, color);
114 WMPostNotificationName(WMColorWellDidChangeNotification, cPtr, NULL);
118 static void
119 updateColorCallback(void *self, void *data)
121 WMColorPanel *panel = (WMColorPanel*)self;
122 WMColorWell *cPtr = (ColorWell*)data;
123 WMColor *color;
125 color = WMGetColorPanelColor(panel);
126 WMSetColorWellColor(cPtr, color);
127 WMPostNotificationName(WMColorWellDidChangeNotification, cPtr, NULL);
132 static void
133 activatedObserver(void *data, WMNotification *notification)
136 WMColorWell *cPtr = (WMColorWell*)data;
138 if (!cPtr->flags.active || WMGetNotificationObject(notification) == cPtr)
139 return;
141 W_SetViewBackgroundColor(cPtr->view, WMWidgetScreen(cPtr)->gray);
142 paintColorWell(cPtr);
144 cPtr->flags.active = 0;
150 static WMArray*
151 getXdndTypeArray()
153 WMArray *types = WMCreateArray(1);
154 WMAddToArray(types, XDND_COLOR_DATA_TYPE);
155 return types;
159 WMColorWell*
160 WMCreateColorWell(WMWidget *parent)
162 ColorWell *cPtr;
164 cPtr = wmalloc(sizeof(ColorWell));
165 memset(cPtr, 0, sizeof(ColorWell));
167 cPtr->widgetClass = WC_ColorWell;
169 cPtr->view = W_CreateView(W_VIEW(parent));
170 if (!cPtr->view) {
171 wfree(cPtr);
172 return NULL;
174 cPtr->view->self = cPtr;
176 cPtr->view->delegate = &_ColorWellViewDelegate;
178 cPtr->colorView = W_CreateView(cPtr->view);
179 if (!cPtr->colorView) {
180 W_DestroyView(cPtr->view);
181 wfree(cPtr);
182 return NULL;
184 cPtr->colorView->self = cPtr;
186 WMCreateEventHandler(cPtr->view, ExposureMask|StructureNotifyMask
187 |ClientMessageMask, handleEvents, cPtr);
189 WMCreateEventHandler(cPtr->colorView, ExposureMask, handleEvents, cPtr);
191 WMCreateDragHandler(cPtr->colorView, handleDragEvents, cPtr);
193 WMCreateEventHandler(cPtr->view, ButtonPressMask, handleActionEvents,
194 cPtr);
196 cPtr->colorView->flags.mapWhenRealized = 1;
198 cPtr->flags.bordered = 1;
200 W_ResizeView(cPtr->view, DEFAULT_WIDTH, DEFAULT_HEIGHT);
202 WMAddNotificationObserver(activatedObserver, cPtr,
203 _ColorWellActivatedNotification, NULL);
205 cPtr->color = WMBlackColor(WMWidgetScreen(cPtr));
207 WMAddNotificationObserver(colorChangedObserver, cPtr,
208 WMColorPanelColorChangedNotification, NULL);
210 WMSetViewDragSourceProcs(cPtr->colorView, &_DragSourceProcs);
211 WMSetViewDragDestinationProcs(cPtr->colorView, &_DragDestinationProcs);
213 cPtr->xdndTypes = getXdndTypeArray();
214 WMRegisterViewForDraggedTypes(cPtr->colorView, cPtr->xdndTypes);
216 return cPtr;
220 void
221 WMSetColorWellColor(WMColorWell *cPtr, WMColor *color)
223 if (cPtr->color)
224 WMReleaseColor(cPtr->color);
226 cPtr->color = WMRetainColor(color);
228 if (cPtr->colorView->flags.realized && cPtr->colorView->flags.mapped)
229 paintColorWell(cPtr);
233 WMColor*
234 WMGetColorWellColor(WMColorWell *cPtr)
236 return cPtr->color;
240 void
241 WSetColorWellBordered(WMColorWell *cPtr, Bool flag)
243 flag = ((flag==0) ? 0 : 1);
244 if (cPtr->flags.bordered != flag) {
245 cPtr->flags.bordered = flag;
246 W_ResizeView(cPtr->view, cPtr->view->size.width, cPtr->view->size.height);
251 static void
252 willResizeColorWell(W_ViewDelegate *self, WMView *view,
253 unsigned int *width, unsigned int *height)
255 WMColorWell *cPtr = (WMColorWell*)view->self;
256 int bw;
258 if (cPtr->flags.bordered) {
260 if (*width < MIN_WIDTH)
261 *width = MIN_WIDTH;
262 if (*height < MIN_HEIGHT)
263 *height = MIN_HEIGHT;
265 bw = (int)((float)WMIN(*width, *height)*0.24);
267 W_ResizeView(cPtr->colorView, *width-2*bw, *height-2*bw);
269 if (cPtr->colorView->pos.x!=bw || cPtr->colorView->pos.y!=bw)
270 W_MoveView(cPtr->colorView, bw, bw);
271 } else {
272 W_ResizeView(cPtr->colorView, *width, *height);
274 W_MoveView(cPtr->colorView, 0, 0);
279 static void
280 paintColorWell(ColorWell *cPtr)
282 W_Screen *scr = cPtr->view->screen;
284 W_DrawRelief(scr, cPtr->view->window, 0, 0, cPtr->view->size.width,
285 cPtr->view->size.height, WRRaised);
287 W_DrawRelief(scr, cPtr->colorView->window, 0, 0,
288 cPtr->colorView->size.width, cPtr->colorView->size.height,
289 WRSunken);
291 if (cPtr->color)
292 WMPaintColorSwatch(cPtr->color, cPtr->colorView->window,
293 2, 2, cPtr->colorView->size.width-4,
294 cPtr->colorView->size.height-4);
299 static void
300 handleEvents(XEvent *event, void *data)
302 ColorWell *cPtr = (ColorWell*)data;
304 CHECK_CLASS(data, WC_ColorWell);
307 switch (event->type) {
308 case Expose:
309 if (event->xexpose.count!=0)
310 break;
311 paintColorWell(cPtr);
312 break;
314 case DestroyNotify:
315 destroyColorWell(cPtr);
316 break;
322 static WMArray*
323 dropDataTypes(WMView *self)
325 return ((ColorWell*)self->self)->xdndTypes;
329 static WMDragOperationType
330 wantedDropOperation(WMView *self)
332 return WDOperationCopy;
336 static Bool
337 acceptDropOperation(WMView *self, WMDragOperationType operation)
339 return (operation == WDOperationCopy);
343 static WMData*
344 fetchDragData(WMView *self, char *type)
346 char *color = WMGetColorRGBDescription(((WMColorWell*)self->self)->color);
347 WMData *data;
349 data = WMCreateDataWithBytes(color, strlen(color)+1);
350 wfree(color);
352 return data;
356 static WMPixmap*
357 makeDragPixmap(WMColorWell *cPtr)
359 WMScreen *scr = cPtr->view->screen;
360 Pixmap pix;
362 pix = XCreatePixmap(scr->display, W_DRAWABLE(scr), 16, 16, scr->depth);
364 XFillRectangle(scr->display, pix, WMColorGC(cPtr->color), 0, 0, 15, 15);
366 XDrawRectangle(scr->display, pix, WMColorGC(scr->black), 0, 0, 15, 15);
368 return WMCreatePixmapFromXPixmaps(scr, pix, None, 16, 16, scr->depth);
372 static void
373 handleDragEvents(XEvent *event, void *data)
375 WMColorWell *cPtr = (ColorWell*)data;
377 if (event->type == ButtonPress && event->xbutton.button == Button1) {
378 /* initialise drag icon */
379 WMSetViewDragImage(cPtr->colorView, makeDragPixmap(cPtr));
382 WMDragImageFromView(cPtr->colorView, event);
386 static void
387 handleActionEvents(XEvent *event, void *data)
389 WMColorWell *cPtr = (ColorWell*)data;
390 WMScreen *scr = WMWidgetScreen(cPtr);
391 WMColorPanel *cpanel;
393 if (cPtr->flags.active)
394 W_SetViewBackgroundColor(cPtr->view, scr->gray);
395 else
396 W_SetViewBackgroundColor(cPtr->view, scr->white);
397 paintColorWell(cPtr);
399 cPtr->flags.active ^= 1;
401 if (cPtr->flags.active) {
402 WMPostNotificationName(_ColorWellActivatedNotification, cPtr, NULL);
404 cpanel = WMGetColorPanel(scr);
406 WMSetColorPanelAction(cpanel, updateColorCallback, cPtr);
408 if (cPtr->color)
409 WMSetColorPanelColor(cpanel, cPtr->color);
410 WMShowColorPanel(cpanel);
414 static void
415 destroyColorWell(ColorWell *cPtr)
417 WMRemoveNotificationObserver(cPtr);
419 if (cPtr->color)
420 WMReleaseColor(cPtr->color);
422 WMFreeArray(cPtr->xdndTypes);
424 wfree(cPtr);
428 static Bool
429 dropIsOk(WMDragOperationType request, WMArray *sourceDataTypes)
431 WMArrayIterator iter;
432 char *type;
434 if (request == WDOperationCopy) {
435 WM_ITERATE_ARRAY(sourceDataTypes, type, iter) {
436 if (type != NULL && strcmp(type, XDND_COLOR_DATA_TYPE)==0) {
437 return True;
442 return False;
446 static WMArray*
447 requiredDataTypes(WMView *self, WMDragOperationType request, WMArray *sourceDataTypes)
449 if (dropIsOk(request, sourceDataTypes))
450 return ((ColorWell*)self->self)->xdndTypes;
451 else
452 return NULL;
456 static WMDragOperationType
457 allowedOperation(WMView *self, WMDragOperationType request, WMArray *sourceDataTypes)
459 if (dropIsOk(request, sourceDataTypes))
460 return WDOperationCopy;
461 else
462 return WDOperationNone;
466 static void
467 performDragOperation(WMView *self, WMArray *dropData, WMArray *operations,
468 WMPoint* dropLocation)
470 char *colorName;
471 WMColor *color;
472 WMData* data;
474 /* only one operation requested (WDOperationCopy) implies only one data */
475 data = (WMData*)WMGetFromArray(dropData, 0);
477 if (data != NULL) {
478 colorName = (char*)WMDataBytes(data);
479 color = WMCreateNamedColor(W_VIEW_SCREEN(self), colorName, True);
480 WMSetColorWellColor(self->self, color);
481 WMReleaseColor(color);