note
	description: "[
		TOOL used to hold a JJ_TREE_VIEW for displaying a hierarchical
		structure of VIEWABLE_NODEs.
		]"
	author: "Jimmy J. Johnson"
	date: "21 Apr 06"

class
	JJ_TREE_TOOL

inherit

	TOOL
		redefine
			initialize,
			initialize_interface,
			set_actions,
			target,
			set_target,
			set_button_states,
			draw
		end

create
	default_create

feature {NONE} -- Initialization

	initialize
			-- Set up the window
		do
			create tree_view
				-- Create the new buttons before Precursor {TOOL} so `initialize'
				-- can call `set_actions' without a Void reference.
			create target_system_button
			create new_node_button
			create view_descendants_button
			create view_ancestors_button
			create cut_button
				-- "Register" the widgets with the `interface_table' in use by the
				-- current program (from SHARED in the "Standard Interface" cluster).
			interface_table.register_widget (target_system_button, "{JJ_TREE_TOOL} - target_system")
			interface_table.register_widget (new_node_button, "{JJ_TREE_TOOL} - new_node")
			interface_table.register_widget (view_descendants_button, "{JJ_TREE_TOOL} - view_descendants")
			interface_table.register_widget (view_ancestors_button, "{JJ_TREE_TOOL} - view_ancestors")
			interface_table.register_widget (cut_button, "{JJ_TREE_TOOL} - cut")
			interface_table.register_widget (Current, generating_type)
				-- Create the tool and its views
			Precursor {TOOL}
				-- Add the buttons to the `tool_bar' (from TOOL)
			tool_bar.extend (target_system_button)
			tool_bar.extend (new_node_button)
			tool_bar.extend (view_descendants_button)
			tool_bar.extend (view_ancestors_button)
			tool_bar.extend (cut_button)
				-- Set up the views in this tool.
--			view_manager.enable_mode_changes
			split_manager.extend (tree_view)
			set_actions_for_views
		end

	initialize_interface
			-- Create INTERFACE_ITEMs which could be used by Current.
			-- Called by `initialize'.
		do
				-- Only add an interface item for Current if its `interface_name' has
				-- not already been added; the other items are specific for this tool
				-- and most likely will not be redefine, so no need to check inclusion
				-- of these in the `interface_table'.
				-- In redefinitions of this feature call this at the end of the redefinition
				-- so an item for the `interface_name' can be added to the `interface_table'.
			if not interface_table.has_key (generating_type) then
				interface_table.add_item_with_tuple (<< generating_type, "JJ_TREE_TOOL", "Node tree tool", "Used to view relationships between nodes.", "icon_format_feature_descendants_color.ico">>)
			end
			interface_table.add_item_with_tuple (<<"{JJ_TREE_TOOL} - target_system", "Target System", "Make System be the target", "Set the target of this tool to the applications system.", "icon_object_symbol.ico">>)
			interface_table.add_item_with_tuple (<<"{JJ_TREE_TOOL} - new_node", "New Node", "Create a new node", "Create a new node.", "icon_cluster_symbol_color.ico">>)
			interface_table.add_item_with_tuple (<<"{JJ_TREE_TOOL} - view_descendants", "Descendents", "View descendants", "Show the descendent relationships of targeted object.", "icon_format_descendants_color.ico">>)
			interface_table.add_item_with_tuple (<<"{JJ_TREE_TOOL} - view_ancestors", "Ancestors", "View Ancestors", "Show the ancestor relationships of targeted object.", "icon_format_ancestors_color.ico">>)
			interface_table.add_item_with_tuple (<<"{JJ_TREE_TOOL} - cut", "Cut relationship", "Cut the link to the selected node", "Cut this link to the selected node.", "icon_cut_color.ico">>)
				-- Call Precursor after current is set up.  Specifically after the interface
				-- item for Current's `interface_name' is added.  (see above)
			Precursor {TOOL}
		end

	set_actions
			-- Add actions to the widgets
		do
			Precursor {TOOL}
			target_system_button.select_actions.extend (agent on_target_system_button_pressed)
			new_node_button.select_actions.extend (agent on_new_node_button_pressed (agent new_node))
			view_descendants_button.select_actions.extend (agent on_view_descendants_button_pressed)
			view_ancestors_button.select_actions.extend (agent on_view_ancestors_button_pressed)
			cut_button.select_actions.extend (agent on_cut_button_pressed)
		end

	set_actions_for_views
			-- Add actions to the views.  This can only be done after the views are
			-- created.  Because `set_actions' is called in the precursor to `initialize'
			-- this feature had to be added in order to access the "views" after they
			-- are created in `initialize' with the calls to `register_view_function'
			-- from `view_manager'.
		do
			tree_view.select_actions.extend (agent set_button_states)
		end

feature -- Access

	target: NODE
			-- The object handled by this tool.

	tree_view: JJ_TREE_VIEW
			-- The VIEW which actually does the displaying of
			-- the nodes in a tree.

feature -- Element change

	set_target (a_target: like target)
			-- Change the `target' of the tool.
			-- Redefined to propegate `a_target' to the `tree_view'.
		do
			Precursor {TOOL} (a_target)
			tree_view.set_target (a_target)
			draw
			set_button_states
		end

