source: release/1.5/source/contrib/krueger/InterfaceProjects/Menu/menu-utils.lisp

Last change on this file was 13646, checked in by R. Matthew Emerson, 15 years ago

Merge r13631, r13636 from trunk. (Paul Krueger's updated InterfaceProjects
contrib; fix for ticket:652)

File size: 7.2 KB
RevLine 
[13390]1;; menu-uitls.lisp
2
3#|
4The MIT license.
5
6Copyright (c) 2010 Paul L. Krueger
7
8Permission is hereby granted, free of charge, to any person obtaining a copy of this software
9and associated documentation files (the "Software"), to deal in the Software without restriction,
10including without limitation the rights to use, copy, modify, merge, publish, distribute,
11sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all copies or substantial
15portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
18LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
23|#
24
[13646]25(eval-when (:compile-toplevel :load-toplevel :execute)
26 (require :selector-utils))
[13390]27
28(defpackage :interface-utilities
29 (:nicknames :iu)
30 (:export make-and-install-menu make-and-install-menuitems-after
31 test-menu test2-menu))
32
33(in-package :iu)
34
35;; Utility functions that allow lisp programs to add menus to the existing menubar
36
37#|
38(defun make-menu-item (title-str action-str &key (key-equiv ""))
39 (let* ((ns-title (ccl::%make-nsstring name-str))
40 (action-selector (get-selector action-str))
41 (ns-key (ccl::%make-nsstring key-equiv))
42 (mi (#/initWithTitle:action:keyEquivalent:
43 (#/alloc ns:ns-menu-item)
44 ns-title
45 action-selector
46 ns-key)))
47 (#/autorelease ns-title)
48 (#/autorelease ns-key)
49 (#/autorelease mi)
50 mi))
51
52|#
53
54;; For the following function menu-item-specs should be a list where each
55;; element of the list is itself a list of the form:
56;; (menu-item-name menu-item-action menu-item-key-equivalent menu-item-target)
57;; where each of these except the menu-item-target must be acceptable as an
58;; argument to the function "string". Menu-item-target must be an Ojbective-C object,
59;; but can be nil to signify no target (the default)
60;; Used "menumadness" sample code from Apple Developer website to know what to do ...
61;; NSMenu *newMenu;
62;; NSMenuItem *newItem;
63;;
64;; // Add the submenu
65;; newItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:@"Flashy" action:NULL keyEquivalent:@""];
66;; newMenu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@"Flashy"];
67;; [newItem setSubmenu:newMenu];
68;; [newMenu release];
69;; [[NSApp mainMenu] addItem:newItem];
70;; [newItem release];
71;; Basically you need to create both a menuitem and a menu for any menu displayed in the menubar
72;; and link them together. Then add the menuitem to the main menu (i.e. menubar)
73
74(defun make-and-install-menu (menu-name &rest menu-item-specs)
75 (let* ((ns-menu-name (ccl::%make-nsstring menu-name))
76 (menuitem (#/initWithTitle:action:keyEquivalent:
77 (#/allocWithZone: ns:ns-menu-item
78 (#/menuZone ns:ns-menu))
79 ns-menu-name
80 (%null-ptr)
81 #@""))
82 (menu (#/initWithTitle: (#/allocWithZone:
83 ns:ns-menu (#/menuZone ns:ns-menu))
84 ns-menu-name))
85 (main-menu (#/mainMenu #&NSApp)))
86 (dolist (mi menu-item-specs)
87 (destructuring-bind (mi-title mi-selector &optional (mi-key "") mi-target) mi
88 (let* ((ns-title (ccl::%make-nsstring (string mi-title)))
89 (action-selector (get-selector (string mi-selector)))
90 (ns-key (ccl::%make-nsstring (string mi-key)))
91 (men-item (#/addItemWithTitle:action:keyEquivalent: menu
92 ns-title
93 action-selector
94 ns-key)))
95 (when mi-target
96 (#/setTarget: men-item mi-target))
97 (#/release ns-title)
98 (#/release ns-key))))
99 ;; Link up the new menuitem and new menu
100 (#/setSubmenu: menuitem menu)
101 (#/release menu)
102 ;; Now tell the main menu to make this a sub-menu
103 (#/addItem: main-menu menuitem)
104 (#/release ns-menu-name)
105 (#/release menuitem)
106 menu))
107
108;; The following function inserts one or more new menu-items immediately
109;; following a specified menu-item.
110;; If the menu-item-name is "" the insertion will be after the first divider
111;; (which has a blank name). If the menu-item-name does not exist in the menu,
112;; the items will be placed at the beginning of the menu.
113;; menu-item-specs are as defined above for the make-and-install-menu function.
114;; menu-name and menu-item-name arguments must be acceptable as argument to the
115;; "string" function.
116(defun make-and-install-menuitems-after (menu-name menu-item-name &rest menu-item-specs)
117 (let* ((ns-menu-name (ccl::%make-nsstring menu-name))
118 (main-menu (#/mainMenu #&NSApp))
119 (menuitem (or (#/itemWithTitle: main-menu ns-menu-name)
120 (error "~s is not a valid menu title" menu-name)))
121 (sub-menu (#/submenu menuitem))
122 (ns-menu-item-name (ccl::%make-nsstring menu-item-name))
123 (insert-index (#/indexOfItemWithTitle: sub-menu ns-menu-item-name)))
124 (dolist (mi menu-item-specs)
125 (destructuring-bind (mi-title mi-selector &optional (mi-key "") mi-target) mi
126 (let* ((ns-title (ccl::%make-nsstring (string mi-title)))
127 (action-selector (get-selector (string mi-selector)))
128 (ns-key (ccl::%make-nsstring (string mi-key)))
129 (men-item (#/insertItemWithTitle:action:keyEquivalent:atIndex:
130 sub-menu
131 ns-title
132 action-selector
133 ns-key
134 (incf insert-index))))
135 (when mi-target
136 (#/setTarget: men-item mi-target))
137 (#/release ns-title)
138 (#/release ns-key))))
139 (#/release ns-menu-item-name)
140 (#/release ns-menu-name)))
141
142(defun menu-item-action-selector (menu-name menu-item-name)
143 (let* ((ns-menu-name (ccl::%make-nsstring menu-name))
144 (main-menu (#/mainMenu #&NSApp))
145 (menuitem (or (#/itemWithTitle: main-menu ns-menu-name)
146 (error "~s is not a valid menu title" menu-name)))
147 (sub-menu (#/submenu menuitem))
148 (ns-menu-item-name (ccl::%make-nsstring menu-item-name))
149 (target-mi (#/itemWithTitle: sub-menu ns-menu-item-name)))
150 (#/release ns-menu-item-name)
151 (#/release ns-menu-name)
152 (#/action target-mi)))
153
154
155(defun test-menu ()
156 (make-and-install-menu "New App Menu"
157 '("Menu Item1" "doFirstThing")
158 '("Menu Item2" "doSecondThing")))
159
160(defun test2-menu ()
161 (make-and-install-menuitems-after "File" "New"
162 '("New myDoc" "newMyDoc")))
163
164
165(provide :menu-utils)
Note: See TracBrowser for help on using the repository browser.