mirror of
https://github.com/EiffelSoftware/eiffel-org.git
synced 2026-02-28 11:50:57 +01:00
docs: reorganized the vision2 documentation.
git-svn-id: https://svn.eiffel.com/eiffel-org/trunk@2284 abb3cda0-5349-4a8f-a601-0c33ac3a8c38
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
[[Property:uuid|D1DDF411-5387-4A81-9A85-3EF8A2A4220D]]
|
||||
[[Property:weight|0]]
|
||||
[[Property:title|How to build a concurrent graphical application: EiffelVision with SCOOP]]
|
||||
==How can I build a concurrent graphical application in Eiffel?==
|
||||
|
||||
Eiffel has a great library for producing graphical applications: EiffelVision. Eiffel also has a powerful concurrency mechanism: SCOOP.
|
||||
|
||||
How do you make the two work together? This note gives you simple guidelines to ensure that the EiffelVision-SCOOP marriage is a harmonious and productive one.
|
||||
|
||||
The first question: why does the problem even exist? Let's go back to the pre-SCOOP days. Any graphical application has an "event loop", which keeps watching for graphical user events, such as a mouse click, and triggering the corresponding application responses, such as saving a file (if the user clicked ''OK'' on a ''File Save'' dialog). If you were using multithreading, the event loop would run in the main thread, also called the GUI (Graphical User Interface) thread.
|
||||
|
||||
Enter SCOOP. The old technique cannot work because a processor stuck in a loop cannot process any logged call! If you perform calls on a graphical widget, say the ''OK'' button, they will be logged right away, but they can only execute once the processor has exited its event loop. Not what you want.
|
||||
|
||||
So here is what you should do:
|
||||
|
||||
In a creation procedure used to initialize GUI objects, create an <eiffel>EV_APPLICATION</eiffel> object, using an instruction such as
|
||||
create my_app
|
||||
with <eiffel>my_app</eiffel> of type <eiffel>EV_APPLICATION</eiffel>. (This may be a root creation procedure or a creation procedure of a separate object in case the root processor is going to be used for other operations.)
|
||||
|
||||
Then in the same creation procedure create all the GUI elements. They will all be in the same processor that created the <eiffel>EV_APPLICATION</eiffel> object.
|
||||
|
||||
After that start the application, using
|
||||
my_app.launch
|
||||
In the pre-SCOOP world, launch would start the event loop. Here it only creates a separate object (of type <eiffel>EV_APPLICATION_HANDLER</eiffel>), which will run the event loop, forwarding events to the <eiffel>EV_APPLICATION</eiffel> object.
|
||||
|
||||
This is all the creation procedure should do. Make sure it terminates with the preceding step. Otherwise, the event loop will never run!
|
||||
|
||||
Now you can start using EiffelVision as you are used to, by sending GUI requests to the <eiffel>EV_APPLICATION</eiffel> object:
|
||||
|
||||
* For requests coming from the same processor just use the <eiffel>EV_APPLICATION</eiffel> object directly.
|
||||
* For requests coming from another processor, you can get the access through the feature <eiffel>ev_separate_application</eiffel> of class <eiffel>EV_SHARED_APPLICATION</eiffel>.
|
||||
|
||||
Note that only one <eiffel>EV_APPLICATION</eiffel> object can be used, therefore all GUI objects have to be created in the region of this object.
|
||||
|
||||
That's all! Happy concurrent Eiffeling.
|
||||
@@ -0,0 +1,86 @@
|
||||
[[Property:title|Converting EiffelVision 2 Systems to Void-Safety]]
|
||||
[[Property:weight|1]]
|
||||
[[Property:uuid|96e01318-700b-da6e-42d1-14fee219daf5]]
|
||||
==Introduction==
|
||||
|
||||
In order to convert systems that employ EiffelVision 2 (Vision2) to [[Void-safe Programming in Eiffel|void-safety]], some adjustments may be needed depending on its usage. This page describes the various usage scenarios of Vision2 that will need to be converted in order to adhere to void-safety.
|
||||
<!--break-->
|
||||
==Inheritance Purely from an Interface Class==
|
||||
|
||||
If you have classes that inherit from a Vision2 interface class such as EV_DRAWING_AREA, the first change that has to be made is to alter <eiffel>`initialize'</eiffel> so that any types that are attached (i.e. types that remain non-void throughout the lifetime of its container [parent object]) are instantiated via <eiffel>`create_interface_objects'</eiffel>. This feature needs to be redefined if the type from Vision2 is instantiable. If not, then it may need to be made effective (such as when the class inherits directly from EV_ANY). It is important that any attached types in the interface class are instantiated in <eiffel>`create_interface_objects'</eiffel> and these objects are initialized via <eiffel>`initialize'</eiffel>. Attached types should not be instantiated in <eiffel>`initialize'</eiffel> due to the Bridge Pattern implementation, and initialization of these types in <eiffel>`create_interface_objects'</eiffel> MUST be performed in <eiffel>`initialize'</eiffel>, otherwise unexpected behavior may occur as the Bridge Pattern has not been fully set up at this point in time.
|
||||
|
||||
Example from EV_TIMEOUT
|
||||
<code>
|
||||
create_interface_objects
|
||||
-- <Precursor>
|
||||
do
|
||||
create actions
|
||||
end
|
||||
|
||||
create_implementation
|
||||
-- Create implementation of timeout.
|
||||
do
|
||||
create {EV_TIMEOUT_IMP} implementation.make
|
||||
end
|
||||
</code>
|
||||
|
||||
|
||||
==Inheritance from an Implementation Interface Class with Associating Interface Class==
|
||||
|
||||
If you have an existing, custom platform-dependent implementation, a few more changes will be needed above and beyond those required for the interface class.
|
||||
|
||||
For interface class changes, now the interface object is passed to the implementation after creation, via <eiffel>`assign_interface'</eiffel>. This means that <eiffel>`make'</eiffel> no longer takes an argument (see <eiffel>`create_implementation'</eiffel> above). This also means that to adhere to void-safety all of the types are now created and initialized via the creation routine of the implementation object.
|
||||
|
||||
An example from the conversion of the Windows implementation of EV_BUTTON_IMP:
|
||||
|
||||
<code>
|
||||
make (an_interface: like interface)
|
||||
-- Create `Current' with interface `an_interface'.
|
||||
do
|
||||
base_make (an_interface)
|
||||
wel_make (default_parent, "", 0, 0, 0, 0, 0)
|
||||
extra_width := 20
|
||||
text_alignment := default_alignment
|
||||
-- Retrieve the theme for the button.
|
||||
open_theme := application_imp.theme_drawer.open_theme_data (wel_item, "Button")
|
||||
end
|
||||
|
||||
initialize
|
||||
-- Initialize `Current'.
|
||||
do
|
||||
Precursor {EV_PRIMITIVE_IMP}
|
||||
set_default_font
|
||||
end
|
||||
|
||||
interface: EV_BUTTON;
|
||||
</code>
|
||||
|
||||
would become:
|
||||
|
||||
<code>
|
||||
make
|
||||
-- Initialize `Current'.
|
||||
do
|
||||
wel_make (default_parent, "", 0, 0, 0, 0, 0)
|
||||
extra_width := 20
|
||||
text_alignment := default_alignment
|
||||
-- Retrieve the theme for the button.
|
||||
open_theme := application_imp.theme_drawer.open_theme_data (wel_item, "Button")
|
||||
Precursor {EV_PRIMITIVE_IMP}
|
||||
set_default_font
|
||||
end
|
||||
|
||||
interface: detachable EV_BUTTON note option: stable attribute end;
|
||||
</code>
|
||||
|
||||
The following steps are needed during the conversion:
|
||||
|
||||
* The attribute <eiffel>`interface'</eiffel> needs to be made a stable attribute. The converted <eiffel>`interface'</eiffel> attribute shows the syntax for doing so.
|
||||
|
||||
* Copy any initialization of the widget from <eiffel>`make'</eiffel> to <eiffel>`initialize'</eiffel> excluding <eiffel>`base_make'</eiffel> setup. Any initialization code that relies on <eiffel>`interface'</eiffel> would have to be rewritten so that <eiffel>`interface'</eiffel> gets passed to the new creation routine, which in turn calls the original <eiffel>`make'</eiffel>. See <eiffel>EV_PRINT_PROJECTOR_IMP</eiffel> on Windows <eiffel>`make_with_context'</eiffel> for an example of this.
|
||||
|
||||
* Remove <eiffel>`make'</eiffel>, rename <eiffel>`initialize'</eiffel> to <eiffel>`make'</eiffel>, and make sure that any calls to Precursor do not override any settings set in <eiffel>`initialize'</eiffel>. The ordering may need to be changed in order to make the code void-safe. See <eiffel>EV_POPUP_WINDOW_IMP.make</eiffel> (Windows implementation) where the setting of <eiffel>`user_can_resize'</eiffel> is performed after the Precursor call so that is doesn't get overriden.
|
||||
|
||||
|
||||
{{SeeAlso|[[Void-Safe Programming in Eiffel]]}}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
[[Property:modification_date|Tue, 09 Feb 2021 18:06:35 GMT]]
|
||||
[[Property:publication_date|Tue, 09 Feb 2021 18:01:48 GMT]]
|
||||
[[Property:uuid|21A9B6AB-B2F5-465E-A02F-F7576838965D]]
|
||||
[[Property:weight|0]]
|
||||
[[Property:title|Vison2 : How-to]]
|
||||
[[Property:link_title|How to ...]]
|
||||
Reference in New Issue
Block a user