note description: "[ Base class for all the tool windows. Has history list for stepping forward and backward through the `viewable_items' which have been displayed in the tool. The {TOOL} is a EV_FRAME containing an EV_VERTICAL_BOX called `main_container'. Into `main_container' is placed an EV_HORIZONTAL_BOX serving as a toolbar called `title_bar'. (An EV_HORIZONTAL_BOX was used instead of a EV_TOOL_BAR in order to add widgets other than EV_TOOLBAR_BUTTONS to the toolbar, giving the desired look.) The `title_bar' is built by adding text, buttons, spaces, other bars, etc to it. Below the `title_bar' is added the `cell' from `split_manager' which contains any {VIEW}s in the tool. TNL = `tool_name_label' -- contains the `name' of the tool HTB = `history_tool_bar` -- contains the forth and back buttons TL = `target_label' -- shows the name of the object in the tool TB = `tool_bar' -- clients add buttons here UT = `user_text' -- an EV_LABEL allowed to expand (see `set_user_text') RTB = `resize_tool_bar' -- contains the minimize/miximize and close buttons FB = `forth_button' -- To go back in the history BB = `back_button' -- to go forward in the history xB = `maximize_button' or `restore_button' X = `close_button' `bar' = split_manager.bar -- any buttons produced by `split_manager' are here |------------------------------ title bar -----------------------------------| | | TNL | |--- HTB ---| | TL | |-- TB --| | `bar' | | UT | |--- RTB ---| | | |BB| |FB| | | ... | | ... | | |xB| |X| | |----------------------------------------------------------------------------| | | | | | split_manager.cell | | | | | |----------------------------------------------------------------------------| The `bar' and `cell', both from `split_manager', will be empty because no {VIEW}s have been added to the `split_manager'. Descendants should follow this pattern as described in class {SPLIT_MANAGER}, redefining `initialize'. feature initialize is -- Set up the window. -- Redefine to add the views to the window. do Precursor {TOOL} split_manager.extend (view_one) split_manager.extend (view_two) end Feature `initialize' above assumes two features, `view_one' and `view_two', to be defined to return a descendant of {VIEW} and some effected EV_WIDGET. ]" date: "30 Sep 03" author: "Jimmy J. Johnson" copyright: "Copyright 2012, Jimmy J. Johnson" license: "Eiffel Forum License v2 (see forum.txt)" URL: "$URL: file:///F:/eiffel_repositories/jj_vision/trunk/interface/tools/tool.e $" date: "$Date: 2015-10-24 07:32:40 -0700 (Sat, 24 Oct 2015) $" revision: "$Revision: 23 $" class TOOL inherit VIEW undefine -- default_create, copy redefine create_interface_objects, initialize, add_actions, set_target, draw, state end EV_FRAME rename object_id as ise_object_id undefine is_in_default_state redefine create_interface_objects, initialize end PIXEL_BUFFERS undefine default_create, copy end create make feature {NONE} -- Initialization create_interface_objects -- Create objects to be used by `Current' in `initialize' -- Implemented by descendants to create attached objects -- in order to adhere to void-safety due to the implementation bridge pattern. do Precursor {VIEW} Precursor {EV_FRAME} -- create history create history_dropdown create main_container -- Create the action sequences create maximize_actions create close_actions create restore_actions -- Create the buttons create title_bar create tool_bar create history_tool_bar -- create user_text create resize_tool_bar create tool_name_label create target_label -- create history_combo -- see "fix me" comment before `update_history_combo' feature create split_manager -- Create buttons create back_button create forth_button create maximize_button create restore_button create close_button size_button := maximize_button -- Set button attributes back_button.set_pixmap (create {EV_PIXMAP}.make_with_pixel_buffer (Icon_back_color_buffer)) back_button.set_tooltip ("Back") forth_button.set_pixmap (create {EV_PIXMAP}.make_with_pixel_buffer (Icon_forth_color_buffer)) forth_button.set_tooltip ("Forth") maximize_button.set_pixmap (create {EV_PIXMAP}.make_with_pixel_buffer (Icon_maximize_color_buffer)) maximize_button.set_tooltip ("Maximize") restore_button.set_pixmap (create {EV_PIXMAP}.make_with_pixel_buffer (Icon_restore_color_buffer)) restore_button.set_tooltip ("Restore") close_button.set_pixmap (create {EV_PIXMAP}.make_with_pixel_buffer (Icon_close_color_buffer)) close_button.set_tooltip ("Close") end initialize -- Build the interface for this window -- Must create `view' before calling this. local hs: EV_HORIZONTAL_SEPARATOR do Precursor {EV_FRAME} Precursor {VIEW} -- tools.extend (Current) -- Prevent the tool from holding more than one target, so -- the history functions will work. history_dropdown.set_parent_tool (Current) target_label.set_minimum_width (Target_label_width) -- view_manager.set_single_mode -- split_manager.disable_mode_changes -- Create the toolbar build_tool_bars build_title_bar -- To get the tool bar look I used small 16x16 pixel icons. -- The `title_bar' is an EV_HORIZONTAL_BOX which contains several -- widets. These are a EV_LABLE, an EV_TOOL_BAR, another label -- (which is allowed to expand), and finally another EV_TOOL_BAR -- containing the `minimize_button' or the `restore_button' (depending -- on `is_maximized') and the `close_button'. main_container.extend (title_bar) main_container.disable_item_expand (title_bar) create hs main_container.extend (hs) main_container.disable_item_expand (hs) main_container.extend (split_manager.cell) extend (main_container) set_minimum_height (100) -- set_view (Default_view) -- set_button_states -- No, do not call `add_actions'; it is already called -- from {VIEW}.`initialize' throught {SPLIT_VIEW} -- add_actions end build_title_bar -- Create the small title bar at top of tool local lab: EV_LABEL do -- Add the name of tool to the title bar tool_name_label.set_text (generating_type.name) title_bar.extend (tool_name_label) title_bar.disable_item_expand (tool_name_label) -- Add the forth and back buttons (in `history_tool_bar') title_bar.extend (history_tool_bar) title_bar.disable_item_expand (history_tool_bar) -- Add a title to the tool -- title_bar.extend (target_label) -- title_bar.disable_item_expand (target_label) -- Add a history list combo box -- history_combo.disable_edit -- title_bar.extend (history_combo) -- see "fix me" comment before `update_history_combo' feature -- If use EV_COMBO_BOX the title bar must be bigger to -- allow for `minimum_height' of the box. -- Add the tool bar (to be used in descendants title_bar.extend (tool_bar) title_bar.disable_item_expand (tool_bar) -- Put in a spacer to move the mode buttons to right create lab.make_with_text (" ") title_bar.extend (lab) title_bar.disable_item_expand (lab) -- Add the `bar' from `view_manager' here title_bar.extend (split_manager.bar) -- title_bar.disable_item_expand (split_manager.bar) -- Add the maximize/minimize and hide buttons (in `resize_tool_bar') title_bar.extend (resize_tool_bar) title_bar.disable_item_expand (resize_tool_bar) end build_tool_bars -- Create the tool bar. local vs: EV_VERTICAL_SEPARATOR do history_tool_bar.extend (back_button) history_tool_bar.extend (forth_button) history_tool_bar.extend (target_label) -- create vs -- history_tool_bar.extend (vs) -- history_tool_bar.disable_item_expand (vs) resize_tool_bar.extend (size_button) resize_tool_bar.extend (close_button) end add_actions -- Add functionality to the buttons. do Precursor {VIEW} target_label.set_pebble_function (agent on_get_target) -- Add actions to the buttons. maximize_button.select_actions.extend (agent on_maximize) restore_button.select_actions.extend (agent on_restore) close_button.select_actions.extend (agent on_close) back_button.select_actions.extend (agent on_back) forth_button.select_actions.extend (agent on_forth) -- Add actions to `history' history_dropdown.select_actions.extend (agent on_history_item_selected) target_label.pointer_button_press_actions.extend (agent on_target_label_selected) -- target_label.drop_actions.extend (agent on_field_dropped_on_target_label) -- see "fix me" comment before `update_history_combo' feature -- history_combo.select_actions.extend (agent on_history_selected) -- Add actions to update any views contained in this tool -- No. Don't do this as the tool may contain views which only want to handle a part of the viewable. -- Passing the wrong kind breaks the contract. Make each descendent descide what to pass to its children views. -- viewable_added_action_sequence.extend (agent on_viewable_added) end feature -- Access tool_bar: EV_HORIZONTAL_BOX --EV_TOOL_BAR -- Available for adding new buttons in descendants. state: TOOL_STATE -- Snapshot of the current settings of Current do create Result.make (Current) end feature -- Element change set_target (a_target: like target) -- Change the value of `target' and add it to the `object_set' (the set -- of objects contained in this view. The old target is removed from -- the set. do Precursor {VIEW} (a_target) update_history -- if target_imp /= a_target then -- Precursor {VIEW} (a_target) ---- add_object (a_target.target_label_field) ---- tool_label.set_accept_cursor (a_viewable.accept_cursor) ---- tool_label.set_deny_cursor (a_viewable.deny_cursor) -- update_history -- draw -- end end -- set_user_text (a_string: STRING) -- -- Change the `user_text' -- do -- user_text.set_text (a_string) -- end feature {SPLIT_MANAGER, HISTORY_DROPDOWN} -- Access tool_name_label: EV_LABEL -- String in top left of toolbar to display the name of the tool. target_label: EV_LABEL -- String in the bar to display the name of the `target'. maximize_actions: EV_NOTIFY_ACTION_SEQUENCE -- Actions to be performed when the tool is maximized. close_actions: EV_NOTIFY_ACTION_SEQUENCE -- Actions to be performed when the tool is closed. restore_actions: EV_NOTIFY_ACTION_SEQUENCE -- Actions to be performed when the tool is restored. feature -- Element change -- set_user_text (a_text: STRING_8) -- -- Change the `user_text' that is displayed in the title bar. -- do -- user_text.set_text (a_text) -- end feature -- Status report is_maximized: BOOLEAN -- Is the tool in a maximized state? is_resizable: BOOLEAN -- Is the tool resizable? (E.g. is the `resize_tool_bar' visible?) do Result := resize_tool_bar.is_displayed end -- is_destroyed: BOOLEAN -- -- Is `Current' no longer usable? -- do -- Result := not tools.has (Current) and Precursor {EV_FRAME} -- end feature -- Status setting enable_resize -- Allow the `resize_tool_bar' to show. do resize_tool_bar.show end disable_resize -- Hide the `resize_tool_bar'. do resize_tool_bar.hide end enable_history -- Make the `history_tool_bar' visible do history_tool_bar.show -- target_label.show end disable_history -- Make the `history_tool_bar' NOT visible do history_tool_bar.hide -- target_label.hide end feature -- Basic operations draw -- Builds the string shown at top of the tool in `viewable_label' -- using the id of the object. local n: STRING s: STRING f: EV_FONT i: INTEGER w: INTEGER -- for testing do if is_view_empty then n := "Empty" else if attached {EDITABLE} target as e then n := e.display_name else n := target.generating_type end end f := target_label.font create s.make (0) from i := 1 until i > n.count or else f.string_width (s) >= Target_label_width loop w := f.string_width (s) s.append_character (n.item (i)) i := i + 1 end if f.string_width (s) > Target_label_width then s.remove_tail (1) end target_label.set_text (s) target_label.set_tooltip (n) set_button_states end feature {NONE} -- Actions -- on_field_dropped_on_target_label (a_field: STRING_FIELD) is -- -- React to a drop of `a_field' onto the `target_label'. -- require -- field_exists: a_field /= Void -- do -- target.set_target_label_field (a_field) -- draw_views (target.target_label_field) -- end on_target_label_selected (a_x, a_y, a_button: INTEGER; a_x_tilt, a_y_tilt, a_pressure: DOUBLE; a_screen_x, a_screen_y: INTEGER) -- do if a_button = 1 then history_dropdown.show end end on_history_item_selected -- React to an item selection from the `history_dropdown'. do set_target (selected_history_item_target) end on_get_target: like target -- Used as agent for `target_label.get_pebble_function' because -- an attribute cannot be used as an agent do Result := target end -- see "fix me" comment before `update_history_combo' feature -- on_history_selected is -- -- Handle an item select in the history combo box -- require -- history_exists: history /= Void -- local -- cli: CLUSTER_LIST_ITEM -- do -- cli ?= history_combo.selected_item -- check -- cli_not_void: cli /= Void -- because only CLUSTER_LIST_ITEMS should be in list -- end -- set_cluster (cli.cluster) -- end on_back -- Handle a go back request (from button or menu). require history_exists: history_dropdown /= Void history_can_go_back: not history_dropdown.is_off and then not history_dropdown.is_before local v: HISTORY_ITEM do history_dropdown.back v := history_dropdown.item check attached {like target} v.target as t then set_target (t) end set_button_states end on_forth -- Handle a go forth request (from button or menu). require history_exists: history_dropdown /= Void history_can_go_forth: not history_dropdown.is_off and then not history_dropdown.is_after local v: HISTORY_ITEM do history_dropdown.forth v := history_dropdown.item check attached {like target} v.target as t then set_target (t) end set_button_states end on_maximize -- React to a request (button or menu) to "maximize" by performing -- the actions in `maximize_actions'. require resizing_allowed: is_resizable do maximize_actions.call ([]) end on_restore -- React to a request (button or menu) to "maximize" by performing -- the actions in `maximize_actions'. require resizing_allowed: is_resizable do restore_actions.call ([]) end on_close -- React to a close request by executing the `close_actions'. require resizing_allowed: is_resizable do close_actions.call ([]) end feature {SPLIT_MANAGER, TOOL_STATE} -- Actions maximize -- Put window in maximized state require resizing_allowed: is_resizable do is_maximized := True if not (size_button = restore_button) then resize_tool_bar.go_i_th (resize_tool_bar.index_of (size_button, 1)) resize_tool_bar.replace (restore_button) size_button := restore_button end close_button.disable_sensitive end restore -- Put window back in default state require -- resizing_allowed: is_resizable do is_maximized := False if not (size_button = maximize_button) then resize_tool_bar.go_i_th (resize_tool_bar.index_of (size_button, 1)) resize_tool_bar.replace (maximize_button) size_button := maximize_button end close_button.enable_sensitive end close_button: EV_TOOL_BAR_BUTTON -- Button containing an "X" icon maximize_button: EV_TOOL_BAR_BUTTON -- Button which parent can access intended -- to be used to maximize the tool. restore_button: EV_TOOL_BAR_BUTTON -- Button which parent can access intended -- to be used to normalize (restore) the tool. feature {NONE} -- Implementation update_history -- Update the history list. require target_exists: target /= Void local found: BOOLEAN v: HISTORY_ITEM oldest_v: HISTORY_ITEM do -- if not history.has (viewable) then -- not needed if history is a SET -- does history have viewable? Must do a search because list items from history_dropdown.start until found or else history_dropdown.is_exhausted loop v := history_dropdown.item if v.is_simular (new_history_item) then found := True else history_dropdown.forth end end if found then -- leave list as is but change time stamp of found item v := history_dropdown.item v.reset_time_stamp else -- not found so must add a new one v := new_history_item history_dropdown.extend (v) if history_dropdown.count > maximum_history_items then -- find oldest item in list and remove it oldest_v := history_dropdown.first from history_dropdown.start until history_dropdown.is_exhausted loop v := history_dropdown.item if v.time_stamp < oldest_v.time_stamp then oldest_v := history_dropdown.item end history_dropdown.forth end history_dropdown.start history_dropdown.prune (oldest_v) end history_dropdown.start history_dropdown.search (v) -- Display a string describing the target target_label.set_text (v.target.generating_type.name + " " + v.time_stamp.as_string) check not_off: not history_dropdown.is_off -- because just inserted it end end -- update_history_combo -- see "fix me" comment before `update_history_combo' feature -- set_button_states -- end ensure proper_histroy_count: history_dropdown.count <= maximum_history_items end -- Fix me!!! -- `update_history_combo' is a problem. -- Line "history_combo.wipe_out" causes a system crash, perhaps the screen -- objects are not getting destroyed? Tried destroying each item in combo -- but that did not help. -- Also, can't seem to set the text; get an infinate loop? -- Besides, the combo box is too tall; it make the TOOL's toolbar and buttons -- too big, so commenting it out. -- update_history_combo is -- -- Put the history items into the `history_combo' box -- local -- cli: CLUSTER_LIST_ITEM -- pos: CURSOR -- c: CLUSTER -- do -- history_combo.wipe_out -- pos := history.cursor -- c := history.item.cluster -- from history.start -- until history.exhausted -- loop -- if history.item.cluster /= c then -- create cli.make (history.item.cluster) -- history_combo.extend (cli) -- end -- history.forth -- end -- history.go_to (pos) -- history_combo.enable_edit -- so set_text will work -- history_combo.set_text (history.item.cluster.id) -- history_combo.disable_edit -- end set_button_states -- Set the states of the back and forth buttons. do if history_dropdown.is_empty or history_dropdown.is_first or history_dropdown.is_before then back_button.disable_sensitive else back_button.enable_sensitive end if history_dropdown.is_empty or history_dropdown.is_last or history_dropdown.is_after then forth_button.disable_sensitive else forth_button.enable_sensitive end if history_dropdown.is_empty then target_label.disable_sensitive else target_label.enable_sensitive end end main_container: EV_VERTICAL_BOX -- Holds the other widgets in the TOOL. title_bar: EV_HORIZONTAL_BOX -- Holds the name of tool, `history_tool_bar', and `resize_tool_bar'. history_tool_bar: EV_HORIZONTAL_BOX --EV_TOOL_BAR -- The toolbar with the forth, back and posibly history buttons. -- user_text: EV_LABEL -- -- Text settable by `set_user_text' resize_tool_bar: EV_TOOL_BAR -- Tool bar to hold resize and close buttons feature {NONE} -- Implementation forth_button: EV_BUTTON --EV_TOOL_BAR_BUTTON -- Button containing go back icon back_button: EV_BUTTON --EV_TOOL_BAR_BUTTON -- Button containing go forth icon size_button: EV_TOOL_BAR_BUTTON -- Button containing maximize or restore icon -- history_combo: EV_COMBO_BOX -- see "fix me" comment before `update_history_combo' feature -- To pull down a history list maximum_history_items: INTEGER = 5 -- Number of items to keep in history list feature {HISTORY_DROPDOWN} -- Implementation history_dropdown: HISTORY_DROPDOWN -- A dropdown-like box containing the clusters previously targetted -- in this tool from which selections can be made to retarget the tool. new_history_item: HISTORY_ITEM -- Helper routine called by `update_history' when it needs to -- create a new time-stamped viewable for placement in the `history'. -- Made a seperate routine because descendents may want to store -- other types of items in the history list. do create Result.make (target) end selected_history_item_target: like target -- The item from the `history_dropdown' typecast to `target' do check attached {HISTORY_ITEM} history_dropdown.selected_item as hi then check attached {like target} hi.target as t then Result := t end end ensure Result_exists: Result /= Void end feature {NONE} -- Implementation split_manager: SPLIT_MANAGER -- Controls placement of sub-windows --feature {TOOL} -- Implementation -- tools: LINKED_SET [TOOL] -- -- Keeps track of all the TOOLs in the system -- once -- create Result.make -- end feature {NONE} -- Constants Target_label_width: INTEGER = 100 -- Sets the size of the `target_label' in pixels. invariant close_button_exists: close_button /= Void restore_button_exists: restore_button /= Void maximize_button_exists: maximize_button /= Void -- label_clickable_when: history.is_empty implies not object_label.is_sensitive end