270 lines
8.6 KiB
Plaintext
270 lines
8.6 KiB
Plaintext
|
note
|
||
|
description: "[
|
||
|
Objects that represent a scrollable area in which the contents are always aligned with the top left while
|
||
|
smaller than client area.
|
||
|
|
||
|
When using this control, you must be careful of the following things:
|
||
|
|
||
|
An action sequence is connected to the idle_actions of the application from time to time. As it is removed,
|
||
|
it is the final agent contained, so if you must add to the idle actions, you should not add at the last position.
|
||
|
|
||
|
An agent is connected to the `resize_actions' of the widget inserted. If you clear this action sequence, `Current'
|
||
|
will not update as the widget size changes. Removing the widget via `remove_item' removes the final agent from
|
||
|
`resize_actions'.
|
||
|
|
||
|
None of the inherited features for addition and removal of widget does not work correctly. Use `add_item'
|
||
|
and `remove_item' only.
|
||
|
]"
|
||
|
author: "Julian Rogers"
|
||
|
date: "$Date: 2012-03-16 14:05:07 -0400 (Fri, 16 Mar 2012) $"
|
||
|
revision: "$Revision: 7 $"
|
||
|
|
||
|
class
|
||
|
LEFT_ALIGNED_SCROLLABLE_AREA
|
||
|
|
||
|
inherit
|
||
|
EV_VERTICAL_BOX
|
||
|
redefine
|
||
|
initialize,
|
||
|
is_in_default_state
|
||
|
end
|
||
|
|
||
|
feature {NONE} -- Creation
|
||
|
|
||
|
initialize
|
||
|
-- Initialize `Current'.
|
||
|
local
|
||
|
h_box: EV_HORIZONTAL_BOX
|
||
|
do
|
||
|
create cell
|
||
|
create viewport
|
||
|
create vertical_scroll_bar
|
||
|
vertical_scroll_bar.change_actions.extend (agent scroll_vertically)
|
||
|
create horizontal_scroll_bar
|
||
|
horizontal_scroll_bar.change_actions.extend (agent scroll_horizontally)
|
||
|
horizontal_scroll_bar.hide
|
||
|
vertical_scroll_bar.hide
|
||
|
create horizontal_box
|
||
|
extend (horizontal_box)
|
||
|
create main_fixed
|
||
|
viewport.extend (main_fixed)
|
||
|
create h_box
|
||
|
extend (h_box)
|
||
|
h_box.extend (horizontal_scroll_bar)
|
||
|
cell.set_minimum_size (vertical_scroll_bar.minimum_width, horizontal_scroll_bar.minimum_height)
|
||
|
h_box.extend (cell)
|
||
|
h_box.disable_item_expand (cell)
|
||
|
cell.hide
|
||
|
|
||
|
disable_item_expand (h_box)
|
||
|
horizontal_box.extend (viewport)
|
||
|
horizontal_box.extend (vertical_scroll_bar)
|
||
|
horizontal_box.disable_item_expand (vertical_scroll_bar)
|
||
|
|
||
|
resize_actions.extend (agent resized)
|
||
|
|
||
|
is_initialized := True
|
||
|
end
|
||
|
|
||
|
|
||
|
feature -- Access
|
||
|
|
||
|
add_item (an_item: EV_WIDGET)
|
||
|
-- Add `an_item' to `Current'.
|
||
|
require
|
||
|
an_item_not_void: an_item /= Void
|
||
|
do
|
||
|
main_fixed.extend (an_item)
|
||
|
main_fixed.set_item_position (an_item, 0, 0)
|
||
|
the_item := an_item
|
||
|
the_item.resize_actions.extend (agent item_resized)
|
||
|
resized (0, 0, 0, 0)
|
||
|
ensure
|
||
|
item_set: the_item = an_item
|
||
|
end
|
||
|
|
||
|
feature -- Status report
|
||
|
|
||
|
the_item: EV_WIDGET
|
||
|
-- Item currently contained.
|
||
|
|
||
|
feature -- Status setting
|
||
|
|
||
|
remove_item
|
||
|
-- Remove item from `Current'
|
||
|
do
|
||
|
if the_item /= Void then
|
||
|
main_fixed.wipe_out
|
||
|
the_item := Void
|
||
|
the_item.resize_actions.go_i_th (the_item.resize_actions.count)
|
||
|
the_item.resize_actions.remove
|
||
|
end
|
||
|
ensure
|
||
|
no_item_contained: the_item = Void
|
||
|
end
|
||
|
|
||
|
|
||
|
feature {NONE} -- Implementation
|
||
|
|
||
|
item_resized (an_x, a_y, a_width, a_height: INTEGER)
|
||
|
-- `the_item' has been resized, respond by updating `Current'.
|
||
|
do
|
||
|
resized (0, 0, width, height)
|
||
|
end
|
||
|
|
||
|
resized (an_x, a_y, a_width, a_height: INTEGER)
|
||
|
-- `Current' has been resized. Determine if the scroll bars must be updated, and if necessary
|
||
|
-- connect an idle action that executes `update_scroll_bars' if their visible status has changed.
|
||
|
-- The visible status of the scroll bars must not be updated via `show' or `hide' during execution of
|
||
|
-- this feature as it is called from within the resize. Resizing a Vision2 interface during a resize
|
||
|
-- event is dangerous in this situation. Hence we must connect `update_scroll_bars' to perform the update
|
||
|
-- when the resizing is completed from the idle actions.
|
||
|
do
|
||
|
clear_visibility_flags
|
||
|
if the_item /= Void then
|
||
|
if viewport.width < the_item.width then
|
||
|
if not horizontal_scroll_bar.is_show_requested then
|
||
|
show_horizontal := True
|
||
|
end
|
||
|
horizontal_scroll_bar.value_range.adapt (create {INTEGER_INTERVAL}.make (0, the_item.width - viewport.width))
|
||
|
horizontal_scroll_bar.set_leap (viewport.width.max (1))
|
||
|
elseif horizontal_scroll_bar.is_show_requested then
|
||
|
hide_horizontal := True
|
||
|
end
|
||
|
if viewport.height < the_item.height then
|
||
|
if not vertical_scroll_bar.is_show_requested then
|
||
|
show_vertical := True
|
||
|
end
|
||
|
|
||
|
vertical_scroll_bar.value_range.adapt (create {INTEGER_INTERVAL}.make (0, the_item.height - viewport.height))
|
||
|
vertical_scroll_bar.set_leap (viewport.height.max (1))
|
||
|
elseif vertical_scroll_bar.is_show_requested then
|
||
|
hide_vertical := True
|
||
|
end
|
||
|
|
||
|
-- Ensure that as `Current' is enlarged, if the scroll positions are non zero, the
|
||
|
-- item tends towards the zero position.
|
||
|
if viewport.y_offset > 0 and the_item.height - viewport.y_offset < viewport.height then
|
||
|
viewport.set_y_offset ((the_item.height - viewport.height).max (0))
|
||
|
end
|
||
|
if viewport.x_offset > 0 and the_item.width - viewport.x_offset < viewport.width then
|
||
|
viewport.set_x_offset ((the_item.width - viewport.width).max (0))
|
||
|
end
|
||
|
if show_horizontal or hide_horizontal or show_vertical or hide_vertical and not idle_actions_connected then
|
||
|
idle_actions_connected := True
|
||
|
application.idle_actions.extend (agent update_scroll_bars)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
update_scroll_bars
|
||
|
-- Actually perform hiding and showing of scroll bars deferred from `resized'.
|
||
|
-- Note that we must recompute the scroll bar values, as the widgets may have been resized since we
|
||
|
-- originally flagged that there must be a change of visibility.
|
||
|
do
|
||
|
if show_vertical then
|
||
|
vertical_scroll_bar.show
|
||
|
end
|
||
|
if hide_vertical then
|
||
|
vertical_scroll_bar.hide
|
||
|
end
|
||
|
if show_horizontal then
|
||
|
horizontal_scroll_bar.show
|
||
|
end
|
||
|
if hide_horizontal then
|
||
|
horizontal_scroll_bar.hide
|
||
|
end
|
||
|
|
||
|
if horizontal_scroll_bar.is_show_requested and vertical_scroll_bar.is_show_requested then
|
||
|
cell.show
|
||
|
else
|
||
|
cell.hide
|
||
|
end
|
||
|
|
||
|
if show_vertical or show_horizontal or hide_horizontal or hide_vertical then
|
||
|
if vertical_scroll_bar.is_show_requested then
|
||
|
vertical_scroll_bar.value_range.adapt (create {INTEGER_INTERVAL}.make (0, the_item.height - viewport.height))
|
||
|
vertical_scroll_bar.set_leap (viewport.height.max (1))
|
||
|
end
|
||
|
|
||
|
if horizontal_scroll_bar.is_show_requested then
|
||
|
horizontal_scroll_bar.value_range.adapt (create {INTEGER_INTERVAL}.make (0, the_item.width - viewport.width))
|
||
|
horizontal_scroll_bar.set_leap (viewport.width.max (1))
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
-- Ensure that as `Current' is enlarged, if the scroll positions are non zero, the
|
||
|
-- item tends towards the zero position.
|
||
|
if viewport.y_offset > 0 and the_item.height - viewport.y_offset < viewport.height then
|
||
|
viewport.set_y_offset ((the_item.height - viewport.height).max (0))
|
||
|
end
|
||
|
if viewport.x_offset > 0 and the_item.width - viewport.x_offset < viewport.width then
|
||
|
viewport.set_x_offset ((the_item.width - viewport.width).max (0))
|
||
|
end
|
||
|
|
||
|
|
||
|
-- Remove the idle action as leaving it hogs the CPU.
|
||
|
application.idle_actions.go_i_th (application.idle_actions.count)
|
||
|
application.idle_actions.remove
|
||
|
idle_actions_connected := False
|
||
|
end
|
||
|
|
||
|
show_vertical, hide_vertical, show_horizontal, hide_horizontal, show_cell, hide_cell: BOOLEAN
|
||
|
-- Flags to determine if the visible state of widgets must be updated.
|
||
|
|
||
|
clear_visibility_flags
|
||
|
-- Clear visibility flags to False.
|
||
|
do
|
||
|
show_vertical := False
|
||
|
show_horizontal := False
|
||
|
hide_horizontal := False
|
||
|
hide_vertical := False
|
||
|
end
|
||
|
|
||
|
|
||
|
scroll_vertically (new_value: INTEGER)
|
||
|
-- Respond to a scrolling of `vertical_scroll_bar'.
|
||
|
do
|
||
|
viewport.set_y_offset (new_value)
|
||
|
end
|
||
|
|
||
|
scroll_horizontally (new_value: INTEGER)
|
||
|
-- Respond to a scrolling of `horizontal_scroll_bar'.
|
||
|
do
|
||
|
viewport.set_x_offset (new_value)
|
||
|
end
|
||
|
|
||
|
is_in_default_state: BOOLEAN = True
|
||
|
-- Is `Current' in its default state.
|
||
|
|
||
|
idle_actions_connected: BOOLEAN
|
||
|
-- Is the idle event for showing scroll bars already connected?
|
||
|
|
||
|
vertical_scroll_bar: EV_VERTICAL_SCROLL_BAR
|
||
|
-- Vertical scroll bar comprising `Current'.
|
||
|
|
||
|
horizontal_scroll_bar: EV_HORIZONTAL_SCROLL_BAR
|
||
|
-- Horizontal scroll bar comprising `Current'.
|
||
|
|
||
|
horizontal_box: EV_HORIZONTAL_BOX
|
||
|
-- Horizontal box comprising `Current'.
|
||
|
|
||
|
viewport: EV_VIEWPORT
|
||
|
-- Viewport comprising `Current'.
|
||
|
|
||
|
main_fixed: EV_FIXED
|
||
|
-- The Fixed required in `Current'.
|
||
|
|
||
|
cell: EV_CELL
|
||
|
-- A cell placed betwen the corners of the scroll bars.
|
||
|
|
||
|
application: EV_APPLICATION
|
||
|
-- Once access to EV_APPLICATION.
|
||
|
once
|
||
|
--((create {EV_ENVIRONMENT}).application).idle_actions.extend (agent update_scroll_bars)
|
||
|
Result := ((create {EV_ENVIRONMENT}).application)
|
||
|
end
|
||
|
|
||
|
end -- class LEFT_ALIGNED_SCROLLABLE_AREA
|