1081 lines
22 KiB
Plaintext
1081 lines
22 KiB
Plaintext
note
|
|
description: "[
|
|
A EV_FIGURE_GROUP is an ARRAYED_LIST of EV_FIGURE.
|
|
Since EV_FIGURE_GROUP is also an EV_FIGURE (composite pattern) you
|
|
can rotate, scale and change the position of an EV_FIGURE_GROUP.
|
|
All elements in the group are rotated around the center
|
|
of the EV_FIGURE_GROUP. A EV_FIGURE can only be grouped
|
|
in one group at the same time.
|
|
|
|
]"
|
|
legal: "See notice at end of class."
|
|
status: "See notice at end of class."
|
|
date: "$Date: 2014-06-03 19:49:45 -0400 (Tue, 03 Jun 2014) $"
|
|
revision: "$Revision: 44 $"
|
|
|
|
class
|
|
EV_MODEL_GROUP
|
|
|
|
inherit
|
|
EV_MODEL
|
|
undefine
|
|
point_count
|
|
redefine
|
|
rotate,
|
|
create_interface_objects,
|
|
default_create,
|
|
recursive_transform,
|
|
set_x,
|
|
set_y,
|
|
set_x_y,
|
|
invalid_rectangle,
|
|
update_rectangle,
|
|
invalidate,
|
|
validate,
|
|
bounding_box
|
|
end
|
|
|
|
ARRAYED_LIST [EV_MODEL]
|
|
rename
|
|
make as list_make
|
|
export
|
|
{NONE} put_i_th
|
|
undefine
|
|
is_equal,
|
|
copy
|
|
redefine
|
|
append,
|
|
force,
|
|
extend,
|
|
replace,
|
|
insert,
|
|
prune_all,
|
|
wipe_out,
|
|
remove,
|
|
merge_left,
|
|
merge_right,
|
|
make_from_array,
|
|
default_create,
|
|
swap,
|
|
has,
|
|
make_filled,
|
|
list_make,
|
|
-- I added these
|
|
at,
|
|
last,
|
|
first
|
|
end
|
|
|
|
EV_MODEL_SINGLE_POINTED
|
|
undefine
|
|
default_create
|
|
end
|
|
|
|
create
|
|
default_create,
|
|
make_with_point,
|
|
make_with_position
|
|
|
|
create {EV_MODEL_GROUP}
|
|
list_make,
|
|
make_filled
|
|
|
|
feature {NONE} -- Initialization
|
|
|
|
create_interface_objects
|
|
-- <Precursor>
|
|
do
|
|
create lookup_table.make (initiale_size)
|
|
create point_array.make_empty (1)
|
|
make_empty_area (initiale_size)
|
|
Precursor {EV_MODEL}
|
|
end
|
|
|
|
default_create
|
|
-- Create an empty EV_MODEL_GROUP.
|
|
do
|
|
Precursor {EV_MODEL}
|
|
point_array.extend (create {EV_COORDINATE}.make (0, 0))
|
|
index := 0
|
|
is_grouped := True
|
|
ensure then
|
|
is_grouped: is_grouped
|
|
not_is_in_group: not is_in_group
|
|
end
|
|
|
|
make_filled (n: INTEGER_32)
|
|
-- <Precursor>
|
|
do
|
|
default_create
|
|
Precursor {ARRAYED_LIST} (n)
|
|
end
|
|
|
|
list_make (n: INTEGER)
|
|
-- <Precursor>
|
|
do
|
|
default_create
|
|
Precursor {ARRAYED_LIST} (n)
|
|
end
|
|
|
|
feature -- Access
|
|
|
|
angle: DOUBLE
|
|
-- `Current' has to be rotated around (`x',`y') for -`angle'
|
|
-- to be in upright position.
|
|
do
|
|
Result := current_angle
|
|
ensure then
|
|
Result_equal_current_angle: Result = current_angle
|
|
end
|
|
|
|
point_x: INTEGER
|
|
-- x position of `point'.
|
|
do
|
|
Result := point_array.item (0).x
|
|
end
|
|
|
|
point_y: INTEGER
|
|
-- y position of `point'.
|
|
do
|
|
Result := point_array.item (0).y
|
|
end
|
|
|
|
deep_elements: LIST [EV_MODEL]
|
|
-- All elements in `Current' and in its subgroups.
|
|
local
|
|
l_group: detachable EV_MODEL_GROUP
|
|
l_list: ARRAYED_LIST [EV_MODEL]
|
|
do
|
|
create l_list.make (0)
|
|
from
|
|
start
|
|
until
|
|
after
|
|
loop
|
|
l_group ?= item
|
|
if l_group /= Void then
|
|
l_list.append (l_group.deep_elements)
|
|
end
|
|
l_list.extend (item)
|
|
forth
|
|
end
|
|
Result := l_list
|
|
ensure
|
|
Result_not_Void: Result /= Void
|
|
end
|
|
|
|
at alias "@" (i: INTEGER): like item assign put_i_th
|
|
-- Item at `i'-th position, redefined by jjj to conform to `item'
|
|
do
|
|
check attached {like item} Precursor {ARRAYED_LIST} (i) as v then
|
|
Result := v
|
|
end
|
|
end
|
|
|
|
first: like item
|
|
-- Item at first position, redefined by jjj to conform to `item'
|
|
do
|
|
check attached {like item} Precursor {ARRAYED_LIST} as v then
|
|
Result := v
|
|
end
|
|
end
|
|
|
|
last: like item
|
|
-- Item at last position, redefined by jjj to conform to `item'
|
|
do
|
|
check attached {like item} Precursor {ARRAYED_LIST} as v then
|
|
Result := v
|
|
end
|
|
end
|
|
|
|
feature -- Status report
|
|
|
|
is_rotatable: BOOLEAN
|
|
-- Is this figure group rotatable?
|
|
local
|
|
l_area: like area
|
|
i, nb: INTEGER
|
|
do
|
|
if is_grouped then
|
|
Result := True
|
|
l_area := area
|
|
from
|
|
i := 0
|
|
nb := count - 1
|
|
until
|
|
i > nb or not Result
|
|
loop
|
|
Result := l_area.item (i).is_rotatable
|
|
i := i + 1
|
|
end
|
|
else
|
|
Result := True
|
|
end
|
|
end
|
|
|
|
is_scalable: BOOLEAN
|
|
-- Is this figure group scalable?
|
|
local
|
|
l_area: like area
|
|
i, nb: INTEGER
|
|
do
|
|
if is_grouped then
|
|
Result := True
|
|
l_area := area
|
|
from
|
|
i := 0
|
|
nb := count - 1
|
|
until
|
|
i > nb or not Result
|
|
loop
|
|
Result := l_area.item (i).is_scalable
|
|
i := i + 1
|
|
end
|
|
else
|
|
Result := True
|
|
end
|
|
end
|
|
|
|
is_transformable: BOOLEAN
|
|
-- Is this figure group transformable?
|
|
local
|
|
l_area: like area
|
|
i, nb: INTEGER
|
|
do
|
|
if is_grouped then
|
|
Result := True
|
|
l_area := area
|
|
from
|
|
i := 0
|
|
nb := count - 1
|
|
until
|
|
i > nb or not Result
|
|
loop
|
|
Result := l_area.item (i).is_transformable
|
|
i := i + 1
|
|
end
|
|
else
|
|
Result := True
|
|
end
|
|
end
|
|
|
|
is_grouped: BOOLEAN
|
|
-- Is grouped?
|
|
|
|
has (v: like item): BOOLEAN
|
|
-- Does current include `v'?
|
|
-- (based on v.id)
|
|
do
|
|
if v /= Void then
|
|
Result := lookup_table.has (v.id)
|
|
end
|
|
end
|
|
|
|
has_deep (figure: EV_MODEL): BOOLEAN
|
|
-- Does any item contains `figure'?
|
|
local
|
|
grp: detachable EV_MODEL_GROUP
|
|
do
|
|
from
|
|
start
|
|
until
|
|
after or Result
|
|
loop
|
|
grp ?= item
|
|
if grp = Void then
|
|
Result := figure = item
|
|
elseif grp = figure then
|
|
Result := True
|
|
else
|
|
Result := grp.has_deep (figure)
|
|
end
|
|
forth
|
|
end
|
|
end
|
|
|
|
invalid_rectangle: detachable EV_RECTANGLE
|
|
-- Rectangle that needs erasing.
|
|
-- `Void' if no change is made.
|
|
local
|
|
r: detachable EV_RECTANGLE
|
|
l_area: like area
|
|
i, nb: INTEGER
|
|
do
|
|
if not valid then
|
|
from
|
|
l_area := area
|
|
i := 0
|
|
nb := count - 1
|
|
until
|
|
i > nb
|
|
loop
|
|
r := l_area [i].invalid_rectangle
|
|
if r /= Void and then r.has_area and then l_area [i].is_show_requested then
|
|
if Result = Void then
|
|
if internal_invalid_rectangle = Void then
|
|
create internal_invalid_rectangle
|
|
end
|
|
Result := internal_invalid_rectangle
|
|
Result.copy (r)
|
|
else
|
|
Result.merge (r)
|
|
end
|
|
end
|
|
i := i + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
update_rectangle: detachable EV_RECTANGLE
|
|
-- Rectangle that needs redrawing.
|
|
-- `Void' if no change is made.
|
|
local
|
|
r: detachable EV_RECTANGLE
|
|
l_area: like area
|
|
i, nb: INTEGER
|
|
do
|
|
if not valid and then is_show_requested and then is_grouped then
|
|
from
|
|
l_area := area
|
|
i := 0
|
|
nb := count - 1
|
|
until
|
|
i > nb
|
|
loop
|
|
r := l_area [i].update_rectangle
|
|
if r /= Void then
|
|
if Result = Void then
|
|
if last_update_rectangle = Void then
|
|
-- Reuse `local_update_rectangle'
|
|
create last_update_rectangle
|
|
end
|
|
Result := last_update_rectangle
|
|
Result.copy (r)
|
|
else
|
|
Result.merge (r)
|
|
end
|
|
end
|
|
i := i + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
feature -- Visitor
|
|
|
|
project (a_projector: EV_MODEL_DRAWING_ROUTINES)
|
|
-- <Precursor>
|
|
do
|
|
across Current as ic_models loop
|
|
if ic_models.item.is_show_requested then
|
|
ic_models.item.project (a_projector)
|
|
end
|
|
end
|
|
end
|
|
|
|
feature -- Element change
|
|
|
|
set_x (a_x: INTEGER)
|
|
-- Set `x' to `an_x'.
|
|
local
|
|
a_delta_x: INTEGER
|
|
do
|
|
a_delta_x := a_x - x
|
|
if a_delta_x /= 0 then
|
|
projection_matrix.translate (a_delta_x, 0)
|
|
recursive_transform (projection_matrix)
|
|
if is_in_group and then attached group as l_group and then l_group.is_center_valid then
|
|
l_group.center_invalidate
|
|
end
|
|
end
|
|
center.set_x (a_x)
|
|
is_center_valid := True
|
|
end
|
|
|
|
set_y (a_y: INTEGER)
|
|
-- Set `y' to `an_y'.
|
|
local
|
|
a_delta_y: INTEGER
|
|
do
|
|
a_delta_y := a_y - y
|
|
if a_delta_y /= 0 then
|
|
projection_matrix.translate (0, a_delta_y)
|
|
recursive_transform (projection_matrix)
|
|
if is_in_group and then attached group as l_group and then l_group.is_center_valid then
|
|
l_group.center_invalidate
|
|
end
|
|
end
|
|
center.set_y (a_y)
|
|
is_center_valid := True
|
|
end
|
|
|
|
set_x_y (a_x, a_y: INTEGER)
|
|
-- Set `x' to `an_x'.
|
|
local
|
|
a_delta_x, a_delta_y: INTEGER
|
|
do
|
|
a_delta_x := a_x - x
|
|
a_delta_y := a_y - y
|
|
if a_delta_x /= 0 or a_delta_y /= 0 then
|
|
projection_matrix.translate (a_delta_x, a_delta_y)
|
|
recursive_transform (projection_matrix)
|
|
if is_in_group and then attached group as l_group and then l_group.is_center_valid then
|
|
l_group.center_invalidate
|
|
end
|
|
end
|
|
center.set (a_x, a_y)
|
|
is_center_valid := True
|
|
end
|
|
|
|
set_point_position (a_x, a_y: INTEGER)
|
|
-- Set position of `point' to (`a_x', `a_y').
|
|
local
|
|
a_delta_x, a_delta_y: DOUBLE
|
|
do
|
|
a_delta_x := a_x - point_array [0].x_precise
|
|
a_delta_y := a_y - point_array [0].y_precise
|
|
if a_delta_x /= 0 or a_delta_y /= 0 then
|
|
projection_matrix.translate (a_delta_x, a_delta_y)
|
|
recursive_transform (projection_matrix)
|
|
if is_center_valid then
|
|
center_invalidate
|
|
end
|
|
end
|
|
end
|
|
|
|
ungroup
|
|
-- Ungroup all `figures'.
|
|
require
|
|
is_grouped: is_grouped
|
|
not_is_in_group: not is_in_group
|
|
do
|
|
from
|
|
start
|
|
until
|
|
after
|
|
loop
|
|
item.set_group (Void)
|
|
forth
|
|
end
|
|
is_grouped := False
|
|
current_angle := 0
|
|
center_invalidate
|
|
ensure
|
|
is_ungrouped: not is_grouped
|
|
none_is_in_a_group: not there_exists (agent {EV_MODEL}.is_in_group)
|
|
center_is_invalid: not is_center_valid
|
|
end
|
|
|
|
regroup
|
|
-- Group the `figures' in the group.
|
|
require
|
|
not_is_grouped: not is_grouped
|
|
not_is_in_group: not is_in_group
|
|
do
|
|
from
|
|
start
|
|
until
|
|
after
|
|
loop
|
|
item.set_group (Current)
|
|
forth
|
|
end
|
|
is_grouped := True
|
|
center_invalidate
|
|
ensure
|
|
is_grouped: is_grouped
|
|
all_grouped: for_all (agent {EV_MODEL}.is_in_group)
|
|
center_is_invalid: not is_center_valid
|
|
end
|
|
|
|
-- jjj send_backward (a_figure: EV_MODEL)
|
|
send_backward (a_figure: like item) -- so I could redefine `item' in my worlds
|
|
-- Send `a_figure' one layer backwards.
|
|
require
|
|
a_figure_in_figures: has (a_figure)
|
|
do
|
|
if first /= a_figure then
|
|
start
|
|
search (a_figure)
|
|
swap (index - 1)
|
|
end
|
|
full_redraw
|
|
ensure
|
|
a_figure_in_group: a_figure.group = Current
|
|
a_figure_in_current: has (a_figure)
|
|
end
|
|
|
|
-- jjj bring_forward (a_figure: EV_MODEL)
|
|
bring_forward (a_figure: like item) -- so I could redefine `item' in my worlds
|
|
-- Bring `a_figure' one layer forwards.
|
|
require
|
|
a_figure_in_figures: has (a_figure)
|
|
do
|
|
if last /= a_figure then
|
|
start
|
|
search (a_figure)
|
|
swap (index + 1)
|
|
end
|
|
full_redraw
|
|
ensure
|
|
a_figure_in_group: a_figure.group = Current
|
|
a_figure_in_current: has (a_figure)
|
|
end
|
|
|
|
-- jjj send_to_back (a_figure: EV_MODEL)
|
|
send_to_back (a_figure: like item)
|
|
-- Send `a_figure' to the bottom most layer.
|
|
-- I redefined this because `item' gets redefined in
|
|
-- my classes.
|
|
require
|
|
a_figure_in_figures: has (a_figure)
|
|
do
|
|
if first /= a_figure then
|
|
start
|
|
search (a_figure)
|
|
remove
|
|
put_front (a_figure)
|
|
end
|
|
full_redraw
|
|
ensure
|
|
is_at_front: first = a_figure
|
|
a_figure_in_group: a_figure.group = Current
|
|
a_figure_in_current: has (a_figure)
|
|
end
|
|
|
|
-- jjj bring_to_front (a_figure: EV_MODEL)
|
|
bring_to_front (a_figure: like item)
|
|
-- Bring `a_figure' to the top most layer
|
|
-- I redefined this because `item' gets redefined in
|
|
-- my classes.
|
|
require
|
|
a_figure_in_figures: has (a_figure)
|
|
do
|
|
if last /= a_figure then
|
|
start
|
|
search (a_figure)
|
|
remove
|
|
extend (a_figure)
|
|
end
|
|
full_redraw
|
|
ensure
|
|
is_last: last = a_figure
|
|
a_figure_in_group: a_figure.group = Current
|
|
a_figure_in_current: has (a_figure)
|
|
end
|
|
|
|
-- jjj added feature
|
|
send_to_index (fig: like item; a_index: INTEGER)
|
|
-- Feature added to this override class that places `a_figure'
|
|
-- at the position indicated by `a_index'
|
|
require
|
|
a_figure_in_figures: has (fig)
|
|
do
|
|
if a_index <= 1 then
|
|
send_to_back (fig)
|
|
elseif a_index >= count then
|
|
bring_to_front (fig)
|
|
else
|
|
start
|
|
search (fig)
|
|
remove
|
|
-- The following code was copied from `extend'; instead of
|
|
-- callin Precursor {ARRAYED_LIST} we use `put_i_th'
|
|
lookup_table.put (fig, fig.id)
|
|
-- Precursor {ARRAYED_LIST} (fig)
|
|
go_i_th (a_index)
|
|
put_left (fig)
|
|
fig.set_group (Current)
|
|
center_invalidate
|
|
invalidate
|
|
full_redraw
|
|
end
|
|
end
|
|
|
|
rotate (an_angle: DOUBLE)
|
|
-- Rotate around the center for `an_angle'.
|
|
do
|
|
current_angle := current_angle + an_angle
|
|
Precursor {EV_MODEL} (an_angle)
|
|
ensure then
|
|
angle_equal_an_angle: angle = old angle + an_angle
|
|
end
|
|
|
|
feature -- List change
|
|
|
|
insert (fig: like item; i: INTEGER)
|
|
-- Add `fig' to the group.
|
|
do
|
|
lookup_table.put (fig, fig.id)
|
|
Precursor {ARRAYED_LIST} (fig, i)
|
|
fig.set_group (Current)
|
|
center_invalidate
|
|
invalidate
|
|
full_redraw
|
|
ensure then
|
|
fig_in_lookup_table: fig /= Void implies lookup_table.has (fig.id)
|
|
fig_in_group: fig /= Void implies fig.group = Current
|
|
end
|
|
|
|
extend (fig: like item)
|
|
-- Add `fig' to the group.
|
|
do
|
|
lookup_table.put (fig, fig.id)
|
|
Precursor {ARRAYED_LIST} (fig)
|
|
fig.set_group (Current)
|
|
center_invalidate
|
|
invalidate
|
|
full_redraw
|
|
ensure then
|
|
fig_in_lookup_table: fig /= Void implies lookup_table.has (fig.id)
|
|
fig_in_group: fig /= Void implies fig.group = Current
|
|
end
|
|
|
|
force (fig: like item)
|
|
-- Add `fig' to the group.
|
|
do
|
|
lookup_table.put (fig, fig.id)
|
|
Precursor {ARRAYED_LIST} (fig)
|
|
fig.set_group (Current)
|
|
center_invalidate
|
|
invalidate
|
|
full_redraw
|
|
ensure then
|
|
fig_in_lookup_table: fig /= Void implies lookup_table.has (fig.id)
|
|
fig_in_group: fig /= Void implies fig.group = Current
|
|
end
|
|
|
|
replace (fig: like item)
|
|
-- Replace current item by `fig'.
|
|
do
|
|
item.unreference_group
|
|
lookup_table.remove (item.id)
|
|
Precursor {ARRAYED_LIST} (fig)
|
|
fig.set_group (Current)
|
|
lookup_table.put (fig, fig.id)
|
|
center_invalidate
|
|
invalidate
|
|
full_redraw
|
|
ensure then
|
|
fig_in_lookup_table: fig /= Void implies lookup_table.has (fig.id)
|
|
item_not_in_lookup_table: not lookup_table.has (old item.id)
|
|
fig_in_group: fig /= Void implies fig.group = Current
|
|
item_not_in_group: not (old item).is_in_group
|
|
end
|
|
|
|
remove
|
|
-- Remove `item' from figure.
|
|
do
|
|
item.unreference_group
|
|
lookup_table.remove (item.id)
|
|
Precursor {ARRAYED_LIST}
|
|
center_invalidate
|
|
invalidate
|
|
full_redraw
|
|
ensure then
|
|
item_not_in_lookup_table: not lookup_table.has (old item.id)
|
|
item_not_in_group: not (old item).is_in_group
|
|
end
|
|
|
|
prune_all (fig: like item)
|
|
-- Remove `fig' from the group.
|
|
do
|
|
if has (fig) then
|
|
fig.unreference_group
|
|
lookup_table.remove (fig.id)
|
|
end
|
|
Precursor {ARRAYED_LIST} (fig)
|
|
center_invalidate
|
|
invalidate
|
|
full_redraw
|
|
ensure then
|
|
item_not_in_lookup_table: fig /= Void implies not lookup_table.has (fig.id)
|
|
end
|
|
|
|
merge_left (other: ARRAYED_LIST [EV_MODEL])
|
|
-- Merge `other' into group before cursor.
|
|
-- `other' will be empty afterwards.
|
|
do
|
|
insert_list_to_table (other)
|
|
change_group (other)
|
|
Precursor {ARRAYED_LIST} (other)
|
|
center_invalidate
|
|
invalidate
|
|
full_redraw
|
|
end
|
|
|
|
merge_right (other: ARRAYED_LIST [EV_MODEL])
|
|
-- Merge `other' into group after cursor.
|
|
-- `other' will be empty afterwards.
|
|
do
|
|
insert_list_to_table (other)
|
|
change_group (other)
|
|
Precursor {ARRAYED_LIST} (other)
|
|
center_invalidate
|
|
invalidate
|
|
full_redraw
|
|
end
|
|
|
|
wipe_out
|
|
-- Remove all items.
|
|
do
|
|
from start until after loop
|
|
if item.is_in_group then
|
|
item.unreference_group
|
|
end
|
|
forth
|
|
end
|
|
Precursor {ARRAYED_LIST}
|
|
lookup_table.wipe_out
|
|
center_invalidate
|
|
invalidate
|
|
full_redraw
|
|
end
|
|
|
|
append (s: SEQUENCE [EV_MODEL])
|
|
-- append (s: SEQUENCE [like item])
|
|
-- Append a copy of `s'.
|
|
local
|
|
l: like s
|
|
l_cursor: CURSOR
|
|
do
|
|
if s = Current then
|
|
l := s.twin
|
|
else
|
|
l := s
|
|
end
|
|
from
|
|
resize (count + s.count)
|
|
l_cursor := cursor
|
|
l.start
|
|
until
|
|
l.exhausted
|
|
loop
|
|
extend (l.item)
|
|
lookup_table.put (l.item, l.item.id)
|
|
l.forth
|
|
end
|
|
go_to (l_cursor)
|
|
center_invalidate
|
|
invalidate
|
|
full_redraw
|
|
end
|
|
|
|
-- jjj make_from_array (a: ARRAY [EV_MODEL])
|
|
make_from_array (a: ARRAY [like item])
|
|
-- Create list from array `a'.
|
|
local
|
|
i: INTEGER
|
|
do
|
|
wipe_out
|
|
resize (a.count)
|
|
from
|
|
i := a.lower
|
|
until
|
|
i > a.upper
|
|
loop
|
|
if a.item (i) /= Void then
|
|
extend (a.item (i))
|
|
end
|
|
i := i + 1
|
|
end
|
|
center_invalidate
|
|
invalidate
|
|
full_redraw
|
|
end
|
|
|
|
swap (i: INTEGER)
|
|
-- Exchange item at `i'-th position with item
|
|
-- at cursor position.
|
|
local
|
|
old_item: like item
|
|
do
|
|
old_item := item
|
|
Precursor {ARRAYED_LIST} (i)
|
|
lookup_table.put (old_item, old_item.id)
|
|
old_item.set_group (Current)
|
|
ensure then
|
|
item_in_lookup_table: lookup_table.has (old item.id)
|
|
i_in_lookup_table: lookup_table.has (i_th (i).id)
|
|
item_in_group: (old item).group = Current
|
|
i_th_in_group: i_th (i).group = Current
|
|
end
|
|
|
|
feature -- Status settings
|
|
|
|
invalidate
|
|
-- Some property of `Current' has changed.
|
|
local
|
|
l_area: like area
|
|
i, nb: INTEGER
|
|
do
|
|
if valid then
|
|
Precursor {EV_MODEL}
|
|
from
|
|
l_area := area
|
|
i := 0
|
|
nb := count - 1
|
|
until
|
|
i > nb
|
|
loop
|
|
if l_area [i].valid then
|
|
l_area [i].invalidate
|
|
end
|
|
i := i + 1
|
|
end
|
|
else
|
|
Precursor {EV_MODEL}
|
|
end
|
|
end
|
|
|
|
validate
|
|
-- Validate `Current'.
|
|
local
|
|
l_area: like area
|
|
i, nb: INTEGER
|
|
l_figure: EV_MODEL
|
|
l_rect: detachable EV_RECTANGLE
|
|
do
|
|
if not valid then
|
|
if count > 0 then
|
|
create l_rect
|
|
l_area := area
|
|
from
|
|
i := 0
|
|
nb := count - 1
|
|
until
|
|
i > nb
|
|
loop
|
|
l_figure := l_area.item (i)
|
|
if not l_figure.valid then
|
|
l_figure.validate
|
|
end
|
|
i := i + 1
|
|
end
|
|
if world = Current then
|
|
-- We do not want the origin of the world to be included in the update.
|
|
l_rect := calculated_bounding_box
|
|
if l_rect = Void then
|
|
create l_rect
|
|
end
|
|
else
|
|
update_rectangle_to_bounding_box (l_rect)
|
|
end
|
|
if internal_invalid_rectangle /= Void then
|
|
internal_invalid_rectangle.copy (l_rect)
|
|
else
|
|
internal_invalid_rectangle := l_rect
|
|
end
|
|
elseif internal_invalid_rectangle /= Void then
|
|
-- Reset any previous invalid rectangle.
|
|
internal_invalid_rectangle.move_and_resize (0, 0, 0, 0)
|
|
end
|
|
valid := True
|
|
end
|
|
end
|
|
|
|
feature -- Events
|
|
|
|
position_on_figure (a_x, a_y: INTEGER): BOOLEAN
|
|
-- Is the point on (`a_x', `a_y') on this figure?
|
|
--| Used to generate events.
|
|
-- Always returns `False', but descendants can override
|
|
-- it to improve efficiency.
|
|
do
|
|
Result := False
|
|
end
|
|
|
|
bounding_box: EV_RECTANGLE
|
|
-- Smallest orthogonal rectangular area `Current' fits in.
|
|
local
|
|
l_result: detachable EV_RECTANGLE
|
|
do
|
|
if attached internal_bounding_box as l_internal_bounding_box and then l_internal_bounding_box.has_area then
|
|
Result := l_internal_bounding_box.twin
|
|
else
|
|
l_result := calculated_bounding_box
|
|
if world = Current then
|
|
-- If `Current' is the world then we need then we need the origin to be included so that its size is remembered.
|
|
create Result.make (point_x, point_y, 0, 0)
|
|
if l_result /= Void then
|
|
Result.merge (l_result)
|
|
end
|
|
else
|
|
if l_result /= Void then
|
|
Result := l_result
|
|
else
|
|
create Result
|
|
end
|
|
end
|
|
|
|
if attached internal_bounding_box as l_internal_bounding_box then
|
|
l_internal_bounding_box.copy (Result)
|
|
else
|
|
internal_bounding_box := Result.twin
|
|
end
|
|
end
|
|
end
|
|
|
|
feature {EV_MODEL_GROUP} -- Figure group
|
|
|
|
recursive_transform (a_transformation: EV_MODEL_TRANSFORMATION)
|
|
-- Same as transform but without precondition
|
|
-- is_transformable and without invalidating
|
|
-- groups center
|
|
local
|
|
l_area: like area
|
|
i, nb: INTEGER
|
|
do
|
|
a_transformation.project (point_array.item (0))
|
|
if is_grouped then
|
|
from
|
|
i := 0
|
|
nb := count - 1
|
|
l_area := area
|
|
until
|
|
i > nb
|
|
loop
|
|
l_area.item (i).recursive_transform (a_transformation)
|
|
i := i + 1
|
|
end
|
|
end
|
|
invalidate
|
|
is_center_valid := False
|
|
end
|
|
|
|
feature {NONE} -- Implementation
|
|
|
|
calculated_bounding_box: detachable EV_RECTANGLE
|
|
-- Smallest orthogonal rectangular area `Current' fits in.
|
|
do
|
|
if is_grouped then
|
|
create Result
|
|
update_rectangle_to_calculated_bounding_box (Result)
|
|
end
|
|
end
|
|
|
|
update_rectangle_to_calculated_bounding_box (a_rectangle: EV_RECTANGLE)
|
|
-- Smallest orthogonal rectangular area `Current' fits in.
|
|
local
|
|
l_area: like area
|
|
i, nb: INTEGER
|
|
l_bbox: like internal_bounding_box
|
|
l_initial: BOOLEAN
|
|
do
|
|
if is_grouped then
|
|
from
|
|
create l_bbox
|
|
l_initial := True
|
|
l_area := area
|
|
i := 0
|
|
nb := count - 1
|
|
until
|
|
i > nb
|
|
loop
|
|
if l_area.item (i).is_show_requested then
|
|
l_area [i].update_rectangle_to_bounding_box (l_bbox)
|
|
if l_bbox.width > 0 and then l_bbox.height > 0 then
|
|
if l_initial then
|
|
a_rectangle.copy (l_bbox)
|
|
l_initial := False
|
|
else
|
|
a_rectangle.merge (l_bbox)
|
|
end
|
|
end
|
|
end
|
|
i := i + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
current_angle: DOUBLE
|
|
-- The rotating angle.
|
|
|
|
set_center
|
|
-- Set x and y such that they are in the
|
|
-- center of the group.
|
|
local
|
|
l_bbox: like bounding_box
|
|
do
|
|
if is_grouped then
|
|
l_bbox := bounding_box
|
|
center.set_precise (l_bbox.left + l_bbox.width /2, l_bbox.top + l_bbox.height / 2)
|
|
else
|
|
center.set (0, 0)
|
|
end
|
|
is_center_valid := True
|
|
end
|
|
|
|
initiale_size: INTEGER = 5
|
|
-- Initialize size of `Current'.
|
|
|
|
change_group (other: ARRAYED_LIST [EV_MODEL])
|
|
-- Change group of all figures in `other' to Current.
|
|
-- Used by `merge_left' and `merge_right'.
|
|
local
|
|
n: INTEGER
|
|
do
|
|
from
|
|
n := 1
|
|
until
|
|
n > other.count
|
|
loop
|
|
other.i_th (n).set_group (Current)
|
|
n := n + 1
|
|
end
|
|
end
|
|
|
|
full_redraw
|
|
-- Request `invalid_rectangle' to be ignored.
|
|
local
|
|
w: detachable EV_MODEL_WORLD
|
|
do
|
|
w := world
|
|
if w /= Void then
|
|
w.full_redraw
|
|
end
|
|
end
|
|
|
|
lookup_table: HASH_TABLE [EV_MODEL, INTEGER]
|
|
-- Lookup table to search faster.
|
|
|
|
insert_list_to_table (list: ARRAYED_LIST [EV_MODEL])
|
|
-- Insert list element to lookup_table.
|
|
do
|
|
from
|
|
list.start
|
|
until
|
|
list.after
|
|
loop
|
|
lookup_table.put (list.item, list.item.id)
|
|
list.forth
|
|
end
|
|
end
|
|
|
|
invariant
|
|
|
|
is_grouped_implies_all_grouped: is_grouped implies for_all (agent {EV_MODEL}.is_in_group)
|
|
angle_equal_current_angle: angle = current_angle
|
|
not_is_grouped_implies_angel_equals_zero: not is_grouped implies (angle = 0)
|
|
|
|
note
|
|
copyright: "Copyright (c) 1984-2006, Eiffel Software and others"
|
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
|
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 -- class EV_MODEL_GROUP
|
|
|
|
|
|
|
|
|
|
|
|
|