1 /* Menu.c- menu definition
3 * WPrefs - Window Maker Preferences Program
5 * Copyright (c) 2000 Alfredo K. Kojima
7 * 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.
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.
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
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
28 #include <X11/keysym.h>
29 #include <X11/cursorfont.h>
46 #define MAX_SECTION_SIZE 4
48 typedef struct _Panel
{
54 CallbackRec callbacks
;
64 WMPixmap
*markerPix
[LastInfo
];
77 WMTextField
*commandT
; /* command to run */
78 WMButton
*xtermC
; /* inside xterm? */
90 WMTextField
*dcommandT
;
106 Bool dontAsk
; /* whether to comfirm submenu remove */
111 /* about the currently selected item */
112 WEditMenuItem
*currentItem
;
113 InfoType currentType
;
114 WMWidget
*sections
[LastInfo
][MAX_SECTION_SIZE
];
146 static char *commandNames
[] = {
163 #define NEW(type) memset(wmalloc(sizeof(type)), 0, sizeof(type))
166 #define ICON_FILE "menus"
170 static void showData(_Panel
*panel
);
173 static void updateMenuItem(_Panel
*panel
, WEditMenuItem
*item
,
174 WMWidget
*changedWidget
);
176 static void menuItemSelected(struct WEditMenuDelegate
*delegate
,
177 WEditMenu
*menu
, WEditMenuItem
*item
);
179 static void menuItemDeselected(struct WEditMenuDelegate
*delegate
,
180 WEditMenu
*menu
, WEditMenuItem
*item
);
182 static void menuItemCloned(struct WEditMenuDelegate
*delegate
, WEditMenu
*menu
,
183 WEditMenuItem
*origItem
, WEditMenuItem
*newItem
);
185 static void menuItemEdited(struct WEditMenuDelegate
*delegate
, WEditMenu
*menu
,
186 WEditMenuItem
*item
);
188 static Bool
shouldRemoveItem(struct WEditMenuDelegate
*delegate
,
189 WEditMenu
*menu
, WEditMenuItem
*item
);
192 static void freeItemData(ItemData
*data
);
196 static WEditMenuDelegate menuDelegate
= {
207 dataChanged(void *self
, WMNotification
*notif
)
209 _Panel
*panel
= (_Panel
*)self
;
210 WEditMenuItem
*item
= panel
->currentItem
;
211 WMWidget
*w
= (WMWidget
*)WMGetNotificationObject(notif
);
213 updateMenuItem(panel
, item
, w
);
218 buttonClicked(WMWidget
*w
, void *data
)
220 _Panel
*panel
= (_Panel
*)data
;
221 WEditMenuItem
*item
= panel
->currentItem
;
223 updateMenuItem(panel
, item
, w
);
228 icommandLClicked(WMWidget
*w
, void *data
)
230 _Panel
*panel
= (_Panel
*)data
;
233 cmd
= WMGetListSelectedItemRow(w
);
234 if (cmd
== 3 || cmd
== 4) {
235 WMMapWidget(panel
->quickB
);
237 WMUnmapWidget(panel
->quickB
);
240 WMMapWidget(panel
->paramF
);
242 WMUnmapWidget(panel
->paramF
);
255 captureShortcut(Display
*dpy
, _Panel
*panel
)
262 while (panel
->capturing
) {
263 XAllowEvents(dpy
, AsyncKeyboard
, CurrentTime
);
264 WMNextEvent(dpy
, &ev
);
265 if (ev
.type
==KeyPress
&& ev
.xkey
.keycode
!=0) {
266 ksym
= XKeycodeToKeysym(dpy
, ev
.xkey
.keycode
, 0);
267 if (!IsModifierKey(ksym
)) {
268 key
=XKeysymToString(ksym
);
269 panel
->capturing
= 0;
281 if (ev
.xkey
.state
& ControlMask
) {
282 strcat(buffer
, "Control+");
284 if (ev
.xkey
.state
& ShiftMask
) {
285 strcat(buffer
, "Shift+");
287 if (ev
.xkey
.state
& Mod1Mask
) {
288 strcat(buffer
, "Mod1+");
290 if (ev
.xkey
.state
& Mod2Mask
) {
291 strcat(buffer
, "Mod2+");
293 if (ev
.xkey
.state
& Mod3Mask
) {
294 strcat(buffer
, "Mod3+");
296 if (ev
.xkey
.state
& Mod4Mask
) {
297 strcat(buffer
, "Mod4+");
299 if (ev
.xkey
.state
& Mod5Mask
) {
300 strcat(buffer
, "Mod5+");
304 return wstrdup(buffer
);
310 sgrabClicked(WMWidget
*w
, void *data
)
312 _Panel
*panel
= (_Panel
*)data
;
313 Display
*dpy
= WMScreenDisplay(WMWidgetScreen(panel
->win
));
317 if (w
== panel
->sclearB
) {
318 WMSetTextFieldText(panel
->shortT
, "");
319 updateMenuItem(panel
, panel
->currentItem
, panel
->shortT
);
323 if (!panel
->capturing
) {
324 panel
->capturing
= 1;
325 WMSetButtonText(w
, _("Cancel"));
326 XGrabKeyboard(dpy
, WMWidgetXID(panel
->win
), True
, GrabModeAsync
,
327 GrabModeAsync
, CurrentTime
);
328 shortcut
= captureShortcut(dpy
, panel
);
330 WMSetTextFieldText(panel
->shortT
, shortcut
);
331 updateMenuItem(panel
, panel
->currentItem
, panel
->shortT
);
335 panel
->capturing
= 0;
336 WMSetButtonText(w
, _("Capture"));
337 XUngrabKeyboard(dpy
, CurrentTime
);
342 changedItemPad(WMWidget
*w
, void *data
)
344 _Panel
*panel
= (_Panel
*)data
;
345 int padn
= WMGetPopUpButtonSelectedItem(w
);
347 WMUnmapWidget(panel
->itemPad
[panel
->currentPad
]);
348 WMMapWidget(panel
->itemPad
[padn
]);
350 panel
->currentPad
= padn
;
355 putNewSubmenu(WEditMenu
*menu
, char *title
)
360 item
= WAddMenuItemWithTitle(menu
, title
);
362 tmp
= WCreateEditMenu(WMWidgetScreen(menu
), title
);
363 WSetEditMenuAcceptsDrop(tmp
, True
);
364 WSetEditMenuDelegate(tmp
, &menuDelegate
);
365 WSetEditMenuSubmenu(menu
, item
, tmp
);
372 putNewItem(_Panel
*panel
, WEditMenu
*menu
, int type
, char *title
)
377 item
= WAddMenuItemWithTitle(menu
, title
);
379 data
= NEW(ItemData
);
381 WSetEditMenuItemData(item
, data
, (WMCallback
*)freeItemData
);
382 WSetEditMenuItemImage(item
, panel
->markerPix
[type
]);
389 makeFactoryMenu(WMWidget
*parent
, int width
)
393 pad
= WCreateEditMenuPad(parent
);
394 WMResizeWidget(pad
, width
, 10);
395 WSetEditMenuMinSize(pad
, wmksize(width
, 0));
396 WSetEditMenuMaxSize(pad
, wmksize(width
, 0));
397 WSetEditMenuSelectable(pad
, False
);
398 WSetEditMenuEditable(pad
, False
);
399 WSetEditMenuIsFactory(pad
, True
);
400 WSetEditMenuDelegate(pad
, &menuDelegate
);
407 createPanel(_Panel
*p
)
409 _Panel
*panel
= (_Panel
*)p
;
410 WMScreen
*scr
= WMWidgetScreen(panel
->win
);
411 WMColor
*black
= WMBlackColor(scr
);
412 WMColor
*white
= WMWhiteColor(scr
);
413 WMColor
*gray
= WMGrayColor(scr
);
414 WMFont
*bold
= WMBoldSystemFontOfSize(scr
, 12);
415 WMFont
*font
= WMSystemFontOfSize(scr
, 12);
420 menuDelegate
.data
= panel
;
423 panel
->boldFont
= bold
;
424 panel
->normalFont
= font
;
426 panel
->black
= black
;
427 panel
->white
= white
;
432 Display
*dpy
= WMScreenDisplay(scr
);
436 pixm
= WMCreatePixmap(scr
, 7, 7, WMScreenDepth(scr
), True
);
438 pix
= WMGetPixmapXID(pixm
);
440 XDrawLine(dpy
, pix
, WMColorGC(black
), 0, 3, 6, 3);
441 XDrawLine(dpy
, pix
, WMColorGC(black
), 3, 0, 3, 6);
443 XDrawLine(dpy, pix, WMColorGC(black), 1, 0, 3, 3);
444 XDrawLine(dpy, pix, WMColorGC(black), 1, 6, 3, 3);
445 XDrawLine(dpy, pix, WMColorGC(black), 0, 0, 0, 6);
448 pix
= WMGetPixmapMaskXID(pixm
);
450 gc
= XCreateGC(dpy
, pix
, 0, NULL
);
452 XSetForeground(dpy
, gc
, 0);
453 XFillRectangle(dpy
, pix
, gc
, 0, 0, 7, 7);
455 XSetForeground(dpy
, gc
, 1);
456 XDrawLine(dpy
, pix
, gc
, 0, 3, 6, 3);
457 XDrawLine(dpy
, pix
, gc
, 3, 0, 3, 6);
459 panel
->markerPix
[ExternalInfo
] = pixm
;
460 panel
->markerPix
[PipeInfo
] = pixm
;
461 panel
->markerPix
[DirectoryInfo
] = pixm
;
462 panel
->markerPix
[WSMenuInfo
] = pixm
;
468 panel
->frame
= WMCreateFrame(panel
->win
);
469 WMResizeWidget(panel
->frame
, FRAME_WIDTH
, FRAME_HEIGHT
);
470 WMMoveWidget(panel
->frame
, FRAME_LEFT
, FRAME_TOP
);
472 panel
->typeP
= WMCreatePopUpButton(panel
->frame
);
473 WMResizeWidget(panel
->typeP
, 150, 20);
474 WMMoveWidget(panel
->typeP
, 10, 10);
476 WMAddPopUpButtonItem(panel
->typeP
, _("New Items"));
477 WMAddPopUpButtonItem(panel
->typeP
, _("Sample Commands"));
478 WMAddPopUpButtonItem(panel
->typeP
, _("Sample Submenus"));
480 WMSetPopUpButtonAction(panel
->typeP
, changedItemPad
, panel
);
482 WMSetPopUpButtonSelectedItem(panel
->typeP
, 0);
489 pad
= makeFactoryMenu(panel
->frame
, 150);
490 WMMoveWidget(pad
, 10, 40);
492 data
= putNewItem(panel
, pad
, ExecInfo
, "Run Program");
493 data
= putNewItem(panel
, pad
, CommandInfo
, "Internal Command");
494 smenu
= putNewSubmenu(pad
, "Submenu");
495 data
= putNewItem(panel
, pad
, ExternalInfo
, "External Submenu");
496 data
= putNewItem(panel
, pad
, PipeInfo
, "Generated Submenu");
497 data
= putNewItem(panel
, pad
, DirectoryInfo
, "Directory Contents");
498 data
= putNewItem(panel
, pad
, WSMenuInfo
, "Workspace Menu");
500 panel
->itemPad
[0] = pad
;
508 sview
= WMCreateScrollView(panel
->frame
);
509 WMResizeWidget(sview
, 150, 180);
510 WMMoveWidget(sview
, 10, 40);
511 WMSetScrollViewHasVerticalScroller(sview
, True
);
513 pad
= makeFactoryMenu(panel
->frame
, 130);
515 WMSetScrollViewContentView(sview
, WMWidgetView(pad
));
517 data
= putNewItem(panel
, pad
, ExecInfo
, _("XTerm"));
518 data
->param
.exec
.command
= "xterm -sb -sl 2000 -bg black -fg white";
520 data
= putNewItem(panel
, pad
, ExecInfo
, _("rxvt"));
521 data
->param
.exec
.command
= "rxvt";
523 data
= putNewItem(panel
, pad
, ExecInfo
, _("ETerm"));
524 data
->param
.exec
.command
= "eterm";
526 data
= putNewItem(panel
, pad
, ExecInfo
, _("Run..."));
527 data
->param
.exec
.command
= "%a(Run,Type command to run)";
529 data
= putNewItem(panel
, pad
, ExecInfo
, _("Netscape"));
530 data
->param
.exec
.command
= "netscape";
532 data
= putNewItem(panel
, pad
, ExecInfo
, _("gimp"));
533 data
->param
.exec
.command
= "gimp";
535 data
= putNewItem(panel
, pad
, ExecInfo
, _("epic"));
536 data
->param
.exec
.command
= "xterm -e epic";
538 data
= putNewItem(panel
, pad
, ExecInfo
, _("ee"));
539 data
->param
.exec
.command
= "ee";
541 data
= putNewItem(panel
, pad
, ExecInfo
, _("xv"));
542 data
->param
.exec
.command
= "xv";
544 data
= putNewItem(panel
, pad
, ExecInfo
, _("Acrobat Reader"));
545 data
->param
.exec
.command
= "acroread || /usr/local/Acrobat4/bin/acroread";
547 data
= putNewItem(panel
, pad
, ExecInfo
, _("ghostview"));
548 data
->param
.exec
.command
= "gv";
550 data
= putNewItem(panel
, pad
, CommandInfo
, _("Exit Window Maker"));
551 data
->param
.command
.command
= 3;
555 panel
->itemPad
[1] = sview
;
560 WEditMenu
*pad
, *smenu
;
564 sview
= WMCreateScrollView(panel
->frame
);
565 WMResizeWidget(sview
, 150, 180);
566 WMMoveWidget(sview
, 10, 40);
567 WMSetScrollViewHasVerticalScroller(sview
, True
);
569 pad
= makeFactoryMenu(panel
->frame
, 130);
571 WMSetScrollViewContentView(sview
, WMWidgetView(pad
));
573 /* data = putNewItem(panel, pad, ExternalInfo, _("Debian Menu"));
574 data->param.pipe.command = "/etc/X11/WindowMaker/menu.hook";
576 data
= putNewItem(panel
, pad
, PipeInfo
, _("RedHat Menu"));
577 data
->param
.pipe
.command
= "wmconfig --output wmaker";
579 data
= putNewItem(panel
, pad
, PipeInfo
, _("Menu Conectiva"));
580 data
->param
.pipe
.command
= "wmconfig --output wmaker";
582 data
= putNewItem(panel
, pad
, DirectoryInfo
, _("Themes"));
583 data
->param
.directory
.command
= "setstyle";
584 data
->param
.directory
.directory
= "/usr/share/WindowMaker/Themes /usr/local/share/WindowMaker/Themes $HOME/GNUstep/Library/WindowMaker/Themes";
585 data
->param
.directory
.stripExt
= 1;
587 data
= putNewItem(panel
, pad
, DirectoryInfo
, _("Bg Images (scale)"));
588 data
->param
.directory
.command
= "wmsetbg -u -s";
589 data
->param
.directory
.directory
= "/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
590 data
->param
.directory
.stripExt
= 1;
592 data
= putNewItem(panel
, pad
, DirectoryInfo
, _("Bg Images (tile)"));
593 data
->param
.directory
.command
= "wmsetbg -u -t";
594 data
->param
.directory
.directory
= "/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
595 data
->param
.directory
.stripExt
= 1;
597 smenu
= putNewSubmenu(pad
, _("Assorted XTerms"));
599 data
= putNewItem(panel
, smenu
, ExecInfo
, _("XTerm Yellow on Blue"));
600 data
->param
.exec
.command
= "xterm -sb -sl 2000 -bg midnightblue -fg yellow";
602 data
= putNewItem(panel
, smenu
, ExecInfo
, _("XTerm White on Black"));
603 data
->param
.exec
.command
= "xterm -sb -sl 2000 -bg black -fg white";
605 data
= putNewItem(panel
, smenu
, ExecInfo
, _("XTerm Black on White"));
606 data
->param
.exec
.command
= "xterm -sb -sl 2000 -bg white -fg black";
608 data
= putNewItem(panel
, smenu
, ExecInfo
, _("XTerm Black on Beige"));
609 data
->param
.exec
.command
= "xterm -sb -sl 2000 -bg '#bbbb99' -fg black";
611 data
= putNewItem(panel
, smenu
, ExecInfo
, _("XTerm White on Green"));
612 data
->param
.exec
.command
= "xterm -sb -sl 2000 -bg '#228822' -fg white";
614 data
= putNewItem(panel
, smenu
, ExecInfo
, _("XTerm White on Olive"));
615 data
->param
.exec
.command
= "xterm -sb -sl 2000 -bg '#335533' -fg white";
617 data
= putNewItem(panel
, smenu
, ExecInfo
, _("XTerm Blue on Blue"));
618 data
->param
.exec
.command
= "xterm -sb -sl 2000 -bg '#112244' -fg '#88aabb'";
620 data
= putNewItem(panel
, smenu
, ExecInfo
, _("XTerm BIG FONTS"));
621 data
->param
.exec
.command
= "xterm -sb -sl 2000 -bg black -fg white -fn 10x20";
625 panel
->itemPad
[2] = sview
;
629 width
= FRAME_WIDTH
- 20 - 150 - 10;
631 panel
->optionsF
= WMCreateFrame(panel
->frame
);
632 WMResizeWidget(panel
->optionsF
, width
, FRAME_HEIGHT
- 15);
633 WMMoveWidget(panel
->optionsF
, 10 + 150 + 10, 5);
639 panel
->commandF
= WMCreateFrame(panel
->optionsF
);
640 WMResizeWidget(panel
->commandF
, width
, 50);
641 WMMoveWidget(panel
->commandF
, 10, 20);
642 WMSetFrameTitle(panel
->commandF
, _("Program to Run"));
644 panel
->commandT
= WMCreateTextField(panel
->commandF
);
645 WMResizeWidget(panel
->commandT
, width
- 20, 20);
646 WMMoveWidget(panel
->commandT
, 10, 20);
648 WMAddNotificationObserver(dataChanged
, panel
,
649 WMTextDidChangeNotification
,
653 panel
->xtermC
= WMCreateSwitchButton(panel
->commandF
);
654 WMResizeWidget(panel
->xtermC
, width
- 20, 20);
655 WMMoveWidget(panel
->xtermC
, 10, 50);
656 WMSetButtonText(panel
->xtermC
, _("Run the program inside a Xterm"));
658 WMMapSubwidgets(panel
->commandF
);
663 panel
->pathF
= WMCreateFrame(panel
->optionsF
);
664 WMResizeWidget(panel
->pathF
, width
, 150);
665 WMMoveWidget(panel
->pathF
, 10, 40);
666 WMSetFrameTitle(panel
->pathF
, _("Path for Menu"));
668 panel
->pathT
= WMCreateTextField(panel
->pathF
);
669 WMResizeWidget(panel
->pathT
, width
- 20, 20);
670 WMMoveWidget(panel
->pathT
, 10, 20);
672 WMAddNotificationObserver(dataChanged
, panel
,
673 WMTextDidChangeNotification
,
676 label
= WMCreateLabel(panel
->pathF
);
677 WMResizeWidget(label
, width
- 20, 80);
678 WMMoveWidget(label
, 10, 50);
679 WMSetLabelText(label
, _("Enter the path for a file containing a menu\n"
680 "or a list of directories with the programs you\n"
681 "want to have listed in the menu. Ex:\n"
682 "~/GNUstep/Library/WindowMaker/menu\n"
684 "/usr/X11R6/bin ~/xbin"));
686 WMMapSubwidgets(panel
->pathF
);
691 panel
->pipeF
= WMCreateFrame(panel
->optionsF
);
692 WMResizeWidget(panel
->pipeF
, width
, 100);
693 WMMoveWidget(panel
->pipeF
, 10, 50);
694 WMSetFrameTitle(panel
->pipeF
, _("Command"));
696 panel
->pipeT
= WMCreateTextField(panel
->pipeF
);
697 WMResizeWidget(panel
->pipeT
, width
- 20, 20);
698 WMMoveWidget(panel
->pipeT
, 10, 20);
700 WMAddNotificationObserver(dataChanged
, panel
,
701 WMTextDidChangeNotification
,
705 label
= WMCreateLabel(panel
->pipeF
);
706 WMResizeWidget(label
, width
- 20, 40);
707 WMMoveWidget(label
, 10, 50);
708 WMSetLabelText(label
, _("Enter a command that outputs a menu\n"
709 "definition to stdout when invoked."));
711 WMMapSubwidgets(panel
->pipeF
);
716 panel
->dcommandF
= WMCreateFrame(panel
->optionsF
);
717 WMResizeWidget(panel
->dcommandF
, width
, 90);
718 WMMoveWidget(panel
->dcommandF
, 10, 25);
719 WMSetFrameTitle(panel
->dcommandF
, _("Command to Open Files"));
721 panel
->dcommandT
= WMCreateTextField(panel
->dcommandF
);
722 WMResizeWidget(panel
->dcommandT
, width
- 20, 20);
723 WMMoveWidget(panel
->dcommandT
, 10, 20);
725 WMAddNotificationObserver(dataChanged
, panel
,
726 WMTextDidChangeNotification
,
730 label
= WMCreateLabel(panel
->dcommandF
);
731 WMResizeWidget(label
, width
- 20, 45);
732 WMMoveWidget(label
, 10, 40);
733 WMSetLabelText(label
, _("Enter the command you want to use to open the\n"
734 "files in the directories listed below."));
736 WMMapSubwidgets(panel
->dcommandF
);
739 panel
->dpathF
= WMCreateFrame(panel
->optionsF
);
740 WMResizeWidget(panel
->dpathF
, width
, 80);
741 WMMoveWidget(panel
->dpathF
, 10, 125);
742 WMSetFrameTitle(panel
->dpathF
, _("Directories with Files"));
744 panel
->dpathT
= WMCreateTextField(panel
->dpathF
);
745 WMResizeWidget(panel
->dpathT
, width
- 20, 20);
746 WMMoveWidget(panel
->dpathT
, 10, 20);
748 WMAddNotificationObserver(dataChanged
, panel
,
749 WMTextDidChangeNotification
,
752 panel
->dstripB
= WMCreateSwitchButton(panel
->dpathF
);
753 WMResizeWidget(panel
->dstripB
, width
- 20, 20);
754 WMMoveWidget(panel
->dstripB
, 10, 50);
755 WMSetButtonText(panel
->dstripB
, _("Strip extensions from file names"));
757 WMSetButtonAction(panel
->dstripB
, buttonClicked
, panel
);
759 WMMapSubwidgets(panel
->dpathF
);
764 panel
->shortF
= WMCreateFrame(panel
->optionsF
);
765 WMResizeWidget(panel
->shortF
, width
, 50);
766 WMMoveWidget(panel
->shortF
, 10, 160);
767 WMSetFrameTitle(panel
->shortF
, _("Keyboard Shortcut"));
769 panel
->shortT
= WMCreateTextField(panel
->shortF
);
770 WMResizeWidget(panel
->shortT
, width
- 20 - 170, 20);
771 WMMoveWidget(panel
->shortT
, 10, 20);
773 WMAddNotificationObserver(dataChanged
, panel
,
774 WMTextDidChangeNotification
,
777 panel
->sgrabB
= WMCreateCommandButton(panel
->shortF
);
778 WMResizeWidget(panel
->sgrabB
, 80, 24);
779 WMMoveWidget(panel
->sgrabB
, width
- 90, 18);
780 WMSetButtonText(panel
->sgrabB
, _("Capture"));
781 WMSetButtonAction(panel
->sgrabB
, sgrabClicked
, panel
);
783 panel
->sclearB
= WMCreateCommandButton(panel
->shortF
);
784 WMResizeWidget(panel
->sclearB
, 80, 24);
785 WMMoveWidget(panel
->sclearB
, width
- 175, 18);
786 WMSetButtonText(panel
->sclearB
, _("Clear"));
787 WMSetButtonAction(panel
->sclearB
, sgrabClicked
, panel
);
789 WMMapSubwidgets(panel
->shortF
);
791 /* internal command */
793 panel
->icommandL
= WMCreateList(panel
->optionsF
);
794 WMResizeWidget(panel
->icommandL
, width
, 80);
795 WMMoveWidget(panel
->icommandL
, 10, 20);
797 WMSetListAction(panel
->icommandL
, icommandLClicked
, panel
);
799 WMAddNotificationObserver(dataChanged
, panel
,
800 WMListSelectionDidChangeNotification
,
803 WMInsertListItem(panel
->icommandL
, 0, _("Arrange Icons"));
804 WMInsertListItem(panel
->icommandL
, 1, _("Hide All Windows Except For The Focused One"));
805 WMInsertListItem(panel
->icommandL
, 2, _("Show All Windows"));
807 WMInsertListItem(panel
->icommandL
, 3, _("Exit Window Maker"));
808 WMInsertListItem(panel
->icommandL
, 4, _("Exit X Session"));
809 WMInsertListItem(panel
->icommandL
, 5, _("Restart Window Maker"));
810 WMInsertListItem(panel
->icommandL
, 6, _("Start Another Window Manager : ("));
812 WMInsertListItem(panel
->icommandL
, 7, _("Save Current Session"));
813 WMInsertListItem(panel
->icommandL
, 8, _("Clear Saved Session"));
814 WMInsertListItem(panel
->icommandL
, 9, _("Refresh Screen"));
815 WMInsertListItem(panel
->icommandL
, 10, _("Open Info Panel"));
816 WMInsertListItem(panel
->icommandL
, 11, _("Open Copyright Panel"));
819 panel
->paramF
= WMCreateFrame(panel
->optionsF
);
820 WMResizeWidget(panel
->paramF
, width
, 50);
821 WMMoveWidget(panel
->paramF
, 10, 105);
822 WMSetFrameTitle(panel
->paramF
, _("Window Manager to Start"));
824 panel
->paramT
= WMCreateTextField(panel
->paramF
);
825 WMResizeWidget(panel
->paramT
, width
- 20, 20);
826 WMMoveWidget(panel
->paramT
, 10, 20);
828 WMAddNotificationObserver(dataChanged
, panel
,
829 WMTextDidChangeNotification
,
832 WMMapSubwidgets(panel
->paramF
);
835 panel
->quickB
= WMCreateSwitchButton(panel
->optionsF
);
836 WMResizeWidget(panel
->quickB
, width
, 20);
837 WMMoveWidget(panel
->quickB
, 10, 120);
838 WMSetButtonText(panel
->quickB
, _("Do not confirm action."));
839 WMSetButtonAction(panel
->quickB
, buttonClicked
, panel
);
844 label
= WMCreateLabel(panel
->optionsF
);
845 WMResizeWidget(label
, width
- 20, FRAME_HEIGHT
- 50);
846 WMMoveWidget(label
, 10, 20);
847 WMSetLabelText(label
,
848 _("Instructions:\n\n"
849 " - drag items from the left to the menu to add new items\n"
850 " - drag items out of the menu to remove items\n"
851 " - drag items in menu to change their position\n"
852 " - double click in a menu item to change the label\n"
853 " - click on a menu item to change related information"));
856 WMRealizeWidget(panel
->frame
);
857 WMMapSubwidgets(panel
->frame
);
858 WMMapWidget(panel
->frame
);
863 for (i
= 0; i
< 3; i
++)
864 WMUnmapWidget(panel
->itemPad
[i
]);
866 changedItemPad(panel
->typeP
, panel
);
868 panel
->sections
[NoInfo
][0] = label
;
870 panel
->sections
[ExecInfo
][0] = panel
->commandF
;
871 panel
->sections
[ExecInfo
][1] = panel
->shortF
;
873 panel
->sections
[CommandInfo
][0] = panel
->icommandL
;
874 panel
->sections
[CommandInfo
][1] = label
;
875 panel
->sections
[CommandInfo
][2] = panel
->shortF
;
877 panel
->sections
[ExternalInfo
][0] = panel
->pathF
;
879 panel
->sections
[PipeInfo
][0] = panel
->pipeF
;
881 panel
->sections
[DirectoryInfo
][0] = panel
->dpathF
;
882 panel
->sections
[DirectoryInfo
][1] = panel
->dcommandF
;
884 panel
->currentType
= NoInfo
;
893 freeItemData(ItemData
*data
)
895 #define CFREE(d) if (d) free(d)
898 switch (data
->type
) {
900 CFREE(data
->param
.command
.parameter
);
901 CFREE(data
->param
.command
.shortcut
);
905 CFREE(data
->param
.exec
.command
);
906 CFREE(data
->param
.exec
.shortcut
);
910 CFREE(data
->param
.pipe
.command
);
914 CFREE(data
->param
.external
.path
);
918 CFREE(data
->param
.directory
.command
);
919 CFREE(data
->param
.directory
.directory
);
932 parseCommand(proplist_t item
)
934 ItemData
*data
= NEW(ItemData
);
936 char *command
= NULL
;
937 char *parameter
= NULL
;
938 char *shortcut
= NULL
;
942 p
= PLGetArrayElement(item
, i
++);
943 command
= PLGetString(p
);
944 if (strcmp(command
, "SHORTCUT") == 0) {
945 p
= PLGetArrayElement(item
, i
++);
946 shortcut
= PLGetString(p
);
947 p
= PLGetArrayElement(item
, i
++);
948 command
= PLGetString(p
);
950 p
= PLGetArrayElement(item
, i
++);
952 parameter
= PLGetString(p
);
954 if (strcmp(command
, "EXEC") == 0 || strcmp(command
, "SHEXEC") == 0) {
956 data
->type
= ExecInfo
;
958 data
->param
.exec
.command
= wstrdup(parameter
);
960 data
->param
.exec
.shortcut
= wstrdup(shortcut
);
962 } else if (strcmp(command
, "OPEN_MENU") == 0) {
965 * dir menu, menu file
967 * |pipe (TODO: ||pipe)
970 while (isspace(*p
) && *p
) p
++;
972 data
->type
= PipeInfo
;
973 data
->param
.pipe
.command
= wtrimspace(p
+1);
979 s
= strstr(p
, "WITH");
986 data
->type
= DirectoryInfo
;
990 while (*s
&& isspace(*s
)) s
++;
991 data
->param
.directory
.command
= wstrdup(s
);
993 wtokensplit(p
, &tokens
, &tokn
);
996 ctokens
= wmalloc(sizeof(char*)*tokn
);
998 for (i
= 0, j
= 0; i
< tokn
; i
++) {
999 if (strcmp(tokens
[i
], "-noext") == 0) {
1001 data
->param
.directory
.stripExt
= 1;
1003 ctokens
[j
++] = tokens
[i
];
1006 data
->param
.directory
.directory
= wtokenjoin(ctokens
, j
);
1009 wtokenfree(tokens
, tokn
);
1011 data
->type
= ExternalInfo
;
1012 data
->param
.external
.path
= p
;
1015 } else if (strcmp(command
, "WORKSPACE_MENU") == 0) {
1016 data
->type
= WSMenuInfo
;
1020 if (strcmp(command
, "ARRANGE_ICONS") == 0) {
1022 } else if (strcmp(command
, "HIDE_OTHERS") == 0) {
1024 } else if (strcmp(command
, "SHOW_ALL") == 0) {
1026 } else if (strcmp(command
, "EXIT") == 0) {
1028 } else if (strcmp(command
, "SHUTDOWN") == 0) {
1030 } else if (strcmp(command
, "RESTART") == 0) {
1036 } else if (strcmp(command
, "SAVE_SESSION") == 0) {
1038 } else if (strcmp(command
, "CLEAR_SESSION") == 0) {
1040 } else if (strcmp(command
, "REFRESH") == 0) {
1042 } else if (strcmp(command
, "INFO_PANEL") == 0) {
1044 } else if (strcmp(command
, "LEGAL_PANEL") == 0) {
1047 wwarning(_("unknown command '%s' in menu"), command
);
1051 data
->type
= CommandInfo
;
1053 data
->param
.command
.command
= cmd
;
1055 data
->param
.command
.shortcut
= wstrdup(shortcut
);
1057 data
->param
.command
.parameter
= wstrdup(parameter
);
1072 updateFrameTitle(_Panel
*panel
, char *title
, InfoType type
)
1074 if (type
!= NoInfo
) {
1079 tmp
= wstrappend(title
, _(": Execute Program"));
1083 tmp
= wstrappend(title
, _(": Perform Internal Command"));
1087 tmp
= wstrappend(title
, _(": Open a Submenu"));
1091 tmp
= wstrappend(title
, _(": Program Generated Submenu"));
1095 tmp
= wstrappend(title
, _(": Directory Contents Menu"));
1099 tmp
= wstrappend(title
, _(": Open Workspaces Submenu"));
1106 WMSetFrameTitle(panel
->optionsF
, tmp
);
1109 WMSetFrameTitle(panel
->optionsF
, NULL
);
1116 changeInfoType(_Panel
*panel
, char *title
, InfoType type
)
1120 if (panel
->currentType
!= type
) {
1122 w
= panel
->sections
[panel
->currentType
];
1128 WMUnmapWidget(panel
->paramF
);
1129 WMUnmapWidget(panel
->quickB
);
1133 w
= panel
->sections
[type
];
1141 updateFrameTitle(panel
, title
, type
);
1143 panel
->currentType
= type
;
1150 updateMenuItem(_Panel
*panel
, WEditMenuItem
*item
, WMWidget
*changedWidget
)
1152 ItemData
*data
= WGetEditMenuItemData(item
);
1154 assert(data
!= NULL
);
1156 #define REPLACE(v, d) if (v) free(v); v = d
1158 switch (data
->type
) {
1160 if (changedWidget
== panel
->commandT
) {
1161 REPLACE(data
->param
.exec
.command
,
1162 WMGetTextFieldText(panel
->commandT
));
1164 if (changedWidget
== panel
->shortT
) {
1165 REPLACE(data
->param
.exec
.shortcut
,
1166 WMGetTextFieldText(panel
->shortT
));
1171 if (changedWidget
== panel
->icommandL
) {
1172 data
->param
.command
.command
=
1173 WMGetListSelectedItemRow(panel
->icommandL
);
1175 switch (data
->param
.command
.command
) {
1178 if (changedWidget
== panel
->quickB
) {
1179 REPLACE(data
->param
.command
.parameter
,
1180 WMGetButtonSelected(panel
->quickB
)
1181 ? wstrdup("QUICK") : NULL
);
1186 if (changedWidget
== panel
->paramT
) {
1187 REPLACE(data
->param
.command
.parameter
,
1188 WMGetTextFieldText(panel
->paramT
));
1192 if (changedWidget
== panel
->shortT
) {
1193 REPLACE(data
->param
.command
.shortcut
,
1194 WMGetTextFieldText(panel
->shortT
));
1201 if (changedWidget
== panel
->pipeT
) {
1202 REPLACE(data
->param
.pipe
.command
,
1203 WMGetTextFieldText(panel
->pipeT
));
1208 if (changedWidget
== panel
->pathT
) {
1209 REPLACE(data
->param
.external
.path
,
1210 WMGetTextFieldText(panel
->pathT
));
1215 if (changedWidget
== panel
->dpathT
) {
1216 REPLACE(data
->param
.directory
.directory
,
1217 WMGetTextFieldText(panel
->dpathT
));
1219 if (changedWidget
== panel
->dcommandT
) {
1220 REPLACE(data
->param
.directory
.command
,
1221 WMGetTextFieldText(panel
->dcommandT
));
1223 if (changedWidget
== panel
->dstripB
) {
1224 data
->param
.directory
.stripExt
=
1225 WMGetButtonSelected(panel
->dstripB
);
1240 menuItemCloned(WEditMenuDelegate
*delegate
, WEditMenu
*menu
,
1241 WEditMenuItem
*origItem
, WEditMenuItem
*newItem
)
1243 ItemData
*data
= WGetEditMenuItemData(origItem
);
1249 #define DUP(s) (s) ? wstrdup(s) : NULL
1251 newData
= NEW(ItemData
);
1253 newData
->type
= data
->type
;
1255 switch (data
->type
) {
1257 newData
->param
.exec
.command
= DUP(data
->param
.exec
.command
);
1258 newData
->param
.exec
.shortcut
= DUP(data
->param
.exec
.shortcut
);
1262 newData
->param
.command
.command
= data
->param
.command
.command
;
1263 newData
->param
.command
.parameter
= DUP(data
->param
.command
.parameter
);
1264 newData
->param
.command
.shortcut
= DUP(data
->param
.command
.shortcut
);
1268 newData
->param
.pipe
.command
= DUP(data
->param
.pipe
.command
);
1272 newData
->param
.external
.path
= DUP(data
->param
.external
.path
);
1276 newData
->param
.directory
.directory
= DUP(data
->param
.directory
.directory
);
1277 newData
->param
.directory
.command
= DUP(data
->param
.directory
.command
);
1278 newData
->param
.directory
.stripExt
= data
->param
.directory
.stripExt
;
1287 WSetEditMenuItemData(newItem
, newData
, (WMCallback
*)freeItemData
);
1293 static void menuItemEdited(struct WEditMenuDelegate
*delegate
, WEditMenu
*menu
,
1294 WEditMenuItem
*item
)
1296 _Panel
*panel
= (_Panel
*)delegate
->data
;
1299 updateFrameTitle(panel
, WGetEditMenuItemTitle(item
), panel
->currentType
);
1301 submenu
= WGetEditMenuSubmenu(menu
, item
);
1303 WSetEditMenuTitle(submenu
, WGetEditMenuItemTitle(item
));
1311 static Bool
shouldRemoveItem(struct WEditMenuDelegate
*delegate
,
1312 WEditMenu
*menu
, WEditMenuItem
*item
)
1314 _Panel
*panel
= (_Panel
*)delegate
->data
;
1319 if (WGetEditMenuSubmenu(menu
, item
)) {
1322 res
= WMRunAlertPanel(WMWidgetScreen(menu
), NULL
,
1323 _("Remove Submenu"),
1324 _("Removing this item will destroy all items inside\n"
1325 "the submenu. Do you really want to do that?"),
1327 _("Yes, don't ask again."));
1334 panel
->dontAsk
= True
;
1343 menuItemDeselected(WEditMenuDelegate
*delegate
, WEditMenu
*menu
,
1344 WEditMenuItem
*item
)
1346 _Panel
*panel
= (_Panel
*)delegate
->data
;
1348 changeInfoType(panel
, NULL
, NoInfo
);
1353 menuItemSelected(WEditMenuDelegate
*delegate
, WEditMenu
*menu
,
1354 WEditMenuItem
*item
)
1356 ItemData
*data
= WGetEditMenuItemData(item
);
1357 _Panel
*panel
= (_Panel
*)delegate
->data
;
1359 panel
->currentItem
= item
;
1362 changeInfoType(panel
, WGetEditMenuItemTitle(item
), data
->type
);
1364 switch (data
->type
) {
1369 WMSetTextFieldText(panel
->commandT
, data
->param
.exec
.command
);
1370 WMSetTextFieldText(panel
->shortT
, data
->param
.exec
.shortcut
);
1374 WMSelectListItem(panel
->icommandL
,
1375 data
->param
.command
.command
);
1376 WMSetListPosition(panel
->icommandL
,
1377 data
->param
.command
.command
- 2);
1378 WMSetTextFieldText(panel
->shortT
, data
->param
.command
.shortcut
);
1380 switch (data
->param
.command
.command
) {
1383 WMSetButtonSelected(panel
->quickB
,
1384 data
->param
.command
.parameter
!=NULL
);
1387 WMSetTextFieldText(panel
->paramT
,
1388 data
->param
.command
.parameter
);
1392 icommandLClicked(panel
->icommandL
, panel
);
1396 WMSetTextFieldText(panel
->pipeT
, data
->param
.pipe
.command
);
1400 WMSetTextFieldText(panel
->pathT
, data
->param
.external
.path
);
1404 WMSetTextFieldText(panel
->dpathT
, data
->param
.directory
.directory
);
1405 WMSetTextFieldText(panel
->dcommandT
, data
->param
.directory
.command
);
1406 WMSetButtonSelected(panel
->dstripB
, data
->param
.directory
.stripExt
);
1421 buildSubmenu(_Panel
*panel
, proplist_t pl
)
1423 WMScreen
*scr
= WMWidgetScreen(panel
->win
);
1425 WEditMenuItem
*item
;
1430 tp
= PLGetArrayElement(pl
, 0);
1431 title
= PLGetString(tp
);
1433 menu
= WCreateEditMenu(scr
, title
);
1435 for (i
= 1; i
< PLGetNumberOfElements(pl
); i
++) {
1438 pi
= PLGetArrayElement(pl
, i
);
1440 tp
= PLGetArrayElement(pi
, 0);
1441 bp
= PLGetArrayElement(pi
, 1);
1443 title
= PLGetString(tp
);
1445 if (PLIsArray(bp
)) { /* it's a submenu */
1448 submenu
= buildSubmenu(panel
, pi
);
1450 item
= WAddMenuItemWithTitle(menu
, title
);
1452 WSetEditMenuSubmenu(menu
, item
, submenu
);
1456 item
= WAddMenuItemWithTitle(menu
, title
);
1458 data
= parseCommand(pi
);
1460 if (panel
->markerPix
[data
->type
])
1461 WSetEditMenuItemImage(item
, panel
->markerPix
[data
->type
]);
1462 WSetEditMenuItemData(item
, data
, (WMCallback
*)freeItemData
);
1466 WSetEditMenuAcceptsDrop(menu
, True
);
1467 WSetEditMenuDelegate(menu
, &menuDelegate
);
1469 WMRealizeWidget(menu
);
1477 buildMenuFromPL(_Panel
*panel
, proplist_t pl
)
1479 panel
->menu
= buildSubmenu(panel
, pl
);
1480 WMMapWidget(panel
->menu
);
1486 getDefaultMenu(_Panel
*panel
)
1488 proplist_t menu
, pmenu
;
1489 char *menuPath
, *gspath
;
1491 gspath
= wusergnusteppath();
1493 menuPath
= wmalloc(strlen(gspath
)+128);
1494 /* if there is a localized plmenu for the tongue put it's filename here */
1495 sprintf(menuPath
, _("%s/Library/WindowMaker/plmenu"), gspath
);
1497 menu
= PLGetProplistWithPath(menuPath
);
1499 wwarning("%s:could not read property list menu", menuPath
);
1501 if (strcmp("%s/Library/WindowMaker/plmenu",
1502 _("%s/Library/WindowMaker/plmenu"))!=0) {
1504 sprintf(menuPath
, "%s/Library/WindowMaker/plmenu", gspath
);
1505 menu
= PLGetProplistWithPath(menuPath
);
1506 wwarning("%s:could not read property list menu", menuPath
);
1511 sprintf(buffer
, _("Could not open default menu from '%s'"),
1513 WMRunAlertPanel(WMWidgetScreen(panel
->win
), panel
->win
,
1514 _("Error"), buffer
, _("OK"), NULL
, NULL
);
1531 showData(_Panel
*panel
)
1537 gspath
= wusergnusteppath();
1539 menuPath
= wmalloc(strlen(gspath
)+32);
1540 strcpy(menuPath
, gspath
);
1541 strcat(menuPath
, "/Defaults/WMRootMenu");
1543 pmenu
= PLGetProplistWithPath(menuPath
);
1545 if (!pmenu
|| !PLIsArray(pmenu
)) {
1548 res
= WMRunAlertPanel(WMWidgetScreen(panel
->win
), panel
->win
,
1550 _("The menu file format currently in use is not supported\n"
1551 "by this tool. Do you want to discard the current menu\n"
1552 "to use this tool?"),
1553 _("Yes, Discard and Update"),
1554 _("No, Keep Current Menu"), NULL
);
1556 if (res
== WAPRDefault
) {
1557 pmenu
= getDefaultMenu(panel
);
1560 pmenu
= PLMakeArrayFromElements(PLMakeString("Applications"),
1564 panel
->dontSave
= True
;
1569 panel
->menuPath
= menuPath
;
1571 buildMenuFromPL(panel
, pmenu
);
1591 processData(char *title
, ItemData
*data
)
1595 static char *pscut
= NULL
;
1596 static char *pomenu
= NULL
;
1600 pscut
= PLMakeString("SHORTCUT");
1601 pomenu
= PLMakeString("OPEN_MENU");
1604 item
= PLMakeArrayFromElements(PLMakeString(title
), NULL
);
1607 switch (data
->type
) {
1610 if (strpbrk(data
->param
.exec
.command
, "&$*|><?`")) {
1619 if (notblank(data
->param
.exec
.shortcut
)) {
1620 PLAppendArrayElement(item
, pscut
);
1621 PLAppendArrayElement(item
,
1622 PLMakeString(data
->param
.exec
.shortcut
));
1625 PLAppendArrayElement(item
, PLMakeString(s1
));
1626 PLAppendArrayElement(item
, PLMakeString(data
->param
.exec
.command
));
1630 if (notblank(data
->param
.command
.shortcut
)) {
1631 PLAppendArrayElement(item
, pscut
);
1632 PLAppendArrayElement(item
,
1633 PLMakeString(data
->param
.command
.shortcut
));
1636 i
= data
->param
.command
.command
;
1638 PLAppendArrayElement(item
, PLMakeString(commandNames
[i
]));
1643 if (data
->param
.command
.parameter
)
1644 PLAppendArrayElement(item
,
1645 PLMakeString(data
->param
.command
.parameter
));
1648 case 7: /* restart */
1649 if (data
->param
.command
.parameter
)
1650 PLAppendArrayElement(item
,
1651 PLMakeString(data
->param
.command
.parameter
));
1658 PLAppendArrayElement(item
, pomenu
);
1659 s1
= wstrappend("| ", data
->param
.pipe
.command
);
1660 PLAppendArrayElement(item
, PLMakeString(s1
));
1665 PLAppendArrayElement(item
, pomenu
);
1666 PLAppendArrayElement(item
, PLMakeString(data
->param
.external
.path
));
1674 l
= strlen(data
->param
.directory
.directory
);
1675 l
+= strlen(data
->param
.directory
.command
);
1678 PLAppendArrayElement(item
, pomenu
);
1681 sprintf(tmp
, "%s%s WITH %s",
1682 data
->param
.directory
.stripExt
? "-noext " : "",
1683 data
->param
.directory
.directory
,
1684 data
->param
.directory
.command
);
1686 PLAppendArrayElement(item
, PLMakeString(tmp
));
1692 PLAppendArrayElement(item
, PLMakeString("WORKSPACE_MENU"));
1705 processSubmenu(WEditMenu
*menu
)
1707 WEditMenuItem
*item
;
1714 s
= WGetEditMenuTitle(menu
);
1715 pl
= PLMakeString(s
);
1717 pmenu
= PLMakeArrayFromElements(pl
, NULL
);
1720 while ((item
= WGetEditMenuItem(menu
, i
++))) {
1723 s
= WGetEditMenuItemTitle(item
);
1725 submenu
= WGetEditMenuSubmenu(menu
, item
);
1727 pl
= processSubmenu(submenu
);
1729 pl
= processData(s
, WGetEditMenuItemData(item
));
1732 PLAppendArrayElement(pmenu
, pl
);
1741 buildPLFromMenu(_Panel
*panel
)
1745 menu
= processSubmenu(panel
->menu
);
1754 storeData(_Panel
*panel
)
1758 if (panel
->dontSave
)
1761 menu
= buildPLFromMenu(panel
);
1763 PLSetFilename(menu
, PLMakeString(panel
->menuPath
));
1772 InitMenu(WMScreen
*scr
, WMWindow
*win
)
1776 panel
= wmalloc(sizeof(_Panel
));
1777 memset(panel
, 0, sizeof(_Panel
));
1779 panel
->sectionName
= _("Applications Menu Definition");
1781 panel
->description
= _("Edit the menu for launching applications.");
1785 panel
->callbacks
.createWidgets
= createPanel
;
1786 panel
->callbacks
.updateDomain
= storeData
;
1788 AddSection(panel
, ICON_FILE
);