This commit is contained in:
Jocelyn Fiat
2024-06-17 09:09:33 +02:00
commit 6dde6425c2
560 changed files with 81728 additions and 0 deletions

View File

@@ -0,0 +1,303 @@
note
description: "[
An EV_FIGURE_ELLIPTIC is defined by pa and pb
and not rotatable. If you need a rotatable elliptic
use a EV_FIGURE_ROTATED_ELLIPTIC but if not elliptic
is a lot faster.
pa-----------
| |
| |
| center |
| |
| |
----------- pb
radius1 is half horizontal distance between pa and pb.
radius2 is half vertical distance between pa and pb.
]"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date: 2013-04-25 18:08:32 -0400 (Thu, 25 Apr 2013) $"
revision: "$Revision: 33 $"
deferred class
EV_MODEL_ELLIPTIC
inherit
EV_MODEL_ATOMIC
export
{ANY} Pi
undefine
point_count
redefine
default_create,
bounding_box
end
EV_MODEL_DOUBLE_POINTED
undefine
default_create
end
feature {NONE} -- Initialization
default_create
-- Create a EV_FIGURE_ELLIPTIC at (0,0) with no dimension.
do
Precursor {EV_MODEL_ATOMIC}
create point_array.make_empty (2)
point_array.extend (create {EV_COORDINATE}.make (0, 0))
point_array.extend (create {EV_COORDINATE}.make (0, 0))
is_center_valid := True
end
feature -- Access
angle: DOUBLE = 0.0
-- Since not rotatable.
is_scalable: BOOLEAN
-- Elliptic is scalable.
do
Result := True
end
is_rotatable: BOOLEAN
-- Elliptic is not rotatable.
-- (Use a rotatable_elliptic)
do
-- jjj Result := False
Result := True
end
is_transformable: BOOLEAN
-- Elliptic is not transformable.
do
-- jjj Result := False
Result := True
end
radius1: INTEGER
-- The horizontal radius.
local
l_point_array: like point_array
p0, p1: EV_COORDINATE
do
l_point_array := point_array
p0 := l_point_array.item (0)
p1 := l_point_array.item (1)
Result := as_integer ((p0.x_precise - p1.x_precise) / 2).abs
end
radius2: INTEGER
-- The vertical radius.
local
l_point_array: like point_array
p0, p1: EV_COORDINATE
do
l_point_array := point_array
p0 := l_point_array.item (0)
p1 := l_point_array.item (1)
Result := as_integer ((p0.y_precise - p1.y_precise) / 2).abs
end
point_a_x: INTEGER
-- x position of `point_b'.
do
Result := point_array.item (0).x
end
point_a_y: INTEGER
-- y position of `point_b'.
do
Result := point_array.item (0).y
end
point_b_x: INTEGER
-- x position of `point_b'.
do
Result := point_array.item (1).x
end
point_b_y: INTEGER
-- y position of `point_b'.
do
Result := point_array.item (1).y
end
feature -- Element change
set_radius1 (radius: INTEGER)
-- Set `radius1' to `radius'.
require
radius_positive: radius >= 0
local
l_point_array: like point_array
p0, p1: EV_COORDINATE
cx: DOUBLE
do
l_point_array := point_array
p0 := l_point_array.item (0)
p1 := l_point_array.item (1)
cx := (p0.x_precise + p1.x_precise) / 2
p0.set_x_precise (cx - radius)
p1.set_x_precise (cx + radius)
invalidate
center_invalidate
ensure
set: radius1 = radius
end
set_radius2 (radius: INTEGER)
-- Set `radius2' to `radius'.
require
radius_positive: radius >= 0
local
l_point_array: like point_array
p0, p1: EV_COORDINATE
cy: DOUBLE
do
l_point_array := point_array
p0 := l_point_array.item (0)
p1 := l_point_array.item (1)
cy := (p0.y_precise + p1.y_precise) / 2
p0.set_y_precise (cy - radius)
p1.set_y_precise (cy + radius)
invalidate
center_invalidate
ensure
set: radius2 = radius
end
set_radius1_and_radius2 (a_radius1, a_radius2: INTEGER)
-- Set `radius1' to `a_radius1' and `radius2` to `a_radius2'.
require
radius1_positive: a_radius1 >= 0
radius2_positive: a_radius2 >= 0
local
l_point_array: like point_array
p0, p1: EV_COORDINATE
cx, cy: DOUBLE
do
l_point_array := point_array
p0 := l_point_array.item (0)
p1 := l_point_array.item (1)
cx := (p0.x_precise + p1.x_precise) / 2
cy := (p0.y_precise + p1.y_precise) / 2
p0.set_x_precise (cx - a_radius1)
p1.set_x_precise (cx + a_radius1)
p0.set_y_precise (cy - a_radius2)
p1.set_y_precise (cy + a_radius2)
invalidate
center_invalidate
ensure
set: radius1 = a_radius1 and radius2 = a_radius2
end
set_point_a_position (ax, ay: INTEGER)
-- Set position of `point_a' to position of (`ax', `ay').
do
point_array.item (0).set_precise (ax, ay)
invalidate
center_invalidate
end
set_point_b_position (ax, ay: INTEGER)
-- Set position of `point_b' to position of (`ax', `ay').
do
point_array.item (1).set_precise (ax, ay)
invalidate
center_invalidate
end
feature -- Events
bounding_box: EV_RECTANGLE
-- Smallest orthegonal rectangle `Current' fits in.
local
min_x, min_y, max_x, max_y, lw2, v1, v2: DOUBLE
lx, ly, w, h: INTEGER
l_point_array: like point_array
pa, pb: EV_COORDINATE
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_point_array := point_array
pa := l_point_array.item (0)
pb := l_point_array.item (1)
v1 := pa.x_precise
v2 := pb.x_precise
min_x := v1.min (v2)
max_x := v1.max (v2)
v1 := pa.y_precise
v2 := pb.y_precise
min_y := v1.min (v2)
max_y := v1.max (v2)
check
max_x >= min_x
max_y >= min_y
end
lw2 := line_width / 2
lx := as_integer (min_x - lw2)
ly := as_integer (min_y - lw2)
w := as_integer ((max_x - min_x) + lw2) + 1
h := as_integer ((max_y - min_y) + lw2) + 1
create Result.make (lx, ly, w, h)
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 {NONE} -- Implementation
set_center
-- Set position of the center.
local
l_point_array: like point_array
pa, pb: EV_COORDINATE
do
l_point_array := point_array
pa := l_point_array.item (0)
pb := l_point_array.item (1)
center.set_precise ((pa.x_precise + pb.x_precise) / 2, (pa.y_precise + pb.y_precise) / 2)
is_center_valid := True
end
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_ELLIPTIC

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,280 @@
note
description: "[
Pixmaps drawn on `point'.
p1 --------- p2
|............
|............
|............
p3
point.x = p1.x and point.y = p1.y
]"
legal: "See notice at end of class."
status: "See notice at end of class."
keywords: "figure, picture, pixmap"
date: "$Date: 2013-04-25 18:08:32 -0400 (Thu, 25 Apr 2013) $"
revision: "$Revision: 33 $"
class
EV_MODEL_PICTURE
inherit
EV_MODEL_ATOMIC
redefine
default_create,
recursive_transform,
default_line_width,
border_width
end
EV_MODEL_SINGLE_POINTED
undefine
default_create,
point_count
end
EV_SHARED_SCALE_FACTORY
undefine
default_create
end
create
default_create,
make_with_point,
make_with_pixmap,
make_with_identified_pixmap,
make_with_position
feature {NONE} -- Initialization
default_create
-- Create in (0, 0)
do
Precursor {EV_MODEL_ATOMIC}
pixmap_factory.register_pixmap (default_pixmap)
id_pixmap := default_pixmap
scaled_pixmap := pixmap
is_default_pixmap_used := True
create point_array.make_empty (3)
point_array.extend (create {EV_COORDINATE}.make (0, 0))
point_array.extend (create {EV_COORDINATE}.make (0, 0))
point_array.extend (create {EV_COORDINATE}.make (0, 0))
end
make_with_pixmap (a_pixmap: EV_PIXMAP)
-- Create with `a_pixmap'.
require
a_pixmap_not_void: a_pixmap /= Void
do
default_create
set_pixmap (a_pixmap)
end
make_with_identified_pixmap (an_id_pixmap: EV_IDENTIFIED_PIXMAP)
-- Create with `an_id_pixmap'.
require
an_id_pixmap_not_Void: an_id_pixmap /= Void
do
default_create
set_identified_pixmap (an_id_pixmap)
end
feature -- Access
pixmap: EV_PIXMAP
-- Pixmap that is displayed.
do
Result := id_pixmap.pixmap
end
angle: DOUBLE = 0.0
-- Since not rotatable
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
feature -- Status report
width: INTEGER
-- Width of pixmap.
do
Result := as_integer (point_array.item (1).x_precise - point_array.item (0).x_precise)
end
height: INTEGER
-- Height of Pixmap.
do
Result := as_integer (point_array.item (2).y_precise - point_array.item (0).y_precise)
end
is_default_pixmap_used: BOOLEAN
-- Is `Current' using a default pixmap?
-- jjj is_rotatable: BOOLEAN = False
is_rotatable: BOOLEAN = True
-- Is rotatable? (No)
is_scalable: BOOLEAN = True
-- Is scalable? (Yes)
-- jjj is_transformable: BOOLEAN = False
is_transformable: BOOLEAN = True
-- Is transformable? (No)
feature -- Visitor
project (a_projector: EV_MODEL_DRAWING_ROUTINES)
-- <Precursor>
do
a_projector.draw_figure_picture (Current)
end
feature -- Status setting
set_pixmap (a_pixmap: EV_PIXMAP)
-- Set `pixmap' to `a_pixmap'.
require
a_pixmap_not_void: a_pixmap /= Void
do
set_identified_pixmap (pixmap_factory.registered_pixmap (a_pixmap))
ensure
pixmap_assigned: pixmap = a_pixmap
end
set_identified_pixmap (an_id_pixmap: EV_IDENTIFIED_PIXMAP)
-- Set `id_pixmap' to `an_id_pixmap' and initialize `scaled_pixmap'.
require
an_id_pixmap_not_Void: an_id_pixmap /= Void
do
id_pixmap := an_id_pixmap
pixmap_factory.register_pixmap (id_pixmap)
scaled_pixmap := pixmap
is_default_pixmap_used := False
point_array.item (1).set_x_precise (point_array.item (0).x_precise + pixmap.width)
point_array.item (2).set_y_precise (point_array.item (0).y_precise + pixmap.height)
invalidate
center_invalidate
ensure
set: id_pixmap = an_id_pixmap
end
set_point_position (ax, ay: INTEGER)
-- Set position of `point' to `a_point'.
local
a_delta_x, a_delta_y: DOUBLE
l_point_array: like point_array
p0, p1, p2: EV_COORDINATE
do
l_point_array := point_array
p0 := l_point_array.item (0)
p1 := l_point_array.item (1)
p2 := l_point_array.item (2)
a_delta_x := ax - p0.x_precise
a_delta_y := ay - p0.y_precise
p0.set_precise (ax, ay)
p1.set_precise (p1.x_precise + a_delta_x, p1.y_precise + a_delta_y)
p2.set_precise (p2.x_precise + a_delta_x, p2.y_precise + a_delta_y)
invalidate
center_invalidate
end
feature -- Events
position_on_figure (a_x, a_y: INTEGER): BOOLEAN
-- Is (`a_x', `a_y') on this figure?
local
ax, ay: DOUBLE
p0: EV_COORDINATE
l_point_array: like point_array
do
l_point_array := point_array
p0 := l_point_array.item (0)
ax := p0.x_precise
ay := p0.y_precise
Result := point_on_rectangle (a_x, a_y, ax, ay, l_point_array.item (1).x_precise, l_point_array.item (2).y_precise)
end
feature {EV_MODEL_GROUP}
recursive_transform (a_transformation: EV_MODEL_TRANSFORMATION)
-- Same as transform but without precondition
-- is_transformable and without invalidating
-- groups center
do
Precursor {EV_MODEL_ATOMIC} (a_transformation)
update_scaled_pixmap
end
feature {EV_MODEL_DRAWER}
scaled_pixmap: like pixmap
-- Scaled version of `pixmap'.
feature {NONE} -- Implementation
id_pixmap: EV_IDENTIFIED_PIXMAP
default_pixmap: EV_IDENTIFIED_PIXMAP
-- Pixmap set by `default_create'.
once
Result := pixmap_factory.registered_pixmap (create {EV_PIXMAP})
pixmap_factory.register_pixmap (Result)
end
set_center
-- Set the center.
local
l_point_array: like point_array
p0: EV_COORDINATE
do
l_point_array := point_array
p0 := l_point_array.item (0)
center.set_precise ((p0.x_precise + l_point_array.item (1).x_precise) / 2, (p0.y_precise + l_point_array.item (2).y_precise) / 2)
is_center_valid := True
end
update_scaled_pixmap
-- Scale `pixmap' store result in `scaled_pixmap'.
do
if scaled_pixmap.width /= width or else scaled_pixmap.height /= height then
scaled_pixmap := pixmap_factory.scaled_pixmap (id_pixmap, width.max (1), height.max (1))
end
end
default_line_width: INTEGER = 0
-- <Precursor>
border_width: INTEGER = 0
-- <Precursor>
invariant
pixmap_exists: pixmap /= Void
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_PICTURE

View File

@@ -0,0 +1,374 @@
note
description: "[
`text's in a `font' displayed on p0 == point.
p0---------------------------p2
|fooooooooooooooooooooooooooo
| p3
|bar center
|foobar
p1
p3.y - p0.y is the should height of a character to match scale
p3.x - p0.x is the should width of a character to match scale
]"
legal: "See notice at end of class."
status: "See notice at end of class."
keywords: "figure, text, string"
date: "$Date: 2013-04-25 18:08:32 -0400 (Thu, 25 Apr 2013) $"
revision: "$Revision: 33 $"
class
EV_MODEL_TEXT
inherit
EV_MODEL_ATOMIC
undefine
is_equal
redefine
default_create,
recursive_transform,
default_line_width,
border_width
end
EV_FONT_CONSTANTS
export
{NONE} all
{ANY} valid_family, valid_weight, valid_shape
undefine
default_create,
out,
is_equal
end
EV_MODEL_SINGLE_POINTED
undefine
default_create,
point_count,
is_equal
end
COMPARABLE
undefine
default_create
end
EV_SHARED_SCALE_FACTORY
undefine
default_create,
is_equal
end
create
default_create,
make_with_text,
make_with_position
feature {NONE} -- Initialization
default_create
-- Create in (0, 0)
do
Precursor {EV_MODEL_ATOMIC}
create point_array.make_empty (4)
point_array.extend (create {EV_COORDINATE})
point_array.extend (create {EV_COORDINATE})
point_array.extend (create {EV_COORDINATE})
create {STRING_32} text.make_empty
id_font := default_font
scaled_font := font
point_array.extend (create {EV_COORDINATE}.make (font.width, font.height))
is_default_font_used := True
is_center_valid := True
ensure then
center_is_valid: is_center_valid
end
make_with_text (a_text: READABLE_STRING_GENERAL)
-- Create with `a_text'.
require
a_text_not_void: a_text /= Void
do
default_create
set_text (a_text)
set_center
ensure
center_is_valid: is_center_valid
end
feature -- Access
text: STRING_32
-- Text that is displayed.
font: EV_FONT
-- Typeface `text' is displayed in.
do
Result := id_font.font
end
angle: DOUBLE = 0.0
-- Since not rotatable.
is_scalable: BOOLEAN = True
-- Is scalable? (Yes)
--jjj is_rotatable: BOOLEAN = False
is_rotatable: BOOLEAN = True
-- Not yet.
-- jjj is_transformable: BOOLEAN = False
is_transformable: BOOLEAN = True
-- No.
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
feature -- Status report
width: INTEGER
-- Horizontal dimension.
local
l_point_array: like point_array
do
l_point_array := point_array
Result := as_integer (l_point_array.item (2).x_precise - l_point_array.item (0).x_precise)
end
height: INTEGER
-- Vertical dimension.
local
l_point_array: like point_array
do
l_point_array := point_array
Result := as_integer (l_point_array.item (1).y_precise - l_point_array.item (0).y_precise)
end
is_default_font_used: BOOLEAN
-- Is `Current' using a default font?
is_less alias "<" (other: like Current): BOOLEAN
-- Is current object less than `other'?
do
Result := text < other.text
end
feature -- Visitor
project (a_projector: EV_MODEL_DRAWING_ROUTINES)
-- <Precursor>
do
a_projector.draw_figure_text (Current)
end
feature -- Status setting
set_point_position (ax, ay: INTEGER)
-- Set position of `point' to (`ax', `ay').
local
a_delta_x, a_delta_y: DOUBLE
l_point_array: like point_array
p0, p1, p2, p3: EV_COORDINATE
do
l_point_array := point_array
p0 := l_point_array.item (0)
p1 := l_point_array.item (1)
p2 := l_point_array.item (2)
p3 := l_point_array.item (3)
a_delta_x := ax - p0.x_precise
a_delta_y := ay - p0.y_precise
p0.set (ax, ay)
p1.set_precise (p1.x_precise + a_delta_x, p1.y_precise + a_delta_y)
p2.set_precise (p2.x_precise + a_delta_x, p2.y_precise + a_delta_y)
p3.set_precise (p3.x_precise + a_delta_x, p3.y_precise + a_delta_y)
invalidate
center_invalidate
end
set_font (a_font: like font)
-- Assign `a_font' to `font'.
require
a_font_not_void: a_font /= Void
do
set_identified_font (font_factory.registered_font (a_font))
ensure
font_assigned: font = a_font
end
set_identified_font (an_id_font: EV_IDENTIFIED_FONT)
-- Set `id_font' to `an_id_font' initialize `scaled_font'.
require
an_id_font_not_Void: an_id_font /= Void
local
l_point_array: like point_array
p0: EV_COORDINATE
should_height, real_height, scale_factor: DOUBLE
do
real_height := id_font.font.height
id_font := an_id_font
font_factory.register_font (id_font)
l_point_array := point_array
should_height := l_point_array.item (3).y_precise - l_point_array.item (0).y_precise
scale_factor := should_height / real_height
scaled_font := font_factory.scaled_font (id_font, as_integer (id_font.font.height * scale_factor).max (1))
p0 := l_point_array.item (0)
l_point_array.item (3).set_precise (p0.x_precise + scaled_font.width, p0.y_precise + scaled_font.height)
update_dimensions
invalidate
center_invalidate
ensure
set: id_font = an_id_font
end
set_text (a_text: READABLE_STRING_GENERAL)
-- Assign `a_text' to `text'.
require
a_text_not_void: a_text /= Void
do
text := a_text.as_string_32
update_dimensions
invalidate
ensure
text_assigned: text.same_string_general (a_text)
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.
local
l_point_array: like point_array
p0: EV_COORDINATE
do
l_point_array := point_array
p0 := l_point_array.item (0)
Result := point_on_rectangle (a_x, a_y, p0.x_precise, p0.y_precise, l_point_array.item (2).x_precise, l_point_array.item (1).y_precise)
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_font: like font
l_point_array: like point_array
should_height: INTEGER
do
Precursor {EV_MODEL_ATOMIC} (a_transformation)
l_font := scaled_font
l_point_array := point_array
should_height := as_integer (l_point_array.item (3).y_precise - l_point_array.item (0).y_precise).max (1)
if should_height /= l_font.height then
scaled_font := font_factory.scaled_font (id_font, should_height)
if should_height > 1 then
update_dimensions
end
end
end
feature {EV_MODEL_DRAWER}
scaled_font: like font
left_offset: INTEGER
feature {NONE} -- Implementation
id_font: EV_IDENTIFIED_FONT
update_dimensions
-- Reassign `width' and `height'.
local
t: TUPLE [width: INTEGER; height: INTEGER; left_offset: INTEGER; right_offset: INTEGER]
l_point_array: like point_array
p0: EV_COORDINATE
do
t := scaled_font.string_size (text)
left_offset := t.left_offset
l_point_array := point_array
p0 := l_point_array.item (0)
l_point_array.item (1).set_y_precise (p0.y_precise + t.height)
l_point_array.item (2).set_x_precise (p0.x_precise + t.width - left_offset + t.right_offset)
center_invalidate
end
default_font: EV_IDENTIFIED_FONT
-- Font set by `default_create'.
local
l_font: EV_FONT
once
create l_font
Result := font_factory.registered_font (l_font)
font_factory.register_font (Result)
end
set_center
-- Set the position to the center
local
l_point_array: like point_array
p0, p1, p2: EV_COORDINATE
do
l_point_array := point_array
p0 := l_point_array.item (0)
p1 := l_point_array.item (1)
p2 := l_point_array.item (2)
center.set_precise ((p1.x_precise + p2.x_precise) / 2, (p1.y_precise + p2.y_precise) / 2)
is_center_valid := True
end
default_line_width: INTEGER = 0
-- <Precursor>
border_width: INTEGER = 0
-- <Precursor>
invariant
text_exists: text /= Void
font_exists: font /= Void
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_TEXT

View File

@@ -0,0 +1,707 @@
note
description:
"Projectors for widgets."
legal: "See notice at end of class."
status: "See notice at end of class."
keywords: "projector, events"
date: "$Date: 2023-11-29 10:19:43 +0100 (Wed, 29 Nov 2023) $"
revision: "$Revision: 107425 $"
deferred class
EV_MODEL_WIDGET_PROJECTOR
inherit
EV_MODEL_PROJECTOR
EV_MODEL_DRAWER
undefine
default_colors
end
EV_MODEL_PROJECTION_ROUTINES
EV_SHARED_APPLICATION
feature {NONE} -- Initialization
make_with_drawable_widget (a_world: like world; a_drawable: EV_DRAWABLE; a_widget: like widget)
-- Create with `a_world' and `a_drawable' (= `a_widget').
require
a_world_not_void: a_world /= Void
a_drawable_not_void: a_drawable /= Void
a_widget_not_void: a_widget /= Void
do
make_with_drawable (a_drawable)
-- This is only for letting users who have defined their own figure to still be
-- able to use the `register_figure'.
create draw_routines.make_filled (Void, 0, 20)
make_with_world (a_world)
widget := a_widget
project_agent := agent project
area_x := 0
area_y := 0
widget.pointer_motion_actions.extend (agent mouse_move)
widget.pointer_button_press_actions.extend (agent button_press)
widget.pointer_double_press_actions.extend (agent double_press)
widget.pointer_button_release_actions.extend (agent button_release)
widget.pointer_leave_actions.extend (agent pointer_leave)
widget.pick_actions.extend (agent on_pick_request)
widget.set_pebble_function (agent on_pebble_request)
widget.set_actual_drop_target_agent (agent on_drop_target_request)
end
make_with_drawable_widget_and_buffer (
a_world: like world;
a_drawable: EV_DRAWABLE;
a_buffer: EV_PIXMAP;
a_widget: like widget)
-- Create with `a_world', `a_drawable' (= `a_widget') and `a_buffer'.
require
a_world_not_void: a_world /= Void
a_drawable_not_void: a_drawable /= Void
a_buffer_not_void: a_buffer /= Void
a_widget_not_void: a_widget /= Void
do
make_with_drawable_widget (a_world, a_buffer, a_widget)
area := a_drawable
end
project_agent: detachable PROCEDURE note option: stable attribute end
-- Agent used for projection.
feature -- Access
widget: EV_WIDGET
-- `device' if conforms to EV_WIDGET.
-- `Void' otherwise.
area: detachable EV_DRAWABLE
-- Area associated with `widget'.
-- `Void' if no buffer is used.
area_x, area_y: INTEGER
-- Coordinates of top-left corner of displayed part of `drawable'.
-- (0, 0) when no buffer is used.
feature -- Status report
buffer_used: BOOLEAN
-- Is `drawable' only a buffer area for `area'?
do
Result := area /= Void
end
is_figure_selected: BOOLEAN
-- Was button pointer pressed on a figure?
feature -- Element change
change_area_position (a_x, a_y: INTEGER)
-- `area' has moved to (`a_x', `a_y') of `drawable'.
local
u: EV_RECTANGLE
l_area: like area
do
if buffer_used then
l_area := area
check l_area /= Void then end
area_x := a_x
area_y := a_y
create u.make (0, 0, l_area.width, l_area.height)
update_rectangle (u, 0, 0)
end
end
feature -- Basic operations
project
-- Make a standard projection of world on device.
local
a, e, u: detachable EV_RECTANGLE
do
if not is_projecting and then attached world as l_world then
is_projecting := True
if l_world.is_redraw_needed then
full_project
l_world.full_redraw_performed
else
e := l_world.invalid_rectangle
if e /= Void then
u := l_world.update_rectangle
if u /= Void then
e.merge (u)
end
a := area_bounding_box
if a /= Void then
-- Optimized projection to only project the viewable projection area.
e := a.intersection (a)
end
if e.has_area then
project_rectangle (e)
end
end
end
is_projecting := False
end
end
project_rectangle (u: EV_RECTANGLE)
-- Project area under `u'.
local
pixmap: detachable EV_PIXMAP
l_world: like world
do
l_world := world
check l_world /= Void then end
drawable.set_background_color (l_world.background_color)
drawable.set_anti_aliasing (l_world.is_anti_aliasing_enabled)
drawable.clear_rectangle (u.left, u.top, u.width, u.height)
if l_world.grid_visible then
draw_grid (l_world)
end
if l_world.is_show_requested then
project_figure_group (l_world, u)
end
if has_mouse then
change_current (figure_on_position (l_world, last_pointer_x,
last_pointer_y))
end
if l_world.points_visible then
draw_points (l_world)
end
l_world.validate
if buffer_used then
-- Flush `drawable' on `area'.
pixmap ?= drawable
if pixmap /= Void and then attached area as l_area then
l_area.draw_sub_pixmap (0, 0, pixmap, u)
end
end
end
full_project
-- Project entire area.
do
project_rectangle (drawable_bounding_box)
end
update_rectangle (u: EV_RECTANGLE; a_x, a_y: INTEGER)
-- Flush `u' on `area' at (`a_x', `a_y').
require
buffer_used: buffer_used
local
pixmap: detachable EV_PIXMAP
do
pixmap ?= drawable
if pixmap /= Void and then attached area as l_area then
u.set_x (u.x + area_x)
u.set_y (u.y + area_y)
l_area.draw_sub_pixmap (a_x, a_y, pixmap, u)
end
end
update
require
buffer_used: buffer_used
do
update_rectangle (create {EV_RECTANGLE}.make (0, 0, drawable.width, drawable.height), 0, 0)
end
clear_device
-- Erase entire canvas.
do
drawable.set_background_color (world.background_color)
drawable.clear
end
feature {NONE} -- Event implementation
current_figure: detachable EV_MODEL
-- Figure mouse is currently on.
--| To generate leave and enter actions.
last_pointer_x, last_pointer_y: INTEGER
-- Last mouse coordinates.
--| Used when world changes using `project'.
has_mouse: BOOLEAN
-- Does canvas have mouse on it?
figure_on_position (group: EV_MODEL_GROUP; x, y: INTEGER): detachable EV_MODEL
-- Figure mouse-cursor is on.
local
i: INTEGER
found_closed_figure: detachable EV_MODEL_CLOSED
l_model: EV_MODEL
do
if world.capture_figure /= Void then
Result := world.capture_figure
else
from
i := group.count
until
Result /= Void or else i < 1
loop
l_model := group [i]
if l_model.is_show_requested and l_model.is_sensitive then
if l_model.position_on_figure (x, y) then
Result := l_model
elseif attached {EV_MODEL_GROUP} l_model as grp then
Result := figure_on_position (grp, x, y)
end
if attached {EV_MODEL_CLOSED} Result as closed_figure and then closed_figure.background_color = Void then
-- is a not closed_figure under it?
Result := Void
if found_closed_figure = Void then
-- if not take the first closed_figure found.
found_closed_figure := closed_figure
end
end
end
i := i - 1
end
if Result = Void and then found_closed_figure /= Void then
Result := found_closed_figure
end
end
end
button_press (x, y, button: INTEGER; x_tilt, y_tilt, pressure: DOUBLE; screen_x, screen_y: INTEGER)
-- Pointer button down happened.
local
event_fig: detachable EV_MODEL
p: BOOLEAN
w_x, w_y: INTEGER
do
w_x := x + area_x
w_y := y + area_y
from
event_fig := figure_on_position (world, w_x, w_y)
if event_fig = Void then
event_fig := world
is_figure_selected := False
else
is_figure_selected := True
end
until
event_fig = Void
loop
if event_fig.is_show_requested and event_fig.is_sensitive and attached event_fig.internal_pointer_button_press_actions as l_actions then
l_actions.call ([w_x, w_y, button,x_tilt, y_tilt, pressure, screen_x, screen_y])
if event_fig.are_events_sent_to_group then
event_fig := event_fig.group
else
event_fig := Void
end
else
event_fig := event_fig.group
end
p := True
end
if p then
project
end
end
double_press (x, y, button: INTEGER; x_tilt, y_tilt, pressure: DOUBLE;
screen_x, screen_y: INTEGER)
-- Pointer double click happened.
local
event_fig: detachable EV_MODEL
p: BOOLEAN
w_x, w_y: INTEGER
do
w_x := x + area_x
w_y := y + area_y
from
event_fig := figure_on_position (world, w_x, w_y)
if event_fig = Void then
event_fig := world
end
until
event_fig = Void
loop
if event_fig.is_show_requested and event_fig.is_sensitive and attached event_fig.internal_pointer_double_press_actions as l_actions then
l_actions.call ([w_x, w_y, button,x_tilt, y_tilt, pressure, screen_x, screen_y])
if event_fig.are_events_sent_to_group then
event_fig := event_fig.group
else
event_fig := Void
end
else
event_fig := event_fig.group
end
p := True
end
if p then
project
end
end
button_release (x, y, button: INTEGER; x_tilt, y_tilt, pressure: DOUBLE;
screen_x, screen_y: INTEGER)
-- Pointer button up happened.
local
event_fig: detachable EV_MODEL
p: BOOLEAN
w_x, w_y: INTEGER
do
w_x := x + area_x
w_y := y + area_y
is_figure_selected := False
from
event_fig := figure_on_position (world, w_x, w_y)
if event_fig = Void then
event_fig := world
end
until
event_fig = Void
loop
if event_fig.is_show_requested and event_fig.is_sensitive and attached event_fig.internal_pointer_button_release_actions as l_actions then
l_actions.call ([w_x, w_y, button, x_tilt, y_tilt, pressure, screen_x, screen_y])
if event_fig.are_events_sent_to_group then
event_fig := event_fig.group
else
event_fig := Void
end
else
event_fig := event_fig.group
end
p := True
end
if p then
project
end
end
pointer_leave
-- Pointer left canvas.
do
has_mouse := False
end
has_focus (a_figure: EV_MODEL): BOOLEAN
-- Is mouse cursor on `a_figure'?
local
grp: detachable EV_MODEL_GROUP
do
if current_figure = a_figure then
Result := True
else
grp ?= a_figure
if grp /= Void then
from grp.start until Result or grp.after loop
Result := has_focus (grp.item)
grp.forth
end
end
end
end
change_current (new_current_figure: detachable EV_MODEL)
-- Change current to `new_focused_figure'.
--| Generate leave and/or enter events accordingly.
local
old_figure: detachable EV_MODEL
event_fig: detachable EV_MODEL
same_fig: detachable EV_MODEL
p: BOOLEAN
action: detachable EV_LITE_ACTION_SEQUENCE [TUPLE]
do
if current_figure /= new_current_figure then
if
new_current_figure /= Void and then
new_current_figure.is_show_requested and then
new_current_figure.is_sensitive and then
attached new_current_figure.pointer_style as l_new_current_figure_pointer_style
then
widget.set_pointer_style (l_new_current_figure_pointer_style)
else
widget.set_pointer_style (default_cursor)
end
old_figure := current_figure
current_figure := new_current_figure
if old_figure /= Void then
from
event_fig := old_figure
until
event_fig = Void or else has_focus (event_fig)
loop
action := event_fig.internal_pointer_leave_actions
if action /= Void and event_fig.is_show_requested and event_fig.is_sensitive then
action.call (Void)
if event_fig.are_events_sent_to_group then
event_fig := event_fig.group
else
event_fig := Void
end
else
event_fig := event_fig.group
end
p := True
end
end
same_fig := event_fig
if current_figure /= Void then
from
event_fig := current_figure
until
event_fig = Void or else event_fig = same_fig
loop
action := event_fig.internal_pointer_enter_actions
if action /= Void and event_fig.is_show_requested and event_fig.is_sensitive then
action.call (Void)
if event_fig.are_events_sent_to_group then
event_fig := event_fig.group
else
-- Exit loop
event_fig := same_fig
end
else
event_fig := event_fig.group
end
p := True
end
end
end
if p then
project
end
ensure
-- current_figure_assigned: current_figure = new_current_figure
end
mouse_move (x, y: INTEGER; x_tilt, y_tilt, pressure: DOUBLE;
screen_x, screen_y: INTEGER)
-- Fire events that belong to mouse movement.
--| i.e. leave, enter, motion.
local
event_fig: detachable EV_MODEL
p: BOOLEAN
w_x, w_y: INTEGER
do
if not is_projecting then
w_x := x + area_x
w_y := y + area_y
has_mouse := True
last_pointer_x := w_x
last_pointer_y := w_y
from
event_fig := figure_on_position (world, w_x, w_y)
change_current (event_fig)
if event_fig = Void then
event_fig := world
end
until
event_fig = Void
loop
if event_fig.is_show_requested and event_fig.is_sensitive and attached event_fig.internal_pointer_motion_actions as l_actions then
l_actions.call ([w_x, w_y, x_tilt, y_tilt, pressure, screen_x, screen_y])
p := p or else not event_fig.valid
if event_fig.are_events_sent_to_group then
event_fig := event_fig.group
else
event_fig := Void
end
else
event_fig := event_fig.group
end
end
if p or else not world.valid then
if project_agent /= Void then
ev_application.do_once_on_idle (project_agent)
end
end
end
end
on_pebble_request (a_x, a_y: INTEGER): detachable ANY
-- Pebble of current figure.
-- If figure is `Void', return pebble of world.
--| Because when a context menu is up, no events are sent
--| to the world, first simulate a mouse motion to update
--| the projection.
local
fig: detachable EV_MODEL
do
mouse_move (a_x, a_y, 0.0, 0.0, 0.0, 0, 0)
fig := current_figure
if fig = Void or else ev_application.ctrl_pressed then
Result := world.real_pebble (a_x, a_y)
elseif fig.is_show_requested and fig.is_sensitive then
from until Result /= Void or fig = Void loop
Result := fig.real_pebble (a_x, a_y)
if Result = Void then
fig := fig.group
end
end
if Result /= Void and then fig /= Void then
widget.set_accept_cursor (fig.accept_cursor)
widget.set_deny_cursor (fig.deny_cursor)
end
end
end
on_drop_target_request (a_x, a_y: INTEGER): detachable EV_ABSTRACT_PICK_AND_DROPABLE
-- Find actual drop target.
local
event_fig: detachable EV_MODEL
w_x, w_y: INTEGER
do
w_x := a_x + area_x
w_y := a_y + area_y
event_fig := figure_on_position (world, w_x, w_y)
if event_fig = Void and then not world.drop_actions.is_empty then
Result := world
else
from until Result /= Void or event_fig = Void loop
check event_fig /= Void end
if not event_fig.drop_actions.is_empty then
Result := event_fig
end
event_fig := event_fig.group
end
end
end
on_pick_request (a_x, a_y: INTEGER)
-- Pick event of current figure.
local
event_fig, fig: detachable EV_MODEL
do
event_fig := figure_on_position (world, a_x + area_x, a_y + area_y)
if
event_fig /= Void and then
event_fig.is_show_requested and then
event_fig.is_sensitive
then
from
until
fig /= Void or event_fig = Void
loop
check
event_fig /= Void
end
if not event_fig.pick_actions.is_empty then
fig := event_fig
else
event_fig := event_fig.group
end
end
if
fig /= Void and then
attached fig.pick_actions as l_actions and then
not l_actions.is_empty
then
l_actions.call ([a_x, a_y])
end
end
end
feature {EV_MODEL_WORLD_CELL} -- Element change
simulate_mouse_move (ax, ay: INTEGER)
-- Let `Current' behave as if pointer was moved to `ax', `ay'
do
mouse_move (ax, ay, 0, 0, 0, 0, 0)
end
feature {NONE} -- Implementation
drawable_position: EV_COORDINATE
-- Position of drawable relative to world.
-- Redefined by descendents.
do
create Result
end
drawable_bounding_box: EV_RECTANGLE
-- Bounding box of the projector
do
create Result.make (drawable_position.x, drawable_position.y, drawable.width, drawable.height)
end
area_bounding_box: detachable EV_RECTANGLE
-- Bounding box of the visible area if used.
do
if attached area as l_area then
create Result.make (area_x, area_y, l_area.width, l_area.height)
end
end
default_cursor: EV_POINTER_STYLE
-- Default cursor on world.
do
Result := default_pixmaps.standard_cursor
end
axle_length: INTEGER = 15
-- Length of x and y axles when points are displayed.
draw_points (figure: EV_MODEL)
-- Draw representation of all points in `figure' to canvas.
require
figure_not_void: figure /= Void
local
group: detachable EV_MODEL_GROUP
l_points: SPECIAL [EV_COORDINATE]
i, nb: INTEGER
bbox: EV_RECTANGLE
l_item: EV_COORDINATE
do
bbox := figure.bounding_box
drawable.set_foreground_color (default_colors.red)
drawable.fill_ellipse (figure.x-5 + offset_x, figure.y-5 + offset_y, 11, 11)
drawable.set_foreground_color (default_colors.black)
drawable.draw_rectangle (bbox.left + offset_x, bbox.top + offset_y, bbox.width, bbox.height)
group ?= figure
if group = Void then
l_points := figure.point_array
from
i := 0
nb := l_points.count - 1
until
i > nb
loop
l_item := l_points.item (i)
drawable.draw_segment (l_item.x + offset_x, l_item.y + offset_y, figure.x + offset_x, figure.y + offset_y)
drawable.fill_ellipse (l_item.x - 5 + offset_x, l_item.y - 5 + offset_y, 11, 11)
i := i + 1
end
end
group ?= figure
if group /= Void then
from
group.start
until
group.after
loop
draw_points (group.item)
group.forth
end
end
end
note
copyright: "Copyright (c) 1984-2023, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end