@ -195,21 +195,24 @@ int Fl_Tree::handle(int e) {
// Do shortcuts first or scrollbar will get them...
// Do shortcuts first or scrollbar will get them...
if ( ( Fl : : focus ( ) = = this ) & & // tree has focus?
if ( ( Fl : : focus ( ) = = this ) & & // tree has focus?
_prefs . selectmode ( ) > FL_TREE_SELECT_NONE ) { // select mode that supports kb events?
_prefs . selectmode ( ) > FL_TREE_SELECT_NONE ) { // select mode that supports kb events?
if ( ! _item_focus ) {
if ( ! _item_focus ) { // no current focus item?
set_item_focus ( first ( ) ) ;
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 ) {
if ( _item_focus ) {
int ekey = Fl : : event_key ( ) ;
int ekey = Fl : : event_key ( ) ;
switch ( ekey ) {
switch ( ekey ) {
case FL_Enter : // ENTER: toggle open/close
case FL_Enter : // ENTER: toggle open/close
case FL_KP_Enter : {
case FL_KP_Enter : {
open_toggle ( _item_focus , when ( ) ) ;
open_toggle ( _item_focus , when ( ) ) ; // toggle item in focus
break ;
return ( 1 ) ; // done, we handled key
}
}
case ' ' : // SPACE: change selection state
case ' ' : // SPACE: change selection state
switch ( _prefs . selectmode ( ) ) {
switch ( _prefs . selectmode ( ) ) {
case FL_TREE_SELECT_NONE :
case FL_TREE_SELECT_NONE :
break ;
break ; // ignore, let group have shot at event
case FL_TREE_SELECT_SINGLE :
case FL_TREE_SELECT_SINGLE :
if ( is_ctrl ) { // CTRL-SPACE: (single mode) toggle
if ( is_ctrl ) { // CTRL-SPACE: (single mode) toggle
if ( ! _item_focus - > is_selected ( ) ) {
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
select_only ( _item_focus , when ( ) ) ; // SPACE: (single mode) select only
}
}
_lastselect = _item_focus ;
_lastselect = _item_focus ;
return ( 1 ) ;
return ( 1 ) ; // done, we handled key
case FL_TREE_SELECT_MULTI :
case FL_TREE_SELECT_MULTI :
if ( is_ctrl ) {
if ( is_ctrl ) {
select_toggle ( _item_focus , when ( ) ) ; // CTRL-SPACE: (multi mode) toggle selection
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
select ( _item_focus , when ( ) ) ; // SPACE: (multi-mode) select
}
}
_lastselect = _item_focus ;
_lastselect = _item_focus ;
return ( 1 ) ;
return ( 1 ) ; // done, we handled key
}
}
break ;
break ;
case FL_Right : // RIGHT: open children (if any)
case FL_Right : // RIGHT: open children (if any)
@ -280,7 +283,7 @@ int Fl_Tree::handle(int e) {
case FL_TREE_SELECT_MULTI :
case FL_TREE_SELECT_MULTI :
// Do a 'select all'
// Do a 'select all'
select_all ( ) ;
select_all ( ) ;
_lastselect = first ( ) ;
_lastselect = first_visible ( ) ;
take_focus ( ) ;
take_focus ( ) ;
return ( 1 ) ;
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.
/// Remove the specified \p item from the tree.
/// \p item may not be NULL.
/// \p item may not be NULL.
/// If it has children, all those are removed too.
/// 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.
/// \returns 0 if done, -1 if 'item' not found.
///
///
int Fl_Tree : : remove ( Fl_Tree_Item * item ) {
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 ) {
if ( item = = _root ) {
clear ( ) ;
clear ( ) ;
} else {
} 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 ) ;
if ( ! parent ) return ( - 1 ) ;
parent - > remove_child ( item ) ; // remove child + children
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 ) {
Fl_Tree_Item * Fl_Tree : : next_visible_item ( Fl_Tree_Item * item , int dir ) {
if ( ! item ) { // no start item?
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 ) return ( 0 ) ;
if ( item - > visible_r ( ) ) return ( item ) ; // return first/last visible item
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
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.
/// Return the next item after \p item, or 0 if no more items.
///
///
/// Use this code to walk the entire tree:
/// Use this code to walk the entire tree:
@ -844,6 +864,26 @@ Fl_Tree_Item* Fl_Tree::last() {
return ( item ) ;
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.
/// Returns the first selected item in the tree.
///
///
/// Use this to walk the tree looking for all the selected items, eg:
/// 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 ) ;
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.
/// Set the item that currently should have keyboard focus.
/// Handles calling redraw() to update the focus box (if it is visible).
/// 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
/// 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 ) {
void Fl_Tree : : do_callback_for_item ( Fl_Tree_Item * item , Fl_Tree_Reason reason ) {
callback_reason ( reason ) ;
callback_reason ( reason ) ;