2001-11-27 20:44:08 +03:00
|
|
|
//
|
2005-02-06 19:28:36 +03:00
|
|
|
// "$Id$"
|
2001-11-27 20:44:08 +03:00
|
|
|
//
|
|
|
|
// MacOS system menu bar widget for the Fast Light Tool Kit (FLTK).
|
|
|
|
//
|
2005-02-25 00:55:12 +03:00
|
|
|
// Copyright 1998-2005 by Bill Spitzak and others.
|
2001-11-27 20:44:08 +03:00
|
|
|
//
|
|
|
|
// This library is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU Library General Public
|
|
|
|
// License as published by the Free Software Foundation; either
|
|
|
|
// version 2 of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This library is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
// Library General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Library General Public
|
|
|
|
// License along with this library; if not, write to the Free Software
|
|
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
|
|
// USA.
|
|
|
|
//
|
2005-04-16 04:13:17 +04:00
|
|
|
// Please report all bugs and problems on the following page:
|
|
|
|
//
|
|
|
|
// http://www.fltk.org/str.php
|
2001-11-27 20:44:08 +03:00
|
|
|
//
|
|
|
|
|
|
|
|
/**
|
2001-12-06 03:17:47 +03:00
|
|
|
* This code is a quick hack! It was written as a proof of concept.
|
2001-11-27 20:44:08 +03:00
|
|
|
* It has been tested on the "menubar" sample program and provides
|
|
|
|
* basic functionality.
|
|
|
|
*
|
|
|
|
* To use the System Menu Bar, simply replace the main Fl_Menu_Bar
|
|
|
|
* in an application with Fl_Sys_Menu_Bar.
|
|
|
|
*
|
|
|
|
* FLTK features not supported by the Mac System menu
|
|
|
|
*
|
|
|
|
* - no invisible menu items
|
|
|
|
* - no sybolic labels
|
|
|
|
* - embossed labels will be underlined instead
|
|
|
|
* - no font sizes
|
|
|
|
* - Shortcut Characters should be English alphanumeric only, no modifiers yet
|
|
|
|
* - no disable main menus
|
|
|
|
* - changes to menubar in run-time don't update!
|
|
|
|
* (disable, etc. - toggle and readio button do!)
|
|
|
|
*
|
|
|
|
* No care was taken to clean up the menu bar after destruction!
|
|
|
|
* ::menu(bar) should only be called once!
|
|
|
|
* Many other calls of the parent class don't work.
|
|
|
|
* Changing the menu items has no effect on the menu bar.
|
|
|
|
*/
|
|
|
|
|
2004-03-11 08:17:12 +03:00
|
|
|
#if defined(__APPLE__)
|
|
|
|
|
2004-11-21 17:32:22 +03:00
|
|
|
#include <FL/x.H>
|
2001-11-27 20:44:08 +03:00
|
|
|
#include <FL/Fl.H>
|
|
|
|
#include <FL/Fl_Sys_Menu_Bar.H>
|
|
|
|
|
2002-04-11 15:52:43 +04:00
|
|
|
#include "flstring.h"
|
2001-11-27 20:44:08 +03:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
typedef const Fl_Menu_Item *pFl_Menu_Item;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* copy the text of a menuitem into a buffer.
|
|
|
|
* Skip all '&' which would mark the shortcut in FLTK
|
|
|
|
* Skip all Mac control characters ('(', '<', ';', '^', '!' )
|
|
|
|
*/
|
|
|
|
static void catMenuText( const char *src, char *dst )
|
|
|
|
{
|
|
|
|
char c;
|
|
|
|
while ( *dst )
|
|
|
|
dst++;
|
|
|
|
if ( *src == '-' )
|
|
|
|
src++;
|
|
|
|
while ( ( c = *src++ ) )
|
|
|
|
{
|
|
|
|
if ( !strchr( "&(<;^!", c ) )
|
|
|
|
*dst++ = c;
|
|
|
|
}
|
|
|
|
*dst = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* append a marker to identify the menu font style
|
|
|
|
* <B, I, U, O, and S
|
|
|
|
*/
|
|
|
|
static void catMenuFont( const Fl_Menu_Item *m, char *dst )
|
|
|
|
{
|
|
|
|
if ( !m->labeltype_ && !m->labelfont_ )
|
|
|
|
return;
|
|
|
|
while ( *dst )
|
|
|
|
dst++;
|
|
|
|
|
|
|
|
if ( m->labelfont_ & FL_BOLD )
|
|
|
|
strcat( dst, "<B" );
|
|
|
|
if ( m->labelfont_ & FL_ITALIC )
|
|
|
|
strcat( dst, "<I" );
|
|
|
|
//if ( m->labelfont_ & FL_UNDERLINE )
|
|
|
|
// strcat( dst, "<U" );
|
|
|
|
|
|
|
|
if ( m->labeltype_ == FL_EMBOSSED_LABEL )
|
|
|
|
strcat( dst, "<U" );
|
|
|
|
else if ( m->labeltype_ == FL_ENGRAVED_LABEL )
|
|
|
|
strcat( dst, "<O" );
|
|
|
|
else if ( m->labeltype_ == FL_SHADOW_LABEL )
|
|
|
|
strcat( dst, "<S" );
|
|
|
|
//else if ( m->labeltype_ == FL_SYMBOL_LABEL )
|
|
|
|
; // not supported
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* append a marker to identify the menu shortcut
|
|
|
|
* <B, I, U, O, and S
|
|
|
|
enum {
|
2003-06-12 05:36:18 +04:00
|
|
|
kMenuNoModifiers = 0,
|
|
|
|
kMenuShiftModifier = (1 << 0),
|
|
|
|
kMenuOptionModifier = (1 << 1),
|
|
|
|
kMenuControlModifier = (1 << 2),
|
|
|
|
kMenuNoCommandModifier = (1 << 3)
|
2001-11-27 20:44:08 +03:00
|
|
|
};
|
|
|
|
*/
|
2002-07-11 08:11:41 +04:00
|
|
|
static void setMenuShortcut( MenuHandle mh, int miCnt, const Fl_Menu_Item *m )
|
2001-11-27 20:44:08 +03:00
|
|
|
{
|
|
|
|
if ( !m->shortcut_ )
|
|
|
|
return;
|
2002-07-11 08:11:41 +04:00
|
|
|
if ( m->flags & FL_SUBMENU )
|
|
|
|
return;
|
|
|
|
if ( m->flags & FL_SUBMENU_POINTER )
|
|
|
|
return;
|
2001-11-27 20:44:08 +03:00
|
|
|
char key = m->shortcut_ & 0xff;
|
|
|
|
if ( !isalnum( key ) )
|
|
|
|
return;
|
|
|
|
|
|
|
|
long macMod = kMenuNoModifiers;
|
2002-07-11 08:11:41 +04:00
|
|
|
if ( m->shortcut_ & FL_SHIFT || isupper(key) ) macMod |= kMenuShiftModifier;
|
|
|
|
if ( m->shortcut_ & FL_ALT ) macMod |= kMenuOptionModifier;
|
|
|
|
if ( m->shortcut_ & FL_META ) macMod |= kMenuControlModifier;
|
|
|
|
if ( !(m->shortcut_ & FL_CTRL) ) macMod |= kMenuNoCommandModifier;
|
2001-11-27 20:44:08 +03:00
|
|
|
|
2002-07-11 08:11:41 +04:00
|
|
|
//SetMenuItemKeyGlyph( mh, miCnt, key );
|
|
|
|
SetItemCmd( mh, miCnt, toupper(key) );
|
2001-11-27 20:44:08 +03:00
|
|
|
SetMenuItemModifiers( mh, miCnt, macMod );
|
|
|
|
}
|
|
|
|
|
2005-02-06 19:28:36 +03:00
|
|
|
#if 0
|
|
|
|
// this function needs to be verified before we compile it back in.
|
2001-11-27 20:44:08 +03:00
|
|
|
static void catMenuShortcut( const Fl_Menu_Item *m, char *dst )
|
|
|
|
{
|
|
|
|
if ( !m->shortcut_ )
|
|
|
|
return;
|
|
|
|
char c = m->shortcut_ & 0xff;
|
|
|
|
if ( !isalnum( c & 0xff ) )
|
|
|
|
return;
|
|
|
|
while ( *dst )
|
|
|
|
dst++;
|
2002-07-11 08:11:41 +04:00
|
|
|
if ( m->shortcut_ & FL_CTRL )
|
2001-11-27 20:44:08 +03:00
|
|
|
{
|
|
|
|
sprintf( dst, "/%c", toupper( c ) );
|
|
|
|
}
|
|
|
|
//if ( isalnum( mm->shortcut_ ) && !( mm->flags & FL_SUBMENU ) )
|
|
|
|
//sprintf( buf+strlen(buf), "/%c", mm->shortcut_ );
|
|
|
|
}
|
2005-02-06 19:28:36 +03:00
|
|
|
#endif
|
2001-11-27 20:44:08 +03:00
|
|
|
|
|
|
|
static void setMenuFlags( MenuHandle mh, int miCnt, const Fl_Menu_Item *m )
|
|
|
|
{
|
|
|
|
if ( m->flags & FL_MENU_TOGGLE )
|
|
|
|
{
|
|
|
|
SetItemMark( mh, miCnt, ( m->flags & FL_MENU_VALUE ) ? 0x12 : 0 );
|
|
|
|
}
|
|
|
|
else if ( m->flags & FL_MENU_RADIO )
|
|
|
|
SetItemMark( mh, miCnt, ( m->flags & FL_MENU_VALUE ) ? 0x13 : 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void catMenuFlags( const Fl_Menu_Item *m, char *dst )
|
|
|
|
{
|
|
|
|
if ( !m->flags )
|
|
|
|
return;
|
|
|
|
while ( *dst )
|
|
|
|
dst++;
|
|
|
|
if ( m->flags & FL_MENU_INACTIVE )
|
|
|
|
strcat( dst, "(" );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* create a sub menu for a specific menu handle
|
|
|
|
*/
|
|
|
|
static void createSubMenu( MenuHandle mh, int &cnt, pFl_Menu_Item &mm )
|
|
|
|
{
|
|
|
|
char buf[255];
|
|
|
|
int miCnt = 1;
|
|
|
|
while ( mm->text )
|
|
|
|
{
|
2005-02-06 19:28:36 +03:00
|
|
|
MenuHandle smh = 0;
|
2001-11-27 20:44:08 +03:00
|
|
|
buf[1] = 0;
|
|
|
|
catMenuFont( mm, buf+1 );
|
2002-07-11 08:11:41 +04:00
|
|
|
//catMenuShortcut( mm, buf+1 );
|
2001-11-27 20:44:08 +03:00
|
|
|
catMenuText( mm->text, buf+1 );
|
|
|
|
catMenuFlags( mm, buf+1 );
|
|
|
|
if ( mm->flags & (FL_SUBMENU | FL_SUBMENU_POINTER) )
|
|
|
|
{
|
|
|
|
cnt++;
|
|
|
|
smh = NewMenu( cnt, (unsigned char*)"\001 " );
|
|
|
|
sprintf( buf+1+strlen(buf+1), "/\033!%c", cnt );
|
|
|
|
}
|
|
|
|
if ( mm->flags & FL_MENU_DIVIDER )
|
|
|
|
strcat( buf+1, ";-" );
|
|
|
|
buf[0] = strlen( buf+1 );
|
|
|
|
AppendMenu( mh, (unsigned char*)buf );
|
|
|
|
// insert Appearanc manager functions here!
|
|
|
|
setMenuFlags( mh, miCnt, mm );
|
2002-07-11 08:11:41 +04:00
|
|
|
setMenuShortcut( mh, miCnt, mm );
|
2001-11-27 20:44:08 +03:00
|
|
|
SetMenuItemRefCon( mh, miCnt, (UInt32)mm );
|
|
|
|
miCnt++;
|
|
|
|
if ( mm->flags & FL_MENU_DIVIDER )
|
|
|
|
miCnt++;
|
|
|
|
if ( mm->flags & FL_SUBMENU )
|
|
|
|
{
|
|
|
|
createSubMenu( smh, cnt, ++mm );
|
|
|
|
}
|
|
|
|
else if ( mm->flags & FL_SUBMENU_POINTER )
|
|
|
|
{
|
|
|
|
const Fl_Menu_Item *smm = (Fl_Menu_Item*)mm->user_data_;
|
|
|
|
createSubMenu( mh, cnt, smm );
|
|
|
|
}
|
|
|
|
mm++;
|
|
|
|
}
|
|
|
|
InsertMenu( mh, -1 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* create a system menu bar using the given list of menu structs
|
|
|
|
*
|
|
|
|
* \author Matthias Melcher
|
|
|
|
*
|
|
|
|
* @param m list of Fl_Menu_Item
|
|
|
|
*/
|
|
|
|
void Fl_Sys_Menu_Bar::menu(const Fl_Menu_Item *m)
|
|
|
|
{
|
|
|
|
fl_open_display();
|
|
|
|
Fl_Menu_Bar::menu( m );
|
|
|
|
fl_sys_menu_bar = this;
|
|
|
|
|
|
|
|
char buf[255];
|
|
|
|
int cnt = 1; // first menu is no 2. no 1 is the Apple Menu
|
|
|
|
|
|
|
|
const Fl_Menu_Item *mm = m;
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if ( !mm->text )
|
|
|
|
break;
|
|
|
|
buf[1] = 0;
|
|
|
|
catMenuText( mm->text, buf+1 );
|
|
|
|
buf[0] = strlen( buf+1 );
|
|
|
|
MenuHandle mh = NewMenu( ++cnt, (unsigned char*)buf );
|
|
|
|
if ( mm->flags & FL_SUBMENU )
|
|
|
|
createSubMenu( mh, cnt, ++mm );
|
|
|
|
else if ( mm->flags & FL_SUBMENU_POINTER )
|
|
|
|
{
|
|
|
|
const Fl_Menu_Item *smm = (Fl_Menu_Item*)mm->user_data_;
|
|
|
|
createSubMenu( mh, cnt, smm );
|
|
|
|
}
|
|
|
|
|
|
|
|
InsertMenu( mh, 0 );
|
2001-12-06 03:17:47 +03:00
|
|
|
if ( mm->flags & FL_MENU_INACTIVE ) DisableMenuItem( mh, 0 );
|
2001-11-27 20:44:08 +03:00
|
|
|
mm++;
|
|
|
|
}
|
|
|
|
DrawMenuBar();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
const Fl_Menu_Item* Fl_Sys_Menu_Bar::picked(const Fl_Menu_Item* v) {
|
|
|
|
Fl_menu_Item *ret = Fl_Menu_Bar::picked( v );
|
|
|
|
|
|
|
|
if ( m->flags & FL_MENU_TOGGLE )
|
|
|
|
{
|
|
|
|
SetItemMark( mh, miCnt, ( m->flags & FL_MENU_VALUE ) ? 0x12 : 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
void Fl_Sys_Menu_Bar::draw() {
|
|
|
|
/* -- nothing to do, system should take care of this
|
|
|
|
draw_box();
|
|
|
|
if (!menu() || !menu()->text) return;
|
|
|
|
const Fl_Menu_Item* m;
|
|
|
|
int X = x()+6;
|
|
|
|
for (m=menu(); m->text; m = m->next()) {
|
|
|
|
int W = m->measure(0,this) + 16;
|
|
|
|
m->draw(X, y(), W, h(), this);
|
|
|
|
X += W;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
int Fl_Menu_Bar::handle(int event) {
|
|
|
|
const Fl_Menu_Item* v;
|
|
|
|
if (menu() && menu()->text) switch (event) {
|
|
|
|
case FL_ENTER:
|
|
|
|
case FL_LEAVE:
|
|
|
|
return 1;
|
|
|
|
case FL_PUSH:
|
|
|
|
v = 0;
|
|
|
|
J1:
|
|
|
|
v = menu()->pulldown(x(), y(), w(), h(), v, this, 0, 1);
|
|
|
|
picked(v);
|
|
|
|
return 1;
|
|
|
|
case FL_SHORTCUT:
|
|
|
|
if (visible_r()) {
|
|
|
|
v = menu()->find_shortcut();
|
|
|
|
if (v && v->submenu()) goto J1;
|
|
|
|
}
|
|
|
|
return test_shortcut() != 0;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
2004-03-11 08:17:12 +03:00
|
|
|
#endif /* __APPLE__ */
|
|
|
|
|
2001-11-27 20:44:08 +03:00
|
|
|
//
|
2005-02-06 19:28:36 +03:00
|
|
|
// End of "$Id$".
|
2001-11-27 20:44:08 +03:00
|
|
|
//
|