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 */
112 /* about the currently selected item */
113 WEditMenuItem
*currentItem
;
114 InfoType currentType
;
115 WMWidget
*sections
[LastInfo
][MAX_SECTION_SIZE
];
147 static char *commandNames
[] = {
164 #define NEW(type) memset(wmalloc(sizeof(type)), 0, sizeof(type))
167 #define ICON_FILE "menus"
171 static void showData(_Panel
*panel
);
174 static void updateMenuItem(_Panel
*panel
, WEditMenuItem
*item
,
175 WMWidget
*changedWidget
);
177 static void menuItemSelected(struct WEditMenuDelegate
*delegate
,
178 WEditMenu
*menu
, WEditMenuItem
*item
);
180 static void menuItemDeselected(struct WEditMenuDelegate
*delegate
,
181 WEditMenu
*menu
, WEditMenuItem
*item
);
183 static void menuItemCloned(struct WEditMenuDelegate
*delegate
, WEditMenu
*menu
,
184 WEditMenuItem
*origItem
, WEditMenuItem
*newItem
);
186 static void menuItemEdited(struct WEditMenuDelegate
*delegate
, WEditMenu
*menu
,
187 WEditMenuItem
*item
);
189 static Bool
shouldRemoveItem(struct WEditMenuDelegate
*delegate
,
190 WEditMenu
*menu
, WEditMenuItem
*item
);
193 static void freeItemData(ItemData
*data
);
197 static WEditMenuDelegate menuDelegate
= {
208 dataChanged(void *self
, WMNotification
*notif
)
210 _Panel
*panel
= (_Panel
*)self
;
211 WEditMenuItem
*item
= panel
->currentItem
;
212 WMWidget
*w
= (WMWidget
*)WMGetNotificationObject(notif
);
214 updateMenuItem(panel
, item
, w
);
219 buttonClicked(WMWidget
*w
, void *data
)
221 _Panel
*panel
= (_Panel
*)data
;
222 WEditMenuItem
*item
= panel
->currentItem
;
224 updateMenuItem(panel
, item
, w
);
229 icommandLClicked(WMWidget
*w
, void *data
)
231 _Panel
*panel
= (_Panel
*)data
;
234 cmd
= WMGetListSelectedItemRow(w
);
235 if (cmd
== 3 || cmd
== 4) {
236 WMMapWidget(panel
->quickB
);
238 WMUnmapWidget(panel
->quickB
);
241 WMMapWidget(panel
->paramF
);
243 WMUnmapWidget(panel
->paramF
);
256 captureShortcut(Display
*dpy
, _Panel
*panel
)
263 while (panel
->capturing
) {
264 XAllowEvents(dpy
, AsyncKeyboard
, CurrentTime
);
265 WMNextEvent(dpy
, &ev
);
266 if (ev
.type
==KeyPress
&& ev
.xkey
.keycode
!=0) {
267 ksym
= XKeycodeToKeysym(dpy
, ev
.xkey
.keycode
, 0);
268 if (!IsModifierKey(ksym
)) {
269 key
=XKeysymToString(ksym
);
270 panel
->capturing
= 0;
282 if (ev
.xkey
.state
& ControlMask
) {
283 strcat(buffer
, "Control+");
285 if (ev
.xkey
.state
& ShiftMask
) {
286 strcat(buffer
, "Shift+");
288 if (ev
.xkey
.state
& Mod1Mask
) {
289 strcat(buffer
, "Mod1+");
291 if (ev
.xkey
.state
& Mod2Mask
) {
292 strcat(buffer
, "Mod2+");
294 if (ev
.xkey
.state
& Mod3Mask
) {
295 strcat(buffer
, "Mod3+");
297 if (ev
.xkey
.state
& Mod4Mask
) {
298 strcat(buffer
, "Mod4+");
300 if (ev
.xkey
.state
& Mod5Mask
) {
301 strcat(buffer
, "Mod5+");
305 return wstrdup(buffer
);
311 sgrabClicked(WMWidget
*w
, void *data
)
313 _Panel
*panel
= (_Panel
*)data
;
314 Display
*dpy
= WMScreenDisplay(WMWidgetScreen(panel
->parent
));
318 if (w
== panel
->sclearB
) {
319 WMSetTextFieldText(panel
->shortT
, "");
320 updateMenuItem(panel
, panel
->currentItem
, panel
->shortT
);
324 if (!panel
->capturing
) {
325 panel
->capturing
= 1;
326 WMSetButtonText(w
, _("Cancel"));
327 XGrabKeyboard(dpy
, WMWidgetXID(panel
->parent
), True
, GrabModeAsync
,
328 GrabModeAsync
, CurrentTime
);
329 shortcut
= captureShortcut(dpy
, panel
);
331 WMSetTextFieldText(panel
->shortT
, shortcut
);
332 updateMenuItem(panel
, panel
->currentItem
, panel
->shortT
);
336 panel
->capturing
= 0;
337 WMSetButtonText(w
, _("Capture"));
338 XUngrabKeyboard(dpy
, CurrentTime
);
343 changedItemPad(WMWidget
*w
, void *data
)
345 _Panel
*panel
= (_Panel
*)data
;
346 int padn
= WMGetPopUpButtonSelectedItem(w
);
348 WMUnmapWidget(panel
->itemPad
[panel
->currentPad
]);
349 WMMapWidget(panel
->itemPad
[padn
]);
351 panel
->currentPad
= padn
;
356 putNewSubmenu(WEditMenu
*menu
, char *title
)
361 item
= WAddMenuItemWithTitle(menu
, title
);
363 tmp
= WCreateEditMenu(WMWidgetScreen(menu
), title
);
364 WSetEditMenuAcceptsDrop(tmp
, True
);
365 WSetEditMenuDelegate(tmp
, &menuDelegate
);
366 WSetEditMenuSubmenu(menu
, item
, tmp
);
373 putNewItem(_Panel
*panel
, WEditMenu
*menu
, int type
, char *title
)
378 item
= WAddMenuItemWithTitle(menu
, title
);
380 data
= NEW(ItemData
);
382 WSetEditMenuItemData(item
, data
, (WMCallback
*)freeItemData
);
383 WSetEditMenuItemImage(item
, panel
->markerPix
[type
]);
390 makeFactoryMenu(WMWidget
*parent
, int width
)
394 pad
= WCreateEditMenuPad(parent
);
395 WMResizeWidget(pad
, width
, 10);
396 WSetEditMenuMinSize(pad
, wmksize(width
, 0));
397 WSetEditMenuMaxSize(pad
, wmksize(width
, 0));
398 WSetEditMenuSelectable(pad
, False
);
399 WSetEditMenuEditable(pad
, False
);
400 WSetEditMenuIsFactory(pad
, True
);
401 WSetEditMenuDelegate(pad
, &menuDelegate
);
408 createPanel(_Panel
*p
)
410 _Panel
*panel
= (_Panel
*)p
;
411 WMScreen
*scr
= WMWidgetScreen(panel
->parent
);
412 WMColor
*black
= WMBlackColor(scr
);
413 WMColor
*white
= WMWhiteColor(scr
);
414 WMColor
*gray
= WMGrayColor(scr
);
415 WMFont
*bold
= WMBoldSystemFontOfSize(scr
, 12);
416 WMFont
*font
= WMSystemFontOfSize(scr
, 12);
421 menuDelegate
.data
= panel
;
424 panel
->boldFont
= bold
;
425 panel
->normalFont
= font
;
427 panel
->black
= black
;
428 panel
->white
= white
;
433 Display
*dpy
= WMScreenDisplay(scr
);
437 pixm
= WMCreatePixmap(scr
, 7, 7, WMScreenDepth(scr
), True
);
439 pix
= WMGetPixmapXID(pixm
);
441 XDrawLine(dpy
, pix
, WMColorGC(black
), 0, 3, 6, 3);
442 XDrawLine(dpy
, pix
, WMColorGC(black
), 3, 0, 3, 6);
444 XDrawLine(dpy, pix, WMColorGC(black), 1, 0, 3, 3);
445 XDrawLine(dpy, pix, WMColorGC(black), 1, 6, 3, 3);
446 XDrawLine(dpy, pix, WMColorGC(black), 0, 0, 0, 6);
449 pix
= WMGetPixmapMaskXID(pixm
);
451 gc
= XCreateGC(dpy
, pix
, 0, NULL
);
453 XSetForeground(dpy
, gc
, 0);
454 XFillRectangle(dpy
, pix
, gc
, 0, 0, 7, 7);
456 XSetForeground(dpy
, gc
, 1);
457 XDrawLine(dpy
, pix
, gc
, 0, 3, 6, 3);
458 XDrawLine(dpy
, pix
, gc
, 3, 0, 3, 6);
460 panel
->markerPix
[ExternalInfo
] = pixm
;
461 panel
->markerPix
[PipeInfo
] = pixm
;
462 panel
->markerPix
[DirectoryInfo
] = pixm
;
463 panel
->markerPix
[WSMenuInfo
] = pixm
;
468 panel
->box
= WMCreateBox(panel
->parent
);
469 WMSetBoxExpandsToParent(panel
->box
, 2, 2, 0, 0);
471 panel
->typeP
= WMCreatePopUpButton(panel
->box
);
472 WMResizeWidget(panel
->typeP
, 150, 20);
473 WMMoveWidget(panel
->typeP
, 10, 10);
475 WMAddPopUpButtonItem(panel
->typeP
, _("New Items"));
476 WMAddPopUpButtonItem(panel
->typeP
, _("Sample Commands"));
477 WMAddPopUpButtonItem(panel
->typeP
, _("Sample Submenus"));
479 WMSetPopUpButtonAction(panel
->typeP
, changedItemPad
, panel
);
481 WMSetPopUpButtonSelectedItem(panel
->typeP
, 0);
488 pad
= makeFactoryMenu(panel
->box
, 150);
489 WMMoveWidget(pad
, 10, 40);
491 data
= putNewItem(panel
, pad
, ExecInfo
, _("Run Program"));
492 data
= putNewItem(panel
, pad
, CommandInfo
, _("Internal Command"));
493 smenu
= putNewSubmenu(pad
, _("Submenu"));
494 data
= putNewItem(panel
, pad
, ExternalInfo
, _("External Submenu"));
495 data
= putNewItem(panel
, pad
, PipeInfo
, _("Generated Submenu"));
496 data
= putNewItem(panel
, pad
, DirectoryInfo
, _("Directory Contents"));
497 data
= putNewItem(panel
, pad
, WSMenuInfo
, _("Workspace Menu"));
499 panel
->itemPad
[0] = pad
;
507 sview
= WMCreateScrollView(panel
->box
);
508 WMResizeWidget(sview
, 150, 180);
509 WMMoveWidget(sview
, 10, 40);
510 WMSetScrollViewHasVerticalScroller(sview
, True
);
512 pad
= makeFactoryMenu(panel
->box
, 130);
514 WMSetScrollViewContentView(sview
, WMWidgetView(pad
));
516 data
= putNewItem(panel
, pad
, ExecInfo
, _("XTerm"));
517 data
->param
.exec
.command
= "xterm -sb -sl 2000 -bg black -fg white";
519 data
= putNewItem(panel
, pad
, ExecInfo
, _("rxvt"));
520 data
->param
.exec
.command
= "rxvt";
522 data
= putNewItem(panel
, pad
, ExecInfo
, _("ETerm"));
523 data
->param
.exec
.command
= "eterm";
525 data
= putNewItem(panel
, pad
, ExecInfo
, _("Run..."));
526 data
->param
.exec
.command
= "%a(Run,Type command to run)";
528 data
= putNewItem(panel
, pad
, ExecInfo
, _("Netscape"));
529 data
->param
.exec
.command
= "netscape";
531 data
= putNewItem(panel
, pad
, ExecInfo
, _("gimp"));
532 data
->param
.exec
.command
= "gimp";
534 data
= putNewItem(panel
, pad
, ExecInfo
, _("epic"));
535 data
->param
.exec
.command
= "xterm -e epic";
537 data
= putNewItem(panel
, pad
, ExecInfo
, _("ee"));
538 data
->param
.exec
.command
= "ee";
540 data
= putNewItem(panel
, pad
, ExecInfo
, _("xv"));
541 data
->param
.exec
.command
= "xv";
543 data
= putNewItem(panel
, pad
, ExecInfo
, _("Acrobat Reader"));
544 data
->param
.exec
.command
= "acroread || /usr/local/Acrobat4/bin/acroread";
546 data
= putNewItem(panel
, pad
, ExecInfo
, _("ghostview"));
547 data
->param
.exec
.command
= "gv";
549 data
= putNewItem(panel
, pad
, CommandInfo
, _("Exit Window Maker"));
550 data
->param
.command
.command
= 3;
554 panel
->itemPad
[1] = sview
;
559 WEditMenu
*pad
, *smenu
;
563 sview
= WMCreateScrollView(panel
->box
);
564 WMResizeWidget(sview
, 150, 180);
565 WMMoveWidget(sview
, 10, 40);
566 WMSetScrollViewHasVerticalScroller(sview
, True
);
568 pad
= makeFactoryMenu(panel
->box
, 130);
570 WMSetScrollViewContentView(sview
, WMWidgetView(pad
));
572 data
= putNewItem(panel
, pad
, ExternalInfo
, _("Debian Menu"));
573 data
->param
.pipe
.command
= "/etc/X11/WindowMaker/menu.hook";
575 data
= putNewItem(panel
, pad
, PipeInfo
, _("RedHat Menu"));
576 data
->param
.pipe
.command
= "wmconfig --output wmaker";
578 data
= putNewItem(panel
, pad
, PipeInfo
, _("Menu Conectiva"));
579 data
->param
.pipe
.command
= "wmconfig --output wmaker";
581 data
= putNewItem(panel
, pad
, DirectoryInfo
, _("Themes"));
582 data
->param
.directory
.command
= "setstyle";
583 data
->param
.directory
.directory
= "/usr/share/WindowMaker/Themes /usr/local/share/WindowMaker/Themes $HOME/GNUstep/Library/WindowMaker/Themes";
584 data
->param
.directory
.stripExt
= 1;
586 data
= putNewItem(panel
, pad
, DirectoryInfo
, _("Bg Images (scale)"));
587 data
->param
.directory
.command
= "wmsetbg -u -s";
588 data
->param
.directory
.directory
= "/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
589 data
->param
.directory
.stripExt
= 1;
591 data
= putNewItem(panel
, pad
, DirectoryInfo
, _("Bg Images (tile)"));
592 data
->param
.directory
.command
= "wmsetbg -u -t";
593 data
->param
.directory
.directory
= "/opt/kde2/share/wallpapers /usr/share/WindowMaker/Backgrounds $HOME/GNUstep/Library/WindowMaker/Backgrounds";
594 data
->param
.directory
.stripExt
= 1;
596 smenu
= putNewSubmenu(pad
, _("Assorted XTerms"));
598 data
= putNewItem(panel
, smenu
, ExecInfo
, _("XTerm Yellow on Blue"));
599 data
->param
.exec
.command
= "xterm -sb -sl 2000 -bg midnightblue -fg yellow";
601 data
= putNewItem(panel
, smenu
, ExecInfo
, _("XTerm White on Black"));
602 data
->param
.exec
.command
= "xterm -sb -sl 2000 -bg black -fg white";
604 data
= putNewItem(panel
, smenu
, ExecInfo
, _("XTerm Black on White"));
605 data
->param
.exec
.command
= "xterm -sb -sl 2000 -bg white -fg black";
607 data
= putNewItem(panel
, smenu
, ExecInfo
, _("XTerm Black on Beige"));
608 data
->param
.exec
.command
= "xterm -sb -sl 2000 -bg '#bbbb99' -fg black";
610 data
= putNewItem(panel
, smenu
, ExecInfo
, _("XTerm White on Green"));
611 data
->param
.exec
.command
= "xterm -sb -sl 2000 -bg '#228822' -fg white";
613 data
= putNewItem(panel
, smenu
, ExecInfo
, _("XTerm White on Olive"));
614 data
->param
.exec
.command
= "xterm -sb -sl 2000 -bg '#335533' -fg white";
616 data
= putNewItem(panel
, smenu
, ExecInfo
, _("XTerm Blue on Blue"));
617 data
->param
.exec
.command
= "xterm -sb -sl 2000 -bg '#112244' -fg '#88aabb'";
619 data
= putNewItem(panel
, smenu
, ExecInfo
, _("XTerm BIG FONTS"));
620 data
->param
.exec
.command
= "xterm -sb -sl 2000 -bg black -fg white -fn 10x20";
624 panel
->itemPad
[2] = sview
;
628 width
= FRAME_WIDTH
- 20 - 150 - 10;
630 panel
->optionsF
= WMCreateFrame(panel
->box
);
631 WMResizeWidget(panel
->optionsF
, width
, FRAME_HEIGHT
- 15);
632 WMMoveWidget(panel
->optionsF
, 10 + 150 + 10, 5);
638 panel
->commandF
= WMCreateFrame(panel
->optionsF
);
639 WMResizeWidget(panel
->commandF
, width
, 50);
640 WMMoveWidget(panel
->commandF
, 10, 20);
641 WMSetFrameTitle(panel
->commandF
, _("Program to Run"));
643 panel
->commandT
= WMCreateTextField(panel
->commandF
);
644 WMResizeWidget(panel
->commandT
, width
- 20, 20);
645 WMMoveWidget(panel
->commandT
, 10, 20);
647 WMAddNotificationObserver(dataChanged
, panel
,
648 WMTextDidChangeNotification
,
652 panel
->xtermC
= WMCreateSwitchButton(panel
->commandF
);
653 WMResizeWidget(panel
->xtermC
, width
- 20, 20);
654 WMMoveWidget(panel
->xtermC
, 10, 50);
655 WMSetButtonText(panel
->xtermC
, _("Run the program inside a Xterm"));
657 WMMapSubwidgets(panel
->commandF
);
662 panel
->pathF
= WMCreateFrame(panel
->optionsF
);
663 WMResizeWidget(panel
->pathF
, width
, 150);
664 WMMoveWidget(panel
->pathF
, 10, 40);
665 WMSetFrameTitle(panel
->pathF
, _("Path for Menu"));
667 panel
->pathT
= WMCreateTextField(panel
->pathF
);
668 WMResizeWidget(panel
->pathT
, width
- 20, 20);
669 WMMoveWidget(panel
->pathT
, 10, 20);
671 WMAddNotificationObserver(dataChanged
, panel
,
672 WMTextDidChangeNotification
,
675 label
= WMCreateLabel(panel
->pathF
);
676 WMResizeWidget(label
, width
- 20, 80);
677 WMMoveWidget(label
, 10, 50);
678 WMSetLabelText(label
, _("Enter the path for a file containing a menu\n"
679 "or a list of directories with the programs you\n"
680 "want to have listed in the menu. Ex:\n"
681 "~/GNUstep/Library/WindowMaker/menu\n"
683 "/usr/X11R6/bin ~/xbin"));
685 WMMapSubwidgets(panel
->pathF
);
690 panel
->pipeF
= WMCreateFrame(panel
->optionsF
);
691 WMResizeWidget(panel
->pipeF
, width
, 100);
692 WMMoveWidget(panel
->pipeF
, 10, 50);
693 WMSetFrameTitle(panel
->pipeF
, _("Command"));
695 panel
->pipeT
= WMCreateTextField(panel
->pipeF
);
696 WMResizeWidget(panel
->pipeT
, width
- 20, 20);
697 WMMoveWidget(panel
->pipeT
, 10, 20);
699 WMAddNotificationObserver(dataChanged
, panel
,
700 WMTextDidChangeNotification
,
704 label
= WMCreateLabel(panel
->pipeF
);
705 WMResizeWidget(label
, width
- 20, 40);
706 WMMoveWidget(label
, 10, 50);
707 WMSetLabelText(label
, _("Enter a command that outputs a menu\n"
708 "definition to stdout when invoked."));
710 WMMapSubwidgets(panel
->pipeF
);
715 panel
->dcommandF
= WMCreateFrame(panel
->optionsF
);
716 WMResizeWidget(panel
->dcommandF
, width
, 90);
717 WMMoveWidget(panel
->dcommandF
, 10, 25);
718 WMSetFrameTitle(panel
->dcommandF
, _("Command to Open Files"));
720 panel
->dcommandT
= WMCreateTextField(panel
->dcommandF
);
721 WMResizeWidget(panel
->dcommandT
, width
- 20, 20);
722 WMMoveWidget(panel
->dcommandT
, 10, 20);
724 WMAddNotificationObserver(dataChanged
, panel
,
725 WMTextDidChangeNotification
,
729 label
= WMCreateLabel(panel
->dcommandF
);
730 WMResizeWidget(label
, width
- 20, 45);
731 WMMoveWidget(label
, 10, 40);
732 WMSetLabelText(label
, _("Enter the command you want to use to open the\n"
733 "files in the directories listed below."));
735 WMMapSubwidgets(panel
->dcommandF
);
738 panel
->dpathF
= WMCreateFrame(panel
->optionsF
);
739 WMResizeWidget(panel
->dpathF
, width
, 80);
740 WMMoveWidget(panel
->dpathF
, 10, 125);
741 WMSetFrameTitle(panel
->dpathF
, _("Directories with Files"));
743 panel
->dpathT
= WMCreateTextField(panel
->dpathF
);
744 WMResizeWidget(panel
->dpathT
, width
- 20, 20);
745 WMMoveWidget(panel
->dpathT
, 10, 20);
747 WMAddNotificationObserver(dataChanged
, panel
,
748 WMTextDidChangeNotification
,
751 panel
->dstripB
= WMCreateSwitchButton(panel
->dpathF
);
752 WMResizeWidget(panel
->dstripB
, width
- 20, 20);
753 WMMoveWidget(panel
->dstripB
, 10, 50);
754 WMSetButtonText(panel
->dstripB
, _("Strip extensions from file names"));
756 WMSetButtonAction(panel
->dstripB
, buttonClicked
, panel
);
758 WMMapSubwidgets(panel
->dpathF
);
763 panel
->shortF
= WMCreateFrame(panel
->optionsF
);
764 WMResizeWidget(panel
->shortF
, width
, 50);
765 WMMoveWidget(panel
->shortF
, 10, 160);
766 WMSetFrameTitle(panel
->shortF
, _("Keyboard Shortcut"));
768 panel
->shortT
= WMCreateTextField(panel
->shortF
);
769 WMResizeWidget(panel
->shortT
, width
- 20 - 170, 20);
770 WMMoveWidget(panel
->shortT
, 10, 20);
772 WMAddNotificationObserver(dataChanged
, panel
,
773 WMTextDidChangeNotification
,
776 panel
->sgrabB
= WMCreateCommandButton(panel
->shortF
);
777 WMResizeWidget(panel
->sgrabB
, 80, 24);
778 WMMoveWidget(panel
->sgrabB
, width
- 90, 18);
779 WMSetButtonText(panel
->sgrabB
, _("Capture"));
780 WMSetButtonAction(panel
->sgrabB
, sgrabClicked
, panel
);
782 panel
->sclearB
= WMCreateCommandButton(panel
->shortF
);
783 WMResizeWidget(panel
->sclearB
, 80, 24);
784 WMMoveWidget(panel
->sclearB
, width
- 175, 18);
785 WMSetButtonText(panel
->sclearB
, _("Clear"));
786 WMSetButtonAction(panel
->sclearB
, sgrabClicked
, panel
);
788 WMMapSubwidgets(panel
->shortF
);
790 /* internal command */
792 panel
->icommandL
= WMCreateList(panel
->optionsF
);
793 WMResizeWidget(panel
->icommandL
, width
, 80);
794 WMMoveWidget(panel
->icommandL
, 10, 20);
796 WMSetListAction(panel
->icommandL
, icommandLClicked
, panel
);
798 WMAddNotificationObserver(dataChanged
, panel
,
799 WMListSelectionDidChangeNotification
,
802 WMInsertListItem(panel
->icommandL
, 0, _("Arrange Icons"));
803 WMInsertListItem(panel
->icommandL
, 1, _("Hide All Windows Except For The Focused One"));
804 WMInsertListItem(panel
->icommandL
, 2, _("Show All Windows"));
806 WMInsertListItem(panel
->icommandL
, 3, _("Exit Window Maker"));
807 WMInsertListItem(panel
->icommandL
, 4, _("Exit X Session"));
808 WMInsertListItem(panel
->icommandL
, 5, _("Restart Window Maker"));
809 WMInsertListItem(panel
->icommandL
, 6, _("Start Another Window Manager : ("));
811 WMInsertListItem(panel
->icommandL
, 7, _("Save Current Session"));
812 WMInsertListItem(panel
->icommandL
, 8, _("Clear Saved Session"));
813 WMInsertListItem(panel
->icommandL
, 9, _("Refresh Screen"));
814 WMInsertListItem(panel
->icommandL
, 10, _("Open Info Panel"));
815 WMInsertListItem(panel
->icommandL
, 11, _("Open Copyright Panel"));
818 panel
->paramF
= WMCreateFrame(panel
->optionsF
);
819 WMResizeWidget(panel
->paramF
, width
, 50);
820 WMMoveWidget(panel
->paramF
, 10, 105);
821 WMSetFrameTitle(panel
->paramF
, _("Window Manager to Start"));
823 panel
->paramT
= WMCreateTextField(panel
->paramF
);
824 WMResizeWidget(panel
->paramT
, width
- 20, 20);
825 WMMoveWidget(panel
->paramT
, 10, 20);
827 WMAddNotificationObserver(dataChanged
, panel
,
828 WMTextDidChangeNotification
,
831 WMMapSubwidgets(panel
->paramF
);
834 panel
->quickB
= WMCreateSwitchButton(panel
->optionsF
);
835 WMResizeWidget(panel
->quickB
, width
, 20);
836 WMMoveWidget(panel
->quickB
, 10, 120);
837 WMSetButtonText(panel
->quickB
, _("Do not confirm action."));
838 WMSetButtonAction(panel
->quickB
, buttonClicked
, panel
);
843 label
= WMCreateLabel(panel
->optionsF
);
844 WMResizeWidget(label
, width
- 10, FRAME_HEIGHT
- 50);
845 WMMoveWidget(label
, 10, 20);
846 WMSetLabelText(label
,
847 _("Instructions:\n\n"
848 " - drag items from the left to the menu to add new items\n"
849 " - drag items out of the menu to remove items\n"
850 " - drag items in menu to change their position\n"
851 " - drag items with Control pressed to copy them\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
->box
);
857 WMMapSubwidgets(panel
->box
);
858 WMMapWidget(panel
->box
);
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] = panel
->shortF
;
876 panel
->sections
[ExternalInfo
][0] = panel
->pathF
;
878 panel
->sections
[PipeInfo
][0] = panel
->pipeF
;
880 panel
->sections
[DirectoryInfo
][0] = panel
->dpathF
;
881 panel
->sections
[DirectoryInfo
][1] = panel
->dcommandF
;
883 panel
->currentType
= NoInfo
;
890 pos
= WMGetViewScreenPosition(WMWidgetView(panel
->box
));
893 pos
.x
+= FRAME_WIDTH
+ 20;
898 pos
.y
= WMAX(pos
.y
- 100, 0);
900 WEditMenuShowAt(panel
->menu
, pos
.x
, pos
.y
);
908 freeItemData(ItemData
*data
)
910 #define CFREE(d) if (d) wfree(d)
913 switch (data
->type
) {
915 CFREE(data
->param
.command
.parameter
);
916 CFREE(data
->param
.command
.shortcut
);
920 CFREE(data
->param
.exec
.command
);
921 CFREE(data
->param
.exec
.shortcut
);
925 CFREE(data
->param
.pipe
.command
);
929 CFREE(data
->param
.external
.path
);
933 CFREE(data
->param
.directory
.command
);
934 CFREE(data
->param
.directory
.directory
);
947 parseCommand(proplist_t item
)
949 ItemData
*data
= NEW(ItemData
);
951 char *command
= NULL
;
952 char *parameter
= NULL
;
953 char *shortcut
= NULL
;
957 p
= PLGetArrayElement(item
, i
++);
958 command
= PLGetString(p
);
959 if (strcmp(command
, "SHORTCUT") == 0) {
960 p
= PLGetArrayElement(item
, i
++);
961 shortcut
= PLGetString(p
);
962 p
= PLGetArrayElement(item
, i
++);
963 command
= PLGetString(p
);
965 p
= PLGetArrayElement(item
, i
++);
967 parameter
= PLGetString(p
);
969 if (strcmp(command
, "EXEC") == 0 || strcmp(command
, "SHEXEC") == 0) {
971 data
->type
= ExecInfo
;
973 data
->param
.exec
.command
= wstrdup(parameter
);
975 data
->param
.exec
.shortcut
= wstrdup(shortcut
);
977 } else if (strcmp(command
, "OPEN_MENU") == 0) {
980 * dir menu, menu file
982 * |pipe (TODO: ||pipe)
985 while (isspace(*p
) && *p
) p
++;
987 data
->type
= PipeInfo
;
988 data
->param
.pipe
.command
= wtrimspace(p
+1);
994 s
= strstr(p
, "WITH");
1001 data
->type
= DirectoryInfo
;
1005 while (*s
&& isspace(*s
)) s
++;
1006 data
->param
.directory
.command
= wstrdup(s
);
1008 wtokensplit(p
, &tokens
, &tokn
);
1011 ctokens
= wmalloc(sizeof(char*)*tokn
);
1013 for (i
= 0, j
= 0; i
< tokn
; i
++) {
1014 if (strcmp(tokens
[i
], "-noext") == 0) {
1016 data
->param
.directory
.stripExt
= 1;
1018 ctokens
[j
++] = tokens
[i
];
1021 data
->param
.directory
.directory
= wtokenjoin(ctokens
, j
);
1024 wtokenfree(tokens
, tokn
);
1026 data
->type
= ExternalInfo
;
1027 data
->param
.external
.path
= p
;
1030 } else if (strcmp(command
, "WORKSPACE_MENU") == 0) {
1031 data
->type
= WSMenuInfo
;
1035 if (strcmp(command
, "ARRANGE_ICONS") == 0) {
1037 } else if (strcmp(command
, "HIDE_OTHERS") == 0) {
1039 } else if (strcmp(command
, "SHOW_ALL") == 0) {
1041 } else if (strcmp(command
, "EXIT") == 0) {
1043 } else if (strcmp(command
, "SHUTDOWN") == 0) {
1045 } else if (strcmp(command
, "RESTART") == 0) {
1051 } else if (strcmp(command
, "SAVE_SESSION") == 0) {
1053 } else if (strcmp(command
, "CLEAR_SESSION") == 0) {
1055 } else if (strcmp(command
, "REFRESH") == 0) {
1057 } else if (strcmp(command
, "INFO_PANEL") == 0) {
1059 } else if (strcmp(command
, "LEGAL_PANEL") == 0) {
1062 wwarning(_("unknown command '%s' in menu"), command
);
1066 data
->type
= CommandInfo
;
1068 data
->param
.command
.command
= cmd
;
1070 data
->param
.command
.shortcut
= wstrdup(shortcut
);
1072 data
->param
.command
.parameter
= wstrdup(parameter
);
1087 updateFrameTitle(_Panel
*panel
, char *title
, InfoType type
)
1089 if (type
!= NoInfo
) {
1094 tmp
= wstrconcat(title
, _(": Execute Program"));
1098 tmp
= wstrconcat(title
, _(": Perform Internal Command"));
1102 tmp
= wstrconcat(title
, _(": Open a Submenu"));
1106 tmp
= wstrconcat(title
, _(": Program Generated Submenu"));
1110 tmp
= wstrconcat(title
, _(": Directory Contents Menu"));
1114 tmp
= wstrconcat(title
, _(": Open Workspaces Submenu"));
1121 WMSetFrameTitle(panel
->optionsF
, tmp
);
1124 WMSetFrameTitle(panel
->optionsF
, NULL
);
1131 changeInfoType(_Panel
*panel
, char *title
, InfoType type
)
1135 if (panel
->currentType
!= type
) {
1137 w
= panel
->sections
[panel
->currentType
];
1143 WMUnmapWidget(panel
->paramF
);
1144 WMUnmapWidget(panel
->quickB
);
1147 w
= panel
->sections
[type
];
1155 updateFrameTitle(panel
, title
, type
);
1157 panel
->currentType
= type
;
1164 updateMenuItem(_Panel
*panel
, WEditMenuItem
*item
, WMWidget
*changedWidget
)
1166 ItemData
*data
= WGetEditMenuItemData(item
);
1168 assert(data
!= NULL
);
1170 #define REPLACE(v, d) if (v) wfree(v); v = d
1172 switch (data
->type
) {
1174 if (changedWidget
== panel
->commandT
) {
1175 REPLACE(data
->param
.exec
.command
,
1176 WMGetTextFieldText(panel
->commandT
));
1178 if (changedWidget
== panel
->shortT
) {
1179 REPLACE(data
->param
.exec
.shortcut
,
1180 WMGetTextFieldText(panel
->shortT
));
1185 if (changedWidget
== panel
->icommandL
) {
1186 data
->param
.command
.command
=
1187 WMGetListSelectedItemRow(panel
->icommandL
);
1189 switch (data
->param
.command
.command
) {
1192 if (changedWidget
== panel
->quickB
) {
1193 REPLACE(data
->param
.command
.parameter
,
1194 WMGetButtonSelected(panel
->quickB
)
1195 ? wstrdup("QUICK") : NULL
);
1200 if (changedWidget
== panel
->paramT
) {
1201 REPLACE(data
->param
.command
.parameter
,
1202 WMGetTextFieldText(panel
->paramT
));
1206 if (changedWidget
== panel
->shortT
) {
1207 REPLACE(data
->param
.command
.shortcut
,
1208 WMGetTextFieldText(panel
->shortT
));
1215 if (changedWidget
== panel
->pipeT
) {
1216 REPLACE(data
->param
.pipe
.command
,
1217 WMGetTextFieldText(panel
->pipeT
));
1222 if (changedWidget
== panel
->pathT
) {
1223 REPLACE(data
->param
.external
.path
,
1224 WMGetTextFieldText(panel
->pathT
));
1229 if (changedWidget
== panel
->dpathT
) {
1230 REPLACE(data
->param
.directory
.directory
,
1231 WMGetTextFieldText(panel
->dpathT
));
1233 if (changedWidget
== panel
->dcommandT
) {
1234 REPLACE(data
->param
.directory
.command
,
1235 WMGetTextFieldText(panel
->dcommandT
));
1237 if (changedWidget
== panel
->dstripB
) {
1238 data
->param
.directory
.stripExt
=
1239 WMGetButtonSelected(panel
->dstripB
);
1254 menuItemCloned(WEditMenuDelegate
*delegate
, WEditMenu
*menu
,
1255 WEditMenuItem
*origItem
, WEditMenuItem
*newItem
)
1257 ItemData
*data
= WGetEditMenuItemData(origItem
);
1263 #define DUP(s) (s) ? wstrdup(s) : NULL
1265 newData
= NEW(ItemData
);
1267 newData
->type
= data
->type
;
1269 switch (data
->type
) {
1271 newData
->param
.exec
.command
= DUP(data
->param
.exec
.command
);
1272 newData
->param
.exec
.shortcut
= DUP(data
->param
.exec
.shortcut
);
1276 newData
->param
.command
.command
= data
->param
.command
.command
;
1277 newData
->param
.command
.parameter
= DUP(data
->param
.command
.parameter
);
1278 newData
->param
.command
.shortcut
= DUP(data
->param
.command
.shortcut
);
1282 newData
->param
.pipe
.command
= DUP(data
->param
.pipe
.command
);
1286 newData
->param
.external
.path
= DUP(data
->param
.external
.path
);
1290 newData
->param
.directory
.directory
= DUP(data
->param
.directory
.directory
);
1291 newData
->param
.directory
.command
= DUP(data
->param
.directory
.command
);
1292 newData
->param
.directory
.stripExt
= data
->param
.directory
.stripExt
;
1301 WSetEditMenuItemData(newItem
, newData
, (WMCallback
*)freeItemData
);
1306 menuItemEdited(struct WEditMenuDelegate
*delegate
, WEditMenu
*menu
,
1307 WEditMenuItem
*item
)
1309 _Panel
*panel
= (_Panel
*)delegate
->data
;
1312 updateFrameTitle(panel
, WGetEditMenuItemTitle(item
), panel
->currentType
);
1314 submenu
= WGetEditMenuSubmenu(menu
, item
);
1316 WSetEditMenuTitle(submenu
, WGetEditMenuItemTitle(item
));
1322 shouldRemoveItem(struct WEditMenuDelegate
*delegate
, WEditMenu
*menu
,
1323 WEditMenuItem
*item
)
1325 _Panel
*panel
= (_Panel
*)delegate
->data
;
1330 if (WGetEditMenuSubmenu(menu
, item
)) {
1333 res
= WMRunAlertPanel(WMWidgetScreen(menu
), NULL
,
1334 _("Remove Submenu"),
1335 _("Removing this item will destroy all items inside\n"
1336 "the submenu. Do you really want to do that?"),
1338 _("Yes, don't ask again."));
1345 panel
->dontAsk
= True
;
1354 menuItemDeselected(WEditMenuDelegate
*delegate
, WEditMenu
*menu
,
1355 WEditMenuItem
*item
)
1357 _Panel
*panel
= (_Panel
*)delegate
->data
;
1359 changeInfoType(panel
, NULL
, NoInfo
);
1364 menuItemSelected(WEditMenuDelegate
*delegate
, WEditMenu
*menu
,
1365 WEditMenuItem
*item
)
1367 ItemData
*data
= WGetEditMenuItemData(item
);
1368 _Panel
*panel
= (_Panel
*)delegate
->data
;
1370 panel
->currentItem
= item
;
1373 changeInfoType(panel
, WGetEditMenuItemTitle(item
), data
->type
);
1375 switch (data
->type
) {
1380 WMSetTextFieldText(panel
->commandT
, data
->param
.exec
.command
);
1381 WMSetTextFieldText(panel
->shortT
, data
->param
.exec
.shortcut
);
1385 WMSelectListItem(panel
->icommandL
,
1386 data
->param
.command
.command
);
1387 WMSetListPosition(panel
->icommandL
,
1388 data
->param
.command
.command
- 2);
1389 WMSetTextFieldText(panel
->shortT
, data
->param
.command
.shortcut
);
1391 switch (data
->param
.command
.command
) {
1394 WMSetButtonSelected(panel
->quickB
,
1395 data
->param
.command
.parameter
!=NULL
);
1398 WMSetTextFieldText(panel
->paramT
,
1399 data
->param
.command
.parameter
);
1403 icommandLClicked(panel
->icommandL
, panel
);
1407 WMSetTextFieldText(panel
->pipeT
, data
->param
.pipe
.command
);
1411 WMSetTextFieldText(panel
->pathT
, data
->param
.external
.path
);
1415 WMSetTextFieldText(panel
->dpathT
, data
->param
.directory
.directory
);
1416 WMSetTextFieldText(panel
->dcommandT
, data
->param
.directory
.command
);
1417 WMSetButtonSelected(panel
->dstripB
, data
->param
.directory
.stripExt
);
1432 buildSubmenu(_Panel
*panel
, proplist_t pl
)
1434 WMScreen
*scr
= WMWidgetScreen(panel
->parent
);
1436 WEditMenuItem
*item
;
1441 tp
= PLGetArrayElement(pl
, 0);
1442 title
= PLGetString(tp
);
1444 menu
= WCreateEditMenu(scr
, title
);
1446 for (i
= 1; i
< PLGetNumberOfElements(pl
); i
++) {
1449 pi
= PLGetArrayElement(pl
, i
);
1451 tp
= PLGetArrayElement(pi
, 0);
1452 bp
= PLGetArrayElement(pi
, 1);
1454 title
= PLGetString(tp
);
1456 if (!bp
|| PLIsArray(bp
)) { /* it's a submenu */
1459 submenu
= buildSubmenu(panel
, pi
);
1461 item
= WAddMenuItemWithTitle(menu
, title
);
1463 WSetEditMenuSubmenu(menu
, item
, submenu
);
1467 item
= WAddMenuItemWithTitle(menu
, title
);
1469 data
= parseCommand(pi
);
1471 if (panel
->markerPix
[data
->type
])
1472 WSetEditMenuItemImage(item
, panel
->markerPix
[data
->type
]);
1473 WSetEditMenuItemData(item
, data
, (WMCallback
*)freeItemData
);
1477 WSetEditMenuAcceptsDrop(menu
, True
);
1478 WSetEditMenuDelegate(menu
, &menuDelegate
);
1480 WMRealizeWidget(menu
);
1488 buildMenuFromPL(_Panel
*panel
, proplist_t pl
)
1490 panel
->menu
= buildSubmenu(panel
, pl
);
1496 getDefaultMenu(_Panel
*panel
)
1498 proplist_t menu
, pmenu
;
1499 char *menuPath
, *gspath
;
1501 gspath
= wusergnusteppath();
1503 menuPath
= wmalloc(strlen(gspath
)+128);
1504 /* if there is a localized plmenu for the tongue put it's filename here */
1505 sprintf(menuPath
, _("%s/Library/WindowMaker/plmenu"), gspath
);
1507 menu
= PLGetProplistWithPath(menuPath
);
1509 wwarning("%s:could not read property list menu", menuPath
);
1511 if (strcmp("%s/Library/WindowMaker/plmenu",
1512 _("%s/Library/WindowMaker/plmenu"))!=0) {
1514 sprintf(menuPath
, "%s/Library/WindowMaker/plmenu", gspath
);
1515 menu
= PLGetProplistWithPath(menuPath
);
1516 wwarning("%s:could not read property list menu", menuPath
);
1521 sprintf(buffer
, _("Could not open default menu from '%s'"),
1523 WMRunAlertPanel(WMWidgetScreen(panel
->parent
), panel
->parent
,
1524 _("Error"), buffer
, _("OK"), NULL
, NULL
);
1541 showData(_Panel
*panel
)
1547 gspath
= wusergnusteppath();
1549 menuPath
= wmalloc(strlen(gspath
)+32);
1550 strcpy(menuPath
, gspath
);
1551 strcat(menuPath
, "/Defaults/WMRootMenu");
1553 pmenu
= PLGetProplistWithPath(menuPath
);
1555 if (!pmenu
|| !PLIsArray(pmenu
)) {
1558 res
= WMRunAlertPanel(WMWidgetScreen(panel
->parent
), panel
->parent
,
1560 _("The menu file format currently in use is not supported\n"
1561 "by this tool. Do you want to discard the current menu\n"
1562 "to use this tool?"),
1563 _("Yes, Discard and Update"),
1564 _("No, Keep Current Menu"), NULL
);
1566 if (res
== WAPRDefault
) {
1567 pmenu
= getDefaultMenu(panel
);
1570 pmenu
= PLMakeArrayFromElements(PLMakeString("Applications"),
1574 panel
->dontSave
= True
;
1579 panel
->menuPath
= menuPath
;
1581 buildMenuFromPL(panel
, pmenu
);
1601 processData(char *title
, ItemData
*data
)
1605 static char *pscut
= NULL
;
1606 static char *pomenu
= NULL
;
1610 pscut
= PLMakeString("SHORTCUT");
1611 pomenu
= PLMakeString("OPEN_MENU");
1614 item
= PLMakeArrayFromElements(PLMakeString(title
), NULL
);
1617 switch (data
->type
) {
1620 if (strpbrk(data
->param
.exec
.command
, "&$*|><?`=")) {
1629 if (notblank(data
->param
.exec
.shortcut
)) {
1630 PLAppendArrayElement(item
, pscut
);
1631 PLAppendArrayElement(item
,
1632 PLMakeString(data
->param
.exec
.shortcut
));
1635 PLAppendArrayElement(item
, PLMakeString(s1
));
1636 PLAppendArrayElement(item
, PLMakeString(data
->param
.exec
.command
));
1640 if (notblank(data
->param
.command
.shortcut
)) {
1641 PLAppendArrayElement(item
, pscut
);
1642 PLAppendArrayElement(item
,
1643 PLMakeString(data
->param
.command
.shortcut
));
1646 i
= data
->param
.command
.command
;
1648 PLAppendArrayElement(item
, PLMakeString(commandNames
[i
]));
1653 if (data
->param
.command
.parameter
) {
1654 PLAppendArrayElement(item
,
1655 PLMakeString(data
->param
.command
.parameter
));
1659 case 6: /* restart */
1660 if (data
->param
.command
.parameter
) {
1661 PLAppendArrayElement(item
,
1662 PLMakeString(data
->param
.command
.parameter
));
1670 PLAppendArrayElement(item
, pomenu
);
1671 s1
= wstrconcat("| ", data
->param
.pipe
.command
);
1672 PLAppendArrayElement(item
, PLMakeString(s1
));
1677 PLAppendArrayElement(item
, pomenu
);
1678 PLAppendArrayElement(item
, PLMakeString(data
->param
.external
.path
));
1686 l
= strlen(data
->param
.directory
.directory
);
1687 l
+= strlen(data
->param
.directory
.command
);
1690 PLAppendArrayElement(item
, pomenu
);
1693 sprintf(tmp
, "%s%s WITH %s",
1694 data
->param
.directory
.stripExt
? "-noext " : "",
1695 data
->param
.directory
.directory
,
1696 data
->param
.directory
.command
);
1698 PLAppendArrayElement(item
, PLMakeString(tmp
));
1704 PLAppendArrayElement(item
, PLMakeString("WORKSPACE_MENU"));
1717 processSubmenu(WEditMenu
*menu
)
1719 WEditMenuItem
*item
;
1726 s
= WGetEditMenuTitle(menu
);
1727 pl
= PLMakeString(s
);
1729 pmenu
= PLMakeArrayFromElements(pl
, NULL
);
1732 while ((item
= WGetEditMenuItem(menu
, i
++))) {
1735 s
= WGetEditMenuItemTitle(item
);
1737 submenu
= WGetEditMenuSubmenu(menu
, item
);
1739 pl
= processSubmenu(submenu
);
1741 pl
= processData(s
, WGetEditMenuItemData(item
));
1744 PLAppendArrayElement(pmenu
, pl
);
1753 buildPLFromMenu(_Panel
*panel
)
1757 menu
= processSubmenu(panel
->menu
);
1766 storeData(_Panel
*panel
)
1770 if (panel
->dontSave
)
1773 menu
= buildPLFromMenu(panel
);
1775 PLSetFilename(menu
, PLMakeString(panel
->menuPath
));
1785 showMenus(_Panel
*panel
)
1787 WEditMenuUnhide(panel
->menu
);
1792 hideMenus(_Panel
*panel
)
1794 WEditMenuHide(panel
->menu
);
1801 InitMenu(WMScreen
*scr
, WMWidget
*parent
)
1805 panel
= wmalloc(sizeof(_Panel
));
1806 memset(panel
, 0, sizeof(_Panel
));
1808 panel
->sectionName
= _("Applications Menu Definition");
1810 panel
->description
= _("Edit the menu for launching applications.");
1812 panel
->parent
= parent
;
1814 panel
->callbacks
.createWidgets
= createPanel
;
1815 panel
->callbacks
.updateDomain
= storeData
;
1816 panel
->callbacks
.showPanel
= showMenus
;
1817 panel
->callbacks
.hidePanel
= hideMenus
;
1820 AddSection(panel
, ICON_FILE
);