Author:admin

Date:2008-09-17T13:53:28.000000Z


git-svn-id: https://svn.eiffel.com/eiffel-org/trunk@3 abb3cda0-5349-4a8f-a601-0c33ac3a8c38
This commit is contained in:
jfiat
2008-09-17 13:53:28 +00:00
parent 4fee9356ea
commit 2ee31ab9c7
763 changed files with 36576 additions and 0 deletions

View File

@@ -0,0 +1,101 @@
[[Property:title|EiffelBase Sample: Calculator]]
[[Property:weight|0]]
This sample consists of a command line reverse Polish notation (RPN) calculator.
{{note| '''Note:''' A RPN calculator works slightly differently from standard calculators. It consists of a stack of numbers. Operations are applied to the two numbers on top of the stack. The result is then put on top of the stack so that it can be used in the next operation. This sample refers to the top of the stack as ''Accumulator''.
==Compiling==
To compile the example:
# Launch EiffelStudio.
# Click '''Add project'''
# Browse to ''$ISE_EIFFEL\examples\base\calculator\''
# Choose ''calculator.ecf''
# Choose the location where the project will be compiled, by default the same directory containing the configuration file.
# Click '''Open'''.
==Running==
After you launch the sample, the following text appears in a console:
<code>
*********************************
Calculator in reverse Polish form
*********************************
Allowable operations are:
'/': Divide top two numbers on the stack.
'0': Empty the stack.
'a': Enter operand onto stack.
'?': Help.
'*': Multiply top two numbers on the stack.
'+': Add top two numbers on the stack
'q': Quit.
'-': Subtract top two numbers on the stack.
Enter a number, followed by :
</code>
Enter the first number to be put onto the stack, for example <code>3</code>.
{{note| '''Note:''' Failing to enter a number at this stage will cause the sample to stop. This sample was designed to showcase the use of EiffelBase data structures and is not protected against unexpected entries. }}
You may then add another number on the stack by entering the character <code>a</code>:
<code>
*********************************
Calculator in reverse Polish form
*********************************
Allowable operations are:
'/': Divide top two numbers on the stack.
'0': Empty the stack.
'a': Enter operand onto stack.
'?': Help.
'*': Multiply top two numbers on the stack.
'+': Add top two numbers on the stack
'q': Quit.
'-': Subtract top two numbers on the stack.
Enter a number, followed by : 3
Accumulator = 3
Next operation? a
Enter a number, followed by :
</code>
Enter a second number, for example <code>2</code>. You can then apply any operation to the two operands such as minus:
<code>
...
Next operation? a
Enter a number, followed by : 2
Accumulator = 2
Next operation? -
Accumulator = 1
Next operation?
</code>
You may use the operation <code>0</code> to clear the stack at any time. You may use <code>q</code> to quit the program.
{{tip| '''Tip:''' You can use the command <code>?</code> to display the list of available operations. }}
==Under the Hood==
This sample shows how to leverage EiffelBase data structures in a simple Eiffel system. The root class CALCULATOR first instantiates all ''state'' objects, each corresponding to one possible operation. The state classes all inherit from STATE. They are:
* PLUS: Add stack's two top numbers.
* MINUS: Substract stack's two top numbers.
* MULTIPLY: Multiply stack's two top numbers.
* DIVIDE: Divide stack's two top numbers.
* EMPTY: Empty stack.
* HELP: Prints available commands.
* QUESTION: Get number from user.
* QUIT: Close application.
Each of these classes implement the feature do_one_state from STATE which performs the operation associated with the state. The initial state is QUESTION which asks for the initial number to put in the ''accumulator''. Following states depend on the user input. <br/>
Every descendant of STATE implement the feature operation which performs the corresponding stack transformation.
See the reference for the class interfaces.
}}

View File

@@ -0,0 +1,14 @@
[[Property:title|EiffelBase, Abstract Container Structures: The Taxonomy]]
[[Property:weight|0]]
A container data structure (or container in the sequel) is an object which serves to store and access collections of objects, called the '''items''' of the container. All classes describing containers are descendants of the deferred class [[ref:libraries/base/reference/container_chart|CONTAINER]] .
A container can be studied from three viewpoints: access, storage and traversal.
* The '''access''' criterion affects how the clients of a container can access its items. For example, in a stack or queue, only one item is accessible at any given time, and clients do not choose that item; in contrast, clients of an array or hash table must provide an index, or more generally a key, to access an item.
* The '''storage''' criterion affects how the items are put together. For example some containers are finite, others potentially infinite; among finite structures, some are bounded, others unbounded.
* The '''traversal''' criterion affects how, if in any way, the items of a container can be traversed. A traversal is a mechanism which makes it possible to examine each item of a container once, in a clearly specified order. For example some containers can be traversed sequentially, in one direction or two; tree structures lend themselves to preorder, postorder and breadth-first traversals.
For each of these criteria the Base library offers a single-inheritance hierarchy of deferred classes. The top of the access hierarchy is class [[ref:libraries/base/reference/collection_chart|COLLECTION]] ; the top of the storage hierarchy is class [[ref:/libraries/base/reference/box_chart|BOX]] ; the top of the traversal hierarchy is class [[ref:/libraries/base/reference/traversable_chart|TRAVERSABLE]] . These three classes are heirs of the most general class [[ref:libraries/base/reference/container_chart|CONTAINER]] .

View File

@@ -0,0 +1,351 @@
[[Property:title|EiffelBase Data Structures, Lists]]
[[Property:weight|1]]
Many applications need sequential structures, also called linear structures, in particular lists and circular chains. Apart from three classes describing individual list cells, all the classes involved are descendants of class [[ref:/libraries/base/reference/linear_chart|LINEAR]] , one of the deferred classes describing general traversal properties and introduced in the chapter that described the general data structure taxonomy. More precisely, all but one of the classes of interest for the present discussion are descendants, direct or indirect, from a class called [[ref:/libraries/base/reference/chain_chart|CHAIN]] which describes general sequential structures possessing a cursor as well as insertion properties. The exception is class [[ref:/libraries/base/reference/countable_sequence_chart|COUNTABLE_SEQUENCE]] , which describes infinite structures; all the others describe finite structures. <br/>
[[ref:/libraries/base/reference/chain_chart|CHAIN]] is an heir of [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] , which describes a more general notion of sequence. [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] is a descendant of [[ref:/libraries/base/reference/linear_chart|LINEAR]] . There are two main categories of sequential structures: some, called circular chains, are cyclic; others, called lists, are not. Another distinction exists between dynamic structures, which may be extended at will, and fixed ones, which have a bounded capacity. <br/>
In all of the structures under review you may insert two or more occurrences of a given item in such a way that the occurrences are distinguishable. In other words, the structures are bags rather than just sets, although it is possible to use them to implement sets.
=Higher Level Traversal Classes=
The list and chain classes are characterized, for their traversal properties, as being linear and, more precisely, bilinear. In the traversal hierarchy, the relevant deferred classes are [[ref:/libraries/base/reference/linear_chart|LINEAR]] and [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] , introduced in the [[EiffelBase, Abstract Container Structures: The Taxonomy|discussion]] of the general taxonomy.
==Linear structures==
[[ref:/libraries/base/reference/linear_chart|LINEAR]] describes sequential structures that may be traversed one way. It introduces in particular the following features, illustrated on the figure below:
* <eiffel>after</eiffel>, a boolean-valued query which determines whether you have moved past the last position (a more precise specification is given below).
* <eiffel>off</eiffel>, a boolean-valued query which is false if and only if there is no item at the current position; for [[ref:/libraries/base/reference/linear_chart|LINEAR]] this is the same as:
<code>is_empty and not after</code>
* <eiffel>item</eiffel>, a query which returns the item at the current position - provided of course there is one, as expressed by the precondition:
<code>not off</code>
* <eiffel>start</eiffel>, a command to move to the first position if any (if is_empty is true the command has no effect).
* <eiffel>forth</eiffel>, a command to advance by one position; the precondition is not after.
* <eiffel>finish</eiffel>, a command to move to the last position; the precondition is: <br/>
<code>not is_empty</code>
[[Image:linear|fig.1: Linear Structure]]
There is also a procedure <eiffel>search</eiffel> with one argument, which determines whether the value of that argument appears in the structure at or after the current position, and if not makes <eiffel>after</eiffel> become true. This procedure is internally used by the default implementation of the <eiffel>has</eiffel> function (the general membership test) for linear structures. Like has for all containers, <eiffel>search</eiffel> uses object or reference equality depending on the value set for <eiffel>object_comparison</eiffel>.
An invariant property of [[ref:/libraries/base/reference/linear_chart|LINEAR]] structures is that the current position may go off one step past the last item if any, but no further. The precondition of <eiffel>forth</eiffel> - not after - helps ensure this. The first item (if any) being at position 1, the maximum allowable position is <eiffel>count</eiffel> + 1, where <eiffel>count</eiffel> is the number of items.
==Bilinear structures==
[[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] describes linear structures which may be traversed both ways. It inherits from [[ref:/libraries/base/reference/linear_chart|LINEAR]] and extends it with two new features which ensure complete symmetry between the two directions of movement:
* <eiffel>before</eiffel>, a boolean-valued query which determines whether you have moved to the left of the first position (a more precise specification is given below).
* <eiffel>back</eiffel>, a command to move backward by one position; the precondition is not before.
For bilinear structures the position can range between 0 (not just 1) and count + 1. Query off is accordingly redefined so as to yield the value of after or before.
[[Image:bilinear|fig.2: Bilinear Structure]]
==Invariant properties for after, before and off==
The redefinition of <eiffel>off</eiffel> illustrates a general methodological advice about invariants: be careful about not over-constraining the invariant by including properties that may be made more general in descendants. It might have been tempting to include in [[ref:/libraries/base/reference/linear_chart|LINEAR]] an invariant clause of the form
<code>off = is_empty or after</code>
This property, however, would be too constraining. More precisely, it is always true that the right-hand side implies the left-hand-side: if a linear structure is either empty or after, then it is off. But the converse is not true, since certain kinds of linear structure, for example bilinear ones, may be off but neither empty nor after. <br/>
The actual invariant for class [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] is obtained in three stages. In class [[ref:/libraries/base/reference/traversable_chart|TRAVERSABLE]] the feature off is deferred and a basic property of that feature is expressed by the invariant clause
<code>empty_constraint:is_empty implies off</code>
In [[ref:/libraries/base/reference/linear_chart|LINEAR]] , feature <eiffel>off</eiffel> is effected through an implementation which returns the value of the expression <eiffel>is_empty</eiffel> or <eiffel>after</eiffel>. The class adds an invariant clause which, however, says less than the implementation to leave some room for variation:
<code>after_constraint:after implies off</code>
Finally [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] , an heir of [[ref:/libraries/base/reference/linear_chart|LINEAR]] , redefines <eiffel>off</eiffel> to return the value of the expression
<code>before or after</code>
and adds the invariant clause
<code>before_constraint: before implies off</code>
The new implementation of <eiffel>off</eiffel>
<code>after or before</code>
would not guarantee the invariant clause inherited from [[ref:/libraries/base/reference/traversable_chart|TRAVERSABLE]] were it not for another clause introduced in [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] :
<code>empty_property: is_empty implies (after or before )</code>
which indicates that an empty bilinear structure must always be <eiffel>after</eiffel> or <eiffel>before</eiffel> but not both, however, as stated by the last new clause, the reason for which is discussed in detail below:
<code>not_both: not(after and before)</code>
The flat-short form of [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] shows the complete reconstructed invariant:
<code>
not_both: not (after and before)
empty_property: is_empty implies (after or before)
before_constraint: before implies off
after_constraint: after implies off
empty_constraint: is_empty implies off</code>
==Iteration patterns==
For a more general form of this scheme, applicable to circular chains as well as other linear structures, replace <eiffel>off</eiffel> by <eiffel>exhausted</eiffel>. With the features shown above, a typical iteration mechanism on a non-empty linear structure 'lin' is of the form:
<code>
from
lin.start
some_optional_initializing_operation (lin)
until
lin.off
loop
lin.some_action (lin.item)
lin.forth
end</code>
The value of <code> lin </code> <code> . </code>off is always true for an empty structure, so in this case the loop will, correctly, execute only its initialization actions if present. <br/>
This is a very common pattern, which you will find in the library classes themselves (for example has is implemented in this way) and many application clients. The iterator classes corresponding to linear structures ([[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] ) turn this pattern and several related ones into actual reusable routines. <br/>
For bilinear structures there is another traversal mechanism going backward rather than forward; it is the same as above except that <eiffel>finish</eiffel> replaces <eiffel>start</eiffel> and <eiffel>back</eiffel> replaces <eiffel>finish</eiffel>. The exit condition remains <eiffel>off</eiffel> since <eiffel>before</eiffel>, like <eiffel>after</eiffel>, implies <eiffel>off</eiffel>.
==A precise view of after and before==
Getting the specification of <eiffel>after</eiffel> and before <eiffel>right</eiffel>, so that it will handle all cases properly, requires some care. <br/>
For every one of the structures under discussion there is a notion of current position, which we may call the cursor position even though for the moment the cursor is a virtual notion only. (Actual cursor objects will come later when we combine [[ref:/libraries/base/reference/linear_chart|LINEAR]] , [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] and other classes from the traversal hierarchy with [[ref:/libraries/base/reference/cursor_structure_chart|CURSOR_STRUCTURE]] and other classes from the collection hierarchy.) The informal definition is that <eiffel>after</eiffel> is true if and only if the cursor - in this informal sense of a fictitious marker signaling the current position - is one position after the last item, if any, and that <eiffel>before</eiffel> is true if and only if the cursor is one position before the first item. When the cursor is on any of the items, <eiffel>after</eiffel> and <eiffel>before</eiffel> are false; <eiffel>after</eiffel> holds when the cursor is to the right of the last item, and <eiffel>before</eiffel> when it is to the left of the first item. This leaves open the question of what conventions to take for an empty structure. If iteration schemes of the above type are to work, then <eiffel>after</eiffel> must be true for an empty structure. For a bilinear structure, however, we should have total symmetry between the two pairs of features
* <eiffel>start</eiffel>, <eiffel>forth</eiffel>, <eiffel>after</eiffel>.
* <eiffel>finish</eiffel>, <eiffel>back</eiffel>, <eiffel>before</eiffel>.
So for an empty list both <eiffel>before</eiffel> and <eiffel>after</eiffel> should be true. This scheme was used in early version of the Base libraries. It has some disadvantages, however; in particular it is not compatible with the simple, symmetric properties:
<code>after = (index = count + 1)
before = (index = 0)</code>
which express elementary definitions for <eiffel>after</eiffel> and <eiffel>before</eiffel> in terms of <eiffel>index</eiffel>, the current position, and <eiffel>count</eiffel>, the number of items (items being numbered from 1 to count). For an empty structure <eiffel>count</eiffel> is zero, so if we want <eiffel>after</eiffel> and <eiffel>before</eiffel> to be both true in this case we have to sacrifice one of the above properties, since the first would imply index to 1 and the second to 0. But again symmetry reigns supreme: we should either keep both properties or renounce both. The solution was to renounce both and replace them by slightly more complicated ones:
<code>after = (is_empty or (index = count + 1))
before = (is_empty or (index = 0))</code>
When a structure is created, some initializations will have to be made; the default initializations will usually lead to a value of 0 rather than 1 for index, although this dissymetry is not apparent in the assertions. Although acceptable, this solution leads to small but unpleasant complications, in particular frequent conditional instructions of the form
<code>if after and not is_empty then...</code>
The solution finally retained for the Base libraries uses a different technique, which has turned out to be preferable. The idea is to replace the conceptual picture by one in which there are always two fictitious sentinel items. The two sentinel items are only present conceptually. They are of course not taken into account for the computation of <eiffel>count</eiffel> and, although it is possible to conceive of an implementation which would actually reserve space for them (for example in an array representation), none of the implementations used in Base for the classes of this documentation and other descendants of [[ref:/libraries/base/reference/linear_chart|LINEAR]] do. The only purpose of the sentinels is to provide two valid theoretical cursor positions, which exist regardless of the number of actual (non-sentinel) items in the structure. <br/>
The sentinel items always appear at positions 0 and <eiffel>count</eiffel> + 1; this property is true even if the structure is empty of items, in which case count is zero. As a result, the following properties are part of the invariant:
<code>0 <= index
index <= count + 1
before = (index = 0)
after = (index = count + 1)
not (after and before)</code>
The last property given indicates that a structure can never be both <eiffel>after</eiffel> <code>and</code> <eiffel>before</eiffel>, since even in an empty structure the two sentinels are still present, with the cursor on one of them. For an empty structure, <eiffel>index</eiffel> will be zero by convention, so that <eiffel>before</eiffel> will be true and <eiffel>after</eiffel> false. But this property is not reflected in any of the invariant clauses.
==Some lessons==
This discussion has illustrated some of the important patterns of reasoning that are frequently involved in serious object-oriented design. Among the lessons are four ideas which you may find useful in many different cases. First, consistency is once again the central principle. Throughout the design of a class library we must constantly ask ourselves:
* How do I make my next design decision compatible with the previous ones?
* How do I take my next design decision so that it will be easy - or at least possible - to make future ones compatible with it?
Another frequent concern, partly a consequence of consistency, is symmetry. To mathematicians and physicists, symmetry considerations are often important in guiding the search for a solution to a problem; if the problem exhibits a certain symmetry, a candidate solution will be rejected if it does not satisfy that symmetry. Such was the situation here: since the structure's specification is symmetric with respect to the two possible directions of traversal, so too should the feature design be. <br/>
The third lesson is also well-known in mathematics and physics: the usefulness of looking at limit cases. To check that a design is sound it is often useful to examine what becomes of it when it is applied to extreme situations - in particular, as was done in this example, empty structures. <br/>
Finally, the only way to make delicate design decisions is to express the issues clearly through assertions, most notably invariants. To analyze the properties under discussion, and weigh the various alternatives, we need the precision of mathematical logic. Once again note that without assertions it would be impossible to build a good library; we would have no way to know precisely what we are talking about.
=Sequences And Chains=
Still deferred, classes [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] and[[ref:/libraries/base/reference/chain_chart|CHAIN]] provide the basis for all list and chain classes, as well as for many trees and for dispensers. <br/>
SEQUENCE is constructed with the full extent of the technique described in the discussion of the taxonomy: using multiple inheritance to combine one class each from the access, traversal and storage hierarchy. [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] indeed has three parents:
* [[ref:/libraries/base/reference/active_chart|ACTIVE]] gives the access properties. A sequence is an active structure with a notion of current item. Remember that active structures are a special case of bags.
* [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] , as studied above, indicates that a sequence may be traversed both ways.
* FINITE, from the storage hierarchy, indicates that the class describes finite sequences. (A class [[ref:/libraries/base/reference/countable_sequence_chart|COUNTABLE_SEQUENCE]] is also present, as described below.)
To the features of [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] , [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] principally adds features for adding, changing and removing items. A few procedures in particular serve to insert items at the end:
* <code> s .put ( v ) adds v at the end of a sequence s </code>.
* <eiffel>extend</eiffel> and <eiffel>force</eiffel>, at the [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] level, do the same as <eiffel>put</eiffel>.
* <code> s .append ( s1 ) adds to the end of s the items of s1 (another sequence), preserving their s1 </code> order.
Other procedures work on the current position:
* <code> s . </code><eiffel>remove</eiffel> removes the item at current position.
* <code> s .replace ( v ) replaces by v </code> the item at current position.
SEQUENCE, however, does not provide a procedure to insert an item at the current position, since not all implementations of sequences support this possibility; you will find it in descendants of [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] seen below. <br/>
Yet another group of features are based on the first occurrence of a certain item, or on all occurrences:
* <code> s .prune ( v ) removes the first occurrence of v in s </code>, if any.
* <code> s .prune_all ( v ) removes all occurrences of v </code>.
These procedures have various abstract preconditions: <code> s .extendible for additions, s .writable for replacements, s . </code><eiffel>prunable</eiffel> for removals. Properties <eiffel>extendible</eiffel> and <eiffel>prunable</eiffel> characterize general categories of container structures rather than individual instances; for example <eiffel>extendible</eiffel> is always true for the 'dynamic' structures seen below. In contrast, <eiffel>writable</eiffel> depends on the current status of each instance. In general <eiffel>writable</eiffel> will be true if there is an item at the current position.
==Chains==
Chains are sequences with a few more properties: items may be accessed through their indices, and it is possible to define cursor objects attached to individual items. <br/>
Class [[ref:/libraries/base/reference/chain_chart|CHAIN]] is an heir of [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] . It gets its access properties from [[ref:/libraries/base/reference/cursor_structure_chart|CURSOR_STRUCTURE]] (which adds the notion of cursor to the features of [[ref:/libraries/base/reference/active_chart|ACTIVE]] , already present in [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] ) and is also an heir of [[ref:/libraries/base/reference/indexable_chart|INDEXABLE]] . This ancestry implies in particular the presence of the following features:
* <eiffel>cursor</eiffel>, from [[ref:/libraries/base/reference/cursor_structure_chart|CURSOR_STRUCTURE]] , which makes it possible to keep a reference to an item of the structure.
* <eiffel>i_th</eiffel> and <eiffel>put_i_th</eiffel> from [[ref:/libraries/base/reference/table_chart|TABLE]] , via [[ref:/libraries/base/reference/indexable_chart|INDEXABLE]] , which make it possible to access and replace the value of an item given by its integer index.
These features were called <eiffel>item</eiffel> and <eiffel>put</eiffel> in [[ref:/libraries/base/reference/table_chart|TABLE]] , but are renamed here to remove the conflict with homonymous features from [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] . <br/>
Procedure <eiffel>put</eiffel> for chains is the version obtained from [[ref:/libraries/base/reference/cursor_structure_chart|CURSOR_STRUCTURE]] , which has the same effect as <eiffel>replace</eiffel> - replacing the value of the item at cursor position. The <eiffel>put</eiffel> procedure from [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] is renamed <eiffel>sequence_ put</eiffel>. This feature is not exported by [[ref:/libraries/base/reference/chain_chart|CHAIN]] , however, since its effect (adding an item at the end) may be obtained through the simpler name <eiffel>extend</eiffel>.
==Dynamic chains==
By default, chains can only be extended at the end, through <eiffel>extend</eiffel> and <eiffel>sequence_put</eiffel>. Of particular interest are those chains where clients can insert and remove items at any position. Such chains are said to be dynamic, and described by [[ref:/libraries/base/reference/chain_chart|CHAIN]] 's heir [[ref:/libraries/base/reference/dynamic_chain_chart|DYNAMIC_CHAIN]] . The new features are predictable:
* Procedure <eiffel>put_front</eiffel> adds an item before the first. (As noted, the procedures to add an item after the last are already available in chains.)
* Procedures <eiffel>put_left</eiffel> and <eiffel>put_right</eiffel> add an item at the left and right of the cursor position.
* Procedures <eiffel>remove_left</eiffel> and remove_right remove an item at the left and right or the cursor position.
* Procedures <eiffel>merge_left</eiffel> and <eiffel>merge_right</eiffel> are similar to <eiffel>put_left</eiffel> and <eiffel>put_right</eiffel> but insert another dynamic chain rather than a single item. As the word 'merge' suggests, the merged structure, passed as argument, does not survive the process; it is emptied of its items. To preserve it, perform a <eiffel>clone</eiffel> or <eiffel>copy</eiffel> before the merge operation.
The class also provides implementations of <eiffel>prune</eiffel>, <eiffel>prune_all</eiffel> and <eiffel>wipe_out</eiffel> from [[ref:libraries/base/reference/collection_chart]] . To make these implementations useful, it defines queries <eiffel>extendible</eiffel> and <eiffel>prunable</eiffel> so that they return the value true.
=Lists And Circular Structures=
A chain is a finite sequential structure. This property means that items are arranged in a linear order and may be traversed from the first to the last. To do this you may use a loop of the form shown above, based on procedures <eiffel>start</eiffel> and <eiffel>forth</eiffel>. <br/>
This property leaves room for several variants. In particular chains may be straight or circular.
* A straight chain, which from now on will be called a list, has a beginning and an end.
* A circular chain, as represented by class [[ref:/libraries/base/reference/circular_chart|CIRCULAR]] and its descendants, has a much more flexible notion of first item. It is organized so that every item has a successor.
This representation is conceptual only; in fact the implementations of circular chains found in the Base libraries are based on lists, implemented in one of the ways described below (in particular linked and arrayed). <br/>
The major originality of circular chains is that unless the structure is empty procedure <eiffel>forth</eiffel> is always applicable: it will cycle past the last item, coming back to the <br/>
first. The symmetric property applies to <eiffel>back</eiffel>. The cyclic nature of <eiffel>forth</eiffel> and <eiffel>back</eiffel> for circular chains is expressed precisely by the assertions. The version of <eiffel>forth</eiffel> for class [[ref:/libraries/base/reference/chain_chart|CHAIN]] , which comes from [[ref:/libraries/base/reference/linear_chart|LINEAR]] , has precondition
<code>not after</code>
Similarly, the precondition for back is
<code>not before</code>
For lists, after becomes true when the cursor moves past the last item. For circular chains, however, after and before are never true except for an empty structure; this is expressed by the invariant clauses of class [[ref:/libraries/base/reference/circular_chart|CIRCULAR]] :
<code>not before</code>
For a non-empty circular chain, then, you can circle forever around the items, using forth or back.
==Choosing the first item==
For a list, the first and last items are fixed, and correspond to specific places in the physical representation. <br/>
A circular chain also needs a notion of first item, if only to enable a client to initiate a traversal through procedure start. Similarly, there is a last item - the one just before the first in a cyclic traversal. (If the chain has just one item, it is both first and last.) <br/>
For circular chains, however, there is no reason why the first item should always remain the same. One of the benefits that clients may expect from the use of a circular <br/>
structure is the ability to choose any item as the logical first. Class [[ref:/libraries/base/reference/circular_chart|CIRCULAR]] offers for that purpose the procedure <eiffel>set_start</eiffel> which designates the current cursor position as the first in the circular chain. Subsequent calls to <eiffel>start</eiffel> will move the cursor to this position; calls to <eiffel>finish</eiffel> will move the cursor to the cyclically preceding position. With most implementations, there will then be two notions of first position: the logical first, which clients may freely choose through calls to <eiffel>set_start</eiffel>; and the <eiffel>physical first</eiffel>, which results from the implementation. In a representation using an array with indices from 1 to <eiffel>capacity</eiffel>, for example, the physical first is position 1, and the logical first may be any index in the permitted range. In a linked representation, there will be a cell first element corresponding to the physical first, but the logical first is any cell in the chain. <br/>
In such cases the circular chain classes have features called <eiffel>standard_first</eiffel>, <eiffel>standard_last</eiffel>, <eiffel>standard_start</eiffel> and so on, which are not exported (so that you will not see them in the flat-short forms) but serve to implement visible features such as <eiffel>first</eiffel>, <eiffel>last</eiffel> and <eiffel>forth</eiffel>. For example a possible implementation of <eiffel>forth</eiffel> for circular chains is
<code>forth is
-- Move cursor to next item, cyclically.
do
standard_forth
if standard_after then
standard_start
end
if isfirst then
exhausted := True
end
end</code>
==Traversing a list or circular chain==
The properties of <eiffel>forth</eiffel> for circular chains imply that a traversal loop written as
<code>from
lin.start
until
lin.off
loop
...
lin.forth
end </code>
would not work if <code> lin </code> is a non-empty circular structure: <eiffel>off</eiffel> would never become true, so that the loop would forever cycle over the structure's items. The same would apply to a loop using finish and back instead of <eiffel>start</eiffel> and <eiffel>forth</eiffel>. This behavior is the natural result of the semantics defined for <eiffel>off</eiffel> , <eiffel>forth</eiffel> and <eiffel>back</eiffel> for circular structures. But it prevents us from using these features to perform a single traversal which will visit every item once. <br/>
Using <eiffel>exhausted</eiffel> in lieu of off solves this problem. In class [[ref:/libraries/base/reference/circular_chart|CIRCULAR]] , <eiffel>exhausted</eiffel> is an attribute which is set to false by <eiffel>start</eiffel> and <eiffel>finish</eiffel>, and is set to true by <eiffel>forth</eiffel> when advancing from the last item to the first and by <eiffel>back</eiffel> when backing up from the first item to the last. So you should write the loop as
<code>from
lin.start
some_optional_initializing_operation (lin)
until
lin.exhausted
loop
...
lin.some_action (lin.item)
lin.forth
end</code>
This form is applicable to all linear structures, circular or not, since <eiffel>exhausted</eiffel> is introduced in class [[ref:/libraries/base/reference/linear_chart|LINEAR]] as a function which returns the same value as <eiffel>off</eiffel> .Its redefinition into an attribute, modified by <eiffel>start</eiffel>,<eiffel> finish</eiffel>, <eiffel>forth</eiffel> and <eiffel>back</eiffel>, does not occur until class [[ref:/libraries/base/reference/circular_chart|CIRCULAR]] . <br/>
Because <eiffel>exhausted</eiffel> is more general than <eiffel>off</eiffel> , the iteration scheme just given (and its equivalent going backwards) is preferable to the earlier one using <eiffel>off </eiffel>, especially if there is any chance that the iteration might one day be applied to a lin structure that is circular. Classes of the Iteration library, in particular [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , rely on this scheme for iterating over linear structures.
==Dynamic structures==
For both lists and circular chains, the most flexible variants, said to be dynamic, allow insertions and deletions at any position. <br/>
The corresponding classes are descendants of [[ref:/libraries/base/reference/dynamic_list_chart|DYNAMIC_LIST]] and [[ref:/libraries/base/reference/dynamic_circular_chart|DYNAMIC_CIRCULAR]] , themselves heirs of [[ref:/libraries/base/reference/dynamic_chain_chart|DYNAMIC_CHAIN]] studied above. <br/>
==Infinite sequences==
Class [[ref:/libraries/base/reference/countable_sequence_chart|COUNTABLE_SEQUENCES]] , built by inheritance from [[ref:/libraries/base/reference/countable_chart|COUNTABLE]] , [[ref:/libraries/base/reference/linear_chart|LINEAR]] and [[ref:/libraries/base/reference/active_chart|ACTIVE]] , is similar to [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] but describes infinite rather than finite sequences.
=Implementations=
We have by now seen the concepts underlying the linear structures of the Base libraries, especially lists and circular chains. Let us look at the techniques used to implement them.
==Linked and arrayed implementations==
Most of the implementations belong to one of four general categories, better described <br/>
as two categories with two subcategories each:
* Linked implementations, which may be one-way or two-way.
* Arrayed implementations, which may be resizable or fixed.
A linked implementation uses linked cells, each containing an item and a reference to the next cell. One-way structures are described by classes whose names begin with LINKED_, for example [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] . Two-way structures use cells which, in addition to the reference to the next cell, also include a reference to the previous one. Their names begin with TWO_WAY_. <br/>
An arrayed implementation uses an array to represent a linear structure. If the array is resizable, the corresponding class name begins with ARRAYED_, for example <br/>
[[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] ; if not, the prefix is FIXED_.
==Linked structures==
A linked structure requires two classes: one, such as [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] , describes the list proper; the other, such as [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] , describes the individual list cells. The figure should help understand the difference; it describes a linked list, but the implementation of linked circular chains is similar.
[[Image:linked-list|fig.3: Linked list and linked cells]]
The instance of type [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] shown at the top contains general information about the list, such as the number of items (<eiffel>count</eiffel>) and a reference to the first element (first). Because lists are active structures with a notion of current position, there is also a reference active to the cell at the current position. An entity declared as
<code>my_list: LINKED_LIST [SOME_TYPE] </code>
will have as its run-time value (if not void) a reference to such an object, which is really a list header. The actual list content is given by the [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] instances, each of which contains a value of type <eiffel>SOME_TYPE</eiffel> and a reference to the next item, called <eiffel>right</eiffel>. <br/>
Clearly, a header of type [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] <code> [ </code> <eiffel>SOME_TYPE</eiffel> <code> ] will be associated with cells of type [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] [ </code> <eiffel>SOME_TYPE</eiffel> <code> ] </code>. <br/>
Features such as active and first are used only for the implementation; they are not exported, and so you will not find them in the flat-short specifications, although the figures show them to illustrate the representation technique. <br/>
A similar implementation is used for two-way-linked structures such as two-way lists and two-way circular chains.
[[Image:two-way-list|fig.4: Two way linked list]]
==Linked cells==
The classes describing list cells are descendants of a deferred class called [[ref:/libraries/base/reference/cell_chart|CELL]] , whose features are:
* <eiffel>item</eiffel>, the contents of the cell.
* <eiffel>put </eiffel> <code> ( v : </code> <code> like </code> <eiffel>item</eiffel> <code> ) </code>, which replaces the contents of the cell by a new value.
Class [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] is an effective descendant of [[ref:/libraries/base/reference/cell_chart|CELL]] , used for one-way linked structures. It introduces features <eiffel>right</eiffel>, a reference to another cell to which the current <br/>
cell will be linked. Two-way linked structures use [[ref:/libraries/base/reference/bi_linkable_chart|BI_LINKABLE]] , an heir of [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] which to the above features adds <eiffel>left</eiffel>, a reference to the preceding cell in the structure.
{{warning| '''Caution''': Do not confuse the <eiffel>item</eiffel> feature of [[ref:/libraries/base/reference/cell_chart|CELL]] and its descendants, such as [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] , with the <eiffel>item</eiffel> feature of the classes describing linear structures, such as [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] . For a linked list, <eiffel>item</eiffel> returns the item at cursor position. }}
It may be implemented as
<code>item: G is
-- Current item
do
Result := active.item
end</code>
using the <eiffel>item</eiffel> feature of [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] , applied to <eiffel>active</eiffel>.
==One-way and two-way linked chains==
If you look at the interfaces of one-way and two-way linked structures, you will notice that they are almost identical. This is because it is possible to implement features such as <eiffel>back</eiffel> for one-way structures such as described by [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] and [[ref:/libraries/base/reference/linked_circular_chart|LINKED_CIRCULAR]] . A simple implementation of <eiffel>back</eiffel> stores away a reference to the current active item, executes <eiffel>start</eiffel>, and then performs <eiffel>forth</eiffel> until the item to the right of the cursor position is the previous <eiffel>active</eiffel>. <br/>
Although correct, such an implementation is of course rather inefficient since it requires a traversal of the list. In terms of algorithmic complexity, it is in O (<eiffel>count</eiffel>), meaning that its execution time is on the average proportional to the number of items in the structure. In contrast, <eiffel>forth</eiffel> is O (1), that is to say, takes an execution time bounded by a constant.
{{warning| '''Caution''': As a consequence, you should not use one-way linked structures if you need to execute more than occasional <eiffel>back</eiffel> operations (and other operations requiring access to previous items, such as <eiffel>remove_left</eiffel>). }}
Two-way linked structures, such as those described by [[ref:/libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] and [[ref:/libraries/base/reference/two_way_circular_chart|TWO_WAY_CIRCULAR]] , treat the two directions symmetrically, so that <eiffel>back</eiffel> will be just as efficient as <eiffel>forth</eiffel>. Hence the following important advice: If you need to traverse a linked structure both ways, not just left to right, use the <eiffel>TWO_WAY_</eiffel> classes, not the <eiffel>LINKED_</eiffel> versions. The <eiffel>TWO_WAY_</eiffel> structures will take up more space, since they use [[ref:/libraries/base/reference/bi_linkable_chart|BI_LINKABLE]] rather than [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] cells, but for most applications this space penalty is justified by the considerable gains in time that will result if right-to-left operations are frequently needed.
==Arrayed chains==
Arrayed structures as described by [[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] , [[ref:/libraries/base/reference/fixed_list_chart|FIXED_LIST]] and [[ref:/libraries/base/reference/arrayed_circular_chart|ARRAYED_CIRCULAR]] use arrays for their implementations. A list or circular chain of <eiffel>count</eiffel> items may be stored in positions 1 to <eiffel>count</eiffel> of an array of <eiffel>capacity</eiffel> items, where <eiffel>capacity</eiffel> >= <eiffel>count</eiffel>. <br/>
An instance of [[ref:/libraries/base/reference/fixed_list_chart|FIXED_LIST]] , as the name suggests, has a fixed number of items. In particular:
* Query extendible has value false for [[ref:/libraries/base/reference/fixed_list_chart|FIXED_LIST]] : you may replace existing items, but not add any, even at the end. A [[ref:/libraries/base/reference/fixed_list_chart|FIXED_LIST]] is created with a certain number of items and retains that number.
* As a result, [[ref:/libraries/base/reference/fixed_list_chart|FIXED_LIST]] joins the deferred feature count of [[ref:/libraries/base/reference/list_chart|LIST]] with the feature count of ARRAY, which satisfies the property <eiffel>count</eiffel> = <eiffel>capacity</eiffel>.
* Query <eiffel>prunable </eiffel>has value false too: it is not possible to remove an item from a fixed list.
In contrast, [[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] has almost the same interface as [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] . In particular, it is possible to add items at the end using procedure <eiffel>extend</eiffel>; if the call causes the list to grow beyond the current array's capacity, it will trigger a resizing. This is achieved by using the procedure <eiffel>force</eiffel> of class ARRAY to implement <eiffel>extend</eiffel>. [[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] even has the insertion procedures (<eiffel>put_front</eiffel>, <eiffel>put_left</eiffel>, <eiffel>put_right</eiffel>) and removal procedures (<eiffel>prune</eiffel>, <eiffel>remove</eiffel>, <eiffel>remove_left</eiffel>, <eiffel>remove_right</eiffel>) that apply to arbitrary positions and appear in the linked implementations. These procedures, however, are rather inefficient, since they usually require moving a whole set of array items, an O (count) operation. (Procedure <eiffel>extend</eiffel> does not suffer from this problem, since it is easy to add an item to the end of an array, especially if there is still room so that no resizing is necessary.)
{{warning| '''Caution''': The situation of these features in [[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] is similar to the situation of <eiffel>back</eiffel> in classes describing one-way linked structures: it is convenient to include them because they may be needed once in a while and an implementation exists; but using them more than occasionally may result in serious inefficiencies. If you do need to perform arbitrary insertions and removal, use linked structures, not arrayed ones. }}
Arrayed structures, however, use up less space than linked representations. So they are appropriate for chains on which, except possibly for insertions at the end, few insertion and removal operations or none at all are expected after creation. [[ref:/libraries/base/reference/fixed_list_chart|FIXED_LIST]] offers few advantages over [[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] . [[ref:/libraries/base/reference/fixed_list_chart|FIXED_LIST]] may be useful, however, for cases in which the fixed number of items is part of the specification, and any attempt to add more items must be treated as an error. For circular chains only one variant is available, [[ref:/libraries/base/reference/arrayed_circular_chart|ARRAYED_CIRCULAR]] , although writing a <eiffel>FIXED_</eiffel> version would be a simple exercise.
==Multi-arrayed lists==
For lists one more variant is available, combining some of the advantages of arrayed and linked implementations: [[ref:/libraries/base/reference/multi_array_list_chart|MULTI_ARRAY_LIST]] . With this implementation a list is <br/>
divided into a number of blocks. Each block is an array, but the successive arrays are linked.
=Sorted Linear Structures=
The class [[ref:/libraries/base/reference/comparable_struct_chart|COMPARABLE_STRUCT]] , an heir of [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] , is declared as
<code>deferred class
COMPARABLE_STRUCT [G -> COMPARABLE]
inherit
BILINEAR
feature
... </code>
As indicated by the constrained generic parameter it describes bilinear structures whose items may be compared by a total order relation.
{{warning| '''Caution''': Note that the class name, chosen for brevity's sake, is slightly misleading: it is not the structures that are comparable but their items. }}
COMPARABLE_STRUCT introduces the features <eiffel>min</eiffel> and <eiffel>max</eiffel>, giving access to the minimum and maximum elements of a structure; these are always present for a finite <br/>
structure with a total order relation. [[ref:/libraries/base/reference/sorted_struct_chart|SORTED_STRUCT]] , an heir of [[ref:/libraries/base/reference/comparable_struct_chart|COMPARABLE_STRUCT]] , describes structures that can be sorted; it introduces the query sorted and the command sort. <br/>
The deferred class [[ref:/libraries/base/reference/part_sorted_list_chart|PART_SORTED_LIST]] describes lists whose items are kept ordered in a way that is compatible with a partial order relation defined on them. The class is declared as
<code>deferred class
PART_SORTED_LIST [G -> COMPARABLE]...</code>
An implementation based on two-way linked lists is available through the effective heir [[ref:/libraries/base/reference/sorted_two_way_list_chart|SORTED_TWO_WAY_LIST]] . <br/>
The deferred class [[ref:/libraries/base/reference/sorted_list_chart|SORTED_LIST]] , which inherits from [[ref:/libraries/base/reference/part_sorted_list_chart|PART_SORTED_LIST]] , assumes that the order relation on G is a total order. As a result, the class is able to introduce features <eiffel>min</eiffel>, <eiffel>max</eiffel> and <eiffel>median</eiffel>. Here too a two-way linked list implementation is available, through the effective class [[ref:/libraries/base/reference/sorted_two_way_list_chart|SORTED_TWO_WAY_LIST]] .

View File

@@ -0,0 +1,35 @@
[[Property:title|EiffelBase, Dispensers]]
[[Property:weight|2]]
A dispenser is called that way because of the image of a vending machine (a dispenser) of a rather primitive nature, in which there is only one button. If you press the button and the dispenser is not empty, you get one of its items in the exit tray at the bottom, but you do not choose that item: the machine does. There is also an input slot at the top, into which you may deposit new items; but you have no control over the order in which successive button press operations will retrieve these items.
The deferred class [[ref:/libraries/base/reference/dispenser_chart|DISPENSER]] provides the facilities which will be shared by all specialized classes. In fact, the interface of all dispenser classes is nearly identical, with the exception of a few extra possibilities offered by priority queues. Many kinds of dispenser are possible, each defined by the relation that the machine defines between the order in which items are inserted and the order in which they arereturned. The Base libraries support three important categories - stacks, queues, and priority queues:
* A stack is a dispenser with a last-in, first-out (LIFO) internal policy: items come out in the reverse order of their insertion. Each button press returns the last deposited item.
* A queue is a dispenser with a first-in, first-out (FIFO) internal policy: items come out in the order of their insertion. Each button press returns the oldest item deposited and not yet removed.
* In a priority queue, items have an associated notion of order; the element that comes out at any given time is the largest of those which are in the dispenser.
==Stacks==
Stacks - dispensers with a LIFO retrieval policy - are a ubiquitous structure in software development. Their most famous application is to parsing (syntactic analysis), but many other types of systems use one or more stacks. Class STACK describes general stacks, without commitment to a representation. This is a deferred class which may not be directly instantiated. The fundamental operations are put (add an element at end of queue), item (retrieve the oldest element, non-destructively), remove (remove the oldest element), is_empty (test for empty queue). <br/>
Three effective heirs are provided:
* [[ref:/libraries/base/reference/linked_stack_chart|LINKED_STACK]] : stacks implemented as linked lists, with no limit on the number of items (<eiffel>count</eiffel>).
* [[ref:/libraries/base/reference/bounded_stack_chart|BOUNDED_STACK]] : stacks implemented as arrays. For such stacks, the maximum number of items (<eiffel>capacity</eiffel>) is set at creation time.
* [[ref:/libraries/base/reference/arrayed_stack_chart|ARRAYED_STACK]] : also implemented as arrays, but in this case there is no limit on the number of items; the interface is the same as [[ref:/libraries/base/reference/linked_stack_chart|LINKED_STACK]] except for the creation procedure. If the number of elements exceeds the initially allocated capacity, the array will simply be resized.
==Queues==
Class [[ref:/libraries/base/reference/queue_chart|QUEUE]] describes general queues, without commitment to a representation. This is a deferred class which may not be directly instantiated. Three non-deferred heirs are also provided, distinguished by the same properties as their stack counterparts:
* [[ref:/libraries/base/reference/linked_queue_chart|LINKED_QUEUE]]
* [[ref:/libraries/base/reference/bounded_queue_chart|BOUNDED_QUEUE]]
* [[ref:/libraries/base/reference/arrayed_queue_chart|ARRAYED_QUEUE]]
==Priority Queues==
In a priority queue, each item has an associated priority value, and there is an order relation on these values. The item returned by item or removed by remove is the element with the highest priority.The most general class is [[ref:/libraries/base/reference/priority_queue_chart|PRIORITY_QUEUE]] , which is deferred. Two effective variants are provided:
* [[ref:/libraries/base/reference/linked_priority_queue_chart|LINKED_PRIORITY_QUEUE]] , a linked list implementation.
* [[ref:/libraries/base/reference/heap_priority_queue_chart|HEAP_PRIORITY_QUEUE]] which is more efficient and is to be preferred in most cases. A heap is organized like a binary tree, although physically stored in an array; elements with a high priority percolate towards the root.
Because it must be possible to compare priorities, the type of the items must conform to [[ref:/libraries/base/reference/part_comparable_chart|PART_COMPARABLE]] . Constrained genericity ensures this; all the priority queue classes have a formal generic parameter constrained by [[ref:/libraries/base/reference/part_comparable_chart|PART_COMPARABLE]] .

View File

@@ -0,0 +1,572 @@
[[Property:title|EiffelBase, Iteration]]
[[Property:weight|6]]
The classes of the Iteration cluster encapsulate control structures representing common traversal operations.
=Iterators and Agents=
The recent introduction of the agents mechanism in Eiffel offers an attractive alternative to the <eiffel>Iterator</eiffel> cluster of EiffelBase.
=The Notion of iterator=
Let us first explore the role of iterators in the architecture of a system.
==Iterating over data structures==
Client software that uses data structures of a certain type, for example lists or trees, often needs to traverse a data structure of that type in a predetermined order so as to apply a certain action to all the items of the structure, or to all items that satisfy a certain criterion. Such a systematic traversal is called an iteration. <br/>
Cases of iteration can be found in almost any system. Here are a few typical examples:
* A text processing system may maintain a list of paragraphs. In response to a user command, such as a request to resize the column width, the system will iterate over the entire list so as to update all paragraphs.
* A business system may maintain a list of customers. If the company decides that a special promotion will target all customers satisfying a certain criterion (for example all customers that have bought at least one product over the past six months), the system will iterate over the list, generating a mailing for every list item that satisfies the criterion.
* An interactive development environment for a programming language may maintain a syntax tree. In response to a program change, the system will traverse the tree to determine what nodes are affected by the change and update them.
These examples illustrate the general properties of iteration. An iteration involves a data structure of a known general type and a particular ordering of the structure's items. For some structures, more than one ordering will be available; for example a tree iteration may use preorder, postorder or breadth-first (as defined below). The iteration involves an operation, say <eiffel>item_action</eiffel>, to be applied to the selected items. It may also involve a boolean-valued query, say <eiffel>item_test</eiffel>, applicable to candidate items. Finally, it involves a certain policy, usually based on <eiffel>item_test</eiffel>, as to which items should be subjected to <eiffel>item_action</eiffel>. Typical example policies are:
* Apply <eiffel>item_action</eiffel> to all the items in the structure. (In this case item_test is not relevant).
* Apply <eiffel>item_action</eiffel> to all items that satisfy <eiffel>item_test</eiffel>.
* Apply <eiffel>item_action</eiffel> to all items up to the first one that satisfies <eiffel>item_test</eiffel>.
The Iteration library provides many more, covering in particular all the standard control structures.
==Iterations and control structures==
You can perform iterations without any special iteration classes. For example if customers is declared as
<code>customers: LIST [CUSTOMER]</code>
then a class <eiffel>SPECIAL_PROMOTION</eiffel> of a text processing system may include in one of its routines a loop of the form
<code>
from
customers.start
until
customers.exhausted
loop
if recent_purchases.has (customers.item>) then
target_list.put (customers.item>)
end
customers.forth
end</code>
Such schemes are quite common. But it is precisely because they occur frequently that it is useful to rely on library classes to handle them. One of the principal tasks of object-oriented software development is to identify recurring patterns and build reusable classes that encapsulate them, so that future developers will be able to rely on ready-made solutions. <br/>
The classes of the Iteration library address this need. Using them offers two benefits:
* You avoid writing loops, in which the definition of sub-components such as exit conditions, variants and invariants is often delicate or error-prone.
* You can more easily adapt the resulting features in descendant classes. The rest of this chapter shows how to obtain these benefits.
=Simple Examples=
To get a first grasp of how one can work with the Iteration library, let us look at a typical iteration class and a typical iteration client.
==An example iterator routine==
Here, given with its full implementation, is a typical Iteration library routine: the procedure until_do from [[ref:libraries/base/reference/linear_iterator_chart]] , the class defining iteration mechanisms on linear (sequential) structures.
<code>
until_do is
-- Apply action to every item of target,
-- up to but excluding first one satisfying test.
-- (Apply to full list if no item satisfies test.)
require
traversable_exists: target /= Void
do
from
target.start
invariant
''invariant_value''
until
target.exhausted or else test
loop
action
target.forth
end
ensure
achieved: target.exhausted or else test
invariant_satisfied: ''invariant_value''
end</code>
The precise form of the procedure in the class relies on a call to another procedure, until_continue, and on inherited assertions. Here everything has been unfolded for illustration purposes. <br/>
This procedure will traverse the linear structure identified by target and apply the procedure calledaction on every item up to but excluding the first one satisfying test. <br/>
The class similarly offers <eiffel>do_all</eiffel>, <eiffel>do_while</eiffel>, <eiffel>do_for</eiffel>, <eiffel>do_if</eiffel> and other procedures representing the common control structures. It also includes functions such as <eiffel>exists</eiffel> and <eiffel>forall</eiffel>, corresponding to the usual quantifiers. <br/>
These iteration schemes depend on the procedure <eiffel>action</eiffel>, defining the action to be applied to successive elements, and on the function <eiffel>test</eiffel>, defining the boolean query to be applied to these elements. These features are declared in class [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] (the highest-level deferred class of the Iteration library); here is <eiffel>test</eiffel>:
<code>
test: BOOLEAN is
-- Test to be applied to item at current position in
-- target (default: value of item_test on item)
require
traversable_exists: target /= Void
not_off: not target.off
do
Result := item_test (target.item>)
ensure
not_off: not target.off
end</code>
This indicates that the value of the boolean function <eiffel>test</eiffel> will be obtained by applying <eiffel>item_test</eiffel> to the item at the current position in the target structure. In [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] , function <eiffel>item_test</eiffel> always return ; descendant classes will redefine it so as to describe the desired test. Similarly, <eiffel>action</eiffel> is declared in class [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] as a call to <eiffel>item_action</eiffel>. Descendants will redefine <eiffel>item_action</eiffel>, which as initially declared in [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] is a procedure with a null body. <br/>
Going through <eiffel>item_action</eiffel> and <eiffel>item_test</eiffel> provides an extra degree of flexibility. Normally the action and test performed at each step apply to <eiffel>target</eiffel> <code> . </code><eiffel>item></eiffel>, so that it suffices to redefine the <eiffel>item_features</eiffel>. This is the case with all examples studied in this chapter. In a more general setting, however, you might need to redefine <eiffel>action</eiffel> and <eiffel>test</eiffel> themselves.
==An example use of iteration==
Here now is an example illustrating the use of these mechanisms. The result will enable us to resize all the paragraphs of a text up to the first one that has been modified - as we might need to do, in a text processing system, to process an interactive user request. Assume a class <eiffel>TEXT</eiffel> that describes lists of paragraphs with certain additional features. The example will also assume a class <eiffel>PARAGRAPH</eiffel> with a procedure <eiffel>resize</eiffel>, and a boolean-valued attribute <eiffel>modified</eiffel> which indicates whether a paragraph has been modified. Class <eiffel>TEXT</eiffel> inherits from [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] and so is a descendant of [[ref:/libraries/base/reference/linear_chart|LINEAR]] :
<code>
class
TEXT
inherit
LINKED_LIST [PARAGRAPH]
...
feature
...
end</code>
In a class <eiffel>TEXT_PROCESSOR</eiffel>, you can use an iteration procedure to write a very simple procedure <eiffel>resize_ paragraphs</eiffel> that will resize all paragraphs up to but excluding the first one that has been modified:
<code>
class
TEXT_PROCESSOR
inherit
LINEAR_ITERATOR [PARAGRAPH]
redefine
item_action, item_test
end
feature
resize_paragraphs (t: TEXT) is
-- Resize all the paragraphs of t up to but excluding
-- the first one that has been modified.
do
set (t)
until_do
end
feature {NONE}
item_test (p PARAGRAPH): BOOLEAN is
-- Has p been modified?
do
Result := p.modified
end
item_action (p: PARAGRAPH) is
-- Resize p.
do
p.resize
end
...
end</code>
Thanks to the iteration mechanism, the procedure <eiffel>resize_paragraphs</eiffel> simply needs two procedure calls:
* To set its argument <code> t </code> as the iteration target, it uses procedure <eiffel>set</eiffel>. (This procedure is from class [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] which passes it on to all iterator classes.)
* Then it simply calls <eiffel>until_do</eiffel> as defined above.
Procedure <eiffel>item_action</eiffel> is redefined to describe the operation to be performed on each successive element. Function <eiffel>item_test</eiffel> is redefined to describe the exit test. <br/>
As presented so far, the mechanism seems to limit every descendant of an iteration class to just one form of iteration. As shown later in this chapter, it is in fact easy to generalize the technique to allow a class to use an arbitrary number of iteration schemes. <br/>
What is interesting here is that the redefinitions of <eiffel>item_test</eiffel> and <eiffel>item_action</eiffel> take care of all the details. There is no need to write any loop or other control structure. We are at the very heart of the object-oriented method, enjoying the ability to encapsulate useful and common software schemes so that client developers will only need to fill in what is specific to their application.
=Using the Iteration Library=
Let us now explore the classes of the Iteration library and the different ways of using them.
==Overview of the classes==
There are only four Iteration classes, whose simple inheritance structure appeared at the beginning of this chapter.
* [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] , a deferred class which describes the most general notion.
* [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , for iterating over linear structures and chains.
* [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] , a repeated heir of [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , for iterating in either direction over a bilinear structure.
* [[ref:/libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] , for iterating over trees.
As you will remember from the [[EiffelBase, Abstract Container Structures: The Taxonomy|presentation]] of the abstract overall taxonomy, the traversal hierarchy describes how data structures can be traversed; its most general class is [[ref:/libraries/base/reference/two_way_list_chart|TRAVERSABLE]] . <br/>
Each one of the iterator classes is paired with a traversal class (or two in one case):
{|
|-
| [[ref:/libraries/base/reference/iterator_chart|ITERATOR]]
| [[ref:/libraries/base/reference/two_way_list_chart|TRAVERSABLE]]
|-
| [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]]
| [[ref:/libraries/base/reference/linear_chart|LINEAR]]
|-
| [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]]
| [[ref:/libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]]
|-
| [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]]
| [[ref:/libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] , [[ref:/libraries/base/reference/two_way_circular_chart|TWO_WAY_CIRCULAR]]
|-
| [[ref:/libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]]
| [[ref:/libraries/base/reference/cursor_tree_chart|CURSOR_TREE]]
|}
Each iterator class relies on the corresponding traversal class to provide the features for traversing the corresponding data structures, such as <eiffel>start</eiffel>, <eiffel>forth</eiffel> and <eiffel>exhausted</eiffel> for linear structures. <br/>
Of course the data structure class used in connection with a given iterator class does not need to be the iterator's exact correspondent as given by the above table; it may be any one of its descendants. For example you may use [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] to iterate over data structures described not just by [[ref:/libraries/base/reference/linear_chart|LINEAR]] but also by such descendants as [[ref:/libraries/base/reference/list_chart|LIST]] , [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] , [[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] , or even [[ref:/libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] if you do not need the backward iteration features (for which you will have to use [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] ).
==General iteration facilities==
Class [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] defines the features that apply to all forms of iterator. <br/>
An iterator will always apply to a certain target structure. The target is introduced in [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] by the feature target: [[ref:/libraries/base/reference/traversable_chart|TRAVERSABLE]] [G] <br/>
Both the iterator classes and the traversal classes are generic, with a formal generic parameter G. The actual generic parameters will be matched through the choice of iteration target: for a generic derivation of the form <eiffel>SOME_ITERATOR</eiffel> [ <eiffel>ACTUAL_TYPE</eiffel>] the target can only be of type <eiffel>SOME_TRAVERSABLE</eiffel> [ <eiffel>ACTUAL_TYPE</eiffel>] for the same <eiffel>ACTUAL_TYPE</eiffel>, where <eiffel>SOME_TRAVERSABLE</eiffel> is the traversal class matching <eiffel>SOME_ITERATOR</eiffel> according to the preceding table ([[ref:/libraries/base/reference/linear_chart|LINEAR]] for [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] and so on), or one of its proper descendants. <br/>
Each of the proper descendants of [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] redefines the type of target to the matching proper descendant of [[ref:/libraries/base/reference/traversable_chart|TRAVERSABLE]] , to cover more specific variants of the iteration target, For example in [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] the feature is redefined to be of type [[ref:/libraries/base/reference/linear_chart|LINEAR]] . [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] also introduces the procedure for selecting a target:
<code>
set (s: like target) is
-- Make s the new target of iterations.
require
s /= Void
do
target := s
ensure
target = s
target /= Void
end</code>
Next [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] introduces the routines describing the elementary action and test that will be applied to items of the iteration targets:
<code>
action is
-- Action to be applied to item at current position in
-- target.
-- (default: item_action on item at current position.)
-- Note: for iterators to work properly, redefined
-- versions of this feature should not change the
-- traversable structure.
require
traversable_exists: target /= Void
not_off: not target.off
invariant_satisfied: invariant_value
do
item_action (target.item>)
ensure
not_off: not target.off
invariant_satisfied: invariant_value
end
test: BOOLEAN is
-- Test to be applied to item at current position in
-- target (default: value of item_test on item)
require
traversable_exists: target /= Void
not_off: not target.off
do
Result := item_test (target.item>)
ensure
not target.off
end</code>
These routines rely on two others, <eiffel>item_action</eiffel> and <eiffel>item_test</eiffel>, which both take an argument of type G, the formal generic parameter. The reason, already noted above, is that in a vast majority of cases the iterated action and test solely depend, at each step of the traversal, on the item (of type G) at the current position. To define an iteration process, then, it suffices to redefine<eiffel> item_action</eiffel> and <eiffel>item_test</eiffel> in a descendant of the appropriate iteration class. Only in complex cases will it be necessary to redefine <eiffel>action</eiffel> and <eiffel>test</eiffel> themselves. <br/>
If you encounter such a case, note the caveat about action changing the target's structure. Understandably enough, an iterator that attempts to change the data structure while traversing it may engage in strange behavior. No such risk exists if you only redefine <eiffel>item_action</eiffel>, which may change the contents of items but not the structure itself. <br/>
Another feature introduced in [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] is the query <eiffel>invariant_value</eiffel>, describing invariant properties that must be ensured at the beginning of any iteration and preserved by every iteration step. As declared in [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] this query always returns true, but proper descendants can redefine it to describe more interesting invariant properties. <br/>
Finally, [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] introduces in deferred form the general iteration routines applicable to all iteration variants. They include two queries corresponding to the quantifiers of first-order predicate calculus:
* <eiffel>for_all</eiffel> will return true if all items of the target structure satisfy test.
* <eiffel>exists</eiffel> will return true if at least one item satisfies test.
The other routines are commands which will traverse the target structure and apply action to items selected through test:
* <eiffel>do_all</eiffel> applies <eiffel>action</eiffel> to all items.
* <eiffel>do_if</eiffel>, to those items which satisfy test.
* <eiffel>until_do</eiffel>, to all items up to but excluding the first one that satisfies test.
* <eiffel>do_until</eiffel>, to all items up to and including the first one that satisfies test.
* <eiffel>while_do</eiffel> and <eiffel>do_while</eiffel>, to all items up to the first one that does not satisfy test. (This can also be achieved with <eiffel>until_do</eiffel> or <eiffel>do_until </eiffel> by choosing the opposite test.)
All these features, and most of the other iteration features introduced in proper descendants of [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] and described next, have no argument. Information about the target of iteration comes from feature <eiffel>target</eiffel>, set by procedure <eiffel>set</eiffel>; information about what needs to be done for each item of the target structure comes from <eiffel>item_action</eiffel> and <eiffel>item_test</eiffel>.
==Linear and chain iteration==
[[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , an effective class, refines the iteration mechanisms for cases in which the target is a linear structure, such as a list in any implementation or a circular chain. <br/>
The class effects all the deferred features inherited from [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] , taking advantage of the linear traversal mechanisms present in the corresponding traversal class, [[ref:/libraries/base/reference/linear_chart|LINEAR]] . Here for example is the effecting of <eiffel>do_if</eiffel>:
<code>
do_if is
-- Apply action to every item of target satisfying
-- test.
do
from
target.start
invariant
invariant_value
until
target.exhausted
loop
if test then
action
end
forth
end
end</code>
This routine text relies on features <eiffel>start</eiffel>, <eiffel>forth</eiffel> and <eiffel>exhausted</eiffel> which, together with <eiffel>off</eiffel>, have for convenience been carried over to [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] from their counterparts in [[ref:/libraries/base/reference/linear_chart|LINEAR]] , with feature declarations such as
<code>
off: BOOLEAN is
-- Is position of target off?
require
traversable_exists: target /= Void
do
Result := target.off
end</code>
and similarly for the others. <br/>
In addition to effecting the general iteration features from [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] , class [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] introduces iteration features that apply to the specific case of linear structures:
* <eiffel>search </eiffel> <code> ( b :BOOLEAN) moves the iteration to the first position satisfying test if b is true, or not satisfying test if b </code> is false. This use of a boolean argument to switch between two opposite semantics is not part of the recommended style, and you will find few if any other examples in the Base libraries. Here, however, it was deemed preferable to the alternative, which would have involved four separate procedures (if together with <eiffel>search</eiffel> we consider <eiffel>continue_search</eiffel> discussed next).
* With a linear structure we can implement an iteration corresponding to the 'for' loop of traditional programming languages, defined by three integers: the starting position, the number of items to be traversed, and the step between consecutive items. This is provided by procedure <eiffel>do_for</eiffel> <code> ( starting , number , step :INTEGER). </code>
* Since with a linear target the iterator can advance the cursor step by step, the basic iteration operations are complemented by variants which pick up from the position reached by the last call: <eiffel>continue_until</eiffel>, <eiffel>until_continue</eiffel>, <eiffel>continue_while</eiffel>, <eiffel>while_continue</eiffel>, <eiffel>continue_search</eiffel>, <eiffel>continue_for</eiffel>.
==Two-way iteration==
Class [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] has all the features of [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , to which it adds features for iterating backward as well as forward. <br/>
The class introduces commands <eiffel>finish</eiffel> and <eiffel>back</eiffel>, applying the corresponding operations to the two-way target. It also has a backward variant for every iteration feature. The name of each such variant is the name of the forward feature followed by ''_back'': <eiffel>do_all_back</eiffel>, <eiffel>until_do_back</eiffel> and so on. <br/>
An alternative design would have kept just one set of features and added two features: a command reverse to reverse the direction of future iteration operations, and a query backward to find out the direction currently in force. <br/>
Contrary to what one might at first imagine, class [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] is extremely short and simple; its <code> Feature </code> clause only contains the declarations of two features, <eiffel>finish</eiffel> and <eiffel>back</eiffel>. <br/>
The trick is to use repeated inheritance. [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] inherits twice from [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] ; the first inheritance branch yields the forward iteration features, the second yields those for backward iteration. There is no need for any explicit declaration or redeclaration of iteration features. Here is the entire class text that yields this result:
<code>
class
TWO_WAY_CHAIN_ITERATOR [G]
inherit
LINEAR_ITERATOR [G]
redefine
target
select
start,
forth,
do_all,
until_do,
do_until,
do_if,
do_for,
search,
forall,
exists,
until_continue,
continue_until,
continue_for,
continue_search
end
LINEAR_ITERATOR [G]
rename
start as finish,
forth as back,
do_all as do_all_back,
until_do as until_do_back,
do_until as do_until_back,
do_if as do_if_back,
do_for as do_for_back,
search as search_back,
forall as forall_back,
exists as exists_back,
until_continue as until_continue_back,
continue_until as continue_until_back,
continue_for as continue_for_back,
continue_search as continue_search_back
redefine
target
end
feature -- Status report
target: BI_LINEAR [G]
-- The structure to which iteration features will
-- apply
feature -- Cursor movement
finish is
-- Move cursor of target to last position.
do
target.finish
end
back is
-- Move cursor of target backward one position.
do
target.back
end
end
</code>
This class provides a good example of the economy of expression that the full inheritance mechanism affords through the combination of renaming, redefinition, repeated inheritance rules and selection, without sacrificing clarity and maintainability.
==Tree iteration==
Tree iterations, provided by class [[ref:/libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] , work on trees of the cursor tree form; only with this form of tree are traversal operations possible. Three forms of iteration are provided: preorder, postorder and breadth-first. They correspond to the three traversal policies described in the discussion of trees. Here too it would seem that a rather lengthy class is needed, but repeated inheritance works wonders. <br/>
[[ref:/libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] simply inherits three times from [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , renaming the features appropriately in each case:
* <eiffel>pre_do_all</eiffel>, <eiffel>pre_until</eiffel> and so on.
* <eiffel>post_do_all</eiffel>, <eiffel>post_until</eiffel> and so on.
* <eiffel>breadth_do_all</eiffel>, <eiffel>breadth_until</eiffel> and so on.
All it needs to do then is to redefine the type of target to be [[ref:/libraries/base/reference/cursor_tree_chart|CURSOR_TREE]] <code> [ </code> <eiffel>G</eiffel> <code> ] </code>, and to redefine six features: the three renamed start ( <eiffel>pre_start</eiffel> etc.) and the three forth ( <eiffel>pre_ forth</eiffel> and so on). These seven redefinitions give us a full-fledged battery of tree iteration mechanisms.
=Building and Using Iterators=
To conclude this discussion, let us now put together the various mechanisms studied so far, to see how authors of client software can use the Iteration library to perform possibly complex iterations on various data structures without ever writing a single loop or test. The basic ideas were sketched above but now we have all the elements for the full view. <br/>
An application class may use one of the iteration classes in either of two ways: as a descendant (single or repeated) or as a client. The descendant technique is extremely simple but less versatile.
==The single descendant technique==
Assume an application class <eiffel>PROCESSOR</eiffel> that is a proper descendant of one of the effective iteration classes studied in this chapter. Then a routine of <eiffel>PROCESSOR</eiffel>, say <eiffel>iterate</eiffel>, may iterate a certain action over a data structure, subject to a certain test. First, class <eiffel>PROCESSOR</eiffel> must specify the action by redefining item_action and item_test (or, in the most general case, action and test). Then routine iterate must specify the target data structure through a call of the form set <code> ( </code> <code> t ) where t represents the selected target data structure. The type of t must correspond tothe iteration class selected as ancestor of </code> <eiffel>PROCESSOR</eiffel>: for [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] it must be a descendant of [[ref:/libraries/base/reference/linear_chart|LINEAR]] (such as [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] , [[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] , LINKED_CIRCULAR or any other list or circular chain classes); for [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] it must be a descendant of [[ref:/libraries/base/reference/linear_chart|BILINEAR]] such as [[ref:/libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] or [[ref:/libraries/base/reference/two_way_circular_chart|TWO_WAY_CIRCULAR]] ; for [[ref:/libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] it must be a descendant of [[ref:/libraries/base/reference/cursor_tree_chart|CURSOR_TREE]] . In all cases the actual generic parameters of the iterator class and ofthe data structure class must be compatible. Then the iteration proper is obtained simply by calling the appropriate procedure, without any qualification or arguments, for example: do_ if <br/>
It is hard to imagine a simpler scheme: no loops, no initialization, no arguments. Feature item_action may need to rely on some variable values. Because it does not take any argument, such values will have to be treated as attributes, with the corresponding <eiffel>set_...</eiffel> procedures to set and change their values. This also applies to the two schemes set next. <br/>
The single descendant technique has one drawback: it provides the iterating class, <eiffel>PROCESSOR</eiffel>, with only one set of iteration particulars. This limitation does not affect the number of targets: you may use as many targets as you wish, as long as they are of compatible types, by calling a routine such as iterate several times, or calling several such routines, each call being preceded by a call to set to define a new target. The limitation also does not affect the iterating scheme: one iteration could use do_if, the next do_all and so on. But it does require the action and test to be the same in all cases. <br/>
The next two techniques will remove this limitation.
==Using repeated inheritance==
One way to obtain several iteration schemes is a simple extension to the single descendant technique. You can use repeated inheritance to provide two or more variants. We have in fact already encountered the technique when studying how to derive [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] and [[ref:/libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] from [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] . The general pattern, applied here to just two iteration schemes but easily generalized to more, is straightforward:
<code>
class
DUAL_PROCESSOR
inherit
LINEAR_ITERATOR [SOME_TYPE]
rename
item_action as action1,
item_test as test1,
do_if as do_if1,
redefine
action1, test1
select
action1, test1
end
LINEAR_ITERATOR [SOME_TYPE]
rename
item_action as action2,
item_test as test2,
do_if as do_if2,
redefine
action2, test2
end
feature
action1 is
-- Action for the first scheme
do
...
end
test1: BOOLEAN is
-- Test for the first scheme
do
...
end
action2 is
-- Action for the second scheme
do
...
end
test2: BOOLEAN is
-- Test for the second scheme
do
...
end
iterate1 is
-- Execute iteration of first kind.
do
set (...)
do_if1
end
iterate2 is
-- Execute iteration of second kind.
do
set (...)
do_if2
end
...
end
</code>
The repeated inheritance machinery takes care of the rest.
==Using explicit iterator objects==
To obtain maximum flexibility, classes that need iteration facilities should be clients rather than descendants of the iteration classes. The resulting scheme is completely dynamic: to perform iterations you use iterator objects as discussed earlier. <br/>
The following example illustrates the technique. Consider a deferred class <eiffel>FIGURE</eiffel> describing the notion of graphical figure, with many effective descendants ( <eiffel>POLYGON</eiffel>, <eiffel>CIRCLE</eiffel> and so on). It is useful to define <eiffel>COMPLEX_FIGURE</eiffel>, describing figures that are recursively composed of sub-figures. This is a remarkable example of multiple inheritance:
<code>
class
COMPLEX_FIGURE
inherit
FIGURE,
LINKED_LIST [FIGURE]
feature
...
end
</code>
In the feature clause we want to provide the appropriate effectings for the deferred features of class <eiffel>FIGURE</eiffel>: <eiffel>display</eiffel>, <eiffel>hide</eiffel>, <eiffel>translate</eiffel> and all other basic figure operations. <br/>
We can use loops for that purpose, for example
<code>
display is
-- Recursively display all components of the complex
-- figure
do
from
start
until
exhausted
loop
item.display
forth
end
end
</code>
Although acceptable and even elegant, this scheme will cause significant duplication: all the <eiffel>FIGURE</eiffel> features - not just <eiffel>display</eiffel> but also <eiffel>hide</eiffel>, <eiffel>rotate</eiffel>, <eiffel>move</eiffel> and others - will have the same structure, with a loop. We can use iterators to avoid this duplication. The repeated inheritance technique would work, but given the large number of <eiffel>FIGURE</eiffel> features the amount of repeated inheritance that would be needed seems unwieldy. It is also not very desirable to have to change the inheritance structure of the system just to add a new feature to <eiffel>FIGURE</eiffel>. The more dynamic approach using iterator objects seems preferable. <br/>
To implement this approach, define a class for iterating on complex figures:
<code>
class
COMPLEX_FIGURE_ITERATOR
inherit
LINEAR_ITERATOR
redefine
target
end
create
set
feature
target: COMPLEX_FIGURE
end
</code>
Then for each operation to be iterated define a small class. For example:
<code>
class
FIGURE_DISPLAYER
inherit
COMPLEX_FIGURE_ITERATOR
redefine
item_action
end
create
set
feature
item_action (f: FIGURE) is
-- Action to be applied to each figure: display
-- it.
do
f.display
end
end
</code>
Similarly, you may define <eiffel>FIGURE_HIDER</eiffel>, <eiffel>FIGURE_MOVER</eiffel> and others. Then the features of <eiffel>COMPLEX_FIGURE</eiffel> are written almost trivially, without any explicit loops; for example:
<code>
display is
-- Recursively display all components of the complex
-- figure
local
disp: FIGURE_DISPLAYER
do
create disp.set (Current)
disp.do_all
end
</code>
and similarly for all the others. <br/>
Note the use of <eiffel>set</eiffel> as creation procedure, which is more convenient than requiring the clients first to create an iterator object and then to call <eiffel>set</eiffel>. This is also safer, since with <eiffel>set</eiffel> as a creation procedure the client cannot forget to initialize the target. (If a class <eiffel>C</eiffel> has a creation clause, the creation instruction <code> create </code> <eiffel>C</eiffel>.)

View File

@@ -0,0 +1,32 @@
[[Property:title|EiffelBase, Sets]]
[[Property:weight|4]]
Sets are containers where successive occurrences of the same item are not distinguished: inserting the same item twice has the same observable effect as inserting it once.
==Deferred classes==
The most general class describing sets is [[ref:libraries/base/reference/set_chart|SET]] . The usual operations of set theory such as union and intersection have been relegated to [[ref:libraries/base/reference/subset_chart|SUBSET]] , an heir of [[ref:libraries/base/reference/set_chart|SET]] . This enables a class to inherit from [[ref:libraries/base/reference/set_chart|SET]] without having to effect these operations if it satisfies the basic set property but has no convenient implementation of the subset operations.
==Sets without a notion of order==
[[ref:libraries/base/reference/linked_set_chart|LINKED_SET]] provides a basic implementation of [[ref:libraries/base/reference/set_chart|SET]] by linked lists.
==Sets of comparable elements and sorted sets==
The deferred class [[ref:libraries/base/reference/comparable_set_chart|COMPARABLE_SET]] , declared as
<code>
deferred class
[[ref:libraries/base/reference/comparable_set_chart|COMPARABLE_SET]] [G -> [[ref:libraries/base/reference/comparable_chart|COMPARABLE]] ]
inherit
[[ref:libraries/base/reference/subset_chart|SUBSET]] [G]
[[ref:/libraries/base/reference/comparable_struct_chart|COMPARABLE_STRUCT]] [G]
...
</code>
describes sets whose items may be compared by a total order relation. The class has the features [[ref:libraries/base/reference/comparable_set_chart|min]] and [[ref:libraries/base/reference/comparable_set_chart|max]] . <br/>
Two implementations of [[ref:libraries/base/reference/comparable_set_chart|COMPARABLE_SET]] are provided. One, [[ref:libraries/base/reference/two_way_sorted_set_chart|TWO_WAY_SORTED_SET]] , uses sorted two-way lists. The other, [[ref:libraries/base/reference/binary_search_tree_set_chart|BINARY_SEARCH_TREE_SET]] , uses binary search trees. <br/>
If the items are partially rather than totally ordered, you may use the class [[ref:libraries/base/reference/part_sorted_set_chart|PART_SORTED_SET]] [G -> [[ref:libraries/base/reference/part_comparable_chart|PART_COMPARABLE]] ], which uses a two-way sorted list implementation.

View File

@@ -0,0 +1,57 @@
[[Property:title|EiffelBase, Tables]]
[[Property:weight|5]]
Hash tables are a convenient mechanism tostore and retrieve objects identified by unique keys.
==Why use hash tables?==
The main advantage of hash tables is the efficiency of the basic operations: store ( [[ref:libraries/base/reference/hash_table_chart|put]] ) and retrieve ( [[ref:libraries/base/reference/hash_table_chart|item]] , [[ref:libraries/base/reference/hash_table_chart|remove]] ). <br/>
The idea behind hash tables is to try to emulate the data structure that provides the ultimate in efficiency: the array. On an array <eiffel>a</eiffel>, for some integer <eiffel>i</eiffel> whose value lies within the bounds of <eiffel>a</eiffel>, the basic operations are
<code>
a.put (x, i)
x := a.item (i)
x := a @ i </code>
The first causes the value of a at index <eiffel>i</eiffel> to be <eiffel>x</eiffel>; the second (and the third, which is simply a syntactical variant) access the value at index <eiffel>i</eiffel> and assign it to <eiffel>x</eiffel>. With the usual computer architectures, these operations are very fast: because arrays items are stored contiguously in memory, a computer will need just one addition (base address plus index) and one memory access to perform a put or item. <br/>
Not only are the operation times small; they are constant (or more precisely bounded by a constant). This is a great advantage over structures such as lists or trees which you must traverse at least in part to retrieve an item, so that access and modification times grow with the number of items. With an array, disregarding the influence of other factors such as memory paging, the time for a put or item is for all practical purposes the same whether the array has five items or five hundred thousand. These properties make arrays excellent data structures for keeping objects. Unfortunately, they are only applicable if the objects satisfy three requirements:
* '''A1'''. For each object there must be an associated integer, which for the purpose of this discussion we may call the object's index (since it will serve as index for the object in the array.)
* '''A2'''. No two objects may have the same index.
* '''A3'''. If we want to avoid wasting huge amount of storage, all the indices must lie in a contiguous or almost contiguous range.
Hash tables may be viewed as a rehabilitation mechanism for objects that do not naturally possess these three properties. If we are unable to find a natural index, we can sometimes devise an artificial one. To do so we must be able to find a key. Each key must uniquely identify the corresponding object; this is the same as property '''A2''', making keys similar to indices. But keys are not necessarily integers (violating property '''A1'''), although it must be possible to associate an integer with each key. The mechanism that maps keys to integers is called the hashing function. <br/>
Thanks to the hashing mechanism we will indeed be able to store suitable objects into arrays, approaching the optimal efficiency of this data structure. The efficiency will not be quite as good, however, for two reasons:
* We must pay the price of computing the hash function whenever we store or retrieve an object.
* Different keys may hash into the same integer value, requiring extra processing to find an acceptable index.
With good implementations, however, it is possible to use hash tables with a performance that is not much worse than that of arrays and, most importantly, may be treated as if the time for a put, an item or a remove were constant. This will mean that you can consider operations such as
<code>h.put (x, k)
h := a.item (k)</code>
where <eiffel>h</eiffel> is a hash-table and <eiffel>k</eiffel> is a key (for example a string) as conceptually equivalentto the array operations mentioned above. <br/>
The quality of a hashed implementation will depend both on the data structure that will store the objects, and on the choice of hashing function. Class [[ref:libraries/base/reference/hash_table_chart|HASH_TABLE]] attempts to address the first concern; for the second, client developers will be responsible for choosing the proper hashing function, although Base provides a few predefined functions, in particular for class [[ref:/libraries/base/reference/string_8_chart|STRING]] .
==When hash tables are appropriate==
You may keep objects in a hash table if for each one of these objects you can find a key that uniquely identifies it. The objects and their keys may be of many possible kinds:
* '''H1'''. In a simple example, the objects are integers; each integer serves as its own key. (More precisely we will use its absolute value, since it is convenient to have non-negative keys only.) This case is of more than theoretical interest, since it makes hash tables appropriate for storing a set of integers with widely scattered values, for which simple array storage would be a waste of space (see requirement '''A3''' above).
* '''H2'''. Frequently, the objects will be composite, that is to say, instances of a developer-defined class, and one of the attributes of that class, of type [[ref:/libraries/base/reference/string_8_chart|STRING]] , can serve as the key. For example if you were writing an Eiffel compiler you would probably need to keep a data structure that includes information about classes of the system. Each class is represented by an object with several fields describing the properties of the class; one of these fields, the class name, corresponding to an attribute of type [[ref:/libraries/base/reference/string_8_chart|STRING]] , will serve as key.
* '''H3'''. Instead of being the full object (as in case '''H1''') or one of the object's fields (as in case '''H2'''), the key may have to be computed through a function of the generating class, which will take into account several attributes of the class (that is to say, for each object, several fields).
What this practically means is that in all cases you will need, in the generating class of the objects to be stored, a query (attribute or function) that gives the key. The type of the key is highly variable but must in all cases be a descendant of [[ref:/libraries/base/reference/hashable_chart|HASHABLE]] . This is true of both [[ref:/libraries/base/reference/integer_32_chart|INTEGER]] (case '''H1''') and [[ref:/libraries/base/reference/string_8_chart|STRING]] (case '''H2'''). The requirements for being a [[ref:/libraries/base/reference/hashable_chart|HASHABLE]] are not harsh: all you need is a function hash_code that returns a non-negative integer.>
==Using hash tables==
Class [[ref:libraries/base/reference/hash_table_chart|HASH_TABLE]] takes two generic parameters:
<code>
class HASH_TABLE [G, H -> HASHABLE] ... </code>
G represents the type of the objects to be stored in the hash table, H the type of their keys. <br/>
When viewed as an implementation of containers, [[ref:libraries/base/reference/hash_table_chart|HASH_TABLE]] , in a strict sense, represents bags rather than sets: unlike the other classes in this chapter, it allows an object to have two or more distinct occurrences in a single container. But this is only true if we consider a hash table as a repository of objects of type G. In reality each item of the table is identified by a pair of values, one from G and one from H. Because the keys must uniquely identify objects, the hash table viewed as a container of such pairs is indeed a set. The creation procedure make takes an integer argument, as in
<code>create my_table.make (n)</code>
The value of <eiffel>n</eiffel> indicates how many items the hash table is expected to have to accommodate. This number of items is not a hardwired size, just information passed to the class. In particular:
* The actual size of the underlying array representation will be higher than n since efficient operation of hash table algorithms require the presence of enough breathing space - unoccupied positions.
* If the number of items in the table grows beyond the initial allocation, the table will automatically be resized.
It is useful, however, to use a reasonable upon creation: not too large to avoid wasting space, but not too small to avoid frequent applications of resizing, an expensive operation.

View File

@@ -0,0 +1,117 @@
[[Property:title|EiffelBase, Trees]]
[[Property:weight|3]]
Trees and their immediate generalization, forests, are useful for any system that manipulates hierarchically organized information. The range of applications is broad, from abstract syntax trees in compilers through document structures in text processing systems to company organization charts in business software. <br/>
Trees, in particular binary trees and their variants, also provide convenient implementations of container data structures.
==Basic Terminology==
A tree consists of a set of nodes. Each node may have zero or more children, other nodes of which it is the parent. Each node has at most one parent, although it may have an arbitrary number of children.
[[Image:tree|tree]]
A node with no parent, such as the node marked ''A'' on the figure, is called a root; a node with no children, such as ''E'', ''F'', ''G'', ''H'' and ''I'', is called a leaf. The length of a path from the root to a leaf (that is to say, the number of nodes on the path minus one) is the height of the tree; the average length of all such paths is the average height. On the figure the height is 2 and the average height is 11/6 since of the six paths five have length 2 and one has length 1.
The children of a common node are called siblings. For example ''G'', ''H'' and ''I'' are siblings on the figure. The siblings of a node are usually considered to be ordered; the order corresponds to the direction from left to right on conventional figures such as this one.
The descendants of a node are the node itself and, recursively, the descendants of its children. The ancestors of a node are the node itself and, recursively, the ancestors of its parent. For example the descendants of ''A'' are all the tree's nodes; and the ancestors of ''I'' are ''A'', ''D'' and ''I''.
To obtain a tree rather than a more general kind of graph, there is an extra requirement: in we start from an arbitrary node, go to the parent, to the parent's parent and so on (for as long as there is a parent), we will never find the starting node again. In more precise terms the condition is that the 'parent' relation must not have any cycles. (That relation is in fact a partial function, since every node has zero or one parent.) If we consider infinite as well as finite trees the above condition must be restated to express that if we start from an arbitrary node and repeatedly go to the parent we will eventually hit a root. This discussion, however, will only consider finite trees (those with a finite number of nodes), for which the two statements are equivalent.
The definition given so far properly defines forests rather than trees. ''A'' tree is a forest with at most one root (that is to say, with exactly one root unless it is empty), such as the example on the last figure. The discussion and the library classes will handle trees rather than forest, but this is not a very important difference since by using an obvious device you can treat any forest as a tree: simply add an extra node, and make it the parent of all the forest's roots.
Another important observation is that there is a one-to-one correspondence between trees and nodes. To any node N of a tree T we can associate a tree: take T, remove all nodes that are not descendants of N, and use N as the new root. Conversely, to any tree we can associate a node - its root. This correspondence enables us to treat the two concepts of tree and node as essentially the same.
==Recursive Trees==
The closeness of the notions of tree and node yields an elegant definition of trees in terms of lists. If we look at trees or, equivalently, at tree nodes, we can consider each node as being both:
* A list: the list of its children.
* A list cell (similar to a [[ref:libraries/base/reference/linkable_chart|LINKABLE ]] or [[ref:libraries/base/reference/bi_linkable_chart|BI_LINKABLE]] for one-way and two-way linked lists), paired with the node's siblings.
This yields a simple definition of trees by multiple inheritance from [[ref:libraries/base/reference/list_chart|LIST]] and [[ref:libraries/base/reference/cell_chart|CELL]] .
===Dynamic recursive trees===
An example of dynamic tree structure is provided by class [[ref:libraries/base/reference/two_way_tree_chart|TWO_WAY_TREE]] , an heir of both [[ref:libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] and [[ref:libraries/base/reference/bi_linkable_chart|BI_LINKABLE]] . There is also [[ref:libraries/base/reference/linked_tree_chart|LINKED_TREE]] , which inherits from [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] and [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] , but [[ref:libraries/base/reference/two_way_tree_chart|TWO_WA Y_TREE]] is generally preferable since children of a node often needs to be traversed both ways; the notion of order is usually less significant here than for lists. Such a form of definition is a particularly effective way of conveying the profoundly recursive nature of trees. The corresponding classes are useful in many different areas such as graphics, text processing and compilation. To create a one-way or two-way linked tree, use
<code>create my_tree.make (root_value)</code>
This will attach my_tree to a new one-node tree, with root_value at the root node. Here my_tree must be declared of type [[ref:libraries/base/reference/two_way_tree_chart|TWO_WAY_TREE]] [MY_TYPE] for some type MY_TYPE, and root_value must be of type MY_TYPE. <br/>
A class with a similar interface but using arrays rather than lists to represent nodes is also available: [[ref:libraries/base/reference/arrayed_tree_chart|ARRAYED_TREE ]] . This class is more efficient in both time and space for trees whose nodes have many children that are accessed randomly, if relatively few child insertions occur after node creation. Here the creation procedure indicates the initial number of children:
<code>create my_tree.make (max_estimated_children, root_value)</code>
The integer argument max_estimated_children only serves for the initial allocation; the array will be resized if the number of children grows beyond the initial size. As with the previous kinds of tree, the newly created node initially has no children.
===Fixed trees===
[[ref:libraries/base/reference/two_way_tree_chart|TWO_WAY_TREE]] is useful for fully dynamic trees, in which a node may get new children at any time. For some applications, the number of children of a tree, although still arbitrary, is set for each node when the node is created, and will not change after that. Of course, some children may be absent; the corresponding entries will be void references. Class [[ref:libraries/base/reference/fixed_tree_chart|FIXED_TREE]] provides the basic mechanism; as you may have guessed, the implementation associates with each node an array of its children, arrays usually being the right structure when a collection of objects is known not to change size after creation. To create a fixed tree, use
<code>create my_tree.make (how_many_children, root_value)</code>
The root will have the associated value root value and will have how_many_ children children, all initially void. Unlike the argument max_estimated_children for the creation procedure of [[ref:libraries/base/reference/arrayed_tree_chart|ARRAYED_TREE]] , the value of how_many_children is the final arity of the newly created node; since it set separately for each node on creation, the various nodes of a tree can have different arities, as illustrated on the above figure.
===Properties of recursive trees===
Whether fixed or dynamic, recursive trees fully enjoy their dual origin. This means in particular that each node is viewed as a list of its children, and can apply to this list the features inherited from [[ref:libraries/base/reference/list_chart|LIST]] , appropriately renamed; for example: <br/>
[[ref:libraries/base/reference/dynamic_tree_chart|child_put_left]] <br/>
[[ref:libraries/base/reference/dynamic_tree_chart|child_forth]] <br/>
[[ref:libraries/base/reference/dynamic_tree_chart|child_put]] <br/>
and so on. Feature [[ref:libraries/base/reference/dynamic_tree_chart|count]] , inherited from [[ref:libraries/base/reference/list_chart|LIST]] , indicates the number of children; it is renamed arity to conform to accepted tree terminology. (The word is a substantived form of the 'ary' adjective ending, as in 'ternary', 'quaternary' and so on, which yielded the expression 'n-ary'.)
==Binary Trees==
Binary trees are a special case of fixed trees in which nodes always have two children, although either or both of these children may be void.
===Basic binary trees===
Class [[ref:libraries/base/reference/binary_tree_chart|BINARY_TREE]] describes binary trees. <br/>
<br/>
[[Image:binary-tree|binary_tree]] <br/>
<br/>
The children are represented by features [[ref:libraries/base/reference/binary_tree_chart|left_child]] and [[ref:libraries/base/reference/binary_tree_chart|right_child]] . Queries [[ref:libraries/base/reference/binary_tree_chart|has_left]] and [[ref:libraries/base/reference/binary_tree_chart|has_right]] indicate whether any of these is non-void; arity is redefined to yield the number of non-void children (0, 1 or 2).
===Binary representations of trees===
For any ordinary tree, there exists a standard representation as a binary tree, which is useful in some applications. The correspondence is one-to-one, so that the original tree may be reconstructed without ambiguity. It actually applies to forests rather than trees and works as follows, ''fr'' being the first root in a forest: the binary tree's root corresponds to ''fr''; its left subtree is obtained recursively from the forest made by the subtrees of ''fr''; and its right subtree is obtained recursively from the original forest deprived of the tree rooted at ''fr''. If you start from a tree rather than a forest the binary tree's root will have no right child. <br/>
Function [[ref:libraries/base/reference/tree_chart|binary_representation]] , in [[ref:libraries/base/reference/tree_chart|TREE]] , creates a binary tree representation (the function's result) obtained from the current tree. <br/>
Procedure [[ref:libraries/base/reference/dynamic_tree_chart|fill_ from_binary]] , in [[ref:libraries/base/reference/dynamic_tree_chart|DYNAMIC_TREE]] , reconstructs a tree from a binary tree representation passed as argument.
===Binary search trees===
Class [[ref:libraries/base/reference/binary_search_tree_chart|BINARY_SEARCH_TREE]] describes binary search trees, an implementation ofbags which is appropriate for comparable items. <br/>
Binary search trees rely for insertion on a policy whereby any item less than the root is inserted (recursively) into the left subtree, and any item greater than the root into the right subtree. So if the insertion order is reasonably random the items will distribute evenly among the various branches, This means that the average height of the tree will be not much more than the optimal: [log2 n] where n is the number of nodes and [x], for any x, is the integer part of x. <br/>
Since search operations will follow the same principle (search left if smaller than the root, and so on), the time to find an item or ascertain that it is not there is proportional to the average height. In normal cases this means about [log2 n] basic operations, rather than n with a linear structure such as a list, and hence much better performance for large n.
==Cursor Trees==
Recursive trees, as described so far, are not active data structures: even though each node has its own cursor to traverse the list of its children, there is no global cursor on the tree as a whole. It is not hard to see that the notion of recursive tree is in fact incompatible with the presence of a global cursor. In situations where you need such a cursor, enabling you to move freely from a node to its children, siblings and parents, you may use class [[ref:libraries/base/reference/cursor_tree_chart]] and its descendants.
===The conceptual model===
With cursor trees the model is different from what we have seen earlier in this chapter: there is a clear distinction between the nodes and the tree itself. The manipulated object is a tree, and the notion of node is merely implicit. In the various operations presented below and illustrated on the following figure, 'up' means towards the root and 'down' towards the leaves. This, of course, is the reverse of the properties of trees of the other kind - those which grow towards the sun and serve to print books about software.
===Operations on cursor trees===
The cursor supported by instances of [[ref:libraries/base/reference/cursor_tree_chart]] has a position referring to a node of the tree, which is then considered to be the active node, or is off the tree. The different off positions are: [[ref:libraries/base/reference/cursor_tree_chart|above]] (above the root), [[ref:libraries/base/reference/cursor_tree_chart|below]] (below a leaf), [[ref:libraries/base/reference/cursor_tree_chart|before]] (before a leftmost sibling), [[ref:libraries/base/reference/cursor_tree_chart|after]] (after a rightmost sibling.) As with linear structures, fictitious sentinel elements are assumed to be present to the left, right, top and bottom. <br/>
Various procedures are available to move the cursor in all directions:
* [[ref:libraries/base/reference/cursor_tree_chart|down (i)]] moves the cursor down to the <code> i </code>-th child of the active node. If <code> i </code> is equal to 0 the cursor ends up before; if <code> i </code> is equal to the arity of the current parent plus 1, the cursor ends up [[ref:libraries/base/reference/cursor_tree_chart|after]] . Calling [[ref:libraries/base/reference/cursor_tree_chart|down (i)]] when the cursor is on a leaf node results in setting [[ref:libraries/base/reference/cursor_tree_chart|below]] and [[ref:libraries/base/reference/cursor_tree_chart|before]] to true if <code> i </code> is equal to 0, or [[ref:libraries/base/reference/cursor_tree_chart|below]] and [[ref:libraries/base/reference/cursor_tree_chart|after]] to true if is equal to arity+1.
* [[ref:libraries/base/reference/cursor_tree_chart|forth]] and [[ref:libraries/base/reference/cursor_tree_chart|back]] move the cursor forward and backward between siblings and can cause the cursor to end up [[ref:libraries/base/reference/cursor_tree_chart|after]] or [[ref:libraries/base/reference/cursor_tree_chart|before]] .
* [[ref:libraries/base/reference/cursor_tree_chart|up]] moves the cursor up one level. The call may be made even when the cursor is [[ref:libraries/base/reference/cursor_tree_chart|after]] or [[ref:libraries/base/reference/cursor_tree_chart|before]] . If the cursor is on the root of the tree or below in an empty tree, the cursor ends up [[ref:libraries/base/reference/cursor_tree_chart|above]] .
You can move the cursor in any one direction ( [[ref:libraries/base/reference/cursor_tree_chart|up]] , [[ref:libraries/base/reference/cursor_tree_chart|down]] , [[ref:libraries/base/reference/cursor_tree_chart|forth]] , [[ref:libraries/base/reference/cursor_tree_chart|back]] ), repeatedly, until it is [[ref:libraries/base/reference/cursor_tree_chart|off]] ( [[ref:libraries/base/reference/cursor_tree_chart|above]] , [[ref:libraries/base/reference/cursor_tree_chart|below,]] [[ref:libraries/base/reference/cursor_tree_chart|after]] , [[ref:libraries/base/reference/cursor_tree_chart|before]] respectively), but once it is [[ref:libraries/base/reference/cursor_tree_chart|off]] , further movement in the same direction is prohibited. For example the precondition of [[ref:/libraries/base/reference/cursor_tree_chart|put_left]] requires [[ref:libraries/base/reference/cursor_tree_chart|before]] to be false, and the precondition of [[ref:/libraries/base/reference/cursor_tree_chart|put_right]] requires [[ref:libraries/base/reference/cursor_tree_chart|after]] to be false. <br/>
It is possible to move down from an [[ref:libraries/base/reference/cursor_tree_chart|above]] position; in an empty tree this brings the cursor [[ref:libraries/base/reference/cursor_tree_chart|below]] . Similarly, it is possible to move up from [[ref:libraries/base/reference/cursor_tree_chart|below]] , left from [[ref:libraries/base/reference/cursor_tree_chart|after]] , right from [[ref:libraries/base/reference/cursor_tree_chart|before]] . <br/>
The sentinel element above the tree's root is considered to be the root of a forest containing just one tree. This view justifies the convention for the result of arity when the cursor is above: 0 if the tree [[ref:libraries/base/reference/cursor_tree_chart|is_empty]] , 1 if it has a root (viewed as the child of the fictitious sentinel element).
===Manipulating the cursor explicitly===
The cursor attached to a cursor tree is not just a conceptual notion but an actual object, of type [[ref:libraries/base/reference/cursor_chart|CURSOR]] . You may use the query cursor to obtain a reference to the current cursor. Procedure [[ref:libraries/base/reference/cursor_tree_chart|go_to]] takes a cursor as argument and brings the tree's cursor to the node identified by the value of that argument.
===Traversals===
A useful notion associated with trees and particularly applicable to cursor trees is that of traversal. <br/>
A traversal is a certain policy for ordering all the nodes in a tree - usually to apply an operation to all these nodes in the resulting order. [[ref:libraries/base/reference/cursor_tree_chart]] and its descendants support three forms of traversal: preorder, postorder and breadth-first. They correspond to the most commonly used traversal policies on trees, illustrated on the figure (where the children of each node are assumed to be ordered from left to right):
[[Image:tree|tree]]
* Preorder is the traversal that visits the root first, then (recursively) traverses each subtree in order. On the figure we will visit node ''A'' first then, recursively, the subtrees rooted at ''B'' (which implies visiting ''E'' and ''F''), ''C'' and ''D''. The resulting order is: ''A B E F C D G H I''.
* Postorder first traverses (recursively) the subtrees, then visits the root. On the example this gives: '' E F B C G H I D A''.
* Breadth-first visits the nodes level by level, starting with the root: first the root, then all its children, then all their children and so on. Here the resulting order is: ''A B C D E F G H I''.
For each of the traversals, procedures are available to move the cursor accordingly, for example [[ref:libraries/base/reference/cursor_tree_chart|breadth_start]] and [[ref:libraries/base/reference/cursor_tree_chart|breadth_ forth]] for breadth-first, and similar names for the others.

View File

@@ -0,0 +1,21 @@
[[Property:title|EiffelBase Data Structures Overview]]
[[Property:weight|1]]
The data structures cluster of EiffelBase includes classes that cover a wide range of data structures classes for you to reuse in your systems. The cluster is divided into a number of subclusters. Each subcluster contains one or more '''deferred''' classes, which provide the general high-level abstractions; other classes in the cluster inherit from the deferred ones.
The highest-level class is [[ref:libraries/base/reference/container_chart| CONTAINER]] , with the following heirs:
* [[ref:libraries/base/reference/collection_chart|COLLECTION]] , which describes containers through their access properties (defining how to access a container's items, forexample through an index or according to a last-in, first-out policy).
* [[ref:libraries/base/reference/traversable_chart|TRAVERSABLE]] , which considers their traversal properties, such as sequential or hierarchical.
* [[ref:libraries/base/reference/box_chart|BOX]] , which describes their storage properties, such as being bounded or unbounded.
The documentation further discusses:
* The [[EiffelBase, Abstract Container Structures: The Taxonomy|taxonomy]] of the abstract container structures.
* The [[EiffelBase Data Structures, Lists|list-based structures hierarchy]] .
* The [[EiffelBase, Dispensers|dispenser-based structures hierarchy]] .
* The [[EiffelBase, Trees|tree-based structures hierarchy]] .
* The [[EiffelBase, Sets|set-based structures hierarchy]] .
* The [[EiffelBase, Tables|table-based structures hierarchy]] .
* The [[EiffelBase, Iteration|iteration mechanisms]] .

View File

@@ -0,0 +1,465 @@
[[Property:title|EiffelBase, The Kernel]]
[[Property:weight|0]]
In addition to basic concepts close to the language level, the Kernel covers such common needs as '''input''' and '''output''', '''storage''' and '''retrieval''' of objects on persistent storage, fine control over '''exception handling''' and '''memory management''', and access to '''operating system facilities'''. The kernel can be divided into 5 logical clusters of classes:
* The first cluster contains the universal class defining facilities accessible to all other classes: [[ref:/libraries/base/reference/any_chart|ANY]] . Every developer-defined class is a descendant of this class.
* The second cluster includes classes whose facilities are directly related to language concepts:
** Classes describing the basic types: [[ref:/libraries/base/reference/boolean_chart|BOOLEAN]] , [[ref:/libraries/base/reference/character_8_chart|CHARACTER]] , [[ref:/libraries/base/reference/integer_32_chart|INTEGER]] , [[ref:/libraries/base/reference/real_32_chart|REAL]] and [[ref:/libraries/base/reference/real_64_chart|DOUBLE]]
** Arrays: class [[ref:/libraries/base/reference/array_chart|ARRAY]]
** Tuples: class [[ref:/libraries/base/reference/tuple_chart|TUPLE]]
** Strings: class [[ref:/libraries/base/reference/string_8_chart|STRING]]
** Basic facilities: class [[ref:/libraries/base/reference/basic_routines_chart|BASIC_ROUTINES]]
* The third cluster provides input and output facilities:
** [[ref:/libraries/base/reference/std_files_chart|STD_FILES]] offers basic mechanisms, sufficient for simple input and output.
** [[ref:/libraries/base/reference/file_chart|FILE]] describes the notion of sequential file, viewed as a sequence of characters and fully integrated in the data structure library.
** [[ref:/libraries/base/reference/directory_chart|DIRECTORY]] gives properties of directories (files serving as collections of other files).
* The next cluster, through class [[ref:/libraries/base/reference/storable_chart|STORABLE]] , makes it possible to store object structures on persistent storage and retrieve them later. This facility can also be used to transmit object structures through pipes or over a network.
* The last cluster provides access to internal properties of the compiler and environment, useful for applications that need some fine-tuning of the basic mechanisms:
** Class [[ref:/libraries/base/reference/exceptions_chart|EXCEPTIONS]] (complemented by [[ref:/libraries/base/reference/unix_signals_chart|UNIX_SIGNALS]] for Unix-type platforms) provides control over the exception handling mechanism, in particular for applications that need to handle different types of exception in different ways.
** Similarly, classes [[ref:/libraries/base/reference/memory_chart|MEMORY]] and [[ref:/libraries/base/reference/gc_info_chart|GC_INFO]] provide ways to control the garbage collector and tailor it to specific needs.
** Class ARGUMENTS gives access to the command-line arguments.
=Universal Class and its Features=
The Eiffel inheritance mechanism is set up in such a way that every class is a descendant of a Kernel Library class called [[ref:/libraries/base/reference/any_chart|ANY]] . The features of this class provide a number of generally applicable facilities covering such needs as comparison, copying and rudimentary input and output.
==The structure of universal classes==
Every class which has no inheritance clause is understood to have an inheritance clause of the form
<code>
inherit
ANY
</code>
As a result, every developer-defined class is a descendant of [[ref:/libraries/base/reference/any_chart|ANY]] . You may introduce your own project specific features in [[ref:/libraries/base/reference/any_chart|ANY]] so that all the classes of your system will be able to use these features.
==Using the universal classes==
If you need to rename or redefine a feature inherited from one of the universal classes, you should include an explicit inheritance clause, as in
<code>
class
C
inherit
ANY
rename
out as basic_out
redefine
print
end
...
feature
...
end
</code>
The features of [[ref:/libraries/base/reference/any_chart|ANY]] are usable in both qualified and unqualified form. For example, the argumentless function out, which produces a printable representation of any object, may be called under either of the forms
<code>
x := out
x := a.out
</code>
The first call yields a printable representation of the current object; the second, which assumes that a is not void, yields a printable representation of the object attached to a.
==Input and output features==
Some of the features of [[ref:/libraries/base/reference/any_chart|ANY]] cover common input and output needs. <br/>
Feature <eiffel>io</eiffel>, of type [[ref:/libraries/base/reference/std_files_chart|STD_FILES]] , gives access to standard input and output facilities. For example, <eiffel>io</eiffel> <code> . </code><eiffel>input</eiffel> is the standard input file and <eiffel>io</eiffel>.<eiffel>new_line</eiffel> will print a line feed on the standard output. Feature <eiffel>io</eiffel> is declared as a once function which, when first called, returns the value of an instance of [[ref:/libraries/base/reference/std_files_chart|STD_FILES]] that provides access to the standard input, the standard output and the error output. As a result, <eiffel>io</eiffel> is never void, so that operations such as <eiffel>io</eiffel> <code> . </code><eiffel>new_line</eiffel> are always possible. <br/>
Function <eiffel>out</eiffel>, of type [[ref:/libraries/base/reference/string_8_chart|STRING]] , is a universal mechanism for obtaining a simple external representation of any object. For non-void <code> x </code> of any type, the string <code> x </code> <code> . </code><eiffel>out</eiffel> is a printable representation of <code> x </code>. This works for <code> x </code> of all types, reference or expanded. For example, if <code> x </code> is an integer expression, <code> x </code> <code> . </code><eiffel>out</eiffel> is its string representation, such as <code> -897 </code>; if n is a non-void reference, <code> x </code> <code> . </code><eiffel>out</eiffel> is (recursively) the concatenation of the result of applying out to the successive fields of the attached object, each labeled by the name of the corresponding attribute. You may redefine out in any class to specify any suitable format for displaying instances of the class. To obtain the default representation regardless of any redefinition of out, use tagged_out, declared as a frozen synonym of the original out. <br/>
The call print <code> ( </code> <code> x </code> <code> ) </code> will output the value of <code> x </code> <code> . </code><eiffel>out</eiffel> on the default output if <code> x </code> is not void, and do nothing otherwise.
==Copy and comparison routines==
Procedure copy copies the fields of an object onto those of another. It is used under the form
<code>
target.copy (source)
</code>
Here both target and source must be non-void; this means that <eiffel>copy</eiffel> is only good for copying onto an object that already exists. If you need both to allocate a new object and to initialize it as a copy of another, use the function clone. For non-void source, the assignment
<code>
target := clone (source)
</code>
starts by creating a new object. If <code> source </code> is void, <code> target </code> will be made void too. The boolean function <eiffel>equal</eiffel> compares two objects for field-by-field equality. This is different from the equality operators <code> = </code> and <code> /= </code> which, in the case of reference types, compare references, not objects. <br/>
The function <eiffel>deep_clone</eiffel> produces a duplicate of an entire object structure. The boolean function <eiffel>deep_equal</eiffel> determines whether two object structures are recursively identical. These routines are the ''deep'' counterparts of the shallow copy and equality tests provided by <eiffel>clone</eiffel> and <eiffel>equal</eiffel>. <br/>
A class that needs a specific notion of equality and the corresponding copy semantics may redefine <eiffel>copy</eiffel> and <eiffel>is_equal</eiffel> (from which equal follows, since equal <code> ( </code> <code> a </code> <code> , </code> <code> b </code> <code> ) </code> is defined as <code> a </code> <code> . </code><eiffel>is_equal </eiffel> <code> ( </code> <code> b </code> <code> ) </code> for non-void <code> a </code>). You will find such redefinitions in a number of classes of the Base libraries. For example an instance of [[ref:/libraries/base/reference/string_8_chart|STRING]] is a string descriptor containing a reference to the actual character sequence, not that sequence itself, so that what the default equal compares and the default copy copies is the descriptor, not the string. Class [[ref:/libraries/base/reference/string_8_chart|STRING]] redefines these routines to yield the semantics normally expected by string clients; the frozen variants <eiffel>standard_copy</eiffel> and <eiffel>standard_equal</eiffel>, originally declared as synonyms to <eiffel>equal</eiffel> and <eiffel>copy</eiffel>, remain available with the default semantics. <br/>
The function <eiffel>clone</eiffel> is defined in terms of <eiffel>copy</eiffel>, and so will follow any redefinition of <eiffel>copy</eiffel>. This makes it impossible to change the semantics of one but not of the other, which would be a mistake. The variant <eiffel>standard_clone</eiffel> is defined in terms of <eiffel>standard_copy</eiffel>.
==Type information==
The string-valued query <eiffel>generator</eiffel>, applied to any object, returns the name of the object's generating class: the class of which it is an instance. The boolean function <eiffel>conforms_to</eiffel> makes it possible to test dynamically whether the type of an object conforms to that of another - that is to say whether the first one's generator is a descendant of the second one's. <br/>
These two features enable clients to ascertain the dynamic type of an entity at runtime. They are only useful for low-level components; the normal mechanism for type-dependent operations is dynamic binding.
==Miscellaneous==
The query Void, of type <eiffel>NONE</eiffel>, denotes a reference that is always void - not attached to any object. <br/>
Procedure <eiffel>do_nothing</eiffel> does what its name implies. <br/>
Function default also has an empty body; its result type is <code> like Current </code>, so what it returns is the default value of the current type. This is mostly interesting for expanded types, since for reference types the default value is simply a void reference.
=Language-related Facilities=
A number of classes offer facilities which are very close to the language level. Here too the book ''Eiffel: The Language'' covers the classes in detail, so we can satisfy ourselves with a quick summary; the flat-short forms appear in part C.
==Basic types==
The basic types [[ref:/libraries/base/reference/boolean_chart|BOOLEAN]] , [[ref:/libraries/base/reference/character_8_chart|CHARACTER]] , [[ref:/libraries/base/reference/integer_32_chart|INTEGER]] , [[ref:/libraries/base/reference/real_32_chart|REAL]] and [[ref:/libraries/base/reference/real_64_chart|DOUBLE]] are defined by classes of the Kernel library. <br/>
In reading the class specifications for the numeric types [[ref:/libraries/base/reference/integer_32_chart|INTEGER]] , [[ref:/libraries/base/reference/real_32_chart|REAL]] and [[ref:/libraries/base/reference/real_64_chart|DOUBLE]] , you might think that the type declarations are too restrictive. For example the addition operation in class [[ref:/libraries/base/reference/real_32_chart|REAL]] reads
<code>
infix "+" (other: REAL): REAL
</code>
but there is actually no problem here. A language convention applicable to all arithmetic expressions, the Balancing rule, states that in any such expression all operands are considered to be converted to the heaviest type, where [[ref:/libraries/base/reference/real_64_chart|DOUBLE]] is heavier than [[ref:/libraries/base/reference/real_32_chart|REAL]] and [[ref:/libraries/base/reference/real_32_chart|REAL]] is heavier than [[ref:/libraries/base/reference/integer_32_chart|INTEGER]] . So mixed-type arithmetic, consistent with common practice, is possible and indeed frequent.
==Arrays==
To create and manipulate one-dimensional arrays, use class [[ref:/libraries/base/reference/array_chart|ARRAY]] of the Kernel Library. Arrays are not primitive language elements; instead, they are handled through class [[ref:/libraries/base/reference/array_chart|ARRAY]] . This class is 'normal' in the sense that it may be used just as any other class by client and descendant classes. It is also somewhat special, however, in that the Eiffel compiler knows about it and uses this knowledge to generate efficient code for array operations. <br/>
To create an instance of [[ref:/libraries/base/reference/array_chart|ARRAY]] , use the creation instruction
<code>
create my_array.make (1, u)
</code>
where the arguments indicate the lower and upper bounds. These bounds will then be accessible as <code> my_array </code> <code> . </code>lower and <code> my_array </code> <code> . </code><eiffel>upper</eiffel>. The number of items is <code> my_array </code> <code> . </code><eiffel>count</eiffel>; feature <eiffel>capacity</eiffel> is a synonym for <eiffel>count</eiffel>. The class invariant expresses the relation between <eiffel>count</eiffel>, <eiffel>lower</eiffel> and <eiffel>upper</eiffel>. <br/>
To access and change the item at index ''i'' in array a, you may use features <eiffel>item</eiffel> and <eiffel>put</eiffel>, as in
<code>
x := my_array.item (i)
my_array.put (new_value, i)
</code>
Function item has an infix synonym, <code> infix </code> <code> " </code>@ <code> " </code>, so that you may also write the first assignment above more concisely as
<code>
x := my_array @ i
</code>
<br/>
Features <eiffel>item</eiffel>, <code> infix </code> <code> " </code>@ <code> " </code>and <eiffel>put</eiffel> have preconditions requiring the index ( <code> i </code>in the above calls) to be within the bounds of the array. This means that you can detect bounds violations (which correspond to bugs in the client software) by using a version of class [[ref:/libraries/base/reference/array_chart|ARRAY]] compiled with precondition checking on. The bounds of an array may be changed dynamically through procedure <eiffel>resize</eiffel>. Previously entered elements are retained. Rather than an explicit resize, you may use calls to procedure <eiffel>force</eiffel> which has the same signature as put but no precondition; if the index is not within the current bounds force will perform a resize as necessary.
==Optimizing array computations==
''' CAUTION''': Although [[ref:/libraries/base/reference/array_chart|ARRAY]] benefits from an efficient implementation, its more advanced facilities such as resizing do not come for free. For extensive computations on large arrays, an optimization may be desirable, bypassing these facilities. The technique yields loops that run at about the same speed as the corresponding loops written in C or Fortran (the usual references for array computations). It is of interest for advanced uses only, so that you may safely skip this section on first reading unless your domain of application is numerical computation or some other area requiring high-performance array manipulations.
The optimization relies on the class SPECIAL, used internally by [[ref:/libraries/base/reference/array_chart|ARRAY]] but of no direct interest to client developers in most common uses. With the declarations
<code>
my_array: ARRAY [SOME_TYPE]
direct_access: SPECIAL [SOME_TYPE]
</code>
you may use <eiffel>direct_access</eiffel> in lieu of 'my_array' within a critical loop, provided none of the operations may resize the array. Typically, the operations should only include put and item. In such a case you can use the following scheme:
<code>
direct_access:= my_array.area
-- The critical loop:
from
some_initialization
index := some_initial_index
until
index = some_final_index
loop
...
x := direct_access.item (index)
...
direct_access.put (some_value, index)
...
end
</code>
This replaces an original loop where the operations were on <code> my_array </code>. Feature <eiffel>area</eiffel> of [[ref:/libraries/base/reference/array_chart|ARRAY]] gives direct access to the special object, an instance of SPECIAL, containing the array values. Features <eiffel>put</eiffel> and <eiffel>item</eiffel> are available in SPECIAL as in [[ref:/libraries/base/reference/array_chart|ARRAY]] , but without the preconditions; in other words, you will not get any bounds checking. Instances of SPECIAL are always indexed from zero, in contrast with arrays, whose lower bound is arbitrary, 1 being the most common value. But rather than performing index translations (that is to say, subtracting <code> my_array </code> <code> . </code><eiffel>lower</eiffel> from index throughout the loop) it is preferable to use the following simple technique: if the lower bound 'lb' of <code> my_array </code> is 1 or another small integer, use 0 as lower bound instead when creating <code> my_array </code>, but only use the positions starting at 'lb'. You will waste a few memory positions (0 to lb-1), but will not have to change anything in your algorithm and will avoid costly subtractions. <br/>
It is important to note that this optimization, if at all necessary, should at most affect a few loops in a large system. You should always begin by writing your software using the normal [[ref:/libraries/base/reference/array_chart|ARRAY]] facilities; then once you have the certainty that the software is correct, if you detect that a large array computation is hampering the efficiency of the system, you may apply the above technique to get the fastest performance out of that computation. The change to the software will be minimal - a few lines - and will be easy to undo if necessary.
==Tuples==
A new Kernel Library class is introduced: [[ref:/libraries/base/reference/tuple_chart|TUPLE]] . <br/>
Alone among all classes, class [[ref:/libraries/base/reference/tuple_chart|TUPLE]] has a variable number of generic parameters. [[ref:/libraries/base/reference/tuple_chart|TUPLE]] , [[ref:/libraries/base/reference/tuple_chart|TUPLE]] [X], [[ref:/libraries/base/reference/tuple_chart|TUPLE]] [X, Y], [[ref:/libraries/base/reference/tuple_chart|TUPLE]] [X, Y, Z] and so on are all valid types, assuming valid types X, Y, Z and so on. <br/>
Conformance rules:
<code>[CONF1]
For n >= 0
TUPLE [U1, U2, ..., Un, Un+1] conforms to
TUPLE [U1, U2, ..., Un]</code>
(and hence to [[ref:/libraries/base/reference/tuple_chart|TUPLE]] [T <code>1</code>, T <code>2</code>, ..., T <code>n</code>] if each of the U <code>i</code> conforms to each of the T <code>i</code> for 1 <= i <= n.)
In particular all tuple types conform to [[ref:/libraries/base/reference/tuple_chart|TUPLE]] , with no parameter.
<code>[CONF2]
For n >= 0 If *every* one of the types T1, T2, ..., Tn conforms
to a type T, then TUPLE [T1, T2, ..., Tn] conforms
to [[ref:/libraries/base/reference/array_chart|ARRAY]] [T].</code>
Definition: a "tuple type" is any type based on class [[ref:/libraries/base/reference/tuple_chart|TUPLE]] , i.e. any type of the form [[ref:/libraries/base/reference/tuple_chart|TUPLE]] [T <code>1</code>, T <code>2</code>, ..., T <code>n</code>] for any n (including 0, for which there is no generic parameter).
{{note|(Note 1: CONF1 should be understood in terms of the underlying mathematical model. Mathematically, [[ref:/libraries/base/reference/tuple_chart|TUPLE]] [T <code>1</code>, T <code>2</code>, ..., T <code>n</code>] is the set TUPLE <code>n</code> of all partial functions f from N+ (the set of non-negative integers) to T <code>1</code> U T <code>2</code> U ... T <code>n</code>, such that:
* The domain of f contains the interval 1..n (in other words, f is defined for any i such that 1 <= i <= n).
* For 1 <= i <= n, f (i) is a member of T <code>i</code>.
}}
With this definition, TUPLE <code>n</code> is indeed a subset of TUPLE <code>n+1</code>, and in particular TUPLE <code>0</code>, the empty set, is a subset of TUPLE <code>n</code> for any n.)
Semantics: an instance of [[ref:/libraries/base/reference/tuple_chart|TUPLE]] [T <code>1</code>, T <code>2</code>, ..., T <code>n</code>] is a tuple whose first element is an instance of T <code>1</code>, the second element being an instance of T <code>2</code> etc. (The precise definition is the mathematical one given in note 1.) Note that there can be more than n elements to the tuple: for example a tuple with first element 5 and second element "FOO" is an instance of all of the following tuple types: [[ref:/libraries/base/reference/tuple_chart|TUPLE]] ; [[ref:/libraries/base/reference/tuple_chart|TUPLE]] [[[ref:/libraries/base/reference/integer_32_chart|INTEGER]] ]; [[ref:/libraries/base/reference/tuple_chart|TUPLE]] [[[ref:/libraries/base/reference/integer_32_chart|INTEGER]] , [[ref:/libraries/base/reference/string_8_chart|STRING]] ].
It may seem restrictive at first to permit only one class, [[ref:/libraries/base/reference/tuple_chart|TUPLE]] , to have an arbitrary number of actual generic parameters. Why not have a general mechanism for declaring any class C so that all of C [X], C [X, Y] etc. are valid? But in fact this is not really a restriction. To obtain this effect without any complicated language convention, just declare C as
C [G -> TUPLE]
and then use the generic derivations
C [TUPLE [X]] <br/>
C [TUPLE [X, Y]]
and so on. This also makes it possible to have the effect of some fixed parameters and some variable ones, as in
C [G, H, I -> TUPLE]
so we have all the necessary flexibility.)
==Tuple expressions==
Let e <code>1</code>, e <code>2</code>, ..., e <code>n</code> be expressions of respective types T <code>1</code>, T <code>2</code>, ..., T <code>n</code>. Then the expression
[e <code>1</code>, e <code>2</code>, ..., e <code>n</code>]
denotes an instance of [[ref:/libraries/base/reference/tuple_chart|TUPLE]] [T <code>1</code>, T <code>2</code>, ..., T <code>n</code>], whose first element is e <code>1</code>, the second element being e <code>2</code> etc. <br/>
Tuple expressions can be nested: whereas
[1, 2, 3]
is a tuple with three elements (representing an instance of [[ref:/libraries/base/reference/tuple_chart|TUPLE]] [[[ref:/libraries/base/reference/integer_32_chart|INTEGER]] , [[ref:/libraries/base/reference/integer_32_chart|INTEGER]] , [[ref:/libraries/base/reference/integer_32_chart|INTEGER]] ]),
[1, [2, 3]]
is a tuple with two elements, the second one itself a tuple; the overall expression represents an instance of [[ref:/libraries/base/reference/tuple_chart|TUPLE]] [[[ref:/libraries/base/reference/integer_32_chart|INTEGER]] , [[ref:/libraries/base/reference/tuple_chart|TUPLE]] [[[ref:/libraries/base/reference/integer_32_chart|INTEGER]] , [[ref:/libraries/base/reference/integer_32_chart|INTEGER]] ]. <br/>
As a special case of tuple expression syntax, the delimiters [ and ] are replaced by parentheses for the tuple representing the actual argument list of a routine call (see section 4).
==Tuple features==
The exact specification of class [[ref:/libraries/base/reference/tuple_chart|TUPLE]] will be described in an addition to ELKS. The principal features are:
* [[ref:/libraries/base/reference/tuple_chart|count]] (number of significant elements)
* [[ref:/libraries/base/reference/tuple_chart|item]] (i), with the obvious precondition: the i-th element, of type [[ref:/libraries/base/reference/any_chart]] (since the value of i is not known at compile time); also first, second, third, fourth and fifth, of the appropriate types.
* [[ref:/libraries/base/reference/tuple_chart|put]] (x, i), with the obvious precondition: replace i-th element with x. If argument x is not of the appropriate type T <code>i</code> there is no effect.
* [[ref:/libraries/base/reference/tuple_chart|is_equal]] : redefined to consider only the first n elements, where n is the smaller length.
Other features under consideration include:
* stripped (i): a tuple of type [[ref:/libraries/base/reference/tuple_chart|TUPLE]] [T <code>1</code>, T <code>2</code>, T <code>i-1</code>, T <code>i+1</code>, ..., T <code>n</code>], derived from the current one by removing the i-th component, again with the obvious precondition.
* wedged (x, i): a tuple with one more element, inserted at position i.
* '''infix''' "+": tuple concatenation
* '''infix''' "++": element concatenation; t ++ x is the same thing as t.wedged (x, t.count + 1).
==What have we gained?==
First we have solved the only case in the Eiffel language in which an expression has no precisely defined type: polymorphic manifest arrays. We don't have manifest arrays any more, but manifest tuples, with a precisely defined type. No incompatibility is introduced thanks to rule CONF2. The original syntax for manifest arrays, Result := <<e <code>1</code>, e <code>2</code>, ..., e <code>n</code>>>, will continue to be supported. <br/>
Second, we can define functions that return multiple results. This is a quite significant increase in expressive power. No common language has that. (You have to go to Lisp and functional languages.) Just define [[ref:/libraries/base/reference/tuple_chart|TUPLE]] [...] as the result type; in the function, you will write things like
Result := [e <code>1</code>, e <code>2</code>, ..., e <code>n</code>]
Also, from a theoretical viewpoint, feature calls are simpler and more homogeneous: every feature takes exactly one tuple as argument and returns exactly one tuple as a result. (Either of these tuples may be empty: the first for a feature with no argument, the second for a procedure.) The syntax for a call becomes
<code>Feature Arguments</code>
with Arguments defined as
<code>Tuple_expression</code>
where the Tuple_expression uses the form given in section 2 but with the outermost [ and ] delimiters replaced by parentheses to conform to usual practice. So the call
<code>f (a, b, c)</code>
which we continue to think of as having three arguments a, b and c, formally has only one tuple argument [a, b, c]. This is of course not to be confused with a call of the form
<code>g ([a, b, c])</code>
which has one argument (a tuple with three elements) in both the ordinary and the formal sense.
==Active, iterators, numerical applications, introspection==
For a set of important applications of tuples see the book chapter on [[EiffelBase, Iteration|agents and iterators]] which also covers aspects of numerical software and related topics following from the tuple mechanism.
==Temporary limitations==
The implementation of tuples has the following limitations:
* Conformance of [[ref:/libraries/base/reference/array_chart|ARRAY]] types to [[ref:/libraries/base/reference/tuple_chart|TUPLE]] types is not yet fully supported.
* Class [[ref:/libraries/base/reference/tuple_chart|TUPLE]] does not have features such as first and second. You must use item and, in most cases, an assignment attempt.
==Strings==
Strings are handled by class [[ref:/libraries/base/reference/string_8_chart|STRING]] , similar in many respects to [[ref:/libraries/base/reference/array_chart|ARRAY]] . Strings are of arbitrary size. The make creation procedure takes an integer argument, as in:
<code>
s, s1, s2, s3: STRING
...
create s.make (30)</code>
The argument indicates the number of characters for the initial allocation. This is not an absolute limit: the string will automatically grow or shrink as a result of future operations. You may always request a resizing explicitly by calling procedure resize.
==String descriptor==
The object attached at run-time to an entity such declared of type [[ref:/libraries/base/reference/string_8_chart|STRING]] is not the actual sequence of characters but a string descriptor, which contains a reference to the actual string contents.
As a result, four assignment or assignment-like operations are possible:
* '''A1''' <code> s1 </code> <code> := </code> <code> s </code>
* '''A2''' <code> s2 </code> <code> . </code>share <code> ( </code> <code> s </code> <code> ) </code>
* '''A3''' <code> s3 </code> <code> := </code>clone <code> ( </code> <code> s </code> <code> ) </code>
* '''A4''' <code> s4 </code> <code> . </code>copy <code> ( </code> <code> s </code> <code> ) </code>
As illustrated below, ''' A1''' is a reference assignment: <code> s1 </code> will be attached to the same descriptor as s. ''' A2''' keeps the descriptors distinct, but make them refer to the same sequence of characters. ''' A3''' uses the redefinition of clone for class [[ref:/libraries/base/reference/string_8_chart|STRING]] : <code> s3 </code> will be attached to a new string, completely distinct from the string attached to <code> s1 </code> although made of identical characters. ''' A4''' has almost the same effect as '''A3''', but is only applicable if <code> s4 </code> was not void, and will override the existing descriptor rather than creating a new one.
[[Image:strings]]
fig. 1: Effect of string assignment and copy operations
[[ref:/libraries/base/reference/basic_routines_chart|BASIC_ROUTINES]] provides a number of conversion functions, such as charconv.
=Files, Input, Output=
A few classes of the Kernel Library support file manipulation, input and output: [[ref:/libraries/base/reference/std_files_chart|STD_FILES]] , FILE, [[ref:/libraries/base/reference/directory_chart|DIRECTORY]] and [[ref:/libraries/base/reference/unix_file_info_chart|UNIX_FILE_INFO]] . For simple applications it suffices to use [[ref:/libraries/base/reference/std_files_chart|STD_FILES]] , but to understand the concepts better it is preferable to look first at the other two.
==General files==
FILE describes the notion of sequential file viewed as a data structure which fits in the general taxonomy of EiffelBase. <br/>
The class declaration defines files as unbounded sequences of characters. This means that you will find in FILE all the operations on sequential data structures that you have come to know and love by reading this documentation - at least, all that apply. Just as stacks and linked lists, files have <eiffel>put</eiffel>, <eiffel>extend</eiffel>, <eiffel>has</eiffel>, <eiffel>item</eiffel> and so on. More specific to files are the typed input and output operations. For output, you will find <eiffel>put_character</eiffel>, <eiffel>put_integer</eiffel>, <eiffel>put_real</eiffel>, <eiffel>put_double</eiffel> and <eiffel>put_string</eiffel>, as well as <eiffel>new_line</eiffel>. For input you will find <eiffel>read_integer</eiffel> and its co-conspirators.
{{warning| '''Caution''': Note the application to input features of the command-query separation principle. <br/>
The input features such as read_integer do not by themselves return a result; they set the values of queries such as last_integer. So the normal way to read is through two operations: <br/>
<br/>
<code> my_file </code> <code> . </code>read_integer <br/>
<code> new_value </code> <code> := </code> <code> my_file </code> <code> . </code>last_integer }}
Queries are available to determine the status of a file, in particular <eiffel>exists</eiffel>, <eiffel>is_readable</eiffel>, <eiffel>is_executable</eiffel>, <eiffel>is_writable</eiffel>, <eiffel>is_creatable</eiffel>, <eiffel>is_closed</eiffel>, <eiffel>is_open_read</eiffel> and so on.
{{warning| '''Caution''': You will notice in the flat-short form that all these queries except the first have exists as a precondition. This precondition is good for efficiency since it saves an existence test - a relatively expensive operation - when you know that a certain file exists. But it also means that if you have any doubt about the file's existence you must use the queries in the style <br/>
<br/>
<code> if </code> <code> my_file </code> <code> . </code>exists <code> and then </code> <code> my_file </code> <code> . </code>is_readable <code> then </code>... }}
FILE is a deferred class. Various implementations are possible. A quite detailed one is PLAIN_TEXT_FILE, which adds many features for accessing reading and writing data from/to a file. <br/>
[[ref:/libraries/base/reference/unix_file_info_chart|UNIX_FILE_INFO]] describes objects that contain internal information, such as protection mode and size, about a file. <br/>
The class [[ref:/libraries/base/reference/directory_chart|DIRECTORY]] describes those files which are directories - nodes in the tree describing the file structure.
==Basic input and output==
Regardless of the operating system that you use, for simple input and output [[ref:/libraries/base/reference/std_files_chart|STD_FILES]] is sufficient. You may inherit from that class to gain direct access to its features; or you may declare an entity of type [[ref:/libraries/base/reference/std_files_chart|STD_FILES]] . But remember that a feature of this type is always available: io, from class [[ref:/libraries/base/reference/any_chart|ANY]] . Thanks to this feature you may include simple input and output in any class, with instructions such as
<code>io.put_string ("My message")</code>
[[ref:/libraries/base/reference/std_files_chart|STD_FILES]] defines three default files through features <eiffel>input</eiffel>, <eiffel>output</eiffel> and <eiffel>error</eiffel>. These features are Once functions, so that the first reference to any one of them will automatically create the corresponding file descriptor and open the associated file. <br/>
To simplify the writing of common input and output operations, the most frequently used features of class FILE - for reading and writing integers, reals and so on, as discussed next - have been repeated in [[ref:/libraries/base/reference/std_files_chart|STD_FILES]] so as to apply to the default input and output. Procedure put_string in the example at the beginning of this section is typical: it writes its output on the standard output. More generally, [[ref:/libraries/base/reference/std_files_chart|STD_FILES]] has all the <eiffel>put_xxx</eiffel>, <eiffel>read_xxx</eiffel> and <eiffel>last_xxx</eiffel> features of FILE.
=PERSISTENCE, STORAGE AND RETRIEVAL=
Most object-oriented applications need the ability to store object structures on persistent storage for later retrieval, and to transfer such object structures to other applications. <br/>
Class [[ref:/libraries/base/reference/storable_chart|STORABLE]] addresses this need.
==Persistence completeness==
A fundamental requirement on object persistence mechanisms is the '' Persistence Completeness'' rule, stated as follows in ''Eiffel: The Language'': <br/>
Whenever a routine of class [[ref:/libraries/base/reference/storable_chart|STORABLE]] stores an object into an external file, it stores with it the dependents of that object. Whenever one of the associated retrieval routines retrieves a previously stored object, it also retrieves all its dependents. <br/>
Storing an object just by itself would usually result in wrong semantics: most objects contain references to other objects, which must also be stored and retrieved with it. The persistence completeness rule ensures that this is always the case. It also means, of course, that the features of [[ref:/libraries/base/reference/storable_chart|STORABLE]] must do much more than simple input and output; they must perform complete traversals of object structures.
==Using the storage and retrieval facilities==
Class [[ref:/libraries/base/reference/storable_chart|STORABLE]] is meant to be used as ancestor. You can use its features in any descendant <eiffel>C</eiffel>; for example a routine of <eiffel>C</eiffel> may contain a call of the form <eiffel>basic_store</eiffel> <code> ( </code> <code> my_descriptor </code> <code> ) </code>. <br/>
The effect of this call will be to store the current object and all its dependents into the file denoted by my_descriptor. <br/>
Although basic_store and other procedures of [[ref:/libraries/base/reference/storable_chart|STORABLE]] will in general process objects of many different types, only the generating class of the structure's initial object, <eiffel>C</eiffel> in our example, needs to be a descendant of [[ref:/libraries/base/reference/storable_chart|STORABLE]] .
==Varieties of store operations==
Two variants of the store operation are supported: basic store and general store. Basic store produces more compact structures in the resulting files, and is slightly faster; but the resulting structure is dependent on the system which executes the store operation ('System' is taken here, as elsewhere in this documentation, in its Eiffel sense of an executable assembly of classes, compiled together with the help of a configuration file.) This means that you can use procedure <eiffel>basic_store</eiffel> to store an object structure during an execution of a system if you will only retrieve it later in that execution, or in a <br/>
subsequent execution of the same system. If you need to store objects from a certain system and then retrieve them from a different system, possibly running on a different computer, use <eiffel>general_store</eiffel>. The result of <eiffel>general_store</eiffel> is still platform-dependent; the representation of numbers, in particular, is determined by the underlying machine architecture. A third variant called <eiffel>independent_store</eiffel> will be added in the future to [[ref:/libraries/base/reference/storable_chart|STORABLE]] , using an entirely platform-independent storage format; then a system running on a computer with a certain architecture will be able to retrieve, without any explicit conversion operation, object structures stored by a system running on a machine of a completely different architecture. With <eiffel>general_store</eiffel> the storing and retrieving computers must have compatible architectures.
==Retrieval==
You only need to be aware of the difference between basic and general store at storage time. The stored structure will always be available through feature retrieved; this feature will figure out, from the format of the stored structure, whether it was stored by <eiffel>basic_store</eiffel> or <eiffel>general_store</eiffel>, and will decode it accordingly. <br/>
Feature <eiffel>retrieved</eiffel> returns a result of type [[ref:/libraries/base/reference/storable_chart|STORABLE]] and is typically used through an assignment attempt of the form
<code>x ?= retrieved (my_descriptor)</code>
<br/>
The assignment attempt is necessary because <eiffel>retrieved</eiffel> returns a result of type [[ref:/libraries/base/reference/storable_chart|STORABLE]] whereas the type of <code> x </code> will be based on a proper descendant of [[ref:/libraries/base/reference/storable_chart|STORABLE]] . If the structure in the file has been corrupted and <eiffel>retrieved</eiffel> is unable to do its job, it will trigger an exception. The code for that exception in class [[ref:/libraries/base/reference/exceptions_chart|EXCEPTIONS]] (which inherits it from EXCEP_CONST and is discussed in the next section, together with the notion of exception code) is <eiffel>Retrieve_exception</eiffel>.
==Recoverable storable==
Sometime you will be in a position where the schema of a class will have changed between the time you stored your object and the time you are trying to retrieve it. Such changes include:
* class name changed
* attributes have been added or removed
* attributes have been renamed
* attributes type have changed
The storable mechanism allows you to retrieve the old version of the object only if it was saved using the <eiffel>independent_store</eiffel> facility. Each time you retrieve an object of a certain base class whose schema has changed, the feature <eiffel>correct_mismatch</eiffel> will be called. This feature is defined in <eiffel>[/libraries/base/reference/any_chart.xml|ANY]</eiffel> and by default will raise an exception. To handle the mismatch, you need to redefine <eiffel>correct_mismatch</eiffel> in the base class whose schema has been changed. For example in EiffelBase, <eiffel>[/libraries/base/reference/hash_table_chart.xml|HASH_TABLE]</eiffel> has changed between version 5.1 and version 5.2 to use <eiffel> SPECIAL</eiffel> rather than <eiffel>[/libraries/base/reference/array_chart.xml|ARRAY]</eiffel>for its internal data storage. To retrieve a 5.1 version of <eiffel>[/libraries/base/reference/hash_table_chart.xml|HASH_TABLE]</eiffel>, you need to define <eiffel>correct_mismatch</eiffel> as following:
<code>
correct_mismatch is
-- Attempt to correct object mismatch during retrieve using `mismatch_information'.
local
array_content: ARRAY [G]
array_keys: ARRAY [H]
array_marks: ARRAY [BOOLEAN]
do
-- In version 5.1 and earlier, `content', `keys' and `deleted_marks'
-- where of base class [[ref:/libraries/base/reference/array_chart|ARRAY]] . In 5.2 we changed it to be a SPECIAL for
-- efficiency reasons. In order to retrieve an old [[ref:/libraries/base/reference/hash_table_chart|HASH_TABLE]] we
-- need to convert those [[ref:/libraries/base/reference/array_chart|ARRAY]] instances into SPECIAL instances.
-- Convert `content' from [[ref:/libraries/base/reference/array_chart|ARRAY]] to SPECIAL
array_content ?= mismatch_information.item ("content")
if array_content /= Void then
content := array_content.area
end
-- Convert `keys' from [[ref:/libraries/base/reference/array_chart|ARRAY]] to SPECIAL
array_keys ?= mismatch_information.item ("keys")
if array_keys /= Void then
keys := array_keys.area
end
-- Convert `deleted_marks' from [[ref:/libraries/base/reference/array_chart|ARRAY]] to SPECIAL
array_marks ?= mismatch_information.item ("deleted_marks")
if array_marks /= Void then
deleted_marks := array_marks.area
end
if content = Void or keys = Void or deleted_marks = Void then
-- Could not retrieve old version of [[ref:/libraries/base/reference/hash_table_chart|HASH_TABLE]] . We throw an exception.
Precursor {TABLE}
end
end
</code>
Note the use of <eiffel>mismatch_information</eiffel>, this is a once feature of <eiffel>[/libraries/base/reference/any_chart.xml|ANY]</eiffel> of type <eiffel> MISMATCH_INFORMATION </eiffel>which behaves like a <eiffel>[/libraries/base/reference/hash_table_chart.xml|HASH_TABLE]</eiffel>. The keys of the table are the names of the attributes on which a mismatch occurred and the values are the corresponding object fields as they were originally stored. In this particular case of <eiffel>[/libraries/base/reference/hash_table_chart.xml|HASH_TABLE]</eiffel> we know that the previous version was an <eiffel>[/libraries/base/reference/array_chart.xml|ARRAY]</eiffel>, so we do an assignment attempt and if it succeeds we assign its <eiffel>area </eiffel>to the corresponding attribute of <eiffel>[/libraries/base/reference/hash_table_chart.xml|HASH_TABLE]</eiffel>.
If a class name changed, then you need to create an instance of <eiffel>CLASS_NAME_TRANSLATIONS</eiffel>, it behaves like a <eiffel>[/libraries/base/reference/hash_table_chart.xml|HASH_TABLE]</eiffel> where the keys represent the old name, and the value the new name. This instance needs to be created before the call to retrieved.
=Access To Internal Properties=
In some applications you may need to fine-tune the exception handling and memory management mechanisms. You may also need a simple way to access command-line arguments. In less common cases you may require low-level access to internal properties of objects.
==Exception handling==
Class [[ref:/libraries/base/reference/exceptions_chart|EXCEPTIONS]] enables you to control the handling of exceptions. [[ref:/libraries/base/reference/unix_signals_chart|UNIX_SIGNALS]] , discussed next, complements it for the special case of fine-grain signal handling on Unix or Unix-like platforms. Both are meant to be inherited by any class that needs their facilities. <br/>
The basic exception mechanism treats all exceptions in the same way. In some cases it may be useful to discriminate in a Rescue clause between the various possible causes. <br/>
Class [[ref:/libraries/base/reference/exceptions_chart|EXCEPTIONS]] provides the features to do this. Each kind of exception has an integer code, which you can use through several features:
* The integer-valued query exception which gives the code of the latest exception.
* Queries which determine the general nature of the latest exception: <eiffel>is_signal</eiffel> which determines whether the exception was an operating system signal; <eiffel>is_developer_exception</eiffel> which determines whether it was explicitly caused by a raise, as explained next; <eiffel>assertion_violation</eiffel>.
* Query<eiffel> recipient_name</eiffel> which gives the name of the exception's recipient - the routine that was interrupted by the exception.
The class also provides a set of constant integer-valued attributes which denote the various possible codes, such as <eiffel>No_more_memory</eiffel>, <eiffel>Routine_ failure</eiffel> and <eiffel>Precondition_violation</eiffel>. So you can test the value of exception against these codes if you need to ascertain the precise nature of an exception. To keep [[ref:/libraries/base/reference/exceptions_chart|EXCEPTIONS]] simple these constant attributes are declared in a class EXCEP_CONST, of which [[ref:/libraries/base/reference/exceptions_chart|EXCEPTIONS]] is an heir. <br/>
Another occasional requirement is for a mechanism to trigger an exception explicitly. Procedure raise answers this needs; the argument, a string, is the tag chosen for the exception. The code in this case is <eiffel>Developer_exception</eiffel>; the query <eiffel>is_developer_exception</eiffel> will return true; and the tag is accessible through feature <eiffel>tag_name</eiffel>. <br/>
You will notice in the interface specification for [[ref:/libraries/base/reference/exceptions_chart|EXCEPTIONS]] that for some properties of the latest exception there are two features, one with a name such as exception or recipient_name as seen above and the other with a name prefixed by original_: <eiffel>original_exception</eiffel>, <eiffel>original_recipient_name</eiffel>.
{{warning| ''' CAUTION''': The reason for the presence of these pairs is that the immediately visible cause of a routine interruption may not be the real one. Assume that routine <eiffel>r</eiffel> from class <eiffel>C</eiffel>, which has a Rescue clause, calls <eiffel>s</eiffel> from <eiffel>D</eiffel> with no Rescue clause, and that some call executed by <eiffel>s</eiffel> causes a precondition violation. Because <eiffel>s</eiffel> has no Rescue clause of its own, <eiffel>s</eiffel> will fail. Up the call chain, the first routine that has a Rescue clause - <eiffel>r</eiffel> itself, or one of its own direct or indirect callers - may process the exception; but if it examines the exception code through attribute exception it will get the value of <eiffel>Routine_failure</eiffel>. This may be what you want; but to handle the situation in a finer way you will usually need to examine the code for the original exception, the one that interrupted <eiffel>s</eiffel>. This code will be accessible through the attribute original_exception, which in this case will have the value of <eiffel>Precondition</eiffel>, the exception code for precondition violations. So you have the choice between exploring the properties of the original exception, or those of the resulting routine failures. Just make sure you know what you are looking for. }}
As you will see from the header comments in the flat-short form of class [[ref:/libraries/base/reference/exceptions_chart|EXCEPTIONS]] , the queries that return detailed information about an exception, such as <eiffel>assertion_violation</eiffel>, all give an answer determined by <eiffel>original_exception</eiffel> rather than <eiffel>exception</eiffel>, since when the two are different (that is to say, when you handle the exception in a routine other than the original recipient) the value of exception is always <eiffel>Routine_failure</eiffel> and there is nothing more to say about it.
==Signal handling==
The features of class [[ref:/libraries/base/reference/exceptions_chart|EXCEPTIONS]] enable you to determine whether a certain exception is a signal - an operating system event such as may result from a child process that disappears, a window that is resized, a user that hits the Break key and many others. But they do not give you more details because the exact set of possible signals is highly platform-dependent. <br/>
Class [[ref:/libraries/base/reference/unix_signals_chart|UNIX_SIGNALS]] complements EXCEP_CONST by providing codes for the signals of Unix and similar systems, such as Sigkill for the 'kill' signal and Sigbus for bus error. <br/>
Query <eiffel>is_defined </eiffel> <code> ( </code> <code> some_signal </code> <code> ) </code>, where <code> some_signal </code> is an integer code, will determine whether some_signal is supported on the platform. <br/>
A class whose routines need to perform specific processing depending on the nature of signals received should inherit from [[ref:/libraries/base/reference/unix_signals_chart|UNIX_SIGNALS]] , or a similar class for another platform. <br/>
Because signal codes are platform-dependent, the features of [[ref:/libraries/base/reference/unix_signals_chart|UNIX_SIGNALS]] are implemented as once functions - computed on the first call - rather than constants, although this makes no difference to clients.
==Memory management==
Class [[ref:/libraries/base/reference/memory_chart|MEMORY]] , like [[ref:/libraries/base/reference/exceptions_chart|EXCEPTIONS]] , is meant to be used as an ancestor by classes that need its facilities. It offers a number of features for controlling memory management and fine-tuning the garbage collection mechanism, a key component of the Eiffel Software environment. <br/>
One of the most useful features in this class is dispose. This procedure describes actions to be applied to an unreachable object just before the garbage collector reclaims it. By default, as declared in [[ref:/libraries/base/reference/memory_chart|MEMORY]] , the procedure does nothing; but you may redefine it in a proper descendant of [[ref:/libraries/base/reference/memory_chart|MEMORY]] to describe dispose actions. Normally such actions will involve freeing external resources: for example a class describing file descriptors may redefine dispose so that whenever a descriptor object is garbage-collected the corresponding file will be closed.
{{warning| '''Caution''': This example is typical of proper uses of dispose.In a dispose procedure you should not include any instruction that could modify the Eiffel object structure, especially if some objects in that structure may themselves have become unreachable: these instructions could conflict with the garbage collector's operations and cause catastrophic behavior. The legitimate use of dispose redefinitions is for disposing of non-Eiffel resources. }}
Other features of [[ref:/libraries/base/reference/memory_chart|MEMORY]] provide direct control over the operation of the garbage collector. You can in particular stop garbage collection through a call to <eiffel>collection_off</eiffel>, and restart it through a call to <eiffel>collection_on</eiffel>. By default, garbage collection is always on (a testimony to its authors' trust in its efficiency). Garbage collection is normally incremental, so as not to disrupt the application in a perceptible way. To start a complete garbage collection mechanism - reclaiming all unused objects - call procedure <eiffel>full_collect</eiffel>. The remaining features of [[ref:/libraries/base/reference/memory_chart|MEMORY]] enable finer control of the collection mechanism and are useful in special cases only. You will even find a free procedure providing brave (and competent) developers with a mechanism for reclaiming individual objects manually. <br/>
MEM_INFO, the result type for query <eiffel>memory_statistics</eiffel> in [[ref:/libraries/base/reference/memory_chart|MEMORY]] , describes objects containing information collected about memory usage. The features of [[ref:/libraries/base/reference/gc_info_chart|GC_INFO]] provide statistics about the garbage collector's operation.
==Command-line arguments==
Writing, assembling and compiling a system yields an executable command. The system's users will call that command with arguments. These are normally provided in textual form on the command line, as in
<code>'''your_system''' arg1 arg2 arg3 </code>
although one may conceive of other ways of entering the command arguments, such as tabular or graphical form-filling. In any case the software must be able to access the values passed as command arguments. <br/>
A language mechanism is available for that purpose: the Root Class rule indicates that the creation procedure of the root class may have a single argument (in the Eiffel sense of argument to a routine) of type [[ref:/libraries/base/reference/array_chart|ARRAY]] [[[ref:/libraries/base/reference/string_8_chart|STRING]] <code> ] </code>. The corresponding array of strings will be initialized at the beginning of the system's execution with the values entered as arguments to that execution of the command. <br/>
Although this facility suffices in many cases, it is not always convenient if you suddenly need to access the command arguments in a class that is far-away from the root. An alternative mechanism, class ARGUMENTS, is available. Once again, this is a class from which you should inherit if you need its facilities. It has just two exported features:
* <eiffel>argument_count</eiffel>, a non-negative integer, is the number of command arguments.
* <eiffel>argument</eiffel> <code>(</code>i<code>)</code>, a string, is the i-th command argument. Here <code> i </code> must be between 0 and <eiffel>argument_count</eiffel>; the convention is that for <code> i </code> <code> = 0 </code> the result is the name of the command itself.

View File

@@ -0,0 +1,30 @@
[[Property:title|EiffelBase Support Cluster]]
[[Property:weight|2]]
The support cluster offers some commonly needed functionality that do not belong to the kernel.
==Conversions, mathematical properties and ASCII characters==
A few utility classes complement the [[EiffelBase, The Kernel|kernel]] facilities. [[ref:/libraries/base/reference/primes_chart|PRIMES]] , [[ref:/libraries/base/reference/random_chart|RANDOM]] and [[ref:/libraries/base/reference/fibonacci_chart|FIBONACCI]] are part of the data structure taxonomy; the others are meant to be used as ancestors by classes needing their features.
Two classes provide basic mathematical functions such as logarithms and trigonometric functions: [[ref:/libraries/base/reference/single_math_chart|SINGLE_MATH]] for single precision and [[ref:/libraries/base/reference/double_math_chart|DOUBLE_MATH]] for the double-precision variants. [[ref:/libraries/base/reference/math_const_chart|MATH_CONST]] contains mathematical constants: <code> p </code>, the square root of two, Euler's constant <code> e </code>.
[[ref:/libraries/base/reference/primes_chart|PRIMES]] , [[ref:/libraries/base/reference/random_chart|RANDOM]] and [[ref:/libraries/base/reference/fibonacci_chart|FIBONACCI]] are data structure classes - heirs of [[ref:/libraries/base/reference/countable_sequence_chart|COUNTABLE_SEQUENCE]] . In all of these classes function i_th takes an integer argument <code> i </code> and will return the i-th element of the sequence under consideration - prime numbers, pseudo-random numbers or Fibonacci numbers. These sequences are active structures, on which forth will advance the current position and item will return the value at the current position. A few other features are specific to each case: for example [[ref:/libraries/base/reference/random_flatshort|higher_prime]] will yield the smallest prime greater than or equal to a certain value, and [[ref:/libraries/base/reference/random_flatshort|set_seed]] will define the seed to be used for starting the pseudo-random sequence.
==Internal object structures==
Class [[ref:/libraries/base/reference/internal_chart|INTERNAL]] provides low-level access to internal object structures. It, too, is meant to be used as ancestor by classes needing its features. <br/>
Here are some of the most useful calls and what they yield, <eiffel>obj</eiffel> being an entity attached to an object <eiffel>O</eiffel> and <eiffel>i</eiffel> an integer:
* [[ref:/libraries/base/reference/internal_flatshort|class_name]] (<eiffel>obj</eiffel>): the name of the generator class for O.
* [[ref:/libraries/base/reference/internal_flatshort|dynamic_type ]] <code> ( obj ) </code>: the integer code for the type of <eiffel>O</eiffel>, where each type in a system is identified by a unique code.
* [[ref:/libraries/base/reference/internal_flatshort|field_count ]] <code> ( obj ) </code>: the number of fields in <eiffel>O</eiffel>.
* [[ref:/libraries/base/reference/internal_flatshort|physical_size ]] <code> ( obj ) </code>: the space occupied by <eiffel>O</eiffel>, in bytes.
* <eiffel>field_xx</eiffel> <code> ( i, obj ) </code> where <eiffel>xx</eiffel> is name or offset: name or offset of the i-th field of <eiffel>O</eiffel>.
* [[ref:/libraries/base/reference/internal_flatshort|field ]] <code> ( i, obj ) </code>: the value of the i-th field of , if a reference; declared of type ANY in the class.
* <eiffel>yy_field</eiffel> <code> ( i, obj ) </code> where <eiffel>yy</eiffel> is boolean, character, integer, real or double: the value of the i-th field of <eiffel>O</eiffel>, if of the corresponding type; each declared of the appropriate type in the class.
* [[ref:/libraries/base/reference/internal_flatshort|is_special ]] <code> ( obj ) </code>, a boolean query which indicates whether <eiffel>O</eiffel> is a special object (the sequence of values representing the elements of an array or the characters of a string).
{{warning| '''CAUTION:''' Only very special cases justify the use of this class. Unless you are writing the lowest level of an interface between an Eiffel application and external tools (such as a database management system), and this requires passing to those tools information about the internals of Eiffel objects, you almost certainly should not use [[ref:/libraries/base/reference/internal_chart|INTERNAL]] . }}

View File

@@ -0,0 +1,106 @@
[[Property:title|IFELL]]
[[Property:weight|4]]
<code> (This license describes the terms applicable to the open-source EiffelBase libraries. For the EiffelStudio and other libraries license terms, please refer to the Eiffel Software end-user license.) </code>
On August 4, 1998 -- as part of the Eiffel Summit at TOOLS USA '98 -- Interactive Software Engineering (Eiffel Software) officially made its flagship [[EiffelBase Library|EiffelBase library ]] available for free to any organization that wants to use it, for either commercial or non-profit purposes.
The terms of the new EiffelBase license are given below. Changes since the original version are recorded in the [[#changes|changes section]] .
We hope that others will be inspired by this example to release their own reusable Eiffel components to the public.
==Preamble==
(This Preamble is not part of the license.)
EiffelBase is one of the principal contributions of Eiffel: a library of fundamental structures and algorithms covering the basics of computing, and resulting from a "Linnaean" effort at a general-purpose taxonomy of computing structures. We believe that EiffelBase is one of the most carefully designed and extensively used libraries in the object-oriented industry. The library and its design principles are described in detail in the book [http://www.eiffel.com/doc/ ''Reusable Software: The Base Object-Oriented Component Libraries'' ] .
EiffelBase is at the center of Eiffel Software's Eiffel and has been among the major factors attracting users to the technology. In spite of this competitive advantage, Eiffel Software officially announced in June of 1998 that it would release the library to the public in source form, under the terms of the license below. There are two main reasons for this initiative:
* As the software industry seems poised to adopt the idea of reusable components, we feel that EiffelBase provides an ideal basis and are happy to contribute it to the community.
* We are impressed by the quality of some public-domain software and the effectiveness of the "open source" movement. We hope that the public availability of EiffelBase in source form will encourage many people to take a close look at the classes of EiffelBase, criticize its weaker points, provide improvements, and add their own high-quality contributions.
===About the license===
After considering existing license contracts for publicly available software, we felt that the GPL (Gnu Public License) as well as LGPL, its variant for libraries, while useful and interesting, were not adequate since they are too restrictive.
<span id="contamination"></span>
In particular a crucial requirement was that the license should allow commercial companies to use EiffelBase (and other libraries that may use this license in the future) in for-profit developments without any fear (justified or not) that GPL-like requirements could cause proprietary elements of their products to come under the open source umbrella themselves.
The closest model was that of the Perl Artistic License, which significantly influenced the terms of the agreement as shown below. It too, however, was not applicable verbatim. EiffelBase was initially designed as a commercial product and then released as free software, a different situation from that of software that was never commercial.
You will note that there are few restrictions on the use of EiffelBase in the license given below. You can use EiffelBase in your academic work and re-publish the source; you can produce a commercial software product using EiffelBase and not owe a cent to Eiffel Software.
===Ownership===
EiffelBase remains an Eiffel Software product and will continue to be distributed as such to Eiffel Software customers. This means in particular that there is no o lessening of our maintenance and support responsibility to our customers under maintenance. In fact, the increased scrutiny and outside contributions will mean an increase of our commitment to develop EiffelBase and of the quality of the product.
==The License Text==
This is the official license text.
===Definitions===
"Eiffel Software" refers to Interactive Software Engineering Inc.
"The Library" refers to the collection of software texts in the Eiffel language, originally written by Eiffel Software, and constituting the EiffelBase library of fundamental computing science structures, as well as any derivatives of these texts as may be created through textual modification (by people) or through translation to lower-level languages (by programs such as compilers).
"Standard Version" refers to the version of the Library maintained by Eiffel Software and distributed by Eiffel Software to its customers under maintenance.
"You" means any person interested in using, modifying or distributing the Library.
"Source form" means the text of the Library's classes, in the Eiffel language.
"Object form" means the translation, as performed by a compiler or other program, of the Library or part of the Library into another, usually lower-level code (such as C, assembly language or machine language) intended for execution by a machine.
<span id="reference_implementation"></span>
"Reference implementation" means the latest officially released version of Eiffel Software's implementation of the Eiffel language.
===Statement of copyright and ownership===
'''1.''' The Library is the property of Eiffel Software and bears Eiffel Software's copyright. Any use you make of the Library must respect Eiffel Software's proprietary rights.
===Right of use===
'''2.''' Eiffel Software hereby grants you permission to do any of the following without payment to Eiffel Software, under the conditions of sections 3 to 7 of this Agreement:
* '''2.1.''' Use the Library, in source form or object form, as part of any software you develop and distribute to other parties.
* '''2.2.''' Distribute the source of the Library to other parties.
===Conditions===
<span id="encourage_bug_reports"></span>
'''3.''' If you use (2.1) or distribute (2.2) the Library, you are encouraged, but not required,to provide to Eiffel Software and the rest of the Library's user community any bug fixes or other improvements that you make to the existing classes of the Library.
'''4.'''If you produce new classes based on the Library or extending the Library, you are encouraged, but not required, to make them available in the same way.
'''5.''' If you use the Library (2.1) in source or object form for producing software that you distribute, you are encouraged, but not required, to include the following mention (or its translation into the language of the rest of the distribution, if other than English) in the documentation of your software, including textual documentation as well as online documentation such as "About..." entries:
* ''This product includes EiffelBase software from Interactive Software Engineering, used according to the terms of the Eiffel Software Free Eiffel Library License (IFELL). ''See [http://eiffel.com/ http://eiffel.com] and, for the license terms, [http://eiffel.com/products/base/license.html http://eiffel.com/products/base/license.html] .
'''6.''' If you distribute the source code of part or all of the Library (2.2) you must:
* Distribute entire classes, not just extracts.
* Retain, in the distributed version, the entire copyright notice of these classes.
* If you need to make any modification to the classes, mark those modifications clearly in the class texts.
* <span id="valid_eiffel"></span> Ensure that the text remains valid Eiffel. Note that this license does not authorize you to distribute versions of the Library restated in other programming, analysis or design languages, except if mechanically translated from the source form by an Eiffel compiler, in which case they fall under "object form". For any non-mechanical adaptation to other languages you must obtain authorization from Eiffel Software. "Valid Eiffel" includes the language described in the latest edition or printing of the book [http://www.eiffel.com/services/training/books.html ''Eiffel: The Language'' ] (Prentice Hall), plus any changes or extensions that have been approved by the Nonprofit International Consortium for Eiffel (NICE) or have been accepted for discussion by the Language Committee of NICE, provided they are accepted by the reference implementation.
* <span id="obsolete_version"></span> If Eiffel Software releases a new version of the Library, you must, no later than six months after the release of that version, either: (A) update your distribution to the new version; (B) add the following notice to all files in your distribution:" ''This is an obsolete version of EiffelBase. The latest version is available from http://eiffel.com''"; or (C) cease distributing your version.
You may not charge any fee for the distribution of the Library (source or binary), although you may charge for software that includes the Library in whole or in part as per the other provisions of this Agreement.
'''7.''' You may not use the name of Eiffel Software to endorse or promote products derived from the Library without specific prior written permission.
'''8.''' THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
<span id="changes"></span>
==Changes==
(This list of changes is not part of the license.)
'''General note on changes''': as usage of free EiffelBase grows and more people contribute to it, some terms of the license text may occasionally have to be changed in light of this accumulated experience and of comments received from users and contributors. It is our intention to ensure that
* (1) Any such changes will be minor, affecting the details of the licensing rather than the spirit of IFELL.
* (2) If they affect the substance of the license in any way, they go in the general direction of extending, not restricting, the rights of users of EiffelBase.
Should a question arise regarding use of EiffelBase, the terms to be applied are those in effect at the time of use, disregarding any later change.
'''28 June 2000''': in response to comments by Joachim Durchholz through Patrick Schoenbach, replacement of most occurrences of the word "EiffelBase" by"the Library" to facilitate application to other libraries.
'''7 May 1999''': in response to comments by David Broadfoot on the Eiffel Software user list, rewording of the [[#contamination|explanation]] of why we are applying more liberal terms than GPL-style licenses. regarding fears of [[#contamination|contamination]] with the Gnu Public License.
'''6 May 1999''': following comments by Ed Avis and Alexander Kjeldaas, we now permit distribution maintainers to continue distributing an old version as long as they [[#obsolete_version|mention clearly that it's obsolete ]] .
'''7 April 1999''': following comments by Loryn Jenkins and Ed Avis, removal of the requirement that bug fixes and improvements be provided back to the maintainers of the library. This requirement has been changed to a mere [[#encourage_bug_reports|encouragement ]] , facilitating use of the library. Of course it is in everyone's interest to report bugs and improvements.
'''7 April 1999''': following comments by Loryn Jenkins, loosening of the [[#valid_eiffel|definition of "valid Eiffel"]] . This change also caused addition of the notion of [[#reference_implementation|reference implementation]] . The purpose is to avoid crippling EiffelBase by preventing it from utilizing innovative language constructs and corrections in the language contributions. Such language extensions are OK as long as they have been accepted for discussion by NICE and are supported by the reference implementation.
'''1 April 1999''': following some comments by Richard Stallman,addition of a qualification (" ''justified or not''") to the notes regarding fears of [[#contamination|contamination ]] with the Gnu Public License. Our intention is not to criticize the GPL but simply to note that the GPL does cause some fears, "justified or not", among commercial developers.

View File

@@ -0,0 +1,42 @@
[[Property:title|Compilation of multithreaded systems]]
[[Property:weight|3]]
==Settings==
* Set the option multithreaded in the project settings under Advanced.
* Do not use a non-multi-threaded precompiled library. The corresponding multi-threaded libraries of base, WEL and Vision2 should be located in $ISE_EIFFEL/precomp/spec/$PLATFORM/ with the mt prefix.
* You may want to include the thread library (located at "$ISE_EIFFEL/library/thread") to your project. This setting can be done in [[Group Options| the groups section of the project settings window]] .
* When using external C libraries, be sure that they are MT-safe: on the platforms where the Eiffel Threads are available. For example [[WEL Library|Wel]] and [[EiffelNet Library|Net]] multi-threaded libraries can be recognized by the `mt' prefix.
==Compilation==
Just launch the compilation: the Eiffel compiler will generate and link the multi-threaded executable. If the project was already compiled, clean the project and recompile it from scratch.
==External C files==
The C files that you link with a multi-threaded Eiffel application must be compiled in multi-threaded mode. In addition, you should follow some basic guidelines, which you can find in any documentation on threads. Here are the main requirements:
* Check what you are importing is safe: you cannot arbitrarily enter non-threaded code in a multi-threaded program. Check your include files and libraries you use for the linking to decide if they can be used in multi-threaded mode.
* If you are using CECIL in multi-threaded mode, you must compile your C files with the same defined symbols as those used to compile the generated C-code in multi-threaded mode.
* Threaded code can safely refer to unsafe code ONLY from the initial thread.
{{note|'''Note''': if you use the libraries Net and MEL in multi-threaded mode, you should use libmtnet. a and libmtmel. a. When using MEL, you have to be aware that Motif 1. 2 is not threaded-safe (i.e not reentrant). Motif 2. x is threaded-safe.}}
==Thread Safe Eiffel libraries==
Most libraries are not thread safe. This means that even though you can use them in a multi-threaded environment, you will need to add the necessary protection to ensure that objects are accessed only by one thread at a time.
Most of the issues is related to the use of EiffelBase containers which have been designed at a time where threads where not present. In the future we will certainly provide a version of EiffelBase which will be designed to be thread safe, in the meantime, you have to use basic protection mechanism such a mutexes to guarantee a safe execution of your programs.
Here is a summary of what you need to include in your project settings when using our libraries:
- EiffelBase: not thread safe, no externals required
- WEL: partly thread safe regarding creation of graphical objects that belongs to two different threads, but since it relies on EiffelBase, be aware of what has been said. Other libraries have the same dependency on EiffelBase and this warning will not be repeated.
- MEL: you have to be aware that Motif 1. 2 is not thread safe and that Motif 2.x is. Therefore you can use MEL in a multi-threaded program only if you have Motif 2.x. In this case, you need to include libmtmel.a instead of libmel.a
- EiffelNet: thread safe with above limitation on EiffelBase.
- COM: not thread safe.

View File

@@ -0,0 +1,23 @@
[[Property:title|Multithread FAQ]]
[[Property:weight|6]]
===I've launched several threads and they do not seem to be executed:===
The thread that launched the several threads may be dead before its children.
===Two threads can lock the same mutex, however none of them unlocks it:===
Same problem as above. Maybe the first thread that locked the shared mutex died before the second tried to lock it: thus, the first one automatically unlocked it when it died. You should put a join_all or an infinite loop in the parent thread.
===I've added the option multithreaded in the project settings and it crashes:===
If you have already compiled your system in non-MT mode, you cannot change the mode of compilation and simply relaunch your compilation (the generated C-code would be incompatible). Delete all your object files in your W_code or F_code directory and freeze or finalize the system again.
===My once function changed during my MT-Eiffel-program:===
The once functions are once per thread in Multithreaded mode. Hence, each once function is thread-specific and is initialized the first time it is called in a thread.
You can create a once per process by following [[Once features in multithreaded mode|these instructions]] .

View File

@@ -0,0 +1,49 @@
[[Property:title|Once features in multithreaded mode]]
[[Property:weight|4]]
==Manipulating Once features in multithreaded mode==
Eiffel introduced the powerful mechanism of once routines. A once routine has a body that will be executed only once, at the first call. Subsequent calls will have no further effect and, in the case of a function, will return the same result as the first. This provides a simple way of sharing objects in an object-oriented context.
For multithreaded applications, the appropriate semantics is that once routines must be called once per thread (rather than once per process). This is the semantics supported by EiffelThread.
Then the once feature is not initialized once per process but once per thread. Your once feature will be called again in any new thread execution.
==Once per Process/Thread==
Current once features in Eiffel are once per thread. This means that when a once feature is called in a thread, the Eiffel run-time will check whether it has been already computed in this thread. If not, the once feature will be initialized and computed. This seems to be a relevant way of managing once features in multithreaded mode: most of the time, a once called in a thread is not likely to share its result.
However, in some case, we need to share once features.
Moreover, an Eiffel programmer should be able to have an alternative between a once per thread or per process implementation.
==Using Once per process/thread features in EIFFEL==
Here is what you will do to implement a once per process feature:
<code>
class
TEST_ONCE_PER_PROCESS
feature
object_per_thread: OBJECT is
-- Once per thread.
once
create Result.make
end
object_per_process: OBJECT is
-- New 'object' (once per process)
-- that could be shared between threads
-- without reinitializing it.
indexing
once_status: global
once
create Result.make
end
end -- class TEST_ONCE_PER_PROCESS
</code>
You can do the same with once procedures.

View File

@@ -0,0 +1,158 @@
[[Property:title|Thread library overview]]
[[Property:weight|1]]
This is only a quick overview of the [[EiffelThread Library|Thread library]] . The reference of this library should give all its content.
==Creating and launching threads: the class THREAD (deferred)==
The class of the thread object you want to create should inherit the <eiffel>THREAD</eiffel> class. <br/>
Your thread is represented by a class which inherits from <eiffel>THREAD</eiffel> (deferred class). <br/>
<code>
class
MY_THREAD
inherit
THREAD
...
feature
execute is
-- define the deferred feature from THREAD.
do
...
end
...
end -- class MY_THREAD
</code>
Creating a thread is like creating an Eiffel object:
<code>
my_thread: MY_THREAD
-- MY_THREAD inherits from THREAD and defines
-- the deferred procedure `execute'
create my_thread
</code>
{{note| '''Note''': You have created a thread object but have not started the thread itself yet. <br/>
To run the thread, use the feature <eiffel>launch</eiffel> from <eiffel>THREAD</eiffel>. }}
<code> my_thread.launch</code>
On the Eiffel side, the procedure <eiffel>execute</eiffel> will be launched. This procedures deferred in class <eiffel>THREAD</eiffel>, you have to define it in <eiffel>MY_THREAD</eiffel>.
On the C side, a C thread will be created and launched.
{{warning| '''Caution''': you may call <eiffel>join_all</eiffel> and the end of the execution of the parent thread if you do not want it to die before its child, otherwise they may prematurely terminate.
==The class MUTEX==
The implementation of the class <eiffel>MUTEX</eiffel> is mapped on the C standard thread library. An instance of class <eiffel>MUTEX</eiffel> can be shared between different thread.
<eiffel>my_mutex.pointer</eiffel> is the pointer to the nested C mutex of <eiffel>my_mutex</eiffel>.
* Declaration of the mutex:
<code> my_mutex: MUTEX</code>
* Creation of mutex:
<code> create my_mutex.make</code>
* Locking the mutex:
<code> my_mutex.lock</code>
* Unlocking the mutex:
<code> my_mutex.unlock</code>
* <eiffel>try_lock</eiffel>: if it is not locked yet, lock the mutex and return True, otherwise it returns False.
<code> my_mutex.lock</code>
* Is my mutex initialized?
<code> my_mutex.is_set</code>
{{note| '''Note''': on Windows: The <eiffel>MUTEX</eiffel> objects on Windows are recursive while they are not on Unix. A recursive mutex can be locked twice by the same thread. }}
{{warning| '''Caution''': be sure that a mutex is unlocked when it is disposed. }}
==The class SEMAPHORE==
Like <eiffel>MUTEX</eiffel>, the features of this class are mapped on the C thread library. An instance of class <eiffel>SEMAPHORE</eiffel> can be shared between thread.
* Declaration of the semaphore :
<code> my_sem: SEMAPHORE</code>
Creation of semaphore: initialize semaphore with nb_tokens, it requires nb_tokens > = 0
<code> create my_sem.make (nb_tokens)</code>
* Wait for a token:
<code> my_sem.wait</code>
* Give back a token:
<code> my_sem.post</code>
* <eiffel>try_wait</eiffel>, similar to try_lock from <eiffel>MUTEX</eiffel>, if a token is available, take it and return <code> True </code>, otherwise return <code> False </code>.
<code> my_sem.try_wait</code>
{{warning| '''Caution''': be sure that a semaphore does not wait for a token when it is disposed }}
==The class CONDITION_VARIABLE==
This class allows to use condition variables in Eiffel. An instance of class <eiffel>CONDITION_VARIABLE</eiffel> can be shared between threads.
* Declaration of the condition variable
<code> my_cond: CONDITION_VARIABLE</code>
* Creation:
<code> create my_cond.make</code>
* Wait for a signal (send by <eiffel>signal</eiffel>). You need to use a mutex.
<code>
my_mutex: MUTEX
create my_mutex.make
</code>
<code> my_mutex </code> must be locked by the calling thread so as <eiffel>wait</eiffel> can be called. <eiffel>wait</eiffel> atomically unlocks <code> my_mutex </code> and waits for the condition variable <code> my_mutex </code> to receive a signal. As soon as it received a signal, <code> my_cond </code> locks <code> my_mutex </code>;
<code>
my_mutex.lock
-- You must lock `my_mutex' before calling wait.
my_cond.wait (my_mutex)
-- Here the critical code to execute when `my_cond' received a signal.
my_mutex.unlock
-- Unlock the mutex at the end of the critical section.
</code>
* Send a signal one thread blocked on the condition variable `my_cond'.
<code> my_cond.signal</code>
* Send a signal to all the threads blocked on the condition variable `my_cond'.
<code> my_cond.broadcast</code>
*
{{warning| '''Caution''': be sure that a condition variable is unblocked when it is disposed. }}
==Miscellaneous classes==
class <eiffel>THREAD_ATTRIBUTES</eiffel>: defines the attributes of an Eiffel Thread regarding the thread scheduling policy and priority.
==Controlling execution: THREAD_CONTROL==
* <eiffel>yield</eiffel>: the calling thread yields its execution in favor of an other thread of same priority.
* <eiffel>join_all</eiffel>: the calling thread waits for all other threads to finished (all its children).
* A parent thread can wait for the termination of a child process through the feature <eiffel>join</eiffel> of class <eiffel>THREAD_CONTROL</eiffel> (inherited by <eiffel>THREAD</eiffel>):
<code>
thr: MY_THREAD
...
thr.launch
...
thr.join
</code>
}}

View File

@@ -0,0 +1,12 @@
[[Property:title|EiffelThread]]
[[Property:weight|0]]
The EiffelThread library includes the main components needed to build multithreaded systems. <br/>
See:
* [[EiffelThread: Introduction|Introduction]]
* [[Thread library overview|Library description]]
* [[Multithread FAQ|FAQ]]

View File

@@ -0,0 +1,65 @@
[[Property:title|Esql Sample]]
[[Property:weight|0]]
This sample consists of a command line SQL parser. SQL statements are filtered through a monitor and sent to the RDBMS.
==Compiling==
To compile the example:
* Launch EiffelStudio.
* Click '''Add project'''
* Browse to ''$ISE_EIFFEL\examples\store\esql\''.
* Choose ''esql.ecf''
* Choose the location where the project will be compiled, by default the same directory containing the configuration file.
* Choose the targe according to the installed DBMS.
* Click '''OK'''.
==Running==
This sample lets you interact with your database through a console.
First you have to enter the database connection information:
* For ODBC:
<code>
Database user authentication:
Data Source Name: handson
Name: smith
Password: mypass
</code>
{{note| '''Note:''' '' Name'' and ''Password'' are no required with ODBC. If you don't need ''Name'' and ''Password'', you can simply hit '''Return''' when prompted ''.'' }}
* For Oracle:
<code>
Database user authentication:
Name: smith@HANDSON
Password: mypass
</code>
{{note| '''Note:''' you have to specify the Oracle User Name and Net Service Name with the syntax ''<user>@<service> ''where ''<user>'' stands for the User Name and ''<service>'' stands for the Net Service Name. }}
Then you can enter standard SQL queries to interact with your database, for instance:
<code>
SQL> select firstname, lastname from CONTACTS where lastname = 'Smith'
John Smith
SQL>
</code>
{{note| '''Note:''' enter ''exit'' to quit the application. }}
==Under the Hood==
This sample showcases the use of the 3 basic classes to interact with your database:
* [[ref:libraries/store/reference/db_control_chart|DB_CONTROL]] to connect and disconnect to your database.
* [[ref:libraries/store/reference/db_selection_chart|DB_SELECTION]] to perform 'select' queries.
* [[ref:libraries/store/reference/db_change_chart|DB_CHANGE]] to perform SQL queries that output no result.
The whole sample code is contained in the root class:
* ESQL for Oracle.
* ESQL_ODBC for ODBC.

View File

@@ -0,0 +1,80 @@
[[Property:title|Inserter Sample]]
[[Property:weight|2]]
This sample lets the user insert a DB_BOOK object in your database using EiffelStore insertion facilities.
==Compiling==
To compile the example:
* Launch EiffelStudio.
* Click '''Add project'''
* Browse to ''$ISE_EIFFEL\examples\store\insert\''.
* Clicking open loads the selected project
* Choose inserter.ecf
* Select the target according to the installed DBMS
* Choose the location where the project will be compiled, by default the same directory containing the configuration file.
* Click '''OK'''.
==Running==
This sample lets you interact with your database through a console.
First you have to enter the database connection information:
* For ODBC:
<code>
Database user authentication:
Data Source Name: handson
Name: smith
Password: mypass
</code>
{{note| '''Note:''' '' Name'' and ''Password'' are no required with ODBC. If you don't need ''Name'' and ''Password'', you can simply hit '''Return''' when prompted ''.'' }}
* For Oracle:
<code>
Database user authentication:
Name: smith@HANDSON
Password: mypass
</code>
{{note| '''Note:''' you have to specify the Oracle User Name and Net Service Name with the syntax ''<user>@<service> ''where ''<user>'' stands for the User Name and ''<service>'' stands for the Net Service Name. }}
Then you can insert a book in the database, for instance:
<code>
What new book should I create?
Author? John Smith
Title? My book
Quantity? 1
Price? 50
Year? 2001
Double value? 12.675
Object inserted
</code>
{{note| '''Note:''' if your database does not contain a <eiffel>DB_BOOK</eiffel> table, this example will create it. }}
==Under the Hood==
This sample showcases the use of the [[ref:libraries/store/reference/db_store_chart|DB_STORE]] class to [[Data Object Coupling| perform database insertions]] where the SQL language is totally abstracted.
The whole sample code is contained in the root class:
* INSERTER for Oracle.
* INSERTER_ODBC for ODBC.

View File

@@ -0,0 +1,95 @@
[[Property:title|Selector Sample]]
[[Property:weight|1]]
This sample creates a <eiffel>DB_BOOK</eiffel> table in your database, enters sample data in it and lets you select rows from this table with author's name.
==Compiling==
To compile the example:
* Launch EiffelStudio.
* Click '''Add project'''
* Browse to ''$ISE_EIFFEL\examples\store\select\''.
* Clicking open loads the selected project
* Choose select.ecf
* Select the target according to the installed DBMS
* Choose the location where the project will be compiled, by default the same directory containing the configuration file.
* Click '''OK'''.
==Running==
Before running this sample, one must do link a specific file to data.sql as follows:
With Oracle:
''ln data.sql.oracle data.sql''
With ODBC:
''ln data.sql.odbc data.sql''
{{warning| '''Caution:''' the ''data.sql'' file must be available in the sample application current directory. If you run the sample from EiffelStudio, this directory should be the ''EIFGENs/target/W_CODE/'' directory of your project (where target is one of the installed DBMS). }}
This sample lets you interact with your database through a console.
First you have to enter the database connection information:
* For ODBC:
<code>
Database user authentication:
Data Source Name: handson
Name: smith
Password: mypass
</code>
{{note| '''Note:''' '' Name'' and ''Password'' are no required with ODBC. If you don't need ''Name'' and ''Password'', you can simply hit '''Return''' when prompted. }}
* For Oracle:
<code>
Database user authentication:
Name: smith@HANDSON
Password: mypass
</code>
{{note| '''Note:''' you have to specify the Oracle User Name and Net Service Name with the syntax ''<user>@<service> ''where ''<user>'' stands for the User Name and ''<service>'' stands for the Net Service Name. }}
Then you can select rows from this table with author's name, for instance:
<code>
Author? ('exit' to terminate):Bertrand Meyer
Seeking for books whose author's name match: Bertrand Meyer
Author:Bertrand Meyer
Title:Eiffel The Libraries
Quantity:11
Price:20
double_value:435.60000610351562
First publication:07/01/1994 12:00:00.0 AM
Author:Bertrand Meyer
Title:Eiffel The Language
Quantity:9
Price:51
double_value:775.22998046875
First publication:07/01/1992 12:00:00.0 AM
Author? ('exit' to terminate):
</code>
{{note| '''Note:''' enter ''exit'' to quit the application. }}
==Under the Hood==
This sample showcases the use of the [[ref:libraries/store/reference/db_selection_chart|DB_SELECTION]] class to perform smart ''select'' queries, using:
* [[Data Object Coupling|Database data and Eiffel objects Coupling]] .
* [[Query variables|Variables Binding]] .
The whole sample code is contained in the root class:
* SELECTOR for Oracle.
* SELECTOR_ODBC for ODBC.

View File

@@ -0,0 +1,431 @@
[[Property:title|EiffelStore DataView Cluster]]
[[Property:weight|3]]
==1. Introduction==
DataView cluster helps the programmer creating a GUI for a RDBMS. It gives a basic solution for a RDBMS GUI and also enables the developer to customize his GUI from this basic interface.
This cluster is client of EiffelStore to interface with a RDBMS and EiffelVision2 to create a GUI. However, the use of EiffelStore and EiffelVision 2 is sufficiently encapsulated to let the programmer use other database/graphic libraries.
Notice finally that DataView is based on some common O-O ''design patterns''. Knowing these patterns will help you understand how the library works. It can also give an example of patterns use.
==2. Specifications==
This part draws the main capabilities that can be expected from the DataView cluster. These capabilities are not exhaustive since the cluster architecture enables to add easily new capabilities to it.
===2.1. Required database structure===
The cluster has been designed to work well with relational databases on Third Normal Form. Database tables must also have an unique numeric ID.
* The cluster automatically performs associations between related tables. This is required to work fine with 3rd NF architectures.
* The unique ID enables to update the database content. If you only intend to display database table content, unique IDs are not required.
* The numeric ID enables to directly give IDs to new table rows. If you don't intend to create table rows, this is not necessary. Notice that with only a couple of redefinitions, the numeric ID requirement problem can be overcome.
===2.2. Database content display===
The cluster provides facilities to:
* display a set of table rows.
* select a (current) table row in the set.
* display the current table row so that it can be edited.
For instance, an interface can display a multi-column list of table rows. A given row can be selected in the list and its information can be then edited through a set of text fields and combo-boxes.
The standard cluster usage is to define a GUI that will associate a given frame/window to a given database table, that is, the information that is displayed in a GUI area will be determined at compile-time. This enables to adapt the GUI display to the type of information displayed, which is recommended when creating a GUI for non-developer users (or any people that should not be aware of the database structure and functioning). Nevertheless, determining the type of information displayed by a frame/window at runtime is still possible as not hard-coded.
Abstracting database in the GUI might not be as easy as only changing database attribute fields names. Information to display may not match the database tables structure. However, for consistency reasons, we can assume that he information to display within a GUI area belongs to a set of associated tables. The easiest solution is to create database views that directly contain the information to display on the GUI area. This implies though that the database has to be modified for the GUI needs.
DataView cluster affords a second solution:
* Model-View separation enables to merge graphically information that is separated in the process part (i.e. that is from a different table).
* Table associations facilities enable to specify to display automatically content of table rows associated to a given table row. For instance, with a CONTACTS table associated to a COMPANIES table, the cluster can retrieve automatically a COMPANIES table row associated to a selected CONTACTS table row.
===2.3. Actions performed on the database===
The cluster provides facilities for the following actions:
* Creating a table row
* Deleting a table row
* Updating the content of a table row
* Selecting a set of table rows
Other capabilities can be added to these ones, for instance by writing descendants of DataView cluster classes that would handle more database operations.
Operations relative to the database structure modification, for instance creating a database table, may be more difficult to add since the database structure is hard-coded. But these advanced capabilities might not be necessary in a GUI for non-developer users.
==3. General description==
===3.1. Global architecture===
The DataView cluster is based on 1 class called [[ref:libraries/store/reference/dv_table_component_chart|DV_TABLE_COMPONENT]] that represents the interface for 1 relational database table. An architecture using ''DataView'' is centered on database table structure rather than the GUI structure. The basic idea is to have:
* 1 database relational table
* 1 GUI window or frame
* 1 [[ref:libraries/store/reference/dv_table_component_chart|DV_TABLE_COMPONENT]] object
This is then possible to adapt the code to have a GUI meeting the specifications, database structure can be totally abstracted in the interface, which might be more convenient for non-developer GUI users.
===3.2. Library structure===
The cluster can be separated into 3 main parts:
* The '''model''': processes the information and interfaces with an abstract graphic interface (the handle) and an abstract database interface.
* The '''handle''': defines an abstract graphic interface for the model.
* The '''view''': implements the handle interface with EiffelVision2 widgets.
The abstract database interface is defined in the EiffelStore generation.tables_access cluster. This cluster can indeed been used independently from the DataView cluster.
===3.3. Model cluster structure===
The '''model''' cluster processes the information retrieved from the GUI and the database and update then both GUI and database.
The cluster is based on the [[ref:libraries/store/reference/dv_table_component_chart|DV_TABLE_COMPONENT]] class which objects represents a database relational table (or view).
DV_TABLE_COMPONENT objects can be interconnected to match the table associations. The [[ref:libraries/store/reference/dv_table_component_chart|DV_TABLE_COMPONENT]] class has been designed to work with 3rd Normal Form relational databases. [[ref:libraries/store/reference/dv_table_component_chart|DV_TABLE_COMPONENT]] achieves most of the work to retrieve associated table rows for a 3NF database. For instance, when deleting a table row, the component ensures that every associated table row is also deleted.
[[ref:libraries/store/reference/dv_table_component_chart|DV_TABLE_COMPONENT]] objects can be customized by adding some subcomponents to it. Subcomponents enable to display table rows content on screen, to navigate among table rows and to perform different database queries.
[[Image:sub-component-objects]]
Process objects structure for a GUI
===3.4. Design patterns===
This cluster adapts several well-known O-O design patterns.
====3.4.1. Model-View separation pattern====
The GUI appearance is totally abstracted in the GUI processing part, this enables to change the GUI display without changing any part of the model part.This is implemented with 2 sets of classes:
* A set of interfaces that corresponds to each type of abstract widgets needed by the model.
* A set of classes that implements these interfaces. Notice that an implementation class can implement several interfaces and several classes can implement the same interface.
Let's see an example through a BON diagram:
[[Image:model-view-relationship]]
Model-View separation pattern implementation in ''DataView''
* Light blue classes represents the model cluster.
* Orange class represents the handle.
* Yellow and green classes represents the view cluster.
* Pink classes represents the EiffelVision2 library.
====3.4.2. Strategy pattern====
DataView cluster provides the developer with a basic GUI implementation AND lets them customize their application. This is possible with a strategy pattern:
The developer assigns different subcomponents to a [[ref:libraries/store/reference/dv_table_component_chart|DV_TABLE_COMPONENT]] object to define its behavior. The component object only uses the interface of each subcomponent.
A default implementation is written for each interface to let the user use the cluster as quick as possible. To adapt components behavior to their needs, the developer can then create a new subcomponent class inheriting from the abstract interface.
This BON diagram illustrates this for [[ref:libraries/store/reference/dv_creator_chart|DV_CREATOR]] and [[ref:libraries/store/reference/dv_searcher_chart|DV_SEARCHER]] subcomponents:
[[Image:dv-table-component-strategy]]
Strategy pattern used in ''DataView'' model cluster
==4. Cluster interface==
This part describes how to use the table component class and its subcomponents classes:
* The [[ref:libraries/store/reference/dv_searcher_chart|DV_SEARCHER]] class to [[#dv_searcher|select table rows from the database]] .
* The [[ref:libraries/store/reference/dv_tablerows_navigator_chart|DV_TABLEROW_NAVIGATOR]] class to [[#dv_tablerow_navigator|navigate among selected table rows]] .
* The [[ref:libraries/store/reference/dv_creator_chart|DV_CREATOR]] class to [[#dv_creator|create new table rows in the database]] .
* The [[ref:libraries/store/reference/dv_tablerow_fields_chart|DV_TABLEROW_FIELDS]] class to [[#dv_tablerow_fields|edit a table row content]] .
===4.1. DV_TABLE_COMPONENT class===
This class is responsible for the management of a database table. Its behavior is determined by its assigned subcomponents.
To create a valid and functional [[ref:libraries/store/reference/dv_tablerows_component_chart|DV_TABLE_COMPONENT]] object, follow these steps:
# Call set_tablecode to specify which table the component will deal with.
# Specify [[#output_handler|handlers to output messages]] .
# Set the [[#database_handler|database handler]] .
# Add different [[#controllers|controllers corresponding to actions to perform]] .
# Set [[#subcomponents|subcomponents]] .
# Set [[#associated_components|associated components]] .
# Call activate to let the component work. This will basically set different default values for non required information not set during the creation process.
The component can then be used on an interface:
* Input interactions are done via component and subcomponents controllers (4).
* Output interactions are done via output handlers (2).
====4.1.1. Output handlers====
Output handlers are specific to the [[ref:libraries/store/reference/dv_tablerows_component_chart|DV_TABLE_COMPONENT]] object, that is, you can output messages in a different way within your GUI. However, the same handlers will be used for subcomponents.
3 handlers can be set:
* `status_handler' to display status information
* `warning_handler' to display warning information. Warnings usually correspond to database errors, they are called warnings because the database error is "caught" and the message should enable the user to round the problem.
* `confirmation_handler' to ask for confirmation before an action.
These handlers have default values, which are:
* For `status_handler' and `warning_handler', messages are displayed on standard output (with {ANY}.io.put_string)
* For `confirmation_handler', action is executed without confirmation.
====4.1.2. Database handler====
This handler is specific to the application. It must inherit from <eiffel>ABSTRACT_DB_TABLE_MANAGER</eiffel>. Since it is specific to the program, it can be set before creating any [[ref:libraries/store/reference/dv_table_component_chart|DV_TABLE_COMPONENT]] object through {DV_DATABASE_HANDLER}.set_database_handler.The [[ref:libraries/store/reference/db_table_manager_chart|DB_TABLE_MANAGER]] class is the default database handler for EiffelStore.
4.1.3. Action controllers
No subcomponent is associated to 'write', 'refresh' and 'delete' actions since these actions does not require specific behavioral choices.
To perform 'write', 'refresh' and 'delete' at runtime, a controller is associated to each of these actions. This controller triggers the action when a determined user event is grabbed, for instance, when the user clicks a button.
[[#dv_s_control|Controllers]] are implemented by the abstract class [[ref:libraries/store/reference/dv_sensitive_control_chart|DV_SENSITIVE_CONTROL]] of cluster user_interactions (handle).
====4.1.4. Subcomponents====
Subcomponents can be assigned to a table component to specify its behavior to create table rows, select table rows from the database and navigate among selected table rows. A special subcomponent enable to display the ''current'' table row, i.e. the table row that can be edited to update the database. The default behavior for these subcomponents is that the functionality is not available, that is, subcomponents are not mandatory.
These components share the table component output handlers. They are automatically activated when table component is activated.
====4.1.5. Associated components====
Table components can be associated to reflect relation of database tables represented. Associated table components are organized:
* 1 master component enables to manually select database table rows.
* Slave components automatically select table rows that are associated to the current table row of the master component.
{{note| '''Note''': Notice that table associations can be '''nested'''. }}
2 types of associations are possible to reflect table relations:
* The slave table is dependent on the master table (1:N relationship)
* The slave table is necessary for the master table (N:1 relationship)
Let us see an example with 3 relational tables:
[[Image:table-objects-associations]]
Tables architecture and corresponding component objects
The object architecture leads to a GUI where the user can select a company and see the company country information and contacts in this company.
Finally, notice that by default slave components have the same output handlers as their master and slave components are activated when the master component is.
===4.2. DV_SEARCHER class===
====4.2.1. Overview====
[[ref:libraries/store/reference/dv_searcher_chart|DV_SEARCHER]] is responsible for retrieving table rows from the database. Let us see how it interacts with a table component:
[[Image:component-search-relation]]
Basic relationship between table component class and search class
* `display' assigns a set of table rows to the table component.
* `refresh' asks to refresh the table rows from the same database query.
[[ref:libraries/store/reference/dv_searcher_chart|DV_SEARCHER]] component does not afford an extended interface. This interface is defined in its descendants. The implemented [[ref:libraries/store/reference/dv_searcher_chart|DV_SEARCHER]] descendants are:
* [[ref:libraries/store/reference/dv_typed_searcher_chart|DV_TYPED_SEARCHER]] performs different [[#dv_typed_searcher|basic searches]] used by the cluster.
* [[ref:libraries/store/reference/dv_interactive_searcher_chart|DV_INTERACTIVE_SEARCHER]] enables to create a graphic interface to [[#dv_interactive_searcher|let user set search parameters]] .
====4.2.2. DV_TYPED_SEARCHER class====
This class provides 3 types of searches:
* "Every row" search: every rows of a table are fetched.
* "ID selection" search: the selection is qualified by an ID.
* "Qualified selection" search: the selection is qualified.
=====4.2.2.1. "Every row" search=====
Call read to set table rows on the associated table component.
=====4.2.2.2. "ID selection" search=====
Call read_from_tablerow to set table rows on the associated table component. Qualification ID is the ID of the table row in parameter. Table of row in parameter must be the table of rows to select.
This capability is used by DataView cluster in [[ref:libraries/store/reference/dv_choice_creator_chart|DV_CHOICE_CREATOR]] to select a just-created table row and display it on the table component.
=====4.2.2.3. "Qualified selection" search=====
Call read_from_table row to set table rows on the associated table component. Table of row in parameter may not be the table of rows to select.
To extract the qualifier, the search component needs additional information:
* The location of the qualifying value in the table row passed in parameter (set_row_attribute_code)
* The qualifying attribute location in the table rows to select (set_criterion)
This capability is used in [[ref:libraries/store/reference/dv_tablerows_component_chart|DV_TABLE_COMPONENT]] when a table row is selected to set associated table rows to slave components. Take a look at add_necessary_table and add_dependent_table.
====4.2.3. DV_INTERACTIVE_SEARCHER class====
This class enables to create a graphic interface to let user perform basic searches. These searches are qualified by one table attribute. This interface has 5 parts:
* A [[#dv_s_control| controller]] that enables to launch the search
* A [[#dv_s_string| text input field]] to set qualifying attribute
* A [[#dv_s_string| text input field]] to set qualifying value
* A [[#dv_s_integer| typed input field]] to set qualification type
* A [[#dv_s_check| Boolean input field]] to set case sensitivity
Text input fields correspond to handle class [[ref:libraries/store/reference/dv_sensitive_string_chart|DV_SENSITIVE_STRING]] , typed input fields corresponds to handle class [[ref:libraries/store/reference/dv_sensitive_integer_chart|DV_SENSITIVE_INTEGER]] and Boolean input fields corresponds to handle class [[ref:libraries/store/reference/dv_sensitive_check_chart|DV_SENSITIVE_CHECK]] .
===4.3. DV_TABLEROW_NAVIGATOR class===
====4.3.1. Overview====
Table component class contains a set of table rows. This class lets table component class know which of these rows is the current one.
[[Image:component-navigate-relation]]
Basic relationship between table component class and navigation class
[[ref:libraries/store/reference/dv_choice_creator_chart|DV_CHOICE_CREATOR]] also uses the class to enable to select associated table rows when creating a new table row (for instance, when creating a company, an existing country should be selected). Let us see how this is designed:
[[Image:dv-tablerows-navigator-clients]]
DV_TABLEROWS_NAVIGATOR clients
{{note| '''Note''': DV_TABLEROWS_COMPONENT class merely carries a set of table rows and enables to select one table row. }}
DV_CONTROL_NAVIGATOR affords a way to navigate among searched table rows.
====4.3.2. DV_CONTROL_NAVIGATOR class====
This class enables 2 navigation systems:
* Navigating among table rows with "previous" and "next" controllers.
* Navigating among table rows through a display list.
{{tip| '''Tip''': Notice that both systems can be used. }}
You can directly set [[#dv_s_control| controllers]] for "previous" and"next" actions. A 3rd controller, "edit list", enables to show or raise the display list.
{{warning| '''Caution''': Notice that DV_CONTROL_NAVIGATOR only manages this controller sensitivity. }}
You can assign a [[#dv_tablerow_list| display list]] to the navigator with a [[ref:libraries/store/reference/dv_tablerow_list_chart|DV_TABLEROW_LIST]] component.
===4.4. DV_CREATOR class===
====4.4.1. Overview====
This class enables to create database table rows.
[[Image:component-create-relation]]
Basic relationship between table component class and navigation class
[[ref:libraries/store/reference/dv_creator_chart|DV_CREATOR]] class contains minimum information to interact with [[ref:libraries/store/reference/dv_tablerows_component_chart|DV_TABLE_COMPONENT]] : when a table row is created, a creator component may display it on the table component. In this case, when the table component needs to refresh the table rows set, this refreshing action need to be managed by the creator component:
* `set_just_created' informs a table component that displayed table row set comes from the creator component.
* `refresh' lets the creation component refresh table component display.
Much of the work, that is row creation, is totally abstracted in DV_CREATOR.DV_CHOICE_CREATOR implements DV_CREATOR and thus affords a creation procedure.
====4.4.2. DV_CHOICE_CREATOR class====
=====4.4.2.1. Overview=====
This class creates a new table row and sets its key values:
* Database handle gives the primary key value (ID) .
* The class asks the user for foreign key values (for table associations) by displaying available values in a list.
DV_TABLEROW_NAVIGATOR is used to select a foreign key value, let us see how this is implemented:
[[Image:dv-choice-creator-fkeys-selection]]
[[ref:libraries/store/reference/dv_choice_creator_chart|DV_CHOICE_CREATOR]] suppliers for foreign keys selection
[[ref:libraries/store/reference/dv_tablerow_id_provider_chart|DV_TABLEROW_ID_PROVIDER]] inherits from [[ref:libraries/store/reference/dv_tablerows_component_chart|DV_TABLEROWS_COMPONENT]] to interface with [[ref:libraries/store/reference/dv_tablerows_navigator_chart|DV_TABLEROWS_NAVIGATOR]] .
Relation between [[ref:libraries/store/reference/dv_choice_creator_chart|DV_CHOICE_CREATOR]] and [[ref:libraries/store/reference/dv_tablerow_id_provider_chart|DV_TABLEROW_ID_PROVIDER]] is basically:
[[Image:creator-provider-relation]]
<eiffel>DV_CHOICE_CREATOR/DV_TABLEROW_ID_PROVIDER</eiffel> basic interactions
Creation process and [[ref:libraries/store/reference/dv_choice_creator_chart|DV_CHOICE_CREATOR]] objects creation procedure can help you use this class.
=====4.4.2.2. Creation process=====
Table row creation process is:
# Table row creation is triggered by a [[#dv_s_control| controller]] ("create")
# <eiffel>DV_CHOICE_CREATOR</eiffel> creates a table row object
# <eiffel>DV_CHOICE_CREATOR </eiffel> requests a first foreign key value to [[ref:libraries/store/reference/dv_tablerow_id_provider_chart|DV_TABLEROW_ID_PROVIDER]] (through `select_from_table')
# <eiffel>DV_TABLEROW_ID_PROVIDER </eiffel> loads the available table rows that can be referenced
# <eiffel>DV_TABLEROW_ID_PROVIDER</eiffel> assigns the table rows to <eiffel>DV_TABLEROWS_NAVIGATOR</eiffel> and pops up the interface with the table rows
# Table row selection is triggered by a [[#dv_s_control| controller]] ("ok")
# <eiffel>DV_TABLEROW_ID_PROVIDER</eiffel> retrieves the selected table row ID and gives it back to <eiffel>DV_CHOICE_CREATOR</eiffel> (through `add_foreign_key_value')
# <eiffel>DV_CHOICE_CREATOR</eiffel> requests other foreign key values to <eiffel>DV_TABLEROW_ID_PROVIDER</eiffel>
# <eiffel>DV_CHOICE_CREATOR</eiffel> creates the database row with a new ID through the database handle
=====4.4.2.3. Objects creation procedure=====
To create a DV_CHOICE_CREATOR, follow these steps:
# Create an object conforming to DV_TABLEROWS_NAVIGATOR
# Create a <eiffel>DV_TABLEROW_ID_PROVIDER</eiffel> object and assign the <eiffel>DV_TABLEROWS_NAVIGATOR</eiffel> object to it
# Set a [[#dv_s_control| controller]] to trigger foreign key selection
# Set the action to perform to pop up the interface to select the foreign key
# Create a <eiffel>DV_CHOICE_CREATOR</eiffel> object and assign the <eiffel>DV_TABLEROW_ID_PROVIDER</eiffel> object to it
# Set a [[#dv_s_control| controller]] to trigger table row creation
===4.5. DV_TABLEROW_FIELDS class===
====4.5.1. Overview====
This class enable to display and edit the current table row of a table component. Let us see first how it interacts with the table component:
[[Image:component-fields-relation]]
DV_TABLE_COMPONENT/DV_TABLEROW_FIELDS basic interactions
* refresh_tablerow refreshes display with a new table row
* update_tablerow requests an updated table row for database update. Unchanged values are kept from a default table row
* updated_tablerow is the last updated table row
The class contains a list of fields that represent editable table attributes.The design is simple:
[[Image:dv-tablerow-fields-design]]
Table row edition capability design
====4.5.2. DV_TABLEROW_FIELD class====
This class enables to edit a table row attribute value. The view is abstracted using the handle cluster [[ref:libraries/store/reference/dv_sensitive_string_chart|DV_SENSITIVE_STRING]] class that [[#dv_s_string|represents the editable text value]] .
This class manages a field value but can also provide field name and type if [[#dv_s_string|graphic fields]] are provided. Notice that standard [[ref:libraries/store/reference/dv_tablerow_field_chart|DV_TABLEROW_FIELD]] objects can be generated through the [[ref:libraries/store/reference/dv_factory_chart|DV_FACTORY]] class, which is a component factory.
==5. Handle cluster==
This cluster provides the model with an interface to input or output data on the GUI. This enables to remove any link to a graphic implementation in the model, following the [[#model-view_sep|Model-View separation]] design pattern. The cluster contains a set of interface classes to design this:
* The [[ref:libraries/store/reference/dv_sensitive_control_chart|DV_SENSITIVE_CONTROL]] class to [[#dv_s_control|let the user trigger an action]] .
* The [[ref:libraries/store/reference/dv_sensitive_string_chart|DV_SENSITIVE_STRING]] class to [[#dv_s_string|input or output a text value]] .
* The [[ref:libraries/store/reference/dv_sensitive_string_chart|DV_SENSITIVE_INTEGER]] class to [[#dv_s_integer|input or output a quantity value]] .
* The [[ref:libraries/store/reference/dv_sensitive_check_chart|DV_SENSITIVE_CHECK]] class to [[#dv_s_check|input or output a tag value]] .
* The [[ref:libraries/store/reference/dv_tablerow_list_chart|DV_TABLEROW_LIST]] class to [[#dv_tablerow_list|display a set of table rows and grab events on it]] .
===5.1. DV_SENSITIVE_CONTROL class===
The [[ref:libraries/store/reference/dv_sensitive_control_chart|DV_SENSITIVE_CONTROL]] class lets a model class trigger a specific action on a determined user event. Furthermore, the model class lets the user know when its state enables to trigger the action, by setting the controller sensitivity (i.e. if the controller is insensitive, the action cannot be triggered).
{{note| '''Note''': sensitivity excepted, these controllers could have been implemented by Eiffel ''agents''. }}
{{note| '''Note''': sensitivity enables to let the user know ''before''triggering an action if this is possible or not. The other possibility is to let the user know ''after'' trying to trigger the action that it was not possible(with a warning for instance): this is often less convenient. }}
The standard controllers are buttons or menu items: the specific action is triggered when button is clicked or menu item selected.
[[ref:libraries/store/reference/dv_sensitive_control_chart|DV_SENSITIVE_CONTROL]] is inherited by [[ref:libraries/store/reference/dv_button_chart|DV_BUTTON]] that implements an EiffelVision2 button. Other implementations can be added, such as a menu item.
===5.2. DV_SENSITIVE_STRING class===
The [[ref:libraries/store/reference/dv_sensitive_string_chart|DV_SENSITIVE_STRING]] class lets a model class input or output a text graphically. As for controllers, the model class lets the user know when a text value can be input by setting the widget sensitivity.
The standard graphical widgets to perform this are text fields, but several other widgets can be used:
* A combo-box so that the interface can suggest different values.
* A label if the text only need to be output.
{{note| '''Note''': customized, specific widgets can be defined, you can for instance take a look at the DV_STRING_LIST class. }}
===5.3. DV_SENSITIVE_INTEGER class===
This class lets a model class input or output an <eiffel>INTEGER</eiffel> value graphically. As for controllers, the model class lets the user know when an integer value can be input by setting the widget sensitivity.
Different widgets can be used to implement this:
* A text field. Notice that the value entered should be checked to ensure it is an <eiffel>INTEGER </eiffel>value.
* A combo-box. Each combo-box option is associated to an integer.
* A scroll button.
===5.4. DV_SENSITIVE_CHECK class===
This class lets a model class input or output a <eiffel>BOOLEAN </eiffel>value graphically. As for controllers, the model class lets the user know when a Boolean value can be input by setting the widget sensitivity.
The standard widget to implement this is a check box.
===5.5. DV_TABLEROW_LIST class===
The [[ref:libraries/store/reference/dv_tablerow_list_chart|DV_TABLEROW_LIST]] class provides an interface to display a set of table rows so that the user can select a particular row.
* The model can be informed of a row selection or deselection: the class accepts actions (implemented by ''agents'') that are triggered when a row is selected or deselected.
* The model can retrieve the currently selected row: the class yields the current index position in the list.
[[ref:libraries/store/reference/dv_tablerow_multilist_chart|DV_TABLEROW_MULTILIST]] implements DV_TABLEROW_LIST with an EiffelVision2 multi-column list.
{{note| '''Note''': This class is used for the [[#dv_control_navigator|standard implementation]] of [[ref:libraries/store/reference/dv_tablerows_navigator_chart|DV_TABLEROW_NAVIGATOR]] to [[#dv_tablerow_navigator|navigate among table rows]] selected from the database. }}

View File

@@ -0,0 +1,654 @@
[[Property:title|Data structures creation]]
[[Property:weight|1]]
==1. Overview==
EiffelStore enables to create data structures mapped to your own database. This part describes how the EiffelStore wizard generates these structures mapped to your database and how you can map your own classes to your database with EiffelStore.
'''Tip:''' We recommend that you read [[Data structures use|what are and how to use]] these data structures before reading this section.
The EiffelStore wizard generates the database-specific classes from an EiffelStore generation system based on template files containing tags.
Let us see first [[#generation_system| how the EiffelStore generation system works]] . Let us see then [[#wizard_generation| how the EiffelStore wizard uses this system]] for the data structures generation.
==2. EiffelStore generation system==
This part describes the class creation in 4 steps:
* [[#capabilities|Mapping system possibilities]]
* [[#mapping_system|General mapping system]]
* [[#tags_descr|Tags description]]
* [[#gen_impl_overview|Implementation overview]]
===2.1. Capabilities===
Let us see first what information you can map into your classes.
2 kinds of classes can be generated:
* Classes that represents a database table.
* Classes that represents the whole database.
====2.1.1. Database table classes====
You can insert information about a database table:
* The table name
* The number of attributes of table
You can also select a piece of code, map it to a table attribute and repeat the operation for every attribute. Information that can be inserted is:
* The attribute names
* The attribute types
* The attribute default creation values
* The attribute positions in the table
Thus you can get for instance class attributes that correspond to database attributes:
<code>
class CONTACTS
feature
id: INTEGER
lastname: STRING
firstname: STRING
</code>
You can also modify the piece of code to map for the first and last attributes, for cosmetics reasons. You can also choose to only map a piece of code to attributes of a given type.
====2.1.2. Database content classes====
Database content classes can basically store the list of your database tables.
You can select a piece of code and map it to database table information:
* Database table name.
* Database table position in the database.
The mapped pieces of code are then concatenated in your file.
===2.2. General mapping system===
EiffelStore follows this sequence of steps to generate a class:
# You provide meta-data about the table or view
# You provide the template
# It parses the template to find the tags
# It replaces each tag by the meta-data value corresponding to the tag
Let us take an example:
{| border="1"
|-
| template file extract
| corresponding result file extract
|-
| attribute_count: <ACNT>
| attribute_count: 5
|}
This works for meta-data on the class or view. For meta-data on class (or view) attributes, a second tag type enables to specify text areas that are mapped to specific table (or view) attributes.
Let us take an example:
{| border="1"
|-
| template file extract
| corresponding result file extract
|-
| <A:A:A><AN:L>: <TN:U> <br/>
</A>
| companyid: DOUBLE <br/>
companyname: STRING
|}
Text contained in the tag 'A' is mapped to each table (or view) attribute and the resulting texts are concatenated. Let us see now the details about each tag.
===2.3. Tags description===
====2.3.1. Database table tags description====
The available tags for database table classes generation can be separated into 3 types:
* Tags corresponding to [[#table_meta-data|table meta-data]]
* Tags corresponding to [[#attribute_meta-data|attribute meta-data]]
* Tags to [[#enclosing_tag|enclose attribute meta-data]]
=====2.3.1.1. Table meta-data tags=====
{| border="1"
|-
| '''Tag name'''
| '''Tag description'''
| '''Options'''
|-
| '''Option name'''
| '''Option description'''
|-
| <CN:?>
| Table name
| U
| in uppercase
|-
| I
| with initial capital
|-
| L
| in lowercase
|-
| <ACNT>
| Attribute count
| N/A
|}
=====2.3.1.2. Attribute meta-data tags=====
{| border="1"
|-
| '''Tag name'''
| '''Tag description'''
| '''Options'''
|-
| '''Option name'''
| '''Option description'''
|-
| <AN:?>
| Attribute name
| U
| in uppercase
|-
| I
| with initial capital
|-
| L
| in lowercase
|-
| <IT>
| Attribute position in the table
| N/A
|-
| <TN:?>
| Attribute type name
| U
| in uppercase
|-
| I
| with initial capital
|-
| L
| in lowercase
|-
| <TDV>
| Attribute type default value
| N/A
|}
'''Note''': Attribute tags are only valid within an enclosing tag.
=====2.3.1.3. Enclosing tags=====
The tag <A:?:?> </A> encloses text that will be mapped to attributes matching criteria. These criteria are specified by the tag options:
* First option: attribute type criterion
{| border="1"
|-
| '''Option name'''
| '''Option description'''
|-
| A
| All attributes
|-
| I
| INTEGER attributes
|-
| S
| STRING attributes
|-
| D
| DATE attributes
|-
| B
| BOOLEAN attributes
|-
| C
| CHARACTER attributes
|-
| F
| DOUBLE attributes
|}
* Second option: attribute position criterion
{| border="1"
|-
| '''Option name'''
| '''Option description'''
|-
| A
| All attributes
|-
| F
| First attribute
|-
| I
| Intermediate attributes
|-
| L
| Last attribute
|}
* '''Note''': this option is generally used to have a valid and nice layout or indentation.
'''Note''': several options can be selected for one criterion.
====2.3.2. Database content tags description====
The tags described above can be reused for database content:database content class mapping is equivalent to the previous mapping but within a different scope:
* class corresponds to the database rather than tables
* class content deals with tables rather than table attributes
The meaning of available tags is so modified:
* [[#system_meta-data_ext|System meta-data tags]]
* [[#table_meta-data_ext| Table meta-data tags]]
* [[#enclosing_tag_ext| Enclosing tags]]
'''Note''': every tag is not available for this mapping.
=====2.3.2.1. System meta-data tags=====
{| border="1"
|-
| '''Tag name'''
| '''Tag description'''
|-
| <ACNT>
| Table count
|}
=====2.3.2.2. Table meta-data tags=====
{| border="1"
|-
| '''Tag name'''
| '''Tag description'''
| '''Options'''
|-
| '''Option name'''
| '''Option description'''
|-
| <CN:?>
| Table name
| U
| in uppercase
|-
| I
| with initial capital
|-
| L
| in lowercase
|-
| <IT>
| Table position in the database
| N/A
|}
=====2.3.2.3. Enclosing tags=====
The tag <A:A:?> </A> encloses text that will be mapped to tables matching a position criterion. This criterion is specified by the tag options:
{| border="1"
|-
| '''Option name'''
| '''Option description'''
|-
| A
| All tables
|-
| F
| First table
|-
| I
| Intermediate tables
|-
| L
| Last table
|}
===2.4. Implementation overview===
The data structure generation system is implemented with 4 EiffelStore classes:
* DB_CLASS_GENERATOR abstractly generates a class mapped to database meta-data.
* DB_TABLE_CLASS_GENERATOR generates a class mapped to a database table.
* DB_ACCESS_CLASS_GENERATOR generates a class mapped to the database.
* DB_TEMPLATE_TAGS defines available tags for mapping and their meaning.
[[Image:estore-generation.generator]]
Generation classes BON diagram
==3.EiffelStore wizard==
The EiffelStore wizard uses the [[#generation_system| EiffelStore generation system]] described above to generate the data structures mapped to your database.
The wizard generates 3 types of classes:
* [[#wiz_table_classes|Classes storing database table rows content]]
* [[#wiz_descr_classes|Classes describing a database table]]
* [[#wiz_access_class|A class describing the database and giving access to the previous types of classes]]
The wizard uses one different template for each class.
===3.1. Table classes===
For each selected database table, a class is created from the same template, mapping the database table. This template is:
<code>
indexing
description: "Class which allows EiffelStore to retrieve/store%
%the content of a table row from database table <CN:U>"
author: "EiffelStore Wizard"
date: "$Date: 2004-12-09 23:29:16 +0100 (Thu, 09 Dec 2004) $"
revision: "$Revision: 46989 $"
class
<CN:U>
inherit
DB_TABLE
-- redefine
-- out
-- end
undefine
Tables,
is_valid_code
end
DB_SPECIFIC_TABLES_ACCESS_USE
create
make
feature -- Access
<A:A:A> <AN:L>: <TN:U>
</A> table_description: DB_TABLE_DESCRIPTION is
-- Description associated to the <CN:L>.
do
tables.<CN:L>_description.set_<CN:L> (Current)
Result := tables.<CN:L>_description
end
feature -- Initialization
set_default is
do
<A:A:A> <AN:L> := <TDV>
</A>
end
feature -- Basic operations
<A:A:A> set_<AN:L> (a_<AN:L>: <TN:U>) is
do
<AN:L> := a_<AN:L>
end
</A>feature -- Output
out: STRING is
-- Printable representation of current object.
do
Result := ""
<A:A:A>
if <AN:L> /= Void then
Result.append ("<AN:I>: " + <AN:L>.out + "%N")
end
</A>
end
end -- class CODES
</code>
'''Note''': the template content can be adjusted, for instance to add comments or change the indexing. However, the fundamental template structure should not be changed to use data structures as described in the [[Data structures use|corresponding section]] .
===3.2. Description classes===
For each selected database table, a class is also created from a unique template, mapping the database table. This template is:
<code>
indexing
description: "Description of class <CN:U>"
author: "EiffelStore Wizard"
date: "$Date: 2004-12-09 23:29:16 +0100 (Thu, 09 Dec 2004) $"
revision: "$Revision: 46989 $"
class
<CN:U>_DESCRIPTION
inherit
DB_TABLE_DESCRIPTION
-- rename
-- Tables as Abstract_tables
undefine
Tables,
is_valid_code
end
DB_SPECIFIC_TABLES_ACCESS_USE
create
{DB_SPECIFIC_TABLES_ACCESS} make
feature -- Access
Table_name: STRING is "<CN:U>"
Table_code: INTEGER is <CI>
Attribute_number: INTEGER is <ACNT>
-- Number of attributes in the table.
Id_code: INTEGER is
-- Table ID attribute code.
do
Result := <IC>
end
<A:A:A> <AN:I>: INTEGER is <IT>
</A> attribute_code_list: ARRAYED_LIST [INTEGER] is
-- Feature code list
once
create Result.make (Attribute_number)
<A:A:A> Result.extend (<AN:I>)
</A> end
description_list: ARRAYED_LIST [STRING] is
-- Feature name list. Can be interpreted as a list
-- or a hash-table.
once
create Result.make (Attribute_number)
<A:A:A> Result.extend ("<AN:I>")
</A> end
type_list: ARRAYED_LIST [INTEGER] is
-- Feature type list. Can be interpreted as a list
-- or a hash-table.
once
create Result.make (Attribute_number)
<A:A:A> Result.extend (<TN:I>_type)
</A> end
to_delete_fkey_from_table: HASH_TABLE [INTEGER, INTEGER] is
-- List of tables depending on this one and their
-- foreign key for this table.
-- Deletion on this table may imply deletions on
-- depending tables.
once
<DH> end
to_create_fkey_from_table: HASH_TABLE [INTEGER, INTEGER] is
-- List of associated necessary tables and the
-- linking foreign keys.
-- Creation on this table may imply creations on
-- associated necessary tables.
once
<CH> end
attribute (i: INTEGER): ANY is
-- Get feature value of feature whose code is 'i'.
do
inspect i
<A:A:A>
when <AN:I> then
Result := <CN:L>.<AN:L>
</A>
end
end
set_attribute (i: INTEGER; value: ANY) is
-- Set feature value of feature whose code is `i' to `value'.
-- `value' must be of type STRING, INTEGER, BOOLEAN, CHARACTER,
-- DOUBLE or DATE_TIME. References are made automatically from
-- expanded types.
local
integer_value: INTEGER_REF
double_value: DOUBLE_REF
boolean_value: BOOLEAN_REF
character_value: CHARACTER_REF
date_time_value: DATE_TIME
string_value: STRING
do
inspect i
<A:S:A>
when <AN:I> then
string_value ?= value
<CN:L>.set_<AN:L> (string_value)
</A><A:F:A> when <AN:I> then
double_value ?= value
if double_value /= Void then
<CN:L>.set_<AN:L> (double_value.item)
else
<CN:L>.set_<AN:L> (0.0)
end
</A><A:I:A>
when <AN:I> then
integer_value ?= value
if integer_value /= Void then
<CN:L>.set_<AN:L> (integer_value.item)
else
<CN:L>.set_<AN:L> (0)
end
</A><A:D:A>
when <AN:I> then
date_time_value ?= value
<CN:L>.set_<AN:L> (date_time_value)
</A><A:C:A>
when <AN:I> then
character_value ?= value
if character_value /= Void then
<CN:L>.set_<AN:L> (character_value.item)
else
<CN:L>.set_<AN:L> ('%U')
end
</A><A:B:A>
when <AN:I> then
boolean_value ?= value
if boolean_value /= Void then
<CN:L>.set_<AN:L> (boolean_value.item)
else
<CN:L>.set_<AN:L> (False)
end
</A>
end
end
feature {<CN:U>} -- Basic operations
set_<CN:L> (a_<CN:L>: <CN:U>) is
-- Associate the description to a piece of <CN:L>.
require
not_void: a_<CN:L> /= Void
do
<CN:L> := a_<CN:L>
ensure
<CN:L> = a_<CN:L>
end
feature {NONE} -- Implementation
<CN:L>: <CN:U>
-- Piece of <CN:L> associated with the description
end -- class CODES_DESCRIPTION
</code>
'''Note''': As for the table class generation, the template content can be adjusted, for instance to add comments or change the indexing. However, the fundamental template structure should not be changed.
Some additional tags are directly replaced by the wizard:
* The <CR> and <DR> tags are replaced with information on associated tables.
* The <IC> tag is replaced by information on the primary key (table ID).
* The <CI> tag is replaced by the table position in the database.
===2.3.3. Access class===
The <eiffel>DB_SPECIFIC_TABLES_ACCESS</eiffel> class is mapped to the database from the following template:
<code>
indexing
description: "Description of database tables.%
%Use this class through DB_SPECIFIC_TABLES_ACCESS_USE."
author: "EiffelStore Wizard"
date: "$Date: 2004-12-09 23:29:16 +0100 (Thu, 09 Dec 2004) $"
revision: "$Revision: 46989 $"
class
DB_SPECIFIC_TABLES_ACCESS
inherit
DB_TABLES_ACCESS
creation
make
feature -- Access
<A:A:A> <CN:I>: INTEGER is <IT>
</A> Table_number: INTEGER is <ACNT>
code_list: ARRAYED_LIST [INTEGER] is
-- Table code list.
once
create Result.make (Table_number)
<A:A:A> Result.extend (<CN:I>)
</A> end
name_list: ARRAYED_LIST [STRING] is
-- Table name list. Can be interpreted as a list
-- or a hash-table.
once
create Result.make (Table_number)
<A:A:A> Result.extend ("<CN:I>")
</A> end
obj (i: INTEGER): DB_TABLE is
-- Return instance of table with code `i'.
do
inspect i
<A:A:A>
when <CN:I> then
create {<CN:U>} Result.make
</A>
end
end
description (i: INTEGER): DB_TABLE_DESCRIPTION is
-- Return description of table with code `i'.
do
inspect i
<A:A:A>
when <CN:I> then
Result := <CN:L>_description
</A>
end
end
<A:A:A> <CN:L>_description: <CN:U>_DESCRIPTION is
-- Unique description of table `<CN:U>'.
once
create Result.make
end
</A>
end -- class DB_SPECIFIC_TABLES_ACCESS
</code>

View File

@@ -0,0 +1,222 @@
[[Property:title|Data structures use]]
[[Property:weight|0]]
==1. Overview==
EiffelStore affords a context that optimizes and facilitates the use of the classes that maps your database content.
The main advantage of database-specific structures is the static checking: you can determine at compile-time the type of information you are accessing or modifying.
However, it can be more flexible to determine the type of data you are dealing with at run-time. This can be particularly useful for GUI applications, take a look at the [[EiffelStore DataView Cluster|DataView cluster]] .
Each data structure carries some meta-data about its type so that the run-time typing hazards can be avoided with assertions based on this meta-data.
The advantage of this system is two-fold:
* You can choose to use compile-time type checking or not, depending on your own needs.
* If you choose run-time type checking, assertions ensure that each object type is valid and prevent cat calls.
Let us see first [[#capabilities|what you can do]] with data structures and their context, then [[#implementation|how it is implemented]] .
==2. Data structure capabilities==
Database-specific classes and their context let you perform the following operations:
* [[#cap_storage|Storing table/view rows content]]
* [[#cap_manipulation|Manipulating abstract table/view rows content]]
* [[#cap_objects_metadata|Getting objects metadata]]
* [[#cap_database_metadata|Accessing database metadata]]
* [[#cap_more|More interesting features]]
===2.1. Storing table/view rows content===
You can store table/view rows content into classes that have the table or view name: one database table/view row correspond to one Eiffel object. Each table attribute will correspond to a class attribute with the same name. ''set'' commands enable to change the object content to insert rows in the database or update rows. [[ref:libraries/store/reference/db_selection_flatshort|DB_SELECTION]] class can directly map database results into these objects, and you can directly create a table/view row from one object with the [[ref:libraries/store/reference/db_store_flatshort|DB_STORE]] class. Take a look at the [[Data Object Coupling|data-object coupling]] section.
===2.2. Manipulating abstract table/view rows content===
Each table/view storage structure inherits from the [[ref:libraries/store/reference/db_table_flatshort|DB_TABLE]] abstract class. This enables to handle [[ref:libraries/store/reference/db_table_flatshort|DB_TABLE]] objects as abstract database table/view structures.
You can then access or modify [[ref:libraries/store/reference/db_table_flatshort|DB_TABLE]] attributes: instead of accessing attributes with their ''name'', which implies that the object type is known at compile-time, attributes can then be accessed with a ''code''.
<code>
tablerow: DB_TABLE
...
display_attribute (code: INTEGER) is
-- Display attribute with `code'.
do
io.putstring (tablerow.table_description.attribute (code).out)
end
</code>
{{note| '''Note:''' to access attributes data with ''code'', you need to use the [[ref:/libraries/store/reference/db_table_description_flatshort|DB_TABLE_DESCRIPTION]] object associated to your [[ref:libraries/store/reference/db_table_flatshort|DB_TABLE]] object. }}
===2.3. Getting objects metadata===
While manipulating <eiffel>DB_TABLE</eiffel> objects, you can easily get:
* Which database table/view the object references.
* What are the types of its attributes.
'''Note:''' you also get objects metadata through the <eiffel>DB_TABLE_DESCRIPTION</eiffel> object associated to your DB_TABLE object.
Objects metadata used in assertions ensures objects type validity. To illustrates this, let's look at the contract form of a class that manipulates "abstract" table/view rows:
<code>
set_table_code (code: INTEGER)
-- Assign `code' to `tablecode'.
tablecode: INTEGER
-- Table code.
compute (tablerow: DB_TABLE)
-- Compute `tablerow'.
require
type_is_ok: tablerow.table_description.Table_code = tablecode
</code>
===2.4. Accessing database metadata===
Basic database metadata is also available: the <eiffel>DB_SPECIFIC_TABLES_ACCESS_USE</eiffel> class (generated), stores INTEGER codes for each database table/view. These codes afford related table/view name and related new storing objects (i.e. that conforms to DB_TABLE class).
<code>
tables: DB_SPECIFIC_TABLES_ACCESS
...
new_object (code: INTEGER): DB_TABLE is
-- New object of table with `code'.
do
Result := tables.obj (code)
end
</code>
===2.5. More interesting features===
The <eiffel>DB_TABLE_DESCRIPTION</eiffel> class offers more features to get table row attributes as conveniently as possible:
* The table/view row primary key value (ID)
* The list of table/view row attributes
* A selection of table/view row attributes
* The list of table/view row attributes mapped to a function.
* Printable attribute values (i.e. the associated STRING values)
==3. Implementation==
Database-specific classes can be divided into 3 types:
* Classes holding database table rows content (inheriting from <eiffel>DB_TABLE</eiffel>)
* Classes describing database tables (inheriting from <eiffel>DB_TABLE_DESCRIPTION</eiffel>)
* A class describing the database and giving access to the previous types of classes (inheriting from <eiffel>DB_TABLES_ACCESS</eiffel>)
One database table is hence associated to one table class and one description class. Both classes are closely [[#table-descr_relationship| interrelated]] to provide what the developer need. The [[#table_access_classes|table access classes]] describes the database tables and gives access to both table and description classes.
Each database-specific (generated) class inherits from an abstract class. These abstract classes gathers all the facilities that are not specific to your database, and so that can be inherited by all the database-specific classes.
Let us see abstract and database-specific classes relationship:
[[Image:tables-access-inherit]]
General and generated classes relationships
* Yellow classes are abstract.
* Green classes are database-specific.
==2. Table and description classes relationship==
Table classes, that inherit from <eiffel>DB_TABLE</eiffel>, and description classes, that inherit from <eiffel>DB_TABLE_DESCRIPTION</eiffel>, both deals with database tables. This section explains what are their own role and their relationship.
===2.1. Table classes===
As seen in the previous section, table classes merely store table rows attribute values. Their objects can be considered as database table rows, or more precisely, database table rows on the Eiffel side. These classes inherit from <eiffel>DB_TABLE</eiffel>.
Each of these classes are associated to a description class.
'''Tip:''' Use table classes to ''carry'' data.
===2.2. Description classes===
The description classes goal is 3-fold:
* [[#cap_objects_metadata|Getting meta-data]] about the table represented at run-time.
* [[#cap_manipulation|Getting table rows data]] dynamically.
* [[#cap_more|Facilitating data management]] .
These descriptions inherit from [[ref:libraries/store/reference/db_table_description_flatshort|DB_TABLE_DESCRIPTION]] .
Since they only describes a table and provide tools, description objects can be unique. EiffelStore ensures their unicity for resources optimization.
'''Tip:''' Use description classes to ''access and modify'' data.
===2.3. Relationship===
Each table class is associated to the description class corresponding to the same database table.
A table class object provides the associated table description:
<code>
row: DB_TABLE
description: DB_TABLE_DESCRIPTION
...
row := db_manager.database_result
description := row.table_description
</code>
As descriptions are unique, every table row object is associated to the same description. The following figure illustrates this:
[[Image:table-descr-objects]]
table and description objects relationship
As seen in the previous section, to manipulate abstract table/view rows content, you have to use the description class. The following example shows how to output a table row ID value.
<code>
row: DB_TABLE
description: DB_TABLE_DESCRIPTION
...
-- Link description unique object to `row' content.
description := row.table_description
io.putstring (description.attribute (description.id_name) + ": ")
io.putstring (description.attribute (description.id_code).out)
</code>
As descriptions are unique, this means that description objects are also associated to a specific table object to deal with it (i.e. access or modify its content). Actually, the table_description feature associates the description with the current object and then returns this description.
{{note| '''Note:''' The table_description feature is still a query as the association part should not be visible at the interface level. }}
On the whole, you have to pay attention to always execute table_descriptionon your table/view row to get the appropriate description.
==3. Table access classes==
===3.1. Overview===
Table access classes provide facilities to manage table row and table description objects. They also give basic database table meta-data.
The following figure shows table access classes and their relations.
* Yellow classes are EiffelStore classes
* Green class is generated
* Pink class is an application class
[[Image:db-specific-tables-access-use]]
Table access classes BON diagram
[[Image:table-descr-access-objects]]
Relationship between the tables access object, description and table objects
===3.2. DB_SPECIFIC_TABLES_ACCESS class===
The <eiffel>DB_SPECIFIC_TABLES_ACCESS</eiffel> class stores the unique table description object. It also provides the following facilities:
* Every database table code
* Table descriptions from a table code
* Sample table class objects from a table code
* Table names from a table code
'''Note''': database table codes given in the class match the table codes provided by <eiffel>DB_TABLE_DESCRIPTION</eiffel>.
===3.3. Abstract access class===
The DB_TABLES_ACCESS class provides an interface for the <eiffel>DB_SPECIFIC_TABLES_ACCESS</eiffel> class which is non-specific to the database. This can be used by non database-specific code (for instance the [[EiffelStore DataView Cluster|DataView cluster]] ) to access database tables.
Unique table description objects and table codes are of course not directly available from this class, but the following features are still available:
* Table descriptions from a table code
* Sample table class objects from a table code
* Table names from a table code
===3.4. Use classes===
The <eiffel>DB_SPECIFIC_TABLES_ACCESS</eiffel> object can be accessed as a kind of "global variable" by any class which inherits from <eiffel>DB_SPECIFIC_TABLES_ACCESS_USE</eiffel>. This class also ensures <eiffel>DB_SPECIFIC_TABLES_ACCESS</eiffel> object unicity.
The DB_TABLES_ACCESS_USE class affords the same possibility but with no reference to the <eiffel>DB_SPECIFIC_TABLES_ACCESS</eiffel> object. The unique <eiffel>DB_SPECIFIC_TABLES_ACCESS</eiffel> should be set to this class as of type <eiffel>DB_TABLES_ACCESS</eiffel>.
<br/>

View File

@@ -0,0 +1,11 @@
[[Property:title|EiffelStore Generation Cluster]]
[[Property:weight|2]]
The EiffelStore library lets the user associate database elements with Eiffel objects. These database elements are basically database table rows, database view rows or more generally sets of database attribute values. The easiest way to manipulate database elements is to insert their content into Eiffel objects and to work on these Eiffel objects as database elements.
A first solution to implement this is to use some adaptable structures that will fit to any database element. This is done in EiffelStore through the [[ref:libraries/store/reference/db_tuple_flatshort|DB_TUPLE]] class, which contains mainly an [[ref:libraries/base/reference/array_chart|ARRAY]] [[[ref:libraries/base/reference/string_8_chart|STRING]] ] containing element attribute names and an [[ref:libraries/base/reference/array_chart|ARRAY]] [[[ref:libraries/base/reference/any_chart|ANY]] ] containing element attribute values. This solution has one major drawback: any static checking is impossible: the developer cannot be sure at compile time of the nature of a [[ref:libraries/store/reference/db_tuple_flatshort|DB_TUPLE]] , i.e. what it represents, and cannot know if attributes number, names and types are correct. To overcome this problem, a second solution is to use data structures that statically fits to the expected database element, as introduced in the [[Data Object Coupling|DataObject Coupling]] section.
The major problem of this technique is that structures are static: one structure, so one class instead of one object, should be created for each database element.

View File

@@ -0,0 +1,91 @@
[[Property:title|EiffelStore Implementation Layer]]
[[Property:weight|1]]
Each interface class has an implementation counterpart that implements specific DBMS handling. The class prefix indicates clearly its layer, for instance:
* [[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] is the interface to perform a database selection query.
* [[ref:/libraries/store/reference/database_selection_flatshort|DATABASE_SELECTION]] [[[ref:/libraries/store/reference/database_flatshort|DATABASE]] ] is its implementation.
The abstract [[ref:/libraries/store/reference/database_flatshort|DATABASE]] class represents a DBMS, i.e. it is the Eiffel-side database call interface. It is inherited for instance by the instantiable <eiffel>ORACLE</eiffel> and <eiffel>ODBC</eiffel> classes.
EiffelStore enables to link common interface objects with database-specific implementation objects using a '''handle'''. This handle also enables to switch between different databases.
Let us see in 4 steps how EiffelStore implements this handle system:
* The [[#handle|active database handle]] .
* The [[#association|association between interface and implementation]] objects.
* The [[#access|access to the DBMS call interface]] from the implementation layer.
* The [[#selection|active database selection]] from the database application.0
==The active database handle==
The <eiffel>HANDLE_USE </eiffel>class provides access to the unique <eiffel>HANDLE</eiffel> instance. This object stores all the information about the active database, mainly:
* Database login information:
<code>
login: LOGIN [DATABASE]
-- Session login
</code>
* Database status information:
<code>
status: DB_STATUS
-- Status of active database
</code>
==Association between interface and implementation==
The association between an interface object and its implementation counterpart is done at the interface object creation.
Every interface class inherits from the <eiffel>HANDLE_USE</eiffel> class and can access the active database handle. This handle contains a <eiffel>DB</eiffel> [<eiffel>DATABASE</eiffel>] object that provides implementation objects corresponding to every interface objects.
The creation procedure for a <eiffel>DB_CHANGE</eiffel> object is for instance:
<code>
make is
-- Create an interface object to change active base.
do
implementation := handle.database.db_change
create ht.make (name_table_size)
implementation.set_ht (ht)
end
</code>
==Access to the DBMS call interface==
Every implementation class can access the active database call interface by inheriting from the <eiffel>HANDLE_SPEC</eiffel> [<eiffel>DATABASE</eiffel>] class. This class provides access to the <eiffel>DATABASE</eiffel> object, i.e. an instance of class ORACLE or ODBC.
<eiffel>DATABASE </eiffel>descendants are actually wrappers for the DBMS call interfaces written in C. More precisely, call interfaces as delivered by the DBMS companies are called in an EiffelStore C library. The C libraries are then wrapped into Eiffel classes, <eiffel>DATABASE</eiffel> descendants.
==Active database selection==
As seen in the [[Database Connection|interface connection]] part, active database selection is performed by the {<eiffel>DATABASE_APPL</eiffel>}.<eiffel>set_base</eiffel> feature: when a <eiffel>DATABASE_APPL</eiffel> object calls set_base, database represented by this object is activated.
Let us give some details about the set_base feature:
* Database call interface global reference is updated through {<eiffel>HANDLE_SPEC</eiffel>}.<eiffel>update_handle</eiffel>.
* All information about the database is set to the handle, mainly:
** Login information.
** Status information.
{{note| '''Note''': When database is inactive, its information is stored in the <eiffel>DATABASE_APPL</eiffel> object. }}
The corresponding code looks like:
<code>
session_status: DB_STATUS
-- A session management object reference.
...
set_base is
...
update_handle
if session_status = Void then
create session_status.make
end
handle.set_status (session_status)
...
</code>
{{seealso| '''See Also''' <br/>
[[EiffelStore Interface Layer|The interface layer]] <br/>
}}

View File

@@ -0,0 +1,36 @@
[[Property:title|Data Modification]]
[[Property:weight|1]]
Use the [[ref:/libraries/store/reference/db_change_flatshort|DB_CHANGE]] class to perform any operation on your database that does not require access to a result. You can for instance modify table row content, drop table rows, create and delete tables.
{{note| '''Note''': Take a look at the [[Data Object Coupling|Data Storing]] capability if you want to '''insert''' table rows. }}
[[ref:/libraries/store/reference/db_change_flatshort|DB_CHANGE]] allows you to modify the database data using the SQL language:
* Prepare your SQL query and use modify:
<code>
modification: DB_CHANGE
-- Modification tool.
...
create modification.make
modification.modify("Update CONTACTS set Firstname = ' John'")
</code>
* Commit your changes with your session control:
<code>
session_control: DB_CONTROL
-- Session control.
...
session_control.commit
</code>
{{tip| '''Tip''': It is always better to check the database status for errors before committing changes. }}
{{seealso| '''See Also''' <br/>
[[Data Object Coupling|Data storing]] <br/>
[[Stored Procedures|Stored procedures]] <br/>
[[EiffelStore Implementation Layer|Implementation]] <br/>
}}

View File

@@ -0,0 +1,91 @@
[[Property:title|Data Object Coupling]]
[[Property:weight|4]]
A smart way to work with relational databases is to have Eiffel objects directly mapping relational tables. Three EiffelStore classes enable this coupling:
* [[ref:/libraries/store/reference/db_repository_flatshort|DB_REPOSITORY]] objects [[#describe|describe a relational table]] and allow Eiffel to create objects mapping database tables.
* [[ref:/libraries/store/reference/db_store_flatshort|DB_STORE]] works directly with [[ref:/libraries/store/reference/db_repository_flatshort|DB_REPOSITORY]] objects to [[#insert|insert data into relational tables]] .
* [[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] can [[#map|map a database query result into Eiffel objects]] .
==Describing relational tables with DB_REPOSITORY==
A [[ref:/libraries/store/reference/db_repository_flatshort|DB_REPOSITORY]] object stores available information about a table. To access this information, you mainly have to give the table name and load the table description:
<code>
repository: DB_REPOSITORY
...
create repository.make ("CONTACTS")
repository.load
if repository.exists then
...
end
</code>
{{tip| '''Tip''': Loading a table description is often a costly operation: table has to be fetched among existing tables then every table column description must be loaded. Hence it is better to store and reuse a repository (maybe with a HASH_TABLE) once it has been loaded. }}
Using the table information, [[ref:/libraries/store/reference/db_repository_flatshort|DB_REPOSITORY]] then helps generating Eiffel classes mapping relational tables:
* You can directly use {[[ref:/libraries/store/reference/db_repository_flatshort|DB_REPOSITORY]] }.generate_class. Generated class may look like:
<code>
class CONTACTS
feature -- Access
id: INTEGER
...
feature -- Settings
set_id (an_id: INTEGER) is
-- Set an_id to id.
do
id := an_id
end
...
</code>
{{note| '''Note''': The EiffelStore Wizard uses the generation.generator cluster to generate the classes mapped to your database. }}
==Inserting data in the database==
[[ref:/libraries/store/reference/db_store_flatshort|DB_STORE]] lets you easily insert rows into a table using:
* the table description provided by [[ref:/libraries/store/reference/db_repository_flatshort|DB_REPOSITORY]] .
* a class mapping the relational table.
This is straight-forward since you only have to give [[ref:/libraries/store/reference/db_store_flatshort|DB_STORE]] the object filled with the table values. Suppose you want to add a contact into your database:
<code>
storage: DB_STORE
contacts_rep: DB_REPOSITORY
a_contact: CONTACTS
...
create storage.make
-- contacts_rep is loaded and exists.
storage.set_repository (contacts_rep)
-- a_contact carries values to insert into the database.
storage.put (a_contact)
</code>
==Accessing database content with Eiffel objects==
[[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] lets you map data retrieved from the database into Eiffel objects: Result column names must match object attributes names so you can use for instance classes created by [[ref:/libraries/store/reference/db_repository_flatshort|DB_REPOSITORY]] . Class <eiffel>DB_ACTION</eiffel> redefines ACTION and can be used to retrieve Eiffel objects directly into an ARRAYED_LIST:
<code>
selection: DB_SELECTION
list_filling: DB_ACTION [CONTACTS]
contact: CONTACTS
...
selection.object_convert (contact)
create list_filling.make (selection, contact)
selection.set_action (list_filling)
...
selection.load_result
if selection.is_ok then
Result := list_filling.list
end
</code>
{{note| '''Note''': You can see how actions are used in [[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] . }}
<br/>
{{seealso| '''See Also''' <br/>
[[Database Selection|Performing a database selection.]] <br/>
[[Data structures use|Database-specific structures use.]] <br/>
}}

View File

@@ -0,0 +1,38 @@
[[Property:title|Database Connection]]
[[Property:weight|0]]
# To connect to your database, you have to create a '''handle''': this handle actually links the interface classes with corresponding implementation classes mapped to your DBMS. This handle is implemented by the DATABASE_APPL class:
<code>
database_appl: DATABASE_APPL [ODBC]
-- Database handle.
...
create database_appl.login (a_name, a_psswd)
database_appl.set_base
</code>
<br/>
{{note| '''Note''': Calling set_base links the EiffelStore interface to this specific handle. }}
{{tip| '''Tip''': You can manage handles to many databases: as an instance of <eiffel>DATABASE_APPL</eiffel> stands for a specific database handle, you only have to create one instance of <eiffel>DATABASE_APPL</eiffel> for every DBMS handle you wish to create. Do not forget to call set_base to activate appropriate handle. }}
{{note| '''Note''': The generic parameter of <eiffel>DATABASE_APPL</eiffel> specifies the actual DBMS used. }}
# Once your handle is created, you have to create a session manager which will allow you to manage your database, specifically to establish connection, disconnect and also handle errors. The class <eiffel>DB_CONTROL</eiffel> enables your application to plainly control the functioning and status of your database and to request any information about it.
<code>
session_control: DB_CONTROL
-- Session control.
...
create session_control.make
session_control.connect
</code>
{{note| '''Note''': Take a look at the [[Database control|database control]] part to see how to use <eiffel>DB_CONTROL</eiffel> capabilities. }}
{{seealso| '''See Also''' <br/>
[[Database control|Database control and error handling]] <br/>
[[EiffelStore Implementation Layer|Implementation]] <br/>
}}

View File

@@ -0,0 +1,68 @@
[[Property:title|Database control]]
[[Property:weight|7]]
Use the [[ref:/libraries/store/reference/db_control_flatshort|DB_CONTROL]] class to check or change database status and behavior. The main operations you are likely to use are:
* [[#errors|Handling]] database errors.
* [[#connection|Connecting]] to the database.
* [[#commit|Committing]] changes in the database.
==Handling database errors==
Every EiffelStore interface class has an is_ok feature. This enables to check directly if the last database operation has been successful.
When an error is detected, you can access through [[ref:/libraries/store/reference/db_control_flatshort|DB_CONTROL]] further information about the error:
* error_message provides a description of the error that occurred.
* error_code returns a code corresponding to the error type. This code enables to handle specific errors within your code without parsing the error_message.
* warning_message provides a warning message about the last transaction performed.
Once you have handled your error, for instance by displaying the error_message on screen, you can call reset to perform new database transactions.
==Managing database connection==
[[ref:/libraries/store/reference/db_control_flatshort|DB_CONTROL]] lets you connect, check connection and disconnect from the database.
The following example sum up these capabilities:
<code>
session_control: DB_CONTROL
...
session_control.connect
if session_control.is_connected then
-- Perform your transactions here.
session_control.disconnect
end
</code>
==Committing changes in the database==
Every modification you do in the database are usually not directly saved. This enables to limit damage caused by mishandlings. You can then manage database modification through 2 commands:
* ''Commit'' saves the changes in the database.
* ''Rollback'' restores the database content corresponding to last commitment.
The following example illustrates the use of these commands:
<code>
session_control: DB_CONTROL
...
from
until
transaction_completed or else not session_control.is_ok
loop
-- Perform your transaction here.
end
if session_control.is_ok then
session_control.commit
else
session_control.rollback
end
</code>
The loop performs a multi-step transaction. If transaction is not carried out entirely, the database could stay in an invalid state: this code ensures that database remains in a valid state.
{{warning| '''Caution''': Some databases can be in an auto-commit mode. Furthermore, some special database commands can automatically commit database changes. }}
{{seealso| '''See Also''' <br/>
[[Database Connection|Database connection]] <br/>
[[EiffelStore Implementation Layer|Implementation]] <br/>
}}

View File

@@ -0,0 +1,29 @@
[[Property:title|Database Selection]]
[[Property:weight|2]]
Use the [[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] class to select data from the database. Once you have selected the data, you can [[Selection Access|access]] it with convenience using adaptative EiffelStore structures.
{{note| '''Note''': Take a look at the [[Data Object Coupling|Database/Eiffel objects Coupling]] if you need information about your database structure. }}
[[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] enables your application to get database content using SQL 'select' queries:
* You can carry out 'select' queries in an intuitive way using directly the SQL language:
<code>
selection: DB_SELECTION
...
create selection.make
selection.set_query ("select * from CONTACTS where firstname = 'John'")
selection.execute
</code>
{{tip| '''Tip''': Always check the database status for errors after your 'select' query. }}
* You can also customize your selection using [[Query variables|bind variables]] .
{{seealso| '''See Also''' <br/>
[[Query variables|Binding variables in a database query.]] <br/>
[[Data Object Coupling|Coupling database objects with Eiffel objects.]] <br/>
[[Selection Access|Accessing selected data from the database.]] <br/>
}}

View File

@@ -0,0 +1,22 @@
[[Property:title|EiffelStore Interface Layer]]
[[Property:weight|0]]
The Interface layer gathers a set of classes covering all the capabilities an application need to interface efficiently with a DBMS.
The interface affords these main capabilities:
* [[Database Connection|Connecting]] to the database.
* [[Data Modification|Modifying]] database objects.
* [[Database Selection|Selecting]] data from the database.
* [[Selection Access|Accessing]] data selected from the database.
* [[Data Object Coupling|Coupling]] database objects with Eiffel objects.
* [[Query variables|Binding variables]] in a database query.
* Using [[Stored Procedures|stored procedures]] .
* Dealing with database [[Database control|status and behavior]] .
{{note| '''Note''': In general, each of these capabilities corresponds to one EiffelStore class. }}
{{seealso| '''See Also''' <br/>
[[EiffelStore Implementation Layer|The implementation layer]] }}

View File

@@ -0,0 +1,49 @@
[[Property:title|Query variables]]
[[Property:weight|5]]
If you have to execute database queries which only differ in the expression values, you can create a template query and then bind variables into this template for each execution.
This mechanism can be applied for requests with a result ([[ref:/libraries/store/reference/db_selection_chart|DB_SELECTION]] ) or without ([[ref:/libraries/store/reference/db_change_chart|DB_CHANGE]] ). Hence both classes inherits from STRING_HDL that actually handle variable binding.
To use variable binding:
* [[#create|Create]] a template query.
* [[#bind|Bind]] variables to the query.
==Creating a template query==
Template queries are parsed to replace each variable by its bound value. To create a template query, you have hence to put directly variables where the values would take place.
Variables syntax is simple: the ':' special character followed by the variable name.
<code>
selection: DB_SELECTION
Bind_var: STRING is "firstname"
...
create selection.make
selection.set_query ("Select * from CONTACTS where Firstname = ':" + Bind_var + "'")
</code>
{{note| '''Note''': The code example shows how to bind variables to a [[ref:/libraries/store/reference/db_selection_chart|DB_SELECTION]] object but the mechanism is exactly the same for [[ref:/libraries/store/reference/db_change_chart|DB_CHANGE]] objects. }}
==Binding variables to a query==
Once you have created your query, you can map variable names to values and execute the query:
<code>
selection: DB_SELECTION
Bind_var: STRING is "firstname"
...
loop
io.read_line
selection.set_map_name (io.laststring, Bind_var)
selection.execute_query
...
selection.unset_map_name (Bind_var)
end
</code>
{{seealso| '''See Also''' <br/>
[[Database Selection|Performing a database selection.]] <br/>
[[Data Modification|Modifying database content.]] <br/>
}}

View File

@@ -0,0 +1,103 @@
[[Property:title|Selection Access]]
[[Property:weight|3]]
Once you have [[Database Selection|selected data]] from the database, it returns a set of rows containing queried columns values. Each row loaded with DB_SELECTION is stored in a DB_RESULT object. The easiest way to access the data is thus to refer to DB_RESULT objects themselves.
{{note| '''Note''': Take a look at the [[Data Object Coupling|Database/Eiffel objects Coupling]] to learn advanced data handling features. }}
To use DB_RESULT, process in 2 steps:
* [[#retrieve|retrieve]] DB_RESULT objects.
* [[#access|access]] DB_RESULT content.
==Retrieving DB_RESULT objects==
[[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] class provides different ways to customize result loading:
* You want to access an '''unique''' row: [[ref:/libraries/store/reference/db_result_flatshort|DB_RESULT]] object is accessible via cursor:
<code>
selection: DB_SELECTION
my_result: DB_RESULT
...
selection.query ("...")
if selection.is_ok then
selection.load_result
my_result := selection.cursor
end
</code>
* You want to load a '''complete list''' of rows: [[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] can store [[ref:/libraries/store/reference/db_result_flatshort|DB_RESULT]] objects in a list. To do this, you have mainly to provide a LIST object to DB_SELECTION with set_container:
<code>
selection: DB_SELECTION
container: ARRAYED_LIST [DB_RESULT]
create container.make (Max_results)
...
selection.set_container (container)
...
from
container.start
until
container.after
loop
...
end
</code>
{{tip| '''Tip''': Provide [[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] with the LIST structure convenient for what you need to do with the results. }}
* You want to '''select part''' of the result set: you can set an action in [[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] that will be executed each time a row is loaded. This action can for instance manipulate current row and define a stop condition.
** You need to define a descendant of class ACTION and set it to [[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] :
<code>
class
MY_ACTION
inherit
ACTION
redefine
execute, found
end
...
execute is
do
i := i + 1
end
...
found: BOOLEAN is
do
Result := i >= Max_result
end
</code>
** Then set action to [[ref:/libraries/store/reference/db_selection_flatshort|DB_SELECTION]] :
<code>
selection: DB_SELECTION
action: MY_ACTION
...
selection.set_action (action)
selection.query ("...")
if selection.is_ok then
selection.load_result
end
</code>
==Accessing content of DB_RESULT==
A DB_RESULT object merely carries data retrieved from the database. You have to convert it to a DB_TUPLE to access data within the retrieved row conveniently, i.e. mostly the column values:
<code>
selection: DB_SELECTION
tuple: DB_TUPLE
...
create tuple
tuple.copy (selection.cursor)
if tuple.count >= 2 and then tuple.column_name (2).is_equal ("Firstname") then
io.putstring (tuple.item (2).out)
end
</code>
{{seealso| '''See Also''' <br/>
[[Database Selection|Performing a database selection.]] <br/>
[[Data Object Coupling|Coupling database data and Eiffel objects.]] <br/>
}}

View File

@@ -0,0 +1,71 @@
[[Property:title|Stored Procedures]]
[[Property:weight|6]]
When sending requests to the database, the request is first parsed then executed. Instead of parsing many times the same requests, i.e. with only changes in expression values, most of RDBMS enable to '''precompile''' requests. These requests can then be executed as routines and are identified by a name and a signature.
EiffelStore lets you use stored procedures with [[ref:/libraries/store/reference/db_proc_flatshort|DB_PROC]] class to:
* [[#execute|Execute]] a stored procedure.
* [[#create|Create]] a stored procedure.
==Executing a stored procedure==
To execute a stored procedure:
* Create a [[ref:/libraries/store/reference/db_proc_flatshort|DB_PROC]] object and load the stored procedure you want to use:
<code>
procedure: DB_PROC
...
create procedure.make ("UPDATE")
procedure.load
if procedure.exists then
...
end
</code>
* Execute the procedure through a [[ref:/libraries/store/reference/db_selection_chart|DB_SELECTION]] (if a result is expected) or a [[ref:/libraries/store/reference/db_change_chart|DB_CHANGE ]] object (otherwise).
{{note| '''Note''': Requests with a result ([[ref:/libraries/store/reference/db_selection_chart|DB_SELECTION]] ) or without ([[ref:/libraries/store/reference/db_change_chart|DB_CHANGE]] ) are both abstract '''expressions'''. DB_PROC executes an abstract expression using an object of [[ref:/libraries/store/reference/db_expression_chart|DB_EXPRESSION]] type, which corresponds to an abstract expression. [[ref:/libraries/store/reference/db_selection_chart|DB_SELECTION]] and [[ref:/libraries/store/reference/db_change_chart|DB_CHANGE]] inherits from [[ref:/libraries/store/reference/db_expression_chart|DB_EXPRESSION]] . }}
You can execute your request mostly like a basic one:
** Create your request.
** Bind request variables. Variables are stored procedure arguments.
{{note| '''Note''': Take a look at how to [[Query variables|bind variables]] to a query. }}
** Execute the query through the DB_PROC object.
<code>
procedure: DB_PROC
expr: DB_CHANGE
...
procedure.execute (expr)
expr.clear_all
</code>
** Check for errors and load result if any.
==Creating a stored procedure==
DB_PROC also enables you to create or drop stored procedures:
* Use store to create a procedure.
* Use drop to delete one.
The following example shows how to overwrite a procedure in the database:
<code>
procedure: DB_PROC
...
create procedure.make ("NEW_PROCEDURE")
procedure.load
if procedure.exists then
procedure.drop
end
procedure.load
if not procedure.exists then
procedure.set_arguments (<<"one_arg">>, <<"">>)
procedure.store ("update contacts set firstname = one_arg where contactid = 1")
end
</code>
{{seealso| '''See Also''' <br/>
[[Database Selection|Performing a database selection.]] <br/>
[[Data Object Coupling|Coupling database data and Eiffel objects.]] <br/>
}}

View File

@@ -0,0 +1,14 @@
[[Property:title|EiffelStore Content]]
[[Property:link_title|EiffelStore Tutorial]]
[[Property:weight|1]]
EiffelStore main classes are grouped into 2 main layers:
* The [[EiffelStore Interface Layer|interface layer]] provides a high-level, unique interface for every DBMS.
* The [[EiffelStore Implementation Layer|implementation layer]] customizes high-level routines to various DBMS handles.
Other cluster can facilitate your database management:
* The [[EiffelStore Generation Cluster|generation cluster]] , with the EiffelStore wizard, generates a facilitated and dynamic interface with your database.
* The [[EiffelStore DataView Cluster|dataview cluster]] lets you create a customized database GUI.

View File

@@ -0,0 +1,17 @@
[[Property:title|EiffelStore Library]]
[[Property:link_title|EiffelStore]]
[[Property:weight|1]]
Type: Library <br/>
Platform: Any <br/>
See:
* [[EiffelStore Introduction|Introduction]]
* [[EiffelStore Content|Content]]
* [[EiffelStore Samples|Samples]]
* [[ref:libraries/store/reference/index|Reference]]

View File

@@ -0,0 +1,114 @@
[[Property:title|Absolute time]]
[[Property:weight|0]]
The classes dealing with date and those dealing with time have almost the same construction. At the top of the hierarchy are the constants and the notion of value ([[ref:libraries/time/reference/time_value_chart|TIME_VALUE]] , [[ref:libraries/time/reference/date_value_chart|DATE_VALUE]] , [[ref:libraries/time/reference/date_time_value_chart|DATE_TIME_VALUE]] ). From this notion come two kinds of heirs which are the absolute notion of time (classes [[ref:libraries/time/reference/date_chart|DATE]] , [[ref:libraries/time/reference/time_chart|TIME]] and [[ref:libraries/time/reference/date_time_chart|DATE_TIME]] ) and the notion of duration (classes [[ref:libraries/time/reference/date_duration_chart|DATE_DURATION]] , [[ref:libraries/time/reference/time_duration_chart|TIME_DURATION]] , [[ref:libraries/time/reference/date_time_duration_chart|DATE_TIME_DURATION]] ).
[[ref:libraries/time/reference/date_chart|DATE]] , [[ref:libraries/time/reference/time_chart|TIME]] and [[ref:libraries/time/reference/date_time_chart|DATE_TIME]] inherit from the deferred class <eiffel>ABSOLUTE</eiffel>. It implies that instances of these classes are used as absolutes. We can imagine an oriented axis on which are reported values. <eiffel>ABSOLUTE </eiffel>inherits <eiffel>COMPARABLE</eiffel>, there is a complete order inside the class and its heir. <eiffel>ABSOLUTE</eiffel> is a client of <eiffel>DURATION</eiffel>, so that each instance of <eiffel>ABSOLUTE </eiffel>is linked with the duration between the origin and itself.
The default way to compare absolute objects is to compare their respective duration to each other.
==TIME==
[[ref:libraries/time/reference/time_chart|TIME]] deals with hour, minute and second. Is is possible to use more precision for time (there is no limit inside the class). See More precision in <eiffel>TIME</eiffel> for documentation. This section deals only with second.
====Creation====
There are three ways to create an instance of the class <eiffel>TIME</eiffel>: by choosing the time (make), by getting the time from the system (make_now), or by choosing the number of seconds elapsed from the origin (make_by_seconds). The arguments of make and make_by_seconds have to respect the range of a day (see preconditions).
====Origin and cyclic representation====
The origin is 0 hour 0 minute and 0 second. Notion of time is relative to a day in a cyclic representation: days begin at 0:0:0 and end at 23:59:59. If a second is added to 23:59:59 then the result will be 0:0:0. Subtracting a minute to 0:0:0 will yield 23:59:0.
====Comparison====
Instances of [[ref:libraries/time/reference/time_chart|TIME ]] may be compared. Functions <, + > and >= are available. Function is_equal must be use to test equality. = will compare references.
====Measurement====
The duration linked to an instance of [[ref:libraries/time/reference/time_chart|TIME]] (attribute duration) is an instance of [[ref:libraries/time/reference/time_duration_chart|TIME_DURATION]] . It is the duration from the origin until the current time. The function seconds returns the number of seconds since the origin. This function may be useful to get the number of seconds between two events.The feature - creates an interval between two instances of <eiffel>TIME</eiffel>. The duration of this interval is given by the function duration. However, this duration is not canonical (See [[Duration|Duration]] for precisions). In <eiffel>TIME</eiffel>, the feature relative_duration returns the same duration, but more efficiently and also it is canonical.
====Operations====
* Set directly hour, minute and second with set_hour, set_minute and set_second. Arguments must satisfy the rules of creation.
* Adding hours, minutes and seconds with features hour_add, minute_add and second_add. Features add and + take an instance of TIME_DURATION as an Page 3 argument and add it to the current time.
* Moving to the next or the previous hour, minute or second with features hour_forth, hour_back, minute_forth, minute_back, second_forth and second_back. It is faster to use these features rather than those above (hour_back <-> hour_add (-1)).
==DATE==
<eiffel>DATE</eiffel> deals with year, month and day. It is more complicated since there is no regular period in dates: each month contains its own total of days and there are leap years. That is why some peculiarities appear while manipulating objects of this class. There is no limit for a date (inside the class). The only limit comes from INTEGER representation. If INTEGER size is 32 bits (most common case), and as long as the basic unit is a day, the range for a date is from (- 2^31) to 2^31 (days), i.e. 5.8 million years from the origin.
====Creation====
There are also three ways to create an instance of the class <eiffel>DATE</eiffel>: by choosing the date (make, make_month_day_year, make_day_month_year), by getting the date from the system (make_now), or by choosing the number of days elapsed from the origin (make_by_days). The arguments of each creation procedure have to respect the common range (See preconditions).
====Origin====
The origin is 01/01/1600.
====Comparison====
Instances of <eiffel>DATE</eiffel> may be compared. Functions <, + > and >= are available. Function is_equal must be use to test equality, = will compare references.
====Measurement====
Each instance of <eiffel>DATE</eiffel> has a function (duration) which returns the duration since the origin until the current date (it is an instance of DATE_DURATION). This duration is definite, i.e. it contains only days (See below). However, it may be useful to deal directly with days (no need of DATE_DURATION). In this case, the function days of <eiffel>DATE</eiffel> yields the number of days since origin.
====Status Report====
Much information may be gotten from functions written in this part. Most of them are used within the class, but they are exported at the same time.
====Operations====
<eiffel>DATE</eiffel> operations looks like <eiffel>TIME</eiffel> operations:
* Setting directly year, month and day with set_year, set_month and set_day. Arguments must satisfy the rules of creation. These rules are more complicated than those of <eiffel>TIME</eiffel>. For example it is not allowed to set day to 31 if the current month is April, whereas it is allowed if the month is January. It is the same rules as for make. The same thing for years: It is not allowed to set year to a non-leap year if the current date is February 29th of a leap year. However, two features are available to set month and year even if day is too large: set_month_cut_days and set_year_cut_days will cut day down to the largest value allowed.
* Adding years, months and days with features year_add, month_add and day_add. There is no requirement to add a year or a month. However, these features have to return a correct result, i.e. day is checked before each addition-. Adding one month to August 31st will yield September 30th. 31 is cut to 30 since there are only 30 days in September. Features add and + take an instance of DATE_DURATION in argument and add it to the current date. It is written so that years and months are added first, the days last.(see DATE_DURATION below)
* Moving to the next or the previous year, month or day with features year_forth, year_back, month_forth, month_back, day_forth and day_back. It is the same but faster to use these features rather than those upper (year_back <-> year_add (-1)).
* Features relative_duration and definite_duration return the duration between the current date and the argument. The first one returns a result which is canonical (See definitions below), while the second one returns a definite result but may be not canonical.
For example, date1 is April 20th and date2 is May 28th. Both features will yield instances of DURATION; however, relative_duration will yield 1 month and 8 days whereas definite_duration will yield 38 days.
==DATE_TIME==
The aim is to gather the time with the date. <eiffel>DATE_TIME</eiffel> is client of <eiffel>TIME</eiffel> and <eiffel>DATE</eiffel> (see inheritance relation). Some features from <eiffel>DATE</eiffel> and <eiffel>TIME</eiffel> are re-written since they are useful within the class. Many other features may be called indirectly with the correct attribute (time or date).
====Creation====
There are still several ways to create an instance:
* by choosing value for all the attributes of the date and the time (make).
* by getting the time from the system (make_now).
* by gathering an instance of <eiffel>DATE</eiffel> with an instance of <eiffel>TIME</eiffel> (make_by_date_time).This feature copies only the references of its arguments, so that if the time (or the date) is changed, the instance previously initialized will be also changed. If this effect has to be avoided, cloning the arguments is required.
* by encapsulating an instance of <eiffel>DATE</eiffel> (make_by_date). The attribute time is set to the origin, i.e. 0:0:0.
The attribute date is set with the same reference as the argument (See comment of the previous section).
====Access====
To make it easier calls to features of <eiffel>TIME</eiffel> and <eiffel>DATE</eiffel>, the most useful access features are written as features in <eiffel>DATE_TIME</eiffel> (days, seconds and their associated duration date_duration and time_duration).
====Comparison====
Instances of <eiffel>DATE_TIME</eiffel> are totally ordered (the class inherit from <eiffel>ABSOLUTE</eiffel>). Functions <, + > and >= are available. Function is_equal must be used to test equality, = will compare references.
====Measurement====
Function duration gathers functions duration from the attributes time and date. The result is an instance of <eiffel>DATE_TIME_DURATION</eiffel>.
====Element change====
It is possible to change reference of time and date with the features set_time and set_date. To change only one element (for example hour), features from <eiffel>TIME</eiffel> or <eiffel>DATE</eiffel> have to be used.
====Operations====
Addition of hours, minutes and seconds are available directly in the class.The reason is that adding one second may have a consequence on the date. Using second_add from <eiffel>TIME</eiffel> is also possible but the date will not be modified in the case time makes a cycle. It is of course the same for minute and hour. day_add is also available directly since it is frequently used within the class.
Features + and add take an instance of <eiffel>DATE_TIME_DURATION</eiffel> in arguments. The date duration is added first then the time duration. Adding the time duration first would have yield some different result as in this example: the current date is August 30th 23:59:59. The duration to add is one month and one second. Feature add returns October 1st 0:0:0, whereas adding the second first would return September 30th 0:0:0! The same difference occurs with leap years.
Feature relative_duration and definite_duration returns the duration between the current date (with time) and the argument. The first one returns a result which is canonical (see definitions below), while the second one returns a result definite but may be not canonical. It is the same notion than in <eiffel>DATE</eiffel>.
==DATE and DATE_TIME==
Another way to process would have been to make <eiffel>DATE_TIME</eiffel> inherit from <eiffel>DATE</eiffel>,as long as <eiffel>DATE_TIME</eiffel> is a <eiffel>DATE</eiffel>, with more precision. The choice was to have a client relation between them. Otherwise <eiffel>DATE</eiffel> should have known the existence of <eiffel>DATE_TIME</eiffel>, and many assignment attempts would have been useful in features such as infix +. So <eiffel>DATE_TIME</eiffel> is client of <eiffel>DATE</eiffel>.
However, it could be useful to mix instances of <eiffel>DATE</eiffel> of <eiffel>DATE_TIME</eiffel>. As <eiffel>DATE_TIME</eiffel> is client of <eiffel>DATE</eiffel> with its attribute date, it is easy to get only the date from instances of <eiffel>DATE_TIME</eiffel>. On the other way features are available to convert objects from <eiffel>DATE</eiffel> to <eiffel>DATE_TIME</eiffel>. In class <eiffel>DATE</eiffel>, feature to_date_time builds an instance of <eiffel>DATE_TIME</eiffel> with the origin of time (0,0,0). In the class DATE_TIME, the creation procedure make_by_date has the same effect. (The same feature exists for duration, replacing origin by zero).

View File

@@ -0,0 +1,94 @@
[[Property:title|DATE / TIME to STRING Conversion]]
[[Property:weight|3]]
The following table lists format conversion codes.
{|
|-
| '''Code'''
| '''Description'''
|-
| dd
| day - numeric
|-
| [0]dd
| day - numeric (padded with '0' to 2 figures)
|-
| ddd
| day - text (3 letters e.g "Mon", "Tue")
|-
| yyyy
| year - numeric (4 figures)
|-
| yy
| year - numeric (2 figures)
|-
| mm
| month - numeric
|-
| [0]mm
| month - numeric (padded with '0' to 2 figures)
|-
| mmm
| month - text (3 letters e.g "Dec", "Jan")
|-
| hh
| hour - numeric (24 hour clock scale by default)
|-
| [0]hh
| hour - numeric (padded with '0' to 2 figures)
|-
| hh12
| hour - numeric (12 hour clock scale)
|-
| mi
| minute - numeric
|-
| [0]mi
| minute - numeric (padded with '0' to 2 figures)
|-
| ss
| seconds - numeric
|-
| [0]ss
| seconds - numeric (padded with '0' to 2 figures)
|-
| ff<n>
| fractional seconds - numeric (precise to <n> figures)
|-
| ':', '/', '-' and ','
| separators e.g. "03/Aug/97"
|}
These are some examples of output with their associated format code:
{|
|-
| '''Code'''
| '''Output'''
|-
| yy/m/dd
| 97/8/18
|-
| mmm-dd-yy
| Aug-18-97
|-
| dd,mm,yyyy
| 18,Aug,1997
|-
| hh-mi-ss
| 13-06-32
|-
| hh12,mi,ss
| 1,06,32 pm
|-
| hh12:mi:ff
| 1:06:32.25 pm
|-
| hh:mi:ff3
| 13:06:32.248
|-
| [0]mm/dd/yy hh12:mi:ff3
| 08/18/97 1:06:32.248 pm
|}

View File

@@ -0,0 +1,126 @@
[[Property:title|Duration]]
[[Property:weight|1]]
<eiffel>TIME_DURATION</eiffel>, <eiffel>DATE_DURATION</eiffel> AND <eiffel>DATE_TIME_DURATION</eiffel>
The classes dealing with duration inherit DURATION, which inherits GROUP_ELEMENT and PART_COMPARABLE. An instance of <eiffel>TIME_DURATION</eiffel>, <eiffel>DATE_DURATION</eiffel> or <eiffel>DATE_TIME_DURATION</eiffel> is an element of a group, i.e. there is a zero and addition operations (infix +,infix -, prefix + and prefix -). Duration is used as an amount of time, without link to an origin. It may be added to the respective absolute notion (time + time_duration is possible, not time + date_time_duration nor date_time + time_duration...see classes <eiffel>TIME</eiffel>, <eiffel>DATE</eiffel> and <eiffel>DATE_TIME</eiffel>).
Attributes are allowed to take negative values or values which do not stand in the usual range (hour = -1, minute = 75, day = 40...). However, features are available in each class to convert instances into the usual format: functions canonical and to_canonical are present in each class. An instance is canonical (canonical = True) if its attributes stand into the usual range. For example, an instance of <eiffel>TIME_DURATION</eiffel> such as 12:-10:60 is not canonical. to_canonical will return 11:51:0. In <eiffel>DATE_DURATION</eiffel> and <eiffel>DATE_TIME_DURATION</eiffel>, these features are also present.
The order is partially implemented. <eiffel>TIME_DURATION</eiffel> has a complete order whereas <eiffel>DATE_DURATION</eiffel> and <eiffel>DATE_TIME_DURATION</eiffel> are more specific.
==TIME_DURATION==
====Creation====
Two ways are possible: by choosing the value of each attributes hour, minute and second (feature make), or by giving an amount of seconds (make_by_seconds). Any integer value is accepted. It is possible to create a duration with 1 hour and -60 minutes.
====Access====
Zero is a once feature with 0 hour, 0 minute and 0 second. The total amount of second of the current duration is the result of feature seconds_count.
====Comparison====
Instances of <eiffel>TIME_DURATION</eiffel> may be compared easily. The order is the order oft he respective total amount of second. 1:-40:0 is less than 0:0:1800, etc... Functions <, >,<= and >= are available. Is_equal tests equality, = will compare references.
====Element change====
Set directly hour, minute and second with set_hour, set_minute and set_second. Arguments do not need to satisfy any range rule.
====Operations====
* Adding hours, minutes and seconds with features hour_add, minute_add and second_add.
* <eiffel>TIME_DURATION</eiffel> inherits from GROUP_ELEMENT. infix and prefix +, infix and prefix - are available to compose instances of each other.
====Conversion====
Two features ensure a link with the notion of day: to_days returns the number of days equivalent to the current duration. For example, a duration such as 23:60:0 is equivalent to one day. For negative duration, the result is never 0. -1 hour is equivalent to -1 day (i.e. the result of the function is -1). To_days is associated with time_modulo_day. This second function returns an instance of <eiffel>TIME_DURATION</eiffel>. The result represents the difference between the current duration and the number of days yielded by to_days. It implies that the result is always positive and less than one day.
For example, the current duration is 25:70:600. to_days will returns 1 (one day) and time_modulo_day will return 2:20:0:. If the current duration is negative: -23:-80:300,to_days will return -2 (minus two days) and time_modulo_day will return 23:45:0.
Durations may be canonical or not canonical (BOOLEAN canonical). That means the features hour, minute and second are included in a particular range, or not. An instance of <eiffel>TIME_DURATION</eiffel> is canonical if:
* in the case of a positive duration (> zero), all of the three features have to be positive or 0, minute and second less than 60.
* in the case of a negative duration (< zero), all of the three features have to be negative or 0, minute and second strictly greater than -60. The function canonical tests if the duration is canonical or not, the function to_canonical yields a new duration equivalent to the current one and canonical.
==DATE_DURATION==
Dealing with the Gregorian calendar is not so easy because of irregularities. A duration of one month may be equal to 28 up to 31 days, depending on the current date! On the other hand, it could be useful to deal with precise duration. This point leads to an original design of the class: A separation is made between two kinds of instances.
The definite ones and the relative ones. The function definite which returns a BOOLEAN, is true for definite duration and false otherwise. An instance is definite if and only if its attributes month and year are 0. Then only the number of days is used. Relative (non definite) durations have their attributes year, month and day meaningful but it is then impossible to compare them to each other (is one month greater than 30 days?, is one year greater than 365 days?). The main difference appears when a duration is added to a date. In the case of a definite duration, there is no ambiguity. A given number of days are added to the date, taking care of the calendar. In the other case, the result is relative to the origin date. For example, a one month duration may be equal to 28 days if the date is in February or 31 days if the date is in August. A duration becomes definite when its attributes year and month become 0. However it is possible to deal with instances of <eiffel>DATE_DURATION</eiffel> without taking care of this distinction.
===Relative date_duration===
Relative duration cannot be compared with any other durations (including zero). The reason is simple. It is not possible to say if 30 days are less than 1 month: it depends on the date: it is true in August (in a 31 days month) and it is false in February.
If feature > (or <, + + is called with at least one non definite member (the current instance or the argument), the result will be always False. We may only know if two durations are equal, with the feature is_equal. It compares field by field the two durations. When adding a relative date_duration to a date, the years and the months are added first, then the date may be cut (June 31 -> June 30) and finally the days are added. For example, if one month is added to the date August 31st, the result is September 30th.
Nevertheless there is a way to compare relative durations: a relative date_duration may be canonical. It means that the duration has its attributes month and day in a fixed range.month must be between 1 and 12, and day larger than 1 and less than a value between 27 and 30. This value is fixed simply: (in the case of a positive duration) when setting day to 0 and adding one more month, the addition of the start date and this new duration must yield a date strictly after the final date (yielded by adding date and tested duration). For example is 0/0/30 (i.e. 0 year, 0 month and 30 days) canonical?
* If the origin date is 01/15 (15th of January), the final date is 02/14. We cannot convert 30 days into 1 month in this case. The duration is canonical.
* If the origin date is 04/15 (15th of April), the final date is 05/15. The duration is not canonical since it is possible to convert days into 1 month. The origin date is used to determine whether the duration is positive or not. If the final date is after the origin date the duration is positive, otherwise it is negative. That does not mean we can compare it to zero, that is only used to determine the sign of the canonical standard. If the duration is negative, it is canonical only if all the attributes are negative.
A way to compare two relative durations is to make them canonical from the same date, and then to compare the fields. It is the same as adding the durations to the same date, and to compare the final dates to each other.
===Definite date_duration===
Definite durations are characterized by the attribute day. Whenever a duration has its attributes year and month equal to 0, this duration is then definite. On the other hand, if one of these two attributes is not 0, the duration is not definite anymore.
The number of days between an origin date and the result of (date + duration) does not depend on the origin date. It is possible to compare definite date_duration to each other.The order is the one of day.
A definite duration may be canonical or not. It is canonical if the number of day is small enough.
===General description===
====Creation====
Two creation features are available: make takes three arguments (year, month and day). If year and month are null, the duration will be definite; make_by_days takes only the number of day. The duration is automatically definite.
====Comparison====
Features <, >, <= and >= are available. If both instances are definite, numbers of days are compared. If one of them is non definite, the result is False.
====Element change====
Features set_day, set_month and set_year are available to set one of these three attributes day, month, year.
====Operation====
* Add years, months and days with features year_add, month_add and day_add.
* <eiffel>DATE_DURATION</eiffel> inherits from GROUP_ELEMENT. infix and prefix +, infix and prefix - are available to compose instances of each other.
====Conversion====
* to_canonical is used to get a new duration equivalent to the current one and canonical. It needs an argument from class <eiffel>DATE</eiffel>, which is the origin of calculations.
* to_definite is used to get a new duration equivalent to the current one and definite. As with the previous feature, one argument is needed. - to_date_time is used to get an instance of <eiffel>DATE_TIME_DURATION</eiffel>. It will have the same date of the current duration and time set to zero.
==DATE_TIME_DURATION==
<eiffel>DATE_TIME_DURATION</eiffel> is client of <eiffel>DATE_DURATION</eiffel> and <eiffel>TIME_DURATION</eiffel>. Most of the common features described in <eiffel>DATE_DURATION</eiffel> are present in the class. The class deals with its attributes date and time in the same way as <eiffel>DATE_TIME</eiffel>.
There are, as in <eiffel>DATE_DURATION</eiffel>, definite and non definite durations. It is the date part which gives the definite non definite status. Features canonical and to_canonical are present in DATE_TIME_DURATION. They have to deal with the attributes time.
====Creation====
There are still several ways to create an instance:
* by choosing values for all the attributes of date and time (make). - by choosing a value for day and values for all the attributes of time. The instance is then definite (make_definite).
* by gathering an instance of <eiffel>DATE</eiffel> with an instance of <eiffel>TIME</eiffel> (make_by_date_time). This feature copies the references of its arguments, so that if the time (or the date) is changed, the instance previously initialized will be also changed. If this effect has to be avoided, the use of clones is required.
* by encapsulating an instance of <eiffel>DATE</eiffel> (make_by_date). The attribute time is set to zero, i.e. 0:0:0. The attribute date is set with the same reference than the argument.
====Access====
Seconds_count is the amount of seconds of the time part only. To get the total amount of seconds of the current duration, first shift it to a definite duration, then multiply day by the number of seconds in day and add to it seconds_count. Take care that the duration is not more than 68 years. If it is, the number of seconds will be larger than 2 billion, which is the upper limit for INTEGER (4 bytes).
====Comparison====
The rules are the same than those for <eiffel>DATE_DURATION</eiffel>. Features <, >,<= and >= are available. If both instances are definite, numbers of days are compared. If one of them is non definite, the result is False.
====Element change====
It is possible to change reference of time and date with the features set_time and set_date. To change only one element (for example hour), features from <eiffel>TIME_DURATION</eiffel> or <eiffel>DATE_DURATION</eiffel>have to be used.
====Operation====
* <eiffel>DATE_TIME_DURATION</eiffel> inherits from GROUP_ELEMENT. infix and prefix +, infix and prefix - are available to compose instances to each other.
* Only day_add is present. To add only one element, features from <eiffel>TIME_DURATION</eiffel> or <eiffel>DATE_DURATION</eiffel> have to be used.
====Conversion====
* canonical and to_canonical are available in the class. To be canonical an instance of the class must have its attributes time and date canonical. Then time must have the same sign than the one of the current duration. The sign of the current instance is determined by adding it to the argument (from <eiffel>DATE_TIME</eiffel>). That will yield a final date. If this final date is after the origin (= the argument), the current duration is considered positive. Otherwise, it is considered negative. Finally time must be less than one day (if positive) or more than minus one day (if negative). To_canonical returns a duration equivalent to the current one (for the argument) and canonical.
* time_to_canonical looks like to_canonical but focuses mainly on time. It requires a definite duration so that it is possible to compare it to zero. It yields a definite duration equivalent to the current one with a canonical time. hour is then cut so that it stands in the range of one day (0 to 23 if positive and -23 to 0 if negative). The attributes day is also modified to keep the result equivalent to the current duration.time_to_canonical does not need any argument because only time and day are modified.

View File

@@ -0,0 +1,43 @@
[[Property:title|Interval]]
[[Property:weight|2]]
Class <eiffel>INTERVAL</eiffel> deals with intervals between two instances of the same class which conform to<eiffel> ABSOLUTE</eiffel> ( <eiffel>DATE</eiffel>, <eiffel>TIME</eiffel>, <eiffel>DATE_TIME</eiffel>). The notions of interval is directly linked with the notion of order.
The <eiffel>start_bound</eiffel> must be before the <eiffel>end_bound</eiffel>.
====Creation====
The features <eiffel>make</eiffel>, <eiffel>set_start_bound</eiffel> and <eiffel>set_end_bound</eiffel> take clones of their arguments, so that if these arguments are changed, the interval previously created is not.
It would have been possible to create intervals with references to date or time, but a modification of the dates would have been effective in the interval so that only the invariant would have been able to check if the <eiffel>start_bound</eiffel> is still before the <eiffel>end_bound</eiffel>.
====Interval measurement====
The measure of intervals is made by duration: the result is an instance of the class <eiffel>DURATION</eiffel>. However, as <eiffel>DURATION</eiffel> is the common parent of <eiffel>TIME_DURATION</eiffel>, <eiffel>DATE_DURATION</eiffel> and <eiffel>DATE_TIME_DURATION</eiffel>, it does not have many features available. Some features in class <eiffel>TIME</eiffel>, <eiffel>DATE</eiffel>, <eiffel>DATE_TIME</eiffel> return the same result and are more efficient to use. <eiffel>DURATION</eiffel> has to be use as the last solution.
====Comparison====
It includes intersection, inclusion and a special comparison.
* <eiffel>is_equal</eiffel> is present and compare values, not references.
* Feature <eiffel>intersects</eiffel> returns the mathematical result of the intersection of two intervals.
* <eiffel>is_strict_included_by</eiffel>, <eiffel>strict_includes</eiffel>, <eiffel>is_included_by</eiffel> and <eiffel>includes</eiffel> are connected to the same notion of inclusion.
* <, + > and >= use a special rule to compare intervals. int1 < int2 is true if int1 starts and ends strictly before int2. The other features use the <eiffel>same rule</eiffel> and<eiffel> is_equal</eiffel> if needed.
* <eiffel>overlaps</eiffel> looks like <eiffel>intersects</eiffel> but the argument has to be after the current interval. <eiffel>is_overlapped</eiffel> is the opposite.
* <eiffel>meets</eiffel> and <eiffel>is_met</eiffel> are used to test if two intervals have a common bound.
====Status Report====
The main part of the functions need an argument from the same generic type and return a <eiffel>BOOLEAN</eiffel> value.
* <eiffel>empty</eiffel> tests if the bounds are equal.
* <eiffel>has</eiffel>,<eiffel> strict_before</eiffel>, <eiffel>strict_after</eiffel>,<eiffel> before</eiffel> and <eiffel>after</eiffel> test the position of an element relatively to the current interval.
====Element change====
<eiffel>set_start_bound</eiffel> and <eiffel>set_end_bound</eiffel> are available to change the bounds.
====Operations====
<eiffel>Union</eiffel> and <eiffel>intersection</eiffel> are the mathematical functions. <eiffel>gather</eiffel> requires that two intervals meet each other and then yields the union.

View File

@@ -0,0 +1,45 @@
[[Property:title|More precision]]
[[Property:weight|4]]
<eiffel>TIME</eiffel> and <eiffel>TIME_DURATION</eiffel> are designed to deal with high precision in time. The only limit is the one from number representation.
The classes <eiffel>TIME</eiffel> and <eiffel>TIME_DURATION</eiffel> have an attribute <eiffel>fine_second</eiffel> (inherited from <eiffel>TIME_VALUE</eiffel>) which allows high precision. This attribute represents the number of seconds with fractions (it is an instance of <eiffel>DOUBLE</eiffel>). From this attribute are calculated second and fractional_second (which are functions): second is the truncated-to-integer part and fractional_second is the difference between the two previous one, so that the sum of second and fractional_second is always equal to fine_second (see invariant in <eiffel>TIME_VALUE</eiffel>).
As a result of this, when <eiffel>fine_second</eiffel> is positive (3.55 for example), <eiffel>second</eiffel> and <eiffel>fractional_second</eiffel> are also positive (3 and 0.55). When <eiffel>fine_second</eiffel> is negative (- 3.55 for example), <eiffel>second</eiffel> and <eiffel>fractional_second</eiffel> are also negative (- 3 and - 0.55).
Manipulation on second and fractional_second are in fact always made through fine_second. Users who do not want to deal with precision do not need to care about this.
Features dealing with <eiffel>fine_second</eiffel> and <eiffel>fractional_second</eiffel> are described here.
====Creation (common to <eiffel>TIME, </eiffel> <eiffel>TIME_DURATION</eiffel>)====
* <eiffel>make_fine</eiffel> looks like make but it takes a <eiffel>DOUBLE </eiffel>for its third argument (instead of an <eiffel>INTEGER</eiffel>). fine_second is then set to this value.
* <eiffel>make_by_fine_seconds</eiffel> looks like <eiffel>make_by_seconds</eiffel> but it takes a <eiffel>DOUBLE</eiffel> for argument (instead of an <eiffel>INTEGER</eiffel>). Comparison (common) There are no new features. The same ones are available since they are written to deal with precision. It is possible to compare two instances, one with precision and the other one without.
====Measurement and access====
In <eiffel>TIME</eiffel>:
- <eiffel>fine_seconds</eiffel> looks like seconds but it contains fractions.
In <eiffel>TIME_DURATION</eiffel>:
- <eiffel>fine_seconds_count</eiffel> looks like <eiffel>seconds_count</eiffel> but it contains fractions.
====Element change====
* <eiffel>set_fine_second</eiffel> allows to set directly <eiffel>fine_second</eiffel> to a <eiffel>DOUBLE</eiffel>. In <eiffel>TIME</eiffel>, a precondition requires that the argument stands in the allowed range.
* <eiffel>set_fractionals</eiffel> allows to set directly <eiffel>fractional_second</eiffel> to a <eiffel>DOUBLE</eiffel>. In <eiffel>TIME </eiffel>a precondition requires that the argument is positive and smaller than one. In <eiffel>TIME_DURATION</eiffel> the precondition is particular: it is not allowed to have an argument with a different sign than second. Otherwise, as long as <eiffel>fractional_second</eiffel> and <eiffel>second</eiffel> are linked to <eiffel>fine_second</eiffel>, such a setting would mean that second is also changed and <eiffel>fractional_second</eiffel> set to a different value. For example if <eiffel>fine_second</eiffel> = 4.5 (then second = 4 and fractional_second = 0.5) and - 0.8 is the argument of <eiffel>set_fractionals</eiffel>.
The result of that would be<eiffel> fine_second</eiffel> = 3.2 (then <eiffel>second</eiffel> = 3 and <eiffel>fractional_second</eiffel> = 0.2). It is better to prohibit that.
Comment: feature <eiffel>set_second</eiffel> (from both <eiffel>TIME</eiffel> and <eiffel>TIME_DURATION</eiffel>) will cut down <eiffel>fractional_second</eiffel> to zero.
====Operations====
- <eiffel>fine_second_add</eiffel> looks like <eiffel>second_add</eiffel> but takes a <eiffel>DOUBLE</eiffel> for argument.
In <eiffel>TIME_DURATION</eiffel>:
- <eiffel>canonical</eiffel> and <eiffel>to_canonical</eiffel> deals already with precision. There is nothing different.

View File

@@ -0,0 +1,15 @@
[[Property:title|EiffelTime Library]]
[[Property:link_title|EiffelTime]]
[[Property:weight|9]]
Type: Library <br/>
Platform: Any <br/>
See:
* [[EiffelTime|Content]]
* [[ref:libraries/time/reference/index|Reference]]

View File

@@ -0,0 +1,26 @@
[[Property:title|Create an object]]
[[Property:weight|1]]
An EiffelBuild [[EiffelBuild Notation|object]] is a representation of a Vision2 component and its properties.
To create a new instance of an object, [[EiffelBuild Notation|pick]] a type from the [[Type selector|type selector]] and [[EiffelBuild Notation|drop]] onto an existing [[EiffelBuild Notation|object]] (Accessible from the [[Layout constructor|layout constructor]] or [[Builder window|builder window]] ). You will only be able to complete the [[EiffelBuild Notation|drop]] if the targeted [[EiffelBuild Notation|object]] will accept a new object of the transported type.
{{note| '''Note''': Once an [[EiffelBuild Notation|object]] has been [[Create an object|created]] , it will always be contained in a parent [[EiffelBuild Notation|object]] until [[Delete an object|deleted]] . }}
==Creating Window and Dialog Objects==
Window and dialog objects are created by picking a type from the [[Type selector|type selector]] and dropping into the [[Widget selector|widget selector]] . If the target of the drop is a directory within the widget selector, the new object is created within that directory, otherwise in the root of the project location. Window and dialog objects are generated as individual classes by EiffelBuild.
{{note|'''Note''' If there are no other windows or directories in the project, the newly created object is set as the root window.}}
==Creating objects for re-use==
If you wish to create an object that may be re-used in multiple locations within your EiffelBuild project, pick the type from the [[Type selector|type selector]] and drop into the [[Widget selector|widget selector]] . This ensures that at generation time, the object is generated as a seperate class (as with all objects in the [[Widget selector|widget selector]] ). Objects within the [[Widget selector|widget selector]] may be used in a client fashion within other object structures as required, and any changes made to these objects are reflected at all locations in which they are used.
{{seealso| '''See Also''' <br/>
[[Type selector|Type selector]] <br/>
[[Reparent an Object|Reparent an object]] <br/>
[[Delete an object|Delete an object]] }}

View File

@@ -0,0 +1,15 @@
[[Property:title|Delete an object]]
[[Property:weight|2]]
To remove an [[EiffelBuild Notation|object]] from your EiffelBuild system, [[EiffelBuild Notation|pick]] the object you wish to delete, and [[EiffelBuild Notation|drop]] it on [[Image:icon-delete-small-color]] in the [[Main toolbar|main toolbar]] .
You may also delete via the keyboard by pressing the delete key while the tool containing the objects representation has the focus. Whichever [[EiffelBuild Notation|object]] has the selection is deleted.
{{note| '''Note''': To restore a deleted object, you may use the [[History|History]] }}
{{seealso| '''See Also''' <br/>
[[History|History]] <br/>
[[Type selector|Type selector]] }}

View File

@@ -0,0 +1,23 @@
[[Property:title|EiffelBuild: Creating a new project]]
[[Property:weight|0]]
When a project is not open in Build, there are only two menu options available. 'File' and 'Help'. To create a new project, select 'file', 'New project' as illustrated below:
[[Image:new-project]]
This will bring up a directory dialog from which you can select the directory in which you wish to create the new Build project.
Selecting a directory that does not already contain a Build project will create a new project in that directory and the Build tools will become available for development of the newly created project. If a directory was selected that already contains a Build project, the following dialog will be displayed:
[[Image:overwrite-project]]
Selecting 'Ok' will create a new project, overwriting the existing project, and the Build tools will become available for development of the newly created project.
Selecting 'Cancel' will return you to the directory selection dialog, from which you can select the directory in which you wish to create the new Build project.
{{seealso| '''See Also''' <br/>
[[Retrieving a project from a Build project file|Retrieving a project from a Build project file]] <br/>
}}

View File

@@ -0,0 +1,8 @@
[[Property:title|EiffelBuild: Starting a project]]
[[Property:weight|0]]
* [[EiffelBuild: Creating a new project|Creating a new project]]
* [[Retrieving a project from a Build project file|Retrieving a project from a Build project file]]

View File

@@ -0,0 +1,20 @@
[[Property:title|Retrieving a project from a Build project file]]
[[Property:weight|1]]
When a project is not open in Build, there are only two menus available, 'File' and 'Help'. To retrieve an existing project, select 'file', 'Open Project
[[Image:open-project]]
A directory dialog will be displayed from which you can select the Build project file that you wish to retrieve. All build project files are named 'build_project.bpr' and are qualified by the directory in which they reside.
You may also open a recent EiffelBuild project via the 'Recent Projects' entry of the 'file' menu as shown below:
[[Image:recent-projects]]
This list contains the most recent projects that have been used within EiffelBuild, and if none are available, this list is empty and the menu option disabled.
{{seealso| '''See Also''' <br/>
[[EiffelBuild: Creating a new project|Creating a new project]] }}

View File

@@ -0,0 +1,21 @@
[[Property:title|Import a project]]
[[Property:weight|5]]
The contents of an existing project may be imported into the currently open project, permitting re-use of existing structures. All versions of EiffelBuild before 5.4 limited each project to a single titled window, with 5.4 removing this limitation. The ability to import multiple EiffelBuild projects into a single project is useful for maintaining larger systems with many windows.
To import the contents of an existing project, select 'Import Project' from the 'File' menu as illustrated below:
[[Image:import-project]]
Upon selection of the menu item, a file dialog is displayed prompting for the EiffelBuild project to be imported (".bpr" files) . Selecting a valid EiffelBuild project file causes the import to commence, during which, EiffelBuild is unresponsive. Please be patient, as importing a large EiffelBuild project may take a little while, depending on the speed of the system.
Upon completion of the import, there are two possible outcomes:
* No name clashes occurred: No names from the imported project clashes with those of the open project. In this case, notification of success is displayed in the status bar for a short period of time.
* One or more name clashes occurred: One or more objects or constants from the imported project had names that matched that of objects in the open project. As the names are used directly in the generated code, they must be unique within their scope (accessible within the code), and therefore EiffelBuild must resolve these clashes. A dialog is displayed on screen showing all the names that were resolved by EiffelBuild:
[[Image:import-project-clashes]]
{{note| '''Note''': If a name clash occurs, the names of the imported project are modified, not the open project. }}

View File

@@ -0,0 +1,12 @@
[[Property:title|EiffelBuild How To's]]
[[Property:weight|0]]
* [[EiffelBuild: Starting a project|Starting a project]]
* [[Create an object|Create an object]]
* [[Delete an object|Delete an object]]
* [[Save a project|Save a project]]
* [[Reparent an Object|Reparent an object]]
* [[Import a project|Import a Project]]

View File

@@ -0,0 +1,21 @@
[[Property:title|Reparent an Object]]
[[Property:weight|4]]
To reparent an [[EiffelBuild Notation|object]] , you need to [[EiffelBuild Notation|pick]] the [[EiffelBuild Notation|object]] and [[EiffelBuild Notation|drop]] it on the [[EiffelBuild Notation|object]] you wish it to be parented in. The [[EiffelBuild Notation|object]] will be removed from its current parent, and inserted in the new parent at the next available position.
When an [[EiffelBuild Notation|object]] is inserted into a parent, it is always added at the next available position. If you wish to place an [[EiffelBuild Notation|object]] at a particular position within a parent, you must hold down the '''Shift''' key, and drop on an [[EiffelBuild Notation|object]] already contained in parent, Your [[EiffelBuild Notation|object]] will then be inserted in the parent, in the position preceding the child [[EiffelBuild Notation|object]] that you dropped on.
You can access [[EiffelBuild Notation|objects]] from both the [[Builder window|builder window]] and [[Layout constructor|layout constructor]] .
{{note|'''Note''' Although window and dialog objects may be accessed within the [[Widget selector|widget selector]] , it is not possible to build into these objects, you should use the [[Layout constructor|layout constructor]] or [[Builder window|builder window]] directly in this situation. }}
For more information about an [[EiffelBuild Notation|objects]] capacity and permitted children, see the [[EiffelVision Introduction|EiffelVision2]] documentation.
{{seealso| '''See Also''' <br/>
[[Create an object|Create an object]] <br/>
[[Delete an object|Delete an object]] <br/>
[[Builder window|Builder window]] <br/>
[[Layout constructor|Layout constructor]] }}

View File

@@ -0,0 +1,14 @@
[[Property:title|Save a project]]
[[Property:weight|3]]
To save the project that is currently open, select '''Save''' from the '''File''' menu or click on [[Image:icon-save-color]] in the [[Main toolbar|main toolbar]] .
Alternatively, you may use the keyboard shortcut - '''Ctrl+S'''
{{note| '''Note''': If no changes have been made to the system, the save command will be disabled. }}
{{seealso| '''See Also''' <br/>
[[EiffelBuild: Key shortcuts|Key shortcuts]] }}

View File

@@ -0,0 +1,32 @@
[[Property:title|Builder window]]
[[Property:weight|7]]
The Builder window provides a view of the [[EiffelBuild Notation|objects]] in your system, in which the [[EiffelBuild Notation|objects]] may be manipulated.
This window may either be shown or hidden (default). To change between these two states, click [[Image:icon-builder-window-color]] on the [[Main toolbar| main toolbar]] , or select '''Show/Hide builder window''' from the '''View''' menu.
[[Image:builder-window]]
The content of this window is a representation of the [[EiffelBuild Notation|objects]] you have defined in your project. Each [[EiffelBuild Notation|object]] is represented by the [[EiffelVision Introduction|EiffelVision2]] control matching its type. For example, an [[EiffelBuild Notation|object]] representing an <eiffel>EV_BUTTON</eiffel> will be displayed in here using an <eiffel>EV_BUTTON</eiffel>. As this view provides direct access to the objects ( [[EiffelBuild Notation|Pick]] any of the controls in this window), it enables you to build your interface within a view which provides rich visual feedback.
Because this window is just a view of the [[EiffelBuild Notation|objects]] , it will be always synchronized with the [[Layout constructor| layout constructor]] . This means you can [[Reparent an Object| re-parent objects]] , using the [[EiffelBuild Notation|pick and drop]] transport method, seamlessly between the two views. <br/>
{{note|'''Note:''' Holding Ctrl while right clicking on an [[EiffelBuild Notation|object]] in the Builder Window creates a new [[Object editor|object editor]] targeted to the [[EiffelBuild Notation|object]] . Holding Ctrl and Shift while right clicking on an [[EiffelBuild Notation|object]] , highlights it within the [[Layout constructor|layout constructor]] .}}
==Visual Differences==
Although the builder window attempts to show you the interface you are developing, it is not a completely accurate representation (Unlike the [[Display window|display window]] ). The main difference is that all [[EiffelBuild Notation|objects]] representing descendents of EV_CONTAINER are parented in a frame. This was implemented so that you would be able to easily manipulate the containers.
Imagine that this was not the case, and each container [[EiffelBuild Notation|object]] was just represented by an [[EiffelVision Introduction|EiffelVision2]] object matching its type. Because these containers have no visible screen space when filled with children, manipulation of them would have been difficult, and the functionality of this view would be compromised.
In the screenshot above, you can see that there are two [[EiffelBuild Notation|objects]] representing containers in your project, an <eiffel>EV_VERTICAL_BOX</eiffel>, and an <eiffel>EV_HORIZONTAL_BOX</eiffel> (Excluding the <eiffel>EV_TITLED_WINDOW</eiffel> [[EiffelBuild Notation|object]] represented by this window).
The properties of the [[EiffelBuild Notation|objects]] in you system are always reflected in this window, with a few exceptions:
* 'user_can_resize', 'maximum_width', 'maximum_height' and 'title_string' are not reflected in this window.
* 'minimum_width' and `minimum_height' are not reflected in any of the controls representing [[EiffelBuild Notation|objects]] within this window.
{{seealso| '''See also''' <br/>
[[Display window|Display window]] <br/>
[[Layout constructor| Layout constructor]] }}

View File

@@ -0,0 +1,39 @@
[[Property:title|Component selector]]
[[Property:weight|8]]
The component selector allows you to build and retrieve user defined [[EiffelBuild Notation|components]] for use in your project.
[[Image:component-selector]]
==Creating a component==
To define a new [[EiffelBuild Notation|component]] , [[EiffelBuild Notation|pick]] the [[EiffelBuild Notation|object]] that you wish to create the component from, and then [[EiffelBuild Notation|drop]] it anywhere in the component selector. The following dialog will appear:
[[Image:component-namer]]
Modify the suggested name as desired, and then click '''OK''' to create the new component. If you click '''Cancel''', the component will not be created.
The component that has been created will contain enough information to allow a copy to be built of the existing object. This includes all the children of the original object (to any depth) and the properties (width, height, color etc)of all objects within the structure. The only properties of the objects that will not be set inside a component are the user defined names, and any events connected to the objects.
==Using a component==
To create a new set of [[EiffelBuild Notation|objects]] from a [[EiffelBuild Notation|component]] , [[EiffelBuild Notation|pick]] the [[EiffelBuild Notation|component]] , and [[EiffelBuild Notation|drop]] onto an [[EiffelBuild Notation|object]] representation. If an object is full, or does not allow other objects of the new type to be contained, then you will not be able to [[EiffelBuild Notation|drop]] on it. <br/>
If the [[EiffelBuild Notation|pick and drop]] completed successfully, then you should have a new set of objects matching the structure of the [[EiffelBuild Notation|component]] .
<span id="delete_component"></span>
==Deleting a component==
To remove a [[EiffelBuild Notation|component]] from your EiffelBuild system, [[EiffelBuild Notation|pick]] it, and then [[EiffelBuild Notation|drop]] it on [[Image:icon-delete-small-color]] in the [[Main toolbar| main toolbar]] .
{{note| '''Note''': The deletion of a [[EiffelBuild Notation|component]] cannot be undone. }}
==Viewing a component==
To view an existing component, use the [[Component viewer|component_viewer]] .
{{seealso| '''See also''' <br/>
[[Component viewer|Component_viewer]] <br/>
[[Builder window|Builder window]] <br/>
[[Layout constructor| Layout Constructor]] }}

View File

@@ -0,0 +1,29 @@
[[Property:title|Component viewer]]
[[Property:weight|10]]
The Component viewer allows you to view the structure of a [[EiffelBuild Notation|component]] without having to create new [[EiffelBuild Notation|objects]] from the [[EiffelBuild Notation|component]] .
This tool is displayed in a separate window, and may either be shown or hidden (default). To change between these two states, click [[Image:icon-component-viewer-color]] on the [[Main toolbar| main toolbar]] , or select '''Show/Hide component viewer''' from the '''View''' menu.
[[Image:component-viewer]]
==Targeting a component==
To target a [[EiffelBuild Notation|component]] into the tool, [[EiffelBuild Notation|pick]] the [[EiffelBuild Notation|component]] from the [[Component viewer|component_viewer]] , and [[EiffelBuild Notation|drop]] on the [[Image:icon-component-viewer-color]] displayed in the tool bar of the component viewer (See screenshots above). Any existing component displayed is simply removed.
Alternatively, you can hold down the Ctrl key while starting a [[EiffelBuild Notation|pick]] on a [[EiffelBuild Notation|component]] in the [[Component selector| component_selector]] . This will automatically target the [[EiffelBuild Notation|component]] to the component viewer. If the viewer is currently hidden, it will also make it visible.
==View types==
Looking at the left-hand screenshot above, you can see that the [[Image:icon-component-display-view-color]] button is depressed, meaning the component viewer is in display view mode. Clicking on [[Image:icon-component-build-view-color]] will put the component viewer into build mode view as shown in the right-hand screenshot. These modes are mutually exclusive and are described below:
* '''Builder view''' - This view is similar to the view used by the [[Display window|display window]] . i.e. the [[EiffelVision Introduction|EiffelVision2]] controls are displayed exactly as is defined in the [[EiffelBuild Notation|component]] .
* '''Display view''' - This view is similar to the view used by the [[Builder window|builder window]] . i.e. all [[EiffelVision Introduction|EiffelVision2]] containers are represented by frames so they are immediately visible. This makes the actual structure represented by the [[EiffelBuild Notation|component]] completely visible.
{{note| '''Note''': The type of the "root_object" within the component is displayed in the toolbar of the component viewer. }}
{{seealso| '''See also''' <br/>
[[Builder window|Builder window]] <br/>
[[Layout constructor| Layout constructor]] }}

View File

@@ -0,0 +1,174 @@
[[Property:title|Constants]]
[[Property:weight|12]]
EiffelBuild supports the use of constants, permitting you to define a particular value and use it comprehensively throughout your system. If a constant is in use, any changes are reflected immediately in all clients, providing a quick way of globally changing object properties. The Eiffel code generated by EiffelBuild, generates all constants as actual Eiffel constants for use in your system.
The following constant types are supported by EiffelBuild:
* '''String''' - Representing the Eiffel STRING type.
* '''Integer''' - Representing the Eiffel INTEGER type.
* '''Directory''' - Representing a directory location, of type STRING.
* '''Pixmap''' - Representing an EV_PIXMAP, and either absolute, or built from a directory constant.
* '''Font''' - Representing a font, of type EV_FONT.
* '''Color''' - Representing a color, of type EV_COLOR.
==Constants Dialog==
Modification to all constant types is performed from the constants dialog, accessible from the [[Main toolbar|main toolbar]] via the [[Image:icon-format-onces-color]] button. The constants dialog has the following appearance:
[[Image:constants-dialog]]
The screenshot above, shows the constants dialog displayed for a project containing twelve constants, a few of each available type. Each of the constants in the project are displayed in the multi column list occupying most of the dialog.
The "Type", "Name" and "Value" fields displayed along the bottom of the dialog are used to permit addition and modification of constants. The "OK" button displayed in the top right hand corner of the dialog closes the dialog when modifications to the constants are complete.
===Adding a new constant===
To add a new constant to your project, select the type of the constant that you wish to add from the "Type" combo box. Depending on the type of constant selected, the remaining fields, and associated buttons will be modified appropriately, and the steps required to add the constant differ:
* '''String''' and '''Integer''' - Enter the name in the "Name" field, and value in the "Value" field. The "New" button is only enabled when the name is valid, and a valid entry is set, and clicking it adds the new constant.
* '''Directory''' - Enter a name for the directory in the "Name" field, and then select "New" which displays a choose directory dialog. Selecting a directory from this dialog and pressing "OK" adds the new directory constant to the project.
* '''Pixmap''' - Select the "New" button, which brings up the Pixmap Constant Dialog enabling you to select a constant. The use of this dialog is described further down this page.
* '''Font''' - Enter a name in the "Name" field, and then select "New" which displays a font dialog. Selecting a font from this dialog and pressing "OK" adds the new font constant to the project.
* '''Color''' - Enter a name in the "Name" field, and then select "New" which displays a color dialog. Selecting a color from this dialog and pressing "OK" adds the new color constant to the project.
{{note| '''Note''': After adding a new constant, it is immediately displayed with all constants in the dialog. }}
===Modifying an existing constant===
To modify a constant that already exists, select the constant in the multi column list, and depending on the type of the constant, perform the following:
* '''String''' and '''Integer''' - Modify the value, which in turn, enables the "Modify" button, which must be selected for the value to change. Note that if you change the name, the "New" button is enabled as this will now add a new constant.
* '''Directory''' - Select the "Modify" button which displays a directory dialog, permitting selection of the new value.
* '''Pixmap''' - Select the "Modify" button which displays the Pixmap Constant Dialog, in a mode which permits you to select the new pixmap you wish to use.
* '''Font''' - Select the "Modify" button which displays a font dialog, permitting selection of the new font.
* '''Color''' - Select the "Modify" button which displays a color dialog, permitting selection of the new color.
===Removing constants===
To remove a constant from the project, select it in the multi column list, and select the "Remove" button, or press the delete key. If the constant is not in use within the system, it will be removed, otherwise the following dialog is displayed:
[[Image:constant-in-use]]
As objects are reliant on the constant you are removing, you must confirm that you really wish to remove it from the system. If you select "OK", the constant is removed, and the object property relying on that constant is converted to a manifest value. For example, if you are using an Integer constant with a value of 100, and you remove the constant, the property no longer references the constant, but is set explicitly to 100.
{{note| '''Note''': You may sort the constants displayed in the dialog, by clicking the associated column header. }}
==String constant==
A String constant represents an Eiffel STRING, and may be any valid STRING. For example, in the generated constants file, for a String constant named `modify_button_text', the following code is generated:
<code>
modify_button_text: STRING is
-- `Result' is STRING constant named modify_button_text.
once
Result := "Modify"
end
</code>
==Integer constant==
A Integer constant represents an Eiffel INTEGER, and may be any valid INTEGER value. For example, in the generated constants file, for an Integer constant named `medium_padding', the following code is generated:
<code>
medium_padding: INTEGER is
-- `Result' is INTEGER constant named medium_padding.
once
Result := 8
end</code>
==Directory constant==
A Directory constant is an Eiffel representation of a directory, as a STRING value. For example, in the generated constants file, for a Directory constant named `pixmap_location', the following code is generated:
<code>
pixmap_location: STRING is
-- `Result' is DIRECTORY constant named pixmap_location.
once
Result := "C:\pixmaps"
end</code>
==Pixmap constant==
A pixmap constant is a representation of a pixmap image, and two types are available:
* '''Absolute''' - The generated code contains a constant of type EV_PIXMAP, built from a single, absolute path, based on the location of the original pixmap on disk as follows:
<code>
main_pixmap: EV_PIXMAP is
-- `Result' is PIXMAP constant named main_pixmap.
local
a_file_name: FILE_NAME
once
create Result
create a_file_name.make_from_string ("C:\pixmaps\main_pixmap.png")
-- Now set `Result' based on `a_file_name'.
set_with_named_file(Result, a_file_name)
end</code>
* '''Relative''' - The generated code contains a constant of type EV_PIXMAP, built from a file name and a directory constant. This type of pixmap constant is the most frequently used, as it is more flexible. By redefining the value of the directory constant on which it is based, your systems may easily account for the installation location of the pixmap. A relative Pixmap constant is generated as follows:
<code>
main_pixmap: EV_PIXMAP is
-- `Result' is PIXMAP constant named main_pixmap.
local
a_file_name: FILE_NAME
once
create Result
create a_file_name.make_from_string (pixmap_location)
a_file_name.set_file_name("main_pixmap.png")
-- Now set `Result' based on `a_file_name'.
set_with_named_file(Result, a_file_name)
end</code>
Where `pixmap_location' is the name of the Directory constant to which the pixmap is relative.
==Font constant==
A Font constant represents an EV_FONT. For example, in the generated constants file, for a font constant named `times_new_roman', the following code is generated:
<code>times_new_roman: EV_FONT is
-- `Result' is EV_FONT constant named `times_new_roman'.
once
create Result
Result.set_family (feature {EV_FONT_CONSTANTS}.Family_roman)
Result.set_weight (feature {EV_FONT_CONSTANTS}.Weight_regular)
Result.set_shape (feature {EV_FONT_CONSTANTS}.Shape_regular)
Result.set_height_in_points (12)
Result.preferred_families.extend ("Times New Roman")
end</code>
==Color constant==
A Color constant represents an EV_COLOR. For example, in the generated constants file, for a color constant named `red', the following code is generated:
<code>red: EV_COLOR is
-- `Result' is EV_COLOR constant named `red'.
once
Result := create {EV_COLOR}.make_with_8_bit_rgb (255, 0, 0)
end</code>
===Pixmap constant dialog===
The Pixmap Constant dialog is used to select pixmaps for addition to an EiffelBuild project, and is displayed from the Constants dialog when necessary. The Pixmap Constant dialog has the following appearance:
[[Image:pixmap-selection-dialog]]
An individual pixmap may be selected, or a whole directory of pixmaps may be selected from this dialog for addition. In the screenshot above, a directory containing two pixmaps was selected. The "Build from" option at the bottom of the dialog permits you to select if you wish to add an absolute or relative pixmap, and if multiple pixmaps are being added, the currently selected pixmap from the list above is active. The relative "DIRECTORY" for relative pixmaps is filled in automatically if EiffelBuild finds a directory constant in the system that matches the path chosen. If not, you may enter a name in this field to create a new directory matching the required path. If you do not enter a directory name for one or more relative pixmaps, upon closing the dialog, you will be prompted to enter a name for a directory constant used for these pixmaps.
{{note| '''Note''': If you are selecting new pixmaps, and they appear in the dialog as unchecked, it means that an equivalent pixmap already exists in the project. }}
==Loading constants==
The generation of an EiffelBuild project creates two constants classes, an interface class and an implementation class, named to match the setting from the [[EiffelBuild: Project settings window|project settings]] . For example, if you have specified the name "constants" for the constants, two classes are generated, <eiffel>CONSTANTS</eiffel> and the implementation, <eiffel>CONSTANTS_IMP</eiffel>.
By default, all constant values are hard coded into the implementation class, but it is possible to set these to be loaded from an external file upon execution of the generated system. To do this, the "Load constants from file" setting of the [[EiffelBuild: Project settings window|project settings]] must be checked, which causes a file "constants.txt" to be generated, containing the definitions of all Integer and String constant values. As the system is executed, the values of these constants are loaded from the file, and by providing different versions of the file, at the time of deployment, multiple languages may be accounted for in your generated system.
==Using constants==
Constants may be associated to properties of your [[EiffelBuild Notation|objects]] via an [[Object editor|object editor]] targeted to that [[EiffelBuild Notation|object]] . The [[Image:icon-format-onces-color]] button denotes the use of a constant value. For more information regarding using constants, in [[Object editor|object editors]] , see [[Object editor|object editor]] .
When an EiffelBuild project is generated, all constants are added to a class, inherited by each window class. There is an "_IMP" and interface versions of these classes as with each window. For more information regarding the generation of constants, see [[EiffelBuild: Code Generation|code generation]] .
{{note| '''Note''': To modify pixmap constants based on the current installation of an EiffelBuild generated interface, simply redefine the Directory constant used to access the pixmaps within the interface constants class (not "_IMP"), which is not re-generated if it already exists. }}
{{seealso| '''See also''': <br/>
[[EiffelBuild: Code Generation|Code generation]] <br/>
[[Object editor|Object editor]] <br/>
[[EiffelBuild: Project settings window|Project settings]] }}

View File

@@ -0,0 +1,19 @@
[[Property:title|Display window]]
[[Property:weight|6]]
The Display window provides a view of the [[EiffelBuild Notation|objects]] in your system, but unlike the [[Layout constructor|layout constructor]] and [[Builder window|builder window]] , the objects cannot be manipulated.
This window may either be shown or hidden (default). To change between these two states, click [[Image:icon-display-window-color]] on the [[Main toolbar|main toolbar]] , or select '''Show/Hide display window''' from the '''View''' menu.
[[Image:display-window]]
This view is provided so that you can really see what your project will look like when it has been generated and is running as a stand alone [[EiffelVision Introduction|EiffelVision2]] system.
All properties that have been set on the [[EiffelBuild Notation|objects]] in your project are set in the [[EiffelVision Introduction|EiffelVision2]] control matching its type.
{{seealso| '''See Also''' <br/>
[[Builder window|Builder window]] <br/>
[[Layout constructor|Layout constructor]] }}

View File

@@ -0,0 +1,51 @@
[[Property:title|EiffelBuild: Code Generation]]
[[Property:weight|15]]
To generate Eiffel code representing your system, select '''Generate code''' from the '''Project''' menu or click [[Image:icon-code-generation-color]] on the [[Main toolbar|main toolbar]] .
The length of time taken to generate your code is dependent on the speed of the system you are running, and the size of your interface, but typically takes a couple of seconds. A progress bar is displayed during the generation of your system.
The code will be generated according to the options you selected in the [[EiffelBuild: Project settings window|project settings]] .
==Generated classes==
The generation of an EiffelBuild project causes the following files to be generated:
* A constants class and its respective implementation class. For example, if the constants class is named as "constants" in the [[EiffelBuild: Project settings window|project settings]] , two classes, CONSTANTS and CONSTANTS_IMP are generated.
* A class and implementation class for each window, dialog and "top level" widget in the system (each of which is contained in the [[Widget selector|widget selector]] ), named to correspond with the name attribute of the object. For example, for a window in the project named "main_window", the files MAIN_WINDOW and MAIN_WINDOW_IMP are generated.
* An optional file named "constants.txt" which contains definitions of all INTEGER and STRING constants. This is only generated if "Load constants from file" is selected in the [[EiffelBuild: Project settings window|project settings]] . The generated code loads the constants from this file, and allows simple modification for localization, i.e. for foreign languages provide a different version of this file with all strings converted.
For each "top level" widget class in the system (contained in the [[Widget selector|widget selector]] ), the following class hierarchy is generated:
[[Image:class-project-diagram]]
If the "generate as client" option is selected for a particular object (changeable from the [[Object editor|object editor]] , only for objects contained in the [[Widget selector|widget selector]] ), a client supplier relationship exists between the generated widget class and the EiffelVision widget, as illustrated below:
[[Image:class-project-diagram-client]]
{{note| '''Note''': All other diagrams on this page show only the non client version of the settings, where the generated widget inherits from the EiffelVision class. }}
==Project build type==
If [[Build Tab|build type]] is selected as '''Project''' in the [[EiffelBuild: Project settings window|project settings]] , then all the classes listed above in "Generated classes" are generated, along with the following:
* A project configuration file called "build_project.ecf".
* An application class which launches the root window of the project.
The generated files comprise a complete project with a configuration file enabling you to compile and execute the generated system as is. The following diagram illustrates the hierarchy of the generated project, showing only the root window of the project:
[[Image:complete-project-diagram]]
==Modifying code after generation==
The choice to generate an interface and an implementation class for the windows and constants was to enable modification of the interface using EiffelBuild, once you had hand edited code. The rule is that the implementation classes are re-generated every time, but the interface classes are not. It follows from this that you should not add hand written code to the implementation classes (ending in _IMP), as any changes you make will be lost when re-generation takes place.
Using this mechanism, you can generate your initial system using EiffelBuild, and implement any event features that have been generated (in the interface) by EiffelBuild. If you then decide that you wish to modify the look and the feel of the interface, you can return to EiffelBuild, make the necessary adjustments and then re-generate the system.
{{note| '''Note''': When returning to EiffelBuild to modify the interface, if you delete or rename controls, then it is quite possible that you will break your existing code. Care should be taken with all changes of this type. }}
Looking at a generated system, you will see that the [[Object editor|events]] connected to your controls are defined as deferred in the implementation and actually implemented in the interface class. This means that if you return to EiffelBuild with a previously generated system, and add a new event to a control, then you will have to implement the definition in the interface class yourself (as the class interface class is not re-generated).
{{seealso| '''See also''': <br/>
[[EiffelBuild: Project settings window|Project settings]] }}

View File

@@ -0,0 +1,32 @@
[[Property:title|Docking]]
[[Property:weight|3]]
The docking mechanism permits customization of the EiffelBuild interface through the re-ordering of tools to suit your preferences. You may simply "drag" one of the supported tools to a new location as desired. The [[Type selector|Type Selector]] , [[Component selector|Component Selector]] and [[Widget selector|Widget Selector]] all support docking.
==Performing a dock==
To dock one of the three supported tools, press and hold the left mouse button on the title of the tool, and move the mouse so that it points to the new location for the tool. Upon releasing the mouse button, the dock completes, and based on the mouse location, the following may occur:
* '''Re-positioning in the main window''' - If the mouse is held over the three part vertical split area displayed to the left hand side of the EiffelBuild window, the position of the tool within this structure may be modified, providing simple re-ordering. A small grayed area indicates the insertion position of the tool, only displayed if the tools position will be changed upon release. The gray area indicating the new insertion point has the following appearance:
[[Image:docking-insert]]
In this case, the tool being docked will be moved to immediately above the component selector. If no feedback is provided regarding the insertion, upon releasing the mouse button to complete the dock, the tool is moved to an external window.
* '''Docking externally''' - Completing a dock while not above the left hand area of the main window, or if no insert feedback is provided, causes the tool to be moved from its current location to an external window. A tool that is docked externally has the following appearance:
[[Image:docked-external]]
The tool may now be freely moved to any location on screen, in the same fashion as you would move any standard window. The window in which the tool is contained is always displayed "on top" of the main window. There are two methods of restoring the dialog back to its original location in the main window:
** '''Docking back''' - Start a drag from the title of the tool, and point the mouse to the position in which you wish to insert the tool within the main window. If the position is valid, feedback (the gray bar) is displayed, and completing the dock closes the dialog, and re-inserts the tool. If no feedback is provided, the pointed position is not valid, and completing the dock simply moves the window to that position on screen.
** '''Closing the window''' - Clicking the cross displayed to the right hand side of the windows title bar causes the window to be destroyed, and the tool contained to be restored back to its original position within the main window.
{{note| '''Note''': The position of tools that have been docked, is maintained automatically between EiffelBuild sessions. When a new project is opened, they are restored to the positions that they had during the last use. }}
==Main window with externally docked tools==
The following screenshot illustrates the appearance of the main window with all dockable tools external:
[[Image:main-window-with-docked-tools]]
{{seealso| '''See Also''' <br/>
[[EiffelBuild: General interface description|General interface description]] }}

View File

@@ -0,0 +1,45 @@
[[Property:title|EiffelBuild: Key shortcuts]]
[[Property:weight|2]]
Many operations in EiffelBuild do not require the use of the mouse. The same effect can be achieved through the keyboard only.
This page gathers all the keyboard shortcuts available in the environment.
==Key shortcut reference==
{|
|-
| '''Key shortcut'''
| '''action'''
|-
| ''- file shortcuts -''
|-
| Ctrl+O
| Open project.
|-
| Ctrl+N
| New Project.
|-
| Ctrl+S
| Save project
|-
| ''- code generation shortcuts -''
|-
| Ctrl+G
| Generate code from project.
|-
| ''- miscellaneous shortcuts -''
|-
| Delete
| Delete object from currently selected tool.
|-
| Ctrl+T
| Tool always on top.
|}
'''Note''': These shortcuts are not always available and are dependent on the state of EiffelBuild. For example, Ctrl+S does nothing if there is no modified project open.
{{seealso| '''See Also''' <br/>
[[EiffelBuild: General interface description|General interface description]] }}

View File

@@ -0,0 +1,29 @@
[[Property:title|EiffelBuild window overview]]
[[Property:weight|0]]
==Window layout==
The use of EiffelBuild is based around one main window which remains throughout the execution. The appearance of the main window is as follows:
[[Image:main-window]]
The window contains several different tools, highlighted below:
* The [[Type selector|type selector]] - Situated at the top left of the window, this tool contains all the available vision2 types available for interface construction.
* The [[Component selector| component selector]] - Situated in the middle left of the window, below the [[Type selector|type selector]] , this tool contains all the user defined components.
* The [[Widget selector|widget selector]] - Situated in the bottom left of the window contains all of the EiffelVision2 windows contained in the open project. Each of these windows are generated by EiffelBuild as separate classes.
* The [[Layout constructor| layout constructor]] tool - Situated in the middle of the window, this tool displays a graphical representation of the interface that is currently being built.
* The docked [[Object editor|object editor]] - Situated to the right hand side of the window, this object editor automatically targets itself to the selected [[EiffelBuild Notation|object]] in the [[Layout constructor| layout constructor]] .
The [[Type selector|type selector]] , [[Component selector|component selector]] and [[Widget selector|widget selector]] may all be docked from their original position, permitting re-ordering and customization of the main window. Each of these may be docked external to the main window, permitting each to be displayed in their own movable window. For more information regarding the docking mechanism, see [[Docking|docking]] .
{{seealso| '''See Also''' <br/>
[[Main toolbar| Main toolbar]] <br/>
[[Layout constructor| Layout constructor]] <br/>
[[Type selector|Type selector]] <br/>
[[Object editor|Object editor]] <br/>
[[Component selector| Component_selector]] <br/>
[[Docking| Docking]] <br/>
}}

View File

@@ -0,0 +1,10 @@
[[Property:title|EiffelBuild: General interface description]]
[[Property:weight|2]]
* [[EiffelBuild window overview|EiffelBuild window overview]]
* [[Main toolbar|Main toolbars]]
* [[EiffelBuild: Key shortcuts|Key shortcuts]]
* [[Docking|Docking]]

View File

@@ -0,0 +1,66 @@
[[Property:title|Main toolbar]]
[[Property:weight|1]]
At the top of the EiffelBuild development window, one toolbar is displayed by default, as shown below:
[[Image:toolbar]]
The complete list of the icons in the toolbar is displayed below. <br/>
{|
|-
| Icon
| Command
|-
| [[Image:icon-delete-small-color]]
| Delete [[EiffelBuild Notation|object]] / [[EiffelBuild Notation|component]] .
|-
| [[Image:icon-save-color]]
| [[Save a project|Save]] current project.
|-
| [[Image:icon-object-editor-color]]
| New [[Object editor|object editor]]
|-
| [[Image:icon-undo-color]]
| [[History|Undo]] last action.
|-
| [[Image:icon-cmd-history-color]]
| Display full [[History|history]] .
|-
| [[Image:icon-redo-color]]
| [[History|Redo]] last undone action.
|-
| [[Image:icon-code-generation-color]]
| [[EiffelBuild: Code Generation|Generate]] code.
|-
| [[Image:icon-system-color]]
| Display [[EiffelBuild: Project settings window|project settings]] .
|-
| [[Image:icon-builder-window-color]]
| Show/hide [[Builder window|builder window]] .
|-
| [[Image:icon-display-window-color]]
| Show/hide [[Display window|display window]] .
|-
| [[Image:icon-component-viewer-color]]
| Show/hide [[Component viewer|component viewer]] .
|-
| [[Image:icon-format-onces-color]]
| Display [[Constants|Constants]] dialog.
|-
| [[Image:icon-cut-color]]
| Cut selected object to clipboard.
|-
| [[Image:icon-copy-color]]
| Copy selected object to clipboard.
|-
| [[Image:icon-past-color]]
| Paste contents of clipboard.
|-
| [[Image:icon-clipboard-color]]
| View clipboard contents.
|}
The screenshot at the top of this page shows all of the buttons enabled. As the state of the currently open project changes, the state of each of these buttons is updated to reflect this. For example, immediately after saving the project, the save button is disabled until the project is modified again.
'''Note''': It is not possible to customize the toolbar.

View File

@@ -0,0 +1,42 @@
[[Property:title|EiffelBuild Notation]]
[[Property:weight|1]]
This page contains descriptions of terms found within the EiffelBuild documentation.
==Object==
An EiffelBuild object is a representation of a Vision2 component and its properties. When developing with EiffelBuild, you manipulate objects to build the desired interface.
Each object type has a different set of properties that may be manipulated, and these correspond directly to the properties available within the [[EiffelVision Introduction|EiffelVision2]] type. There is property which is specific to an EiffelBuild object, '''Name''' which is used for your identification purposes and as the attribute name in the generated code.
For more information on manipulating objects within EiffelBuild, see:
* How to [[Create an object|create an object]]
* How to [[Reparent an Object| reparent an object]] .
* [[Object editor|Object editor]] for details on modifying object properties.
Within EiffelBuild, there may be multiple views of a single object displayed simultaneously. Any modifications to an object will immediately update all views. Both the [[Layout constructor| layout constructor]] and the [[Builder window|builder window]] provide views of the objects within your project, and in these, the objects may be manipulated. The [[Display window|display window]] also provides a view of the objects in your system, except the objects cannot be manipulated from this view. It can be thought of as a preview of the project you are developing.
<span id="component"></span>
==Component==
EiffelBuild components are templates representing user defined object structures. From a component, you can quickly build a matching structure of objects. Components are available in EiffelBuild so that you do not repeatedly create the same structures over and over again while developing your projects.
You specify a new component by creating it from an existing object structure. See [[Component selector| component_selector]] for more detailed instructions on the use of components.
To view an existing component, use the [[Component viewer|component_viewer]] .
It is not possible to modify a component once created, except to [[Component selector| delete]] it.
<span id="pick_and_drop"></span>
==Pick and Drop==
The pick and drop mechanism is one of Eiffel Software 's exclusive technologies and is provided by [[EiffelVision Introduction|EiffelVision2]] . In EiffelBuild, it allows you to easily send data from a component of the interface to another.
You can '''Pick''' a reference to a '''development object''', such as an object or component with a single click of the '''right''' mouse button. Then as you start moving the mouse around - not pressing any of its buttons - a pebble tracks the cursor position, and a line continuously connects the pebble to the object's original position.
You may terminate this situation in either of two ways:
* If the pebble you are dragging is the regular cursor, you can right-click again to confirm the pick-and-drop and so effectively send the dragged development object to the targeted component. This is known as '''Dropping'''.
Right-clicking when the pebble is the '''no''' cursor, will only stop the pick-and-drop because the component you are hovering with the mouse does not accept your development object.
* If, for any reason, you change your mind, you can cancel the pick-and-drop by left-clicking anywhere or by pressing the Escape key.

View File

@@ -0,0 +1,23 @@
[[Property:title|EiffelBuild Preferences]]
[[Property:weight|14]]
The EiffelBuild preferences are used to handle all user defined preferences. For example, each time a dialog is displayed with a "do not show again" option, your chosen setting is recorded in the preferences. Various properties of the EiffelBuild interface are recorded by the preferences, on a user by user basis, permitting you to adapt the behavior of EiffelBuild to suit your needs.
During use of EiffelBuild, many settings and options that you select, will modify the preferences, ensuring the desired behavior is maintained. To access all of the available EiffelBuild preferences, you may use the Preferences dialog, accessible from the "View", "Preferences", "Preferences..." menu option. The preference dialog has the following appearance:
[[Image:preferences-dialog]]
To the left hand side of the dialog is a tree, containing the preferences structure, while on the right, the actual preferences in the selected tree node are displayed. To modify the value of a particular preference, double click on its "Literal Value" which displays a small dialog permitting modification of the value. Dependent on the type of the property, the dialog displayed may change appropriately.
The button marked "Restore Defaults" in the lower left hand corner of the dialog, may be selected to restore the preferences back to their defaults when EiffelBuild was first launched.
When you have finished modifying the preferences, select the "Close" button to close the dialog.
{{note| '''Note''': The preferences are saved automatically by EiffelBuild, even if the open project is not saved, the preferences are saved whenever a property changes. }}
{{seealso| '''See also''': <br/>
[[EiffelBuild: General interface description|General interface description]] <br/>
[[EiffelBuild Reference|EiffelBuild reference]] }}

View File

@@ -0,0 +1,41 @@
[[Property:title|Build Tab]]
[[Property:weight|0]]
This tab contains information about the type of project you wish to build, and associated information.
Here is the appearance of the Build tab when 'build type' is selected as 'Project':
[[Image:project-build]]
If 'build'_type' is selected as 'Class', then the tab will have the following appearance:
[[Image:project-build-class]]
The options available in this tab are as follows:
* <span id="build_type"></span> '''Build type'''
Select 'Project' if you wish to generate a complete project including an ace file, and an application class, which will launch the GUI you are developing.
Select `Class' if you wish to generate a single class that represents the GUI you are developing. This option is useful if you wish to incorporate your current project into an existing Vision2 system.
* '''Always rebuild ace'''
This option causes the ace file to be completely re-generated every time you generate your project. If you do not wish the ace file to be re-generated, then disable this option. This check box is only available if 'build type' is set to 'project'.
* '''Project name'''
This entry will be added to the generated ace file as the SYSTEM attribute. The executable built from compiling this ace file will have this name. This option is only available if you have specified 'build_type' as 'Project'.
* '''Application class name'''
This entry will be the class name for the generated vision2 application which will launch your GUI. This option is only available if you have specified 'build_type' as 'Project'.
* '''Constants class name'''
This entry is used as the name of the constants class generated by EiffelBuild to define all [[Constants|constants]] contained in your project. Two classes are actually generated from this name, an implementation and an interface class. For example, if you specify a name "constants", two classes, <eiffel>CONSTANTS_IMP</eiffel> and <eiffel>CONSTANTS</eiffel> (inheriting from <eiffel>CONSTANTS_IMP</eiffel>) are generated, and all other classes generated by EiffelBuild, inherit <eiffel>CONSTANTS</eiffel> for access to these constants.
{{seealso| '''See Also''' <br/>
[[EiffelBuild: Code Generation|Code generation]] <br/>
[[EiffelBuild: Project settings window|Project settings window]] <br/>
[[Generation Tab|Generation tab]] <br/>
}}

View File

@@ -0,0 +1,20 @@
[[Property:title|Generation Tab]]
[[Property:weight|1]]
This tab contains information about the available code generation options.
Here is the appearance of the Generation tab with default settings for a Build project:
[[Image:project-generation]]
The options available in this tab are as follows:
* '''Attribute declarations'''
** '''Local''' - All attributes (corresponding to widgets and items generated by EiffelBuild) are declared as local variables.
** '''Attributes''' -- All attributes are declared as attributes of the class with the following export status:
**
*** '''Exported''' - All attributes are exported to ANY.
*** '''Export only named''' - Only those attributes that have been named are exported to ANY while unnaned attributes are not exported..
*** '''Export None''' - None of the attributes are exported.
** '''Grouped''' - Should different objects of same type be declared individually, or grouped?<br/>

View File

@@ -0,0 +1,22 @@
[[Property:title|EiffelBuild: Project settings window]]
[[Property:weight|13]]
This is where global settings regarding your project are going to be made. In here you can specify:
* The type of project you wish to generate
* The system name
* Class names
* Code generation options
The project window can be raised by clicking [[Image:icon-display-window-color]] on the [[Main toolbar| main toolbar]] , or by selecting '''Settings...''' from the '''Project''' menu.
The window is organized as two tabs:
# [[Build Tab|Build]]
# [[Generation Tab|Generation]]
All options are enabled and saved into the project settings file, 'build_project.bpr' as soon as the window is closed.
{{seealso| '''See Also''' <br/>
[[EiffelBuild: Code Generation|Code generation]] }}

View File

@@ -0,0 +1,35 @@
[[Property:title|History]]
[[Property:weight|11]]
EiffelBuild has an limitless undo/redo mechanism built in. However, this mechanism only applies to the structure of the [[EiffelBuild Notation|objects]] you are developing in your project.
For example, every time you [[Create an object|create]] , [[Reparent an Object| reparent]] or [[Delete an object|delete]] an [[EiffelBuild Notation|object]] in your project, this is recorded in the history. If you modify properties of an [[EiffelBuild Notation|object]] (Using an [[Object editor|object editor]] ), these modifications are not recorded in the history.
==Undo==
To undo a change, click [[Image:icon-undo-color]] on the [[Main toolbar| main toolbar]] You can repeatedly undo, until you get to the beginning of the history, at which point, this button is disabled.
==Redo==
To redo a change (only applicable after one ore more undo's), click [[Image:icon-redo-color]] on the [[Main toolbar| main toolbar]] . You can repeatedly redo, until the history becomes current again, and at which point, this button is disabled.
==History window==
[[Image:history-window]]
The screenshot above shows the appearance of the history window.
This visibility of the window may be toggled by clicking [[Image:icon-cmd-history-color]] on the [[Main toolbar| main toolbar]] . You may also select '''History''' from the '''View''' menu to show the history window, and click the '''Close''' button to close the window manually.
Looking at the screenshot above, you will see that the last action in the history list is selected. This is always the case while working, until you start undoing your changes. To go back six steps, so that (in this case), there is just the one BUTTON added to the HORIZONTAL_BOX, you could click the undo button on the [[Main toolbar| main toolbar]] six times, or you can simply select the third item in this list. both have the same effect. You can also redo by selecting an item below the currently selection in the history list (Only possible after an undo).
If you execute an action which will be added to the history while the history is not at the final position, all history events after this current position will be removed, and the history will be up to date again.
{{note| '''Note''': If you use the history list to move through many recorded actions at once, there may be a slight delay dependent on the systems complexity and steps moved. }}
{{seealso| '''See also''' <br/>
[[Builder window|Builder window]] <br/>
[[Layout constructor| Layout constructor]] }}

View File

@@ -0,0 +1,22 @@
[[Property:title|EiffelBuild Reference]]
[[Property:weight|1]]
* [[EiffelBuild Introduction|EiffelBuild Introduction]]
* [[EiffelBuild Notation|EiffelBuild Notation]]
* [[EiffelBuild: General interface description|General interface description]]
* [[Layout constructor|Layout constructor]]
* [[Type selector|Type selector]]
* [[Object editor|Object editor]]
* [[Display window|Display window]]
* [[Builder window|Builder window]]
* [[Component selector|Component selector]]
* [[Widget selector|Widget selector]]
* [[Component viewer|Component viewer]]
* [[History|History]]
* [[Constants|Constants]]
* [[EiffelBuild: Project settings window|Project settings]]
* [[EiffelBuild Preferences|Preferences]]
* [[EiffelBuild: Code Generation|Code generation]]

View File

@@ -0,0 +1,50 @@
[[Property:title|Layout constructor]]
[[Property:weight|3]]
The layout constructor provides a view of the [[EiffelBuild Notation|objects]] you have defined in your system, in which the [[EiffelBuild Notation|objects]] may be manipulated. The root node of the tree is the object currently selected within the [[Widget selector|widget selector]] and objects may be added/moved within the displayed widget structure by picking and dropping the objects as required. For example, in the screenshot below, you could add another list to the vertical box, by picking a list from the [[Type selector|type selector]] and dropping it on the vertical box object.
[[Image:layout-constructor]]
Each item in the tree represents one object. The screenshot above represents the following [[EiffelVision Introduction|EiffelVision2]] interface definition - An EV_TITLED_WINDOW containing one child, of type EV_VERTICAL_BOX. Within the vertical box there is an EV_HORIZONTAL_BOX and an EV_LIST. The list is empty, but the horizontal box contains three different objects of type EV_BUTTON.
{{note|'''Note''': The widget displayed as the root of the Layout Constructor is the currently selected object in the [[Widget selector|Widget Selector]] . To edit the contents of a different widget, select the widget you wish to manipulate from the [[Widget selector|widget selector]] .}}
The information displayed, only shows you the structure of the [[EiffelBuild Notation|objects]] , and although it gives you an indication of the final appearance of the interface you are building, you cannot see the details of the interface. i.e. color, sizes, tool tips etc. To view an accurate representation of the widget structure you are building, show the [[Display window|Layout window]] .
All [[EiffelBuild Notation|objects]] displayed in the Layout Constructure are [[EiffelBuild Notation|pickable]] , so can be easily manipulated, e.g. [[Delete an object|deleted]] or [[Reparent an Object|reparented]] .
{{note| '''Note''': If the [[EiffelBuild Notation|object]] in the tree has the '''Name''' property set, then the text corresponds to the name, otherwise, the text is the type of the [[EiffelBuild Notation|object]] . }}
If you have just started a new project, then the layout constructor will only contain one tree item, TITLED_WINDOW.
==Selection==
The currently selected object within the Layout Constructor is automatically targetted to the docked [[Object editor|object editor]] which is situated to the right hand side of the main EiffelBuild Window. This enables you to quickly and easily edit the properties of the selected object. Note that Ctrl-right clicking on an object in the Layout Constructor displays a floating [[Object editor|object editor]] targeted to that object.
==Expanding/Collapsing==
To Expand all of the items displayed in the layout constructor, select '''Expand layout tree''' from the '''View''' menu, or select the small cross icon displayed at the top of the tool.
Similarly, if you wish to collapse all of the items in the layout constructor, select '''Collapse layout tree''' from the '''View''' menu.
==Highlighting an Object==
An [[EiffelBuild Notation|object]] contained in a system may be highlighted in the Layout Constructor by [[EiffelBuild Notation|picking]] it, and [[EiffelBuild Notation|dropping]] on the button displayed at the top of the Layout Constructor. Clicking this button with the mouse has no effect. The ability to highlight an object in this fashion proves to be particularly useful when building directly into the [[Builder window|builder window]] , as a particular object may be quickly highlighted in the Layout Constructor, and its properties edited.
==Locked Objects==
Objects that are instances of other objects are displayed as locked objects within the Layout Constructor as illustrated below:
[[Image:layout-constructor-locked]]
The object of type OK_CANCEL_BUTTONS is a locked instance of another object as illustrated by the locked icon displayed on top of it's type icon. As a locked object is simply an instance of another object, its internal structure may not be manipulated directly within the Layout Constructor. To change the structure of a locked object, you must directly change the object of which it is an instance.
To add a locked object to your interface, simply pick the object that you wish to re-use from the [[Widget selector|widget selector]] and drop it into the desired parent object within the Layout Constructor. In this case, the instance of the OK_CANCEL_BUTTONS object is actually comprised of a number of widgets which may only be modified through manipulation of the original OK_CANCEL_BUTTONS_OBJECT. Changes made to this original object are then applied to all instances within your interface structures.
You may convert an existing widget structure into a locked instance of a widget by picking the object to be used as the root of the structure (may not be locked) and dropping it into the [[Widget selector|widget selector]] . This creates a new "top level" object within the [[Widget selector|widget selector]] and places a locked instance of this at the original location in the widget structure where it was picked from.
{{note| '''Note''': Double clicking on a locked object within the Layout Constructor, targets the object of which it is an instance to the Layout Constructor. }}
{{seealso| '''See Also''' <br/>
[[Builder window|Builder window]] <br/>
[[Object editor|Object editor]] <br/>
[[Display window|Layout window]] }}

View File

@@ -0,0 +1,72 @@
[[Property:title|Object editor]]
[[Property:weight|5]]
An object editor is a tool which allows you to edit the properties of a selected [[EiffelBuild Notation|object]] . Common properties include minimum width and height, color, text etc.
An object editor can only reference one [[EiffelBuild Notation|object]] at once, and when not empty, it is considered to be "targeted" to the [[EiffelBuild Notation|object]] whose properties it references.
[[Image:object-editor]]
The screenshot above shows a floating object editor. The docked object editor is almost identical except that it is located within the EiffelBuild main window.
==Docked object editor==
The docked object editor is displayed to the right hand side of the EiffelBuild main window. This editor is always displayed and is permanently linked to the [[Layout constructor| layout constructor]] . This means that whenever the selected [[EiffelBuild Notation|object]] changes in the [[Layout constructor| layout constructor]] , the docked object editor becomes targeted to this [[EiffelBuild Notation|object]] .
==Floating object editors==
These object editors appear in their own window, and you may open as many of these as you wish.
To open a new floating object editor, [[EiffelBuild Notation|drop]] an [[EiffelBuild Notation|object]] on [[Image:icon-object-editor-color]] , displayed in the [[Main toolbar| main toolbar]] and also in each existing object editor. The new object editor will then be targeted to the [[EiffelBuild Notation|object]] that was [[EiffelBuild Notation|dropped]] .
{{note| '''Note''': If the [[EiffelBuild Notation|object]] targeted to floating object editor is deleted, then the editor will be destroyed. This helps stop the screen becoming cluttered with empty editors. }}
As a shortcut to a complete [[EiffelBuild Notation|pick and drop]] transport, you may hold down the Ctrl key while starting the [[EiffelBuild Notation|pick]] , which will immediately open a new floating object editor targeted to the [[EiffelBuild Notation|object]] you clicked.
==General use==
When an object editor is targeted to an [[EiffelBuild Notation|object]] , you will see that controls are available within the editor to customize that [[EiffelBuild Notation|object]] . Although every different type of [[EiffelBuild Notation|object]] will have different sets of properties that may be modified, the manipulation of these properties is as standardized as possible. Below are some general rules that apply:
* String properties inputted via a text field are updated within the object every time a key is pressed
* Integer properties inputted via a text field are only updated within the object when return is pressed, or the input box looses the focus.
* Almost without exception, a push button which controls a property, will open up a dialog, allowing the property to be edited. Examples are colors, pixmaps and events.
* If when you attempt to modify a property, it returns back to its original value, it means that the value you attempted to enter was invalid. For example, looking at the screen show above, if you enter -50 into the minimum_height text field and press return, it will revert back to 23. This is because the minimum_height of an <eiffel>EV_BUTTON</eiffel> may not be set to less than 0. To find allowable values for properties of an [[EiffelBuild Notation|object]] , consult the [[EiffelVision Introduction|EiffelVision2]] documentation.
All properties that may be manipulated in an object editor correspond directly to a property of the [[EiffelVision Introduction|EiffelVision2]] control that is represented by the [[EiffelBuild Notation|object]] (Displayed in an object editor as '''type'''). There is one exception to that rule though, and that is the '''Name''' field which is specific to EiffelBuild. This field is used for your identification of the [[EiffelBuild Notation|object]] and as the attribute name in the generated code. For example, when EiffelBuild generates code corresponding to the [[EiffelBuild Notation|object]] targeted in the editor shown above, it would declare the vision2 component as - button1: EV_BUTTON
{{note| '''Note''': You may have as many object editors targeted to the same [[EiffelBuild Notation|object]] as you wish. Whenever a change is made to the [[EiffelBuild Notation|object]] through one of the editors, all other editors targeted to that [[EiffelBuild Notation|object]] are synchronized. }}
==Using Constants==
All fields that may use constants have a button marked with the constants symbol [[Image:icon-format-onces-color]] , which when selected, modifies the field to allow selection of the desired constant. A combo box is displayed with all valid constants (matching the type of the property) displayed, from which you may select the constant you wish to use. To remove the use of the constant, simply press the constants button again, which removes the constant, and sets the property to a manifest value representing the previous value of the last selected constant.
==Advanced property manipulation==
Although many of the properties of [[EiffelBuild Notation|objects]] are relatively simple, and can be manipulated with <eiffel>STRING</eiffel> or <eiffel>INTEGER</eiffel> values, there are others that require more complicated control mechanisms. The following [[EiffelBuild Notation|object]] properties have more complicated interfaces warranting further explanation:
* [[Merging radio button groups]]
* [[Positioning table children]]
* [[Positioning fixed children]]
For all "top level" objects (those contained within the [[Widget selector|widget selector]] which are to be generated as individual classes), a check button marked "Generate as client" is available towards the top of the Object Editor. If this is checked, the generated class uses the widget type of the object as a client, otherwise it inherits directly from the widget's class.
<span id="events"></span>
==Event connection==
As well as being able to manipulate the standard properties of an [[EiffelBuild Notation|object]] , facilities are provided for connecting to the events of an [[EiffelBuild Notation|object]] . Looking at the object editor screenshot above, you will see that there is a button marked '''Select events''' which is also available in all targeted editors.
{{note| '''Note''': The button will be marked '''Modify events''' when one or more events are already selected for the current [[EiffelBuild Notation|object]] . }}
Clicking this button will cause the following dialog to be displayed:
[[Image:event-selection-dialog]]
Looking at the screenshot above, you will see that this dialog contains all the action_sequences available for the <eiffel>EV_BUTTON</eiffel> to which the object editor is targeted.
If you check a button connected with one of the action sequences, you will be then able to enter the name of a feature that you wish to connect to the action sequence. The screenshot above shows the user has connected a feature named `button_pressed' to the `select_actions'. When [[EiffelBuild: Code Generation|code is generated]] , this will cause EiffelBuild to generate an empty feature named `button_pressed' already connected to the `select_actions' of the button.
{{note| '''Note''': You will only be allowed to enter valid and unique Eiffel feature names. If a name is invalid, it will be highlighted in red, and a dialog will warn you when you attempt to close the dialog. }}
{{seealso| '''See Also''' <br/>
[[Create an object|Create an object]] <br/>
[[Delete an object|Delete an object]] }}

View File

@@ -0,0 +1,25 @@
[[Property:title|Merging radio button groups]]
[[Property:weight|0]]
If the current [[Object editor|object editor]] contains an <eiffel>EV_CONTAINER</eiffel> [[EiffelBuild Notation|object]] , then the following control will be available:
[[Image:empty-radio-merge]]
With this control, you can merge two or more instances of <eiffel>EV_CONTAINER</eiffel> together, so that any <eiffel>EV_RADIO_BUTTON</eiffel> contained are grouped.
==Merging==
To create a new merge, [[EiffelBuild Notation|pick]] an [[EiffelBuild Notation|object]] of type <eiffel>EV_CONTAINER</eiffel>, and [[EiffelBuild Notation|drop]] it anywhere on the control. This will merge the radio button group of the <eiffel>EV_CONTAINER</eiffel> referenced in the object editor, to the transported one. Each merge, will show up as a new item in the control.
{{note| '''Note''': Container objects may only be grouped once, and as such, you will not be permitted to add an [[EiffelBuild Notation|object]] that is already contained in the list. }}
==Unmerging==
To unmerge a container [[EiffelBuild Notation|object]] from a group, [[EiffelBuild Notation|pick]] the representation of that [[EiffelBuild Notation|object]] from the list, and [[EiffelBuild Notation|drop]] on [[Image:icon-delete-small-color]] . This will unmerge the [[EiffelBuild Notation|object]] from the current group of containers.
==Locating group member==
To locate the [[EiffelBuild Notation|object]] referenced by a list item in the control, left click the item that you wish to locate. This will display the representation of the associated [[EiffelBuild Notation|object]] within the [[Layout constructor|layout constructor]] , and the associated icon will be animated for a short period of time.

View File

@@ -0,0 +1,22 @@
[[Property:title|Positioning fixed children]]
[[Property:weight|2]]
If the current [[EiffelBuild Notation|object]] in the object editor is of type <eiffel>EV_FIXED</eiffel>, a button marked "position children..." will be contained in the object editor. Click this button, to display the following window:
[[Image:fixed-child-positioner]]
* '''Moving''' - Press and hold the left mouse button within the selected child, and move the mouse.
* '''Resizing''' - Move the mouse over the border of the child, until the cursor changes to a resize cursor, then press and hold the left mouse button to re-size the child.
{{note| '''Note''': As placing a child in an <eiffel>EV_FIXED</eiffel> does not modify the size of the child, it is possible that some children have a size of 0x0 pixels, and hence do not show up in the diagram. In this case, there will be the following displayed in the status bar "Widget is 0x0 pixels, click HERE to enlarge". If you subsequently click on the status bar, then the widget will be enlarged to a more useful size. }}
==Grid Properties==
The grid properties are displayed in the bottom right hand side of the window. You may modify the following attributes:
* '''Snap to grid''' - Select this option if you wish all widget coordinates to be snapped to the grid displayed in the window.
* '''Visible''' - If selected, then the grid is visible.
* '''Grid size''' - The spacing between grid elements in pixels.
When you have finished manipulating the children of the table, click the button marked "Done" to close the dialog.

View File

@@ -0,0 +1,17 @@
[[Property:title|Positioning table children]]
[[Property:weight|1]]
If the current [[EiffelBuild Notation|object]] in the object editor is of type <eiffel>EV_TABLE</eiffel>, a button marked "position children..." is contained in the object editor. Click this button, to display the following window:
[[Image:table-child-positioner]]
Each of the children are displayed on a grid representing the table cells that each occupies (by default 1x1). To manipulate a child of the table, click the left mouse button inside the desired child, and it will be highlighted in red. You may the manipulate the selected child in the following ways:
* '''Moving''' - Press and hold the left mouse button within the selected child, and move the mouse.
* '''Resizing''' - Move the mouse over the border of the child, until the cursor changes to a resize cursor, then press and hold the left mouse button to re-size the child.
{{note| '''Note''': Each child, may only occupy a unique set of cells within the table, and if you attempt to move or re-size a child to an invalid position, it will be displayed in gray. }}
When you have finished manipulating the children of the table, click the button marked "Done" to close the dialog.

View File

@@ -0,0 +1,40 @@
[[Property:title|Type selector]]
[[Property:weight|4]]
The type selector contains all the available Vision2 types supported by EiffelBuild. These are the basic building blocks for your system.
[[Image:type-selector]]
The types are organized into three groups - Primitives, Containers and Items. All types that may be used in EiffelBuild have a text in uppercase, corresponding to their type in [[EiffelVision Introduction|EiffelVision2]] . For example, looking at the screenshot above, the <eiffel>BUTTON</eiffel> item represents an <eiffel>EV_BUTTON</eiffel>, and the <eiffel>EV_COMBO_BOX</eiffel> item represents <eiffel>EV_COMBO_BOX</eiffel>.
{{note| '''Note''': The types available in the type selector are fixed, and cannot be modified. Almost all [[EiffelVision Introduction|EiffelVision2]] components are available. }}
==Creating a new object==
[[EiffelBuild Notation|Objects]] are the building blocks used in EiffelBuild to construct your interface. To create a new [[EiffelBuild Notation|object]] for use in your system, [[EiffelBuild Notation|pick]] the type corresponding to the type of object you wish to create,and [[EiffelBuild Notation|drop]] onto an [[EiffelBuild Notation|object]] representation. If an object is full, or does not allow other objects of the new type to be contained, then you will not be able to [[EiffelBuild Notation|drop]] on it. <br/>
For example, if you have just started a new project, [[EiffelBuild Notation|pick]] HORIZONTAL_BOX from the type selector, and drop it on the <eiffel>EV_TITLED_WINDOW</eiffel> [[EiffelBuild Notation|object]] displayed in the [[Layout constructor| layout constructor]] . This will build you a new [[EiffelBuild Notation|object]] of type <eiffel>EV_HORIZONTAL_BOX</eiffel>, parented in the window. If you then [[EiffelBuild Notation|pick]] a BUTTON from the type selector, you will not be able to [[EiffelBuild Notation|drop]] it on the <eiffel>EV_TITLED_WINDOW</eiffel>, as a window may only contain one child and is therefore currently full. You may however, [[EiffelBuild Notation|drop]] on the <eiffel>EV_HORIZONTAL_BOX</eiffel> object you had just created, as the box is empty, and has space for multiple children. Doing so, will create a new [[EiffelBuild Notation|object]] of type <eiffel>EV_BUTTON</eiffel>, parented in the box.
This shows how simple it is to Build new [[EiffelBuild Notation|objects]] in EiffelBuild, you just need access to the parent [[EiffelBuild Notation|object]] to [[EiffelBuild Notation|drop]] the selected type into.
You may drop an object directly from the Type Selector into the [[Widget selector|widget selector]] which creates the object as a "top level object" ensuring that upon generation, it is represented by an individual set of classes. These top level objects may then be re-used within your interface as desired.
{{note| '''Note''': To understand the types accepted, and the capacity of objects, you should consult the [[EiffelVision Introduction|EiffelVision2]] library reference. }}
==Changing the type of an existing object==
Why would you want to change the type of an existing [[EiffelBuild Notation|object]] , when you could just delete it and create a new [[EiffelBuild Notation|object]] ?
Imagine you have spent some time constructing a complicated interface. You have an EV_VERTICAL_BOX with children many levels deep. You realize that you wanted the <eiffel>EV_VERTICAL_BOX</eiffel> to be of type <eiffel>EV_HORIZONTAL_BOX</eiffel>. If you delete the object, all children contained will also be deleted, which in this case, is not what you want. Changing the type of the object does actually delete the object internally, but will automatically re-parent all of its children into the new object.
To perform a type change, [[EiffelBuild Notation|pick]] the [[EiffelBuild Notation|object]] that you wish to change, and [[EiffelBuild Notation|drop]] it on an item in the type selector representing the desired new type. All existing children of the old [[EiffelBuild Notation|object]] will be automatically re-parented in the new object.
The following rules govern if the type of an existing object may be changed to a new type:
* The parent of the existing [[EiffelBuild Notation|object]] must accept children of type corresponding to the new type.
* The new type must be able to accept all of the existing [[EiffelBuild Notation|objects]] children.
{{seealso| '''See Also''' <br/>
[[Layout constructor|Layout constructor]] <br/>
}}

View File

@@ -0,0 +1,59 @@
[[Property:title|Widget selector]]
[[Property:weight|9]]
The Widget Selector allows you to manage windows, dialogs and "top level" objects within the EiffelBuild project, with all windows accessible through this tool. Using the widget selector, you may add new windows to your project; delete windows; assign a root window (launched from the generated application); and group windows into directories. All objects contained in the Widget Selector are generated as individual classes at generation time. The Widget Selector has the following appearance:
[[Image:window-selector]]
==Adding Objects==
To add an Object to your project, [[EiffelBuild Notation|pick]] the object type from the [[Type selector|type selector]] , and [[EiffelBuild Notation|drop]] into the Widget Selector. There are two possible drop targets within the widget selector:
* '''The Widget Selector itself''' - The newly created object is added to the root directory of the project.
* '''A Directory node''' - The newly created object is added to the directory that was the target of the drop.
Both of these outcomes create a new object in your project that is to be generated as an individual class during code generation.
{{note| '''Note''': The selected object in the Widget Selector is automatically targeted as the root window of the [[Layout constructor|layout constructor]] , permitting building. You may not build directly into the representation of an object within the Widget Selector, as this must be performed within the [[Layout constructor|layout constructor]] or [[Builder window|builder window]] . }}
==Root Window==
The root window of a project is launched by the application class of the generated EiffelBuild project when executed. By assigning a window as a root, you ensure that it will be displayed on screen as the "root" window of the generated system when the system is launched.
The root window of the project is highlighted with a star, indicating that it is the root. Looking at the screenshot at the top of this page, the window named "main_window" is currently flagged as the root window of the project. To set a window as the root window of the project, select the window in the Widget Selector, and press the [[Image:icon-titled-window-main-small-color]] button displayed at the top of the Widget Selector.
==Directories==
The ability to add directories to your project permit organization of objects into sub groups as necessitated by your design. To add a directory to the project, select the [[Image:icon-new-cluster-small-color]] button displayed at the top of the Widget Selector, which displays the following dialog, prompting for the name of the directory to add:
[[Image:new-directory-dialog]]
Enter a unique name that is not already in use, and select "OK" to add the directory to your project. The newly added directory is then visible, as a node in the Widget Selector.
{{note| '''Note''': Creating a new directory in the Widget Selector causes the actual directory on the disk to be created immediately. }}
You may insert objects into a directory, or move an object between directories by [[EiffelBuild Notation|picking]] the object from its representation in the Widget Selector, and [[EiffelBuild Notation|dropping]] on the desired directory. Each object contained in the Widget Selector is generated as a seperate class and the parent directory is used as the generated location on disk.
{{note| '''Note''': If you move an object between directories within an EiffelBuild project that has already generated the Eiffel code for that object, the code files are moved immediately on the disk. }}
Directories may be nested as deeply as required, and the following buttons are available to help with directory nesting:
* [[Image:directory-search-small]] Selecting this button recursively adds all directories from the current project location to the project.
* [[Image:icon-show-hide-directory-color]] Selecting this button causes all directories included within the project that do not contain one or more objects to be hidden/shown within the Widget Selector.
Note that any directories that do not contain objects or have object nested within their structure recursively are displayed grayed out to indicate that there are no objects within.
==Expanding==
The [[Image:icon-expand-all-small-color]] button displayed at the top of the Widget Selector expands all nodes contained.
==Client Representations==
All objects within the Widget Selector that are used as clients within other object structures have client information displayed as subnodes of their representation, as illustrated in the following screenshot:
[[Image:images/eiffelbuild/screenshots/widget_selector_clients.png]]
The OK_CANCEL_BUTTONS object is used is used in two different places within the project: once within INPUT_DIALOG and once within MAIN_WINDOW. If you select the tree node representing the instance of OK_CANCEL_BUTTONS within MAIN_WINDOW, the MAIN_WINDOW is targetted to the [[Type selector|type selector]] with the instance of the OK_CANCEL_BUTTONS object selected.
To use an instance of a widget contained within the Widget Selector as a client, simply pick the representation of the object and drop into the desired parent object within the [[Type selector|type selector]]
{{seealso| '''See also''': <br/>
[[Layout constructor|Layout constructor]] }}

View File

@@ -0,0 +1,60 @@
[[Property:title|EiffelBuild Version History]]
[[Property:weight|2]]
==6.2 Release==
No changes.
==6.1 Release==
No changes.
==6.0 Release==
* Code generation includes the facility of closing the application when last window is closed.
* The EiffelBuild binary has been renamed into '''esbuilder'''.
* Fixed crash when generating code which included a combo box in read-only mode.
* Fixed bug#12920 where pressing a digit while dropping was not adding x-time the selected widgets (where x is the digit pressed).
* Fixed bug#12210 where pixmaps set on a menu would be incorrectly displayed in the generated executable (The last added one will always be shown for all menu entries with a pixmap).
* Fixed bug#11878 where EiffelBuild would crash when saving a project just after removing an event.
* Fixed bug#11738 where EiffelBuild would crash when picking and dropping a top level widget into the Generate button.
==5.7 Release==
* Fixed positioning bug when moving items within their current parent by dropping on another item in that parent with the shift key held down.
* Fixed bug where modifying the "User can resize" property of a window while the tools were always shown on top stopped the tools from being shown on top.
* Added support for multi-line tooltips.
* Added support for `is_item_expanded' from EV_SPLIT_AREA.
* Added the ability to specify a directory for generation, into which location all files are to be generated.
* Event selection dialogs now contain the name of the object to which they refer in their title for cases where multiple dialogs are open simultaneously
* The project settings dialog is now completely navigatable via the keyboard on Windows platforms.
* Added support for Ctrl+Z and Ctrl+Y to navigate through the history.
* The font selection dialog now shows the currently selected font when displayed.
* Deleting an object that is contained within an object editor now clears the contents of the object editor.
* Preferences window now has the focus when displayed so it is fully navigatable via the keyboard.
* Code generation improved to allow the modifying of constants and subsequent update of the interface, permitting multiple languages to be supported.
==5.6 Release==
* Added support for the generation of any widget as a class. You now may place widgets within the "Widget Selector" to enable this. The "Widget Selector" is simply the old "Widget Selector" renamed.
* Added clipboard functionality, permitting the copying/pasting of objects.
* Added support for new constant types: Font and Color.
==5.5 Release==
* Added support for EV_RICH_TEXT which has been added to EiffelVision2.
* Notebook item texts may now be set to string constants.
* Better support for corrupt installations with warning dialogs now displayed.
* Fixed bug with generated code for notebooks often hiding the first item when they were actually displayed.
==5.4 Release==
* Added support for multiple windows, including dialogs.
* Added support for constants of type Integer, String, Directory and Pixmap.
* New tool, "Widget Selector" added to handle organization of windows, including the ability to define subdirectories in a project, and group windows accordingly.
* Tip of the day dialog added.
* Recent projects are now available from the "File" menu.
* The contents of EiffelBuild projects may now be imported.
* The ability to reset the minimum dimensions of widgets have been added. In the previous version, it was not possible to complete undo the effects of setting a widgets minimum size.
* Preferences added, which allow you to customize the default behavior of EiffelBuild. For example, dialogs may be displayed or hidden as desired.
* The layout of EiffelBuild and its tools is now maintained between sessions.
* Docking added, permitting the re-ordering of particular tools within the interface, including making them "float" externally.
* Smarter code generation options, permitting only named attributes to be exported.

View File

@@ -0,0 +1,16 @@
[[Property:title|EiffelBuild]]
[[Property:weight|0]]
Type: Tool <br/>
Platform: Any <br/>
Version: 5.4 <br/>
Availability: Student and Enterprise versions.
See:
* [[EiffelBuild Introduction|Introduction]]
* [[EiffelBuild How To's|How To's]]
* [[EiffelBuild Reference|Reference]]
* [[EiffelBuild Version History|Version History]]

View File

@@ -0,0 +1,31 @@
[[Property:title|Accelerator Sample]]
[[Property:weight|0]]
[[Image:accelerator|accelerator]] <br/>
<br/>
==Compiling==
* Launch EiffelStudio.
* Click '''Add project'''
* Browse to ''$ISE_EIFFEL\examples\vision2\accelerator\''.
* Choose ''accelerator.ecf''
* Choose the location where the project will be compiled, by default the same directory containing the configuration file.
* Click '''OK'''.
==Running==
After launching the application, you will see a window displayed with a similar appearance to the one above. When the window has the focus, the key combination Ctrl + Q will exit the application.
==Under the Hood==
An EV_ACCELERATOR is created and associated with the EV_TITLED_WINDOW used for the main window of the application. The association is made by adding the accelerator to the accelerators list of the window.
This sample contains the following class:
* ACCELERATOR
{{seealso| '''See Also''' <br/>
[[ref:/libraries/vision2/reference/ev_accelerator_chart|EV_ACCELERATOR]] <br/>
[[ref:/libraries/vision2/reference/ev_key_chart|EV_KEY]] <br/>
}}

View File

@@ -0,0 +1,32 @@
[[Property:title|Cursor Sample]]
[[Property:weight|1]]
[[Image:cursor-test|cursor_test]] <br/>
<br/>
==Compiling==
* Launch EiffelStudio.
* Click '''Add project'''
* Browse to ''$ISE_EIFFEL\examples\vision2\cursor\''.
* Choose ''cursor.ecf''
* Choose the location where the project will be compiled, by default the same directory containing the configuration file.
* Click '''OK'''.
==Running==
After launching the application, you will see a window displayed with a similar appearance to the one above. Selecting "File", "Close" or pressing the close icon at any time will exit the application.
To the right hand side of the window you will see an EV_MULTI_COLUMN_LIST containing rows, each with an associated EV_PIXMAP. If you select one of the rows of the list, then press the button marked "Apply", the cursor displayed when over the label displayed to the right hand side of the window will be pixmap of the currently selected list row.
==Under the Hood==
The pixmaps used in the EV_MULTI_COLUMN_LIST were standard pixmaps provided with vision2, accessible through EV_STOCK_PIXMAPS. set_pixmap was used to set the EV_PIXMAP of the EV_MULTI_COLUMN_LIST_ROW. An agent was added to the select_actions of the EV_BUTTON which calls set_pointer_style on the desired widget.
This sample contains the following class:
* CURSOR_TEST

View File

@@ -0,0 +1,37 @@
[[Property:title|Gauges Sample]]
[[Property:weight|2]]
[[Image:gauges|gauges]] <br/>
<br/>
==Compiling==
* Launch EiffelStudio.
* Click '''Add project'''
* Browse to ''$ISE_EIFFEL\examples\vision2\gauges\''.
* Choose ''gauges.ecf''
* Choose the location where the project will be compiled, by default the same directory containing the configuration file.
* Click '''OK'''.
==Running==
After launching the application, you will see a window displayed with a similar appearance to the one above. The spin buttons at the top of the window control the current minimum, maximum and value of the three gauges displayed below. Modifying the values of the spin buttons will alter the three gauges in real time. Also, if you interact with one of the three gauges, any change in one, will be reflected in the others and in the spin buttons.
==Under the Hood==
The change_actions of each EV_GAUGE are used to synchronize all of the gauges.
This sample contains the following class:
* GAUGES
{{seealso| '''See Also''' <br/>
EV_GAUGE <br/>
EV_SCROLL_BAR <br/>
EV_RANGE <br/>
EV_PROGRESS_BAR <br/>
EV_SPIN_BUTTON }}

View File

@@ -0,0 +1,15 @@
[[Property:title|EiffelVision 2 Samples]]
[[Property:weight|3]]
Vision2 ships with a number of samples provided to demonstrate different aspects of the library. If you are a new vision2 user then it is suggested that you first compile and run the [[Widgets Sample|Widgets]] sample. This will demonstrate both the appearance and behavior of the available widgets.
The other samples provided are listed below:
* [[Accelerator Sample|Accelerator]] - Demonstrates the use of an [[ref:/libraries/vision2/reference/ev_accelerator_chart|EV_ACCELERATOR]] .
* [[Cursor Sample|Cursor]] - Demonstrates how to modify the displayed [[ref:/libraries/vision2/reference/ev_cursor_chart|EV_CURSOR]] for an [[ref:/libraries/vision2/reference/ev_widget_chart|EV_WIDGET]] .
* [[Gauges Sample|Gauges]] - Demonstrates different types of [[ref:/libraries/vision2/reference/ev_gauge_chart|EV_GAUGE]] .
* [[Standard_dialogs Sample|Standard_dialogs]] - Demonstrates different types of [[ref:/libraries/vision2/reference/ev_standard_dialog_chart|EV_STANDARD_DIALOG]] .
* [[Viewport Sample|Viewport]] - Demonstrates [[ref:/libraries/vision2/reference/ev_viewport_chart|EV_VIEWPORT]] .

View File

@@ -0,0 +1,28 @@
[[Property:title|Standard_dialogs Sample]]
[[Property:weight|3]]
[[Image:standard-dialogs|Standard_dialogs]] <br/>
<br/>
==Compiling==
* Launch EiffelStudio.
* Click '''Add project'''
* Browse to ''$ISE_EIFFEL\examples\vision2\standard_dialogs\''.
* Choose ''standard_dialogs.ecf''
* Choose the location where the project will be compiled, by default the same directory containing the configuration file.
* Click '''OK'''.
==Running==
After launching the application, you will see a window displayed with a similar appearance to the one above. If you select an item from the "Standard Dialog" menu, a dialog of that type will be displayed. Selecting "Exit" from the "File" menu will exit the application.
==Under the Hood==
This sample contains the following class:
* STANDARD_DIALOGS

View File

@@ -0,0 +1,36 @@
[[Property:title|Viewport Sample]]
[[Property:weight|4]]
[[Image:viewport|viewport]] <br/>
<br/>
==Compiling==
To compile the example:
* Launch EiffelStudio.
* Click '''Add project'''
* Browse to ''$ISE_EIFFEL\examples\vision2\viewport\''.
* Choose ''viewport.ecf''
* Choose the location where the project will be compiled, by default the same directory containing the configuration file.
* Click '''OK'''.
==Running==
After launching the application, you will see a window displayed with a similar appearance to the one above. Modifying the values of the spin buttons will alter the position of the pixmapped button, relative to the viewport in which it is contained.
==Under the Hood==
The features set_x_offset and set_y_offset are used to modify the position of the EV_VIEWPORT relative to the EV_BUTTON contained within.
This sample contains the following class:
* VIEWPORT
{{seealso| '''See Also''' <br/>
EV_VIEWPORT <br/>
EV_SPIN_BUTTON <br/>
[[ref:/libraries/vision2/reference/ev_button_chart|EV_BUTTON]] <br/>
}}

View File

@@ -0,0 +1,44 @@
[[Property:title|Widgets Sample]]
[[Property:weight|-1]]
[[Image:widgets|widgets]] <br/>
<br/>
==Compiling==
* Launch EiffelStudio.
* Click '''Add project'''
* Browse to ''$ISE_EIFFEL\examples\vision2\widgets\''.
* Choose ''widgets.ecf''
* Choose the location where the project will be compiled, by default the same directory containing the configuration file.
* Click '''OK'''.
==Running==
After launching the application, you will see a window displayed with a similar appearance to the one above. You may exit the application at any time, by clicking on the close icon, or you may select "exit" from the "File" menu. Selected "Help", "about" displays a dialog with details about the application.
The left hand side of the main window contains a tree, showing the widgets available within vision2. If you select one of these widgets in the tree, then the type of widget you selected will be displayed in the middle of the main_window. Controls will also the be available to the right hand side of the widget, which allow you to modify its state. These controls do not represent all the available feature of the widget, but demonstrate many of the most common. The text area below the currently selected widget displays the events that have occurred on the widget. Only those events inherited by EV_WIDGET are displayed.
==Under the Hood==
This sample contains the following classes:
* ABOUT_DIALOG
* COLORIZABLE_CONTROL
* CONTAINER_CONTROL
* DESELECTABLE_CONTROL
* DRAWABLE_CONTROL
* GAUGE_CONTROL
* ITEM_LIST_CONTROL
* MAIN_WINDOW
* PIXMAPABLE_CONTROL
* SELECTABLE_CONTROL
* SENSITIVE_CONTROL
* TEXT_COMPONENT_CONTROL
* TEXTABLE_CONTROL
* WIDGET_CONTROL
* WIDGETS

View File

@@ -0,0 +1,62 @@
[[Property:title|EiffelVision Introduction]]
[[Property:weight|0]]
The EiffelVision library offers an object-oriented framework for graphical user interface (GUI) development. Using EiffelVision, developers can access all necessary GUI components, called [[Widgets|widgets]] (buttons, windows, list views) as well as truly graphical elements such as points, lines, arcs, polygons and the like -- to develop a modern, functional and good-looking graphical interactive application.
EiffelVision has played a major role at Eiffel Software and provided numerous Eiffel projects with a powerful, portable graphics development platform. EiffelStudio is totally reliant on EiffelVision for its graphical elements and overall interaction with the user.
* [[EiffelVision Interface Content|Content]]
* [[EiffelVision 2 Samples|Samples]]
* [[ref:libraries/vision2/reference/index|Reference]]
==Scope==
The EiffelVision library addresses all the major needs of developers of systems supporting modern graphical interfaces. EiffelVision runs on Microsoft Windows and all major variations of Unix (including Linux). All versions are fully source-compatible; with only a recompile, applications will run on every supported platform with the native look-and-feel.
EiffelVision provides an effective way of building advanced graphical applications using user interface standards and toolkits (such as Microsoft Windows and GTK) without having to learn the details of the toolkits. Instead, you can use EiffelVision to work entirely in terms of high level abstractions representing windows, buttons, labels, graphical figures, menus, buttons etc., and apply clearly understandable operations to the corresponding objects.
==Architecture==
EiffelVision relies on a two-tiered architecture illustrated by the following figure.
[[Image:vision2--figure1]]
The two tiers play complementary roles:
* At the top level, EiffelVision provides fully portable graphics.
* At the lower level, platform-specific libraries cover the graphical mechanisms of graphics platforms such as Windows and GTK.
The lower tier serves for the implementation of the upper tier, but can also be used independently. For example [[WEL Introduction|WEL]] has had a resounding success with Windows developers who need an advanced mechanism for building Windows-specific graphical applications, taking advantage of every facility of the Windows API (Application Programming Interface) and of the Eiffel approach, but do not need portability on the client side. The GEL library is a '''wrapper''' library, automatically generated from the entire GTK API by a tool named '''The Gote Converter'''.
==Features==
As stated before, the library has undergone some drastic changes since the previous release. Names have been changed to improve consistency. Contracts are added wherever possible. Following is a summary of the other re-engineered aspects of the library:
* Taking full advantage of the '''agent''' mechanism of Eiffel, [[Events|events]] are now triggered through '''action sequences''' (lists of actions) that will be executed in order. This system does not require separate classes to be written for each event, however the command pattern can still be used if desired.
* The [[EiffelVision Pick and Drop|pick-and-drop]] mechanism now relies on the Eiffel type system. A '''stone''' (some transportable object) is now any Eiffel class and can always be dropped on a widget that accepts the type (or a more general type) of that stone.
* [[Containers|containers]] ( [[Widgets|widgets]] that contain other [[Widgets|widgets]] ) are now derived from [[EiffelBase Introduction|EiffelBase]] classes. For example you can now insert [[Widgets|widgets]] in any position and iterate over them.
==Design==
EiffelVision provides programmers with high-level classes, that provide all mechanism and data structures needed to build advanced user interfaces for deployment on almost all platforms without having to worry about detailed requirements of toolkits.
The abstract design has been derived from an analysis of user interfaces. Therefore we have classes with names like MENU, WINDOW, BUTTON, LINE or POLYGON. The features of these classes are simple, clearly defined properties or commands, like the feature `minimize' (a command) on WINDOW or `text' (a property of type STRING) on BUTTON.
{{note| '''Note''': all class names in EiffelVision are pre-pended with EV_ to avoid name clashes with existing classes. BUTTON hence becomes <eiffel>EV_BUTTON</eiffel>, etc. }}
==Properties==
When talking about a property of a class, like `text', in fact we are talking about multiple features. One is a query of the state of the property, in this case simply the query `text'. The other is the set-routine, which is by convention named `set_text' taking exactly one argument of the type of property. A property can be read-only, which means that it cannot be set by clients of the class.
<code>
text: STRING
set_text (a_text: STRING) is ...
</code>
Boolean properties have a different convention. Instead of one set-routine, it has one enable-routine and one disable-routine. The first one sets the property to true, the second to false. This has been done like this because sometimes these enable/disable features have trivial equivalents, for example for feature `enable_visible' a clearer name is `show'.
<code>
is_sensitive: BOOLEAN
enable_sensitive is ...
disable_sensitive is ...
</code>
==Implementation==
For flexibility, EiffelVision is built using the bridge pattern. This means that every platform-dependent component of the library consist of two classes, plus an implementation class for each platform (currently two). One is the <eiffel>interface</eiffel>. All the features of interfaces do nothing except delegate the call to the implementation object which is coupled to it. This object has the static type of the implementation-interface with the name of the interface class, with _I appended to it. From this implementation-interface, implementation classes inherit to implement platform-specific features.

View File

@@ -0,0 +1,24 @@
[[Property:title|Events]]
[[Property:weight|4]]
This cluster contains classes for event handling within Vision2.
==What is an event?==
An event is considered to be an external action that occurs during a program's execution. Correctly dealing with events is an important part of developing a Vision2 application. For example, if a user clicks on a button, you will want to respond to this event by calling a routine that deals with the request. Vision2 contains action sequences for all kinds of widget events. To view the kind of events available to every widget, click [[ref:libraries/vision2/reference/ev_widget_action_sequences_chart|here]] .
==How do I connect to an event?==
Every widget and item has an action sequence associated with it that relates to some kind of event. For example an [[ref:libraries/vision2/reference/ev_button_chart|EV_BUTTON]] has a select_actions action sequence. This gets fired when the user clicks/selects the button. To have a procedure called on this event, you need to create an agent based on this procedure, and then add this to the action sequence (via extend). For a more detailed description of agents and their uses click [[11 Agents|here]] .
An example of adding an agent to an action_sequence is as follows.
<code>
button.select_actions.extend (agent print ("Button Clicked!%N"))
</code>
All Vision2 action sequences inherit [[ref:libraries/vision2/reference/ev_action_sequence_chart|EV_ACTION_SEQUENCE]] and when it is called, all of the agents held within are fired, thus calling all of the procedures represented by the agents. The signature of any agent that you place in an action sequence must conform to those of the action sequences actual generic parameter.
When you want an agent to be called from a certain action sequence and the signatures do not match, you may use [[ref:libraries/vision2/reference/ev_action_sequence_chart|force_extend]] . This will call your agent but has no guarantees on the arguments passed to your procedure.

View File

@@ -0,0 +1,150 @@
[[Property:title|Figures]]
[[Property:weight|7]]
The EiffelVision figure cluster can be considered a high-level way of drawing on an [[ref:libraries/vision2/reference/ev_drawable_chart|EV_DRAWABLE]] descendant. Here are some advantages:
* The model is separated from the representation by using projectors that take a world of figures and project it to any device, not just a drawing area.
* Instead of drawing with static API's like draw_line, real figure objects are used that can move, change color or morph.
* For projection devices that allow this, events may be caught and fired through the appropriate figure object.
==Figure classes==
Every basic figure class inherits from [[ref:libraries/vision2/reference/ev_atomic_figure_chart|EV_ATOMIC_FIGURE]] . An atomic figure has the property of having a representation. [[ref:libraries/vision2/reference/ev_figure_group_chart|EV_FIGURE_GROUP]] on the other hand does not but is a collection of figures. On the top of those two stands [[ref:libraries/vision2/reference/ev_figure_chart|EV_FIGURE]] as common ancestor. As [[ref:libraries/vision2/reference/ev_figure_group_chart|EV_FIGURE_GROUP]] is a collection of EV_FIGUREs, it can contain subgroups.
As top-level group of a world of figures you must use [[ref:libraries/vision2/reference/ev_figure_world_chart|EV_FIGURE_WORLD]] . It inherits from [[ref:libraries/vision2/reference/ev_figure_group_chart|EV_FIGURE_GROUP]] but adds some features for grid and background color.
===Figures===
{| border="1"
|-
| class
| open/closed
| points
| description
|-
| [[ref:libraries/vision2/reference/ev_figure_arc_chart|EV_FIGURE_ARC]]
| open
| 2
| a segment of an open ellipse
|-
| [[ref:libraries/vision2/reference/ev_figure_dot_chart|EV_FIGURE_DOT]]
| open
| 1
| a single point
|-
| [[ref:libraries/vision2/reference/ev_figure_ellipse_chart|EV_FIGURE_ELLIPSE]]
| closed
| 2
| ellipse inside imaginary rectangle
|-
| [[ref:libraries/vision2/reference/ev_figure_equilateral_chart|EV_FIGURE_EQUILATERAL]]
| closed
| 2
| a figure with any number of sides of the same length
|-
| [[ref:libraries/vision2/reference/ev_figure_line_chart|EV_FIGURE_LINE]]
| open
| 2
| a straight line between two points
|-
| [[ref:libraries/vision2/reference/ev_figure_picture_chart|EV_FIGURE_PICTURE]]
| open
| 1
| an image positioned by its top-left point
|-
| [[ref:libraries/vision2/reference/ev_figure_pie_slice_chart|EV_FIGURE_PIE_SLICE]]
| closed
| 2
| a part of a closed ellipse
|-
| [[ref:libraries/vision2/reference/ev_figure_polygon_chart|EV_FIGURE_POLYGON]]
| closed
| *
| a figure defined by any number of points
|-
| [[ref:libraries/vision2/reference/ev_figure_polyline_chart|EV_FIGURE_POLYLINE]]
| open
| *
| a figure consisting of any number of connecting lines
|-
| [[ref:libraries/vision2/reference/ev_figure_rectangle_chart|EV_FIGURE_RECTANGLE]]
| closed
| 2
| figure with four sides
|-
| [[ref:libraries/vision2/reference/ev_figure_star_chart|EV_FIGURE_STAR]]
| open
| 2
| any number of lines emerging from a center point
|-
| [[ref:libraries/vision2/reference/ev_figure_text_chart|EV_FIGURE_TEXT]]
| open
| 1
| a string positioned by its top-left point displayed in the specified font
|}
A closed figure is a figure that has some area enclosed when drawn that can optionally be filled with a color. Closed figures inherit [[ref:libraries/vision2/reference/ev_closed_figure_chart|EV_CLOSED_FIGURE]] which gives them the property fill_color. Open figures inherit [[ref:libraries/vision2/reference/ev_atomic_figure_chart|EV_ATOMIC_FIGURE]] directly just as [[ref:libraries/vision2/reference/ev_closed_figure_chart|EV_CLOSED_FIGURE]] .
===Points===
Central in the design of the figures are points. Figures are built up as much from points as possible. For example, an ellipse is not a center point with two radii, but the biggest fitting ellipse inside an imaginary rectangle, so of two points.
As you can see in the table above, each figure has a certain number of points. These values can be 1, 2 or * (any number). For each value there is a class the figure inherits from. These classes are:
* 1 (a figure has one point): [[ref:libraries/vision2/reference/ev_single_pointed_figure_chart|EV_SINGLE_POINTED_FIGURE]] .
* 2 (a figure has two points): [[ref:libraries/vision2/reference/ev_double_pointed_figure_chart|EV_DOUBLE_POINTED_FIGURE]] .
* * (a figure has zero or more points): [[ref:libraries/vision2/reference/ev_multi_pointed_figure_chart|EV_MULTI_POINTED_FIGURE]] .
These classes offer features to handle the given number of points. [[ref:libraries/vision2/reference/ev_single_pointed_figure_chart|EV_SINGLE_POINTED_FIGURE]] offers the feature:
<code> point: EV_RELATIVE_POINT</code>
[[ref:libraries/vision2/reference/ev_double_pointed_figure_chart|EV_DOUBLE_POINTED_FIGURE]] inherits [[ref:libraries/vision2/reference/ev_single_pointed_figure_chart|EV_SINGLE_POINTED_FIGURE]] for its first point, which is renamed to <eiffel>point_a</eiffel>. It adds <eiffel>point_b</eiffel>, so it has the features:
<code>
point_a: EV_RELATIVE_POINT
point_b: EV_RELATIVE_POINT
</code>
[[ref:libraries/vision2/reference/ev_multi_pointed_figure_chart|EV_MULTI_POINTED_FIGURE]] internally holds an array of points. Its most important feature is:
<code>
i_th_point (i: INTEGER): EV_RELATIVE_POINT
</code>
===Relative point===
The points that the figures use are of type [[ref:libraries/vision2/reference/ev_relative_point_chart|EV_RELATIVE_POINT]] . Each point is relative to another point, which is also relative. Each point is a set of coordinates and a reference point. The absolute coordinates are calculated only when needed by adding the absolute coordinates of the reference point to the relative coordinates.
==Figure worlds==
In order to put the figures you want to display in a context, you have to insert them in a figure world object, an instance of [[ref:libraries/vision2/reference/ev_figure_world_chart|EV_FIGURE_WORLD]] . This is a descendant of [[ref:libraries/vision2/reference/ev_figure_group_chart|EV_FIGURE_GROUP]] and hence works in the same way. This figure world is later associated with one or more projectors.
[[ref:libraries/vision2/reference/ev_figure_world_chart|EV_FIGURE_WORLD]] adds a number of features to [[ref:libraries/vision2/reference/ev_figure_group_chart|EV_FIGURE_GROUP]] . These extra features are needed for the representation by a projector. One is the background color. This feature will be used to erase the canvas for a graphical projector in the specified color. The other features are to manage the grid.
==Projectors==
A projector is an object that knows what a figure world should look like. The figure world itself is not more than a hint towards its representation. For example, if a line is "20" long, this unit might mean pixels, miles, centimeters or whatever. It is up to the projector to interpret units. Also, color might be interpreted as gray scale. Typically, a projector will do the best possible job projecting the world to its device.
With EiffelVision come these projectors:
* [[ref:libraries/vision2/reference/ev_postscript_projector_chart|EV_POSTSCRIPT_PROJECTOR]]
* [[ref:libraries/vision2/reference/ev_drawing_area_projector_chart|EV_DRAWING_AREA_PROJECTOR]]
* [[ref:libraries/vision2/reference/ev_pixmap_projector_chart|EV_PIXMAP_PROJECTOR]]
The first one maps figure worlds to a postscript file. The other two are descendants of [[ref:libraries/vision2/reference/ev_widget_projector_chart|EV_WIDGET_PROJECTOR]] , and can project on widgets that inherit [[ref:libraries/vision2/reference/ev_drawable_chart|EV_DRAWABLE]] : [[ref:libraries/vision2/reference/ev_drawing_area_chart|EV_DRAWING_AREA]] and [[ref:libraries/vision2/reference/ev_pixmap_chart|EV_PIXMAP]] , eventually using double-buffering, which results in a more smooth animation but requires fast copying from memory to the video buffer (can be slow for a remote display).
==Events==
The other features of drawing area and widget is that they generate pointer events. These events can be translated by projectors to map the figure world. These projectors send the event to the appropriate figure. Every figure has all common pointer action sequences:
* <eiffel>pointer_motion_actions</eiffel>
* <eiffel>pointer_button_press_actions</eiffel>
* <eiffel>pointer_double_press_actions</eiffel>
* <eiffel>pointer_button_release_actions</eiffel>
* <eiffel>pointer_enter_actions</eiffel>
* <eiffel>pointer_leave_actions</eiffel>
* <eiffel>pick_actions</eiffel>
* <eiffel>conforming_pick_actions</eiffel>
* <eiffel>drop_actions</eiffel>
There are no events for keyboard focus and no key press events. In case you wish to use these events, use the ones of the pixmap or drawing area.
When using events, keep the z-order in mind. This is the order in which the figures are stacked in the world. The first item of a figure group is the figure that is the farthest away. This means that the figure is obscured by any figures which are in front of it, and events will also not be propagated to this figure in that case.
==Rotation and scaling==
The relative points also support rotation and scaling. These factors work just like coordinates, except scaling, which is multiplied instead of added in the chain of points. This means that when a relative point which is the root of a tree of several points is moved, the entire tree is moved, when it is scaled the entire tree is scaled and same for rotation.
The scaling factor is divided into a horizontal and vertical component. If the factor is 0.5, everything is displayed at half its size. The rotation factor is in radians.

View File

@@ -0,0 +1,18 @@
[[Property:title|EiffelVision Interface Content]]
[[Property:link_title|EiffelVision Library Reference Manual]]
[[Property:weight|1]]
EiffelVision 2 is a platform independent Graphical User Interface (GUI) library that allows easy, simultaneous development of Windowed applications for both Windows & Unix based platforms. Heavily relying on EiffelBase library, EiffelVision 2 has been designed primarily with ease of use in mind. By reusing EiffelBase structures, existing, as well as new Eiffel users will find EiffelVision to be surprising intuitive and easy to use. In no time, users will be producing good-looking Windowed application skeletons, of which will run on a multitude of platforms with no manipulation of code.
The EiffelVision 2 library includes the following interface clusters:
* A [[Kernel| kernel]] cluster that includes classes that are key to a Vision2 application. The main class being [[ref:libraries/vision2/reference/ev_application_chart| EV_APPLICATION]] which is the main entry point of all Vision2 applications.
* A [[Widgets| widgets]] cluster containing classes that used to create Vision2 widgets. Widgets are the visible objects that the user sees and interacts with on the desktop, examples of widgets are windows, buttons and labels.
* An [[Items| items]] cluster includes the classes needed to create items, items can be thought of as widgets that are contained within only a certain type of widget, such as an [[ref:libraries/vision2/reference/ev_list_chart| EV_LIST]] that may only contain objects of type [[ref:libraries/vision2/reference/ev_list_item_chart|EV_LIST_ITEM]] . Items provide an abstract way of dealing with an item widget's internal data structures and provide in many cases the same functionality that a widget does.
* An [[Events| events]] cluster containing classes that allow for user initiated events, such as the clicking of a button to be dealt with via the use of a linked list of agents ( [[ref:libraries/vision2/reference/ev_action_sequence_chart|EV_ACTION_SEQUENCE]] ). Agents can be thought of as an object that encapsulates a certain procedure. When a user clicks a button on the screen, the corresponding [[ref:libraries/vision2/reference/ev_button_chart| EV_BUTTON]] object has its associating pointer_button_press_actions fired and this in turn, fires all of the agents held within, thus calling all of the procedures represented by the agents. Every widget and item has a certain number of [[ref:libraries/base/reference/action_sequence_chart|ACTION_SEQUENCE]] objects that are linked with a certain type of event.
* A [[Properties| properties]] cluster contains classes that allow for the customization of Vision 2 widgets and items. Classes such as [[ref:libraries/vision2/reference/ev_colorizable_chart|EV_COLORIZABLE]] and [[ref:libraries/vision2/reference/ev_fontable_chart|EV_FONTABLE]] contain routines that allow for color and fonts to be altered for a widget or item respectively.
* A [[Support| support]] cluster includes classes that provide more professional touches to an application, whether these are keyboard shortcuts ( [[ref:libraries/vision2/reference/ev_accelerator_list_chart|EV_ACCELERATOR_LIST]] ) or graphical output ( [[ref:libraries/vision2/reference/ev_graphical_format_chart|EV_GRAPHICAL_FORMAT]] ) for drawable widgets such as [[ref:/libraries/vision2/reference/ev_pixmap_chart|EV_PIXMAP]] .
* A [[Figures| figures]] cluster that allows for the projection of two-dimensional shapes (figures) on to an [[ref:libraries/vision2/reference/ev_drawable_chart|EV_DRAWABLE]] or printer via the use of an [[ref:libraries/vision2/reference/ev_projector_chart|EV_PROJECTOR]] .
To see differences between released versions of EiffelVision, click [[Revisions and Bug Fixes|Here]]

View File

@@ -0,0 +1,52 @@
[[Property:title|Items]]
[[Property:weight|3]]
All Vision2 items inherit [[ref:libraries/vision2/reference/ev_item_chart|EV_ITEM]] .
==What is an item?==
A Vision2 item is an object that is used to display information within certain primitives. For example, [[ref:libraries/vision2/reference/ev_list_chart|EV_LIST]] may hold items of type [[ref:libraries/vision2/reference/ev_list_item_chart|EV_LIST_ITEM]] . All Vision2 items are descendants of [[ref:libraries/vision2/reference/ev_pixmapable_chart|EV_PIXMAPABLE]] meaning they can display an [[ref:libraries/vision2/reference/ev_pixmap_chart|EV_PIXMAP]] .
==Item holders==
Below is a structure showing the Vision2 components and the items that they accept. All the items types available in Vision2 are included:
* [[ref:libraries/vision2/reference/ev_list_chart|EV_LIST]] accepts items of type:
** [[ref:libraries/vision2/reference/ev_list_item_chart|EV_LIST_ITEM]]
* [[ref:libraries/vision2/reference/ev_combo_box_chart|EV_COMBO_BOX]] accepts items of type:
** [[ref:libraries/vision2/reference/ev_list_item_chart|EV_LIST_ITEM]]
* [[ref:libraries/vision2/reference/ev_window_chart|EV_WINDOW]] accepts items of type (Use set_menu_bar):
** [[ref:libraries/vision2/reference/ev_menu_bar_chart|EV_MENU_BAR]] accepts items of type:
*** [[ref:libraries/vision2/reference/ev_menu_chart|EV_MENU]] accepts items of type:
**** [[ref:libraries/vision2/reference/ev_menu_chart|EV_MENU]]
**** [[ref:libraries/vision2/reference/ev_menu_item_chart|EV_MENU_ITEM]]
**** [[ref:libraries/vision2/reference/ev_menu_separator_chart|EV_MENU_SEPARATOR]]
**** [[ref:libraries/vision2/reference/ev_radio_menu_item_chart|EV_RADIO_MENU_ITEM]]
**** [[ref:libraries/vision2/reference/ev_check_menu_item_chart|EV_CHECK_MENU_ITEM]]
* [[ref:libraries/vision2/reference/ev_multi_column_list_chart|EV_MULTI_COLUMN_LIST]] accepts items of type:
** [[ref:libraries/vision2/reference/ev_multi_column_list_row_chart|EV_MULTI_COLUMN_LIST_ROW]]
* [[ref:libraries/vision2/reference/ev_tool_bar_chart|EV_TOOL_BAR]] accepts items of type:
** [[ref:libraries/vision2/reference/ev_tool_bar_button_chart|EV_TOOL_BAR_BUTTON]]
** [[ref:libraries/vision2/reference/ev_tool_bar_radio_button_chart|EV_TOOL_BAR_RADIO_BUTTON]]
** [[ref:libraries/vision2/reference/ev_tool_bar_separator_chart|EV_TOOL_BAR_SEPARATOR]]
** [[ref:libraries/vision2/reference/ev_tool_bar_toggle_button_chart|EV_TOOL_BAR_TOGGLE_BUTTON]]
* EV_TREE accepts items of type:
** [[ref:libraries/vision2/reference/ev_dynamic_tree_item_chart|EV_DYNAMIC_TREE_ITEM]] accepts items of type:
*** [[ref:libraries/vision2/reference/ev_dynamic_tree_item_chart|EV_DYNAMIC_TREE_ITEM]]
*** [[ref:libraries/vision2/reference/ev_tree_item_chart|EV_TREE_ITEM]]
** [[ref:libraries/vision2/reference/ev_tree_item_chart|EV_TREE_ITEM]] accepts items of type:
*** [[ref:libraries/vision2/reference/ev_dynamic_tree_item_chart|EV_DYNAMIC_TREE_ITEM]]
*** [[ref:libraries/vision2/reference/ev_tree_item_chart|EV_TREE_ITEM]]

View File

@@ -0,0 +1,87 @@
[[Property:title|Kernel]]
[[Property:weight|1]]
The kernel cluster contains classes that provide functionality that are common to most Windowed application. These classes are considered the core, or kernel of any Vision2 application. The most important of these classes is [[ref:libraries/vision2/reference/ev_application_chart|EV_APPLICATION]] . This is used to initialize the graphical toolkit and event loop of your Vision2 application. Kernel also includes classes such as [[ref:libraries/vision2/reference/ev_timeout_chart| EV_TIMEOUT]] that calls procedures (via agents) at a set interval, and [[ref:libraries/vision2/reference/ev_color_chart| EV_COLOR]] which is used for coloring widgets and items. To start programming with Vision2, you first have to correctly initialize [[ref:libraries/vision2/reference/ev_application_chart|EV_APPLICATION]] .
==Launching your application with EV_APPLICATION - The heart of all Vision2 systems==
[[ref:libraries/vision2/reference/ev_application_chart|EV_APPLICATION]] is the basis for every Vision2 application and is considered the most important class in the library. It is responsible for initializing the underlying toolkit that is driving the windowing system on the platform that you decide to compile your system on. It also also where the main event loop that drives your application is executed.
{{note| '''Note:''' It is ''' not''' possible to create a Vision2 component unless an application exists (query [[ref:/libraries/vision2/reference/ev_environment_chart|EV_ENVIRONMENT]] ). }}
You may inherit [[ref:libraries/vision2/reference/ev_application_chart|EV_APPLICATION]] or use it as a client in order to create your vision2 application. A simple method of using EV_APPLICATION is as follows:
# Create an instance of EV_APPLICATION.
# Create one or more windows for your application.
# Launch the application.
An example of a Vision2 application using inheritance from [[ref:libraries/vision2/reference/ev_application_chart|EV_APPLICATION]] is shown below.
<code>
class
HELLOWORLD_APP
inherit
EV_APPLICATION
create
make
feature
make is
-- Create the application.
local
helloworld_window: EV_TITLED_WINDOW
do
default_create
create helloworld_window
helloworld_window.set_title ("Helloworld!")
helloworld_window.close_request_actions.extend (agent destroy)
helloworld_window.show
launch
end
end
</code>
This is the same Vision2 application but instead using <eiffel>[/libraries/vision2/reference/ev_application_chart.xml| EV_APPLICATION ]</eiffel> in a client/supplier relationship.
<code>
class
HELLOWORLD_APP
create
make
feature
make is
-- Create the Vision2 application with a helloworld window.
local
app: EV_APPLICATION
helloworld_window: EV_TITLED_WINDOW
do
create app
create helloworld_window
helloworld_window.set_title ("Helloworld!")
helloworld_window.close_request_actions.extend (agent app.destroy)
helloworld_window.show
app.launch
end
end
</code>
==What does Launch actually do?==
In Vision2, to launch an application means to pass control to the underlying graphical toolkit. Simply creating an application does not launch it. An explicit call to launch is required for the event processing to begin.
{{note| '''Note: '''A Vision2 system is event based. This means that you do not have control of the execution within a Vision2 system, but must respond appropriately to [[Events|events]] as they occur. Therefore, if you call launch on an [[ref:libraries/vision2/reference/ev_application_chart|EV_APPLICATION]] , the processing for the application will continue indefinitely unless you have provided a way to exit the application. It is essential to initialize your components correctly, so your application can be exited (call <eiffel>destroy</eiffel> on the application). }}
==Building your application skeleton==
Now that you have a basic application skeleton set up you can now go about
* [[Widgets|Creating widgets and setting their properties.]]
* [[Containers|Adding containers to your window(s), then place your created widgets in those containers.]]
* [[Events|Add code to respond to user actions with agents and action sequences.]]
Once you have learnt the basics of GUI programming within Vision2, you are well on the way to creating powerful multi-platform applications. The Application Programming Interface (API) of Vision2 has been designed in a way to ensure that the library is as intuitive, consistent and stylistic as possible. Heavy reuse of components from EiffelBase has been one of the main reasons that made this possible.

View File

@@ -0,0 +1,41 @@
[[Property:title|EiffelVision Pick and Drop]]
[[Property:weight|0]]
Pick and drop is a mechanism which allows data to be transported from a '''source''' object to a '''target'''. Any Vision2 object inheriting [[ref:libraries/vision2/reference/ev_pick_and_dropable_chart|EV_PICK_AND_DROPABLE]] can be used to transport or receive data.
==A simple pick and drop example==
Two necessary components for a pick and drop transport are a '''source''' and a '''target''', both of which must conform to [[ref:libraries/vision2/reference/ev_pick_and_dropable_chart|EV_PICK_AND_DROPABLE]] . The data that is to be transported is known as a '''pebble'''.
The following steps need to be undertaken to set up a simple pick and drop:
* Set the '''source''' by calling set_pebble.
* Set one or more '''targets''' by adding a function to their drop_actions. The arguments of the function must match the type of the '''pebble''' to be transported for the '''source''' otherwise the transport will not be permitted.
A simple example of this is demonstrated here:
<code>
button1.set_pebble ("A PND transport has occured%N")
button2.drop_actions.extend (agent print (?))
</code>
As print takes an argument of type [[ref:/libraries/base/reference/string_8_chart|STRING_8]] , button2 becomes a valid target for the pebble contained in button1. Right clicking the mouse pointer over the '''source''' will start the transport, and right clicking with the mouse pointer over a valid '''target''' will end the transport. The transport can be canceled anytime with a simple left click, just as you would do in EiffelStudio.
{{note| '''Note''': When a transport completes, the '''pebble''' that was transported is passed as an argument to all features in the '''targets'''drop_actions whose argument type matches the '''pebble''' }}
==Three different modes of transport==
There are three different modes of transport available for pick and drop. They are listed below with details of their use:
* Pick and Drop mode. <br/>
This is the default mode for pick and drop, but can be set with <eiffel>set_pick_and_drop_mode</eiffel>. Right clicking on a '''source''' starts the transport and right clicking on a valid '''target''' completes the transport. During execution, a band is drawn from the screen position where the pick started to the current mouse position. Pressing the left mouse button or the escape key during execution will end the transport.
* Drag and drop mode <br/>
This mode can be set with <eiffel>set_drag_and_drop_mode</eiffel>. Left clicking on a '''source''' starts the transport and releasing the left mouse button over a valid '''target''' completes the transport. During execution, a band is drawn from the screen position where the pick started to the current mouse position. Releasing the left mouse button or pressing the escape key during execution will end the transport.
* Target menu mode <br/>
This mode can be set with <eiffel>set_target_menu_mode</eiffel>. Right clicking on a '''source''' brings up a menu of all the valid drop '''targets''' in the system. Selecting one of these targets completes the transport.
==Accept and deny cursors==
When <eiffel>mode_is_pick_and_drop</eiffel> or <eiffel> mode_is_drag_and_drop</eiffel> then the shape of the mouse cursor changes to reflect whether the current GUI component below the mouse accepts the pebble or not. Calling <eiffel>set_accept_cursor</eiffel> allows you to customize this cursor used to represent a valid '''target''' while calling <eiffel>set_deny_cursor</eiffel> allows you to customize the cursor used for non valid '''targets'''.

View File

@@ -0,0 +1,47 @@
[[Property:title|Properties]]
[[Property:weight|5]]
This cluster contains all the common properties available for Vision2 [[Widgets|widgets]] and [[Items|items]] . Every Vision2 widget has the same set of properties inherited from EV_WIDGET, but many widgets also inherit additional properties, further refining the behavior of the widget.
EV_WIDGET inherits the following properties:
* [[ref:libraries/vision2/reference/ev_pick_and_dropable_chart|EV_PICK_AND_DROPABLE]]
** For an overview of the Pick and Drop mechanism, click [[EiffelVision Pick and Drop|here]] .
* [[ref:libraries/vision2/reference/ev_sensitive_chart|EV_SENSITIVE]]
** If a Vision2 component inherits [[ref:libraries/vision2/reference/ev_sensitive_chart|EV_SENSITIVE]] , it can be made to ignore events. <br/>
Use <eiffel>disable_sensitive</eiffel> to disable event handling, and <eiffel>enable_sensitive</eiffel> to restore event handling.
* [[ref:libraries/vision2/reference/ev_colorizable_chart|EV_COLORIZABLE]]
** If a Vision2 component inherits [[ref:libraries/vision2/reference/ev_colorizable_chart|EV_COLORIZABLE]] it has facilities for modifying its foreground and background colors. <br/>
Use <eiffel>set_foreground_color</eiffel> to set the <eiffel>foreground_color</eiffel> and <eiffel>set_background_color</eiffel> to set the <eiffel>background_color</eiffel>. <br/>
Use <eiffel>set_default_colors</eiffel> to restore the colors to their defaults.
* [[ref:libraries/vision2/reference/ev_help_contextable_chart|EV_HELP_CONTEXTABLE]]
** If a Vision2 component inherits [[ref:libraries/vision2/reference/ev_help_contextable_chart|EV_HELP_CONTEXTABLE]] , facilities are provided for associating help to the component when F1 or Shift F1 is pressed.
* [[ref:libraries/vision2/reference/ev_positioned_chart|EV_POSITIONED]]
** If a Vision2 component inherits [[ref:libraries/vision2/reference/ev_positioned_chart|EV_POSITIONED]] it is possible to query its current position, size and minimum size. <br/>
Use <eiffel>x_position</eiffel> and <eiffel>y_position</eiffel> to find its position relative to its parent. <br/>
Use <eiffel>width</eiffel> and <eiffel>height</eiffel> to find its size. <br/>
Use <eiffel>minimum_width</eiffel> and <eiffel>minimum_height</eiffel> to find its size.
* [[ref:libraries/vision2/reference/ev_containable_chart|EV_CONTAINABLE]]
** If a Vision2 component inherits [[ref:libraries/vision2/reference/ev_containable_chart|EV_CONTAINABLE]] it is able question its parent. Use parent to query the current parent.
{{note| '''Note:''' [[ref:libraries/vision2/reference/ev_containable_chart|EV_CONTAINABLE]] has no features for setting the parent. In Vision2, a child has no features for setting its parent, while a parent such as ev_container contains routines for adding children (one example is <eiffel>extend</eiffel>). }}
The following properties are also used within Vision2:
* [[ref:libraries/vision2/reference/ev_deselectable_chart|EV_DESELECTABLE]]
* [[ref:libraries/vision2/reference/ev_drawable_chart|EV_DRAWABLE]]
* [[ref:libraries/vision2/reference/ev_fontable_chart|EV_FONTABLE]]
* [[ref:libraries/vision2/reference/ev_pixmapable_chart|EV_PIXMAPABLE]]
* [[ref:libraries/vision2/reference/ev_positionable_chart|EV_POSITIONABLE]]
* [[ref:libraries/vision2/reference/ev_selectable_chart|EV_SELECTABLE]]
* [[ref:libraries/vision2/reference/ev_textable_chart|EV_TEXTABLE]]
* [[ref:libraries/vision2/reference/ev_tooltipable_chart|EV_TOOLTIPABLE]]

View File

@@ -0,0 +1,16 @@
[[Property:title|Support]]
[[Property:weight|6]]
The support cluster contains many classes providing useful facilities within the library. Many of the classes within this cluster are constant classes, which are filled with constant values for specific contexts, generally indicated by their names. The following constant classes are available within this cluster:
* [[ref:libraries/vision2/reference/ev_dialog_constants_chart|EV_DIALOG_CONSTANTS]]
* [[ref:libraries/vision2/reference/ev_drawable_constants_chart|EV_DRAWABLE_CONSTANTS]]
* [[ref:libraries/vision2/reference/ev_font_constants_chart|EV_FONT_CONSTANTS]]
* [[ref:libraries/vision2/reference/ev_key_constants_chart|EV_KEY_CONSTANTS]]
* [[ref:libraries/vision2/reference/ev_postscript_page_constants_chart|EV_POSTSCRIPT_PAGE_CONSTANTS]]
In a similar vein to constant classes, the two following classes are provided to provide support for default [[ref:libraries/vision2/reference/ev_color_chart|EV_COLOR]] 's and [[ref:libraries/vision2/reference/ev_pixmap_chart|EV_PIXMAP]] 's.
* [[ref:libraries/vision2/reference/ev_stock_colors_chart|EV_STOCK_COLORS]]
* [[ref:libraries/vision2/reference/ev_stock_pixmaps_chart|EV_STOCK_PIXMAPS]]

View File

@@ -0,0 +1,66 @@
[[Property:title|Containers]]
[[Property:weight|1]]
All Vision2 containers inherit [[ref:libraries/vision2/reference/ev_container_chart|EV_CONTAINER]]
==What is a container?==
A container is a Vision2 widget that may contain other widgets. Some containers such as [[ref:libraries/vision2/reference/ev_cell_chart|EV_CELL]] may only hold one widget while containers such as [[ref:libraries/vision2/reference/ev_box_chart|EV_BOX]] may hold multiple widgets. As a container is of type [[ref:libraries/vision2/reference/ev_widget_chart|EV_WIDGET]] , this means that a container may be placed within a container. Windows inherit from [[ref:libraries/vision2/reference/ev_cell_chart|EV_CELL]] and are therefore classed as containers also.
{{note| '''Note: '''Containers may only contain other widgets. Items may only be placed in certain primitives. For example, an [[ref:libraries/vision2/reference/ev_list_item_chart| EV_LIST_ITEM]] may be contained in an [[ref:libraries/vision2/reference/ev_list_chart| EV_LIST]] . }}
==Inheritance from Base==
Wherever possible, Vision2 containers reuse the container structures provided by Base. This provides three main advantages:
# Familiarity for operations such as access, insertions and removals. Anybody who already uses [[EiffelBase Library|Base]] should find it easy to adapt to using Vision2 containers.
# The underlying structures used have been tried and tested for many years and their design has been proved to be robust and effective.
# It provides powerful methods of querying the contents. In the original Vision library, you needed to keep reference to widgets as you could not query the contents of a container.
For example, [[ref:libraries/vision2/reference/ev_container_chart|EV_CONTAINER]] inherits <eiffel>BOX</eiffel> and <eiffel>COLLECTION</eiffel>. Descendents of [[ref:libraries/vision2/reference/ev_container_chart|EV_CONTAINER]] such as [[ref:libraries/vision2/reference/ev_box_chart|EV_BOX]] may also inherit other structures from [[EiffelBase Library|Base]] .
==Usage of Containers==
The main role of a container is to position its children in a certain way. An [[ref:libraries/vision2/reference/ev_horizontal_box_chart| EV_HORIZONTAL_BOX]] for example positions its children side by side along the horizontal axis. To achieve vertical stacking you would use an [[ref:libraries/vision2/reference/ev_vertical_box_chart| EV_VERTICAL_BOX]] .
A code example of adding widgets to a container is as follows:
<code>
add_to_container is
-- Add 3 buttons to a hbox and then show in window.
local
a_window: EV_TITLED_WINDOW
a_hbox: EV_HORIZONTAL_BOX
a_button: EV_BUTTON
do
create a_window
create a_hbox
create a_button.make_with_text ("Button1")
a_hbox.extend (a_button)
a_hbox.extend (create {EV_BUTTON}.make_with_text ("Button2"))
a_hbox.extend (create {EV_BUTTON}.make_with_text ("Button3"))
a_window.extend (a_hbox)
a_window.show
end
</code>
The mapping of a Vision2 container interface is very close to that of containers in Base, such as a linked list.
* To add a widget to a container call `extend'.
* To remove a widget from the container call `prune'.
* To empty a container call `wipe_out'.
* To traverse the container, you can use features such as start, forth, item and off.
{{note| '''Note''': When a widget is added to a container, the container is the parent of the widget. }}
==Size of widget within a container==
The size of a widget in a container is always at least its minimum size. By default, when a widget is added to a container it is expandable. This means that if the container gets bigger, the widget will expand to fit the extra space. This convenient functionality means that you don't have to worry about handling the size of the widget (such as when a user alters the size of a window) as this is all performed automatically. If, on the other hand, you decide you want the widget to remain at a certain size (its minimum size), [[ref:libraries/vision2/reference/ev_box_chart| EV_BOX]] contains the convenient call disable_item_resize.
==Sizing of containers==
As [[ref:libraries/vision2/reference/ev_container_chart|EV_CONTAINER]] is of type [[ref:libraries/vision2/reference/ev_widget_chart|EV_WIDGET]] , the following facilities are provided for setting the minimum size: set_minimum_width, set_minimum_height and set_minimum_size. It is important to remember that as a general rule, '''the current size of a container is always at least the minimum size of all its contents.'''
{{note| '''Note: '''The exception to this is: [[ref:libraries/vision2/reference/ev_fixed_chart|EV_FIXED]] , [[ref:libraries/vision2/reference/ev_viewport_chart|EV_VIEWPORT]] and [[ref:libraries/vision2/reference/ev_scrollable_area_chart|EV_SCROLLABLE_AREA]] which do actually allow their contents to be larger than their current size. <br/>
}}

View File

@@ -0,0 +1,32 @@
[[Property:title|EiffelVision Dialogs]]
[[Property:weight|2]]
This cluster contains all the dialogs provided by Vision2.
==Standard dialogs==
A standard dialog provides a way of interacting with the underlying platform (such as Windows or Linux) to perform basic tasks such as opening a file or printing a document. Vision2 provides six dialogs that allow the user to perform everyday tasks that are
* [[ref:libraries/vision2/reference/ev_color_dialog_chart|EV_COLOR_DIALOG]] -- This allows the user of your app to select an RGB color (useful for graphical apps such as a Paint Program).
* [[ref:libraries/vision2/reference/ev_directory_dialog_chart|EV_DIRECTORY_DIALOG]] -- This allows the user of your app to select a directory.
* [[ref:libraries/vision2/reference/ev_file_open_dialog_chart|EV_FILE_OPEN_DIALOG]] -- This allows the user of your app to select a file to be opened.
* [[ref:libraries/vision2/reference/ev_file_save_dialog_chart|EV_FILE_SAVE_DIALOG]] -- This allows the user of your app to select a filename that will be used for the creation of a file.
* [[ref:libraries/vision2/reference/ev_font_dialog_chart|EV_FONT_DIALOG]] -- This allows the user of your app to select a font (useful for a Word Processor for example).
* [[ref:libraries/vision2/reference/ev_print_dialog_chart|EV_PRINT_DIALOG]] -- This allows the user of your app to choose printer settings may be used in conjunction with [[ref:libraries/vision2/reference/ev_print_projector_chart|EV_PRINT_PROJECTOR]] .
==Creating custom dialogs==
If you wish to provide a custom dialog in your application, [[ref:libraries/vision2/reference/ev_dialog_chart| EV_DIALOG]] has been provided to facilitate this.
==Message dialogs==
A message dialog gives your application a standard way of displaying useful (or vital) information, this information can be displayed with the following message dialogs.
* [[ref:libraries/vision2/reference/ev_message_dialog_chart|EV_MESSAGE_DIALOG]] -- Allows a simple message to be displayed to the user.
* [[ref:libraries/vision2/reference/ev_information_dialog_chart|EV_INFORMATION_DIALOG]] -- Allows useful info to be displayed to the user.
* [[ref:libraries/vision2/reference/ev_question_dialog_chart|EV_QUESTION_DIALOG]] -- Allows the user to respond to a question with Yes or No.
* [[ref:libraries/vision2/reference/ev_warning_dialog_chart|EV_WARNING_DIALOG]] -- Allows a warning to be displayed to the user.
* [[ref:libraries/vision2/reference/ev_confirmation_dialog_chart|EV_CONFIRMATION_DIALOG]] -- Allows the user to confirm an action that has been requested.
* [[ref:libraries/vision2/reference/ev_error_dialog_chart|EV_ERROR_DIALOG]] -- Allows an error message to be shown to the user.

View File

@@ -0,0 +1,50 @@
[[Property:title|Widgets]]
[[Property:weight|2]]
==What is a Widget?==
A Widget is the fundamental building block of your applications GUI, components such as Windows, Buttons and Labels are examples of such. The widget set of Vision2 provides you with the flexibility to easily create powerful graphical applications. All widgets in Vision2 inherit from [[ref:/libraries/vision2/reference/ev_widget_chart| EV_WIDGET]] and the features provided in <eiffel> EV_WIDGET</eiffel> may be called on any widget.
==Variations of Widget==
Within Vision2, widgets have been classified into three different groups:
* [[Primitives|Primitives]] -- These are elements of the user interface that are mainly responsible for interaction with the user, such as an [[ref:/libraries/vision2/reference/ev_button_chart|EV_BUTTON]] .
* [[Containers|Containers]] -- These are used to contain other widgets and position them in a certain way, such as an [[ref:/libraries/vision2/reference/ev_vertical_box_chart| EV_VERTICAL_BOX ]] that stacks its children one by one vertically.
* [[EiffelVision Dialogs|Dialogs]] -- These are pop up dialog windows used for interacting with the user for tasks such as opening a file (EV_FILE_OPEN_DIALOG) or displaying a message (EV_MESSAGE_DIALOG). You may construct your own dialogs by inheriting EV_DIALOG.
==How do I create a widget?==
All widgets in Vision2 are based around the default_create mechanism in Eiffel. This means that all that needs to be done to create a widget is to declare a reference to a type (such as [[ref:libraries/vision2/reference/ev_button_chart|EV_BUTTON]] ) and then call create on that reference. An example of this is as follows.
<code>
a_button: EV_BUTTON
create a_button
</code>
Along with the default creation, Vision2 also includes a few convenience creation functions. Examples of this are make_with_text for all widgets that may have text associated with them (those that inherit from [[ref:libraries/vision2/reference/ev_textable_chart| EV_TEXTABLE]] ), this saves a call to set_text upon default creation of the textable widget.
<code>
create a_button.make_with_text ("Click Me")
</code>
This would be in place of
<code>
create a_button
a_button.set_text ("Click Me")
</code>
{{note|Note: When a widget is created no extra initialization has to be performed. '''The only exception is for a window where you have to call show in order for it to be displayed on screen'''. }}
==Sizing==
As [[ref:libraries/vision2/reference/ev_primitive_chart|EV_PRIMITIVE]] is of type [[ref:libraries/vision2/reference/ev_widget_chart|EV_WIDGET]] , the following facilities are provided for setting the minimum size: set_minimum_width, set_minimum_height and set_minimum_size.
The minimum size of a widget is the smallest possible size that it can possibly be inside its parent container. If an [[ref:libraries/vision2/reference/ev_button_chart|EV_BUTTON]] was created and set with a minimum_size of width/height (100, 100), if this button was inserted in to an [[ref:libraries/vision2/reference/ev_horizontal_box_chart| EV_HORIZONTAL_BOX]] , then the box's size could never be below (100, 100) or it would break the minimum size of the button. '''The size of a container must always be greater or equal to the minimum sizes of its children.'''
{{note| '''Note: '''In Vision2, there is no way to set the current size of the primitive. The current size is dependent on the size of the parent or the minimum_size. }}
==Now what do I do?==
Now that you can create a widget, you will need to actually make it usable to your intended user. This will usually involve these three steps. <br/>
* Setting [[Properties| properties]] for the widget such as color and the minimum size that a widget can possibly be in its parent container.
* Making the widget respond to user [[Events| events]] via the use of agents and action sequences.
* Placing the widget inside a [[Containers| container]] widget (either a window or a child of a window) so it can be shown on screen.

View File

@@ -0,0 +1,17 @@
[[Property:title|Primitives]]
[[Property:weight|0]]
All Vision2 primitives inherit [[ref:libraries/vision2/reference/ev_primitive_chart|EV_PRIMITIVE]] .
==What is a primitive?==
A primitive is a Vision2 widget that may not contain other widgets. Primitives may be placed in [[Containers|containers]] , but a [[Widgets|widget ]] may not contain any child widgets. Some examples of primitives are [[ref:libraries/vision2/reference/ev_button_chart|EV_BUTTON]] and [[ref:libraries/vision2/reference/ev_label_chart|EV_LABEL]] .
==Features of a primitive==
All primitives inherit from [[ref:libraries/vision2/reference/ev_tooltipable_chart|EV_TOOLTIPABLE]] and therefore can have tooltips assigned to them. They all inherit many features from [[ref:libraries/vision2/reference/ev_widget_chart|EV_WIDGET]] . Each descendent of [[ref:libraries/vision2/reference/ev_primitive_chart|EV_PRIMITIVE]] will typically have many available features, specific to their type. For example, [[ref:libraries/vision2/reference/ev_separator_chart|EV_SEPARATOR]] has no extra features, but [[ref:libraries/vision2/reference/ev_label_chart|EV_LABEL]] has features for modifying the current font and also the text to be displayed.
==Widgets as item holders==
Although no primitive can contain another widget, certain primitives may contain one or more [[Items|items]] . One example of this is an [[ref:libraries/vision2/reference/ev_list_chart| EV_LIST]] containing [[ref:libraries/vision2/reference/ev_list_item_chart|EV_LIST_ITEM]] s.

View File

@@ -0,0 +1,16 @@
[[Property:title|EiffelVision 2 Library]]
[[Property:link_title|EiffelVision 2]]
[[Property:weight|10]]
Type: Library <br/>
Platform: Any <br/>
See:
* [[EiffelVision Introduction|Introduction]]
* [[EiffelVision Interface Content|Content]]
* [[EiffelVision 2 Samples|Samples]]
* [[ref:libraries/vision2/reference/index|Reference]]
* [[Revisions and Bug Fixes|Release notes]]

View File

@@ -0,0 +1,762 @@
[[Property:title|Revisions and Bug Fixes]]
[[Property:weight|10]]
This document contains details of modifications and bug fixes to the Vision2 library listed by the release version of EiffelStudio. All bug fixes and modifications are relative to the previously released version.
==EiffelStudio 6.2==
'''Interface modifications'''
* '''EV_WINDOW''' - Added hide actions.
'''Bug fixes'''
* '''Platform independent'''
** '''EV_GRID'''
*** Fixed crashes when rendering child tree nodes
==EiffelStudio 6.1==
'''Interface modifications'''
* '''EV_APPLICATION''' - Added 'is_display_remote' for determining whether the graphical display is on the same machine as the running system.
* '''EV_POINTER_STYLE_CONSTANTS''' - Added hyperlink_cursor constant so that hyperlink cursors may be used in applications
* '''EV_POINTER_STYLE''' - Now pointer style objects may be twinned correctly to match the capability of pixmaps and cursor objects.
* '''EV_DRAWABLE''' - Added 'draw_sub_pixel_buffer' so that pixel buffer data may be rendered to a drawable.
* '''EV_PIXEL_BUFFER''' - Added 'draw_pixel_buffer_with_x_y'.
* '''EV_STOCK_PIXMAPS''' - Now pixel buffers are used for stock icons; this allows for alpha transparency information to be retained.
'''Bug fixes'''
* '''Platform independent'''
** '''EV_GRID'''
*** Fixed certain crashes when recomputing offsets
* '''Windows'''
** '''EV_STOCK_PIXMAPS'''
*** Now alpha information is correctly extracted for stock icons
* '''Linux/Solaris'''
** '''EV_COMBO_BOX'''
*** Fixed calling of change_actions when items are selected via the drop down
** '''EV_POINTER_STYLE'''
*** Fixed issue when converting to a cursor object then reverting back would render a white square instead of the requested cursor
** '''EV_WINDOW'''
*** Fixed issues when calling disable/enable user resize in certain states
==EiffelStudio 6.0==
'''Interface modifications'''
* '''EV_PICK_AND_DROPABLE''' - Added context menu capabilities with 'set_configurable_target_menu_mode', 'set_configurable_target_menu_handler' and 'show_configurable_target_menu' that can be used to override the existing Pick and Drop mechanism.
* '''EV_ACTION_SEQUENCE''' - Now event_data is defined with named tuples for easier reading of the action sequence parameters.
* '''EV_APPLICATION_ACTION_SEQUENCES'''
** Added 'file_drop_actions' for OS based file drag and drop from exterior applications to a Vision2 application.
** Made 'idle_actions' obsolete as it is not thread-safe
** Now a full garbage collection occurs if the application has been idle for 30 seconds
* '''EV_APPLICATION'''
** Added 'transport_in_progress' for querying if a pebble transport is currently taking place.
** Added caps_lock_on for querying if the caps lock key is currently toggled
** `process_events' will now call idle actions when no more events are left in the pending queue
* '''EV_FONT''' - Added 'line_height' to retrieve an appropriate text editor line height in pixels for a font.
* '''EV_PIXEL_BUFFER''' - Added conversion to/from EV_PIXMAP and added 'save_to_named_file' for saving buffer to disk.
* '''EV_POINTER_STYLE_CONSTANTS''' - Added header_sizewe cursor
* '''EV_FIXED''' - Added extend_with_size_and_position and set_with_size_and_position for flicker free update of fixed children.
* '''EV_GRID''' - Added `visible_row_count' for querying the number of currently visible rows.
* '''EV_TEXT_FIELD''' - Added inheritance from EV_TEXT_ALIGNABLE
* '''EV_POPUP_WINDOW''' - Added 'make_with_shadow' creation procedure to create a popup window with an alpha shadow (on platforms that support it).
'''Bug fixes'''
* '''Platform independent'''
** '''EV_GRID'''
*** Fixed refresh issues and certain crashes when removing items from grid
*** Fixed navigation and selection handling for trees
** '''EV_PICK_AND_DROPABLE''' - Fixed 'memory leak' when calling 'pebble_function'.
* '''Windows'''
** Raised compatibility bar to Windows 2000 or greater. No more support for Windows 98 or NT 4.0.
** '''EV_DIALOG'''
*** Fixed resizing bug that led to a difference in behavior from regular EV_WINDOW descendents
*** Corrected calling of cancel actions when closing via the Cross which previously was broken for modeless and modal dialogs
** '''EV_PIXMAP'''
*** Now correctly copying all agents over when the pixmap implementation internally changes state, previously some agents were being lost after certain operations on a pixmap
*** Now mask is correctly queried when saving pixmap
* '''Linux/Solaris'''
** '''EV_ACCELERATOR''' - Reimplemented accelerator implementation so that it works with all key combinations that were previously being unprocessed by gtk
** Completely reimplemented and optimized event handling for faster response, scaled down use of agents for event connection for decreased memory consumption
==EiffelStudio 5.7==
'''Interface modifications'''
* '''STRING_GENERAL''' - All string operations now take STRING_GENERAL instead of STRING, this allows for mixing and matching of 8 and 32-bit string objects and allows for 32bit Unicode values, the return value is always STRING_32
* '''EV_APPLICATION'''
** Added action sequences for querying global user events such as pointer clicks and motion
** Vision2 is now thread-aware with the addition of thread-safe 'add_idle_action' and 'do_once_on_idle' that allow threads to add agents to update the main GUI thread in a safe manner
* '''EV_POINTER_STYLE''' - Added new pointer style class for setting the style of the mouse pointer, EV_CURSOR will be made obsolete, in the future animated cursors and transparency will be available
* '''EV_PIXEL_BUFFER''' - New class for loading/querying and setting RGBA values from disk
* '''EV_FIXED''' - Now item positions may be set to negative values within the fixed widget
* '''EV_BITMAP''' - New class for setting 1 bit masks on EV_PIXMAP via set_mask
* '''EV_TEXT''' - Added 'scroll_to_end' to scroll down so that the last line is visible
* '''EV_WIDGET'''
** Added 'refresh_now' that allows for immediate redraw of a widget without having to wait for the event loop to repaint it. A useful example of this is when calling 'set_text' on EV_LABEL during heavy computation.
** Added ability to ignore the default key action on widgets.
* '''EV_GRID'''
** Changed semantic of `move_row' and `move_rows' so that destination position is now an insertion index before a row instead of placing as the row index itself. This allows for easier insertion of rows. Any code using these features will need to be rechecked as this is a breaking change for rows that are moved down the grid
** Altered `move_rows' so that it will now unparent the top level nodes from the first row being moved whilst keeping any subtree structure
** Added `move_rows_to_parent' that allows moving a block of parented rows from one parent to another
** Added `insert_new_rows' and `insert_new_rows_parented' which permit you to add insert multiple rows at once. This is far quicker than adding rows individually.
** Added `remove_rows' which permits you to remove multiple rows at once. This is far quicker than removing each row individually.
** Fixed `enable_capture' and disable_capture' which previously captured an internally hidden component of the grid, so no events were ever received during capture.
** Previously, `set_default_colors' did not work.
** Fixed bug in `pointer_enter_actions' and `pointer_leave_actions' of EV_GRID_ITEM which were not always fired when the mouse pointer entered or left the grid.
** Corrected `not_row_height_variable_and_vertical_scrolling_per_pixel' precondition of `enable_partial_dynamic_content'.
** Fixed bug which caused an internal exception within the grid when `is_tree_enabled' and `is_content_partially_dynamic'.
** Strengthened preconditions of `insert_new_row_parented' to prevent you inserting a new row at an index within a subtree structure of one of the existing subrows, as in that case, it is impossible for the parent to be the desired row.
** Added capability to hide rows in the grid
** Added ability for locking the position of rows and columns in the grid
* '''EV_GRID_ROW''' - Added `insert_subrows' for the quick addition of multiple subrows at once.
* '''EV_WINDOW''' - Added `is_border_enabled', `enable_border' and `disable_border'. This lets you turn on/off the border as required.
* '''EV_HEADER_ITEM''' - Added `user_can_resize' which enables you to prevent a user from resizing the item. Also added `minimum_width' and `maximum_width' which permit you to restrict the resizing of the item within a particular range.
* '''EV_MESSAGE_DIALOG''' - All message dialogs now use their associated message icon as the icon pixmap displayed in the title bar, instead of the standard EiffelVision2 icon.
* '''EV_DYNAMIC_TREE_ITEM''' - The `subtree_function' is now only executed when you expand the item. In the previous version, querying the contents of the item caused the subtree function to be executed, filling the children.
* '''EV_COMBO_BOX''' - Added `is_list_shown', `list_hidden_actions' and renamed `drop_down_actions' to `list_shown_actions'.
* '''EV_APPLICATION''' - Added `pointer_motion_actions', `pointer_button_press_actions', `pointer_button_release_actions', `pointer_double_press_actions', `mouse_wheel_actions', `key_press_actions', `key_press_string_actions' and `key_release_actions'. Each of these action sequences pass the applicable widget as part of the event data.
'''Bug fixes'''
* '''Platform independent'''
** '''EV_GRID''' - Fixed refresh issues and certain crashes when removing items from grid
* '''Windows'''
** '''EV_WINDOW''' - The default state is now `user_can_resize'. Although this was previously specified within `is_in_default_state', the window was not actually resizeable.
** '''EV_DIALOG'''
*** Calling `enable_user_resize' or `disable_user_resize' on a dialog that is shown relative to another window no longer looses the relative state of the dialog.
*** Fixed failure of a "check" statement within EiffelVision when showing a dialog with a `default_cancel_button' relative or modal to another window.
** '''EV_FONT_DIALOG''' - Fixed issue where displayed font did not take into account font specified through call to `set_font'.
** '''EV_RICH_TEXT''' - Fixed calling of `change_actions' which were never called in the previous version.
** '''EV_PIXMAP''' - If a pixmap was parented directly within a container and Windows XP themes were enabled, the background theme of the parent container was not applied to the pixmap. This was especially noticeable when using EV_NOTEBOOK as a parent container.
** '''EV_WIDGET''' - Fixed bug in theme handling on Windows XP. Previously, any widgets that were created before the first window was created did not draw correctly when displayed.
** '''EV_COMBO_BOX''' - Fixed bug in `key_press_actions' which were called twice when you pressed the up or down arrow keys.
** '''EV_TITLED_WINDOW'''
*** `title' was returning `Void' if you had not explicitly set a `title'.
*** Fixed raise to work when process is not in the foreground, the window will now flash in the window selector
** '''EV_MENU''' - A menu with an ampersand (i.e. menu.set_text ("Test && Verify")) could be truncated when displayed (i.e. the `y' could be missing).
** '''EV_PIXMAP''' - Fixed a memory corruption while loading PNG images.
** Fixed resizing issue which would happen if too many widgets are nested in each other, those nested widgets would not resize properly.
* '''Gtk'''
** '''EV_DIALOG''' - Fixed modal dialogs so that they behave the same as on Windows so that show_modal_to_window is indeed only modal to the parent window
** - Mouse events now only go to the widget that the mouse is currently interacting with
** '''EV_FONT''' - Fixed bug where font names were being matched on substring, meaning that Sans would match with San Serif
** '''EV_TEXT''' - Fixed and optimized calls relating to display lines versus actual lines
** - Fixed potential instability due to signal marshal calls being made during object dispose
** - Completely overhauled event handling implementation to use less resources and be much more optimal
** '''EV_POPUP_WINDOW'''Completely rewrote popup window implementation to be not dependent on the window manager, this means that they will work in all scenarios with WM intervention
** '''EV_ACCELERATOR''' - Fixed crashes caused by certain accelerator combinations
** '''EV_TOOL_BAR_BUTTON''' - Toolbar buttons are now accepted as Pick and Drop targets
==EiffelStudio 5.6==
'''Interface modifications'''
* '''EV_POPUP_WINDOW''' - A new window type which inherits EV_WINDOW with two differences: It does not display a border of any sorts and is not displayed in the task bar. This is especially useful for simulating tooltips and other such pop-ups.
* '''EV_APPLICATION''' - Added 'uncaught_exception_actions' which is called whenever an action sequence called from the underlying toolkit fails to deal with any exceptions raised.
* '''EV_CLIPBOARD''' - Added 'has_text' so that the clipboard can be queried without retrieving the entire contents.
* '''EV_CHECKABLE_TREE''' - A new widget that inherits EV_TREE, providing similar functionality but for each item contained a check box is displayed.
* '''EV_NOTEBOOK'''
** Added `pointed_tab_index' which returns the index of the tab beneath the mouse pointer or 0 if none.
** Added EV_NOTEBOOK_TAB which may be queried via the new query `item_tab'. The object represented by this new class provides the ability to set both the text and a pixmap for the tab item.
** Now inherits EV_ITEM_PIXMAP_SCALER as the tabs support pixmaps through the use of EV_NOTEBOOK_TAB.
* '''EV_COMBO_BOX''' - Added `drop_down_actions', fired as the list is dropped down which permits dynamic filling of the combo box as its contents are displayed.
* '''EV_WIDGET''' - Removed postcondition `has_focus' from `set_focus' since in most cases it does not hold. Indeed between the time you set the focus and the time you check if you still have the focus something could have happen that would remove the focus.
* '''EV_PIXMAP''' - Added `sub_pixmap', this allows a pixmap to be created from a region of another
* '''EV_RICH_TEXT''' - Corrected postcondition of `buffered_format' which restricted the end position to `text_length' instead of `text_length' + 1.
* '''EV_FILE_OPEN_DIALOG''' - Added features for retrieving multiple file names. The following additional features are now available: 'enable_multiple_selection', `disable_multiple_selection', `multiple_selection_enabled' and `file_names'.
* '''EV_TEXT_COMPONENT''' - Removed `is_editable' precondition of `set_caret_position'.
'''Bug fixes'''
* '''Platform independent'''
** '''EV_DIALOG_I''' - Fixed consistency of `default_push_button', before we could get some assertions violations from the implementation classes.
** '''EV_ANY''' - Added protection for multiple calls of `destroy' which previously caused crashes in some situations, now `destroy' calls a `safe_destroy' intermediary which checks if the implementation has not already been destroyed
** '''EV_GAUGE''' - Fixed bug in `make_with_value_range' which did not adjust `value' to `lower', thereby putting the gauge in an invalid state.
* '''Windows'''
** Fixed resizing issue: when a widget is inserted in a hidden window and that the minimum size of the window does not change, the widget would not appear on the window when shown. One had to manually resize the window to make it appear. Now it will appear properly.
** Fixed a crash which could occur when using the tab or arrows keys to navigate between the primitive of a window. It would happen when trying to set the focus on a widget which was previously parented but is not anymore.
** Improved appearance of applications running on Windows XP with manifest files.
** '''EV_RADIO_BUTTON''' - Enabled better navigation between radio buttons of a group using the arrow keys.
** '''EV_SPIN_BUTTON'''
*** When it gets the focus, we set the focus to the associated text field. Before one would loose the focus until one use the mouse to set it to the text field part.
*** Fixed bug which restricted the maximum values permitted to approx. 16,000. Attempting to manipulate the spin button with values greater than this caused precondition violations internally.
** '''EV_SCREEN'''
*** `widget_at_position' returns an instance of EV_COMBO_BOX when cursor is on top of the text part of the combo box, before it would return Void.
*** `set_pointer_position' was not setting the position accurately and it may have actually been set to one of the adjacent positions.
** '''EV_COMBO_BOX'''
*** `focus_out_actions' are only called once when loosing focus. Before they would be called twice and even called when the combo box was getting the focus.
*** Fixed `has_focus' to return True when either the combo or the text field when it exists has the focus.
*** Fixed call on Void target when calling `set_foreground_color' on a displayed combo box which is not editable.
*** Fixed invariant violation with a non editable combo box.
*** Fixed `caret_position' which was failing if you attempted to set a caret position to a value greater than approx 65,000.
*** Fixed `set_focus' which failed if the combo box was non-editable.
*** Fixed handling of escape and enter keys while list was dropped down. If the combo box was contained within a dialog, the default cancel and default push button actions were fired as a result of pressing these keys. These keys are no longer propagated to the dialog in this fashion.
** '''EV_MULTI_COLUMN_LIST''' - Calling `column_width' after calling `resize_column_to_content' did not return the correct result but instead the previously set column width.
** '''EV_NOTEBOOK'''
*** Fixed resizing issue of notebook when it is included in a hidden pane of another notebook, resulting in an assertion violation in the resizing code.
*** Fixed class invariant which failed when calling `destroy'.
** '''EV_WINDOW'''
*** Fixed `screen_x' and `screen_y' so that they return the same value as `x_position' and `y_position'.
*** Fixed issue where `move_actions' were called with incorrect positions (before the given positions were the one from the child of the window, not the window itself).
** '''EV_DIALOG'''
*** Calling `show', moving the window and then subsequently calling `show_relative_to_window' or `show_modal_to_window' caused the dialog to move from its current position. Now the window no longer moves which mirrors the behavior in the opposite case where `show_relative_to_window' or `show_modal_to_window' is called before `show'.
*** Fixed bug which caused processing of particular keys in widgets contained within the dialog to be processed by the dialog preventing the `key_press_actions' from being fired and causing miscellaneous keyboard navigational issues.
*** Proper handling of `remove_default_push_button' and `set_default_push_button'. Before the internal state would be messed up, resulting in calling the `select_actions' of the the `default_push_button' even though the `default_push_button' did not have focus.
*** Better navigation using keys
*** Fixed bug where modal and modeless dialogs were not centered to parent
** '''EV_TREE_NODE''' - Fixed bug which caused a crash if you performed the following: pruned a node from it's parent, pruned an empty node from this just pruned node and then attempted to insert a node within the empty node.
** '''EV_DIRECTORY_DIALOG''' - Fixed bug in which the dialog always reported that "ok" has been selected even if the "cancel" button had been selected. This occurred if the dialog had been shown more than once with "ok" already selected.
** '''EV_PIXMAP'''
*** Fixed color displayed around a pixmap while parented in a container. Previously, gray was always displayed but now we use the `background_color' of the `parent'.
*** Fixed masking blitting in draw_sub_pixmap. Previously the mask wasn't being blitted correctly discoloring the source image
*** Fixed mask handling with PNG loading. Previously if the source image pixels under the mask were not black then masking for icons and cursors didnt work correctly, now any color can be used underneath the mask and it will still be masked correctly
** '''EV_TOOL_BAR'''
*** Fixed `is_show_requested' which was still returning `True' after a call to `hide'.
*** Improved resizing of tool bar buttons. A tool bar button with a text and no associated pixmap used to display an empty area where the pixmap would be displayed if set. Now, in this case, the button is just large enough to display its text.
** '''EV_FONT''' - Fixed bug in `is_equal' which occasionally failed due to rounding errors between `height' and `height_in_points'. Now, `is_equal' compares `height_in_points' for the font which is more accurate and prevents this issue.
** '''EV_APPLICATION''' - `cancel_actions' were not always called when they should have been. If you cancelled a pick and drop by right clicking on a target that does not accept the `pebble', the `cancel_actions' were not fired.
** '''EV_RICH_TEXT'''
*** Fixed bug in `buffered_format' which corrupted the current text upon calling `flush_buffer' if the text contained any RTF reserved characters such as '/', '{' or '}'.
*** Fixed `set_background_color' which was not changing the background color
*** Fixed bug in `disable_word_wrapping' which had a side effect that limited the maximum number of characters to 64000.
** '''EV_TOOL_BAR_BUTTON''' - Fixed bug in handling of enabled/disabled state during a pick and drop transport. The pick and drop mechanism disables tool bar buttons automatically that are not valid targets. If you called `enable_sensitive' or `disable_sensitive' during a pick and drop, this state was not reflected at the end of the pick and drop and the buttons were always restored to their original state. Now the buttons are restored to their last set state.
** '''EV_TITLED_WINDOW''' - Fixed issue with `raise' where in addition of bringing the window to the front it was changing the previously focused widget within that window. Now it preserves the previously focused widget.
** '''EV_PRIMITIVE''' - Fixed bug which affected all primitives that hold items. Calling `destroy' on the primitive and then calling `destroy' on one of the items caused precondition violations internally. The bug was that the call to `destroy' on the primitive did not call `wipe_out' to remove all of the contents and the item was still attempting to access its `parent' which should have been `Void'.
** '''EV_WIDGET'''
*** Fixed two bugs with `key_press_string_actions'. The first was that the action sequence was fired when Escape or Backspace was pressed. As these are not displayable characters, the `key_press_string_actions' are no longer fired for these keys. The second is that pressing Enter was passing the the string "%R" which is the Windows specific newline character. We now pass "%N" when the Enter key is pressed.
*** Fixed bug in `pointer_motion_actions'. In some uncommon situations, it was possible to receive the motion event multiple times with the same position.
*** The `key_press_string_actions' are no longer fired by the "delete" key ( ASCII 127).
** '''EV_TEXT''' - Fixed bug where `caret_position' was returning an incorrect value if it the text had word wrapping enabled and one or more lines in the text were currently word wrapped.
** '''EV_FONT_DIALOG''' - Fixed bug where `name' of `font' returned was incorrect.
** '''EV_SPLIT_AREA''' - Split areas now have a completely flat appearance.
* '''Gtk'''
** '''EV_CURSOR''' - Now the default X-Cursors are used where applicable instead of pixmapped representations of them, this allows for animated cursors if available on the X-server
** '''EV_VIEWPORT''' - Fixed issue where offsets where not being updated right away so querying back to the viewport from an expose caused by the viewport for the values would be incorrect
** '''EV_TEXTABLE''' - Now UTF8 strings from different language locales are displayed correctly and not cut-off
** '''EV_CLIPBOARD''' - Now UTF8 strings from different language locales are handled correctly for copying and pasting
** '''EV_DRAWING_AREA''' -
*** Fixed `flush' to instantly call any pending expose events
*** Fixed issue where drawing area was not being focused when clicked upon by default
** '''EV_FONT'''
*** Fixed memory leaks in font lookup
*** Now all resources get freed on disposal of font
*** Now precalculating `ascent' and `descent' to improve drawing performance
*** Added better default font handling, now if the default font gets passed in, it will be treated as such by the Gtk theme engine
** '''EV_TOOL_BAR_BUTTON''' - Improve appearance of text and pixmap when `disable_vertical_button_style' is called
** '''EV_FONTABLE''' - Improved font handling with theme manager, all default fonts now relate to the Application font chosen from the Gtk theme manager
** '''EV_DRAWABLE'''
*** Corrected font placement with `draw_text' using fonts of the same height that have varying ascent values
*** Corrected `draw_arc' to handle all radian angles for both start_angle and aperture values
*** Fixed mask handling for `draw_sub_pixmap' to work with non-zero 'area' coordinates
** '''EV_MULTI_COLUMN_LIST''' - Fixed memory leak when setting string values
** '''EV_TREE_NODE'''
*** Fixed `remove_pixmap' to remove pixmap from tree model
*** Fixed crash when removing nodes from parent nodes not present in a tree widget
** '''EV_RICH_TEXT'''
*** Now `paste' uses the Vision2 clipboard directly and so all clipboard assertions are fulfilled
*** Fixed `buffered_format' to not wipe out the text buffer of the widget and therefore stop other EV_TEXT features from functioning correctly
*** Now `buffered_append' doesn't wipe out the screen contents of the rich text control
** '''EV_ACCELERATOR''' - Now the key accelerator is checked if valid before proceeding, in some circumstances when a key is not present in the key mapping table adding an accelerator would crash the system, now if the accelerator is not valid for the current key mapping then nothing is done
** '''EV_WINDOW'''
*** Now setting and querying focus works in all circumstances with all window types
** '''EV_PIXMAP''' - Improved pixmap 'stretch' for smaller images
** '''EV_WIDGET'''
*** Optimized motion event handling so that current motion events only get requested when the previous one has been processed
*** Fixed theme managed handling in all widgets so that fonts when changed outside of the application by the theme manager get reflected in the Vision2 application
** '''EV_DIALOG'''
*** Fixed bug where modal and modeless dialogs were not centered to parent
** '''EV_FRAME''' - Corrected issue where changing alignment of text was resetting the vertical alignment
** '''EV_COMBO_BOX''' - Now the drop down box doesn't fire focus out actions when shown
==EiffelStudio 5.5==
'''Interface modifications'''
* '''EV_TEXT'''
** Weakened a number of preconditions that required a non empty final line, which was unnecessary. Removed the obsolete feature `put_new_line' and made `last_line_not_empty' obsolete as it is unnecessary and can be queried via `line'.
** Added `line_number_from_position' which returns the line on which a particular caret position resides.
* '''EV_ACTIVE_LIST''' - New class added which replaces all occurrences of ACTIVE_LIST within the interface. This prevents the EiffelVision implementation from being "unhooked" by user modification through the interface. The class is completely backwards compatible, and does not require any modifications to your code. Classes such as EV_ACCELERATOR_LIST and EV_FONT incorporate this change.
* '''EV_DOCKABLE_SOURCE''' - Added features `is_external_docking_relative', `enable_external_docking_relative' and `disable_external_docking_relative'. This permits you to dock a source to an EV_DOCKABLE_DIALOG that is not displayed relative to the original top window.
* '''EV_RICH_TEXT''' - New class, providing a text control with support for character formatting and colors on a character by character basis. The following supporting classes have been added for use with EV_RICH_TEXT: EV_CHARACTER_FORMAT, EV_CHARACTER_FORMAT_EFFECTS, EV_PARAGRAPH_FORMAT, EV_CHARACTER_FORMAT_RANGE_INFORMATION, EV_PARAGRAPH_FORMAT_RANGE_INFORMATION and EV_PARAGRAPH_CONSTANTS.
* '''EV_ENVIRONMENT''' - Added `fonts' which returns a list of all fonts available on the system.
* '''EV_APPLICATION''' - Added `captured_widget' which returns the EV_WIDGET currently captured in the system, or `Void' if none.
* '''EV_SPLIT_AREA''' - Added `splitter_width' which returns the width of the splitter in pixels.
* '''EV_ANY_HANDLER''' - This is the only class to which `default_create' from EV_ANY is supposed to be exported. However, particular descendents were exporting `default_create' to ANY instead. This has now been fixed.
* '''EV_MESSAGE_DIALOG''' - `make_with_text_and_actions' has now been added to the list of creation procedures.
* '''EV_SCREEN''' - Added `horizontal_resolution' and `vertical_resolution' which return the number of pixels per inch.
* '''EV_FILE_DIALOG''' - Added support for multiple file extensions through the addition of `filters' which provides support for setting both a filter and an associated comment. The existing features `filter' and `set_filter' have been made obsolete.
* '''EV_FONT'''
** Modified return type of `string_size' from TUPLE [INTEGER, INTEGER] to TUPLE [INTEGER, INTEGER, INTEGER, INTEGER]. This does not break any existing code, but provides additional `left_offset' and `right_offset' queries (items 3, 4). Items 1, 2 still return the width and height of the string, but this is only the dimensions to be used when placing multiple strings next to each other. Some characters on more exotic fonts may still extend past this boundary, and the rectangle that fully encloses the string is given by adding the left and right offsets to the width.
** Added `height_in_points' and `set_height_in_points' for setting the height of a font in points (1/72 of an inch). This may be used to ensure that your fonts occupy the same height on screens with varying resolutions.
'''Bug fixes'''
* '''Platform independent'''
** '''EV_DRAWABLE''' - `draw_text' and `draw_text_top_left' now both support text containing new line characters.
** '''EV_APPLICATION''' - `focused_widget' had a side effect which may modify the index of some containers.
** '''EV_DYNAMIC_TREE_ITEM''' - fixed `count' which was not executing the subtree function as necessary when called.
** '''EV_TREE''' - Fixed bug in `has_recursively' which failed if there were one or more dynamic tree items contained.
** '''EV_MULTI_COLUMN_LIST''' - Fixed bug in `set_column_alignments' which crashed if you called it with an empty list after having previously called it with a non empty list.
** '''EV_FIGURE_TEXT''' - Fixed bounding size issues which would cause the `width' and `height' to be returned incorrectly, causing them to be not correctly cleared when moved in a figure world.
** '''EV_FIGURE_GROUP''' - Fixed both `append' and `make_from_array' which were not setting the `group' of each item inserted.
* '''Windows'''
** '''EV_WINDOW'''
*** `move_actions' was always passing positive values for the x and y coordinates of the window, even if they should have been negative.
*** Showing two or more dialogs relative to a window and then hiding the focused relative dialog could cause the window to move being the next window in the Z order. This has now been fixed.
** '''EV_FONT'''
*** Fixed bug when using `preferred_families' after creating a font via `make_with_values'. The family that was specified was previously ignored.
*** Fixed bug in `copy' which in certain cases could lead to a copied font not exhibiting the typeface as the original, even though no assertions were violated.
** '''EV_SCROLL_BAR''' - Fixed handling of scroll bars with upper values greater than 32,000. Previously, dragging the bar of a scroll bar past this limit, corrupted the position of the bar and the `value'.
** '''EV_TEXT'''
*** Corrected `last_position_from_line_number' which was returning an incorrect position when there were multiple lines of text contained, and you queried the final line.
*** Modified `insert_text' so that the control is no longer scrolled to the top as a result. The original position is now maintained wherever possible.
*** Corrected handling of selection for caret positions greater than 64,000 characters. The following features were broken when using caret positions greater than 64,000: `caret_position', `has_selection', `selection_start' and `selection_end'
** '''EV_SPIN_BUTTON'''
*** Corrected positioning in parent container. In many situations, the spin button mis-behaved and would be moved to the 0x0 pixel position in the parent.
*** Fixed tooltips which were never displayed.
** '''EV_LIST_ITEM''' - Setting a pixmap to an item that was already displayed in a list and had a text would cause the end of the text to be cut off. This is now fixed.
** '''EV_COMBO_BOX''' - Fixed tooltips which were never displayed.
** '''EV_TOOL_BAR''' - Fixed a number of serious GDI leaks, the worst of which occurred when items that had a pixmap were removed from a tool bar.
** '''EV_PROGRESS_BAR''' - Fixed bug which was limiting values in the range 0 to 65535.
** '''EV_TEXT_FIELD''' - calling `set_font' now updates the `minimum_height' of the text field so that it is large enough to completely display the font.
* '''Gtk'''
** '''GTK 2.4''' EiffelVision 2 has been completely upgraded from gtk 1.2 to version 2.4 and provides completely new implementations for EV_LIST, EV_COMBO_BOX, EV_FILE_DIALOG, EV_MULTI_COLUMN_LIST, EV_CLIPBOARD, EV_MENU, EV_TREE, EV_FONT, EV_PIXMAP using the latest gtk widget set
** '''EV_WIDGET''' Fixed a screen positioning for all widgets
** '''EV_GAUGE''' Fixed bounds setting
** '''EV_DIALOG''' Now key presses work whilst in Pick and Drop
** '''EV_WIDGET''' Now motion events pass x and y coordinates relative to the captured widget
==EiffelStudio 5.4==
'''Interface modifications'''
* '''EV_ITEM_PIXMAP_SCALER''' - New class added which provides no new functionality, but is a clean abstraction of `pixmaps_width', `pixmaps_height' and `set_pixmaps_size' which were all defined independently in EV_TREE, EV_LIST, EV_MULTI_COLUMN_LIST and EV_COMBO_BOX. Your code will not be affected by this change.
* '''EV_TOOL_BAR''' - Added three new features `has_vertical_button_style', `enable_vertical_button_style' and `disable_vertical_button_style'. The default style for buttons is vertical and was the only style previously available, in which the `pixmap' is displayed above `text'. When vertical style is disabled, the `pixmap' of a button will be displayed to the left of its `text'.
* '''EV_TREE ''' - No longer inherits EV_TREE_NODE_CONTAINER which is now obsolete. Made `selected' obsolete, use selected_item /= Void instead.
* '''EV_TREE_NODE''' - Now inherits EV_TREE_NODE_LIST instead of EV_TREE_NODE_CONTAINER. This provides more functionality at the level of the node, but does not change the features available in non deferred descendents, as they all previously inherited EV_TREE_NODE_LIST. Changed type of `parent' to EV_TREE_NODE_LIST from EV_TREE_NODE_CONTAINER. Removed three obsolete features - `align_text_left', align_text_center' and `align_text_right'.
* '''EV_TREE_ITEM''' - Strengthened `is_expandable' so that it checks `parent_tree' is not Void, this brings it into line with the preconditions of `expand'.
* '''EV_DYNAMIC_TREE_ITEM''' - Strengthened `is_expandable' to check `parent_tree', in line with preconditions of `expand'. Added "valid_operands" precondition to `set_subtree_function' which ensures that you only pass a function with valid operands.
* '''EV_TREE_NODE_CONTAINER''' - Now obsolete, you should use EV_TREE_NODE_LIST instead.
* '''EV_MULTI_COLUMN_LIST''' - Added missing postconditions to `align_text_left', `align_text_right', `align_text_center' and other miscellaneous features that were missing relevant postconditions.
* '''EV_MENU''' - Tightened preconditions of `show' and `show_at' to ensure that the menu is not parented.
* '''EV_TEXT''' Added `has_word_wrapping', `enable_word_wrapping' and `disable_word_wrapping'. These features allow you to switch between horizontal word wrapping, in which lines too long to be displayed will be wrapped, and no word wrapping, in which horizontal scroll bars will be displayed, allowing you to view the complete contents of each line. Previously EV_TEXT would always wrap lines, and the default behavior is `has_word_wrapping' as it was before these changes.
* '''EV_TEXT_COMPONENT''' - Added `has_selection' precondition to `selected_text' which requires that `has_selection' must be True for you to call `selected_text'.
* '''EV_FILE_DIALOG''' - Added `valid_file_title' for validation of a file name excluding the path.
* '''EV_STANDARD_DIALOG''' - Corrected postcondition of `make_with_text' which was checking that `text' was the same object as the STRING passed as an argument. This was incorrect, as `text' is cloned during the creation.
* '''EV_WIDGET''' - Added `remove_real_target' which ensures that `real_target' is Void.
* '''EV_WIDGET_ACTION_SEQUENCES''' - Added `mouse_wheel_actions', fired each time that the mouse wheel is scrolled.
* '''EV_NOTEBOOK''' - Now inherits EV_FONTABLE permitting a font to be applied to the item texts.
* '''EV_ENVIRONMENT'''
** Added `mouse_wheel_scroll_lines' which returns an INTEGER corresponding to the number of lines that should be scrolled in response to each mouse wheel scroll event received.
** Added `has_printer' which returns `True' if at least one printer is installed.
* '''EV_PRINT_CONTEXT''' - Added `horizontal_resolution' and `vertical_resolution' which return the page size in pixels of the page type selected from an EV_PRINT_DIALOG. This permits you to adjust the figure world you are printing to an EV_PRINT_PROJECTOR based on the limits of the page, as determined by `horizontal_resolution' and `vertical_resolution' in pixels.
* '''EV_APPLICATION''' - Added `process_events_until_stopped' and `stop_processing', similar to `process_events', except the processing is executed until `stop_processing' is called.
* '''EV_PRINT_PROJECTOR''' - Added `has_printer' check to `make_with_context', ensuring that if you are to print to a printer, at least one printer is available.
* '''EV_PRINT_CONTEXT''' - `default_create' now initializes a set of standard values, permitting the printing to the default printer, using US letter size.
* '''EV_RELATIVE_POINT''' - The features `set_x_abs', `set_y_abs', `set_angle_abs', `set_scale_x_abs' and `set_scale_y_abs' now all have a precondition ensuring that you may only call them while `being_positioned' is True, which is only the case during execution of a custom positioning agent. Previously, if they were called at other times, the values set would be overridden.
* '''EV_FIGURE''' - `accept_cursor' and `deny_cursor' are now available as queries.
* '''EV_ABSTRACT_PICK_AND_DROPABLE''' - `set_accept_cursor' and `set_deny_cursor' no longer accept `Void' arguments.
* '''EV_FIGURE_MATH ''' - 'line_angle' now correctly returns the angle in radians relative to world.
* '''EV_ARROWED_FIGURE''' - 'start_angle' and 'end_angle' now work in all circumstances
* '''EV_FIGURE_STAR''' - First line generated is now created from 'point_b'
* '''EV_FIGURE_EQUILATERAL''' - First point generated is now based upon 'point_b'
'''Breaking changes'''
* '''EV_TREE_NODE_CONTAINER''' - This class is no longer used in EiffelVision2, and if you were relying on it, you should use EV_TREE_NODE_LIST instead. The type of `parent' for tree nodes has been changed from EV_TREE_NODE_CONTAINER to EV_TREE_NODE_LIST, so if you retrieve the `parent' and then attempt to iterate, you may have declared an instance of EV_TREE_NODE_CONTAINER. In this situation, you should simply change the definition to EV_TREE_NODE_LIST instead.
'''Bug fixes'''
* '''Platform independent'''
** '''EV_DYNAMIC_TREE_ITEM''' - No longer crashes if your `subtree_function' returns Void. In this situation, it will now behave as if the `Result' was empty.
** '''EV_BOX''' - Attempting to dock from an EV_DOCKABLE_SOURCE while the box was empty would not work. This has now been fixed.
** '''EV_TEXT_COMPONENT''' - Calling `append_text', `prepend_text' or `insert_text' while `is_editable' is False caused a precondition failure in the implementation which is now fixed.
** '''EV_DOCKABLE_SOURCE'''
*** It was previously not possible to dock to an empty window, as the target was ignored in error.
*** Fixed bug which caused a crash if a dock was attempted to an empty box.
** '''EV_CHECKABLE_LIST''' - Corrected postcondition of `checked_items' which was checking `selected_items' in error, and therefore almost always failing.
** '''EV_APPLICATION''' - Querying `focused_widget' if the window with the focus was empty caused a crash. This has now been fixed, and in this situation, the window itself is returned.
** '''EV_FIGURE_TEXT''' - Fixed handling of `preferred_fonts' from the `font', which was not taken into account. Previously, the default font was always used.
** '''EV_DYNAMIC_LIST''' - Fixed `retrieve_item_by_data' and `retrieve_items_by_data' which were always performing object comparison, even when reference comparison was selected by passing `False' as the second argument.
** '''EV_TREE_NODE_LIST''' - Fixed `retrieve_item_recursively_by_data' and `retrieve_items_recursively_by_data' which were always performing object comparison, even when reference comparison was selected by passing `False' as the second argument.
** '''EV_CONTAINER''' - Fixed bug in `unmerge_radio_button_groups' which would crash if the container had no radio buttons.
* '''Windows'''
** '''EV_TEXT_COMPONENT''' - fixed bug in `select_region' which would fail if `start_pos' was greater than `end_pos'.
** '''EV_PIXMAP'''
*** `expose_actions' previously had a feature contained related to the implementation, and calling `wipe_out' on `expose_actions' would stop the image from being redrawn. There are now no side effects related to `expose_actions'.
*** Calling `copy' on a pixmap that was parented in an EV_CONTAINER, and therefore displayed on screen had no visual effect until the window was re-painted. The image is now updated immediately. Also, using `copy' on a pixmap in a similar situation that was originally set with a masked icon, and passing a pixmap created from a bitmap file would cause a crash.
*** Fixed display error in handling of pixmaps created from a PNG with a transparent color, using `set_with_named_file'. The background would be garbled and partially black.
** '''EV_LIST'''
*** Calling `disable_sensitive' when already non sensitive would loose the original selection, and calling `enable_sensitive' when already sensitive would alter the selected item. The features will no longer alter the selection if called twice.
*** Fixed result of `background_color' which was returning gray instead of white before a color was assigned
'''EV_CELL''' - If you removed the item, the minimum size was not updated to reflect this, thereby retaining the minimum size as constrained by the minimum size of the now removed item.
** '''EV_TREE_ITEM'''/ '''EV_TREE''' - A call to `disable_select' on an EV_TREE_ITEM will now actually remove the selection from the tree. Previously, the style of the item was changed, but a call to `selected_item' on the tree would still return the item.
** '''EV_FILE_DIALOG''' - Fixed precondition violation when you calling `set_file_name' which was rejecting directory separators.
** '''EV_DIALOG''' - Fixed a bug when you had two dialogs displayed modally, with the second modal to the first. If you had a text field within the second dialog whose `return_actions' contained an agent which would destroy the second dialog, the `select_actions' of the `default_push_button' in the lower dialog would be subsequently fired.
** '''EV_LABEL''' - If a label was disabled through the disabling of a container in which it was contained, it would sometimes not be grayed out. This has now been fixed.
** '''EV_PICK_AND_DROPABLE'''
*** `mode_is_target_menu' did not work for a pick and drop source whose `pebble' was generated by a `pebble_function'.
*** Fixed bug where drag and drop was not working as it was attempting to perform docking instead. If both are enabled, docking has priority.
** '''EV_COMBO_BOX_IMP'''
*** Fixed `set_foreground_color' and `set_background_color' which previously did nothing.
*** Fixed bug in selection. If during execution of the `select_actions' of an item contained, you called `enable_select' on another item within the combo box, subsequently selecting the originally selected item would no longer fire its `select_actions'.
*** `enable_edit' and `disable_edit' were both causing the pixmaps of any items contained to be no longer displayed.
** '''EV_PRINT_DIALOG''' - Querying `print_context' from a print dialog if a user selected "Cancel" would previously crash.
** '''EV_TREE''' and '''EV_MULTI_COLUMN_LIST''' - Fixed result of `background_color' which was returning gray instead of white before a color was assigned
** '''EV_SCREEN''' - `widget_at_pointer_position' now returns the combo box if the mouse pointer is held above the drop down list button of a combo box. Previously, `Void' was returned.
* '''Gtk'''
** '''EV_TREE_NODE''' - Now expansion state remains the same when 'set_pixmap' is called.
** '''EV_DIALOG''' - Fixed bug where 100 percent of CPU time was being used when dialog was shown modally.
** '''EV_WINDOW''' - Now sizing invariants are fulfilled when widget is destroyed, preventing segmentation violation.
** '''EV_COMBO_BOX'''
*** Fixed bug where reselecting an item within the combo box list was in fact deselecting it.
*** Now first item remains selected when items are added.
** '''EV_WINDOW''' - Fixed querying of positioning which never changes if previously set by user.
** '''EV_APPLICATION''' - Priority of `idle_actions' has been changed so that gtk will recalculate widgets sizes before calling its idle handler, this means that all resizing is done before idle actions are called.
** '''EV_WINDOW ''' - Now windows correctly shrink when requested size is smaller than current size
** '''EV_PICK_AND_DROPABLE''' - Fixed bug where if both drag and drop and docking were enabled, both would be executed, now docking overrides drag and drop if both are enabled.
** '''EV_TIMEOUT ''' - Now timeouts correctly unregister themselves on dispose preventing segmentation violation.
** '''EV_PIXMAP ''' - Pixmap stretching now works as expected.
** '''EV_WINDOW''' - Now all window specific events work as expected
** '''EV_TITLED_WINDOW''' - Now is_displayed returns false when window is minimized.
** '''EV_TREE_NODE''' - Insertion of children at specific rows now displays as expected.
** '''EV_WINDOW''' - Now windows have a border and are resizable to match Win32 behavior
** '''EV_SPLIT_AREA''' - Now 'split position' honors request when widget resize is pending
** '''EV_DRAWING_AREA ''' - Fixed full size optimization so that all expose actions are handled correctly
** '''EV_TEXT_COMPONENT - ''' Fixed issue where up and down arrow keys caused widget to lose focus unnecessarily
** '''EV_FONT''' - Now preferred families are taken in to account when no style is set
** '''EV_STANDARD_DIALOG '''- Now all file handling dialogs are resizable
==EiffelStudio 5.3==
'''Interface modifications'''
* '''EV_TITLED_WINDOW_ACTION_SEQUENCES''' added which is inherited only by EV_TITLED_WINDOW and provides three new action sequences :- `minimize_actions', `maximize_actions' and `restore_actions'.
* '''EV_TITLED_WINDOW'''
** You may now only call `maximize' and `minimize' if `is_show_requested'.
** When minimized, `is_displayed' now returns False.
* '''EV_BUTTON''' now inherits EV_FONTABLE, allowing you to modify the font displayed.
* '''EV_DYNAMIC_LIST_ITEM''' - Corrected `off' which was using the version inherited from EV_TREE_NODE when it should have been using the version from EV_TREE_NODE_LIST instead.
* '''EV_RECTANGLE''' - Added precondition to `intersects' which stops a Void rectangle being passed as an argument.
* '''EV_TOOL_BAR_SEPARATOR''' - Now export many inherited features to {ANY} instead of {NONE}, including `parent'.
* '''EV_ENVIRONMENT''' - Added `supported_image_formats' which returns a LINEAR [STRING] containing all valid formats by their three letter extension.
* '''EV_CHECKABLE_LIST''' - New class added which behaves as an EV_LIST, except that for each EV_LIST_ITEM contained, an associated check box is displayed.
* '''EV_MESSAGE_DIALOG''' - No longer deferred, and has two creation procedures `default_create' and `make_with_text'.
* '''EV_STANDARD_DIALOG''' - All descendents now have `make_with_text' as a creation procedure'.
* '''EV_TABLE''' - Now inherits CHAIN instead of ARRAY. This is a breaking change, and may require some modification to your code. The inheritance from ARRAY was seriously flawed. For example, if you were to call `extend' on an EV_CONTAINER object that was currently referencing an EV_TABLE, then this would fail. Now that we inherit CHAIN, this problem, among others of a similar nature are fixed. Another advantage of inheriting CHAIN, is that the table may now be iterated which allows for greater flexibility. <br/>
<br/>
The following list details some of the breaking changes, and how to fix them:
** '''item''' - If you were using `item', you should change this to `item_at_position'. A call to `item' will now return the current item.
** '''put''' - If you were using `put', you must now replace this with `put_at_position'.
** '''extend''' and '''replace''' - These are now both exported, as before, they were exported to {NONE}.
** features inherited from '''ARRAY''' - These are no longer available but you may use the feature `to_array', which returns the contents of the table represented as an ARRAY [EV_WIDGET]. This feature is marked as obsolete, as it is temporary, to simplify the transition to the new inheritance structure of EV_TABLE.
** '''count''' - The previous version of `count' was the one from ARRAY, which returned the number of available (not empty) cells in the table. We now use the version of `count' inherited from EV_CONTAINER which returns the number of widgets currently contained. Previously, the feature `widget_count' was used to return the number of items, but this feature has now been made obsolete. Therefore, if you were previously using `count', replace this with `rows' * `columns', and if you were using `widget_count', replace this with a call to `count'.
** '''item_list''' - This is now obsolete. You may use `linear_representation' to retrieve the contents of the table, or simply traverse the table.
* '''EV_FIXED''' - No longer inherits DOUBLE_MATH.
* '''EV_VIEWPORT''' - No longer inherits DOUBLE_MATH.
* '''EV_TEXT''' - `line_count' now returns the number of lines actually displayed, and not just the newline characters, as an EV_TEXT will wrap the text when necessary. The postcondition of `linecount' has been updated to reflect this change.
* '''EV_FILE_DIALOG''' Added "valid_file_name" precondition to `set_file_name' and a new feature `valid_file_name' which checks that a file name is valid on the current platform.
'''Bug fixes'''
* '''Platform independent'''
** '''EV_WIDGET''' - `pointer_style' now correctly returns the Ibeam cursor for textable widgets.
** '''EV_FIGURE_RECTANGLE'''
*** Corrected `bounding_box' which was previously computed incorrectly when the rectangle was rotated.
*** Fixed `width' and `height' which were always returning one less pixel than they should have.
* '''Windows'''
** '''EV_PIXMAP''' - Setting a tile with `set_tile' followed by a call to a fill routine would crash the implementation.
** '''EV_COMBO_BOX''' - Implemented pick and drop.
** '''EV_TEXT_FIELD''' - Implemented pick and drop.
** '''EV_PASSWORD_FIELD''' - Implemented pick and drop.
** '''EV_TEXT'''
*** Implemented pick and drop.
*** If not `is_editable' and a `background_color' had been set, it was only used on lines containing text. The `background_color' is now correctly displayed throughout the whole control when not `is_editable'.
*** Fixed `select_region' which was selecting an incorrect region starting on any line except the first, when the `text' spanned multiple lines.
*** Fixed `selection_start' and `selection_end' which were incorrect when the selection was not completely contained on the first line.
*** Fixed `first_position_from_line_number' and `last_position_from_line_number' which were returning incorrect values when the text was wrapped.
*** Fixed `caret_position' and `set_caret_position' which were incorrect when the text spanned multiple lines, and the caret was not on the first line.
*** `line_count' now returns the number of lines actually displayed, and not simply the number of newline characters. To query the number of new line characters do :- text.occurrences ('%N')
*** Fixed bug in `search' which was returning -1 instead of 0 when the text was not found.
** '''EV_DRAWABLE''' - Fixed bug when you performed the following: drew a filled shape, called `set_tile' and then drew another filled shape. The tile would not be used on the second fill.
** '''EV_COLOR_DIALOG''' - Querying `color' after a user had canceled the dialog would previously crash a system, if `set_color' had never been called.
** '''EV_COLOR''' - Fixed `set_rgb_with_24_bit' which would fail when called.
** '''EV_BUTTON, EV_TOGGLE_BUTTON''' - The buttons now correctly display a text, pixmap and background color simultaneously. Previously, the background color was never displayed, and either the pixmap or text would be displayed, not both.
** '''EV_PRINT_DIALOG''' - Fixed `set_from_page' and `set_to_page' which were previously not implemented.
** '''EV_LIST'''
*** Fixed a graphical glitch when using `wipe_out' when items were contained that required the horizontal scroll bar to be visible. The scroll bar was not hidden, even though there were no longer any items in the list.
*** Changing the selection behavior between multiple and single selection would cause the scroll bars to become hidden, even if they were necessary. Changing this status will no longer hide the scroll bars if they are required.
** '''EV_TOOL_BAR'''
*** Items that were disabled would sometimes become enabled when other properties of the item were set. For example, performing "my_tool_bar_button.disable_sensitive" followed by "my_tool_bar_button.set_text ("Disabled")" while the button was parented, would result in a sensitive tool bar button. This is now fixed.
*** If you changed the `text' of a tool bar toggle button during the firing of the `select_actions' of the toggle button, the button would become unchecked as a result. This is now fixed, and changing the text will not stop the button from becoming selected.
** '''EV_MULTI_COLUMN_LIST''' - Changing the selection behavior between multiple and single selection would cause the scroll bars to become hidden, even if they were necessary. Changing this status will no longer hide the scroll bars if they are required.
** '''EV_DYNAMIC_TREE_ITEM''' - Calling `set_tooltip' failed and has now been fixed.
** '''EV_TIMEOUT''' - Calling `destroy' more than once on a timeout, caused the implementation to crash, and has now been fixed.
** '''EV_TOOLTIPABLE''' - Tooltips on primitives were not supporting multiple lines and this has now been fixed. Use %N for a line break.
* '''Gtk'''
** '''EV_SCROLLABLE_AREA''' - Items smaller than the area are now positioned correctly.
** '''EV_VIEWPORT'''
*** Widget now works correctly with negative offset values
*** Item position is now handled correctly on item resize.
** '''EV_PIXMAP''' - All drawing routines now flush immediately to screen.
** '''EV_DIALOG''' - Canceling via Enter key is now handled correctly.
** '''EV_LIST''' - Fixed selection of selected item when changing from multiple selection to single selection.
** '''EV_MULTI_COLUMN_LIST'''
*** Row height now incorporates spacing pixel to match the implementation of Windows.
*** Default row height is now slightly larger to be more aesthetically pleasing with smaller fonts sizes.
** '''EV_CONTAINER'''
*** `set_background_pixmap' now works with repeated parenting.
*** Radio group unmerging is now handled correctly.
** '''EV_TEXT_FIELD ''' - Now vertical alignment is identical to that on Windows, including that for text field descendants.
** '''EV_RANGE ''' - Now motions events are passing consistent pointer values instead of sometimes skewed ones.
** '''EV_DRAWING_AREA''' - Now `focus_in_actions' are called in all circumstances.
** '''EV_TEXT'''
*** `scroll_to_line' is now implemented.
*** `line_count' and `current_line_number' now handle lines in text widget and not the text itself.
** '''EV_FIXED''' - Now item sizing is correctly handled in all circumstances.
** '''EV_NOTEBOOK''' - Now tabs are more aesthetically pleasing.
** '''EV_MENU_SEPARATOR ''' - Menu Separators are now more prominent.
** '''EV_TOOLBAR_SEPARATOR - '''Toolbar Separators are now more prominent.
==EiffelStudio 5.2==
'''Interface modifications'''
* '''EV_TEXTABLE''' - `align_text_left', `align_text_right' and `align_text_center' have been extracted into a new class, EV_TEXT_ALIGNABLE which inherits EV_TEXTABLE. All previous descendents of EV_TEXTABLE now inherit EV_TEXT_ALIGNABLE, except EV_TREE_NODE, EV_MENU_ITEM, EV_LIST_ITEM and EV_TOOL_BAR_BUTTON
* '''EV_TEXT_COMPONENT''' - Now inherits EV_TEXTABLE.
* '''EV_TEXT_ALIGNMENT_CONSTANTS''' - New class added to support EV_TEXT_ALIGNABLE.
* '''EV_MENU_ITEM_LIST''' - `parent' is now of type EV_ANY, instead of EV_MENU_ITEM_LIST as it did not hold for EV_MENU_BAR. The renaming of `parent' to `old_parent' in EV_MENU_BAR has now been removed.
* '''EV_VIEWPORT''' - added `set_item_width', `set_item_height' and `set_item_size'.
* '''EV_TABLE'''
** redefined `prunable' to `True' and implemented `prune'.
** Added the following features - `set_item_span', `set_item_position', `set_item_span_and_position', `area_clear_excluding_widget', `item_row_span', `item_column_span', `item_row_position' and `item_column_position'.
* '''EV_WIDGET''' - Changed type of `focus_in_actions' and `focus_out_actions' from EV_FOCUS_ACTION_SEQUENCE to EV_NOTIFY_ACTION_SEQUENCE. `is_parent_recursive' is no longer available. It has been moved to EV_CONTAINER. This was necessary to fix a catcall encountered using vision2 under .NET. The problem manifested with widgets that held items.
* '''EV_FIGURE''' - `proximity_in_actions' and `proximity_out_actions' are now obsolete.
* '''EV_FONTABLE''' - `set_font' now sets a copy of the font internally.
* '''EV_TREE''' - `ensure_item_visible' and `has_recursively' now take an EV_TREE_NODE as arguments, instead of an EV_TREE_ITEM.
* '''EV_TEXT''' - `put_new_line' is now obsolete. Use `set_text ("%N") instead."
* '''EV_APPLICATION_ACTION_SEQUENCES''' - Added `cancel_actions', fired when a pick and drop is canceled, and `pnd_motion_actions' fired while the pointer moves during a pick and drop.
* '''EV_TREE_NODE_LIST'''
** `find_item_recursively_by_data', `has_recursively' and `recursive_do_all' are now implemented in this class, instead of both EV_TREE and EV_TREE_NODE which are descendents.
** Added `retrive_items_recursively_by_data' and `retrieve_item_recursively_by_data' which allow you to specify a comparison criterion, and due to this addition, `find_item_recursively_by_data' has now been made obsolete.
* '''EV_DYNAMIC_LIST''' - Added `retrieve_item_by_data' and `retrieve_items_by_data'.
* '''EV_ITEM_LIST''' - Made `item_by_data' obsolete, as you should now use `retrieve_item_by_data' added in EV_DYNAMIC_LIST.
* '''EV_DIALOG''' - Added `is_relative' and defined `is_modal' in this class, instead of inheriting it from EV_WINDOW.
'''Bug fixes'''
* '''Platform independent'''
** '''EV_FIGURE_POLYLINE''' - Fixed `start_angle' and `end_angle' so that they are computed relative to the first and last polyline segments. This also fixes the start and end arrows, so that when displayed, they now actually point in the direction of their respective line segments.
** '''EV_TREE and EV_TREE_NODE''' - Fixed `find_item_recursively_by_data' which failed on the `index_not_changed' postcondition. Note that these features are now defined in EV_TREE_NODE_LIST.
** '''EV_DYNAMIC_TREE_ITEM''' - Fixed invariant violation from EV_ITEM_LIST, when created with `default_create'.
* '''Windows'''
** '''EV_RADIO_BUTTON''' - The default minimum height after `default_create' is now enough to display the widget correctly.
** '''EV_CHECK_BUTTON''' - The default minimum height after `default_create' is now enough to display the widget correctly.
** '''EV_NOTEBOOK''' - When removing a widget from a notebook, it is now visible. Previously, the widget would be hidden.
** '''EV_LIST, EV_MULTI_COLUMN_LIST, EV_TREE''' - Fixed `set_foreground_color' and `set_background_color'. Previously, calling these features did nothing.
** '''EV_BOX''' - If a widget was not`is_item_expanded', then adding a new widget to the box before that widget would sometimes cause a different widget to become `is_item_expanded'.
** '''EV_TOOL_BAR_RADIO_BUTTON''' - The currently selected button in `peers' was unselected when the button was pressed, and not when it was really selected. This bug made it possible to make `selected_peer' Void, which caused an invariant to fail.
** '''EV_LIST_ITEM''' - Calling `enable_select' when parented in an EV_LIST now also sets the item as focused in the parent. This corrects bugs in keyboard navigation when selecting an item programatically.
** '''EV_FIXED''' - The minimum size is constrained by the positions and sizes of the children (They must be completely displayed), although when the positions of the children were reduced, the minimum allowable size was not recomputed. This meant that the widget would be enlarged when the positions of the children increased, but could never be reduced in size when the positions of the children were decreased.
** '''EV_MENU and EV_MENU_ITEM''' - `set_pixmap' has been implemented as previously, it did nothing.
** '''EV_TABLE''' - re-implemented resizing calculations to fix numerous problems when children had minimum sizes. The minimum size now also includes the border width when empty.
** '''EV_NOTEBOOK''' - `selection_actions' were called when you selected an item through `select_item', even if the item was already selected. `selection_actions' are now only fired when the selection changes.
** '''EV_TREE_ITEM''' - calling `set_pixmap' twice successively with the same EV_PIXMAP caused a postcondition failure.
** '''EV_TEXT''' - Fixed `put_new_line', although it has been made obsolete, as you should just use `append_text ("%N") instead.
** '''EV_SPLIT_AREA''' - Fixed crash reproducable by inserting an EV_PIXMAP directly into the split area.
** '''EV_CONTAINER''' - Fixed `propagate_foreground_color' and `propagate_background_color' which failed when one of the children was a descendent of EV_CELL.
** '''EV_APPLICATION_ACTION_SEQUENCES''' - `drop_actions' was being fired even when the pick and drop was canceled.
** '''EV_PIXMAP''' - Previously, if you were to add an agent to an action sequence of the pixmap, before it was parented, the agent would be removed during the parenting.
** '''EV_MENU'''
*** Pruning an EV_MENU_SEPARATOR when one or more EV_RADIO_MENU_ITEM were still contained in the menu would cause occasional crashes.
*** Previously, when adding an EV_MENU_SEPARATOR, followed by multiple EV_RADIO_MENU_ITEMS, all the items were being selected.
*** Fixed bug in `destroy' which was causing postcondition failures.
** '''EV_TITLED_WINDOW''' - Fixed a GDI leak, manifesting when a window was destroyed.
** '''EV_DIALOG'''
*** Fixed `is_modal' which was previously always returned `False'.
*** Fixed bug with `background_color' and `foreground_color' which was not taken into account if the dialog was shown relative or modally to another window.
*** If a dialog with a default cancel button was displayed using `show', then minimizing the dialog would cause the system to fail internally.
*** Fix bug in `show_relative_to_window' which would cause any associated menus to be removed.
*** Fixed bug in `show', as if the dialog had already been shown modelessly to a window, then calling `show' did not show it independently, but still modelessly.
*** Fixed bug with `show_actions' which would be wiped out if you called `show_modal_to_window' and then `hide'.
*** `set_pixmap' will now actually display the pixmap, whereas before, no pixmap was displayed.
** '''EV_TEXT_COMPONENT''' - Fixed `text_length' which was returning incorrect value for all descendents.
** '''EV_TEXT''' - Fixed `line_count' which was previously returning the correct result + 1.
** '''EV_SCROLLABLE_AREA''' - Fixed crash which occurred when you attempted to use `set_x_offset' or `set_y_offset' before the area had been parented or displayed.
** '''EV_FONTABLE''' - Fixed bug when `font' was queried, `preferred_families' was not returned correctly, and would always be empty.
** '''EV_CONTAINER''' - `set_background_pixmap' was not correctly cloning the image of the pixmap, and the displayed image could then be modified after setting, by changing the image of the original pixmap.
* '''Gtk'''
** Remaining EV_WIDGET memory leaks have been fixed.
** '''EV_WIDGET'''- Focus in/out actions are now correctly called for widgets that do not occupy their entire space allocation such as EV_TEXT_FIELD.
** '''EV_DRAWABLE_IMP''' - Polylines now display correctly on big-endian machines (Sparc, PowerPC).
** '''EV_KEY'''
*** `out' is now correct for all keys (previously Quote and Backquote were incorrect).
*** The events for all keys are now fired when Shift is held down.
** '''EV_STOCK_PIXMAPS''' - Warning and error pixmaps have been updated.
** '''EV_WINDOW''' - `remove_title now' works will all Window Managers.
** '''EV_TITLED_WINDOW'''
*** `propagate_foreground_color' is now fixed in use with pixmaps as children.
*** `set_maximum_size' now works as expected
*** `set_minimum_width' now has no effect on Window height.
*** calls on `minimize' before `launch' now satisfies all assertions
*** calling `destroy' twice now doesn't fail on precondition.
*** `set_position' now satisfies post-condition in all situations.
*** `resize_actions' are now passed the correct values.
*** `move_actions' are now called correctly.
** '''EV_NOTEBOOK''' - now satisfies invariants when empty.
** '''EV_DIALOG'''
*** Destroy now satisfies all invariants.
*** Reported memory leaks now fixed.
** '''EV_LABEL''' - Size is now taken from default gtk style size instead of hard coded 10
** '''EV_FONT''' - Font caching is now vastly improved in terms of speed.
** '''EV_DRAWABLE''' - Calls to `set_font' are now also vastly speeded up.
** '''EV_TABLE'''
*** Memory management is now correct on item removal.
*** Now setting child's parent correctly
** '''EV_TREE_NODE'''
*** Fixed all reported issues regarding item insertion and removal.
** '''EV_CONTAINER''' - Fixed remaining issues with radio grouping and merging.
** '''EV_PICK_AND_DROPABLE''' - Now drop_actions may destroy `Current' without crash.
** '''EV_TEXT_FIELD'''
*** Now default `minimum_width' is reasonable (before 148, now same as Windows being 4 characters wide)
*** Fixed `caret_position' when queried in change actions
==EiffelStudio 5.1==
'''Interface modifications'''
* '''EV_TEXTABLE and EV_TEXT_COMPONENT''' - `text' no longer returns Void when empty.
* '''EV_WINDOW''' - `title' no longer returns `Void' when empty.
* '''EV_TOOLTIPABLE''' - `tooltip' no longer returns `Void' when empty. If empty, no tooltip is displayed.
* '''EV_TITLED_WINDOW''' - `icon_name' no longer returns `Void' when empty.
* '''EV_CLIPBOARD''' - `text' no longer returns `Void' when empty.
* '''EV_MESSAGE_DIALOG''' - `text' no longer returns `Void' when empty.
* '''EV_FILE_DIALOG''' - `file_name' no longer returns `Void' when the "Cancel" button was pressed, `Result' is empty instead.
* '''EV_DIRECTORY_DIALOG''' - `directory' no longer returns `Void when the "Cancel" button was pressed, `Result' is empty instead.
* '''EV_CONTAINER''' - has three new features `set_background_pixmap', `background_pixmap' and `remove_background_pixmap'. `background_pixmap' will be tessellated to cover complete background area.
* '''EV_TREE and EV_TREE_NODE''' - Added `recursively_do_all'.
* '''EV_STANDARD_DIALOGS'''
** `ok_actions' have been renamed in descendents where appropriate. e.g. in EV_PRINT_DIALOG, they are renamed to `print_actions' to match the texts of the associated buttons. Where renamed, `ok_actions' are still available but obsolete.
** Selected button now also returns the correct text of the button (Previously it was always "Ok").
* '''EV_DIALOG_CONSTANTS''' - Added new constants required for the above change to EV_STANDARD_DIALOGS.
* '''EV_DRAWABLE''' - `draw_straight_line' now has a precondition to ensure the points are not identical.
* '''EV_SPLIT_AREA''' - separated `put' from `extend'. They were defined as synonyms, but have different behavior.
* '''EV_DYNAMIC_TREE_ITEM''' - Added `remove_subtree_function'. Item now only shows as expandable if there is a subtree function.
* '''EV_WINDOW''' - Added `maximum_dimension' which is the greatest value allowed for `width' and `height'. This is also the default value for `width' and `height'.
* '''EV_OPTION_BUTTON''' - This class has been made obsolete. It will be removed at the next release.
* '''EV_PICK_AND_DROPABLE_ACTION_SEQUENCES''' - Added `pick_ended_actions' which are called when a pick ends.
* '''EV_WIDGET''' - `set_minimum_height', `set_minimum_width' and `set_minimum_size' now all allow 0 as an argument. Previously, 1 was the minimum valid dimension.
* '''EV_MULTI_COLUMN_LIST''' - `clear_selection' is now obsolete. Use `remove_selection' instead.
'''Bug fixes'''
* '''Platform independent'''
** '''EV_FIXED''' - Corrected `set_item_height', which was failing.
** '''EV_SELECTABLE''' - Corrected postcondition of `is_selected'.
** '''EV_PND_ACTION_SEQUENCE''' -- `veto_pebble_function' is now only called when its argument conforms to the transported pebble.
* '''Windows'''
** '''EV_RANGE''' - The `maximum_value' could not be set greater than 32,000. The full range of an INTEGER may now be set.
** '''`focused_widget' from `EV_APPLICATION'''' - was incorrect if an EV_CONTAINER had just received the focus.
** '''EV_PICK_AND_DROPABLE'''
*** Ending a pick and drop on an EV_TOOL_BAR_BUTTON which has a non `void' pebble no longer starts a transport from the button.
*** Reduced flicker on cursor when picking from an EV_TREE_ITEM or EV_LIST_ITEM.
*** `pebble_function' would previously be called twice during a pick and drop.
** '''EV_FIXED''' - Items contained are now drawn correctly dependent on their z order.
** '''EV_DRAWABLE'''
*** `Remove_clip_area' did not remove the clip_area correctly, but set it to the current size. This meant that if you then enlarged the widget, clipping would be applied.
*** Fixed problems with ordering of calls to certain features which would cause postcondition violations in the implementation.
*** `draw_pie_slice', `fill_pie_slice' and `draw_arc' now have divide by 0 protection in the implementation.
** '''EV_TEXT''' - `set_background_color' now correctly sets the color of the whole background. Previously only the area containing text was modified.
** '''EV_CLIPBOARD''' - Our implementation would sometimes query `text' when not allowed by Windows, thus causing postcondition failures.
** '''EV_BUTTON''' - The result of `text_alignment' after default_create was incorrect.
* '''Gtk'''
** Gtk version of Studio released (including Vision2), so no fixes from 5.0

Some files were not shown because too many files have changed in this diff Show More