indexing description: "[ A widget displaying only the currently selected element. The element can be changed by a drop-down list. See EM_LIST. ]" date: "$Date$" revision: "$Revision$" class EM_COMBOBOX [G] inherit EM_LIST [G] redefine set_font end EM_SHARED_SCENE export {NONE} all end create make_empty, make_from_list feature {NONE} -- Initialisation make_empty is -- Initialise empty list. do create list.make_empty to_string_agent := list.to_string_agent make_list make_void_surface set_keyboard_sensitive (True) resize_to_optimal_dimension key_down_event.subscribe (agent handle_key_down) focus_lost_event.subscribe (agent handle_focus_lost) mouse_button_down_event.subscribe (agent handle_mouse_button_down) list.selection_changed_event.subscribe (agent handle_element_selected) end make_from_list (a_list: DS_LINEAR [G]) is -- Initialise list with elements from `a_list'. do make_empty elements_impl.extend_last (a_list) resize_to_optimal_dimension end delegate_factory: FUNCTION [ANY, TUPLE [], like delegate] is -- Factory to create default delegate do Result := theme_delegates.combobox_delegate_factory end feature -- Access to_string_agent: FUNCTION [ANY, TUPLE [G], STRING] -- Agent to convert elements to a string. feature -- Element change set_to_string_agent (an_agent: like to_string_agent) is -- Set `to_string_agent' to `an_agent'. require an_agent_not_void: an_agent /= Void do to_string_agent := an_agent list.set_to_string_agent (an_agent) set_changed ensure to_string_agent_set: to_string_agent = an_agent changed: is_changed end set_font (a_font: EM_FONT) is -- Set `font' to `a_font'. do Precursor {EM_LIST} (a_font) list.set_font (a_font) end set_selection_background_color (a_color: EM_COLOR) is -- Set background color of selected elements to `a_color'. require a_color_not_void: a_color /= Void do list.set_selection_background_color (a_color) set_changed ensure changed: is_changed end set_selection_foreground_color (a_color: EM_COLOR) is -- Set foreground color of selected elements to `a_color'. require a_color_not_void: a_color /= Void do list.set_selection_foreground_color (a_color) set_changed ensure changed: is_changed end feature {NONE} -- Mouse management handle_mouse_button_down (event: EM_MOUSEBUTTON_EVENT) is -- Handle mouse clicked event. do if is_list_visible then hide_list else show_list end end feature {NONE} -- Keyboard management handle_key_down (event: EM_KEYBOARD_EVENT) is -- Handle key down event. local list_was_visible: BOOLEAN do list_was_visible := is_list_visible if event.key = event.sdlk_up then if selected_index > 1 then set_selected_index (selected_index - 1) else unselect end elseif event.key = event.sdlk_down then if selected_index < count then set_selected_index (selected_index + 1) end end if is_list_visible then if has_selected_element then list.set_selected_index (selected_index) else list.unselect end end if list_was_visible then show_list end end handle_focus_lost is -- Handle focus lost event. do hide_list end feature {NONE} -- Implementation is_list_visible: BOOLEAN -- Is list visible? list: EM_TEXTLIST [G] -- List displaying the elements handle_element_selected (an_element: G) is -- Handle element selected event of 'list'. do hide_list if an_element = Void then unselect else set_selected_element (an_element) end end show_list is -- Show the list local scene: EM_COMPONENT_SCENE do scene ?= running_scene if scene /= Void and not is_list_visible then list.selection_changed_event.suspend_subscription list.wipe_out list.extend (elements_impl) if has_void_element then list.insert_void_element end if has_selected_element then list.set_selected_element (selected_element) else list.unselect end list.set_dimension (width.max (list.optimal_width), list.optimal_height) list.selection_changed_event.restore_subscription if scene.screen.height - screen_y - height < list.height and screen_y > list.height then list.set_position (screen_x, screen_y-list.height) else list.set_position (screen_x, screen_y+height) end scene.add_component (list) is_list_visible := True else if running_scene = Void then Error_handler.raise_warning (Error_handler.Em_error_show_combobox_list_scene_void, []) else Error_handler.raise_warning (Error_handler.Em_error_show_combobox_list_scene_invalid, []) end end end hide_list is -- Hide the list local scene: EM_COMPONENT_SCENE do if is_list_visible then scene ?= running_scene if scene /= Void then scene.remove_component (list) is_list_visible := False else if running_scene = Void then Error_handler.raise_warning (Error_handler.Em_error_hide_combobox_list_scene_void, []) else Error_handler.raise_warning (Error_handler.Em_error_hide_combobox_list_scene_invalid, []) end end end end end