Tweak themes for more color consistency.
[ntk.git] / src / Fl_Sys_Menu_Bar.cxx
blob69b47c345f4f6d23bd8a20c82d4ef4bae13a89b0
1 //
2 // "$Id: Fl_Sys_Menu_Bar.cxx 7518 2010-04-16 19:27:28Z manolo $"
3 //
4 // MacOS system menu bar widget for the Fast Light Tool Kit (FLTK).
5 //
6 // Copyright 1998-2010 by Bill Spitzak and others.
7 //
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
21 // USA.
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
28 /**
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
41 * - no font sizes
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)
57 #include <FL/x.H>
58 #include <FL/Fl.H>
59 #include <FL/Fl_Sys_Menu_Bar.H>
61 #include "flstring.h"
62 #include <stdio.h>
63 #include <ctype.h>
64 #include <stdarg.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 )
76 if ( !m->shortcut_ )
77 return;
78 if ( m->flags & FL_SUBMENU )
79 return;
80 if ( m->flags & FL_SUBMENU_POINTER )
81 return;
82 char key = m->shortcut_ & 0xff;
83 if ( !isalnum( key ) )
84 return;
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 )
114 void *submenu;
115 int miCnt, flags;
117 void *menuItem;
118 submenu = Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::initWithTitle, mm->text);
119 int cnt;
120 Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::numberOfItems, mh, &cnt);
121 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);
127 mm++;
129 while ( mm->text )
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);
139 flags = mm->flags;
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);
152 mm++;
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
169 for (;;)
171 if ( !mm || !mm->text )
172 break;
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 );
183 if ( visible ) {
184 // InsertMenu( mh, 0 );
186 mm++;
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)
200 fl_open_display();
201 Fl_Menu_Bar::menu( m );
202 convertToMenuBar(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)
216 fl_open_display();
217 int rank = Fl_Menu_::add(label, shortcut, cb, user_data, flags);
218 convertToMenuBar(Fl_Menu_::menu());
219 return rank;
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)
232 fl_open_display();
233 int rank = Fl_Menu_::insert(index, label, shortcut, cb, user_data, flags);
234 convertToMenuBar(Fl_Menu_::menu());
235 return rank;
238 void Fl_Sys_Menu_Bar::clear()
240 Fl_Menu_::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());
248 return retval;
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);
277 * Draw the menu bar.
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 $".