feature -- Basic operations

	draw
			-- Builds the string shown at top of the tool in `viewable_label'
			-- using the id of the object.
		local
			s: STRING
			n: NODE
			pw_test: ANY
		do
			Precursor {TOOL}
				-- Reminder:  `target_label' is built in Precursor {TOOL}; it fills in
				-- the `display_name' if the TOOL's target is an EDITALBE, else it uses
				-- the generating type of the target.
				-- So, this redefined version simply addes the "not in system text"
				-- to the display name if necessary.
			s := target_label.tooltip
			pw_test := parent_window.target
			n ?= parent_window.target
			check
				n /= Void
			end
			if n /= Void and then not n.descendants.has (target) then
				s := s + " " + interface_table.short_name ("not in system text")
			end
			target_label.set_tooltip (s)
			set_button_states
		end

	set_button_states
			-- Set the states of the buttons.
		local
			n: NODE
		do
			Precursor {TOOL}
			check
				tree_view_exists: tree_view /= Void
			end
			if tree_view.target = Void then
				new_node_button.disable_sensitive
				cut_button.disable_sensitive
				view_descendants_button.disable_sensitive
				view_ancestors_button.disable_sensitive
			else
				view_descendants_button.enable_sensitive
				view_ancestors_button.enable_sensitive
				n := tree_view.selected_target
				if n.can_adopt then
					new_node_button.enable_sensitive
				else
					new_node_button.disable_sensitive
				end
				if n /= target then
					cut_button.enable_sensitive
				else
					cut_button.disable_sensitive
				end
			end
		end

feature {NONE} -- Implementation (actions)

	on_target_system_button_pressed
			-- React to a press of the `target_system_button' by retargetting
			-- the view to the application's `target' and view descendents mode.
		local
			app: JJ_APPLICATION
			vn: NODE
		do
			app ?= (create {EV_ENVIRONMENT}).application
			check
				app_exists: app /= Void
					-- Because this class is only used by JJJ_APPLICATIONs
			end
			vn ?= app.target
			if vn /= Void then
				set_target (vn)
			end
			if tree_view.selected_item /= Void then
				tree_view.selected_item.disable_select
			end
			set_button_states
		end

	on_new_node_button_pressed (a_function: FUNCTION [NODE])
			-- React to a press of the `new_node_button' by creating a
			-- new node using `a_function' and make the new node a child
			-- under the currently selected node.
		local
			c: ADD_NODE_COMMAND
			ti: EV_TREE_NODE
			new_n, n: NODE
		do
			new_n := a_function.item ([])
			create c
			n := tree_view.selected_target
			c.set_parent_node (n)
			c.set_child_node (new_n)
			command_manager.add_command (c)
				-- restore the selected object after a draw
			ti := tree_view.retrieve_item_recursively_by_data (n, False)
			if ti /= Void then
				ti.enable_select
			end
		end

	new_node: EDITABLE_NODE
			-- Creation feature for a new node, used in `on_new_node_button_pressed'.
		do
			create Result
		ensure
			result_exists: Result /= Void
		end

	on_view_ancestors_button_pressed
			-- React to a press of the `view_ancestors_button' by changing
			-- the `view' to ancestors mode.
		do
			tree_view.set_view_ancestors
		end

	on_view_descendants_button_pressed
			-- React to a press of the `view_descendants_button' by changing
			-- the `view' to descendants mode.
		do
			tree_view.set_view_descendants
		end

	on_cut_button_pressed
			-- React to a press of the `cut_button' by removing the current node
			-- from its parent.  (Does not necessarily delete from the system, but
			-- the node could be deleted if this is its only location in the tree.)
		require
			not_viewing_ancestors: not tree_view.is_viewing_ancestors
			cannot_cut_target_from_its_parent: tree_view.selected_target /= target
		local
			nti: JJ_NODE_ITEM
			nti_parent: JJ_NODE_ITEM
			parent_n: NODE
			n: NODE
			c: CUT_NODE_COMMAND
		do
			n := tree_view.selected_target
			nti := tree_view.selected_item
			nti_parent ?= nti.parent
			if nti_parent = Void then
				parent_n := target
				check
					parent_n.children.has (n)
						-- because otherwise we have the wrong parent
				end
			else
				parent_n := nti_parent.target
			end
			create c
			c.set_parent_node (parent_n)
			c.set_child_node (n)
			command_manager.add_command (c)
				-- Set the selected item to the `target' because we just deleted
				-- the selected item.
			draw_views (target)
		end

feature {NONE} -- Implementation (Buttons)

	target_system_button: EV_TOOL_BAR_BUTTON
			-- To restore the application's `system' as the target of the view.

	new_node_button: EV_TOOL_BAR_BUTTON
			-- To create a new DATABASE_RECORD.

	view_descendants_button: EV_TOOL_BAR_BUTTON
			-- To make the tree show descendants (recursively) of the `target'.

	view_ancestors_button: EV_TOOL_BAR_BUTTON
			-- To make the tree show descendants (recursively) of the `target'.

	cut_button: EV_TOOL_BAR_BUTTON
			-- To cut the link between a parent node and the currently selected node

end

