Fixed menu and shortcut handling (STR #2243). This partly reverts the

fix for STR #2199 - for details see STR #2243.


git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@7816 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Albrecht Schlosser 2010-11-11 09:12:05 +00:00
parent 832c8787ab
commit 2105f203f1
7 changed files with 106 additions and 36 deletions

View File

@ -1,6 +1,7 @@
CHANGES IN FLTK 1.3.0
- removed support for gcc 2.x (or older)
- Fixed menu and shortcut handling (STR #2243)
- Removed support for gcc 2.x (or older)
- Fixed fltk-config to give --libs on one line (STR #2408)
- Fixed tab key navigation to inactive widgets (STR #2420)
- Fixed outside label redraw damage areas (STR #2436)

View File

@ -70,6 +70,17 @@ public:
int find_index(const Fl_Menu_Item *item) const;
int find_index(Fl_Callback *cb) const;
/**
Returns the menu item with the entered shortcut (key value).
This searches the complete menu() for a shortcut that matches the
entered key value. It must be called for a FL_KEYBOARD or FL_SHORTCUT
event.
If a match is found, the menu's callback will be called.
\return matched Fl_Menu_Item or NULL.
*/
const Fl_Menu_Item* test_shortcut() {return picked(menu()->test_shortcut());}
void global();
@ -118,7 +129,7 @@ public:
int value(int i) {return value(menu_+i);}
/** Returns the title of the last item chosen. */
const char *text() const {return value_ ? value_->text : 0;}
/** Returns the title of the last item chosen, or of item i. */
/** Returns the title of item i. */
const char *text(int i) const {return menu_[i].text;}
/** Gets the current font of menu item labels. */

View File

@ -349,7 +349,7 @@ struct FL_EXPORT Fl_Menu_Item {
const Fl_Menu_Item* title = 0,
int menubar=0) const;
const Fl_Menu_Item* test_shortcut() const;
const Fl_Menu_Item* find_shortcut(int *ip=0) const;
const Fl_Menu_Item* find_shortcut(int *ip=0, const bool require_alt = false) const;
/**
Calls the Fl_Menu_Item item's callback, and provides the

View File

@ -845,12 +845,12 @@ public:
// Documentation and implementation in Fl_Widget.cxx
void do_callback(Fl_Widget* o,void* arg=0);
/** Internal use only. */
/* Internal use only. */
int test_shortcut();
/** Internal use only. */
/* Internal use only. */
static unsigned int label_shortcut(const char *t);
/** Internal use only. */
static int test_shortcut(const char*);
/* Internal use only. */
static int test_shortcut(const char*, const bool require_alt = false);
/** Checks if w is a child of this widget.
\param[in] w potential child widget

View File

@ -956,44 +956,56 @@ const Fl_Menu_Item* Fl_Menu_Item::pulldown(
}
/**
This method is called by widgets that want to display menus. The menu
stays up until the user picks an item or dismisses it. The selected
item (or NULL if none) is returned. <I>This does not do the
callbacks or change the state of check or radio items.</I>
<P>X,Y is the position of the mouse cursor, relative to the
This method is called by widgets that want to display menus.
The menu stays up until the user picks an item or dismisses it.
The selected item (or NULL if none) is returned. <I>This does not
do the callbacks or change the state of check or radio items.</I>
X,Y is the position of the mouse cursor, relative to the
window that got the most recent event (usually you can pass
Fl::event_x() and Fl::event_y() unchanged here). </P>
<P>title is a character string title for the menu. If
non-zero a small box appears above the menu with the title in it. </P>
<P>The menu is positioned so the cursor is centered over the item
picked. This will work even if picked is in a submenu.
If picked is zero or not in the menu item table the menu is
positioned with the cursor in the top-left corner. </P>
<P>button is a pointer to an
Fl_Menu_ from which the color and boxtypes for the menu are
pulled. If NULL then defaults are used.
Fl::event_x() and Fl::event_y() unchanged here).
\p title is a character string title for the menu. If
non-zero a small box appears above the menu with the title in it.
The menu is positioned so the cursor is centered over the item
picked. This will work even if \p picked is in a submenu.
If \p picked is zero or not in the menu item table the menu is
positioned with the cursor in the top-left corner.
\p button is a pointer to an Fl_Menu_ from which the color and
boxtypes for the menu are pulled. If NULL then defaults are used.
*/
const Fl_Menu_Item* Fl_Menu_Item::popup(
int X, int Y,
const char* title,
const Fl_Menu_Item* picked,
const Fl_Menu_* but
const Fl_Menu_* button
) const {
static Fl_Menu_Item dummy; // static so it is all zeros
dummy.text = title;
return pulldown(X, Y, 0, 0, picked, but, title ? &dummy : 0);
return pulldown(X, Y, 0, 0, picked, button, title ? &dummy : 0);
}
/**
Search only the top level menu for a shortcut.
Either &x in the label or the shortcut fields are used.
Either &x in the label or the shortcut fields are used.
This tests the current event, which must be an FL_KEYBOARD or
FL_SHORTCUT, against a shortcut value.
\param ip returns the index of the item, if \p ip is not NULL.
\param require_alt if true: match only if Alt key is pressed.
\return found Fl_Menu_Item or NULL
*/
const Fl_Menu_Item* Fl_Menu_Item::find_shortcut(int* ip) const {
const Fl_Menu_Item* Fl_Menu_Item::find_shortcut(int* ip, const bool require_alt) const {
const Fl_Menu_Item* m = first();
if (m) for (int ii = 0; m->text; m = m->next(), ii++) {
if (m->activevisible()) {
if (Fl::test_shortcut(m->shortcut_)
|| Fl_Widget::test_shortcut(m->text)) {
|| Fl_Widget::test_shortcut(m->text, require_alt)) {
if (ip) *ip=ii;
return m;
}

View File

@ -65,7 +65,7 @@ int Fl_Menu_Bar::handle(int event) {
return 1;
case FL_SHORTCUT:
if (visible_r()) {
v = menu()->find_shortcut();
v = menu()->find_shortcut(0, true);
if (v && v->submenu()) goto J1;
}
return test_shortcut() != 0;

View File

@ -54,9 +54,11 @@
/**
Test the current event, which must be an FL_KEYBOARD or
FL_SHORTCUT, against a shortcut value (described in
Fl_Button). Returns non-zero if there is a match. Not to
be confused with
Fl_Widget::test_shortcut().
Fl_Button).
Not to be confused with Fl_Widget::test_shortcut().
\return non-zero if there is a match.
*/
int Fl::test_shortcut(unsigned int shortcut) {
if (!shortcut) return 0;
@ -292,6 +294,18 @@ unsigned int fl_old_shortcut(const char* s) {
// Tests for &x shortcuts in button labels:
/** Returns the Unicode value of the '&x' shortcut in a given text.
The given text \p t (usually a widget's label or a menu text) is
searched for a '&x' shortcut label, and if found, the Unicode
value of the '&x' shortcut is returned.
\param t text or label to search for '&x' shortcut.
\return Unicode (UCS-4) value of shortcut in \p t or 0.
\note Internal use only.
*/
unsigned int Fl_Widget::label_shortcut(const char *t) {
if (!t) return 0;
for (;;) {
@ -306,12 +320,29 @@ unsigned int Fl_Widget::label_shortcut(const char *t) {
}
}
int Fl_Widget::test_shortcut(const char *t) {
#ifdef WIN32
// on MSWindows, users expect shortcuts to work only when the Alt modifier is pressed
if (Fl::event_state(FL_ALT)==0) return 0;
#endif
/** Returns true if the given text \p t contains the entered '&x' shortcut.
This method must only be called in handle() methods or callbacks after
a keypress event (usually FL_KEYDOWN or FL_SHORTCUT). The given text
\p t (usually a widget's label or menu text) is searched for a '&x'
shortcut, and if found, this is compared with the entered key value.
Fl::event_text() is used to get the entered key value.
Fl::event_state() is used to get the Alt modifier, if \p require_alt
is true.
\param t text or label to search for '&x' shortcut.
\param require_alt if true: match only if Alt key is pressed.
\return true, if the entered text matches the '&x' shortcut in \p t
false (0) otherwise.
\note Internal use only.
*/
int Fl_Widget::test_shortcut(const char *t, const bool require_alt) {
if (!t) return 0;
// for menubars etc. shortcuts must work only if the Alt modifier is pressed
if (require_alt && Fl::event_state(FL_ALT)==0) return 0;
unsigned int c = fl_utf8decode(Fl::event_text(), Fl::event_text()+Fl::event_length(), 0);
if (!c) return 0;
if (c == label_shortcut(t))
@ -319,6 +350,21 @@ int Fl_Widget::test_shortcut(const char *t) {
return 0;
}
/** Returns true if the widget's label contains the entered '&x' shortcut.
This method must only be called in handle() methods or callbacks after
a keypress event (usually FL_KEYDOWN or FL_SHORTCUT).
The widget's label is searched for a '&x'
shortcut, and if found, this is compared with the entered key value.
Fl::event_text() is used to get the entered key value.
\return true, if the entered text matches the widget's'&x' shortcut,
false (0) otherwise.
\note Internal use only.
*/
int Fl_Widget::test_shortcut() {
if (!(flags()&SHORTCUT_LABEL)) return 0;
return test_shortcut(label());