diff --git a/include/nana/gui/widgets/listbox.hpp b/include/nana/gui/widgets/listbox.hpp index 63ee49ca..34c0dfcd 100644 --- a/include/nana/gui/widgets/listbox.hpp +++ b/include/nana/gui/widgets/listbox.hpp @@ -800,12 +800,31 @@ namespace nana /// posible use: last_selected_display = last_selected.to_display().item; use with caution, it get invalidated after a sort() index_pair to_display() const; + /// Determines whether the item is displayed on the screen + bool displayed() const; + bool empty() const; - item_proxy & check(bool ck); + /// Checks/unchecks the item + /** + * @param chk Indicates whether to check or uncheck the item + * @param scroll_view Indicates whether to scroll the view to the item. It is ignored if the item is displayed. + * @return the reference of *this. + */ + item_proxy & check(bool chk, bool scroll_view = false); + + /// Determines whether the item is checked bool checked() const; - item_proxy & select(bool); + /// Selects/unselects the item + /** + * @param sel Indicates whether to select or unselect the item + * @param scroll_view Indicates whether to scroll the view to the item. It is ignored if the item is displayed. + * @return the reference of *this. + */ + item_proxy & select(bool sel, bool scroll_view = false); + + /// Determines whether he item is selected bool selected() const; item_proxy & bgcolor(const nana::color&); diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 0dcccdd0..cd40636f 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -4506,12 +4506,28 @@ namespace nana return ess_->lister.relative_pair(pos_); } + bool item_proxy::displayed() const + { + if (!ess_->lister.get(pos_.cat)->expand) + return false; + + auto pos = to_display(); + if (ess_->scroll.offset_y_dpl > pos) + return false; + + auto size = ess_->number_of_lister_items(false); + + auto last = ess_->lister.advance(ess_->scroll.offset_y_dpl, size); + + return (last > pos || last == pos); + } + bool item_proxy::empty() const { return !ess_; } - item_proxy & item_proxy::check(bool ck) + item_proxy & item_proxy::check(bool ck, bool scroll_view) { internal_scope_guard lock; auto & m = cat_->items.at(pos_.item); @@ -4520,6 +4536,15 @@ namespace nana m.flags.checked = ck; ess_->lister.emit_checked(pos_); + if (scroll_view) + { + if (ess_->lister.get(pos_.cat)->expand) + ess_->lister.get(pos_.cat)->expand = false; + + if (!this->displayed()) + ess_->lister.scroll(pos_, !(ess_->scroll.offset_y_dpl > this->to_display())); + } + ess_->update(); } return *this; @@ -4531,26 +4556,37 @@ namespace nana } /// is ignored if no change (maybe set last_selected anyway??), but if change emit event, deselect others if need ans set/unset last_selected - item_proxy & item_proxy::select(bool s) + item_proxy & item_proxy::select(bool sel, bool scroll_view) { internal_scope_guard lock; //pos_ never represents a category if this item_proxy is available. auto & m = cat_->items.at(pos_.item); // a ref to the real item - if(m.flags.selected == s) return *this; // ignore if no change - m.flags.selected = s; // actually change selection - - ess_->lister.emit_selected(this->pos_); - - if (m.flags.selected) + if (m.flags.selected != sel) { - ess_->lister.cancel_others_if_single_enabled(true, pos_); //Cancel all selections except pos_ if single_selection is enabled. - ess_->lister.last_selected_abs = pos_; - } - else if (ess_->lister.last_selected_abs == pos_) + m.flags.selected = sel; // actually change selection + + ess_->lister.emit_selected(this->pos_); + + if (m.flags.selected) + { + ess_->lister.cancel_others_if_single_enabled(true, pos_); //Cancel all selections except pos_ if single_selection is enabled. + ess_->lister.last_selected_abs = pos_; + } + else if (ess_->lister.last_selected_abs == pos_) ess_->lister.last_selected_abs.set_both(npos); - ess_->update(); + if (scroll_view) + { + if (ess_->lister.get(pos_.cat)->expand) + ess_->lister.get(pos_.cat)->expand = false; + + if (!this->displayed()) + ess_->lister.scroll(pos_, !(ess_->scroll.offset_y_dpl > this->to_display())); + } + + ess_->update(); + } return *this; }