diff --git a/gui/components/gui_scrolled_list.cc b/gui/components/gui_scrolled_list.cc index c566f6e2b..ef9923117 100644 --- a/gui/components/gui_scrolled_list.cc +++ b/gui/components/gui_scrolled_list.cc @@ -82,6 +82,7 @@ gui_scrolled_list_t::gui_scrolled_list_t(enum type type, item_compare_func cmp) size = scr_size(0,0); pos = scr_coord(0,0); max_width = scr_size::inf.w; + multiple_selection = false; } @@ -100,7 +101,14 @@ void gui_scrolled_list_t::set_selection(int s) return; } gui_component_t* new_focus = item_list[s]; - + + // reset selected status + FOR(vector_tpl, v, item_list) { + scrollitem_t* item = dynamic_cast(v); + if( item ) { + item->selected = item==new_focus; + } + } container.set_focus(new_focus); } @@ -117,6 +125,19 @@ gui_scrolled_list_t::scrollitem_t* gui_scrolled_list_t::get_selected_item() cons return focus && item_list.is_contained(focus) ? focus : NULL; } +vector_tpl gui_scrolled_list_t::get_selections() const +{ + vector_tpl selections; + for( uint32 i=0; i (item_list[i]); + if( item && item->selected ) { + selections.append(i); + } + } + return selections; +} + + void gui_scrolled_list_t::clear_elements() { container.remove_all(); @@ -181,14 +202,16 @@ bool gui_scrolled_list_t::infowin_event(const event_t *ev) } if( ev->ev_class==EVENT_KEYBOARD && ev->ev_code == SIM_KEY_DOWN && (uint32)(get_selection()+1) < item_list.get_count()) { ev2.ev_code = SIM_KEY_TAB; + ev2.ev_key_mod &= ~1; } bool swallowed = gui_scrollpane_t::infowin_event(&ev2); + scrollitem_t* const new_focus = dynamic_cast( comp->get_focus() ); - // if different element is focused, call listeners - if (focus != dynamic_cast( comp->get_focus() ) ) { + // if different element is focused, calculate selection and call listeners + if ( focus != new_focus ) { + calc_selection(focus, new_focus, *ev); int new_selection = get_selection(); - call_listeners((long)new_selection); swallowed = true; } @@ -197,6 +220,43 @@ bool gui_scrolled_list_t::infowin_event(const event_t *ev) } +void gui_scrolled_list_t::calc_selection(scrollitem_t* old_focus, scrollitem_t* new_focus, event_t ev) +{ + if( !new_focus ) { + // do nothing. + return; + } + else if( !old_focus || !multiple_selection || ev.ev_key_mod==0 ) { + // simply select new_focus + FOR(vector_tpl, v, item_list) { + scrollitem_t* item = dynamic_cast(v); + if( item ) { + item->selected = item==new_focus; + } + } + } + else if( IS_CONTROL_PRESSED(&ev) ) { + // control key is pressed. select or deselect the focused one. + new_focus->selected = !new_focus->selected; + } + else if( IS_SHIFT_PRESSED(&ev) ) { + // shift key is pressed. + sint32 old_idx = item_list.index_of(old_focus); + sint32 new_idx = item_list.index_of(new_focus); + if( old_idx==-1 || new_idx==-1 ) { + // out of index!? + return; + } + const bool sel = !new_focus->selected; + for( sint32 i=min(old_idx,new_idx); i<=max(old_idx,new_idx); i++ ) { + scrollitem_t* item = dynamic_cast(item_list[i]); + if( item && i!=old_idx ) { + item->selected = sel; + } + } + } +} + void gui_scrolled_list_t::cleanup_elements() { bool reset = false; @@ -219,10 +279,13 @@ void gui_scrolled_list_t::cleanup_elements() void gui_scrolled_list_t::draw(scr_coord offset) { + // set focus scrollitem_t* focus = dynamic_cast( comp->get_focus() ); - if (focus) { - focus->focused = win_get_focus() == focus; - focus->selected = true; + FOR(vector_tpl, v, item_list) { + scrollitem_t* item = dynamic_cast(v); + if( item ) { + item->focused = item->selected && win_get_focus()==focus; + } } cleanup_elements(); @@ -239,9 +302,4 @@ void gui_scrolled_list_t::draw(scr_coord offset) } gui_scrollpane_t::draw(offset); - - if (focus) { - focus->focused = false; - focus->selected = false; - } -} +} \ No newline at end of file diff --git a/gui/components/gui_scrolled_list.h b/gui/components/gui_scrolled_list.h index 0a4a3ef0c..e6e6e299e 100644 --- a/gui/components/gui_scrolled_list.h +++ b/gui/components/gui_scrolled_list.h @@ -95,6 +95,9 @@ private: scr_coord_val max_width; // need for overlength entries item_compare_func compare; + + bool multiple_selection; // true when multiple selection is enabled. + void calc_selection(scrollitem_t*, scrollitem_t*, event_t); protected: scroll_container_t container; @@ -116,8 +119,12 @@ public: void set_selection(int s); sint32 get_selection() const; + vector_tpl get_selections() const; + scrollitem_t* get_selected_item() const; sint32 get_count() const { return item_list.get_count(); } + + void enable_multiple_selection() { multiple_selection = true; } /* when rebuilding a list, be sure to call recalculate the slider * with recalculate_slider() to update the scrollbar properly. */