note
	description: "[
				Objects used by {JJ_APPLICATION} to allow commands to be
				undone and redone.
				]"
	date: "2 Oct 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/commands/command_manager.e $"
	date:		"$Date: 2012-07-01 01:30:44 -0400 (Sun, 01 Jul 2012) $"
	revision:	"$Revision: 12 $"

class
	COMMAND_MANAGER

inherit

	SHARED
		export
			{NONE} all
		undefine
			default_create,
			copy,
			is_equal
		end

	LINKED_LIST [JJ_COMMAND]
		export
			{LINKED_LIST}
				all
--			{NONE}
--				all
--			{LINKED_LIST}
--				start,
--				forth,
--				first_element,
--				last_element,
--				count,
--				object_comparison,
--				cursor,
--				go_to,
--				index
			{ANY}
				wipe_out,
				prunable,
--				item,
				is_empty,
--				readable,
--				off,
				has,
				is_equal
--				standard_is_equal,
--				copy,
--				same_type
		redefine
			default_create,
			wipe_out
		end

create
	default_create, make

feature {NONE} -- Initialization

	default_create
			-- Initialize `Current'.
		do
			make
		end

feature -- Access

	marked_index: INTEGER
			-- Mark the command at current `last_executed_index'

	last_executed_index: INTEGER
			-- Index of last executed (and next undoable) command.

	command: JJ_COMMAND
			-- Last inserted command.
		require
			not_empty: not is_empty
		do
			Result := i_th (last_executed_index)
		end

feature -- Element change

	add_command (a_command: JJ_COMMAND)
			-- Remove any commands which have been undone (they will not be
			-- executable after `a_command' is added), then add `a command'
			-- to the list and execute it.
		require
			not_has_command: not has (a_command)
		do
			from go_i_th (last_executed_index + 1)
			until after or else is_empty
			loop
				remove
			end
			extend (a_command)
			execute
			check
				last_executed_index = index_of (a_command, 1)
			end
		ensure
			command_added: has (a_command)
			command_executed: last_executed_index = count
		end

	set_mark
			-- Save a reference to the currently undoable command.
			-- Useful for marking the command state at which a
			-- system was saved.
		do
			marked_index := last_executed_index
		end

feature -- Status report

	is_undoable: BOOLEAN
			-- Can a command be undone?
		do
			Result := last_executed_index > 0
		end

	is_executable: BOOLEAN
			-- Is there a command which can be executed?
			-- That is, was one previousely undone or added?
		do
			Result := last_executed_index + 1 <= count
		end

	is_at_marked_state: BOOLEAN
			-- Is the cursor at item which was marked_index.
			-- Useful for marking and checking if / when a system was saved.
		do
			Result := last_executed_index = marked_index
		end

feature -- Basic operations

	wipe_out
			-- Remove all commands from Current, erasing history.
		do
			Precursor
			last_executed_index := 0
			marked_index := 0
		end

	execute
			-- Execute the command at `last_executed_index'.
		require
			can_execute_a_command: is_executable
		local
			v: VIEW
			c: JJ_COMMAND
		do
			last_executed_index := last_executed_index + 1
			c := i_th (last_executed_index)
			c.execute
--			Persistence_manager.extend_objects (c.affected_objects)
				-- Get a view so the views with the objects changed
				-- by executing the command can be updated.
			v := main_windows.first
--			v.notify_views_with_set (c.affected_objects)
			v.draw_views_with_set (c.affected_objects)
				-- Call `set_widget_states' to update the undo, redo, and save, etc. buttons.
			main_windows.do_all (agent {JJ_MAIN_WINDOW}.set_widget_states)
		ensure
			last_executed_index_incremented: last_executed_index = old last_executed_index + 1
		end

	undo
			-- Reverse execute the last command.
		require
			can_undo_a_command: is_undoable
		local
			v: VIEW
			c: JJ_COMMAND
		do
				-- Get the command at the current index and undo it.
			c := i_th (last_executed_index)
			c.undo
			last_executed_index := last_executed_index - 1
--			persistence_manager.extend_objects (c.affected_objects)
				-- Need to get a view so the views with the objects changed
				-- by undoing the command can be updated.
			v := main_windows.first
--			v.notify_views_with_set (c.affected_objects)
			v.draw_views_with_set (c.affected_objects)
				-- Call `set_widget_states' to update the undo, redo, and save, etc. buttons.
			main_windows.do_all (agent {JJ_MAIN_WINDOW}.set_widget_states)
		ensure
			last_executed_index_decremented: last_executed_index = old last_executed_index - 1
		end

feature {NONE} -- Implementation (Handles to "global" application objects)

--	Persistence_manager: PERSISTENCE_MANAGER is
--			-- Handle (for convinience) to the JJ_APPLICATION's `persistence_manager'.
--		local
--			app: JJ_APPLICATION
--		once
--			app ?= (create {EV_ENVIRONMENT}).application
--			check
--				app /= Void
--					-- Because this class if for use by a JJ_APPLICATION
--			end
--			Result := app.persistence_manager
--		ensure
--			result_exists: Result /= Void
--		end

end

