note
	description: "[
			Objects that represent an EV_DIALOG.
			The original version of this class was generated by EiffelBuild.
		]"
	legal: "See notice at end of class."
	status: "See notice at end of class."
	date: "$Date$"
	revision: "$Revision$"

class
	GB_TABLE_POSITIONER

inherit
	GB_TABLE_POSITIONER_IMP

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

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

	GB_SHARED_PIXMAPS
		export
			{NONE} all
		undefine
			default_create, copy
		end

create
	make_with_editor

feature {NONE} -- Initialization

	user_initialization
			-- called by `initialize'.
			-- Any custom user initialization that
			-- could not be performed in `initialize',
			-- (due to regeneration of implementation class)
			-- can be added here.
		do
			set_icon_pixmap (Icon_build_window @ 1)
			set_title ("EV_TABLE child positioner")
		end

	components: GB_INTERNAL_COMPONENTS
		-- Access to a set of internal components for an EiffelBuild instance.

	make_with_editor (an_editor: GB_EV_TABLE_EDITOR_CONSTRUCTOR; a_components: GB_INTERNAL_COMPONENTS)
			-- Create `Current' and assign `an_editor' to `editor' and `a_components' to `components'.
		require
			a_components_not_void: a_components /= Void
		local
			list_item: EV_LIST_ITEM
			table_content: LINEAR [EV_WIDGET]
		do
			components := a_components
			default_create
			editor := an_editor
			first := editor.first
			selected_item := Void
			drawing_area.pointer_motion_actions.extend (agent track_movement)
			drawing_area.pointer_button_press_actions.extend (agent button_pressed)
			drawing_area.pointer_button_release_actions.extend (agent button_released)
			create world
			create pixmap
			drawing_area.resize_actions.extend (agent update_pixmap_size)
			drawing_area.resize_actions.extend (agent (x, y, w, h: INTEGER_32) do draw_widgets end)
			create projector.make_with_buffer (world, pixmap, drawing_area)

			split_area.enable_item_expand (split_area.first)
			split_area.disable_item_expand (split_area.second)

			create layout_rows_entry.make (editor, rows_parent, rows_string, gb_ev_table_rows, gb_ev_table_rows_tooltip,
				agent set_rows_and_draw (?), agent valid_row_value (?), components)
			create layout_columns_entry.make (editor, columns_parent, columns_string, gb_ev_table_columns, gb_ev_table_columns_tooltip,
				agent set_columns_and_draw (?), agent valid_column_value (?), components)
			layout_rows_entry.set_text (first.rows.out)
			layout_columns_entry.set_text (first.columns.out)

				-- Now create a list item for all children.
			table_content := first.linear_representation
			from
				table_content.start
			until
				table_content.off
			loop
				-- Note that this is slow, as we have to loop through objects
					-- to get a match, while inside this loop.
				list_item := editor.named_list_item_from_widget (table_content.item)
				list_item.set_data (table_content.item)
				list_item.select_actions.extend (agent item_selected (table_content.item))
				list_item.deselect_actions.extend (agent check_unselect)
				list.extend (list_item)
				table_content.forth
			end
			ok_button.select_actions.extend (agent hide)
			show_actions.extend (agent initialize_sizing)
			selected_item_color := red
		ensure
			components_set: components = a_components
		end

	editor: GB_EV_TABLE_EDITOR_CONSTRUCTOR

	first: EV_TABLE

	user_create_interface_objects
			-- Create any auxilliary objects needed for MAIN_WINDOW.
			-- Initialization for these objects must be performed in `user_initialization'.
		do
			-- Create attached types defined in class here, initialize them in `user_initialization'.

		end

