note
	description: "[
		A {VIEW} for displaying an {EDITABLE} using it's `schema'
		]"
	date: "30 Mar 04"
	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/views/dialog_editor_view.e $"
	date:		"$Date: 2012-05-31 14:05:35 -0400 (Thu, 31 May 2012) $"
	revision:	"$Revision: 10 $"

class
	DIALOG_EDITOR_VIEW

inherit

	EV_STOCK_COLORS
		rename
			implementation as colors_implementation
		export
			{NONE} all
		undefine
			default_create,
			is_equal,
			copy
		end

	VIEW
		rename
			target_imp as record_imp,
			target as record,
			set_target as set_record
		undefine
--			default_create,
			copy,
			is_equal
		redefine
			create_interface_objects,
			initialize,
			record_imp,
			set_record,
			draw
		end

--	EV_CELL
	EV_FRAME
		undefine
			is_in_default_state
		redefine
			create_interface_objects,
			initialize
--			data,		-- to make it inaplicable
--			set_data	-- to make it inaplicable
		end

create
	default_create

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 changed_controls.make
			create controls.make
			create save_actions
			create control_select_actions
			create scrollable_area
			create time_drawn.from_seconds (0)
		end

	initialize
			-- Create an editor view.
		do
			Precursor {EV_FRAME}
			Precursor {VIEW}
			extend (scrollable_area)
			set_save_on_change
			set_actions
		end

	set_actions
			-- Add actions to the widgets
		do
			scrollable_area.item.drop_actions.extend (agent on_drop_editable)
		end

feature -- Access

	scrollable_area: EDITOR_SCROLL_AREA

	schema: SCHEMA
			-- Current schema in use by the editor.
		require
			has_schema: has_schema
		do
			check attached schema_imp as s then
				Result := s
			end
		end

	save_actions: EV_NOTIFY_ACTION_SEQUENCE
			-- Actions to be performed after the record is saved.

	control_select_actions: EV_NOTIFY_ACTION_SEQUENCE
			-- Actions to be performed when a control is clicked.

feature -- Element change

	set_record (a_record: like record)
			-- Change `record' to `a_record'
			-- Reload the data into the controls
		do
			Precursor {VIEW} (a_record)
			draw
		end

	set_schema (a_schema: like schema)
			-- Change `schema' to `a_schema'.
			-- Uses the pattern described in feature `set_target' from VIEW to
			-- add `a_schema' to the `object_set' (the set of objects contained
			-- in this view) and removes the old schema (if it had one) from
			-- the `object_set'.
			-- Also, removes old/add new fields contained in `a_schema'.
		do
				-- Save the old `record'
			if attached schema_imp as s and then s /= a_schema then
--				target_set.prune (s)
				schema_imp := a_schema
--				target_set.extend (s)
				draw
			end
		ensure
			schema_assigned: schema = a_schema
--			contains_schema: target_set.has (a_schema)
--			old_schema_removed: (old schema /= Void) and (old schema /= schema) implies not target_set.has (old schema)
		end

feature -- Basic operations

	draw
			-- Rebuild and show the view.
		do
			if has_schema then
				if is_rebuild_needed then
					build_controls
				end
				if record /= Void then
					fill_controls
					if attached schema as s and then record.has_schema (s) then
						enable_controls
					else
						disable_controls
					end
				else
					disable_controls
				end
			end
		end

	disable
			-- Make the controls unresponsive to input.
		do
			is_user_disabled := True
		end

	enable
			-- Make the controls responsive to input.
		do
			is_user_disabled := False
		end

feature -- Status report

	is_user_disabled: BOOLEAN
			-- Has the user requested the controls to be disabled?

	is_save_on_change: BOOLEAN
			-- Are changes made in the controls automatically
			-- saved to `record'?  In other words, is `record'
			-- updated anytime a change is made, or must it
			-- be done manually with a call to `save_record'?

	has_schema: BOOLEAN
			-- Is a `schema' assigned to Current?
		do
			Result := attached schema_imp
		end

feature -- Status setting

	set_save_on_change
			-- Make automatic updates to `record' whenever
			-- a change is made in any control.
		do
			is_save_on_change := True
		end

	set_save_on_request
			-- Require `save_record' to be called in order to
			-- accept any changes make in any control.
		do
			is_save_on_change := False
		end

feature -- Basic operations

	disable_controls
			-- Disable all controls.
		local
			c: CONTROL
		do
			from controls.start
			until controls.exhausted
			loop
				c := controls.item
				c.disable_sensitive
				check attached c.parent as p then
					p.set_foreground_color (Red)
					p.propagate_foreground_color
				end
				controls.forth
			end
		end

	enable_controls
			-- Enable all controls.
		local
			c: CONTROL
		do
			from controls.start
			until controls.exhausted
			loop
				c := controls.item
				c.enable_sensitive
				check attached c.parent as p then
					p.set_foreground_color (Black)
					p.propagate_foreground_color
				end
				controls.forth
			end
		end

