986 lines
26 KiB
Plaintext
986 lines
26 KiB
Plaintext
note
|
|
description: "[
|
|
Root class for widgets in VITP where `item' represents some {VITP_ITEM}.
|
|
This also has features for aligning a widget with another.
|
|
]"
|
|
author: "Jimmy J. Johnson"
|
|
|
|
deferred class
|
|
VITP_WIDGET
|
|
|
|
inherit
|
|
|
|
-- EV_WIDGET
|
|
|
|
JJ_MODEL_WORLD_VIEW
|
|
-- See newgroup message 20398. Concrete descendants must
|
|
-- re-implement `new_filled_list' (from ARRAYED_LIST) as:
|
|
-- new_filled_list (n: INTEGER): like Current
|
|
-- -- New list with `n' elements.
|
|
-- do
|
|
-- create Result.make (n)
|
|
-- end
|
|
-- undefine
|
|
-- new_filled_list
|
|
redefine
|
|
create_interface_objects,
|
|
initialize,
|
|
set_target,
|
|
set_dimming_level,
|
|
target_imp,
|
|
add_actions,
|
|
new_filled_list
|
|
-- Let's try redefining with an empty body; this feature
|
|
-- may be inapplicable anyway.
|
|
-- select
|
|
-- default_create
|
|
end
|
|
|
|
-- DIMABLE
|
|
-- rename
|
|
-- default_create as initialize_dimable
|
|
-- redefine
|
|
-- set_dimming_level
|
|
-- end
|
|
|
|
FONT_AND_COLOR_CONSTANTS
|
|
export
|
|
{NONE}
|
|
all
|
|
undefine
|
|
default_create
|
|
end
|
|
|
|
feature {NONE} -- Initialization
|
|
|
|
create_interface_objects
|
|
-- Initialize attributes
|
|
require else
|
|
not_initialized: not is_initialized
|
|
local
|
|
i: INTEGER
|
|
c: EV_COORDINATE
|
|
do
|
|
accept_cursor := Default_accept_cursor
|
|
deny_cursor := Default_accept_cursor
|
|
foreground_color := Black
|
|
create font
|
|
create text_group
|
|
create name_mt
|
|
create dot
|
|
Precursor {JJ_MODEL_WORLD_VIEW}
|
|
end
|
|
|
|
frozen initialize
|
|
-- Set up the widgets in Current.
|
|
require else
|
|
not_initialized: not is_initialized
|
|
do
|
|
-- set_font (Default_font)
|
|
-- initialize_defining_figure
|
|
extend_widgets
|
|
build_widgets
|
|
set_fonts_and_colors
|
|
position_widgets
|
|
set_widget_order
|
|
-- add_actions
|
|
dot.set_line_width (10)
|
|
-- The Precursor from {VIEW} calls `add_actions'
|
|
Precursor {JJ_MODEL_WORLD_VIEW}
|
|
set_pebble (target)
|
|
is_initialized := True
|
|
end
|
|
|
|
extend_widgets
|
|
-- Put widgets into Current. This cannot be done
|
|
-- in `create_interface_object', because cannot call
|
|
-- `extend' feature until all objects [in descendants]
|
|
-- are also created.
|
|
do
|
|
extend (dot)
|
|
extend (text_group)
|
|
text_group.extend (name_mt)
|
|
-- Cannot put `jj_defining_figure' in yet, because
|
|
-- descendants may not have finished creation and
|
|
-- `jj_defining_figure' is self-initializing.
|
|
-- extend (jj_defining_figure)
|
|
end
|
|
|
|
build_widgets
|
|
-- Now that widgets were created in `create_interface_objects'
|
|
-- and added to Current in `extend_widgets', build up the
|
|
-- widgets by adding internal structure to each widget.
|
|
do
|
|
end
|
|
|
|
set_fonts_and_colors
|
|
-- Set the default fonts for any text widgets and set
|
|
-- the default colors for any contained widgets.
|
|
do
|
|
end
|
|
|
|
position_widgets
|
|
-- Move Current and contained widgets to correct
|
|
-- location and set their sizes
|
|
require
|
|
not_initialized: not is_initialized
|
|
do
|
|
-- Center text on Current
|
|
text_group.set_x_y (x, y)
|
|
end
|
|
|
|
set_widget_order
|
|
-- Ensure the widgets are ordered properly
|
|
-- (i.e. whose on top?)
|
|
do
|
|
bring_to_front (text_group)
|
|
bring_to_front (dot)
|
|
-- Next line is okay, I think
|
|
extend (jj_defining_figure)
|
|
bring_to_front (jj_defining_figure)
|
|
end
|
|
|
|
add_actions
|
|
-- Add actions to Current
|
|
do
|
|
check not is_view_initialized then
|
|
-- pointer_enter_actions.extend (agent on_pointer_enter)
|
|
-- pointer_leave_actions.extend (agent on_pointer_leave)
|
|
-- pointer_motion_actions.extend (agent on_pointer_motion)
|
|
-- pointer_button_press_actions.extend (agent on_button_pressed)
|
|
-- pointer_double_press_actions.extend (agent on_pointer_double_pressed)
|
|
-- pointer_button_release_actions.extend (agent on_button_released)
|
|
-- pointer_motion_actions.extend (agent on_pointer_motion)
|
|
-- pointer_enter_actions.extend (agent on_pointer_enter)
|
|
-- pointer_leave_actions.extend (agent on_pointer_leave)
|
|
end
|
|
Precursor {JJ_MODEL_WORLD_VIEW}
|
|
end
|
|
|
|
-- build_bounding_figure
|
|
-- -- Add points to the `jj_bounding_figure'.
|
|
-- -- The default builds a polygon from the `bounding_box'.
|
|
-- require
|
|
-- not_initialized: not is_initialized
|
|
-- local
|
|
-- bb: like bounding_box
|
|
-- do
|
|
-- jj_bounding_figure.set_point_count (4)
|
|
-- bb := bounding_box
|
|
-- jj_bounding_figure.set_i_th_point_position (1, bb.lower_left.x, bb.lower_left.y)
|
|
-- jj_bounding_figure.set_i_th_point_position (2, bb.upper_left.x, bb.upper_left.y)
|
|
-- jj_bounding_figure.set_i_th_point_position (3, bb.upper_right.x, bb.upper_right.y)
|
|
-- jj_bounding_figure.set_i_th_point_position (4, bb.lower_right.x, bb.lower_right.y)
|
|
-- bring_to_front (jj_bounding_figure)
|
|
-- jj_bounding_figure.hide
|
|
-- jj_bounding_figure.enable_closed
|
|
-- ensure
|
|
-- has_enough_points: jj_bounding_figure.point_count >= 1
|
|
-- has_bounding_figure: has (jj_bounding_figure)
|
|
-- end
|
|
|
|
set_initialized
|
|
-- Make `is_initialized'
|
|
do
|
|
is_initialized := true
|
|
end
|
|
|
|
feature -- Access
|
|
|
|
game: VITP_GAME
|
|
-- The game for which this widget provides an interface.
|
|
do
|
|
Result := target.game
|
|
end
|
|
|
|
foreground_color: EV_COLOR
|
|
-- Can be used to `paint' contained widgets
|
|
|
|
-- background_color: EV_COLOR
|
|
-- -- Can be used to `paint' contained widgets.
|
|
-- defined in EV_MODEL_WORLD
|
|
|
|
font: EV_FONT
|
|
-- The base font from which the size, weight, etc
|
|
-- of the fonts for any texts in Current can be based.
|
|
|
|
dot: EV_MODEL_DOT
|
|
-- A point on Current used for positioning child widgets
|
|
|
|
jj_defining_figure: EV_MODEL_CLOSED
|
|
-- A shape to mark the boundary of Current, used
|
|
-- to determine if widgets overlap or depart an area.
|
|
attribute
|
|
create {EV_MODEL_RECTANGLE} Result.make_with_points (bounding_box.upper_left, bounding_box.lower_right)
|
|
Result.set_line_width (5)
|
|
end
|
|
|
|
midpoint: EV_COORDINATE
|
|
-- The point that is the center of the `jj_bounding_figure'
|
|
-- relative to Current's containing group
|
|
local
|
|
p: EV_COORDINATE
|
|
mid: EV_COORDINATE
|
|
do
|
|
p := point_relative
|
|
mid := points_middle (min_values, max_values)
|
|
create Result.make_precise (p.x + mid.x, p.y + mid.y)
|
|
end
|
|
|
|
feature -- Element change
|
|
|
|
set_target (a_item: like target)
|
|
-- Associate `a_item' with Current.
|
|
local
|
|
s, s1, s2: STRING
|
|
pos: INTEGER
|
|
do
|
|
Precursor {JJ_MODEL_WORLD_VIEW} (a_item)
|
|
-- Set text, handling a couple of {PORT} names specially
|
|
if target = game.Pearl_harbor or
|
|
target = game.Johnston_island or
|
|
target = game.New_hebrides or
|
|
target = game.dutch_harbor or
|
|
target = game.Andaman_islands then
|
|
-- split into two lines
|
|
s := target.name
|
|
pos := s.index_of (' ', 1)
|
|
s1 := s.substring (1, pos - 1)
|
|
s2 := s.substring (pos + 1, s.count)
|
|
-- Add spaces to better center text on circles
|
|
if target = game.pearl_harbor or target = game.dutch_harbor then
|
|
s1 := " " + s1
|
|
elseif target = game.johnston_island then
|
|
s2 := " " + s2
|
|
elseif target = game.new_hebrides then
|
|
s1 := " " + s1
|
|
elseif target = game.andaman_islands then
|
|
s2 := " " + s2
|
|
end
|
|
name_mt.set_text (s1 + "%N" + s2)
|
|
else
|
|
name_mt.set_text (target.name)
|
|
end
|
|
-- Set the color of and draw the contained widgets
|
|
paint
|
|
end
|
|
|
|
set_foreground_color (a_color: EV_COLOR)
|
|
-- Change the color in which the text is drawn
|
|
require
|
|
color_exists: a_color /= Void
|
|
do
|
|
foreground_color := a_color
|
|
paint
|
|
end
|
|
|
|
-- set_font (a_font: EV_FONT)
|
|
-- -- Change the appearance of the `font' from which
|
|
-- -- the fonts (height, weight, etc.) of any text
|
|
-- -- widgets in Current can be based.
|
|
-- do
|
|
-- font := a_font
|
|
-- name_mt.set_font (font)
|
|
-- end
|
|
|
|
feature -- Basic operations
|
|
|
|
set_dimming_level (a_level: INTEGER)
|
|
-- Change the `dimming_level'
|
|
do
|
|
Precursor {JJ_MODEL_WORLD_VIEW} (a_level)
|
|
from start
|
|
until exhausted
|
|
loop
|
|
if attached {VITP_WIDGET} item as v then
|
|
-- io.put_string (" VITP_WIDGET.set_dimming_level - widget is a {" + v.generating_type + "} %N" )
|
|
v.set_dimming_level (a_level)
|
|
end
|
|
forth
|
|
end
|
|
paint
|
|
end
|
|
|
|
paint
|
|
-- Set the color of items in this widget and hide/show figures
|
|
do
|
|
if is_defining_figure_shown then
|
|
jj_defining_figure.show
|
|
else
|
|
jj_defining_figure.hide
|
|
end
|
|
name_mt.set_foreground_color (adjusted_color (foreground_color))
|
|
end
|
|
|
|
-- center_on (a_x, a_y: INTEGER_32)
|
|
-- -- Move Current so its center point is on (a_x, a_y).
|
|
-- local
|
|
-- bb: EV_RECTANGLE
|
|
-- do
|
|
-- bb := bounding_box
|
|
-- set_x_y (a_x - (bb.x + bb.width // 2), a_y - (bb.y + bb.height // 2))
|
|
-- end
|
|
|
|
center_on_point (a_point: EV_COORDINATE)
|
|
-- Transform Current so its center point is on `a_point'
|
|
require
|
|
point_exists: a_point /= Void
|
|
local
|
|
t: EV_MODEL_TRANSFORMATION
|
|
ax, ay: REAL_64
|
|
bb: EV_RECTANGLE
|
|
do
|
|
bb := bounding_box
|
|
ax := a_point.x_precise - (bb.x + bb.width / 2)
|
|
ay := a_point.y_precise - (bb.y + bb.height / 2)
|
|
create t.make_id
|
|
t.translate (ax, ay)
|
|
transform (t)
|
|
end
|
|
|
|
center_on_dot (a_dot: EV_MODEL_DOT)
|
|
-- Place the center of `a_widget' on `a_dot'
|
|
require
|
|
dot_exists: a_dot /= Void
|
|
local
|
|
bb: EV_RECTANGLE
|
|
cx, cy: REAL_64
|
|
dif_x, dif_y: REAL_64
|
|
t: EV_MODEL_TRANSFORMATION
|
|
do
|
|
bb := bounding_box
|
|
cx := bb.width / 2
|
|
cy := bb.height / 2
|
|
dif_x := (bb.x + cx) - a_dot.point.x_precise
|
|
dif_y := (bb.y + cy) - a_dot.point.y_precise
|
|
-- dif_x := (bb.x + cx) - dot.point_x
|
|
-- dif_y := (bb.y + cy) - dot.point_y
|
|
create t.make_zero
|
|
t.translate (-dif_x, -dif_y)
|
|
transform (t)
|
|
end
|
|
|
|
center_on_origin
|
|
-- Place the center of the widget at (0,0)
|
|
local
|
|
t: EV_MODEL_TRANSFORMATION
|
|
ax, ay: REAL_64
|
|
bb: EV_RECTANGLE
|
|
do
|
|
bb := bounding_box
|
|
ax := bb.x + bb.width / 2
|
|
ay := bb.y + bb.height / 2
|
|
create t.make_id
|
|
t.translate (-ax, -ay)
|
|
transform (t)
|
|
end
|
|
|
|
center_widget_on_dot (a_widget: EV_MODEL; a_dot: EV_MODEL_DOT)
|
|
-- Place the center of `a_widget' on `a_dot'
|
|
local
|
|
bb: EV_RECTANGLE
|
|
cx, cy: REAL_64
|
|
dif_x, dif_y: REAL_64
|
|
t: EV_MODEL_TRANSFORMATION
|
|
do
|
|
bb := a_widget.bounding_box
|
|
cx := bb.width / 2
|
|
cy := bb.height / 2
|
|
dif_x := (bb.x + cx) - dot.point.x_precise
|
|
dif_y := (bb.y + cy) - dot.point.y_precise
|
|
create t.make_zero
|
|
t.translate (-dif_x, -dif_y)
|
|
a_widget.transform (t)
|
|
end
|
|
|
|
center_widget_on_other (a_widget: EV_MODEL; a_other: EV_MODEL)
|
|
-- Place the center of `a_widget' on `a_other'
|
|
local
|
|
bb, bb_other: EV_RECTANGLE
|
|
bb_center_x, bb_center_y: REAL_64
|
|
bb_other_center_x, bb_other_center_y: REAL_64
|
|
cx, cy: REAL_64
|
|
dif_x, dif_y: REAL_64
|
|
t: EV_MODEL_TRANSFORMATION
|
|
do
|
|
bb := a_widget.bounding_box
|
|
bb_other := a_other.bounding_box
|
|
bb_center_x := bb.left + bb.width / 2
|
|
bb_center_y := bb.top + bb.height / 2
|
|
bb_other_center_x := bb_other.left + bb_other.width / 2
|
|
bb_other_center_y := bb_other.top + bb_other.height / 2
|
|
dif_x := bb_other_center_x - bb_center_x
|
|
dif_y := bb_other_center_y - bb_center_y
|
|
|
|
-- cx := bb.width / 2
|
|
-- cy := bb.height / 2
|
|
-- dif_x := (bb.x + cx) - dot.point.x_precise
|
|
-- dif_y := (bb.y + cy) - dot.point.y_precise
|
|
-- dif_x := (bb.x + cx) - a_other.point_array.item (0).x_precise
|
|
-- dif_y := (bb.x + cx) - a_other.point_array.item (0).x_precise
|
|
create t.make_zero
|
|
t.translate (dif_x, dif_y)
|
|
a_widget.transform (t)
|
|
-- Check for identical centers
|
|
bb := a_widget.bounding_box
|
|
bb_other := a_other.bounding_box
|
|
bb_center_x := bb.left + bb.width / 2
|
|
bb_center_y := bb.top + bb.height / 2
|
|
bb_other_center_x := bb_other.left + bb_other.width / 2
|
|
bb_other_center_y := bb_other.top + bb_other.height / 2
|
|
dif_x := bb_other_center_x - bb_center_x
|
|
dif_y := bb_other_center_y - bb_center_y
|
|
end
|
|
|
|
translate_widget (a_widget: EV_MODEL; a_x, a_y: INTEGER_32)
|
|
-- Move `a_widget' in x and y directions.
|
|
local
|
|
t: EV_MODEL_TRANSFORMATION
|
|
do
|
|
create t.make_zero
|
|
t.translate (a_x, a_y)
|
|
-- a_widget.transform (t)
|
|
a_widget.set_x_y (a_widget.x + a_x, a_widget.y + a_y)
|
|
end
|
|
|
|
rotate_widget (a_widget: EV_MODEL; a_degrees: REAL_64)
|
|
-- Rotate `a_widget' `a_degrees' clockwise.
|
|
local
|
|
rad: REAL_64
|
|
do
|
|
rad := degrees_to_radians (a_degrees)
|
|
a_widget.rotate (rad)
|
|
end
|
|
|
|
scale_widget (a_widget: EV_MODEL; a_scale: REAL_64)
|
|
-- Resize `a_widget' by `a_scale' factor.
|
|
do
|
|
a_widget.scale (a_scale)
|
|
end
|
|
|
|
align_midpoints (a_other: VITP_WIDGET)
|
|
-- Move Current so its `midpoint' is over the `midpoint' of `a_other'
|
|
local
|
|
t: EV_MODEL_TRANSFORMATION
|
|
po: EV_COORDINATE
|
|
do
|
|
po := points_offset (midpoint, a_other.midpoint)
|
|
create t.make_zero
|
|
t.translate (po.x_precise, po.y_precise)
|
|
transform (t)
|
|
end
|
|
|
|
align_midpoints_with_offset (a_other: VITP_WIDGET; a_x_offset, a_y_offset: REAL_64)
|
|
-- Move Current so its `midpoint' is offset from the `midpoint'
|
|
-- of `a_other' by the offsets (as percentages of the size of
|
|
-- Current in that direction).
|
|
local
|
|
t: EV_MODEL_TRANSFORMATION
|
|
s: EV_COORDINATE
|
|
xx, yy: REAL_64
|
|
do
|
|
s := a_other.size_values
|
|
align_midpoints (a_other)
|
|
xx := s.x_precise * a_x_offset
|
|
yy := s.y_precise * a_y_offset
|
|
create t.make_zero
|
|
t.translate (xx, yy)
|
|
transform (t)
|
|
end
|
|
|
|
align_vertical (a_other: VITP_WIDGET)
|
|
-- Move Current horizontally until it's `midpoint.x' is aligned
|
|
-- with the `midpoint.x' of `a_other'.
|
|
local
|
|
t: EV_MODEL_TRANSFORMATION
|
|
po: EV_COORDINATE
|
|
do
|
|
po := points_offset (midpoint, a_other.midpoint)
|
|
create t.make_zero
|
|
t.translate (po.x_precise, 0.0)
|
|
transform (t)
|
|
end
|
|
|
|
align_horizontal (a_other: VITP_WIDGET)
|
|
-- Move Current vertically until it's `midpoint.y' is aligned
|
|
-- with the `midpoint.y' of `a_other'.
|
|
local
|
|
t: EV_MODEL_TRANSFORMATION
|
|
po: EV_COORDINATE
|
|
do
|
|
po := points_offset (midpoint, a_other.midpoint)
|
|
create t.make_zero
|
|
t.translate (0.0, po.y_precise)
|
|
transform (t)
|
|
end
|
|
|
|
align_lefts (a_other: VITP_WIDGET)
|
|
-- Move Current so its left side is aligned with
|
|
-- the left side of `a_other'
|
|
local
|
|
t: EV_MODEL_TRANSFORMATION
|
|
c, o: REAL_64 -- current's value; other's value
|
|
do
|
|
c := min_values.x
|
|
o := a_other.min_values.x
|
|
create t.make_zero
|
|
t.translate (o - c, 0.0)
|
|
transform (t)
|
|
end
|
|
|
|
align_rights (a_other: VITP_WIDGET)
|
|
-- Move Current so its right side is aligned with
|
|
-- the right side of `a_other'
|
|
local
|
|
t: EV_MODEL_TRANSFORMATION
|
|
c, o: REAL_64
|
|
do
|
|
c := max_values.x
|
|
o := a_other.max_values.x
|
|
create t.make_zero
|
|
t.translate (o - c, 0.0)
|
|
transform (t)
|
|
end
|
|
|
|
align_tops (a_other: VITP_WIDGET)
|
|
-- Move Current so its top side is aligned with
|
|
-- the top side of `a_other'
|
|
local
|
|
t: EV_MODEL_TRANSFORMATION
|
|
c, o: REAL_64
|
|
do
|
|
c := max_values.y
|
|
o := a_other.max_values.y
|
|
create t.make_zero
|
|
t.translate (0.0, o - c)
|
|
transform (t)
|
|
end
|
|
|
|
align_bottoms (a_other: VITP_WIDGET)
|
|
-- Move Current so its bottom side is aligned with
|
|
-- the bottom side of `a_other'
|
|
local
|
|
t: EV_MODEL_TRANSFORMATION
|
|
c, o: REAL_64
|
|
do
|
|
c := min_values.y
|
|
o := a_other.min_values.y
|
|
create t.make_zero
|
|
t.translate (o - c, 0.0)
|
|
transform (t)
|
|
end
|
|
|
|
align_left_to_others_right (a_other: VITP_WIDGET)
|
|
-- Move Current so its left side is aligned with the
|
|
-- left side of `a_other'
|
|
local
|
|
t: EV_MODEL_TRANSFORMATION
|
|
o, c: REAL_64
|
|
do
|
|
c := min_values.x
|
|
o := a_other.max_values.x
|
|
create t.make_zero
|
|
t.translate (o - c, 0.0)
|
|
transform (t)
|
|
end
|
|
|
|
align_right_to_others_left (a_other: VITP_WIDGET)
|
|
-- Move Current so its right side is aligned with the
|
|
-- left side of `a_other'
|
|
local
|
|
t: EV_MODEL_TRANSFORMATION
|
|
c, o: REAL_64
|
|
do
|
|
c := max_values.x
|
|
o := a_other.min_values.x
|
|
create t.make_zero
|
|
t.translate (o - c, 0.0)
|
|
transform (t)
|
|
end
|
|
|
|
align_top_to_others_bottom (a_other: VITP_WIDGET)
|
|
-- Move Current so its top side is aligned with the
|
|
-- bottom side of `a_other'
|
|
local
|
|
t: EV_MODEL_TRANSFORMATION
|
|
c, o: REAL_64
|
|
do
|
|
c := min_values.y
|
|
o := a_other.max_values.y
|
|
create t.make_zero
|
|
t.translate (0.0, o - c)
|
|
transform (t)
|
|
end
|
|
|
|
align_bottom_to_others_top (a_other: VITP_WIDGET)
|
|
-- Move Current so its top side is aligned with the
|
|
-- bottom side of `a_other'
|
|
local
|
|
t: EV_MODEL_TRANSFORMATION
|
|
c, o: REAL_64
|
|
do
|
|
c := min_values.y
|
|
o := a_other.max_values.y
|
|
create t.make_zero
|
|
t.translate (o - c, 0.0)
|
|
transform (t)
|
|
end
|
|
|
|
feature -- Actions
|
|
|
|
-- timer: TIME
|
|
|
|
-- on_pointer_enter
|
|
-- -- React to the mouse pointer entering Current
|
|
-- do
|
|
-- io.put_string ("VITP_WIDGET.on_enter " + vitp_item.name + "%N")
|
|
-- -- Start timer; after delay with no movement show status dialog
|
|
|
|
-- end
|
|
|
|
-- on_pointer_leave
|
|
-- -- React to the mouse pointer leaving Current
|
|
-- do
|
|
-- io.put_string ("VITP_WIDGET.on_leave " + vitp_item.name + "%N")
|
|
|
|
-- end
|
|
|
|
-- on_pointer_motion (ax, ay: INTEGER; ax_tilt, ay_tilt, apressure: DOUBLE;
|
|
-- a_screen_x, a_screen_y: INTEGER)
|
|
-- -- React to the mouse moving within Current
|
|
-- do
|
|
-- io.put_string ("VITP_WIDGET.on_move " + vitp_item.name + "%N")
|
|
|
|
-- end
|
|
|
|
feature -- Status report
|
|
|
|
is_initialized: BOOLEAN
|
|
-- Has Curent been initialized? (I.e. all all widgets built?)
|
|
-- Used to prevent calling `initialize' more than once.
|
|
|
|
is_defining_figure_shown: BOOLEAN
|
|
-- Can be used by descendants to determine if the `jj_bounding_figure'
|
|
-- should be visible or not.
|
|
|
|
feature -- Query
|
|
|
|
contains_point (a_point: EV_COORDINATE): BOOLEAN
|
|
-- Is `a_point' on or in Current's `jj_defining_figure'?
|
|
local
|
|
pts: SPECIAL [EV_COORDINATE] -- for convenience
|
|
i, j: INTEGER
|
|
do
|
|
-- pts := jj_bounding_figure.point_array
|
|
-- -- Remember SPECIAL is zero-based
|
|
-- from
|
|
-- i := 0
|
|
-- j := pts.count - 1
|
|
-- until i > pts.count - 1
|
|
-- loop
|
|
-- if ( ((pts[i].y_precise >= a_point.y_precise) /= (pts[j].y_precise >= a_point.y_precise)) and
|
|
-- (a_point.x_precise <= (pts[j].x_precise - pts[i].x_precise) *
|
|
-- (a_point.y_precise - pts[i].y_precise) /
|
|
-- (pts[j].y_precise - pts[i].y_precise) + pts[i].x_precise) ) then
|
|
-- Result := not Result
|
|
-- end
|
|
-- j := i
|
|
-- i := i + 1
|
|
-- end
|
|
Result := jj_defining_figure.position_on_figure (a_point.x, a_point.y)
|
|
end
|
|
|
|
overlaps (a_other: VITP_WIDGET): BOOLEAN
|
|
-- Does Current occupy any space occupied by a_other
|
|
local
|
|
pts: SPECIAL [EV_COORDINATE]
|
|
i: INTEGER
|
|
do
|
|
if Current /= a_other then
|
|
pts := jj_defining_figure.point_array
|
|
-- Remember SPECIAL is zero-based
|
|
from i := 0
|
|
until i > pts.count - 1 or Result
|
|
loop
|
|
Result := a_other.contains_point (pts[i])
|
|
i := i + 1
|
|
end
|
|
-- Check the other way around
|
|
if not Result then
|
|
pts := a_other.jj_defining_figure.point_array
|
|
from i := 0
|
|
until i > pts.count - 1 or Result
|
|
loop
|
|
Result := contains_point (pts[i])
|
|
i := i + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
touches (a_other: VITP_WIDGET): BOOLEAN
|
|
-- Does Current touch `a_other'?
|
|
do
|
|
|
|
end
|
|
|
|
is_touched_by (a_other: VITP_WIDGET): BOOLEAN
|
|
-- Is Current touched by `a_other'?
|
|
do
|
|
|
|
end
|
|
|
|
contains (a_other: VITP_WIDGET): BOOLEAN
|
|
-- Does Current contain *all* of `a_other'?
|
|
do
|
|
|
|
end
|
|
|
|
is_contained_by (a_other: VITP_WIDGET): BOOLEAN
|
|
-- Is *all* of Current within `a_other'?
|
|
do
|
|
|
|
end
|
|
|
|
diverges_from (a_other: VITP_WIDGET): BOOLEAN
|
|
-- Does Current `intersects' `a_other' while having any
|
|
-- point outside `a_other'
|
|
do
|
|
|
|
end
|
|
|
|
feature {NONE} -- Inapplicable
|
|
|
|
new_filled_list (n: INTEGER): like Current
|
|
-- Redefined to get past void-safety issues
|
|
do
|
|
check
|
|
do_not_call: False then
|
|
-- Because this was redefined to appease void-safety, nothing else.
|
|
end
|
|
end
|
|
|
|
feature -- Actions
|
|
|
|
activate_drop_action
|
|
-- Allow Current to react to the drop of a unit, moving
|
|
-- that unit to the `location' in Current.
|
|
do
|
|
drop_actions.extend (drop_unit_agent)
|
|
end
|
|
|
|
deactivate_drop_action
|
|
-- Remove the agent added by `activate_drop_actions
|
|
do
|
|
drop_actions.start
|
|
drop_actions.prune (drop_unit_agent)
|
|
end
|
|
|
|
frozen drop_unit_agent: PROCEDURE [TUPLE [ATTACK_UNIT]]
|
|
-- Create an agent out of `on_drop_unit' which will be added
|
|
-- to Current when a pick is started and the Sequence of Play
|
|
-- allows for the unit to be dropped here.
|
|
once ("OBJECT")
|
|
Result := agent on_drop_unit
|
|
end
|
|
|
|
on_drop_unit (a_unit: ATTACK_UNIT)
|
|
-- Move `a_unit' to `locaiton'
|
|
do
|
|
print ("{LOCATION_WIDGET}.on_drop_unit: dropped " + a_unit.name + " on " + target.name + "%N")
|
|
end
|
|
|
|
feature {NONE} -- Implementation (actions)
|
|
|
|
on_button_pressed (ax: INTEGER; ay: INTEGER; a_button: INTEGER; x_tilt: DOUBLE; y_tilt: DOUBLE;
|
|
pressure: DOUBLE; a_screen_x: INTEGER; a_screen_y: INTEGER)
|
|
-- Notify `board_world' that Current was clicked
|
|
-- This allows the `board_world' to handle the click *and* to know the
|
|
-- widget on which the click occurred.
|
|
do
|
|
io.put_string ("VITP_WIDGET.on_button_pressed on " + target.name + "%N")
|
|
-- if attached board_world as bw then
|
|
-- bw.on_notify_button_pressed (Current, ax, ay, a_button)
|
|
-- end
|
|
end
|
|
|
|
-- on_pointer_double_pressed (ax: INTEGER; ay: INTEGER; a_button: INTEGER; x_tilt: DOUBLE; y_tilt: DOUBLE;
|
|
-- pressure: DOUBLE; a_screen_x: INTEGER; a_screen_y: INTEGER)
|
|
-- -- Notify `board_world' that Current was double-clicked
|
|
-- -- This allows the `board_world' to handle the click *and* to know the
|
|
-- -- widget on which the click occurred.
|
|
-- do
|
|
-- if attached board_world as bw then
|
|
-- bw.on_notify_button_double_pressed (Current, ax, ay, a_button)
|
|
-- end
|
|
-- end
|
|
|
|
-- on_button_released (ax: INTEGER; ay: INTEGER; a_button: INTEGER; x_tilt: DOUBLE; y_tilt: DOUBLE;
|
|
-- pressure: DOUBLE; a_screen_x: INTEGER; a_screen_y: INTEGER)
|
|
-- -- Notify `board_world' that `a_button' was released on it
|
|
-- do
|
|
-- if attached board_world as bw then
|
|
-- bw.on_notify_button_released (Current, ax, ay, a_button)
|
|
-- end
|
|
-- end
|
|
|
|
-- on_pointer_motion (ax: INTEGER; ay: INTEGER; x_tilt: DOUBLE; y_tilt: DOUBLE;
|
|
-- pressure: DOUBLE; a_screen_x: INTEGER; a_screen_y: INTEGER)
|
|
-- -- Notify `board_world' that mouse was moved on Current
|
|
-- local
|
|
-- c: EV_COORDINATE
|
|
-- do
|
|
-- if attached board_world as bw then
|
|
-- bw.on_notify_pointer_motion (Current, ax, ay)
|
|
-- end
|
|
-- end
|
|
|
|
-- on_pointer_enter
|
|
-- -- React to the mouse entering the `dot'
|
|
-- do
|
|
-- if attached board_world as bw then
|
|
-- bw.on_notify_pointer_enter (Current)
|
|
-- end
|
|
-- end
|
|
|
|
-- on_pointer_leave
|
|
-- -- React to mouse leaving Current
|
|
-- do
|
|
-- if attached board_world as bw then
|
|
-- bw.on_notify_pointer_leave (Current)
|
|
-- end
|
|
-- end
|
|
|
|
feature {VITP_WIDGET} -- Implementation
|
|
|
|
vitp_world: detachable WIDGET_FACTORY
|
|
-- The VITP {WIDGET_FACTORY} if any in which Current recursively resides
|
|
do
|
|
if attached {WIDGET_FACTORY} world as w then
|
|
Result := w
|
|
elseif attached {WIDGET_FACTORY} group as w then
|
|
Result := w
|
|
elseif attached {VITP_WIDGET} group as g then
|
|
Result := g.vitp_world
|
|
end
|
|
end
|
|
|
|
size_values: EV_COORDINATE
|
|
-- The difference between the min_values and max_values.
|
|
-- The "width" and "height" of the `jj_defining_figure' as a tuple.
|
|
local
|
|
po: EV_COORDINATE
|
|
do
|
|
po := points_offset (max_values, min_values)
|
|
create Result.make_precise (po.x_precise.abs, po.y_precise.abs)
|
|
end
|
|
|
|
min_values: EV_COORDINATE
|
|
-- The smallest values of both the x & y coordinates of all
|
|
-- the points in `jj_bounding_figure'
|
|
local
|
|
i: INTEGER
|
|
xx, yy: REAL_64
|
|
c: EV_COORDINATE
|
|
rect: EV_RECTANGLE
|
|
do
|
|
-- create c
|
|
-- xx := {REAL_64}.Max_value
|
|
-- yy := {REAL_64}.Max_value
|
|
-- from i := 1
|
|
-- until i > jj_bounding_figure.point_count
|
|
-- loop
|
|
-- c.set_precise (jj_bounding_figure.i_th_point_x (i), jj_bounding_figure.i_th_point_y (i))
|
|
-- if c.x_precise < xx then
|
|
-- xx := c.x_precise
|
|
-- end
|
|
-- if c.y_precise < yy then
|
|
-- yy := c.y_precise
|
|
-- end
|
|
-- i := i + 1
|
|
-- end
|
|
-- create Result.make_precise (xx, yy)
|
|
create Result.make_precise (bounding_box.left, bounding_box.top)
|
|
end
|
|
|
|
max_values: EV_COORDINATE
|
|
-- The largest values of both the x & y coordinates of all
|
|
-- the points in `jj_bounding_figure'
|
|
local
|
|
i: INTEGER
|
|
xx, yy: REAL_64
|
|
c: EV_COORDINATE
|
|
do
|
|
create c
|
|
-- xx := {REAL_64}.Min_value
|
|
-- yy := {REAL_64}.Min_value
|
|
-- from i := 1
|
|
-- until i > jj_bounding_figure.point_count
|
|
-- loop
|
|
-- c.set_precise (jj_bounding_figure.i_th_point_x (i), jj_bounding_figure.i_th_point_y (i))
|
|
-- if c.x_precise > xx then
|
|
-- xx := c.x_precise
|
|
-- end
|
|
-- if c.y_precise > yy then
|
|
-- yy := c.y_precise
|
|
-- end
|
|
-- i := i + 1
|
|
-- end
|
|
-- create Result.make_precise (xx, yy)
|
|
create Result.make_precise (bounding_box.right, bounding_box.bottom)
|
|
end
|
|
|
|
points_middle (a_point, a_other_point: EV_COORDINATE): EV_COORDINATE
|
|
-- The point midway between the two points
|
|
local
|
|
xx, yy: REAL_64
|
|
do
|
|
xx := (a_other_point.x_precise - a_point.x_precise) / 2
|
|
yy := (a_other_point.y_precise - a_point.y_precise) / 2
|
|
create Result.make_precise (xx, yy)
|
|
end
|
|
|
|
points_offset (a_point, a_other_point: EV_COORDINATE): EV_COORDINATE
|
|
-- The offset of `a_other_point' from `a_point'
|
|
local
|
|
xx, yy: REAL_64
|
|
do
|
|
xx := a_other_point.x_precise - a_point.x_precise
|
|
yy := a_other_point.y_precise - a_point.y_precise
|
|
create Result.make_precise (xx, yy)
|
|
end
|
|
|
|
feature {NONE} -- Implementation
|
|
|
|
degrees_to_radians (degrees: DOUBLE): DOUBLE
|
|
-- Convert degrees to radians.
|
|
-- Helper function for convienence if need to rotate the widget.
|
|
require
|
|
degrees_big_enough: degrees >= -360
|
|
degrees_small_enough: degrees <= 360
|
|
do
|
|
Result := degrees * Pi / 180
|
|
ensure
|
|
-- definition: very_close (Result, degrees * (2 * Pi) / 360)
|
|
result_in_range: Result >= -2 * Pi and Result <= 2 * Pi
|
|
end
|
|
|
|
feature {VITP_WIDGET} -- Implementation
|
|
|
|
name_mt: EV_MODEL_TEXT
|
|
-- The name of the object in Current
|
|
|
|
text_group: EV_MODEL_GROUP
|
|
-- Hold any text widgets in Current so they can
|
|
-- be positioned and resized as a group
|
|
|
|
target_imp: detachable VITP_ITEM
|
|
-- Detachable implementation of `target' for void safety
|
|
|
|
invariant
|
|
|
|
not_empty: target_imp /= Void
|
|
|
|
|
|
end
|