Change to the linux kernel coding style
[wmaker-crm.git] / WPrefs.app / editmenu.c
Commit [+]AuthorDateLineData
e7495baf dan1999-02-17 11:06:40 +00001/* editmenu.c - editable menus
6830b057 dan2004-10-12 21:28:27 +00002 *
e7495baf dan1999-02-17 11:06:40 +00003 * WPrefs - Window Maker Preferences Program
6830b057 dan2004-10-12 21:28:27 +00004 *
4153e2fd dan2003-01-16 23:30:45 +00005 * Copyright (c) 2000-2003 Alfredo K. Kojima
6830b057 dan2004-10-12 21:28:27 +00006 *
e7495baf dan1999-02-17 11:06:40 +00007 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
6830b057 dan2004-10-12 21:28:27 +000019 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
e7495baf dan1999-02-17 11:06:40 +000020 * USA.
21 */
22
a20aebde dan2001-01-18 19:21:56 +000023#include <WINGs/WINGsP.h>
24#include <WINGs/WUtil.h>
e7495baf dan1999-02-17 11:06:40 +000025#include <stdlib.h>
06f59b99 Carlos R. Mafra2008-11-06 01:37:44 +010026#include <stdint.h>
e7495baf dan1999-02-17 11:06:40 +000027#include <assert.h>
28#include <ctype.h>
29
30#include "editmenu.h"
31
32typedef struct W_EditMenuItem {
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020033 W_Class widgetClass;
34 WMView *view;
e7495baf dan1999-02-17 11:06:40 +000035
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020036 struct W_EditMenu *parent;
e7495baf dan1999-02-17 11:06:40 +000037
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020038 char *label;
39 WMPixmap *pixmap; /* pixmap to show at left */
e7495baf dan1999-02-17 11:06:40 +000040
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020041 void *data;
42 WMCallback *destroyData;
e7495baf dan1999-02-17 11:06:40 +000043
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020044 struct W_EditMenu *submenu; /* if it's a cascade, NULL otherwise */
6830b057 dan2004-10-12 21:28:27 +000045
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020046 struct {
47 unsigned isTitle:1;
48 unsigned isHighlighted:1;
49 } flags;
e7495baf dan1999-02-17 11:06:40 +000050} EditMenuItem;
51
e7495baf dan1999-02-17 11:06:40 +000052typedef struct W_EditMenu {
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020053 W_Class widgetClass;
54 WMView *view;
e7495baf dan1999-02-17 11:06:40 +000055
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020056 struct W_EditMenu *parent;
e7495baf dan1999-02-17 11:06:40 +000057
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020058 WMArray *items; /* EditMenuItem */
6830b057 dan2004-10-12 21:28:27 +000059
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020060 EditMenuItem *selectedItem;
6830b057 dan2004-10-12 21:28:27 +000061
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020062 WMTextField *tfield;
e7495baf dan1999-02-17 11:06:40 +000063
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020064 WMButton *closeB;
bb6acdad kojima2000-07-14 15:16:46 +000065
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020066 int titleHeight;
67 int itemHeight;
6830b057 dan2004-10-12 21:28:27 +000068
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020069 WEditMenuDelegate *delegate;
e7495baf dan1999-02-17 11:06:40 +000070
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020071 WMTextFieldDelegate *tdelegate;
1a7c397d kojima2000-07-16 04:05:49 +000072
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020073 /* item dragging */
74 int draggedItem;
75 int dragX, dragY;
6830b057 dan2004-10-12 21:28:27 +000076
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020077 /* only for non-standalone menu */
78 WMSize maxSize;
79 WMSize minSize;
6830b057 dan2004-10-12 21:28:27 +000080
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020081 struct {
82 unsigned standalone:1;
83 unsigned isTitled:1;
6830b057 dan2004-10-12 21:28:27 +000084
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020085 unsigned acceptsDrop:1;
86 unsigned isFactory:1;
87 unsigned isSelectable:1;
88 unsigned isEditable:1;
6830b057 dan2004-10-12 21:28:27 +000089
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020090 unsigned isTornOff:1;
6830b057 dan2004-10-12 21:28:27 +000091
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020092 unsigned isDragging:1;
93 unsigned isEditing:1;
6830b057 dan2004-10-12 21:28:27 +000094
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020095 unsigned wasMapped:1;
96 } flags;
e7495baf dan1999-02-17 11:06:40 +000097} EditMenu;
98
e7495baf dan1999-02-17 11:06:40 +000099/******************** WEditMenuItem ********************/
100
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200101static void destroyEditMenuItem(WEditMenuItem * iPtr);
102static void paintEditMenuItem(WEditMenuItem * iPtr);
103static void handleItemEvents(XEvent * event, void *data);
e7495baf dan1999-02-17 11:06:40 +0000104
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200105static void handleItemClick(XEvent * event, void *data);
e7495baf dan1999-02-17 11:06:40 +0000106
107static W_Class EditMenuItemClass = 0;
108
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200109W_Class InitEditMenuItem(WMScreen * scr)
e7495baf dan1999-02-17 11:06:40 +0000110{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200111 /* register our widget with WINGs and get our widget class ID */
112 if (!EditMenuItemClass) {
113 EditMenuItemClass = W_RegisterUserWidget();
114 }
e7495baf dan1999-02-17 11:06:40 +0000115
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200116 return EditMenuItemClass;
e7495baf dan1999-02-17 11:06:40 +0000117}
118
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200119WEditMenuItem *WCreateEditMenuItem(WMWidget * parent, char *title, Bool isTitle)
e7495baf dan1999-02-17 11:06:40 +0000120{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200121 WEditMenuItem *iPtr;
122 WMScreen *scr = WMWidgetScreen(parent);
e7495baf dan1999-02-17 11:06:40 +0000123
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200124 if (!EditMenuItemClass)
125 InitEditMenuItem(scr);
e7495baf dan1999-02-17 11:06:40 +0000126
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200127 iPtr = wmalloc(sizeof(WEditMenuItem));
e7495baf dan1999-02-17 11:06:40 +0000128
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200129 memset(iPtr, 0, sizeof(WEditMenuItem));
e7495baf dan1999-02-17 11:06:40 +0000130
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200131 iPtr->widgetClass = EditMenuItemClass;
e7495baf dan1999-02-17 11:06:40 +0000132
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200133 iPtr->view = W_CreateView(W_VIEW(parent));
134 if (!iPtr->view) {
135 wfree(iPtr);
136 return NULL;
137 }
138 iPtr->view->self = iPtr;
6830b057 dan2004-10-12 21:28:27 +0000139
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200140 iPtr->parent = parent;
e7495baf dan1999-02-17 11:06:40 +0000141
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200142 iPtr->label = wstrdup(title);
6830b057 dan2004-10-12 21:28:27 +0000143
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200144 iPtr->flags.isTitle = isTitle;
6830b057 dan2004-10-12 21:28:27 +0000145
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200146 if (isTitle) {
147 WMSetWidgetBackgroundColor(iPtr, WMBlackColor(scr));
148 }
6830b057 dan2004-10-12 21:28:27 +0000149
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200150 WMCreateEventHandler(iPtr->view, ExposureMask | StructureNotifyMask, handleItemEvents, iPtr);
6830b057 dan2004-10-12 21:28:27 +0000151
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200152 WMCreateEventHandler(iPtr->view, ButtonPressMask | ButtonReleaseMask
153 | ButtonMotionMask, handleItemClick, iPtr);
6830b057 dan2004-10-12 21:28:27 +0000154
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200155 return iPtr;
e7495baf dan1999-02-17 11:06:40 +0000156}
157
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200158char *WGetEditMenuItemTitle(WEditMenuItem * item)
6d5f1817 kojima2000-07-14 05:48:35 +0000159{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200160 return item->label;
6d5f1817 kojima2000-07-14 05:48:35 +0000161}
162
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200163void *WGetEditMenuItemData(WEditMenuItem * item)
e958044d kojima2000-07-10 22:49:07 +0000164{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200165 return item->data;
e958044d kojima2000-07-10 22:49:07 +0000166}
167
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200168void WSetEditMenuItemData(WEditMenuItem * item, void *data, WMCallback * destroyer)
e958044d kojima2000-07-10 22:49:07 +0000169{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200170 item->data = data;
171 item->destroyData = destroyer;
e958044d kojima2000-07-10 22:49:07 +0000172}
173
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200174void WSetEditMenuItemImage(WEditMenuItem * item, WMPixmap * pixmap)
dcd44b17 kojima2000-07-15 22:00:41 +0000175{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200176 if (item->pixmap)
177 WMReleasePixmap(item->pixmap);
178 item->pixmap = WMRetainPixmap(pixmap);
dcd44b17 kojima2000-07-15 22:00:41 +0000179}
e958044d kojima2000-07-10 22:49:07 +0000180
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200181static void paintEditMenuItem(WEditMenuItem * iPtr)
e7495baf dan1999-02-17 11:06:40 +0000182{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200183 WMScreen *scr = WMWidgetScreen(iPtr);
184 WMColor *color;
185 Window win = W_VIEW(iPtr)->window;
186 int w = W_VIEW(iPtr)->size.width;
187 int h = W_VIEW(iPtr)->size.height;
188 WMFont *font = (iPtr->flags.isTitle ? scr->boldFont : scr->normalFont);
e958044d kojima2000-07-10 22:49:07 +0000189
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200190 if (!iPtr->view->flags.realized)
191 return;
e958044d kojima2000-07-10 22:49:07 +0000192
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200193 color = scr->black;
194 if (iPtr->flags.isTitle && !iPtr->flags.isHighlighted) {
195 color = scr->white;
196 }
e7495baf dan1999-02-17 11:06:40 +0000197
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200198 XClearWindow(scr->display, win);
e7495baf dan1999-02-17 11:06:40 +0000199
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200200 W_DrawRelief(scr, win, 0, 0, w + 1, h, WRRaised);
e958044d kojima2000-07-10 22:49:07 +0000201
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200202 WMDrawString(scr, win, color, font, 5, 3, iPtr->label, strlen(iPtr->label));
e958044d kojima2000-07-10 22:49:07 +0000203
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200204 if (iPtr->pixmap) {
205 WMSize size = WMGetPixmapSize(iPtr->pixmap);
e958044d kojima2000-07-10 22:49:07 +0000206
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200207 WMDrawPixmap(iPtr->pixmap, win, w - size.width - 5, (h - size.height) / 2);
208 } else if (iPtr->submenu) {
209 /* draw the cascade indicator */
210 XDrawLine(scr->display, win, WMColorGC(scr->darkGray), w - 11, 6, w - 6, h / 2 - 1);
211 XDrawLine(scr->display, win, WMColorGC(scr->white), w - 11, h - 8, w - 6, h / 2 - 1);
212 XDrawLine(scr->display, win, WMColorGC(scr->black), w - 12, 6, w - 12, h - 8);
213 }
e7495baf dan1999-02-17 11:06:40 +0000214}
215
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200216static void highlightItem(WEditMenuItem * iPtr, Bool high)
217{
218 if (iPtr->flags.isTitle)
219 return;
220
221 iPtr->flags.isHighlighted = high;
222
223 if (high) {
224 WMSetWidgetBackgroundColor(iPtr, WMWhiteColor(WMWidgetScreen(iPtr)));
225 } else {
226 if (!iPtr->flags.isTitle) {
227 WMSetWidgetBackgroundColor(iPtr, WMGrayColor(WMWidgetScreen(iPtr)));
228 } else {
229 WMSetWidgetBackgroundColor(iPtr, WMBlackColor(WMWidgetScreen(iPtr)));
230 }
231 }
232}
e7495baf dan1999-02-17 11:06:40 +0000233
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200234static int getItemTextWidth(WEditMenuItem * iPtr)
e7495baf dan1999-02-17 11:06:40 +0000235{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200236 WMScreen *scr = WMWidgetScreen(iPtr);
237
238 if (iPtr->flags.isTitle) {
239 return WMWidthOfString(scr->boldFont, iPtr->label, strlen(iPtr->label));
240 } else {
241 return WMWidthOfString(scr->normalFont, iPtr->label, strlen(iPtr->label));
242 }
e7495baf dan1999-02-17 11:06:40 +0000243}
244
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200245static void handleItemEvents(XEvent * event, void *data)
246{
247 WEditMenuItem *iPtr = (WEditMenuItem *) data;
248
249 switch (event->type) {
250 case Expose:
251 if (event->xexpose.count != 0)
252 break;
253 paintEditMenuItem(iPtr);
254 break;
255
256 case DestroyNotify:
257 destroyEditMenuItem(iPtr);
258 break;
259 }
260}
e7495baf dan1999-02-17 11:06:40 +0000261
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200262static void destroyEditMenuItem(WEditMenuItem * iPtr)
263{
264 if (iPtr->label)
265 wfree(iPtr->label);
266 if (iPtr->data && iPtr->destroyData)
267 (*iPtr->destroyData) (iPtr->data);
268 if (iPtr->submenu)
269 WMDestroyWidget(iPtr->submenu);
270
271 wfree(iPtr);
272}
e7495baf dan1999-02-17 11:06:40 +0000273
274/******************** WEditMenu *******************/
275
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200276static void destroyEditMenu(WEditMenu * mPtr);
e7495baf dan1999-02-17 11:06:40 +0000277
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200278static void updateMenuContents(WEditMenu * mPtr);
e7495baf dan1999-02-17 11:06:40 +0000279
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200280static void handleEvents(XEvent * event, void *data);
e7495baf dan1999-02-17 11:06:40 +0000281
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200282static void editItemLabel(WEditMenuItem * item);
e7495baf dan1999-02-17 11:06:40 +0000283
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200284static void stopEditItem(WEditMenu * menu, Bool apply);
6d5f1817 kojima2000-07-14 05:48:35 +0000285
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200286static void deselectItem(WEditMenu * menu);
6d5f1817 kojima2000-07-14 05:48:35 +0000287
e7495baf dan1999-02-17 11:06:40 +0000288static W_Class EditMenuClass = 0;
289
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200290W_Class InitEditMenu(WMScreen * scr)
e7495baf dan1999-02-17 11:06:40 +0000291{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200292 /* register our widget with WINGs and get our widget class ID */
293 if (!EditMenuClass) {
e7495baf dan1999-02-17 11:06:40 +0000294
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200295 EditMenuClass = W_RegisterUserWidget();
296 }
e7495baf dan1999-02-17 11:06:40 +0000297
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200298 return EditMenuClass;
e7495baf dan1999-02-17 11:06:40 +0000299}
300
e7495baf dan1999-02-17 11:06:40 +0000301typedef struct {
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200302 int flags;
303 int window_style;
304 int window_level;
305 int reserved;
306 Pixmap miniaturize_pixmap; /* pixmap for miniaturize button */
307 Pixmap close_pixmap; /* pixmap for close button */
308 Pixmap miniaturize_mask; /* miniaturize pixmap mask */
309 Pixmap close_mask; /* close pixmap mask */
310 int extra_flags;
e7495baf dan1999-02-17 11:06:40 +0000311} GNUstepWMAttributes;
312
e7495baf dan1999-02-17 11:06:40 +0000313#define GSWindowStyleAttr (1<<0)
314#define GSWindowLevelAttr (1<<1)
315
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200316static void writeGNUstepWMAttr(WMScreen * scr, Window window, GNUstepWMAttributes * attr)
e7495baf dan1999-02-17 11:06:40 +0000317{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200318 unsigned long data[9];
319
320 /* handle idiot compilers where array of CARD32 != struct of CARD32 */
321 data[0] = attr->flags;
322 data[1] = attr->window_style;
323 data[2] = attr->window_level;
324 data[3] = 0; /* reserved */
325 /* The X protocol says XIDs are 32bit */
326 data[4] = attr->miniaturize_pixmap;
327 data[5] = attr->close_pixmap;
328 data[6] = attr->miniaturize_mask;
329 data[7] = attr->close_mask;
330 data[8] = attr->extra_flags;
331 XChangeProperty(scr->display, window, scr->attribsAtom, scr->attribsAtom,
332 32, PropModeReplace, (unsigned char *)data, 9);
e7495baf dan1999-02-17 11:06:40 +0000333}
334
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200335static void realizeObserver(void *self, WMNotification * not)
e7495baf dan1999-02-17 11:06:40 +0000336{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200337 WEditMenu *menu = (WEditMenu *) self;
338 GNUstepWMAttributes attribs;
1a7c397d kojima2000-07-16 04:05:49 +0000339
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200340 memset(&attribs, 0, sizeof(GNUstepWMAttributes));
341 attribs.flags = GSWindowStyleAttr | GSWindowLevelAttr;
342 attribs.window_style = WMBorderlessWindowMask;
343 attribs.window_level = WMSubmenuWindowLevel;
e7495baf dan1999-02-17 11:06:40 +0000344
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200345 writeGNUstepWMAttr(WMWidgetScreen(menu), menu->view->window, &attribs);
e7495baf dan1999-02-17 11:06:40 +0000346}
347
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200348static void itemSelectObserver(void *self, WMNotification * notif)
6d5f1817 kojima2000-07-14 05:48:35 +0000349{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200350 WEditMenu *menu = (WEditMenu *) self;
351 WEditMenu *rmenu;
352
353 rmenu = (WEditMenu *) WMGetNotificationObject(notif);
354 /* check whether rmenu is from the same hierarchy of menu? */
355
356 if (rmenu == menu) {
357 return;
358 }
359
360 if (menu->selectedItem) {
361 if (!menu->selectedItem->submenu)
362 deselectItem(menu);
363 if (menu->flags.isEditing)
364 stopEditItem(menu, False);
365 }
6d5f1817 kojima2000-07-14 05:48:35 +0000366}
367
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200368static WEditMenu *makeEditMenu(WMScreen * scr, WMWidget * parent, char *title)
e7495baf dan1999-02-17 11:06:40 +0000369{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200370 WEditMenu *mPtr;
371 WEditMenuItem *item;
e7495baf dan1999-02-17 11:06:40 +0000372
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200373 if (!EditMenuClass)
374 InitEditMenu(scr);
e7495baf dan1999-02-17 11:06:40 +0000375
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200376 mPtr = wmalloc(sizeof(WEditMenu));
377 memset(mPtr, 0, sizeof(WEditMenu));
e7495baf dan1999-02-17 11:06:40 +0000378
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200379 mPtr->widgetClass = EditMenuClass;
e7495baf dan1999-02-17 11:06:40 +0000380
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200381 if (parent) {
382 mPtr->view = W_CreateView(W_VIEW(parent));
383 mPtr->flags.standalone = 0;
384 } else {
385 mPtr->view = W_CreateTopView(scr);
386 mPtr->flags.standalone = 1;
387 }
388 if (!mPtr->view) {
389 wfree(mPtr);
390 return NULL;
391 }
392 mPtr->view->self = mPtr;
e7495baf dan1999-02-17 11:06:40 +0000393
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200394 mPtr->flags.isSelectable = 1;
395 mPtr->flags.isEditable = 1;
e7495baf dan1999-02-17 11:06:40 +0000396
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200397 W_SetViewBackgroundColor(mPtr->view, scr->darkGray);
e7495baf dan1999-02-17 11:06:40 +0000398
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200399 WMAddNotificationObserver(realizeObserver, mPtr, WMViewRealizedNotification, mPtr->view);
6d5f1817 kojima2000-07-14 05:48:35 +0000400
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200401 WMAddNotificationObserver(itemSelectObserver, mPtr, "EditMenuItemSelected", NULL);
e7495baf dan1999-02-17 11:06:40 +0000402
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200403 mPtr->items = WMCreateArray(4);
6830b057 dan2004-10-12 21:28:27 +0000404
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200405 WMCreateEventHandler(mPtr->view, ExposureMask | StructureNotifyMask, handleEvents, mPtr);
e7495baf dan1999-02-17 11:06:40 +0000406
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200407 if (title != NULL) {
408 item = WCreateEditMenuItem(mPtr, title, True);
e7495baf dan1999-02-17 11:06:40 +0000409
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200410 WMMapWidget(item);
411 WMAddToArray(mPtr->items, item);
e958044d kojima2000-07-10 22:49:07 +0000412
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200413 mPtr->flags.isTitled = 1;
414 }
e7495baf dan1999-02-17 11:06:40 +0000415
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200416 mPtr->itemHeight = WMFontHeight(scr->normalFont) + 6;
417 mPtr->titleHeight = WMFontHeight(scr->boldFont) + 8;
e7495baf dan1999-02-17 11:06:40 +0000418
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200419 updateMenuContents(mPtr);
6830b057 dan2004-10-12 21:28:27 +0000420
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200421 return mPtr;
e958044d kojima2000-07-10 22:49:07 +0000422}
e7495baf dan1999-02-17 11:06:40 +0000423
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200424WEditMenu *WCreateEditMenu(WMScreen * scr, char *title)
e958044d kojima2000-07-10 22:49:07 +0000425{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200426 return makeEditMenu(scr, NULL, title);
e958044d kojima2000-07-10 22:49:07 +0000427}
428
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200429WEditMenu *WCreateEditMenuPad(WMWidget * parent)
e958044d kojima2000-07-10 22:49:07 +0000430{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200431 return makeEditMenu(WMWidgetScreen(parent), parent, NULL);
e958044d kojima2000-07-10 22:49:07 +0000432}
433
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200434void WSetEditMenuDelegate(WEditMenu * mPtr, WEditMenuDelegate * delegate)
e958044d kojima2000-07-10 22:49:07 +0000435{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200436 mPtr->delegate = delegate;
e7495baf dan1999-02-17 11:06:40 +0000437}
438
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200439WEditMenuItem *WInsertMenuItemWithTitle(WEditMenu * mPtr, int index, char *title)
e7495baf dan1999-02-17 11:06:40 +0000440{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200441 WEditMenuItem *item;
e7495baf dan1999-02-17 11:06:40 +0000442
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200443 item = WCreateEditMenuItem(mPtr, title, False);
e7495baf dan1999-02-17 11:06:40 +0000444
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200445 WMMapWidget(item);
6d5f1817 kojima2000-07-14 05:48:35 +0000446
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200447 if (index >= WMGetArrayItemCount(mPtr->items)) {
448 WMAddToArray(mPtr->items, item);
449 } else {
450 if (index < 0)
451 index = 0;
452 if (mPtr->flags.isTitled)
453 index++;
454 WMInsertInArray(mPtr->items, index, item);
455 }
e7495baf dan1999-02-17 11:06:40 +0000456
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200457 updateMenuContents(mPtr);
e7495baf dan1999-02-17 11:06:40 +0000458
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200459 return item;
e958044d kojima2000-07-10 22:49:07 +0000460}
e7495baf dan1999-02-17 11:06:40 +0000461
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200462WEditMenuItem *WGetEditMenuItem(WEditMenu * mPtr, int index)
dcd44b17 kojima2000-07-15 22:00:41 +0000463{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200464 if (index >= WMGetArrayItemCount(mPtr->items))
465 return NULL;
046403db dan2001-04-15 01:22:56 +0000466
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200467 return WMGetFromArray(mPtr->items, index + (mPtr->flags.isTitled ? 1 : 0));
dcd44b17 kojima2000-07-15 22:00:41 +0000468}
469
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200470WEditMenuItem *WAddMenuItemWithTitle(WEditMenu * mPtr, char *title)
e958044d kojima2000-07-10 22:49:07 +0000471{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200472 return WInsertMenuItemWithTitle(mPtr, WMGetArrayItemCount(mPtr->items), title);
e958044d kojima2000-07-10 22:49:07 +0000473}
e7495baf dan1999-02-17 11:06:40 +0000474
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200475void WSetEditMenuTitle(WEditMenu * mPtr, char *title)
e958044d kojima2000-07-10 22:49:07 +0000476{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200477 WEditMenuItem *item;
6d5f1817 kojima2000-07-14 05:48:35 +0000478
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200479 item = WMGetFromArray(mPtr->items, 0);
6d5f1817 kojima2000-07-14 05:48:35 +0000480
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200481 wfree(item->label);
482 item->label = wstrdup(title);
6ec98009 kojima2000-07-16 06:29:12 +0000483
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200484 updateMenuContents(mPtr);
6ec98009 kojima2000-07-16 06:29:12 +0000485
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200486 WMRedisplayWidget(item);
6d5f1817 kojima2000-07-14 05:48:35 +0000487}
488
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200489char *WGetEditMenuTitle(WEditMenu * mPtr)
dcd44b17 kojima2000-07-15 22:00:41 +0000490{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200491 WEditMenuItem *item;
dcd44b17 kojima2000-07-15 22:00:41 +0000492
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200493 item = WMGetFromArray(mPtr->items, 0);
dcd44b17 kojima2000-07-15 22:00:41 +0000494
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200495 return item->label;
dcd44b17 kojima2000-07-15 22:00:41 +0000496}
497
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200498void WSetEditMenuAcceptsDrop(WEditMenu * mPtr, Bool flag)
6d5f1817 kojima2000-07-14 05:48:35 +0000499{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200500 mPtr->flags.acceptsDrop = flag;
e958044d kojima2000-07-10 22:49:07 +0000501}
e7495baf dan1999-02-17 11:06:40 +0000502
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200503void WSetEditMenuSubmenu(WEditMenu * mPtr, WEditMenuItem * item, WEditMenu * submenu)
e958044d kojima2000-07-10 22:49:07 +0000504{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200505 item->submenu = submenu;
506 submenu->parent = mPtr;
e958044d kojima2000-07-10 22:49:07 +0000507
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200508 paintEditMenuItem(item);
e958044d kojima2000-07-10 22:49:07 +0000509}
510
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200511WEditMenu *WGetEditMenuSubmenu(WEditMenu * mPtr, WEditMenuItem * item)
6d5f1817 kojima2000-07-14 05:48:35 +0000512{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200513 return item->submenu;
6d5f1817 kojima2000-07-14 05:48:35 +0000514}
515
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200516void WRemoveEditMenuItem(WEditMenu * mPtr, WEditMenuItem * item)
e958044d kojima2000-07-10 22:49:07 +0000517{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200518 if (WMRemoveFromArray(mPtr->items, item) != 0) {
519 updateMenuContents(mPtr);
520 }
e958044d kojima2000-07-10 22:49:07 +0000521}
e7495baf dan1999-02-17 11:06:40 +0000522
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200523void WSetEditMenuSelectable(WEditMenu * mPtr, Bool flag)
e958044d kojima2000-07-10 22:49:07 +0000524{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200525 mPtr->flags.isSelectable = flag;
e7495baf dan1999-02-17 11:06:40 +0000526}
527
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200528void WSetEditMenuEditable(WEditMenu * mPtr, Bool flag)
e7495baf dan1999-02-17 11:06:40 +0000529{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200530 mPtr->flags.isEditable = flag;
e958044d kojima2000-07-10 22:49:07 +0000531}
e7495baf dan1999-02-17 11:06:40 +0000532
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200533void WSetEditMenuIsFactory(WEditMenu * mPtr, Bool flag)
e958044d kojima2000-07-10 22:49:07 +0000534{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200535 mPtr->flags.isFactory = flag;
e958044d kojima2000-07-10 22:49:07 +0000536}
537
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200538void WSetEditMenuMinSize(WEditMenu * mPtr, WMSize size)
e958044d kojima2000-07-10 22:49:07 +0000539{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200540 mPtr->minSize.width = size.width;
541 mPtr->minSize.height = size.height;
e7495baf dan1999-02-17 11:06:40 +0000542}
543
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200544void WSetEditMenuMaxSize(WEditMenu * mPtr, WMSize size)
e7495baf dan1999-02-17 11:06:40 +0000545{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200546 mPtr->maxSize.width = size.width;
547 mPtr->maxSize.height = size.height;
e958044d kojima2000-07-10 22:49:07 +0000548}
549
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200550WMPoint WGetEditMenuLocationForSubmenu(WEditMenu * mPtr, WEditMenu * submenu)
e958044d kojima2000-07-10 22:49:07 +0000551{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200552 WMArrayIterator iter;
553 WEditMenuItem *item;
554 int y;
555
556 if (mPtr->flags.isTitled)
557 y = -mPtr->titleHeight;
558 else
559 y = 0;
560 WM_ITERATE_ARRAY(mPtr->items, item, iter) {
561 if (item->submenu == submenu) {
562 WMPoint pt = WMGetViewScreenPosition(mPtr->view);
563
564 return wmkpoint(pt.x + mPtr->view->size.width, pt.y + y);
565 }
566 y += W_VIEW_HEIGHT(item->view);
567 }
568
569 puts("invalid submenu passed to WGetEditMenuLocationForSubmenu()");
570
571 return wmkpoint(0, 0);
e958044d kojima2000-07-10 22:49:07 +0000572}
573
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200574static void closeMenuAction(WMWidget * w, void *data)
bb6acdad kojima2000-07-14 15:16:46 +0000575{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200576 WEditMenu *menu = (WEditMenu *) data;
bb6acdad kojima2000-07-14 15:16:46 +0000577
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200578 WMAddIdleHandler(WMDestroyWidget, menu->closeB);
579 menu->closeB = NULL;
bb6acdad kojima2000-07-14 15:16:46 +0000580
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200581 WEditMenuHide(menu);
bb6acdad kojima2000-07-14 15:16:46 +0000582}
583
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200584void WTearOffEditMenu(WEditMenu * menu, WEditMenu * submenu)
6d5f1817 kojima2000-07-14 05:48:35 +0000585{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200586 WEditMenuItem *item;
6830b057 dan2004-10-12 21:28:27 +0000587
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200588 submenu->flags.isTornOff = 1;
6830b057 dan2004-10-12 21:28:27 +0000589
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200590 item = (WEditMenuItem *) WMGetFromArray(submenu->items, 0);
6830b057 dan2004-10-12 21:28:27 +0000591
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200592 submenu->closeB = WMCreateCommandButton(item);
593 WMResizeWidget(submenu->closeB, 15, 15);
594 WMMoveWidget(submenu->closeB, W_VIEW(submenu)->size.width - 20, 3);
595 WMRealizeWidget(submenu->closeB);
596 WMSetButtonText(submenu->closeB, "X");
597 WMSetButtonAction(submenu->closeB, closeMenuAction, submenu);
598 WMMapWidget(submenu->closeB);
6d5f1817 kojima2000-07-14 05:48:35 +0000599
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200600 if (menu->selectedItem && menu->selectedItem->submenu == submenu)
601 deselectItem(menu);
6d5f1817 kojima2000-07-14 05:48:35 +0000602}
6830b057 dan2004-10-12 21:28:27 +0000603
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200604Bool WEditMenuIsTornOff(WEditMenu * mPtr)
e958044d kojima2000-07-10 22:49:07 +0000605{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200606 return mPtr->flags.isTornOff;
e7495baf dan1999-02-17 11:06:40 +0000607}
608
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200609void WEditMenuHide(WEditMenu * mPtr)
9c9f7e6c kojima2000-09-25 18:40:56 +0000610{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200611 WEditMenuItem *item;
612 int i = 0;
613
614 if (WMWidgetIsMapped(mPtr)) {
615 WMUnmapWidget(mPtr);
616 mPtr->flags.wasMapped = 1;
617 } else {
618 mPtr->flags.wasMapped = 0;
619 }
620 while ((item = WGetEditMenuItem(mPtr, i++))) {
621 WEditMenu *submenu;
622
623 submenu = WGetEditMenuSubmenu(mPtr, item);
624 if (submenu) {
625 WEditMenuHide(submenu);
626 }
627 }
9c9f7e6c kojima2000-09-25 18:40:56 +0000628}
629
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200630void WEditMenuUnhide(WEditMenu * mPtr)
9c9f7e6c kojima2000-09-25 18:40:56 +0000631{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200632 WEditMenuItem *item;
633 int i = 0;
634
635 if (mPtr->flags.wasMapped) {
636 WMMapWidget(mPtr);
637 }
638 while ((item = WGetEditMenuItem(mPtr, i++))) {
639 WEditMenu *submenu;
640
641 submenu = WGetEditMenuSubmenu(mPtr, item);
642 if (submenu) {
643 WEditMenuUnhide(submenu);
644 }
645 }
9c9f7e6c kojima2000-09-25 18:40:56 +0000646}
647
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200648void WEditMenuShowAt(WEditMenu * menu, int x, int y)
9c9f7e6c kojima2000-09-25 18:40:56 +0000649{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200650 XSizeHints *hints;
9c9f7e6c kojima2000-09-25 18:40:56 +0000651
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200652 hints = XAllocSizeHints();
9c9f7e6c kojima2000-09-25 18:40:56 +0000653
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200654 hints->flags = USPosition;
655 hints->x = x;
656 hints->y = y;
9c9f7e6c kojima2000-09-25 18:40:56 +0000657
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200658 WMMoveWidget(menu, x, y);
659 XSetWMNormalHints(W_VIEW_DISPLAY(menu->view), W_VIEW_DRAWABLE(menu->view), hints);
660 XFree(hints);
4193d226 dan2000-09-26 00:35:33 +0000661
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200662 WMMapWidget(menu);
9c9f7e6c kojima2000-09-25 18:40:56 +0000663}
664
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200665static void updateMenuContents(WEditMenu * mPtr)
e7495baf dan1999-02-17 11:06:40 +0000666{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200667 int newW, newH;
668 int w;
669 int i;
670 int iheight = mPtr->itemHeight;
671 int offs = 1;
672 WMArrayIterator iter;
673 WEditMenuItem *item;
674
675 newW = 0;
676 newH = offs;
677
678 i = 0;
679 WM_ITERATE_ARRAY(mPtr->items, item, iter) {
680 w = getItemTextWidth(item);
681
682 newW = WMAX(w, newW);
683
684 WMMoveWidget(item, offs, newH);
685 if (i == 0 && mPtr->flags.isTitled) {
686 newH += mPtr->titleHeight;
687 } else {
688 newH += iheight;
689 }
690 i = 1;
691 }
692
693 newW += iheight + 10;
694 newH--;
695
696 if (mPtr->minSize.width)
697 newW = WMAX(newW, mPtr->minSize.width);
698 if (mPtr->maxSize.width)
699 newW = WMIN(newW, mPtr->maxSize.width);
700
701 if (mPtr->minSize.height)
702 newH = WMAX(newH, mPtr->minSize.height);
703 if (mPtr->maxSize.height)
704 newH = WMIN(newH, mPtr->maxSize.height);
705
706 if (W_VIEW(mPtr)->size.width == newW && mPtr->view->size.height == newH + 1)
707 return;
708
709 W_ResizeView(mPtr->view, newW, newH + 1);
710
711 if (mPtr->closeB)
712 WMMoveWidget(mPtr->closeB, newW - 20, 3);
713
714 newW -= 2 * offs;
715
716 i = 0;
717 WM_ITERATE_ARRAY(mPtr->items, item, iter) {
718 if (i == 0 && mPtr->flags.isTitled) {
719 WMResizeWidget(item, newW, mPtr->titleHeight);
720 } else {
721 WMResizeWidget(item, newW, iheight);
722 }
723 i = 1;
724 }
e7495baf dan1999-02-17 11:06:40 +0000725}
726
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200727static void deselectItem(WEditMenu * menu)
6d5f1817 kojima2000-07-14 05:48:35 +0000728{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200729 WEditMenu *submenu;
730 WEditMenuItem *item = menu->selectedItem;
6830b057 dan2004-10-12 21:28:27 +0000731
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200732 highlightItem(item, False);
6830b057 dan2004-10-12 21:28:27 +0000733
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200734 if (menu->delegate && menu->delegate->itemDeselected) {
735 (*menu->delegate->itemDeselected) (menu->delegate, menu, item);
736 }
737 submenu = item->submenu;
6d5f1817 kojima2000-07-14 05:48:35 +0000738
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200739 if (submenu && !WEditMenuIsTornOff(submenu)) {
740 WEditMenuHide(submenu);
741 }
6830b057 dan2004-10-12 21:28:27 +0000742
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200743 menu->selectedItem = NULL;
6d5f1817 kojima2000-07-14 05:48:35 +0000744}
745
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200746static void selectItem(WEditMenu * menu, WEditMenuItem * item)
e7495baf dan1999-02-17 11:06:40 +0000747{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200748 if (!menu->flags.isSelectable || menu->selectedItem == item) {
749 return;
750 }
751 if (menu->selectedItem) {
752 deselectItem(menu);
753 }
e958044d kojima2000-07-10 22:49:07 +0000754
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200755 if (menu->flags.isEditing) {
756 stopEditItem(menu, False);
757 }
e958044d kojima2000-07-10 22:49:07 +0000758
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200759 if (item && !item->flags.isTitle) {
760 highlightItem(item, True);
6830b057 dan2004-10-12 21:28:27 +0000761
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200762 if (item->submenu && !W_VIEW_MAPPED(item->submenu->view)) {
763 WMPoint pt;
e7495baf dan1999-02-17 11:06:40 +0000764
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200765 pt = WGetEditMenuLocationForSubmenu(menu, item->submenu);
6d5f1817 kojima2000-07-14 05:48:35 +0000766
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200767 WEditMenuShowAt(item->submenu, pt.x, pt.y);
6d5f1817 kojima2000-07-14 05:48:35 +0000768
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200769 item->submenu->flags.isTornOff = 0;
770 }
6d5f1817 kojima2000-07-14 05:48:35 +0000771
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200772 WMPostNotificationName("EditMenuItemSelected", menu, NULL);
6830b057 dan2004-10-12 21:28:27 +0000773
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200774 if (menu->delegate && menu->delegate->itemSelected) {
775 (*menu->delegate->itemSelected) (menu->delegate, menu, item);
776 }
777 }
e958044d kojima2000-07-10 22:49:07 +0000778
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200779 menu->selectedItem = item;
e7495baf dan1999-02-17 11:06:40 +0000780}
781
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200782static void paintMenu(WEditMenu * mPtr)
e7495baf dan1999-02-17 11:06:40 +0000783{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200784 W_View *view = mPtr->view;
6830b057 dan2004-10-12 21:28:27 +0000785
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200786 W_DrawRelief(W_VIEW_SCREEN(view), W_VIEW_DRAWABLE(view), 0, 0,
787 W_VIEW_WIDTH(view), W_VIEW_HEIGHT(view), WRSimple);
e7495baf dan1999-02-17 11:06:40 +0000788}
789
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200790static void handleEvents(XEvent * event, void *data)
e7495baf dan1999-02-17 11:06:40 +0000791{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200792 WEditMenu *mPtr = (WEditMenu *) data;
793
794 switch (event->type) {
795 case DestroyNotify:
796 destroyEditMenu(mPtr);
797 break;
798
799 case Expose:
800 if (event->xexpose.count == 0)
801 paintMenu(mPtr);
802 break;
803 }
e7495baf dan1999-02-17 11:06:40 +0000804}
805
e958044d kojima2000-07-10 22:49:07 +0000806/* -------------------------- Menu Label Editing ------------------------ */
807
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200808static void stopEditItem(WEditMenu * menu, Bool apply)
e7495baf dan1999-02-17 11:06:40 +0000809{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200810 char *text;
6830b057 dan2004-10-12 21:28:27 +0000811
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200812 if (apply) {
813 text = WMGetTextFieldText(menu->tfield);
6830b057 dan2004-10-12 21:28:27 +0000814
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200815 wfree(menu->selectedItem->label);
816 menu->selectedItem->label = wstrdup(text);
e7495baf dan1999-02-17 11:06:40 +0000817
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200818 updateMenuContents(menu);
dcd44b17 kojima2000-07-15 22:00:41 +0000819
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200820 if (menu->delegate && menu->delegate->itemEdited) {
821 (*menu->delegate->itemEdited) (menu->delegate, menu, menu->selectedItem);
822 }
dcd44b17 kojima2000-07-15 22:00:41 +0000823
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200824 }
825 WMUnmapWidget(menu->tfield);
826 menu->flags.isEditing = 0;
e958044d kojima2000-07-10 22:49:07 +0000827}
828
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200829static void textEndedEditing(struct WMTextFieldDelegate *self, WMNotification * notif)
e958044d kojima2000-07-10 22:49:07 +0000830{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200831 WEditMenu *menu = (WEditMenu *) self->data;
832 int reason;
833 int i;
834 WEditMenuItem *item;
835
836 if (!menu->flags.isEditing)
837 return;
838
839 reason = (int)(uintptr_t) WMGetNotificationClientData(notif);
840
841 switch (reason) {
842 case WMEscapeTextMovement:
843 stopEditItem(menu, False);
844 break;
845
846 case WMReturnTextMovement:
847 stopEditItem(menu, True);
848 break;
849
850 case WMTabTextMovement:
851 stopEditItem(menu, True);
852
853 i = WMGetFirstInArray(menu->items, menu->selectedItem);
854 item = WMGetFromArray(menu->items, i + 1);
855 if (item != NULL) {
856 selectItem(menu, item);
857 editItemLabel(item);
858 }
859 break;
860
861 case WMBacktabTextMovement:
862 stopEditItem(menu, True);
863
864 i = WMGetFirstInArray(menu->items, menu->selectedItem);
865 item = WMGetFromArray(menu->items, i - 1);
866 if (item != NULL) {
867 selectItem(menu, item);
868 editItemLabel(item);
869 }
870 break;
871 }
e7495baf dan1999-02-17 11:06:40 +0000872}
873
e958044d kojima2000-07-10 22:49:07 +0000874static WMTextFieldDelegate textFieldDelegate = {
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200875 NULL,
876 NULL,
877 NULL,
878 textEndedEditing,
879 NULL,
880 NULL
e958044d kojima2000-07-10 22:49:07 +0000881};
882
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200883static void editItemLabel(WEditMenuItem * item)
e7495baf dan1999-02-17 11:06:40 +0000884{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200885 WEditMenu *mPtr = item->parent;
886 WMTextField *tf;
6830b057 dan2004-10-12 21:28:27 +0000887
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200888 if (!mPtr->flags.isEditable) {
889 return;
890 }
e7495baf dan1999-02-17 11:06:40 +0000891
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200892 if (!mPtr->tfield) {
893 mPtr->tfield = WMCreateTextField(mPtr);
894 WMSetTextFieldBeveled(mPtr->tfield, False);
895 WMRealizeWidget(mPtr->tfield);
1a7c397d kojima2000-07-16 04:05:49 +0000896
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200897 mPtr->tdelegate = wmalloc(sizeof(WMTextFieldDelegate));
898 memcpy(mPtr->tdelegate, &textFieldDelegate, sizeof(WMTextFieldDelegate));
e7495baf dan1999-02-17 11:06:40 +0000899
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200900 mPtr->tdelegate->data = mPtr;
6830b057 dan2004-10-12 21:28:27 +0000901
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200902 WMSetTextFieldDelegate(mPtr->tfield, mPtr->tdelegate);
903 }
904 tf = mPtr->tfield;
e7495baf dan1999-02-17 11:06:40 +0000905
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200906 WMSetTextFieldText(tf, item->label);
907 WMSelectTextFieldRange(tf, wmkrange(0, strlen(item->label)));
908 WMResizeWidget(tf, mPtr->view->size.width, mPtr->itemHeight);
909 WMMoveWidget(tf, 0, item->view->pos.y);
910 WMMapWidget(tf);
911 WMSetFocusToWidget(tf);
1a7c397d kojima2000-07-16 04:05:49 +0000912
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200913 mPtr->flags.isEditing = 1;
e958044d kojima2000-07-10 22:49:07 +0000914}
915
e958044d kojima2000-07-10 22:49:07 +0000916/* -------------------------------------------------- */
917
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200918static void slideWindow(Display * dpy, Window win, int srcX, int srcY, int dstX, int dstY)
e958044d kojima2000-07-10 22:49:07 +0000919{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200920 double x, y, dx, dy;
921 int i;
922 int iterations;
e958044d kojima2000-07-10 22:49:07 +0000923
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200924 iterations = WMIN(25, WMAX(abs(dstX - srcX), abs(dstY - srcY)));
6830b057 dan2004-10-12 21:28:27 +0000925
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200926 x = srcX;
927 y = srcY;
6830b057 dan2004-10-12 21:28:27 +0000928
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200929 dx = (double)(dstX - srcX) / iterations;
930 dy = (double)(dstY - srcY) / iterations;
e958044d kojima2000-07-10 22:49:07 +0000931
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200932 for (i = 0; i <= iterations; i++) {
933 XMoveWindow(dpy, win, x, y);
934 XFlush(dpy);
6830b057 dan2004-10-12 21:28:27 +0000935
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200936 wusleep(800);
6830b057 dan2004-10-12 21:28:27 +0000937
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200938 x += dx;
939 y += dy;
940 }
e958044d kojima2000-07-10 22:49:07 +0000941}
942
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200943static int errorHandler(Display * d, XErrorEvent * ev)
e958044d kojima2000-07-10 22:49:07 +0000944{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200945 /* just ignore */
946 return 0;
e958044d kojima2000-07-10 22:49:07 +0000947}
948
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200949static WEditMenu *findMenuInWindow(Display * dpy, Window toplevel, int x, int y)
e958044d kojima2000-07-10 22:49:07 +0000950{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200951 Window foo, bar;
952 Window *children;
953 unsigned nchildren;
954 int i;
955 WEditMenu *menu;
956 WMView *view;
957 int (*oldHandler) (Display *, XErrorEvent *);
958
959 view = W_GetViewForXWindow(dpy, toplevel);
960 if (view && view->self && WMWidgetClass(view->self) == EditMenuClass) {
961 menu = (WEditMenu *) view->self;
962 if (menu->flags.acceptsDrop) {
963 return menu;
964 }
965 }
966
967 if (!XQueryTree(dpy, toplevel, &foo, &bar, &children, &nchildren) || children == NULL) {
968 return NULL;
969 }
970
971 oldHandler = XSetErrorHandler(errorHandler);
972
973 /* first window that contains the point is the one */
974 for (i = nchildren - 1; i >= 0; i--) {
975 XWindowAttributes attr;
976
977 if (XGetWindowAttributes(dpy, children[i], &attr)
978 && attr.map_state == IsViewable
979 && x >= attr.x && y >= attr.y && x < attr.x + attr.width && y < attr.y + attr.height) {
980 Window tmp;
981
982 tmp = children[i];
983
984 menu = findMenuInWindow(dpy, tmp, x - attr.x, y - attr.y);
985 if (menu) {
986 XFree(children);
987 return menu;
988 }
989 }
990 }
991
992 XSetErrorHandler(oldHandler);
993
994 XFree(children);
995 return NULL;
e958044d kojima2000-07-10 22:49:07 +0000996}
997
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200998static void handleDragOver(WEditMenu * menu, WMView * view, WEditMenuItem * item, int x, int y)
e958044d kojima2000-07-10 22:49:07 +0000999{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001000 WMScreen *scr = W_VIEW_SCREEN(menu->view);
1001 Window blaw;
1002 int mx, my;
1003 int offs;
e958044d kojima2000-07-10 22:49:07 +00001004
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +02001005 XTranslateCoordinates(scr->display, W_VIEW_DRAWABLE(menu->view), scr->rootWin, 0, 0, &mx, &my, &blaw);
e958044d kojima2000-07-10 22:49:07 +00001006
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001007 offs = menu->flags.standalone ? 0 : 1;
1008
1009 W_MoveView(view, mx + offs, y);
1010 if (view->size.width != menu->view->size.width) {
1011 W_ResizeView(view, menu->view->size.width - 2 * offs, menu->itemHeight);
1012 W_ResizeView(item->view, menu->view->size.width - 2 * offs, menu->itemHeight);
1013 }
e958044d kojima2000-07-10 22:49:07 +00001014}
e7495baf dan1999-02-17 11:06:40 +00001015
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001016static void handleItemDrop(WEditMenu * menu, WEditMenuItem * item, int x, int y)
1017{
1018 WMScreen *scr = W_VIEW_SCREEN(menu->view);
1019 Window blaw;
1020 int mx, my;
1021 int index;
1022
1023 XTranslateCoordinates(scr->display, W_VIEW_DRAWABLE(menu->view), scr->rootWin, 0, 0, &mx, &my, &blaw);
1024
1025 index = y - my;
1026 if (menu->flags.isTitled) {
1027 index -= menu->titleHeight;
1028 }
1029 index = (index + menu->itemHeight / 2) / menu->itemHeight;
1030 if (index < 0)
1031 index = 0;
1032
1033 if (menu->flags.isTitled) {
1034 index++;
1035 }
1036
1037 if (index > WMGetArrayItemCount(menu->items)) {
1038 WMAddToArray(menu->items, item);
1039 } else {
1040 WMInsertInArray(menu->items, index, item);
1041 }
1042
1043 W_ReparentView(item->view, menu->view, 0, index * menu->itemHeight);
1044
1045 item->parent = menu;
1046 if (item->submenu) {
1047 item->submenu->parent = menu;
1048 }
1049
1050 updateMenuContents(menu);
1051}
e7495baf dan1999-02-17 11:06:40 +00001052
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +02001053static void dragMenu(WEditMenu * menu)
e958044d kojima2000-07-10 22:49:07 +00001054{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001055 WMScreen *scr = W_VIEW_SCREEN(menu->view);
1056 XEvent ev;
1057 Bool done = False;
1058 int dx, dy;
1059 unsigned blau;
1060 Window blaw;
6830b057 dan2004-10-12 21:28:27 +00001061
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +02001062 XGetGeometry(scr->display, W_VIEW_DRAWABLE(menu->view), &blaw, &dx, &dy, &blau, &blau, &blau, &blau);
6d5f1817 kojima2000-07-14 05:48:35 +00001063
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +02001064 XTranslateCoordinates(scr->display, W_VIEW_DRAWABLE(menu->view), scr->rootWin, dx, dy, &dx, &dy, &blaw);
6d5f1817 kojima2000-07-14 05:48:35 +00001065
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001066 dx = menu->dragX - dx;
1067 dy = menu->dragY - dy;
6830b057 dan2004-10-12 21:28:27 +00001068
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001069 XGrabPointer(scr->display, scr->rootWin, False,
1070 ButtonReleaseMask | ButtonMotionMask,
1071 GrabModeAsync, GrabModeAsync, None, scr->defaultCursor, CurrentTime);
6830b057 dan2004-10-12 21:28:27 +00001072
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001073 if (menu->parent)
1074 WTearOffEditMenu(menu->parent, menu);
e7495baf dan1999-02-17 11:06:40 +00001075
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001076 while (!done) {
1077 WMNextEvent(scr->display, &ev);
6830b057 dan2004-10-12 21:28:27 +00001078
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001079 switch (ev.type) {
1080 case ButtonRelease:
1081 done = True;
1082 break;
6830b057 dan2004-10-12 21:28:27 +00001083
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001084 case MotionNotify:
1085 while (XCheckMaskEvent(scr->display, ButtonMotionMask, &ev)) ;
6830b057 dan2004-10-12 21:28:27 +00001086
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001087 WMMoveWidget(menu, ev.xmotion.x_root - dx, ev.xmotion.y_root - dy);
1088 break;
6830b057 dan2004-10-12 21:28:27 +00001089
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001090 default:
1091 WMHandleEvent(&ev);
1092 break;
1093 }
1094 }
e958044d kojima2000-07-10 22:49:07 +00001095
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +02001096 XUngrabPointer(scr->display, CurrentTime);
e958044d kojima2000-07-10 22:49:07 +00001097}
e7495baf dan1999-02-17 11:06:40 +00001098
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +02001099static WEditMenuItem *duplicateItem(WEditMenuItem * item)
1a7c397d kojima2000-07-16 04:05:49 +00001100{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +02001101 WEditMenuItem *nitem;
6830b057 dan2004-10-12 21:28:27 +00001102
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001103 nitem = WCreateEditMenuItem(item->parent, item->label, False);
1104 if (item->pixmap)
1105 nitem->pixmap = WMRetainPixmap(item->pixmap);
1a7c397d kojima2000-07-16 04:05:49 +00001106
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +02001107 return nitem;
1a7c397d kojima2000-07-16 04:05:49 +00001108}
1109
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +02001110static WEditMenu *duplicateMenu(WEditMenu * menu)
6d5f1817 kojima2000-07-14 05:48:35 +00001111{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001112 WEditMenu *nmenu;
1113 WEditMenuItem *item;
1114 WMArrayIterator iter;
1115 Bool first = menu->flags.isTitled;
1a7c397d kojima2000-07-16 04:05:49 +00001116
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +02001117 nmenu = WCreateEditMenu(WMWidgetScreen(menu), WGetEditMenuTitle(menu));
6d5f1817 kojima2000-07-14 05:48:35 +00001118
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001119 memcpy(&nmenu->flags, &menu->flags, sizeof(menu->flags));
1120 nmenu->delegate = menu->delegate;
6830b057 dan2004-10-12 21:28:27 +00001121
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001122 WM_ITERATE_ARRAY(menu->items, item, iter) {
1123 WEditMenuItem *nitem;
6830b057 dan2004-10-12 21:28:27 +00001124
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001125 if (first) {
1126 first = False;
1127 continue;
1128 }
6830b057 dan2004-10-12 21:28:27 +00001129
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001130 nitem = WAddMenuItemWithTitle(nmenu, item->label);
1131 if (item->pixmap)
1132 WSetEditMenuItemImage(nitem, item->pixmap);
6830b057 dan2004-10-12 21:28:27 +00001133
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001134 if (menu->delegate && menu->delegate->itemCloned) {
1135 (*menu->delegate->itemCloned) (menu->delegate, menu, item, nitem);
1136 }
1137 }
dcd44b17 kojima2000-07-15 22:00:41 +00001138
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +02001139 WMRealizeWidget(nmenu);
dcd44b17 kojima2000-07-15 22:00:41 +00001140
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +02001141 return nmenu;
dcd44b17 kojima2000-07-15 22:00:41 +00001142}
1143
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +02001144static void dragItem(WEditMenu * menu, WEditMenuItem * item, Bool copy)
e958044d kojima2000-07-10 22:49:07 +00001145{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001146 static XColor black = { 0, 0, 0, 0, DoRed | DoGreen | DoBlue };
1147 static XColor green = { 0x0045b045, 0x4500, 0xb000, 0x4500, DoRed | DoGreen | DoBlue };
1148 static XColor back = { 0, 0xffff, 0xffff, 0xffff, DoRed | DoGreen | DoBlue };
1149 Display *dpy = W_VIEW_DISPLAY(menu->view);
1150 WMScreen *scr = W_VIEW_SCREEN(menu->view);
1151 int x, y;
1152 int dx, dy;
1153 Bool done = False;
1154 Window blaw;
1155 int blai;
1156 unsigned blau;
1157 Window win;
1158 WMView *dview;
1159 int orix, oriy;
1160 Bool enteredMenu = False;
1161 WMSize oldSize = item->view->size;
1162 WEditMenuItem *dritem = item;
1163 WEditMenu *dmenu = NULL;
1164
1165 if (item->flags.isTitle) {
1166 WMRaiseWidget(menu);
1167
1168 dragMenu(menu);
1169
1170 return;
1171 }
1172
1173 selectItem(menu, NULL);
1174
1175 win = scr->rootWin;
1176
1177 XTranslateCoordinates(dpy, W_VIEW_DRAWABLE(item->view), win, 0, 0, &orix, &oriy, &blaw);
1178
1179 dview = W_CreateUnmanagedTopView(scr);
1180 W_SetViewBackgroundColor(dview, scr->black);
1181 W_ResizeView(dview, W_VIEW_WIDTH(item->view), W_VIEW_HEIGHT(item->view));
1182 W_MoveView(dview, orix, oriy);
1183 W_RealizeView(dview);
1184
1185 if (menu->flags.isFactory || copy) {
1186 dritem = duplicateItem(item);
1187
1188 W_ReparentView(dritem->view, dview, 0, 0);
1189 WMResizeWidget(dritem, oldSize.width, oldSize.height);
1190 WMRealizeWidget(dritem);
1191 WMMapWidget(dritem);
1192 } else {
1193 W_ReparentView(item->view, dview, 0, 0);
1194 }
1195
1196 W_MapView(dview);
1197
1198 dx = menu->dragX - orix;
1199 dy = menu->dragY - oriy;
1200
1201 XGrabPointer(dpy, scr->rootWin, False,
1202 ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
1203 GrabModeAsync, GrabModeAsync, None, scr->defaultCursor, CurrentTime);
1204
1205 if (menu->flags.acceptsDrop)
1206 XRecolorCursor(dpy, scr->defaultCursor, &green, &back);
1207
1208 while (!done) {
1209 XEvent ev;
1210
1211 WMNextEvent(dpy, &ev);
1212
1213 switch (ev.type) {
1214 case MotionNotify:
1215 while (XCheckMaskEvent(dpy, ButtonMotionMask, &ev)) ;
1216
1217 XQueryPointer(dpy, win, &blaw, &blaw, &blai, &blai, &x, &y, &blau);
1218
1219 dmenu = findMenuInWindow(dpy, win, x, y);
1220
1221 if (dmenu) {
1222 handleDragOver(dmenu, dview, dritem, x - dx, y - dy);
1223 if (!enteredMenu) {
1224 enteredMenu = True;
1225 XRecolorCursor(dpy, scr->defaultCursor, &green, &back);
1226 }
1227 } else {
1228 if (enteredMenu) {
1229 W_ResizeView(dview, oldSize.width, oldSize.height);
1230 W_ResizeView(dritem->view, oldSize.width, oldSize.height);
1231 enteredMenu = False;
1232 XRecolorCursor(dpy, scr->defaultCursor, &black, &back);
1233 }
1234 W_MoveView(dview, x - dx, y - dy);
1235 }
1236
1237 break;
1238
1239 case ButtonRelease:
1240 done = True;
1241 break;
1242
1243 default:
1244 WMHandleEvent(&ev);
1245 break;
1246 }
1247 }
1248 XRecolorCursor(dpy, scr->defaultCursor, &black, &back);
1249
1250 XUngrabPointer(dpy, CurrentTime);
1251
1252 if (!enteredMenu) {
1253 Bool rem = True;
1254
1255 if (!menu->flags.isFactory && !copy) {
1256 W_UnmapView(dview);
1257 if (menu->delegate && menu->delegate->shouldRemoveItem) {
1258 rem = (*menu->delegate->shouldRemoveItem) (menu->delegate, menu, item);
1259 }
1260 W_MapView(dview);
1261 }
1262
1263 if (!rem || menu->flags.isFactory || copy) {
1264 slideWindow(dpy, W_VIEW_DRAWABLE(dview), x - dx, y - dy, orix, oriy);
1265
1266 if (!menu->flags.isFactory && !copy) {
1267 WRemoveEditMenuItem(menu, dritem);
1268 handleItemDrop(dmenu ? dmenu : menu, dritem, orix, oriy);
1269 }
1270 } else {
1271 WRemoveEditMenuItem(menu, dritem);
1272 }
1273 } else {
1274 WRemoveEditMenuItem(menu, dritem);
1275
1276 if (menu->delegate && menu->delegate->itemCloned && (menu->flags.isFactory || copy)) {
1277 (*menu->delegate->itemCloned) (menu->delegate, menu, item, dritem);
1278 }
1279
1280 handleItemDrop(dmenu, dritem, x - dy, y - dy);
1281
1282 if (item->submenu && (menu->flags.isFactory || copy)) {
1283 WEditMenu *submenu;
1284
1285 submenu = duplicateMenu(item->submenu);
1286 WSetEditMenuSubmenu(dmenu, dritem, submenu);
1287 }
1288 }
1289
1290 /* can't destroy now because we're being called from
1291 * the event handler of the item. and destroying now,
1292 * would mean destroying the item too in some cases.
1293 */
1294 WMAddIdleHandler((WMCallback *) W_DestroyView, dview);
e958044d kojima2000-07-10 22:49:07 +00001295}
e7495baf dan1999-02-17 11:06:40 +00001296
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +02001297static void handleItemClick(XEvent * event, void *data)
e958044d kojima2000-07-10 22:49:07 +00001298{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001299 WEditMenuItem *item = (WEditMenuItem *) data;
1300 WEditMenu *menu = item->parent;
1301
1302 switch (event->type) {
1303 case ButtonPress:
1304 selectItem(menu, item);
1305
1306 if (WMIsDoubleClick(event)) {
1307 editItemLabel(item);
1308 }
1309
1310 menu->flags.isDragging = 1;
1311 menu->dragX = event->xbutton.x_root;
1312 menu->dragY = event->xbutton.y_root;
1313 break;
1314
1315 case ButtonRelease:
1316 menu->flags.isDragging = 0;
1317 break;
1318
1319 case MotionNotify:
1320 if (menu->flags.isDragging) {
1321 if (abs(event->xbutton.x_root - menu->dragX) > 5
1322 || abs(event->xbutton.y_root - menu->dragY) > 5) {
1323 menu->flags.isDragging = 0;
1324 dragItem(menu, item, event->xbutton.state & ControlMask);
1325 }
1326 }
1327 break;
1328 }
e7495baf dan1999-02-17 11:06:40 +00001329}
1330
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +02001331static void destroyEditMenu(WEditMenu * mPtr)
e7495baf dan1999-02-17 11:06:40 +00001332{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +02001333 WMRemoveNotificationObserver(mPtr);
e7495baf dan1999-02-17 11:06:40 +00001334
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +02001335 WMFreeArray(mPtr->items);
6830b057 dan2004-10-12 21:28:27 +00001336
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +02001337 wfree(mPtr->tdelegate);
6830b057 dan2004-10-12 21:28:27 +00001338
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +02001339 wfree(mPtr);
e7495baf dan1999-02-17 11:06:40 +00001340}