feature {NONE} -- Implementation

	build_controls
			-- Create controls for each FIELD in `schema'.
		require
			schema_exists: schema /= Void
		local
			f: FIELD
			c: CONTROL
		do
			check attached {EDITOR_FIXED} scrollable_area.item as ef then
					-- Because `scrollable_area' is an {EDITOR_SCROLL_AREA}
					-- which *should* hold an {EDITOR_FIXED}.
				ef.wipe_out
				controls.wipe_out
				if attached schema as s then
					from s.start
					until s.exhausted
					loop
						f := s.field
						c := f.as_widget
							-- add actions to each control as it is created
						c.valid_change_actions.extend (agent on_control_changed (c))
						c.select_actions.extend (agent on_control_selected (c))
		--				c.display.pointer_button_press_actions.force_extend (agent on_control_selected (c))
		--				c.label.pointer_button_press_actions.force_extend (agent on_control_selected (c))
							-- put the control into the fixed
						ef.extend (c)
							-- place the control in the correct spot
						scrollable_area.position_control (c)
							-- keep track of the control
						controls.extend (c)
						if is_user_disabled then
							disable_controls
						end
						s.forth
					end
					if not is_user_disabled then
						enable_controls
					end
				end
			end
			check attached schema as s then
				time_drawn := s.time_modified.twin
			end
		end

	save_record
			-- Get the data from each control and put it into the
			-- the record if the data is valid.
		require
			record_exitsts: record /= Void
		local
			dat: ANY	-- for testing
			con: CONTROL	-- control
			c: EDIT_COMMAND
		do
			from changed_controls.start
			until changed_controls.off
			loop
				con := changed_controls.item
				if con.is_display_valid and then not con.field.is_calculated then
					dat := con.value
					c := new_edit_command (record, con.field, con.value)
						-- Disable drawing to keep this control from being updated
						-- when the EDIT_COMMAND is executed.
					disable_drawing
					command_manager.add_command (c)
					enable_drawing
				end
				changed_controls.forth
			end
			save_actions.call ([])
			changed_controls.wipe_out
		end

	new_edit_command (a_record: like record; a_field: FIELD; a_value: ANY): EDIT_COMMAND
			-- Used by `save_record' to get an EDIT_COMMAND
		require
			record_exists: record /= Void
		do
			create Result.make (a_record, a_field, a_value)
		end

	fill_controls
			-- Put the data from the record into the corresponding control
		require
			record_exists: record /= Void
		local
			key: STRING
			con: CONTROL
		do
			from
				controls.start
			until
				controls.exhausted
			loop
				key := controls.item.field.label
				con := controls.item
				if attached record.value (key) as dat then
					con.set_data (dat)
				end
				con.refresh
				controls.forth
			end
		end

feature {CONTROL} -- implementation

	on_drop_editable (a_editable: EDITABLE)
			-- React to drop of `a_editable' on Current except if
			-- it is a FIELD.  (FIELDs are handled by FIELD_EDITOR_VIEW.)
-- Fix me !!!  This makes the interface inconsistent by allowing a drop
--				of a type that is really not allowed.
		require
			editable_exists: a_editable /= Void
		do
				-- The `parent_tool' (a EDIT_TOOL) takes care of the special
				-- case, when `a_editable' is a FIELD.
			if attached parent_tool as pt then
				pt.set_target (a_editable)
			end
		end

	on_control_changed (a_control: CONTROL)
			-- A change has been made to value in `a_control'
		require
			control_exists: a_control /= Void
		do
			changed_controls.extend (a_control)
			if is_save_on_change then
				save_record
				disable_drawing
				draw_views (record)
				enable_drawing
			end
		end

	on_control_selected (a_control: CONTROL)
			-- React to `a_control' being selected.
		require
			control_exists: a_control /= Void
		do
			control_select_actions.call ([a_control])
		end

feature {NONE} -- Implementation

	controls: LINKED_SET [CONTROL]
			-- All the controls in the pages.

	changed_controls: LINKED_SET [CONTROL]
			-- Controls whose data has changed since last save

	is_rebuild_needed: BOOLEAN
			-- Used internally to let `draw' know that the controls
			-- need to be rebuilt, because the schema has changed
			-- since the last call to `draw'.  This prevents calling
			-- `build_controls' (and unnecessarily recreating the
			-- controls again) on every call to `draw'.
		require
			schema_exists: schema /= Void
		do
			check attached schema as s then
				Result := time_drawn < s.time_modified
			end
		end

	time_drawn: YMDHMS_TIME
			-- The time the controls were last drawn.
			-- This is used to allow the controls for a schema to be
			-- redrawn only after the `schema' has changed, not every
			-- time a new `record' is set.
			-- Updated by `build_controls'.

	record_imp: detachable EDITABLE
			-- Detachable implementation of `target' for void-safety

	schema_imp: detachable like schema
			-- Detachable implementation of `schema'

feature {NONE} -- Inaplicable

--	data: ANY
--			-- Not to be used
--			
--	set_data (a_data: like data) is
--			-- Not to be used
--		do
--			check
--				False
--			end
--		end

end
