diff --git a/FL/Fl_Tree.H b/FL/Fl_Tree.H index 9446e08d1..ab637b947 100644 --- a/FL/Fl_Tree.H +++ b/FL/Fl_Tree.H @@ -390,7 +390,13 @@ public: Fl_Tree_Item *find_item(const char *path); const Fl_Tree_Item *find_item(const char *path) const; int item_pathname(char *pathname, int pathnamelen, const Fl_Tree_Item *item) const; +#if FLTK_ABI_VERSION >= 10303 + const Fl_Tree_Item* find_clicked(int yonly=0) const; + Fl_Tree_Item* find_clicked(int yonly=0); +#else const Fl_Tree_Item *find_clicked() const; + Fl_Tree_Item *find_clicked(); +#endif Fl_Tree_Item *item_clicked(); Fl_Tree_Item *first(); Fl_Tree_Item *first_visible(); // deprecated in ABI 10303 diff --git a/FL/Fl_Tree_Item.H b/FL/Fl_Tree_Item.H index b51d90907..8493b7e44 100644 --- a/FL/Fl_Tree_Item.H +++ b/FL/Fl_Tree_Item.H @@ -103,7 +103,6 @@ protected: void draw_vertical_connector(int x, int y1, int y2, const Fl_Tree_Prefs &prefs); void draw_horizontal_connector(int x1, int x2, int y, const Fl_Tree_Prefs &prefs); void recalc_tree(); - const Fl_Tree_Item* find_clicked_(const Fl_Tree_Prefs &prefs, int yonly=0) const; // internal public: Fl_Tree_Item(const Fl_Tree_Prefs &prefs); // CTOR -- backwards compatible #if FLTK_ABI_VERSION >= 10303 @@ -377,8 +376,13 @@ public: ////////////////// // Events ////////////////// - const Fl_Tree_Item *find_clicked(const Fl_Tree_Prefs &prefs, int yonly=0) const; - Fl_Tree_Item *find_clicked(const Fl_Tree_Prefs &prefs, int yonly=0); +#if FLTK_ABI_VERSION >= 10303 + const Fl_Tree_Item* find_clicked(const Fl_Tree_Prefs &prefs, int yonly=0) const; + Fl_Tree_Item* find_clicked(const Fl_Tree_Prefs &prefs, int yonly=0); +#else + const Fl_Tree_Item* find_clicked(const Fl_Tree_Prefs &prefs) const; + Fl_Tree_Item* find_clicked(const Fl_Tree_Prefs &prefs); +#endif int event_on_collapse_icon(const Fl_Tree_Prefs &prefs) const; int event_on_label(const Fl_Tree_Prefs &prefs) const; /// Is this item the root of the tree? diff --git a/src/Fl_Tree.cxx b/src/Fl_Tree.cxx index 03e0a1364..b5f427a0c 100644 --- a/src/Fl_Tree.cxx +++ b/src/Fl_Tree.cxx @@ -415,7 +415,11 @@ int Fl_Tree::handle(int e) { case FL_PUSH: { // clicked on tree last_my = Fl::event_y(); // save for dragging direction.. if (Fl::visible_focus() && handle(FL_FOCUS)) Fl::focus(this); +#if FLTK_ABI_VERSION >= 10303 + Fl_Tree_Item *item = _root->find_clicked(_prefs, 0); +#else Fl_Tree_Item *item = _root->find_clicked(_prefs); +#endif if ( !item ) { // clicked, but not on an item? _lastselect = 0; switch ( _prefs.selectmode() ) { @@ -494,7 +498,11 @@ int Fl_Tree::handle(int e) { // During drag, only interested in left-mouse operations. // if ( Fl::event_button() != FL_LEFT_MOUSE ) break; - Fl_Tree_Item *item = _root->find_clicked(_prefs, 1); // item we're on, vertically +#if FLTK_ABI_VERSION >= 10303 + Fl_Tree_Item *item = _root->find_clicked(_prefs, 1); // item we're on, vertically +#else + Fl_Tree_Item *item = _root->find_clicked(_prefs); // item we're on, vertically +#endif if ( !item ) break; // not near item? ignore drag event ret |= 1; // acknowledge event set_item_focus(item); // becomes new focus item @@ -1047,6 +1055,28 @@ int Fl_Tree::item_pathname(char *pathname, int pathnamelen, const Fl_Tree_Item * return(0); } +#if FLTK_ABI_VERSION >= 10303 +/// Find the item that was last clicked on. +/// You should use callback_item() instead, which is fast, +/// and is meant to be used within a callback to determine the item clicked. +/// +/// This method walks the entire tree looking for the first item that is +/// under the mouse. (The value of the \p 'yonly' flag affects whether +/// both x and y events are checked, or just y) +/// +/// Use this method /only/ if you've subclassed Fl_Tree, and are receiving +/// events before Fl_Tree has been able to process and update callback_item(). +/// +/// \param[in] yonly -- 0: check both event's X and Y values. +/// -- 1: only check event's Y value, don't care about X. +/// \returns The item clicked, or NULL if no item was under the current event. +/// \version 1.3.0, added yonly parameter as a 1.3.3 ABI feature. +/// +const Fl_Tree_Item* Fl_Tree::find_clicked(int yonly) const { + if ( ! _root ) return(NULL); + return(_root->find_clicked(_prefs, yonly)); +} +#else /// Find the item that was last clicked on. /// You should use callback_item() instead, which is fast, /// and is meant to be used within a callback to determine the item clicked. @@ -1057,12 +1087,14 @@ int Fl_Tree::item_pathname(char *pathname, int pathnamelen, const Fl_Tree_Item * /// Use this method /only/ if you've subclassed Fl_Tree, and are receiving /// events before Fl_Tree has been able to process and update callback_item(). /// -/// \returns The item clicked, or 0 if no item was under the current event. +/// \returns The item clicked, or NULL if no item was under the current event. +/// \version 1.3.0 /// const Fl_Tree_Item* Fl_Tree::find_clicked() const { if ( ! _root ) return(NULL); return(_root->find_clicked(_prefs)); } +#endif /// Set the item that was last clicked. /// Should only be used by subclasses needing to change this value. diff --git a/src/Fl_Tree_Item.cxx b/src/Fl_Tree_Item.cxx index cd40bfdd9..ca0fdfcb3 100644 --- a/src/Fl_Tree_Item.cxx +++ b/src/Fl_Tree_Item.cxx @@ -494,11 +494,15 @@ void Fl_Tree_Item::draw_vertical_connector(int x, int y1, int y2, const Fl_Tree_ } } -// Internal -// Find the item that the last event was over. -// If \p 'yonly' is 1, only check event's y value, don't care about x. -// -const Fl_Tree_Item *Fl_Tree_Item::find_clicked_(const Fl_Tree_Prefs &prefs, int yonly) const { +#if FLTK_ABI_VERSION >= 10303 +/// Find the item that the last event was over. +/// If \p 'yonly' is 1, only check event's y value, don't care about x. +/// \param[in] prefs The parent tree's Fl_Tree_Prefs +/// \param[in] yonly -- 0: check both event's X and Y values. +/// -- 1: only check event's Y value, don't care about X. +/// \returns pointer to clicked item, or NULL if none found +/// +const Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs, int yonly) const { if ( ! is_visible() ) return(0); if ( is_root() && !prefs.showroot() ) { // skip event check if we're root but root not being shown @@ -518,33 +522,63 @@ const Fl_Tree_Item *Fl_Tree_Item::find_clicked_(const Fl_Tree_Prefs &prefs, int if ( is_open() ) { // open? check children of this item for ( int t=0; tfind_clicked(prefs, yonly)) != NULL) { // check child and its descendents - return(item); // found? - } + if ( (item = _children[t]->find_clicked(prefs, yonly)) != NULL) // recurse into child for descendents + return(item); // found? } } return(0); } /// Find the item that the last event was over. -/// There is both a const and non-const version of this method. +/// If \p 'yonly' is 1, only check event's y value, don't care about x. +/// \param[in] prefs The parent tree's Fl_Tree_Prefs +/// \param[in] yonly -- 0: check both event's X and Y values. +/// -- 1: only check event's Y value, don't care about X. +/// \returns pointer to clicked item, or NULL if none found +/// \version 1.3.3 ABI /// -/// Returns the item if it is visible, and mouse is over it. -/// Works even if widget deactivated. -/// Use event_on_collapse_icon() to determine if collapse button was pressed. +Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs, int yonly) { + // "Effective C++, 3rd Ed", p.23. Sola fide, Amen. + return(const_cast( + static_cast(*this).find_clicked(prefs, yonly))); +} +#else +/// Find the item that the last event was over. +/// \param[in] prefs The parent tree's Fl_Tree_Prefs +/// \returns pointer to clicked item, or NULL if none found +/// \version 1.3.0 /// -/// If \a yonly is set, only the mouse Y position is checked. -/// -/// \returns const visible item under the event if found, or 0 if none. -/// -const Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs, int yonly) const { - return(find_clicked_(prefs, yonly)); +const Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs) const { + if ( ! is_visible() ) return(0); + if ( is_root() && !prefs.showroot() ) { + // skip event check if we're root but root not being shown + } else { + // See if event is over us + if ( event_inside(_xywh) ) { // event within this item? + return(this); // found + } + } + if ( is_open() ) { // open? check children of this item + for ( int t=0; tfind_clicked(prefs)) != NULL) // recurse into child for descendents + return(item); // found? + } + } + return(0); } -/// A const version of Fl_Tree_Item::find_clicked() -Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs, int yonly) { - return((Fl_Tree_Item*)find_clicked_(prefs, yonly)); +/// Find the item that the last event was over. +/// \param[in] prefs The parent tree's Fl_Tree_Prefs +/// \returns pointer to clicked item, or NULL if none found +/// \version 1.3.0 +/// +Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs) { + // "Effective C++, 3rd Ed", p.23. Sola fide, Amen. + return(const_cast( + static_cast(*this).find_clicked(prefs))); } +#endif static void draw_item_focus(Fl_Boxtype B, Fl_Color fg, Fl_Color bg, int X, int Y, int W, int H) { if (!Fl::visible_focus()) return;