Change to the linux kernel coding style
[wmaker-crm.git] / WINGs / wcolorwell.c
1
2 #include "WINGsP.h"
3
4 #define XDND_COLOR_DATA_TYPE "application/X-color"
5
6 char *WMColorWellDidChangeNotification = "WMColorWellDidChangeNotification";
7
8 typedef struct W_ColorWell {
9 W_Class widgetClass;
10 WMView *view;
11
12 WMView *colorView;
13
14 WMColor *color;
15
16 WMAction *action;
17 void *clientData;
18
19 WMPoint ipoint;
20
21 struct {
22 unsigned int active:1;
23 unsigned int bordered:1;
24 } flags;
25
26 WMArray *xdndTypes;
27 } ColorWell;
28
29 static char *_ColorWellActivatedNotification = "_ColorWellActivatedNotification";
30
31 static void destroyColorWell(ColorWell * cPtr);
32 static void paintColorWell(ColorWell * cPtr);
33
34 static void handleEvents(XEvent * event, void *data);
35
36 static void handleDragEvents(XEvent * event, void *data);
37
38 static void handleActionEvents(XEvent * event, void *data);
39
40 static void willResizeColorWell();
41
42 W_ViewDelegate _ColorWellViewDelegate = {
43 NULL,
44 NULL,
45 NULL,
46 NULL,
47 willResizeColorWell
48 };
49
50 static WMArray *dropDataTypes(WMView * self);
51 static WMDragOperationType wantedDropOperation(WMView * self);
52 static Bool acceptDropOperation(WMView * self, WMDragOperationType operation);
53 static WMData *fetchDragData(WMView * self, char *type);
54
55 static WMDragSourceProcs _DragSourceProcs = {
56 dropDataTypes,
57 wantedDropOperation,
58 NULL,
59 acceptDropOperation,
60 NULL,
61 NULL,
62 fetchDragData
63 };
64
65 static WMArray *requiredDataTypes(WMView * self,
66 WMDragOperationType requestedOperation, WMArray * sourceDataTypes);
67 static WMDragOperationType allowedOperation(WMView * self,
68 WMDragOperationType requestedOperation, WMArray * sourceDataTypes);
69 static void performDragOperation(WMView * self, WMArray * dropDatas,
70 WMArray * operationsList, WMPoint * dropLocation);
71
72 static WMDragDestinationProcs _DragDestinationProcs = {
73 NULL,
74 requiredDataTypes,
75 allowedOperation,
76 NULL,
77 performDragOperation,
78 NULL
79 };
80
81 #define DEFAULT_WIDTH 60
82 #define DEFAULT_HEIGHT 30
83 #define DEFAULT_BORDER_WIDTH 6
84
85 #define MIN_WIDTH 16
86 #define MIN_HEIGHT 8
87
88 static void colorChangedObserver(void *data, WMNotification * notification)
89 {
90 WMColorPanel *panel = (WMColorPanel *) WMGetNotificationObject(notification);
91 WMColorWell *cPtr = (WMColorWell *) data;
92 WMColor *color;
93
94 if (!cPtr->flags.active)
95 return;
96
97 color = WMGetColorPanelColor(panel);
98
99 WMSetColorWellColor(cPtr, color);
100 WMPostNotificationName(WMColorWellDidChangeNotification, cPtr, NULL);
101 }
102
103 static void updateColorCallback(void *self, void *data)
104 {
105 WMColorPanel *panel = (WMColorPanel *) self;
106 WMColorWell *cPtr = (ColorWell *) data;
107 WMColor *color;
108
109 color = WMGetColorPanelColor(panel);
110 WMSetColorWellColor(cPtr, color);
111 WMPostNotificationName(WMColorWellDidChangeNotification, cPtr, NULL);
112 }
113
114 static void activatedObserver(void *data, WMNotification * notification)
115 {
116 /*
117 WMColorWell *cPtr = (WMColorWell*)data;
118
119 if (!cPtr->flags.active || WMGetNotificationObject(notification) == cPtr)
120 return;
121
122 W_SetViewBackgroundColor(cPtr->view, WMWidgetScreen(cPtr)->gray);
123 paintColorWell(cPtr);
124
125 cPtr->flags.active = 0;
126 */
127 }
128
129 static WMArray *getXdndTypeArray()
130 {
131 WMArray *types = WMCreateArray(1);
132 WMAddToArray(types, XDND_COLOR_DATA_TYPE);
133 return types;
134 }
135
136 WMColorWell *WMCreateColorWell(WMWidget * parent)
137 {
138 ColorWell *cPtr;
139
140 cPtr = wmalloc(sizeof(ColorWell));
141 memset(cPtr, 0, sizeof(ColorWell));
142
143 cPtr->widgetClass = WC_ColorWell;
144
145 cPtr->view = W_CreateView(W_VIEW(parent));
146 if (!cPtr->view) {
147 wfree(cPtr);
148 return NULL;
149 }
150 cPtr->view->self = cPtr;
151
152 cPtr->view->delegate = &_ColorWellViewDelegate;
153
154 cPtr->colorView = W_CreateView(cPtr->view);
155 if (!cPtr->colorView) {
156 W_DestroyView(cPtr->view);
157 wfree(cPtr);
158 return NULL;
159 }
160 cPtr->colorView->self = cPtr;
161
162 WMCreateEventHandler(cPtr->view, ExposureMask | StructureNotifyMask
163 | ClientMessageMask, handleEvents, cPtr);
164
165 WMCreateEventHandler(cPtr->colorView, ExposureMask, handleEvents, cPtr);
166
167 WMCreateDragHandler(cPtr->colorView, handleDragEvents, cPtr);
168
169 WMCreateEventHandler(cPtr->view, ButtonPressMask, handleActionEvents, cPtr);
170
171 cPtr->colorView->flags.mapWhenRealized = 1;
172
173 cPtr->flags.bordered = 1;
174
175 W_ResizeView(cPtr->view, DEFAULT_WIDTH, DEFAULT_HEIGHT);
176
177 WMAddNotificationObserver(activatedObserver, cPtr, _ColorWellActivatedNotification, NULL);
178
179 cPtr->color = WMBlackColor(WMWidgetScreen(cPtr));
180
181 WMAddNotificationObserver(colorChangedObserver, cPtr, WMColorPanelColorChangedNotification, NULL);
182
183 WMSetViewDragSourceProcs(cPtr->colorView, &_DragSourceProcs);
184 WMSetViewDragDestinationProcs(cPtr->colorView, &_DragDestinationProcs);
185
186 cPtr->xdndTypes = getXdndTypeArray();
187 WMRegisterViewForDraggedTypes(cPtr->colorView, cPtr->xdndTypes);
188
189 return cPtr;
190 }
191
192 void WMSetColorWellColor(WMColorWell * cPtr, WMColor * color)
193 {
194 if (cPtr->color)
195 WMReleaseColor(cPtr->color);
196
197 cPtr->color = WMRetainColor(color);
198
199 if (cPtr->colorView->flags.realized && cPtr->colorView->flags.mapped)
200 paintColorWell(cPtr);
201 }
202
203 WMColor *WMGetColorWellColor(WMColorWell * cPtr)
204 {
205 return cPtr->color;
206 }
207
208 void WSetColorWellBordered(WMColorWell * cPtr, Bool flag)
209 {
210 flag = ((flag == 0) ? 0 : 1);
211 if (cPtr->flags.bordered != flag) {
212 cPtr->flags.bordered = flag;
213 W_ResizeView(cPtr->view, cPtr->view->size.width, cPtr->view->size.height);
214 }
215 }
216
217 static void willResizeColorWell(W_ViewDelegate * self, WMView * view, unsigned int *width, unsigned int *height)
218 {
219 WMColorWell *cPtr = (WMColorWell *) view->self;
220 int bw;
221
222 if (cPtr->flags.bordered) {
223
224 if (*width < MIN_WIDTH)
225 *width = MIN_WIDTH;
226 if (*height < MIN_HEIGHT)
227 *height = MIN_HEIGHT;
228
229 bw = (int)((float)WMIN(*width, *height) * 0.24);
230
231 W_ResizeView(cPtr->colorView, *width - 2 * bw, *height - 2 * bw);
232
233 if (cPtr->colorView->pos.x != bw || cPtr->colorView->pos.y != bw)
234 W_MoveView(cPtr->colorView, bw, bw);
235 } else {
236 W_ResizeView(cPtr->colorView, *width, *height);
237
238 W_MoveView(cPtr->colorView, 0, 0);
239 }
240 }
241
242 static void paintColorWell(ColorWell * cPtr)
243 {
244 W_Screen *scr = cPtr->view->screen;
245
246 W_DrawRelief(scr, cPtr->view->window, 0, 0, cPtr->view->size.width, cPtr->view->size.height, WRRaised);
247
248 W_DrawRelief(scr, cPtr->colorView->window, 0, 0,
249 cPtr->colorView->size.width, cPtr->colorView->size.height, WRSunken);
250
251 if (cPtr->color)
252 WMPaintColorSwatch(cPtr->color, cPtr->colorView->window,
253 2, 2, cPtr->colorView->size.width - 4, cPtr->colorView->size.height - 4);
254 }
255
256 static void handleEvents(XEvent * event, void *data)
257 {
258 ColorWell *cPtr = (ColorWell *) data;
259
260 CHECK_CLASS(data, WC_ColorWell);
261
262 switch (event->type) {
263 case Expose:
264 if (event->xexpose.count != 0)
265 break;
266 paintColorWell(cPtr);
267 break;
268
269 case DestroyNotify:
270 destroyColorWell(cPtr);
271 break;
272
273 }
274 }
275
276 static WMArray *dropDataTypes(WMView * self)
277 {
278 return ((ColorWell *) self->self)->xdndTypes;
279 }
280
281 static WMDragOperationType wantedDropOperation(WMView * self)
282 {
283 return WDOperationCopy;
284 }
285
286 static Bool acceptDropOperation(WMView * self, WMDragOperationType operation)
287 {
288 return (operation == WDOperationCopy);
289 }
290
291 static WMData *fetchDragData(WMView * self, char *type)
292 {
293 char *color = WMGetColorRGBDescription(((WMColorWell *) self->self)->color);
294 WMData *data;
295
296 data = WMCreateDataWithBytes(color, strlen(color) + 1);
297 wfree(color);
298
299 return data;
300 }
301
302 static WMPixmap *makeDragPixmap(WMColorWell * cPtr)
303 {
304 WMScreen *scr = cPtr->view->screen;
305 Pixmap pix;
306
307 pix = XCreatePixmap(scr->display, W_DRAWABLE(scr), 16, 16, scr->depth);
308
309 XFillRectangle(scr->display, pix, WMColorGC(cPtr->color), 0, 0, 15, 15);
310
311 XDrawRectangle(scr->display, pix, WMColorGC(scr->black), 0, 0, 15, 15);
312
313 return WMCreatePixmapFromXPixmaps(scr, pix, None, 16, 16, scr->depth);
314 }
315
316 static void handleDragEvents(XEvent * event, void *data)
317 {
318 WMColorWell *cPtr = (ColorWell *) data;
319
320 if (event->type == ButtonPress && event->xbutton.button == Button1) {
321 /* initialise drag icon */
322 WMSetViewDragImage(cPtr->colorView, makeDragPixmap(cPtr));
323 }
324
325 WMDragImageFromView(cPtr->colorView, event);
326 }
327
328 static void handleActionEvents(XEvent * event, void *data)
329 {
330 WMColorWell *cPtr = (ColorWell *) data;
331 WMScreen *scr = WMWidgetScreen(cPtr);
332 WMColorPanel *cpanel;
333
334 if (cPtr->flags.active)
335 W_SetViewBackgroundColor(cPtr->view, scr->gray);
336 else
337 W_SetViewBackgroundColor(cPtr->view, scr->white);
338 paintColorWell(cPtr);
339
340 cPtr->flags.active ^= 1;
341
342 if (cPtr->flags.active) {
343 WMPostNotificationName(_ColorWellActivatedNotification, cPtr, NULL);
344 }
345 cpanel = WMGetColorPanel(scr);
346
347 WMSetColorPanelAction(cpanel, updateColorCallback, cPtr);
348
349 if (cPtr->color)
350 WMSetColorPanelColor(cpanel, cPtr->color);
351 WMShowColorPanel(cpanel);
352 }
353
354 static void destroyColorWell(ColorWell * cPtr)
355 {
356 WMRemoveNotificationObserver(cPtr);
357
358 if (cPtr->color)
359 WMReleaseColor(cPtr->color);
360
361 WMFreeArray(cPtr->xdndTypes);
362
363 wfree(cPtr);
364 }
365
366 static Bool dropIsOk(WMDragOperationType request, WMArray * sourceDataTypes)
367 {
368 WMArrayIterator iter;
369 char *type;
370
371 if (request == WDOperationCopy) {
372 WM_ITERATE_ARRAY(sourceDataTypes, type, iter) {
373 if (type != NULL && strcmp(type, XDND_COLOR_DATA_TYPE) == 0) {
374 return True;
375 }
376 }
377 }
378
379 return False;
380 }
381
382 static WMArray *requiredDataTypes(WMView * self, WMDragOperationType request, WMArray * sourceDataTypes)
383 {
384 if (dropIsOk(request, sourceDataTypes))
385 return ((ColorWell *) self->self)->xdndTypes;
386 else
387 return NULL;
388 }
389
390 static WMDragOperationType allowedOperation(WMView * self, WMDragOperationType request, WMArray * sourceDataTypes)
391 {
392 if (dropIsOk(request, sourceDataTypes))
393 return WDOperationCopy;
394 else
395 return WDOperationNone;
396 }
397
398 static void performDragOperation(WMView * self, WMArray * dropData, WMArray * operations, WMPoint * dropLocation)
399 {
400 char *colorName;
401 WMColor *color;
402 WMData *data;
403
404 /* only one operation requested (WDOperationCopy) implies only one data */
405 data = (WMData *) WMGetFromArray(dropData, 0);
406
407 if (data != NULL) {
408 colorName = (char *)WMDataBytes(data);
409 color = WMCreateNamedColor(W_VIEW_SCREEN(self), colorName, True);
410 WMSetColorWellColor(self->self, color);
411 WMReleaseColor(color);
412 }
413 }