2 // "$Id: Fl_Sys_Menu_Bar.cxx 7518 2010-04-16 19:27:28Z manolo $"
4 // MacOS system menu bar widget for the Fast Light Tool Kit (FLTK).
6 // Copyright 1998-2010 by Bill Spitzak and others.
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
29 * This code is a quick hack! It was written as a proof of concept.
30 * It has been tested on the "menubar" sample program and provides
31 * basic functionality.
33 * To use the System Menu Bar, simply replace the main Fl_Menu_Bar
34 * in an application with Fl_Sys_Menu_Bar.
36 * FLTK features not supported by the Mac System menu
38 * - no invisible menu items
39 * - no symbolic labels
40 * - embossed labels will be underlined instead
42 * - Shortcut Characters should be English alphanumeric only, no modifiers yet
43 * - no disable main menus
44 * - changes to menubar in run-time don't update!
45 * (disable, etc. - toggle and radio button do!)
47 * No care was taken to clean up the menu bar after destruction!
48 * ::menu(bar) should only be called once!
49 * Many other calls of the parent class don't work.
50 * Changing the menu items has no effect on the menu bar.
51 * Starting with OS X 10.5, FLTK applications must be created as
52 * a bundle for the System Menu Bar (and maybe other features) to work!
55 #if defined(__APPLE__) || defined(FL_DOXYGEN)
59 #include <FL/Fl_Sys_Menu_Bar.H>
66 #define MenuHandle void *
68 typedef const Fl_Menu_Item
*pFl_Menu_Item
;
72 * Set a shortcut for an Apple menu item using the FLTK shortcut descriptor.
74 static void setMenuShortcut( MenuHandle mh
, int miCnt
, const Fl_Menu_Item
*m
)
78 if ( m
->flags
& FL_SUBMENU
)
80 if ( m
->flags
& FL_SUBMENU_POINTER
)
82 char key
= m
->shortcut_
& 0xff;
83 if ( !isalnum( key
) )
86 void *menuItem
= Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::itemAtIndex
, mh
, miCnt
);
87 Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::setKeyEquivalent
, menuItem
, m
->shortcut_
& 0xff );
88 Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::setKeyEquivalentModifierMask
, menuItem
, m
->shortcut_
);
93 * Set the Toggle and Radio flag based on FLTK flags
95 static void setMenuFlags( MenuHandle mh
, int miCnt
, const Fl_Menu_Item
*m
)
97 if ( m
->flags
& FL_MENU_TOGGLE
)
99 void *menuItem
= Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::itemAtIndex
, mh
, miCnt
);
100 Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::setState
, menuItem
, m
->flags
& FL_MENU_VALUE
);
102 else if ( m
->flags
& FL_MENU_RADIO
) {
103 void *menuItem
= Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::itemAtIndex
, mh
, miCnt
);
104 Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::setState
, menuItem
, m
->flags
& FL_MENU_VALUE
);
110 * create a sub menu for a specific menu handle
112 static void createSubMenu( void * mh
, pFl_Menu_Item
&mm
)
118 submenu
= Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::initWithTitle
, mm
->text
);
120 Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::numberOfItems
, mh
, &cnt
);
122 menuItem
= Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::itemAtIndex
, mh
, cnt
);
123 Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::setSubmenu
, menuItem
, submenu
);
124 if ( mm
->flags
& FL_MENU_INACTIVE
) {
125 Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::setEnabled
, menuItem
, 0);
131 int flRank
= mm
- fl_sys_menu_bar
->Fl_Menu_::menu();
132 Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::addNewItem
, submenu
, flRank
, &miCnt
);
133 setMenuFlags( submenu
, miCnt
, mm
);
134 setMenuShortcut( submenu
, miCnt
, mm
);
135 if ( mm
->flags
& FL_MENU_INACTIVE
) {
136 void *item
= Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::itemAtIndex
, submenu
, miCnt
);
137 Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::setEnabled
, item
, 0);
140 if ( mm
->flags
& FL_SUBMENU
)
142 createSubMenu( submenu
, mm
);
144 else if ( mm
->flags
& FL_SUBMENU_POINTER
)
146 const Fl_Menu_Item
*smm
= (Fl_Menu_Item
*)mm
->user_data_
;
147 createSubMenu( submenu
, smm
);
149 if ( flags
& FL_MENU_DIVIDER
) {
150 Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::addSeparatorItem
, submenu
);
158 * convert a complete Fl_Menu_Item array into a series of menus in the top menu bar
159 * ALL PREVIOUS SYSTEM MENUS, EXCEPT APPLICATION MENU, ARE REPLACED BY THE NEW DATA
161 static void convertToMenuBar(const Fl_Menu_Item
*mm
)
163 int count
;//first, delete all existing system menus
164 Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::numberOfItems
, fl_system_menu
, &count
);
165 for(int i
= count
- 1; i
> 0; i
--) {
166 Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::removeItem
, fl_system_menu
, i
);
168 //now convert FLTK stuff into MacOS menus
171 if ( !mm
|| !mm
->text
)
173 char visible
= mm
->visible() ? 1 : 0;
174 int flRank
= mm
- fl_sys_menu_bar
->Fl_Menu_::menu();
175 Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::addNewItem
, fl_system_menu
, flRank
, NULL
);
177 if ( mm
->flags
& FL_SUBMENU
)
178 createSubMenu( fl_system_menu
, mm
);
179 else if ( mm
->flags
& FL_SUBMENU_POINTER
) {
180 const Fl_Menu_Item
*smm
= (Fl_Menu_Item
*)mm
->user_data_
;
181 createSubMenu( fl_system_menu
, smm
);
184 // InsertMenu( mh, 0 );
192 * @brief create a system menu bar using the given list of menu structs
194 * \author Matthias Melcher
196 * @param m list of Fl_Menu_Item
198 void Fl_Sys_Menu_Bar::menu(const Fl_Menu_Item
*m
)
201 Fl_Menu_Bar::menu( m
);
207 * @brief add to the system menu bar a new menu item
209 * add to the system menu bar a new menu item, with a title string, shortcut int,
210 * callback, argument to the callback, and flags.
212 * @see Fl_Menu_::add(const char* label, int shortcut, Fl_Callback *cb, void *user_data, int flags)
214 int Fl_Sys_Menu_Bar::add(const char* label
, int shortcut
, Fl_Callback
*cb
, void *user_data
, int flags
)
217 int rank
= Fl_Menu_::add(label
, shortcut
, cb
, user_data
, flags
);
218 convertToMenuBar(Fl_Menu_::menu());
223 * @brief insert in the system menu bar a new menu item
225 * insert in the system menu bar a new menu item, with a title string, shortcut int,
226 * callback, argument to the callback, and flags.
228 * @see Fl_Menu_::insert(int index, const char* label, int shortcut, Fl_Callback *cb, void *user_data, int flags)
230 int Fl_Sys_Menu_Bar::insert(int index
, const char* label
, int shortcut
, Fl_Callback
*cb
, void *user_data
, int flags
)
233 int rank
= Fl_Menu_::insert(index
, label
, shortcut
, cb
, user_data
, flags
);
234 convertToMenuBar(Fl_Menu_::menu());
238 void Fl_Sys_Menu_Bar::clear()
241 convertToMenuBar(NULL
);
244 int Fl_Sys_Menu_Bar::clear_submenu(int index
)
246 int retval
= Fl_Menu_::clear_submenu(index
);
247 if (retval
!= -1) convertToMenuBar(Fl_Menu_::menu());
252 * @brief remove an item from the system menu bar
254 * @param rank the rank of the item to remove
256 void Fl_Sys_Menu_Bar::remove(int rank
)
258 Fl_Menu_::remove(rank
);
259 convertToMenuBar(Fl_Menu_::menu());
264 * @brief rename an item from the system menu bar
266 * @param rank the rank of the item to rename
267 * @param name the new item name as a UTF8 string
269 void Fl_Sys_Menu_Bar::replace(int rank
, const char *name
)
271 doMenuOrItemOperation(renameItem
, rank
, name
);
272 fl_sys_menu_bar
->Fl_Menu_::replace(rank
, name
);
278 * Nothing here because the OS does this for us.
280 void Fl_Sys_Menu_Bar::draw() {
284 #endif /* __APPLE__ */
287 // End of "$Id: Fl_Sys_Menu_Bar.cxx 7518 2010-04-16 19:27:28Z manolo $".