Author: spitzak
Date: 2008-11-10 13:10:13 -0800 (Mon, 10 Nov 2008)
New Revision: 6514
Log:
New shortcut assignments using WidgetAssociation data, written
by Andreas Rover.
This makes shortcut assignments much simpler and proves that the
WidgetAssociations are useable for storing data. A function to
find and to remove a specific association had to be added.
Modified:
trunk/fltk/Widget.h
trunk/fltk/WidgetAssociation.h
trunk/fltk/events.h
trunk/src/ShortcutAssignment.cxx
trunk/src/Widget.cxx
trunk/src/WidgetAssociation.cxx
trunk/test/menu.cxx
Modified: trunk/fltk/Widget.h
===================================================================
--- trunk/fltk/Widget.h 2008-11-10 21:05:22 UTC (rev 6513)
+++ trunk/fltk/Widget.h 2008-11-10 21:10:13 UTC (rev 6514)
@@ -102,10 +102,10 @@
void tooltip(const char *t) { tooltip_ = t; }
unsigned shortcut() const ;
- bool shortcut(unsigned key) ;
+ void shortcut(unsigned key) ;
bool add_shortcut(unsigned key);
bool remove_shortcut(unsigned key);
- bool remove_shortcuts() ;
+ void remove_shortcuts() ;
unsigned label_shortcut() const;
bool test_label_shortcut() const;
bool test_shortcut() const ;
@@ -259,6 +259,8 @@
void set(const AssociationType&, void* data);
void* get(const AssociationType&) const;
void* foreach(const AssociationType&, AssociationFunctor&) const;
+ bool remove(const AssociationType&, void* data);
+ bool find(const AssociationType&, void* data) const;
#ifdef FLTK_1_WIDGET // back-compatability section:
Modified: trunk/fltk/WidgetAssociation.h
===================================================================
--- trunk/fltk/WidgetAssociation.h 2008-11-10 21:05:22 UTC (rev 6513)
+++ trunk/fltk/WidgetAssociation.h 2008-11-10 21:10:13 UTC (rev 6514)
@@ -39,8 +39,8 @@
/*! \brief Base class for the association type.
*
- * FLTK allows you to attach any kind user data to a widget. This data is
automatically freed when the
- * widget to which it is attached is destroyed. Internally an association
table is used to connetc the
+ * FLTK allows you to attach any kind of user data to a widget. This data is
automatically freed when the
+ * widget to which it is attached is destroyed. Internally an association
table is used to connect the
* widget pointer with the data pointer that is why all the functions
concerned with this feature contain
* "association" in their name. The advantage of this is that no space is
taken on widgets that do not
* contain the data (or that have the "default value"), and that the
destructor code is not linked in
@@ -62,7 +62,7 @@
class FL_API AssociationType {
public:
- /*! \brief This function is called with associated data is freed
+ /*! \brief This function is called when associated data is freed
* This function must be proveded when creating a data specific subclass.
The function
* must do whatever is necessary to free associated data. Most of the time
it will be a cast
* to the right datatype and a delete
@@ -70,8 +70,8 @@
virtual void destroy(void* data) const = 0;
/*! \brief Finds all data of this association type for a widget
- * This function is just calls fltk::foreach(this, wg, fkt). If \a widget
- * is NULL this all data for any widget.
+ * This function just calls fltk::foreach(this, wg, fkt). If \a wg
+ * is NULL this function will find all data for any widget.
*/
void* foreach(const Widget* wg, AssociationFunctor& fkt) { return
fltk::foreach(this, wg, fkt); }
};
Modified: trunk/fltk/events.h
===================================================================
--- trunk/fltk/events.h 2008-11-10 21:05:22 UTC (rev 6513)
+++ trunk/fltk/events.h 2008-11-10 21:10:13 UTC (rev 6514)
@@ -275,16 +275,17 @@
inline void compose_reset() {compose_state = 0;}
// shortcuts:
-/*! Structure created by Widget::add_shortcut() and returned by
list_shortcuts(). */
-struct ShortcutAssignment {Widget* widget; unsigned key;};
-FL_API const ShortcutAssignment* list_shortcuts(unsigned key, unsigned& count);
-FL_API const ShortcutAssignment* list_shortcuts(const Widget*,unsigned& count);
-FL_API const ShortcutAssignment* list_shortcuts(unsigned& count);
-FL_API const ShortcutAssignment* list_matching_shortcuts(unsigned& count);
FL_API bool try_shortcut();
FL_API const char* key_name(unsigned key);
FL_API unsigned key(const char* name);
+class FL_API ShortcutFunctor {
+ public:
+ virtual bool handle(const Widget*, unsigned key) = 0;
+};
+FL_API unsigned foreachShortcut(const Widget*, ShortcutFunctor&);
+inline unsigned foreachShortcut(ShortcutFunctor& f) { return
foreachShortcut(0,f); }
+
// get current information, not info from last event:
FL_API bool get_key_state(unsigned);
FL_API void get_mouse(int &,int &);
Modified: trunk/src/ShortcutAssignment.cxx
===================================================================
--- trunk/src/ShortcutAssignment.cxx 2008-11-10 21:05:22 UTC (rev 6513)
+++ trunk/src/ShortcutAssignment.cxx 2008-11-10 21:10:13 UTC (rev 6514)
@@ -22,77 +22,27 @@
//
-// Shortcuts are stored entirely using hidden data structures, and are
-// looked up by searching for pointers in tables. This keeps the size
-// of widgets with no shortcut small, and allows us freedom to change
-// the implementation. The current implementation just does binary
-// search for shortcuts and uses insertion sort to put things into the
-// tables, but a hash table is probably better and it should be
-// changed to this someday.
+// Shortcuts are stored in the association table
-// Two parallel arrays are maintained with exactly the same data.
-// One is sorted by widget, the other by key. If the structure gets
-// any more complex we may want to sort arrays of pointers instead.
-
#include <config.h>
#include <fltk/events.h>
#include <fltk/Widget.h>
+#include <fltk/WidgetAssociation.h>
#include <fltk/string.h>
#include <ctype.h>
using namespace fltk;
-static ShortcutAssignment* keylist = 0;
-static ShortcutAssignment* widgetlist = 0;
-static unsigned num_shortcuts = 0;
-static unsigned array_size = 0;
+class shortcutAssociationType : public AssociationType {
-// Returns entry, or pointer where to insert it:
-static ShortcutAssignment* findkey(unsigned key) {
- unsigned a = 0;
- unsigned b = num_shortcuts;
- while (a < b) {
- unsigned c = (a+b)/2;
- ShortcutAssignment* p = keylist+c;
- int n = (p->key&0xffff)-(key&0xffff);
- if (n < 0) a = c+1;
- else if (n > 0) b = c;
- else {
- n = p->key - key;
- if (n < 0) a = c+1;
- else if (n > 0) b = c;
- else {
- // found it, but search backwards for first one
- while (p > keylist && (p-1)->key == key) --p;
- return p;
- }
- }
- }
- return keylist+a;
-}
+ // we use the data pointer as unsigned int, so
+ // we don't need to free anything
+ void destroy(void *data) const {}
+};
-// Search the sorted-by-widget list
-static ShortcutAssignment* findwidget(const Widget* widget) {
- unsigned a = 0;
- unsigned b = num_shortcuts;
- while (a < b) {
- int c = (a+b)/2;
- ShortcutAssignment* p = widgetlist+c;
- if (p->widget < widget) a = c+1;
- else if (p->widget > widget) b = c;
- else {
- // found it, but search backwards for first one
- while (p > widgetlist && (p-1)->widget == widget) --p;
- return p;
- }
- }
- return widgetlist+a;
-}
+// this is our association to the shortcuts associated with widgets
+static shortcutAssociationType shortcutAssociation;
-static unsigned last_list = 0;
-static const ShortcutAssignment* last_list_pointer = 0;
-static unsigned last_list_length = 0;
-
/*!
Add a new shortcut assignment. Returns true if successful. If \a key
@@ -102,8 +52,7 @@
There can be any number of shortcut assignments, fltk stores them in
internal tables shared by all widgets. A widget can have any number
of shortcuts (though most have zero or one), and a given shortcut
- value can be assigned to more than one widget. You can examine
- the assignments with fltk::list_shortcuts().
+ value can be assigned to more than one widget.
If you only want one shortcut use shortcut() to assign it.
@@ -115,8 +64,7 @@
- just <code>'a'</code>
- <code>fltk::SHIFT+'#'</code>
- <code>fltk::SHIFT+fltk::UpKey</code>
- See fltk::list_matching_shortcuts() for the exact rules for how
- a KEY event is matched to a shortcut assignment. Case is ignored
+ Case is ignored
(the lower-case version of any letter is actually put in the table).
When FLTK gets a keystroke, it sends it to the fltk::focus()
@@ -131,249 +79,56 @@
they are interested in). */
bool Widget::add_shortcut(unsigned key) {
if (!key) return false;
- if (!(key&0xff00u)) key = key&0xffff0000u|tolower(key&0xffu);
- // return false if any duplicates, then point after last one:
- ShortcutAssignment* p = findwidget(this);
- while (p < widgetlist+num_shortcuts && p->widget == this) {
- if (p->key == key) return false;
- p++;
- }
- if (num_shortcuts >= array_size) {
- array_size = array_size ? 2*array_size : 64;
- ShortcutAssignment* newlist = new ShortcutAssignment[array_size];
- memcpy(newlist, keylist, num_shortcuts*sizeof(*keylist));
- delete[] keylist;
- keylist = newlist;
- newlist = new ShortcutAssignment[array_size];
- memcpy(newlist, widgetlist, num_shortcuts*sizeof(*widgetlist));
- p = p-widgetlist+newlist;
- delete[] widgetlist;
- widgetlist = newlist;
- }
- // insert the new assignment:
- memmove(p+1, p, (widgetlist+num_shortcuts-p)*sizeof(*widgetlist));
- p->widget = this;
- p->key = key;
- // also insert it into keylist, after all other matching keys:
- p = findkey(key);
- while (p < keylist+num_shortcuts && p->key==key) p++;
- memmove(p+1, p, (keylist+num_shortcuts-p)*sizeof(*keylist));
- p->widget = this;
- p->key = key;
- ++num_shortcuts;
- last_list = 0;
+ key = key&0xffff0000u|tolower(key&0xffu);
+ if (find(shortcutAssociation, (void*)key)) return false;
+ add(shortcutAssociation, (void*)key);
return true;
}
-/*! Delete a shortcut after widget entry is found */
-static void remove_keylist(ShortcutAssignment* p) {
- // Find the matching one in shortcut list (this will crash if missing):
- ShortcutAssignment* q = findkey(p->key);
- for (;;) {
- //assert(q < keylist+num_shortcuts);
- if (q->widget == p->widget) break;
- ++q;
- }
- memmove(q, q+1, (keylist+num_shortcuts-q-1)*sizeof(*keylist));
- last_list = 0;
-}
-/*! Delete a shortcut assignment. Returns true if it actually existed. */
+/*!
+ Delete a shortcut assignment. Returns true if it actually existed.
+*/
bool Widget::remove_shortcut(unsigned key) {
- if (!key) return false;
- if (!(key&0xff00u)) key = key&0xffff0000u|tolower(key&0xffu);
- ShortcutAssignment* p = findwidget(this);
- for (;;) {
- if (p >= widgetlist+num_shortcuts) return false;
- if (p->widget != this) return false;
- if (p->key == key) {
- ::remove_keylist(p);
- // now delete the widgetlist entry:
- memmove(p, p+1, (widgetlist+num_shortcuts-p-1)*sizeof(*widgetlist));
- --num_shortcuts;
- return true;
- }
- ++p;
- }
+ return remove(shortcutAssociation, (void*)key);
}
-/*! Remove all shortcuts for the widget. Returns true if there were
- any. This is automatically done by the Widget destructor.
-*/
-bool Widget::remove_shortcuts() {
- ShortcutAssignment* p = findwidget(this);
- unsigned n = 0;
- while (p+n < widgetlist+num_shortcuts && p[n].widget == this) {
- remove_keylist(p+n);
- n++;
- }
- if (!n) return false;
- memmove(p, p+n, (widgetlist+num_shortcuts-p-n)*sizeof(*widgetlist));
- num_shortcuts -= n;
- return true;
-}
-/*! Returns an array of shortcut assignments for this widget.
- The number of matching ones is put in \a count. Do not
- assumme any particular order for the returned array. Also
- there may be entries with key==0, ignore them.
-
- The returned array is temporary storage and can be overwritten
- by the next call to alter or query shortcuts!
+/*!
+ Remove all shortcuts for the widget.
+ This is automatically done by the Widget destructor.
*/
-const ShortcutAssignment*
-fltk::list_shortcuts(const Widget* widget, unsigned& count) {
- ShortcutAssignment* p = findwidget(widget);
- unsigned n = 0;
- for (; p+n < widgetlist+num_shortcuts && p[n].widget==widget; n++);
- count = n;
- return p;
+void Widget::remove_shortcuts() {
+ set(shortcutAssociation, 0);
}
-/*! Returns one of the add_shortcut() assignments for this widget,
- or returns zero if there are none. If you want to look at more
- than onle you must use fltk::list_shortcuts(this).
-*/
-unsigned Widget::shortcut() const {
- ShortcutAssignment* p = findwidget(this);
- if (p < widgetlist+num_shortcuts && p->widget==this) return p->key;
- return 0;
-}
-/*! Returns an array of shortcut assignments that match the given
- value for \a key. The number of matching ones is put in \a count.
- If there are no matches \a count is set to zero. Do not assumme
- any particular order for the returned array. Also there may be
- entries with widget==0, ignore them.
-
- The returned array is temporary storage and can be overwritten
- by the next call to alter or query shortcuts! */
-const ShortcutAssignment*
-fltk::list_shortcuts(unsigned key, unsigned& count) {
- if (!(key&0xff00u)) key = key&0xffff0000u|tolower(key&0xffu);
- ShortcutAssignment* p = findkey(key);
- unsigned n = 0;
- for (; p+n < keylist+num_shortcuts && p[n].key==key; n++);
- count = n;
- return p;
-}
-
/*!
- Returns an array of shortcut assignments that match the current
- event, which should be a KEY, SHORTCUT, or KEYUP event. The number
- of matching ones is put in \a count. If there are no matches null
- is returned and \a count is set to zero.
-
- The returned array is temporary storage and can be overwritten
- by the next call to alter or query shortcuts! Also there may be
- entries with widget==0, ignore them.
-
- This is very similar to list_shortcuts(event_key()|event_state())
- except if no \e exact match is found, it will try to locate a
- "close" matching key assignment and return that:
-
- - Shift flags \e other than META, ALT, SHIFT, and CTRL do not have to
- be "off". For instance a shortcut with SCROLL_LOCK requires the
- SCROLL_LOCK to be on, but one without it does not require it to
- be off. If there are several matches the numerically-highest
- one is chosen.
- - If no shortcut matches fltk::event_key(), then the first letter
- of fltk::event_text() is converted to upper-case and tried instead,
- and SHIFT can be held down even if the shortcut does not indicate
- it. This means that a shortcut that is a capital 'A' will match
- the 'a' key, and '3' will match both the main and keypad 3, and
- a shortcut of '#' or SHIFT+'#' will work.
+ Returns one of the add_shortcut() assignments for this widget,
+ or returns zero if there are none. If you want to look at more
+ than onle you must use fltk::list_shortcuts(this).
*/
-const ShortcutAssignment*
-fltk::list_matching_shortcuts(unsigned& count) {
- // This will get called a LOT for the same event, so cache the return value:
- if ((event_key()|event_state())==last_list) {
- count = last_list_length;
- return last_list_pointer;
- }
- ShortcutAssignment* ret = 0;
- count = 0;
- // Check against the actual keysym, return highest one (most likely the
- // one with the most shift keys down):
- ShortcutAssignment* p = findkey(event_key());
- for (; p < keylist+num_shortcuts ;) {
- unsigned mismatch = p->key ^ (event_key()|event_state());
- if (mismatch & 0xffff) break; // we are in the next key
- // find out how many identical shortcut assignments there are:
- unsigned n = 1;
- for (; p+n < keylist+num_shortcuts && p[n].key==p->key; n++);
- // we must match all shifts in the shortcut, plus the 4 main shifts:
- if (!(mismatch & (p->key|META|ALT|CTRL|SHIFT))) {
- ret = p;
- count = n;
- }
- // skip to next different shortcut:
- p += n;
- }
- // If nothing matched, try using the ASCII letters. Again find the highest
- // one, but we don't require shift to be up:
- if (!ret && event_text() && event_text()[0]) {
- unsigned c = tolower(event_text()[0]);
- p = findkey(c);
- for (; p < keylist+num_shortcuts ;) {
- unsigned mismatch = p->key ^ (c|event_state());
- if (mismatch & 0xffff) break; // we are in the next key
- // find out how many identical shortcut assignments there are:
- unsigned n = 1;
- for (; p+n < keylist+num_shortcuts && p[n].key==p->key; n++);
- // we must match all shifts in the shortcut, plus the 3 main shifts:
- if (!(mismatch & (p->key|META|ALT|CTRL))) {
- ret = p;
- count = n;
- }
- // skip to next different shortcut:
- p += n;
- }
- }
-#if 0
- if (ret) {
- printf("For key %x found %d matches starting at index %d in:\n",
- event_key()|event_state(), count, ret-keylist);
- for (unsigned n = 0; n < num_shortcuts; n++)
- printf(" %s %x\n", keylist[n].widget->label(), keylist[n].key);
- }
-#endif
- last_list = event_key()|event_state();
- last_list_length = count;
- last_list_pointer = ret;
- return ret;
+unsigned Widget::shortcut() const {
+ return (unsigned int)get(shortcutAssociation);
}
-/*! Returns an array of every shortcut assignment. They are sorted by
- the key, and then by shift flags.
- The returned array is temporary storage and will be overwritten
- by the next call to alter or query shortcuts! Also there may be
- entries with widget==0, ignore them.
-*/
-const ShortcutAssignment* fltk::list_shortcuts(unsigned& count) {
- count = num_shortcuts;
- return keylist;
-}
-
/*!
Same as remove_shortcuts(), add_shortcut(key)
except it may be implemented in a more efficient way.
The result is exactly one shortcut (or none if \a key is zero).
- Return value is intended to indicate if the shortcut changed, but
- that is nyi.
*/
-bool Widget::shortcut(unsigned key) {
- remove_shortcuts();
- return add_shortcut(key);
+void Widget::shortcut(unsigned key) {
+ set(shortcutAssociation, (void*)key);
}
+
/*!
Returns a value that can be passed to add_shortcut() so that this
- widget has a real shortcut assignment to match any &x in it's label().
- The returned value is ALT|c where c is the character after
- the first '&' in the label, or zero if there isn't any '&' sign
- or if flag(RAW_LABEL) is on.
+ widget has a real shortcut assignment to match any &x in it's
+ label(). The returned value is ALT|c where c is the character after
+ the first '&' in the label (except '&&' is ignored), or zero if
+ there isn't any '&' sign or if flag(RAW_LABEL) is on.
*/
unsigned Widget::label_shortcut() const {
if (flag(RAW_LABEL)) return 0;
@@ -387,18 +142,20 @@
return 0;
}
-/*! Test to see if the current KEY or SHORTCUT event matches a shortcut
- specified with &x in the label.
- This will match if the character in the label() after a '&'
- matches event_text()[0]. Case is ignored. The caller may want
- to check if ACCELERATOR or some other shift key is held down
- before calling this so that plain keys do not do anything, and
- should certainly make sure no other widgets want the shortcut.
+/*!
+ Test to see if the current KEY or SHORTCUT event matches a shortcut
+ specified with &x in the label.
- This is ignored if flag(RAW_LABEL) is on (which stops the &x from
- printing as an underscore. The sequence "&&" is ignored as well
- because that is used to print a plain '&' in the label.
+ This will match if the character in the label() after a '&'
+ matches event_text()[0]. Case is ignored. The caller may want
+ to check if ACCELERATOR or some other shift key is held down
+ before calling this so that plain keys do not do anything, and
+ should certainly make sure no other widgets want the shortcut.
+
+ This is ignored if flag(RAW_LABEL) is on (which stops the &x from
+ printing as an underscore. The sequence "&&" is ignored as well
+ because that is used to print a plain '&' in the label.
*/
bool Widget::test_label_shortcut() const {
if (flag(RAW_LABEL)) return false;
@@ -421,37 +178,116 @@
return false;
}
-/*! Same as test_shortcut(true) */
-bool Widget::test_shortcut() const {
- return test_shortcut(true);
-}
-/*! Returns true if the current event matches one of the assignements
- made with add_shortcut(), or if test_label is true and
- test_label_shortcut() returns true. Normally a widget calls this
- in response to a SHORTCUT event to see if the shortcut key is
- assigned to it.
+// this class is a functor class used in the test_shortcut functions below
+// the handle function is called for each associated key of this widget and
+// it checks, if that key fist the current key event
+// if that is the case, the function returns true, making the foreach loop
+// stop and return something != 0, this is a sign for the function that
+// a key has been associated to the current widget that fits the current
+// key event...
+class keyCompareFunctor : public AssociationFunctor {
- This is done by doing list_matching_shortcuts() and seeing if this
- widget is in the returned list. If the list is empty and test_label
- is true, it will return test_label_shortcut().
+ public:
- If the current event matches a \e different widget "better" than
- this one, then false is returned. For instance if this widget has
- 'x' as a shortcut, this will return true if the user types
- 'X'. But if another widget has 'X' then this will return
- false. See fltk::list_matching_shortcuts() for the rules about
- what ones are "better".
+ unsigned int count;
+
+ keyCompareFunctor(void) : count(0) {}
+
+ bool handle(const AssociationType&, const Widget*, void* data) {
+
+ count++;
+
+ unsigned int key = (unsigned int)data;
+
+ unsigned mismatch = key ^ (event_key() | event_state());
+
+ if (!(mismatch & 0xffff) &&
+ !(mismatch & (key|META|ALT|CTRL|SHIFT)))
+ return true;
+
+ mismatch = key ^ (tolower(event_text()[0]) | event_state());
+
+ if (!(mismatch & 0xffff) &&
+ !(mismatch & (key|META|ALT|CTRL|SHIFT)))
+ return true;
+
+ return false;
+ }
+};
+
+
+/*! Same as test_shortcut(true) */
+bool Widget::test_shortcut() const { return test_shortcut(true); }
+
+
+/*!
+ Returns true if the current event matches one of the assignements
+ made with add_shortcut(), or if test_label is true and
+ test_label_shortcut() returns true. Normally a widget calls this
+ in response to a SHORTCUT event to see if the shortcut key is
+ assigned to it.
*/
bool Widget::test_shortcut(bool test_label) const {
- unsigned count;
- const ShortcutAssignment* list = list_matching_shortcuts(count);
- if (!count) return test_label && test_label_shortcut();
- for (unsigned i = 0; i < count; i++)
- if (list[i].widget == this) return true;
+
+ keyCompareFunctor fkt;
+
+ // if there is a suitable assignment, return true
+ if (foreach(shortcutAssociation, fkt)) return true;
+
+ // if not, check how many keys had been assigned, if none,
+ // check for label shortcut
+ if (test_label && fkt.count == 0)
+ return test_label_shortcut();
+
return false;
}
+////////////////////////////////////////////////////////////////
+
+class GlueFunctor : public AssociationFunctor {
+public:
+ ShortcutFunctor& f;
+ GlueFunctor(ShortcutFunctor& g) : f(g) {}
+ bool handle(const AssociationType&, const Widget* widget, void* data) {
+ return f.handle(widget, (unsigned int)data);
+ }
+};
+
+/*!
+ Call the handle() method from the passed ShortcutFunctor object
+ for every Widget::shortcut() assignment known. If any return true
+ then this immediately returns that shortcut value, else this
+ returns zero after calling it for the last one. This is most
+ useful for making a display of shortcuts for the user, or implementing
+ a shortcut editor.
+
+\code
+class ListShortcuts : public ShortcutFunctor {
+public:
+ bool handle(const Widget* widget, unsigned key) {
+ printf("Widget=%s shortcut=%s\n",
+ widget->label() ? widget->label() : "NULL",
+ key_name(key));
+ return false;
+ }
+};
+f() {
+ ListShortcuts listShortcuts;
+ fltk::foreachShortcut(listShortcuts);
+}
+\endcode
+
+ If \a widget is not null, only do assignments for that widget,
+ this is much faster than searching the entire list. This is useful
+ for drawing the shortcuts on a widget (though most fltk widgets only
+ draw the first one).
+*/
+unsigned fltk::foreachShortcut(const Widget* widget, ShortcutFunctor& f) {
+ GlueFunctor g(f);
+ return (unsigned int)(foreach(&shortcutAssociation, widget, g));
+}
+
// End of $Id$
Modified: trunk/src/Widget.cxx
===================================================================
--- trunk/src/Widget.cxx 2008-11-10 21:05:22 UTC (rev 6513)
+++ trunk/src/Widget.cxx 2008-11-10 21:10:13 UTC (rev 6514)
@@ -90,7 +90,6 @@
*/
Widget::~Widget() {
remove_timeout();
- remove_shortcuts();
if (parent_) parent_->remove(this);
throw_focus();
delete_associations_for(this);
Modified: trunk/src/WidgetAssociation.cxx
===================================================================
--- trunk/src/WidgetAssociation.cxx 2008-11-10 21:05:22 UTC (rev 6513)
+++ trunk/src/WidgetAssociation.cxx 2008-11-10 21:10:13 UTC (rev 6514)
@@ -177,6 +177,72 @@
}
/*!
+ * tries to remove one association from a widget, if it exists it is removed
+ * and the function returns true, if such an association doesn't exist false
is returned
+ * and nothing is changed
+ */
+bool Widget::remove(const AssociationType& at, void* data) {
+
+ if (associationTableSize == 0) return false;
+
+ const size_t hash = (size_t)this % associationTableSize;
+
+ PrimaryAssociation* node = associationTable[hash];
+
+ while (node && node->wg != this) node = node->next;
+
+ if (!node) return false;
+
+ Association* ass = node->associations;
+ Association* prev = 0;
+
+ while (ass && ass->at != &at && ass->data != data) {
+ prev = ass;
+ ass = ass->next;
+ }
+
+ if (!ass) return false;
+
+ if (prev)
+ prev->next = ass->next;
+ else
+ node->associations = ass->next;
+
+ ass->at->destroy(ass->data);
+ delete ass;
+
+ return true;
+}
+
+/*!
+ * tries to find an association of this type with the given data
+ * if found the function returns true, else false
+ */
+bool Widget::find(const AssociationType& at, void* data) const {
+
+ if (associationTableSize == 0) return false;
+
+ const size_t hash = (size_t)this % associationTableSize;
+
+ PrimaryAssociation* node = associationTable[hash];
+
+ while (node && node->wg != this) node = node->next;
+
+ if (!node) return false;
+
+ Association* ass = node->associations;
+ Association* prev = 0;
+
+ while (ass && ass->at != &at && ass->data != data) {
+ prev = ass;
+ ass = ass->next;
+ }
+
+ return ass != 0;
+}
+
+
+/*!
Call the functor for each piece of data of the give AssociationType.
This is a wrapper for ::foreach(&at, this, fkt).
*/
Modified: trunk/test/menu.cxx
===================================================================
--- trunk/test/menu.cxx 2008-11-10 21:05:22 UTC (rev 6513)
+++ trunk/test/menu.cxx 2008-11-10 21:10:13 UTC (rev 6514)
@@ -81,6 +81,14 @@
void quit_cb(Widget*, void*) {exit(0);}
+class ListShortcuts : public ShortcutFunctor {
+public:
+ bool handle(const Widget* widget, unsigned key) {
+ printf("Widget=%s shortcut=%s\n", widget->label() ? widget->label() :
"NULL", key_name(key));
+ return false;
+ }
+} listShortcuts;
+
int main(int argc, char **argv) {
Window window(WIDTH,400);
window.begin();
@@ -186,5 +194,7 @@
window.end();
window.show(argc, argv);
+ foreachShortcut(listShortcuts);
+
return run();
}
_______________________________________________
fltk-commit mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-commit