feature {GB_EV_TABLE_EDITOR_CONSTRUCTOR} -- Implementation

	update
			-- Update `Current' to reflect a change in another editor.
		do
			selected_item := Void
			update_prompt
			draw_widgets
		end

feature {NONE} -- Implementation


	initialize_sizing
			-- Set up automatic re-sizing when window is re-sized.
			-- Also initialize size of scrollable area for the first time.
		do
			adjust_scrollable_area
			scrollable_area.resize_actions.extend (agent (x, y, w, h: INTEGER_32) do adjust_scrollable_area end)
		end


	adjust_scrollable_area
			-- Set initial size of `drawing_area' relative to `scrollable_area'
		do
			drawing_area.set_minimum_size (scrollable_area.width.max (first.columns * grid_size + diagram_border * 2),
				scrollable_area.height.max (first.rows * grid_size + diagram_border * 2))
		end


	update_pixmap_size (x, y, a_width, a_height: INTEGER)
			-- Resize `pixmap' to `width', `height'.
		do
				-- A pixmap is 1x1 as default,
				-- and you can not set the size to 0x0.
				-- Why is this?
			if a_width >= 1 and a_height >=1 then
				pixmap.set_size (width, height)
			end
		end

	draw_widgets
			-- Draw representation of all widgets and grid if shown.
		local
			relative_pointa, relative_pointb: EV_RELATIVE_POINT
			figure_rectangle: EV_FIGURE_RECTANGLE
			widgets: LINEAR [EV_WIDGET]
			widget: EV_WIDGET
		do
				-- Remove all previous figures from `world'.
			world.wipe_out
				-- We must  draw the grid if necessary.
			draw_grid

			widgets := first.linear_representation
			from
				widgets.start
			until
				widgets.off
			loop
				widget := widgets.item
				if widget /= selected_item then
					create relative_pointa.make_with_position ((first.item_column_position (widget) - 1) * grid_size + diagram_border, (first.item_row_position (widget) - 1) * grid_size + diagram_border)
					create relative_pointb.make_with_position ((first.item_column_position (widget) - 1) * grid_size + (first.item_column_span (widget)) * grid_size + diagram_border, (first.item_row_position (widget) - 1) * grid_size + (first.item_row_span (widget)) * grid_size + diagram_border)
					create figure_rectangle.make_with_points (relative_pointa, relative_pointb)
					figure_rectangle.set_foreground_color (black)
					figure_rectangle.remove_background_color
					world.extend (figure_rectangle)
				end
				widgets.forth
			end
			if draw_greyed_widget then
					create relative_pointa.make_with_position (grey_x * grid_size + diagram_border, grey_y * grid_size + diagram_border)
					create relative_pointb.make_with_position (grey_x * grid_size + grey_x_span * grid_size + diagram_border, grey_y * grid_size + grey_y_span * grid_size + diagram_border)
					create figure_rectangle.make_with_points (relative_pointa, relative_pointb)
					figure_rectangle.remove_background_color
					figure_rectangle.set_foreground_color (grey)
					world.extend (figure_rectangle)
			end
			if selected_item /= Void then
					create relative_pointa.make_with_position ((first.item_column_position (selected_item) - 1) * grid_size + diagram_border, (first.item_row_position (selected_item) - 1) * grid_size + diagram_border)
					create relative_pointb.make_with_position ((first.item_column_position (selected_item) - 1) * grid_size + (first.item_column_span (selected_item)) * grid_size + diagram_border, (first.item_row_position (selected_item) - 1) * grid_size + (first.item_row_span (selected_item)) * grid_size + diagram_border)
					create figure_rectangle.make_with_points (relative_pointa, relative_pointb)
					figure_rectangle.remove_background_color
					figure_rectangle.set_foreground_color (selected_item_color)
					figure_rectangle.set_line_width (highlighted_width)
					world.extend (figure_rectangle)
			end
			projector.project
		end

	draw_grid
			-- Draw snap to grid in `world'.
		local
			counter: INTEGER
			figure_line: EV_FIGURE_LINE
			color: EV_COLOR
			relative_point: EV_RELATIVE_POINT
			rows_size, columns_size: INTEGER
		do
				-- Create a light green for the grid color.
			create color.make_with_8_bit_rgb (196, 244, 204)

				-- compute commonly requested values.
			rows_size := first.rows * grid_size
			columns_size := first.columns * grid_size

			from
				counter := 0
			until
				counter > columns_size
			loop
				create figure_line.make_with_positions (counter + diagram_border, diagram_border, counter + diagram_border, rows_size + diagram_border)
				figure_line.set_foreground_color (color)
				create relative_point.make_with_position (drawing_area.width + diagram_border, counter + diagram_border)
				world.extend (figure_line)
				counter := counter + grid_size
			end
			from
				counter := 0
			until
				counter > rows_size
			loop
				create figure_line.make_with_positions (diagram_border, counter + diagram_border, columns_size + diagram_border, counter + diagram_border)
				figure_line.set_foreground_color (color)
				world.extend (figure_line)
				counter := counter + grid_size
			end
		end

	set_item_position_and_span (v: EV_WIDGET; a_column, a_row, columns, rows: INTEGER)
			-- Move `v' to `a_column', `a_row' and resize to `columns', `rows'.
		do
			editor.set_item_position_and_span (v, a_column, a_row, columns, rows)
		end

	track_movement (a_x_position, a_y_position: INTEGER; x_tilt, y_tilt, pressure: REAL_64; s_x, s_y: INTEGER_32)
			-- Track `x', `y' position of cursor, and position widgets
			-- as necessary.
		local
			new_x, new_y: INTEGER
			column_position, row_position, end_row_position, end_column_position: INTEGER
			new_column, new_row: INTEGER
			end_position, current_x_position, current_y_position: INTEGER
			x, y: INTEGER
			column_pos, row_pos, column_span, row_span: INTEGER
			orig_column_pos, orig_row_pos, orig_column_span, orig_row_span: INTEGER
		do
				-- Transform coordinates to take into account offset of actual diagram.
			x := a_x_position - diagram_border
			y := a_y_position - diagram_border

			if selected_item /= Void and not resizing_widget and not moving_widget then
				column_position := (first.item_column_position (selected_item) - 1) * grid_size
				row_position := (first.item_row_position (selected_item) - 1) * grid_size
				end_column_position := column_position + first.item_column_span (selected_item) * grid_size
				end_row_position := row_position + first.item_row_span (selected_item) * grid_size

				if close_to (x, y, end_column_position, end_row_position) or
					close_to (x, y, column_position, row_position) then
					if not resizing_widget then
						set_all_pointer_styles (sizenwse_cursor)
					end
				elseif close_to (x, y, column_position, end_row_position) or
					close_to (x, y, end_column_position, row_position) then
					if not resizing_widget then
						set_all_pointer_styles (sizenesw_cursor)
					end
				elseif close_to_line (x, y, end_row_position, column_position + accuracy_value, end_column_position - accuracy_value) or
					close_to_line (x, y, row_position, column_position + accuracy_value, end_column_position - accuracy_value) then
					if not resizing_widget then
						set_all_pointer_styles (sizens_cursor)
					end
				elseif close_to_line (y, x, column_position, row_position + accuracy_value, end_row_position - accuracy_value) or
					close_to_line (y, x, end_column_position, row_position + accuracy_value, end_row_position - accuracy_value) then
					if not resizing_widget then
						set_all_pointer_styles (sizewe_cursor)
					end
				elseif x > column_position and x < end_column_position and y > row_position and y < end_row_position then
					if not resizing_widget then
						set_all_pointer_styles (sizeall_cursor)
					end
				else
					if not resizing_widget or not moving_widget then
						set_all_pointer_styles (standard_cursor)
					end
				end
			end

			if resizing_widget then

					-- Store original values so that we only need to set
					-- any values that changed during the resizing. These
					-- four values will be changed during the resizing as necessary,
					-- so that afterwards, we can use these to position the widget.
				column_pos := first.item_column_position (selected_item)
				row_pos := first.item_row_position (selected_item)
				column_span := first.item_column_span (selected_item)
				row_span := first.item_row_span (selected_item)

					-- Store the original values for comparing with the values above.
					-- if one or more have changed, then we can reposition the
					-- selected item.
				orig_column_pos := column_pos
				orig_row_pos := row_pos
				orig_column_span := column_span
				orig_row_span := row_span


				if x_scale /= 0 then
					if x_offset = 0 then
						end_position := (original_column + original_column_span)
						new_x := x + half_grid_size - ((x + half_grid_size) \\ grid_size)
						current_x_position := (((new_x // grid_size) + 1).max (1)).min (end_position - 1)
						if not first.area_clear_excluding_widget (selected_item, current_x_position, first.item_row_position (selected_item), end_position - current_x_position, first.item_row_span (selected_item)) then
							current_x_position := first_filled_horizontal_space (selected_item, end_position - 1, first.item_row_position (selected_item), first.item_row_span (selected_item))
						end
						column_pos := current_x_position
						column_span := end_position - current_x_position
					else
						x := x - column_position
						new_x := x + half_grid_size - ((x + half_grid_size) \\ grid_size)
						new_column := ((new_x // grid_size) - first.item_column_position (selected_item) + 1).min (first.columns - first.item_column_position (selected_item) + 1).max (1)
						if first.item_column_span (selected_item)/= new_column and first.area_clear_excluding_widget (selected_item, first.item_column_position (selected_item), first.item_row_position (selected_item), new_column, first.item_row_span (selected_item)) then --new_column.max (1).min (first.columns - first.item_column_position (selected_item) + 1), first.item_row_span (selected_item)) then
							column_span := new_column
						end
					end
				end

				if y_scale /= 0 then
					if y_offset = 0 then
						end_position := (original_row + original_row_span)
						new_y := y + half_grid_size - ((y + half_grid_size) \\ grid_size)
						current_y_position := (((new_y // grid_size) + 1).max (1)).min (end_position - 1)
						if not first.area_clear_excluding_widget (selected_item, first.item_column_position (selected_item), current_y_position, first.item_column_span (selected_item), end_position - current_y_position) then
							current_y_position := first_filled_vertical_space (selected_item, end_position - 1, first.item_column_position (selected_item), first.item_column_span (selected_item))
						end
						row_pos := current_y_position
						row_span := end_position - current_y_position
					else
						y := y - row_position
						new_y := y + half_grid_size - ((y + half_grid_size) \\ grid_size)
						new_row := ((new_y // grid_size) - first.item_row_position (selected_item) + 1).min (first.rows - first.item_row_position (selected_item) + 1).max (1)
						if first.item_row_span (selected_item) /= new_row and first.area_clear_excluding_widget (selected_item, first.item_column_position (selected_item), first.item_row_position (selected_item), first.item_column_span (selected_item), new_row) then
							row_span := new_row
						end
					end
				end
					-- Now actually perform the placing of the widget.

				if orig_column_pos /= column_pos or orig_row_pos /= row_pos or orig_row_span /= row_span
					or orig_column_span /= column_span then
						-- We only position and redraw if the size or position has really changed.
					set_item_position_and_span (selected_item, column_pos, row_pos, column_span, row_span)
					draw_widgets
				end
			end
			if moving_widget then
				new_x := x - ((x - x_offset) \\ grid_size)
				new_y := y - ((y - y_offset) \\ grid_size)
				x := ((new_x - x_offset) // grid_size + 1).min (first.columns - first.item_column_span (selected_item) + 1).max (1)
				y := ((new_y - y_offset) // grid_size + 1).min (first.rows - first.item_row_span (selected_item) + 1).max (1)
				if (first.item_column_position (selected_item) /= x or first.item_row_position (selected_item) /= y) then
					if
						first.area_clear_excluding_widget (selected_item, x, y, first.item_column_span (selected_item), first.item_row_span (selected_item)) then
						set_item_position_and_span (selected_item, x, y, first.item_column_span (selected_item), first.item_row_span (selected_item))
						draw_greyed_widget := False
					else
						draw_greyed_widget := True
						grey_x := x - 1
						grey_y := y - 1
						grey_x_span := first.item_column_span (selected_item)
						grey_y_span := first.item_row_span (selected_item)
					end
				end
				draw_widgets
			end
			update_editors
		end

	first_filled_horizontal_space (widget: EV_WIDGET; a_column, a_row, a_row_span: INTEGER): INTEGER
			-- `Result' is lowest column value, counting down from `a_column' which has the rows
			-- `a_row' to `a_row' + `a_row_span' free from items.
		local
			row_counter, column_counter: INTEGER
		do
			from
				column_counter := a_column
			until
				column_counter = 0 or Result /= 0
			loop
				from
					row_counter := a_row
				until
					row_counter = a_row + a_row_span or Result /= 0
				loop
					if first.item_at_position (column_counter, row_counter) /= Void and first.item_at_position (column_counter, row_counter) /= widget then
						Result := column_counter + 1
					end
					row_counter := row_counter + 1
				end
				column_counter := column_counter - 1
			end
		end

	first_filled_vertical_space (widget: EV_WIDGET; a_row, a_column, a_column_span: INTEGER): INTEGER
			-- `Result' is lowest row value, counting down from `a_row' which has the columns
			-- `a_column' to `a_column' + `a_column_span' free from items.
		local
			row_counter, column_counter: INTEGER
		do
			from
				row_counter := a_row
			until
				row_counter = 0 or Result /= 0
			loop
				from
					column_counter := a_column
				until
					column_counter = a_column + a_column_span or Result /= 0
				loop
					if first.item_at_position (column_counter, row_counter) /= Void and first.item_at_position (column_counter, row_counter) /= widget then
						Result := row_counter + 1
					end
					column_counter := column_counter + 1
				end
				row_counter := row_counter - 1
			end
		end

	close_to (current_x, current_y, desired_x, desired_y: INTEGER): BOOLEAN
			-- Is position `current_x', `current_y' within `accuracy_value' of `desired_x', `desired_y'.
		do
			if (current_x - desired_x).abs < accuracy_value and (current_y - desired_y).abs < accuracy_value then
				Result := True
			end
		end

	close_to_line (coordinate_a, coordinate_b, line_offset, line_start, line_end: INTEGER): BOOLEAN
		do
			if coordinate_a > line_start and coordinate_a < line_end and (coordinate_b - line_offset).abs < accuracy_value then
				Result := True
			end
		end

	half_grid_size: INTEGER
			-- Half size of current grid.
		do
			Result := grid_size // 2
		end

	button_pressed (a_x_position, a_y_position, a_button: INTEGER; x_tilt, y_tilt, pressure: REAL_64; s_x, s_y: INTEGER_32)
			-- A button has been pressed. If `a_button' = 1 then
			-- check for movement/resizing.
		local
			column_position, row_position, column_span, row_span,
			end_column_position, end_row_position: INTEGER
			x, y: INTEGER
		do
				-- We need to make `selected_item' Void and redraw it
				-- as black in all other editors referencing `Current'.
			update_editors
				-- Transform coordinates to take into account offset of actual diagram.
			x := a_x_position - diagram_border
			y := a_y_position - diagram_border
			if selected_item /= Void then
					-- We must store the original size and position of `selected_item'.
					-- This is necessary, as in `track_movement', we may move and re-size
					-- `selected_item', although still need to perform the calculations on
					-- the current cursor position against the position of `selected_item'
					-- when the resizing began.
				original_column := first.item_column_position (selected_item)
				original_row := first.item_row_position (selected_item)
				original_column_span := first.item_column_span (selected_item)
				original_row_span := first.item_row_span (selected_item)


					-- Now perform some calculations just once ready for later.
				column_position := (first.item_column_position (selected_item) - 1) * grid_size
				row_position := (first.item_row_position (selected_item) - 1) * grid_size
				end_column_position := column_position + first.item_column_span (selected_item) * grid_size
				end_row_position := row_position + first.item_row_span (selected_item) * grid_size
				row_span := first.item_row_span (selected_item) * grid_size
				column_span := first.item_column_span (selected_item) * grid_size

				if a_button = 1 and not resizing_widget and not moving_widget then
						-- Unset this, if this is not the case, as we have 8 checks which would need it
						-- assigning otherwise
					resizing_widget := True
					if close_to (x, y, end_column_position, end_row_position) then
						x_offset := column_span
						y_offset := row_span
						x_scale := 1; y_scale := 1
					elseif close_to (x, y, column_position, row_position) then
						x_offset := 0
						y_offset := 0
						x_scale := 1; y_scale := 1
					elseif close_to (x, y, column_position, end_row_position) then
						x_offset := 0
						y_offset := row_span
						x_scale := 1; y_scale := 1
					elseif close_to (x, y, end_column_position, row_position) then
						x_offset := column_span
						y_offset := 0
						x_scale := 1; y_scale := 1
					elseif close_to_line (x, y, end_row_position, column_position + accuracy_value, end_column_position - accuracy_value) then
						x_offset := x - column_position
						y_offset := row_span
						x_scale := 0; y_scale := 1
					elseif close_to_line (x, y, row_position, column_position + accuracy_value, end_column_position - accuracy_value) then
						x_offset := x
						y_offset := 0
						x_scale := 0; y_scale := 1
					elseif close_to_line (y, x, column_position, row_position + accuracy_value, end_row_position - accuracy_value) then
						x_offset := 0
						y_offset := y
						x_scale := 1; y_scale := 0
					elseif close_to_line (y, x, end_column_position, row_position + accuracy_value, end_row_position - accuracy_value) then
						x_offset := column_span
						y_offset := y
						x_scale := 1; y_scale := 0
					elseif x > column_position and x < end_column_position and y > row_position and y < end_row_position then
						moving_widget := True
						resizing_widget := False
						x_offset := x - column_position
						y_offset := y - row_position
					else
						resizing_widget := False
					end
					if resizing_widget or moving_widget then
						drawing_area.enable_capture
					end
				end

			end
				-- We need to highlight a widget if the action is
				-- to select a widget.
			if a_button = 1 and not resizing_widget and not moving_widget then
				x := x // grid_size + 1
				y := y // grid_size + 1
					-- Only perform the query if valid coordinates.
				if x <= first.columns and y <= first.rows then
					selected_item := first.item_at_position (x, y)
					if selected_item /= Void then
						list.retrieve_item_by_data (selected_item, True).enable_select
					end
					update_prompt
				end
				draw_widgets
			end
		end

	button_released (x, y, a_button: INTEGER; x_tilt, y_tilt, pressure: REAL_64; s_x, s_y: INTEGER_32)
			-- A button has been released on `drawing_area'
			-- If `a_button' = 1, check for end of resize/movement.
		do
			draw_greyed_widget := False
			if a_button = 1 then
				if resizing_widget then
					resizing_widget := False
					set_all_pointer_styles (standard_cursor)
					drawing_area.disable_capture
				elseif moving_widget then
					moving_widget := False
					set_all_pointer_styles (standard_cursor)
					drawing_area.disable_capture
				end
			draw_widgets
			end
		end

	update_editors
			-- Update all editors referencing `object'.
		do
			editor.update_editors
		end

	set_all_pointer_styles (cursor: EV_POINTER_STYLE)
			-- Assign a pointer style to all figures in
			-- `world' and `drawing_area'.
		do
			from
				world.start
			until
				world.off
			loop
				world.item.set_pointer_style (cursor)
				world.forth
			end
			drawing_area.set_pointer_style (cursor)
		end

	set_rows (row_value: INTEGER)
			-- Resize table to accommodate `row_value' rows.
		do
			editor.set_rows (row_value)
			update_editors
		end

	set_columns (column_value: INTEGER)
			-- Resize table to accommodate `column_value' columns.
		do
			editor.set_columns (column_value)
			update_editors
		end

	set_rows_and_draw (row_value: INTEGER)
			-- Resize table to accommodate `row_value' rows.
		do
			editor.set_rows (row_value)
			drawing_area.set_minimum_height (grid_size * row_value + diagram_border * 2)
			layout_rows_entry.set_text (row_value.out)
			update_editors
			draw_widgets
			update_prompt
		end

	set_columns_and_draw (column_value: INTEGER)
			-- Resize table to accommodate `column_value' columns.
		do
			editor.set_columns (column_value)
			drawing_area.set_minimum_width (grid_size * column_value +  diagram_border * 2)
			layout_columns_entry.set_text (column_value.out)
			update_editors
			draw_widgets
			update_prompt
		end

	valid_row_value (new_value: INTEGER): BOOLEAN
			-- Is `new_value' a valid row size for table.
		do
			Result := first.rows_resizable_to (new_value)
		end

	valid_column_value (new_value: INTEGER): BOOLEAN
			-- Is `new_value' a valid column size for table.
		do
			Result := first.columns_resizable_to (new_value)
		end

	valid_spacing (new_value: INTEGER): BOOLEAN
			-- Is `new_value' a valid spacing value?
		do
			Result := new_value > 0
		end

	item_selected (widget: EV_WIDGET)
			-- Item representing `widget' in `list' has
			-- become selected, so update_display to
			-- reflect this.
		do
			selected_item := widget
			draw_widgets
		end

	check_unselect
			-- If no item is selected in `list' any more,
			-- then we must remove the highlighting from
			-- the display.
		do
			if list.selected_items.count = 0 then
				selected_item := Void
				draw_widgets
			end
		end

	table_minimal_full: BOOLEAN
			-- Is table represented by `Current',
			-- 1x1 and full?
		do
			Result := first.count = 1 and first.rows = 1 and first.columns = 1
		end

	update_prompt
			-- Update `prompt_label'.
		do
			if table_minimal_full then
				prompt_label.set_text (full_prompt)
			elseif selected_item /= Void then
				prompt_label.set_text (position_prompt)
			else
				prompt_label.set_text (select_prompt)
			end
		end

feature {NONE} -- Attributes

	resizing_widget: BOOLEAN
		-- Is a widget currently being resized?

	moving_widget: BOOLEAN
		-- Is a widget currently being moved?

	x_offset, y_offset: INTEGER
		-- Offsets used to hold cursor distance from
		-- point being targeted.

	x_scale, y_scale: INTEGER
		-- Amount to scale movement in the X or Y axis by.
		-- Should be 1 or 0. 1 means full movement, 0 means
		-- that axis is ignored.

	accuracy_value: INTEGER = 3
			-- Value which determines how close pointer must be
			-- to lines/points for resizing.

	projector: EV_DRAWING_AREA_PROJECTOR
		-- Projector used for `world'

	pixmap: EV_PIXMAP
		-- Pixmap for double buffering `world'.

	world: EV_FIGURE_WORLD
		-- Figure world containg all widget representations.

	grid_size: INTEGER = 20
		-- Size of grid representing the table.

	highlighted_width: INTEGER = 3
		-- Width of line used to draw highlighted item.

	selected_item: EV_WIDGET
		-- Item that is currently selected for movement.

	selected_item_color: EV_COLOR
		-- Color used to draw `selected_item'.

	diagram_border: INTEGER = 25
		-- Size of border around table representation in diagram.

	draw_greyed_widget: BOOLEAN
		-- Should a greyed representation of the desired widget position/
		-- size be drawn

	grey_x, grey_y, grey_x_span, grey_y_span: INTEGER
		-- Table coordinates for `draw_greyed_widget'.

	original_column, original_row, original_column_span, original_row_span: INTEGER
		-- Temporary variables used to keep original position of `selected_item'
		-- when button was pressed. These values are used in `track_movement' to
		-- calculate new size/position of `selected_item', based on the current mouse
		-- position.

	select_prompt: STRING = "Please select desired widget."
		-- Prompt to help user.

	full_prompt: STRING = "Child fills table. Resize table to manipulate."
		-- Prompt when table is full.

	position_prompt: STRING = "Position highlighted widget."
		-- Prompt when widget is selected.

	rows_string: STRING = "Rows"

	columns_string: STRING = "Columns"

	layout_rows_entry, layout_columns_entry: GB_INTEGER_INPUT_FIELD;

note
	copyright:	"Copyright (c) 1984-2018, Eiffel Software"
	license:	"GPL version 2 (see http://www.eiffel.com/licensing/gpl.txt)"
	licensing_options:	"http://www.eiffel.com/licensing"
	copying: "[
			This file is part of Eiffel Software's Eiffel Development Environment.
			
			Eiffel Software's Eiffel Development Environment is free
			software; you can redistribute it and/or modify it under
			the terms of the GNU General Public License as published
			by the Free Software Foundation, version 2 of the License
			(available at the URL listed under "license" above).
			
			Eiffel Software's Eiffel Development Environment is
			distributed in the hope that it will be useful,	but
			WITHOUT ANY WARRANTY; without even the implied warranty
			of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
			See the	GNU General Public License for more details.
			
			You should have received a copy of the GNU General Public
			License along with Eiffel Software's Eiffel Development
			Environment; if not, write to the Free Software Foundation,
			Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
		]"
	source: "[
			 Eiffel Software
			 356 Storke Road, Goleta, CA 93117 USA
			 Telephone 805-685-1006, Fax 805-685-6869
			 Website http://www.eiffel.com
			 Customer support http://support.eiffel.com
		]"

end