diff options
| -rw-r--r-- | FL/Fl_Tree.H | 4 | ||||
| -rw-r--r-- | src/Fl_Tree.cxx | 71 | ||||
| -rw-r--r-- | src/Fl_Tree_Item.cxx | 36 | ||||
| -rw-r--r-- | test/tree.fl | 16 |
4 files changed, 81 insertions, 46 deletions
diff --git a/FL/Fl_Tree.H b/FL/Fl_Tree.H index dfa75de90..3ce4eeb77 100644 --- a/FL/Fl_Tree.H +++ b/FL/Fl_Tree.H @@ -366,9 +366,11 @@ public: const Fl_Tree_Item *find_clicked() const; Fl_Tree_Item *item_clicked(); Fl_Tree_Item *first(); + Fl_Tree_Item *first_visible(); Fl_Tree_Item *next(Fl_Tree_Item *item=0); Fl_Tree_Item *prev(Fl_Tree_Item *item=0); Fl_Tree_Item *last(); + Fl_Tree_Item *last_visible(); Fl_Tree_Item *first_selected_item(); Fl_Tree_Item *next_selected_item(Fl_Tree_Item *item=0); @@ -397,6 +399,7 @@ public: int select_only(Fl_Tree_Item *selitem, int docallback=1); int select_all(Fl_Tree_Item *item=0, int docallback=1); void set_item_focus(Fl_Tree_Item *item); + Fl_Tree_Item *get_item_focus() const; int is_selected(Fl_Tree_Item *item) const; int is_selected(const char *path); @@ -473,6 +476,7 @@ public: int is_scrollbar(Fl_Widget *w); int scrollbar_size() const; void scrollbar_size(int size); + int is_vscroll_visible() const; /////////////////////// // callback related diff --git a/src/Fl_Tree.cxx b/src/Fl_Tree.cxx index 95247e354..1f91a00e9 100644 --- a/src/Fl_Tree.cxx +++ b/src/Fl_Tree.cxx @@ -195,21 +195,24 @@ int Fl_Tree::handle(int e) { // Do shortcuts first or scrollbar will get them... if ( (Fl::focus() == this) && // tree has focus? _prefs.selectmode() > FL_TREE_SELECT_NONE ) { // select mode that supports kb events? - if ( !_item_focus ) { - set_item_focus(first()); + if ( !_item_focus ) { // no current focus item? + set_item_focus(first_visible()); // use first vis item + if ( Fl::event_key() == FL_Up || // Up or down? + Fl::event_key() == FL_Down ) // ..if so, already did 'motion' + return(1); // ..so just return. } if ( _item_focus ) { int ekey = Fl::event_key(); switch (ekey) { case FL_Enter: // ENTER: toggle open/close case FL_KP_Enter: { - open_toggle(_item_focus, when()); - break; + open_toggle(_item_focus, when()); // toggle item in focus + return(1); // done, we handled key } case ' ': // SPACE: change selection state switch ( _prefs.selectmode() ) { case FL_TREE_SELECT_NONE: - break; + break; // ignore, let group have shot at event case FL_TREE_SELECT_SINGLE: if ( is_ctrl ) { // CTRL-SPACE: (single mode) toggle if ( ! _item_focus->is_selected() ) { @@ -221,7 +224,7 @@ int Fl_Tree::handle(int e) { select_only(_item_focus, when()); // SPACE: (single mode) select only } _lastselect = _item_focus; - return(1); + return(1); // done, we handled key case FL_TREE_SELECT_MULTI: if ( is_ctrl ) { select_toggle(_item_focus, when()); // CTRL-SPACE: (multi mode) toggle selection @@ -229,7 +232,7 @@ int Fl_Tree::handle(int e) { select(_item_focus, when()); // SPACE: (multi-mode) select } _lastselect = _item_focus; - return(1); + return(1); // done, we handled key } break; case FL_Right: // RIGHT: open children (if any) @@ -280,7 +283,7 @@ int Fl_Tree::handle(int e) { case FL_TREE_SELECT_MULTI: // Do a 'select all' select_all(); - _lastselect = first(); + _lastselect = first_visible(); take_focus(); return(1); } @@ -588,13 +591,16 @@ Fl_Tree_Item* Fl_Tree::insert(Fl_Tree_Item *item, const char *name, int pos) { /// Remove the specified \p item from the tree. /// \p item may not be NULL. /// If it has children, all those are removed too. +/// If item being removed has focus, no item will have focus. /// \returns 0 if done, -1 if 'item' not found. /// int Fl_Tree::remove(Fl_Tree_Item *item) { + // Item being removed is focus item? zero focus + if ( item == _item_focus ) _item_focus = 0; if ( item == _root ) { clear(); } else { - Fl_Tree_Item *parent = item->parent(); // find item's parent + Fl_Tree_Item *parent = item->parent(); // find item's parent if ( ! parent ) return(-1); parent->remove_child(item); // remove child + children } @@ -755,7 +761,8 @@ Fl_Tree_Item* Fl_Tree::item_clicked() { /// Fl_Tree_Item *Fl_Tree::next_visible_item(Fl_Tree_Item *item, int dir) { if ( ! item ) { // no start item? - item = ( dir == FL_Up ) ? last() : first(); // start at top or bottom + item = ( dir == FL_Up ) ? last_visible() : // wrap to bottom + first_visible(); // wrap to top if ( ! item ) return(0); if ( item->visible_r() ) return(item); // return first/last visible item } @@ -782,6 +789,19 @@ Fl_Tree_Item* Fl_Tree::first() { return(_root); // first item always root } +/// Returns the first visible item in the tree. +/// \returns first visible item in tree, or 0 if none. +/// \see first_visible(), last_visible() +/// +Fl_Tree_Item* Fl_Tree::first_visible() { + Fl_Tree_Item *i = showroot() ? first() : next(first()); + while ( i ) { + if ( i->visible() ) return(i); + i = next(i); + } + return(0); +} + /// Return the next item after \p item, or 0 if no more items. /// /// Use this code to walk the entire tree: @@ -844,6 +864,26 @@ Fl_Tree_Item* Fl_Tree::last() { return(item); } +/// Returns the last visible item in the tree. +/// \returns last visible item in the tree, or 0 if none. +/// +/// \see first_visible(), last_visible() +/// +Fl_Tree_Item* Fl_Tree::last_visible() { + Fl_Tree_Item *item = last(); + while ( item ) { + if ( item->visible() ) { + if ( item == _root && !showroot() ) { + return(0); + } else { + return(item); + } + } + item = prev(item); + } + return(item); +} + /// Returns the first selected item in the tree. /// /// Use this to walk the tree looking for all the selected items, eg: @@ -1334,6 +1374,11 @@ int Fl_Tree::select_all(Fl_Tree_Item *item, int docallback) { return(count); } +/// Get the item that currently has keyboard focus. +Fl_Tree_Item* Fl_Tree::get_item_focus() const { + return(_item_focus); +} + /// Set the item that currently should have keyboard focus. /// Handles calling redraw() to update the focus box (if it is visible). /// @@ -1899,6 +1944,12 @@ void Fl_Tree::scrollbar_size(int size) { } } +/// See if the vertical scrollbar is currently visible. +/// \returns 1 if scrollbar visible, 0 if not. +int Fl_Tree::is_vscroll_visible() const { + return(_vscroll->visible() ? 1 : 0); +} + /// Do the callback for the item, setting the item and reason void Fl_Tree::do_callback_for_item(Fl_Tree_Item* item, Fl_Tree_Reason reason) { callback_reason(reason); diff --git a/src/Fl_Tree_Item.cxx b/src/Fl_Tree_Item.cxx index d20437b9e..31080b40c 100644 --- a/src/Fl_Tree_Item.cxx +++ b/src/Fl_Tree_Item.cxx @@ -1023,34 +1023,13 @@ void Fl_Tree_Item::update_prev_next(int index) { /// \returns the next visible item below us, or 0 if there's no more items. /// Fl_Tree_Item *Fl_Tree_Item::next_displayed(Fl_Tree_Prefs &prefs) { - Fl_Tree_Item *c = this; - while ( c ) { - if ( c->is_root() && !prefs.showroot() ) { // on root and can't show it? - c = c->next(); // skip ahead, try again - continue; - } - if ( c->has_children() && c->is_close() ) { // item has children and: invisible or closed? - // Skip children, take next sibling. If none, try parent's sibling, repeat - while ( c ) { - Fl_Tree_Item *sib = c->next_sibling(); // get sibling - if ( sib ) { c = sib; break; } // Found? let outer loop test it - c = c->parent(); // No sibling? move up tree, try parent's sibling - } - } else { // has children and isn't closed, or no children - c = c->next(); // use normal 'next' - } - if ( !c ) return(0); // no more? done - // Check all parents to be sure none are closed. - // If closed, move up to that level and repeat until sure none are closed. - Fl_Tree_Item *p = c->parent(); - while (1) { - if ( !p || p->is_root() ) return(c); // hit top? then we're displayed, return c - if ( p->is_close() ) c = p; // found closed parent? make it current - p = p->parent(); // continue up tree - } - if ( c && c->visible() ) return(c); // item visible? return it + Fl_Tree_Item *item = this; + while ( 1 ) { + item = item->next(); + if ( !item ) return 0; + if ( item->is_root() && !prefs.showroot() ) continue; + if ( item->visible_r() ) return(item); } - return(0); // hit end: no more items } /// Return the previous visible item. (If this item above us has children and is closed, its children are skipped) @@ -1087,7 +1066,8 @@ Fl_Tree_Item *Fl_Tree_Item::prev_displayed(Fl_Tree_Prefs &prefs) { /// 0 -- item (or parents) invisible or close()ed. /// int Fl_Tree_Item::visible_r() const { - for (const Fl_Tree_Item *p=this; p; p=p->parent()) // move up through parents + if ( !visible() ) return(0); + for (const Fl_Tree_Item *p=parent(); p; p=p->parent())// move up through parents if (!p->visible() || p->is_close()) return(0); // any parent not visible or closed? return(1); } diff --git a/test/tree.fl b/test/tree.fl index e8c37d519..35c81ce47 100644 --- a/test/tree.fl +++ b/test/tree.fl @@ -336,7 +336,7 @@ Function {} {open } { Fl_Window window { label tree open - xywh {5 21 1045 580} type Double visible + xywh {5 44 1045 580} type Double visible } { Fl_Group tree { label Tree @@ -1586,6 +1586,13 @@ tree->redraw();} tooltip {Sets the default label bg color for newly created items. When set, this overrides the default behavior of using Fl_Tree::color().} xywh {975 477 16 16} box DOWN_BOX labelsize 12 align 7 code0 {item_labelbgcolor_button->color(tree->item_labelbgcolor());} } + Fl_Button x_item_labelbgcolor_button { + label X + callback {tree->item_labelbgcolor(0xffffffff); +UpdateColorChips(); +tree->redraw();} + tooltip {Make the bgcolor 'transparent' (0xffffffff)} xywh {995 477 16 16} labelsize 10 align 16 + } Fl_Button testsuggs_button { label {Test Suggestions} callback {const char *helpmsg = @@ -1650,13 +1657,6 @@ helpwin->resizable(helpdisp); helpwin->show();} selected tooltip {Suggestions on how to do tests} xywh {935 554 95 16} labelsize 9 } - Fl_Button x_item_labelbgcolor_button { - label X - callback {tree->item_labelbgcolor(0xffffffff); -UpdateColorChips(); -tree->redraw();} - tooltip {Make the bgcolor 'transparent' (0xffffffff)} xywh {995 477 16 16} labelsize 10 align 16 - } } Fl_Box resizer_box { xywh {0 263 15 14} |
