summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManolo Gouy <Manolo>2015-03-22 07:08:04 +0000
committerManolo Gouy <Manolo>2015-03-22 07:08:04 +0000
commitd4867caf80b070541d975bc72136db317cd58c27 (patch)
tree937a8705c73a40ad8918054107d9c21bec73d84e
parent78852b1724aeaf50830e893e62753dbc8fe22e83 (diff)
Fix STR #3176: possible bad border effect when a set of radio menu items is located first in its menu.
Fl_Menu_Item::set_only() is deprecated and replaced by Fl_Menu_::set_only(Fl_Menu_item*). git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@10647 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
-rw-r--r--CHANGES3
-rw-r--r--FL/Fl_Menu_.H1
-rw-r--r--src/Fl_Menu_.cxx58
3 files changed, 59 insertions, 3 deletions
diff --git a/CHANGES b/CHANGES
index 2ce0477c8..8541b853e 100644
--- a/CHANGES
+++ b/CHANGES
@@ -37,6 +37,9 @@ CHANGES IN FLTK 1.3.4 RELEASED: ??? ?? ????
- Restored window background drawing, particularly the 'plastic'
scheme's background (STR #3059). This was a regression since
FLTK 1.3.0.
+ - Fixed possible bad border effect when a set of radio menu items
+ is located first in its menu (STR #3176): Fl_Menu_Item::set_only()
+ is deprecated and replaced by Fl_Menu_::set_only(Fl_Menu_item*).
CHANGES IN FLTK 1.3.3 RELEASED: Nov 03 2014
diff --git a/FL/Fl_Menu_.H b/FL/Fl_Menu_.H
index 7eb37cda7..5b6f5984e 100644
--- a/FL/Fl_Menu_.H
+++ b/FL/Fl_Menu_.H
@@ -176,6 +176,7 @@ public:
Fl_Color down_color() const {return selection_color();}
/** For back compatibility, same as selection_color() */
void down_color(unsigned c) {selection_color(c);}
+ void setonly(Fl_Menu_Item* item);
};
#endif
diff --git a/src/Fl_Menu_.cxx b/src/Fl_Menu_.cxx
index 53bae0467..7b1b3c5ba 100644
--- a/src/Fl_Menu_.cxx
+++ b/src/Fl_Menu_.cxx
@@ -254,8 +254,8 @@ const Fl_Menu_Item* Fl_Menu_::picked(const Fl_Menu_Item* v) {
if (v) {
if (v->radio()) {
if (!v->value()) { // they are turning on a radio item
- set_changed();
- ((Fl_Menu_Item*)v)->setonly();
+ set_changed();
+ setonly((Fl_Menu_Item*)v);
}
redraw();
} else if (v->flags & FL_MENU_TOGGLE) {
@@ -276,7 +276,59 @@ const Fl_Menu_Item* Fl_Menu_::picked(const Fl_Menu_Item* v) {
return v;
}
-/** Turns the radio item "on" for the menu item and turns off adjacent radio items set. */
+/* Scans an array of Fl_Menu_Item's that begins at start, searching for item.
+ Returns NULL if item is not found.
+ If item is present, returns start, unless item belongs to an
+ FL_SUBMENU_POINTER-adressed array of items, in which case the first item of this array is returned.
+ */
+static Fl_Menu_Item *first_submenu_item(Fl_Menu_Item *item, Fl_Menu_Item *start)
+{
+ Fl_Menu_Item* m = start;
+ int nest = 0; // will indicate submenu nesting depth
+ while (1) { // loop over all menu items
+ if (!m->text) { // m is a null item
+ if (!nest) return NULL; // item was not found
+ nest--; // m marks the end of a submenu -> decrement submenu nesting depth
+ } else { // a true item
+ if (m == item) return start; // item is found, return menu start item
+ if (m->flags & FL_SUBMENU_POINTER) {
+ // scan the detached submenu which begins at m->user_data()
+ Fl_Menu_Item *first = first_submenu_item(item, (Fl_Menu_Item*)m->user_data());
+ if (first) return first; // if item was found in the submenu, return
+ }
+ else if (m->flags & FL_SUBMENU) { // a direct submenu
+ nest++; // increment submenu nesting depth
+ }
+ }
+ m++; // step to next menu item
+ }
+}
+
+
+/** Turns the radio item "on" for the menu item and turns "off" adjacent radio items of the same group. */
+void Fl_Menu_::setonly(Fl_Menu_Item* item) {
+ // find the first item of the (sub)menu containing item
+ Fl_Menu_Item* first = first_submenu_item(item, menu_);
+ if (!first) return; // item does not belong to our menu
+ item->flags |= FL_MENU_RADIO | FL_MENU_VALUE;
+ Fl_Menu_Item* j;
+ for (j = item; ; ) { // go down
+ if (j->flags & FL_MENU_DIVIDER) break; // stop on divider lines
+ j++;
+ if (!j->text || !j->radio()) break; // stop after group
+ j->clear();
+ }
+ for (j = item-1; j>=first; j--) { // go up
+ //DEBUG printf("GO UP: WORKING ON: item='%s', flags=%x\n", j->text, j->flags);
+ if (!j->text || (j->flags&FL_MENU_DIVIDER) || !j->radio()) break;
+ j->clear();
+ }
+}
+
+/** Turns the radio item "on" for the menu item and turns "off" adjacent radio items set.
+ \deprecated This method is dangerous if radio items are first in the menu.
+ Use Fl_Menu_::setonly(Fl_Menu_Item*) instead.
+ */
void Fl_Menu_Item::setonly() {
flags |= FL_MENU_RADIO | FL_MENU_VALUE;
Fl_Menu_Item* j;