751 lines
20 KiB
Plaintext
751 lines
20 KiB
Plaintext
note
|
|
description: "[
|
|
Used as common ancestor to all "windows" in a system built using the
|
|
"jj_vision" cluster. It provides a way through feature `draw_views'
|
|
for updating all the views which contain that `target'.
|
|
Alternatively, the view
|
|
can force the redraw of views containing any of several objects by passing
|
|
a set of changed objects to feature `draw_views_with_set'.
|
|
The class should be an ancestor ancestor along with
|
|
some effected EV_WIDGET.
|
|
NOTE: Views which are `is_destroyed' are removed from the global `views' set
|
|
in feature `draw_views'.
|
|
]"
|
|
date: "18 Jul 03"
|
|
author: "Jimmy J. Johnson"
|
|
copyright: "Copyright 2012, Jimmy J. Johnson"
|
|
license: "Eiffel Forum License v2 (see forum.txt)"
|
|
URL: "$URL: file:///F:/eiffel_repositories/jj_vision/trunk/interface/views/view.e $"
|
|
date: "$Date: 2015-10-24 07:32:40 -0700 (Sat, 24 Oct 2015) $"
|
|
revision: "$Revision: 23 $"
|
|
|
|
deferred class
|
|
VIEW
|
|
|
|
inherit
|
|
|
|
DIMABLE
|
|
undefine
|
|
default_create
|
|
redefine
|
|
set_dimming_level
|
|
end
|
|
|
|
SHARED
|
|
undefine
|
|
default_create
|
|
end
|
|
|
|
PIXEL_BUFFERS
|
|
undefine
|
|
default_create
|
|
end
|
|
|
|
--create
|
|
-- make
|
|
|
|
feature {NONE} -- Initialization
|
|
|
|
make (a_target: like target)
|
|
-- Create a new view to display `a_target'
|
|
do
|
|
-- This assignment is required to avoid violating a
|
|
-- precondition "not_empty" later when calling
|
|
-- feature `create_interface_objects".
|
|
target_imp := a_target
|
|
-- `default_create from:
|
|
-- 1) {EV_ANY} calls `create_interface_objects', later `initialize'
|
|
-- 2) {EV_MODEL calls only `create_interface_objects'
|
|
default_create
|
|
set_target (a_target) -- calls `draw'
|
|
-- draw
|
|
ensure
|
|
target_imp /= Void
|
|
end
|
|
|
|
create_interface_objects
|
|
-- Create objects to be used by `Current' in `initialize'
|
|
-- Implemented by descendants to create attached objects
|
|
-- in order to adhere to void-safety due to the implementation
|
|
-- bridge pattern.
|
|
-- Called by `default_create' from {EV_ANY} or {EV_MODEL}
|
|
require
|
|
not_interface_objects_created: not is_interface_objects_created
|
|
do
|
|
create pixmap.make_with_pixel_buffer (Icon_new_class_color_buffer)
|
|
is_interface_objects_created := true
|
|
ensure
|
|
interface_objects_created: is_interface_objects_created
|
|
end
|
|
|
|
initialize
|
|
-- Initialize the view and insert it into a global list of views.
|
|
require
|
|
view_not_initialized: not is_view_initialized
|
|
do
|
|
-- initialize_dimable
|
|
dimming_level := Dim
|
|
previous_dimming_level := Dimmer
|
|
add_actions
|
|
is_view_initialized := True
|
|
ensure
|
|
initialized: is_view_initialized
|
|
end
|
|
|
|
add_actions
|
|
-- Add any actions to Current.
|
|
require
|
|
not_initialized: not is_view_initialized
|
|
do
|
|
pointer_button_press_actions.extend (agent on_prepick_right_click)
|
|
pick_actions.extend (agent on_picked)
|
|
pointer_motion_actions.extend (agent on_postput_move)
|
|
end
|
|
|
|
feature -- Status report
|
|
|
|
is_interface_objects_created: BOOLEAN
|
|
-- Has `create_interface_objects' been called?
|
|
|
|
is_view_initialized: BOOLEAN
|
|
-- Has `initialize' been called?
|
|
|
|
is_pick_notifiable: BOOLEAN
|
|
-- Should Current be notified by other views (normally
|
|
-- a view contained in Current) that some event has
|
|
-- occurred?
|
|
-- Feature `set_parent_view' must have been called on
|
|
-- the child view for this to take effect.
|
|
|
|
has_parent_view: BOOLEAN
|
|
-- Does Current know the view in which it resides?
|
|
do
|
|
Result := attached parent_view_imp
|
|
end
|
|
|
|
feature -- Access
|
|
|
|
application: JJ_APPLICATION
|
|
-- The application in which Current resides.
|
|
do
|
|
check attached {JJ_APPLICATION} (create {EV_ENVIRONMENT}).application as app then
|
|
-- because this class is for use in a {JJ_APPLICATION}.
|
|
Result := app
|
|
end
|
|
end
|
|
|
|
pixmap: EV_PIXMAP
|
|
-- The pixmap associated with this view
|
|
|
|
-- application: JJ_APPLICATION is
|
|
-- -- Convience feature for obtaining the current application.
|
|
-- local
|
|
-- app: JJ_APPLICATION
|
|
-- once
|
|
-- app ?= (create {EV_ENVIRONMENT}).application
|
|
-- check
|
|
-- jj_application_exists: app /= Void
|
|
-- -- Because VIEWs are used in JJ_APPLICATIONs.
|
|
-- end
|
|
-- ensure
|
|
-- result_exists: Result /= Void
|
|
-- end
|
|
|
|
-- command_manager: COMMAND_MANAGER is
|
|
-- -- Manages the COMMAND's called by the system to allow undo/redo capabilities.
|
|
-- -- (This is a handle to the `command_manager' from a JJ_APPLICATION; putting it
|
|
-- -- here instead of in SHARED allows redefinition of the `command_manager' in
|
|
-- -- descendents of JJ_APPLICATION.
|
|
-- once
|
|
-- Result := application.command_manager
|
|
-- end
|
|
|
|
frozen target: attached like target_imp
|
|
-- The primary target in this view. This feature along with
|
|
-- `set_target' allows the view to handle one target specially.
|
|
require
|
|
not_empty: not is_view_empty
|
|
do
|
|
check attached target_imp as t then
|
|
Result := t
|
|
end
|
|
end
|
|
|
|
parent_window: JJ_MAIN_WINDOW
|
|
-- The {JJ_MAIN_WINDOW} if any which contains this view.
|
|
-- Must redefine to change type.
|
|
do
|
|
check attached {EV_CONTAINABLE} Current as c then
|
|
Result := recursive_parent_window (c)
|
|
end
|
|
ensure
|
|
valid_result: Result /= Void
|
|
end
|
|
|
|
parent_tool: detachable TOOL
|
|
-- The TOOL, if any, in which Current resides.
|
|
local
|
|
con: detachable EV_CONTAINER
|
|
do
|
|
from con := parent
|
|
until Result /= Void or else con = Void
|
|
loop
|
|
if attached {TOOL} con as t then
|
|
Result := t
|
|
else
|
|
con := con.parent
|
|
end
|
|
end
|
|
end
|
|
|
|
parent_view: attached like parent_view_imp
|
|
-- The view in which Current resides.
|
|
-- Provides a way for a model view to notify a parent
|
|
-- container of changes
|
|
require
|
|
has_parent_view: has_parent_view
|
|
do
|
|
check attached parent_view_imp as p then
|
|
Result := p
|
|
end
|
|
end
|
|
|
|
parent: detachable EV_CONTAINER
|
|
-- Parent of the current view.
|
|
-- To be effected by joining with an EV_ class
|
|
deferred
|
|
end
|
|
|
|
state: VIEW_STATE
|
|
-- A snapshot of the current look of the view
|
|
do
|
|
create Result.make (Current)
|
|
end
|
|
|
|
feature -- Element change
|
|
|
|
set_target (a_target: like target)
|
|
-- Change the value of `target' and realign the table or list
|
|
-- of views in which `a_target' is displayed.
|
|
do
|
|
-- print ("VIEW.set_target: a_target = " + target.out + "%N")
|
|
-- Remove the old association
|
|
if attached target_imp and then target /= a_target then
|
|
check
|
|
has_associated_view: views_table.has (target)
|
|
-- because `target_imp' not Void and `make'
|
|
end
|
|
views_table.prune (Current)
|
|
target_imp := Void
|
|
end
|
|
if target_imp = Void then
|
|
-- the expected case, except of initial creation
|
|
-- print ("VIEW.set_target: if statement target_imp = Void %N")
|
|
target_imp := a_target
|
|
views_table.extend (Current)
|
|
elseif not views_table.has_view (Current) then
|
|
-- print ("VIEW.set_target: not views_table.has (Current) %N")
|
|
check
|
|
same_object: target_imp = a_target
|
|
-- because of assignment statement in `make'
|
|
end
|
|
views_table.extend (Current)
|
|
end
|
|
draw
|
|
ensure
|
|
has_target: has_target (a_target)
|
|
target_imp /= Void
|
|
end
|
|
|
|
set_parent_view (a_view: VIEW)
|
|
-- Set `parent_view' to `a_view', allowing Current to
|
|
-- notify `a_view' of some event (e.g. right click).
|
|
do
|
|
parent_view_imp := a_view
|
|
end
|
|
|
|
set_dimming_level (a_level: like dimming_level)
|
|
-- Change the `dimming_level'
|
|
do
|
|
Precursor (a_level)
|
|
-- paint
|
|
end
|
|
|
|
feature -- Basic operations
|
|
|
|
-- paint
|
|
-- -- Draw the current view when some property like
|
|
-- -- background color changes
|
|
-- do
|
|
-- end
|
|
|
|
draw
|
|
-- Draw the current view.
|
|
-- Default does nothing
|
|
require
|
|
view_is_drawable: not is_draw_disabled
|
|
do
|
|
end
|
|
|
|
draw_other_views (a_target: ANY)
|
|
-- Draw all views that contain `a_target' except Current
|
|
-- This also cleans any "destroyed" views from the `views' set.
|
|
require
|
|
target_exists: a_target /= Void
|
|
local
|
|
b: BOOLEAN
|
|
do
|
|
b := is_draw_disabled
|
|
disable_drawing
|
|
draw_views (a_target)
|
|
if not b then
|
|
enable_drawing
|
|
end
|
|
end
|
|
|
|
draw_views (a_target: ANY)
|
|
-- Draw the views which contain `a_target'.
|
|
local
|
|
lin: LINEAR [VIEW]
|
|
marks: LINKED_SET [VIEW] -- Views marked for removal.
|
|
v: VIEW
|
|
do
|
|
create marks.make
|
|
lin := views_table.linear (a_target)
|
|
from lin.start
|
|
until lin.after
|
|
loop
|
|
v := lin.item
|
|
if v.is_destroyed then
|
|
marks.extend (v)
|
|
elseif not v.is_draw_disabled then
|
|
v.draw
|
|
end
|
|
lin.forth
|
|
end
|
|
-- Clean out any views that are no longer usable.
|
|
from marks.start
|
|
until marks.exhausted
|
|
loop
|
|
views_table.prune (marks.item)
|
|
marks.forth
|
|
end
|
|
end
|
|
|
|
draw_views_with_set (a_set: LINEAR [ANY])
|
|
-- Draw the views which contain any of the objects in `a_set'.
|
|
-- This also cleans any "destroyed" views from the `views' set.
|
|
require
|
|
set_exists: a_set /= Void
|
|
local
|
|
lin: LINEAR [VIEW]
|
|
marks: LINKED_SET [VIEW] -- Views marked for removal.
|
|
v: VIEW
|
|
do
|
|
create marks.make
|
|
lin := views_table.linear_with_set (a_set)
|
|
from lin.start
|
|
until lin.after
|
|
loop
|
|
v := lin.item
|
|
if v.is_destroyed then
|
|
marks.extend (v)
|
|
elseif not v.is_draw_disabled then
|
|
v.draw
|
|
end
|
|
lin.forth
|
|
end
|
|
-- Clean out any views that are no longer usable.
|
|
from marks.start
|
|
until marks.exhausted
|
|
loop
|
|
views_table.prune (marks.item)
|
|
marks.forth
|
|
end
|
|
end
|
|
|
|
draw_all_views
|
|
-- Draw *all* the views in the system.
|
|
-- Also cleans any "destroyed" views for the `views' set.
|
|
local
|
|
lin: LINEAR [VIEW]
|
|
marks: LINKED_SET [VIEW] -- Views marked for removal.
|
|
v: VIEW
|
|
do
|
|
create marks.make
|
|
lin := views_table.linear_representation
|
|
from lin.start
|
|
until lin.after
|
|
loop
|
|
v := lin.item
|
|
if v.is_destroyed then
|
|
marks.extend (v)
|
|
elseif not v.is_draw_disabled then
|
|
v.draw
|
|
end
|
|
lin.forth
|
|
end
|
|
-- Clean out any views that are no longer usable.
|
|
from marks.start
|
|
until marks.exhausted
|
|
loop
|
|
views_table.prune (marks.item)
|
|
marks.forth
|
|
end
|
|
end
|
|
|
|
feature -- Status report
|
|
|
|
is_in_default_state: BOOLEAN = true
|
|
-- Is `Current' in its default state?
|
|
-- The intent of this class is to be joined with an EV_WIDGET.
|
|
-- The default state of a descendent is most likely not the same
|
|
-- as the default state of the parent EV_WIDGET (after all, a
|
|
-- new type widget is being defined that, by definition looks
|
|
-- different from the parent.)
|
|
-- This silly feature is the post-condition of `default_create'
|
|
-- from EV_WIDGET, which required a choice--either redefine this
|
|
-- feature in every EV_WIDGET descendant or, as chosen here, use
|
|
-- this version (the EV_WIDGET version is irrelavent anyway) and
|
|
-- undefine it in the inherit class of the EV_WIDGET parent.
|
|
|
|
is_destroyed: BOOLEAN
|
|
-- Has the view been destroyed?
|
|
-- This will be joined with an EV_WIDGET feature
|
|
deferred
|
|
end
|
|
|
|
is_view_empty: BOOLEAN
|
|
-- Are there no objects in this VIEW?
|
|
do
|
|
Result := target_imp = Void
|
|
end
|
|
|
|
is_draw_disabled: BOOLEAN
|
|
-- Can the view be drawn using 'draw'?
|
|
|
|
feature -- Status setting
|
|
|
|
disable_drawing
|
|
-- Block the view from being redrawn by calling draw.
|
|
-- Used to reduce number of calls to draw.
|
|
do
|
|
is_draw_disabled := True
|
|
ensure
|
|
drawing_not_allowed: is_draw_disabled
|
|
end
|
|
|
|
enable_drawing
|
|
-- Allow the view to be redrawn on a call to draw.
|
|
do
|
|
is_draw_disabled := False
|
|
ensure
|
|
drawing_allowed: not is_draw_disabled
|
|
end
|
|
|
|
feature -- Query
|
|
|
|
has_target (a_target: like target): BOOLEAN
|
|
-- Does Current contain `a_target'?
|
|
do
|
|
Result := target_imp = a_target
|
|
end
|
|
|
|
display_name (a_object: ANY): STRING
|
|
-- An identifying "out" value corresponding to `a_object'.
|
|
require
|
|
object_exists: a_object /= Void
|
|
do
|
|
if attached {EDITABLE} a_object as e then
|
|
Result := e.display_name
|
|
else
|
|
Result := "fix me"
|
|
print ("VIEW.display_name -- get from once table?")
|
|
end
|
|
ensure
|
|
result_exists: Result /= Void
|
|
end
|
|
|
|
yes_cursor (a_target: ANY): EV_POINTER_STYLE
|
|
-- Cursor for `a_target'.
|
|
do
|
|
create Result.make_with_pixel_buffer (Icon_new_class_color_buffer, 0, 0)
|
|
end
|
|
|
|
no_cursor (a_target: ANY): EV_CURSOR
|
|
-- Cursor for `a_target'.
|
|
do
|
|
create Result
|
|
end
|
|
|
|
linear (a_object: ANY): LINEAR [VIEW]
|
|
-- List of views in which `a_object' is displayed. The
|
|
-- resulting list could be empty.
|
|
do
|
|
Result := views_table.linear (a_object)
|
|
end
|
|
|
|
linear_with_set (a_set: LINEAR [ANY]): LINEAR [VIEW]
|
|
-- List of views in which any of the objects in `a_set'
|
|
-- is displayed.
|
|
do
|
|
Result := views_table.linear_with_set (a_set)
|
|
end
|
|
|
|
frozen post_pick_move_agent: PROCEDURE [TUPLE [a_x, a_y: INTEGER;
|
|
a_x_tilt, a_y_tilt, a_pressure: DOUBLE;
|
|
a_screen_x, a_screen_y: INTEGER]]
|
|
-- Creates an agent out of `on_postput_move' which is added to
|
|
-- the `pointer_motion_actions' of *ALL* views when a pick occurs
|
|
-- (see `on_picked'). Holding on to this agent as a once feature
|
|
-- allows `on_postput_move' to remove this agent from *ALL* the
|
|
-- views after the pick has ended and the mouse is moved [in one
|
|
-- of the views].
|
|
once
|
|
Result := agent on_postput_move
|
|
end
|
|
|
|
feature -- Basic operations
|
|
|
|
target_changed_operations
|
|
-- This feature is called by `notify_views' to perform
|
|
-- actions when that view's `target' was modified.
|
|
do
|
|
print ("{VIEW}.target_changed_operations %N")
|
|
|
|
end
|
|
|
|
pick_notified_operations (a_target: ANY)
|
|
-- React to the pick of `a_target' from some view
|
|
do
|
|
print ("{VIEW}.pick_notified_operations on {" + generating_type.name + "}%N")
|
|
|
|
end
|
|
|
|
pick_ended_operations
|
|
-- React to the end of a pick and drop operation
|
|
do
|
|
print ("{VIEW}.pick_ended_operations on {" + generating_type.name + "} %N")
|
|
|
|
end
|
|
|
|
feature {NONE} -- Agents and support (actions)
|
|
|
|
frozen on_prepick_right_click (x, y, button: INTEGER;
|
|
x_tilt, y_tilt, pressure: DOUBLE;
|
|
screen_x, screen_y: INTEGER)
|
|
-- Notify the parent of all views that contain `target'
|
|
-- that a pick event occurred involving `target'.
|
|
local
|
|
lin: LINEAR [VIEW]
|
|
marks: LINKED_SET [VIEW] -- Views marked for removal.
|
|
v: VIEW
|
|
do
|
|
-- is_picking.set_item (true)
|
|
create marks.make
|
|
lin := views_table.linear (target)
|
|
from lin.start
|
|
until lin.after
|
|
loop
|
|
v := lin.item
|
|
if v.is_destroyed then
|
|
marks.extend (v)
|
|
elseif v.has_parent_view then
|
|
-- Notifiy the parent view of the pick
|
|
v.parent_view.pick_notified_operations (target)
|
|
-- Save the view for notification when pick ends
|
|
pick_notified_views.extend (v.parent_view)
|
|
end
|
|
lin.forth
|
|
end
|
|
-- Clean out any views that are no longer usable.
|
|
from marks.start
|
|
until marks.exhausted
|
|
loop
|
|
views_table.prune (marks.item)
|
|
marks.forth
|
|
end
|
|
end
|
|
|
|
frozen on_picked (a_x, a_y: INTEGER)
|
|
-- Notify the parent of all views that contain `target'
|
|
-- that a pick event occurred involving `target'.
|
|
local
|
|
lin: LINEAR [VIEW]
|
|
marks: LINKED_SET [VIEW] -- Views marked for removal.
|
|
v: VIEW
|
|
do
|
|
is_picking.set_item (true)
|
|
-- create marks.make
|
|
-- lin := views_table.linear (target)
|
|
-- from lin.start
|
|
-- until lin.after
|
|
-- loop
|
|
-- v := lin.item
|
|
-- if v.is_destroyed then
|
|
-- marks.extend (v)
|
|
-- elseif v.has_parent_view then
|
|
-- -- Notifiy the parent view of the pick
|
|
-- v.parent_view.pick_notified_operations (target)
|
|
-- -- Save the view for notification when pick ends
|
|
-- pick_notified_views.extend (v.parent_view)
|
|
-- end
|
|
-- lin.forth
|
|
-- end
|
|
-- -- Clean out any views that are no longer usable.
|
|
-- from marks.start
|
|
-- until marks.exhausted
|
|
-- loop
|
|
-- views_table.prune (marks.item)
|
|
-- marks.forth
|
|
-- end
|
|
end
|
|
|
|
frozen on_postput_move (a_x, a_y: INTEGER;
|
|
a_x_tilt, a_y_tilt, a_pressure: DOUBLE;
|
|
a_screen_x, a_screen_y: INTEGER)
|
|
-- Feature added as agent to `pointer_motion_actions'
|
|
-- to react after a pnp operations has ended. It calls
|
|
-- feature `postput_operations'.
|
|
-- Redefine `postput_operations' to clean up any operations
|
|
-- that occurred in `do_prepick_operations'.
|
|
-- See index clause for information on pick-and-put.
|
|
local
|
|
v: VIEW
|
|
do
|
|
print ("{VIEW}.on_postput_move on " + generating_type.name + "%N")
|
|
-- Notify views when a transport has ended.
|
|
if is_picking.item and then not application.transport_in_progress then
|
|
print ("%T `is_picking and not transport_in_progress pick_notified_views.count = " + pick_notified_views.count.out + "%N")
|
|
is_picking.set_item (false)
|
|
-- Inform any parent views that the pick has ended
|
|
from pick_notified_views.start
|
|
until pick_notified_views.after
|
|
loop
|
|
v := pick_notified_views.item
|
|
v.pick_ended_operations
|
|
pick_notified_views.forth
|
|
end
|
|
pick_notified_views.wipe_out
|
|
end
|
|
end
|
|
|
|
notify_changed (a_target: ANY)
|
|
-- Inform the views that have `a_target' that `a_target'
|
|
-- has changed (i.e. call `on_target_changed' for those
|
|
-- views).
|
|
-- This also cleans any "destroyed" views from the `views' set.
|
|
local
|
|
lin: LINEAR [VIEW]
|
|
marks: LINKED_SET [VIEW] -- Views marked for removal.
|
|
v: VIEW
|
|
do
|
|
create marks.make
|
|
lin := views_table.linear (a_target)
|
|
from lin.start
|
|
until lin.after
|
|
loop
|
|
v := lin.item
|
|
if v.is_destroyed then
|
|
marks.extend (v)
|
|
elseif not v.is_draw_disabled then
|
|
v.target_changed_operations
|
|
end
|
|
lin.forth
|
|
end
|
|
-- Clean out any views that are no longer usable.
|
|
from marks.start
|
|
until marks.exhausted
|
|
loop
|
|
views_table.prune (marks.item)
|
|
marks.forth
|
|
end
|
|
end
|
|
|
|
frozen is_picking: BOOLEAN_REF
|
|
-- Is a pick-and-put (PNP) operation in progress?
|
|
-- It seems the PNP operations intercepts events system-
|
|
-- wide, so this is a global reference.
|
|
-- See index clause for information on pick-and-put.
|
|
once
|
|
create Result
|
|
end
|
|
|
|
pick_notified_views: LINKED_SET [VIEW]
|
|
-- List of views that were notfied by `on_picked'
|
|
once
|
|
create Result.make
|
|
end
|
|
|
|
feature -- Action sequences
|
|
|
|
pointer_button_press_actions: EV_POINTER_BUTTON_ACTION_SEQUENCE
|
|
-- Actions to be performed when screen pointer button is pressed.
|
|
-- Defined here as place-holder to be undefined (i.e. joined) to
|
|
-- the version from {EV_WIDGET} or {EV_MODEL}.
|
|
-- See index clause for information on pick-and-put.
|
|
deferred
|
|
end
|
|
|
|
pointer_motion_actions: EV_POINTER_MOTION_ACTION_SEQUENCE
|
|
-- Actions to be performed when screen pointer moves.
|
|
-- Defined here as place-holder to be undefined (i.e. joined) to
|
|
-- the version from {EV_WIDGET} or {EV_MODEL}.
|
|
-- See index clause for information on pick-and-put.
|
|
deferred
|
|
end
|
|
|
|
pick_actions: EV_PND_START_ACTION_SEQUENCE
|
|
-- Actions to be performed when `pebble' is picked up.
|
|
-- Defined here as place-holder to be undefined by some
|
|
-- {EV_WIDGET} or {EV_MODEL}.
|
|
deferred
|
|
end
|
|
|
|
drop_actions: EV_PND_ACTION_SEQUENCE --EV_PND_START_ACTION_SEQUENCE
|
|
-- Actions to be performed when a pebble is dropped here.
|
|
deferred
|
|
end
|
|
|
|
feature {NONE} -- Implementation
|
|
|
|
recursive_parent_window (a_containable: EV_CONTAINABLE): JJ_MAIN_WINDOW
|
|
-- The {JJ_MAIN_WINDOW} which contains this tool.
|
|
-- This procedure was provided by Julian Rodgers from the Eiffel
|
|
-- users group.
|
|
do
|
|
check attached {EV_CONTAINER} a_containable.parent as cur_parent then
|
|
-- because parent of EV_CONTAINABLE must be an EV_CONTAINER
|
|
if attached {JJ_MAIN_WINDOW} cur_parent as w then
|
|
Result := w
|
|
else
|
|
check attached {EV_CONTAINABLE} cur_parent as con_parent then
|
|
-- because, if `cur_parent' is not a {JJ_MAIN_WINDOW} it must be EV_CONTAINABLE
|
|
Result := recursive_parent_window (con_parent)
|
|
end
|
|
end
|
|
end
|
|
ensure
|
|
result_exists: Result /= Void
|
|
end
|
|
|
|
feature {NONE} -- Implemetation
|
|
|
|
target_imp: detachable ANY
|
|
-- Detachable implementation of `target' for void safety
|
|
|
|
views_table: VIEW_TARGET_TABLE
|
|
-- Global table associating objects to views
|
|
once
|
|
create Result
|
|
end
|
|
|
|
parent_view_imp: detachable VIEW
|
|
-- Detachable implementation of `parent_view'
|
|
|
|
invariant
|
|
|
|
-- not_empty: target_imp /= Void
|
|
|
|
end
|