Fenestra User's Guide (appendix B) -- contents | previous | next
Pylon is the foundation that is used to support to both the implementation of the main library and the communication with library clients when classes from the Eiffel standard kernel library are not sufficient.
A library client need not use this cluster for its own data structures. In this case, it is not necessary to study the full Pylon manual [pylon96] in order to know what is needed to use the few classes that are used in the interface of the GUI clusters. This section documents precisely this usage.
The Pylon classes which are used by the public interface of Fenestra are ordered lists, basic persistence and the date and time abstraction.
Pylon's lists are ordered but not sorted, that is any iteration will go through the items in a definite order. Therefore, the order changes only on request, such as when the list client adds, deletes or inserts elements, or orders a sorting operation.
Lists are accessed through the abstract class P_LIST which is a generic class whose generic parameter is the item type. Typical concrete implementations are linked lists, like P_LINKED_LIST or arrayed lists. If a client needs to create a list in the GUI library context, it is most likely to need an instance of P_LINKED_LIST.
An abbreviated version of the flat-short form of P_LIST with the features useful for this usage follows:
deferred class interface P_LIST [G] indexing cluster: pylon, container; description: "Abstract list (traversable collection)"; interface: abstract; feature specification -- Duplication copy (other : like Current) -- GENERAL's copy. -- Time: O(other.count) require other_not_void : other /= void; conformance : other.conforms_to (Current); ensure result_is_equal : is_equal (other); feature specification -- Comparison is_equal (other : like Current) : BOOLEAN -- GENERAL's equality relation (requires covariant arguments). -- Time: O(count) require other_not_void : other /= void; is_equal_list (other : P_LIST [G]) : BOOLEAN -- Compare two lists which can be of different dynamic type. -- Time: O(count) require valid : other /= void; feature specification -- Conversion from_list (other : P_LIST [G]) -- Convert from another list. -- Note: The previous contents of this list is deleted. -- Time: O(other.count) require valid : other /= void; ensure done : is_equal_list (other); keep_reference : -- keep copy of items. from_array (other : ARRAY [G]) -- Convert from an ARRAY. -- Note: The previous contents of this list is deleted. -- Time: O(other.count) require valid : other /= void; ensure done : other.count = count; keep_reference : -- keep copy of items. from_iterable (it : P_ONEWAY_ITERATOR [G]) -- Convert from a one way linear iterable container. -- Note: The previous contents of this list is deleted. -- Time: O("it.count") require valid : it /= void; initialised : it.outside; ensure keep_reference : -- keep copy of items. to_array : ARRAY [G] -- Convert list to ARRAY. -- Time: O(count) ensure done : is_empty = (Result = void); is_shallow_copy : -- new array, old items. feature specification -- Concatenation append (other : P_LIST [G]) -- Append other container to current. -- Time: O(other.count) require valid : other /= void; ensure keep_reference : -- keep copy of items. append_iterable (it : P_ONEWAY_ITERATOR [G]) -- Append the items from a linear iterator. -- Time: O("it.count") require valid_iterator : it /= void; initialised : it.outside; ensure keep_reference : -- keep copy of items. feature specification -- Iteration iterator : P_ITERATOR [G] -- Get a two-way iterator on this container. deferred ensure done : Result /= void; is_shallow_copy : -- Result /= previous Result feature specification -- Iteration is_protected : BOOLEAN -- Is an iterator inside the data structure? feature specification -- Status is_empty : BOOLEAN -- Is the container empty? is_readable : BOOLEAN -- Is the container currently readable? is_writable : BOOLEAN -- Is the structure writable? feature specification -- Update add (it : G) -- Add item to the container. require writable : is_writable; deferred ensure keep_reference : item = it; replace (it : G) -- Replace the current item. require writable : is_writable; not_empty : not is_empty; deferred ensure keep_reference : item = it; insert (it : G) -- Insert item before the current item. require writable : is_writable; not_empty : not is_empty; deferred ensure keep_reference : item = it; remove -- Remove the current item. require writable : is_writable; not_empty : not is_empty; unlocked : not is_locked; deferred feature specification -- Status count : INTEGER -- Number of items in the container. deferred ensure positive : Result >= 0; item : G -- Current item. require readable : is_readable; not_empty : not is_empty; deferred feature specification -- Update reset -- Remove all objects from the container. require writable : is_writable; deferred ensure done : is_empty; invariant protection : is_protected = (not is_writable); empty : is_empty = (count = 0); end interface -- class P_LIST
The procedures to_array and from_array are especially useful when used as a bridge from or to other data structure libraries.
In order to go through every item in a structure the iteration class P_ITERATOR is used. When a valid iterator is being used, the structure cannot be written to, and is_protected is true. The flat short form shows that any non-empty list always has a current item, although it is not used for iteration -- it does not normally change when iterators are manipulated as they have their own attribute for the currently traversed item.
A typical iteration is:
local list : P_LIST[STRING] it : P_ITERATOR[STRING] -- Iterator has same generic type as list. do list := -- ... obtain a list of string from it := list.iterator it.first -- Enter (and protect) the container. variant it.forward_variant -- Iterator provides variant value. until it.outside -- Is iteration finished? loop io.put_string(it.item) -- Print current iterated item. io.put_new_line it.forth -- Step forward. end end
When the iteration is finished -- is_outside is true -- the structure ceases to be protected, as long as no other iterator is inside the containers. It is possible to have several iterators on a single structure.
The basic persistence has been introduced in the `Graphics' cluster where it is presented, section (see section 5.1). It allows to store an object into a string for later retrieval.
The class P_TEXT_OBJECT adds the function to_string and the procedure from_string to objects which inherit from it. Descendant of this class also have to effect two corresponding procedures object_to_string and object_from_string -- exported to the classification class PUBLIC_NONE. Both have an instance of P_TEXT_OBJECT_MANAGER as their parameter which allows to put and retrieve basic types have from and to the string. The manager class interface is very similar to usual Eiffel IO classes -- put_integer, put_string, for output and get_integer and last_integer type of pairs for input, in addition to the boolean in_success which allows the client to check that the value has been properly retrieved.
The benefits of this system is portability among Eiffel compilers and architectures. It is also completely independent of runtime object structures. For instance a rectangle can be saved as a pair of coordinates even if it is implemented as a single coordinate pair and width and height. The implementation of the rectangle can be changed later without the need of the external string representation to be altered.
To give a practical example, the string version of an object like a point, whose attribute values are 200 for x and 300 for y will look like:
which is produced using the following code:
object_to_string(tm : P_TEXT_OBJECT_MANAGER) is do tm.put_integer(1) -- Placeholder for version. tm.put_integer(x) tm.put_integer(y) end string_to_object(tm : P_TEXT_OBJECT_MANAGER) is local version : INTEGER do tm.get_integer version := tm.last_integer tm.get_integer x := tm.last_integer tm.get_integer y := tm.last_integer if not (tm.in_success and then version = 1) then make -- Default values. end end
This illustrates the general scheme: `(' <TYPE> `:' <CONTENT> `)'. Client applications should not interfere with it in any case, although it can be a useful thing to know for debugging. The content is properly encoded if it contains characters like a closing parenthesis. This enables using the string type to enclose compound objects -- a P_TEXT_OBJECT can have another P_TEXT_OBJECT as an attribute.
The first integer is the version number. It is not a part of the P_TEXT_OBJECT facility but is a convention followed by the GUI library to make future evolutions easier.
The last foundation features used by the main library -- in the `System' cluster -- are date and time abstractions, which are missing from the standard library. The Pylon classes are used to represent the time and not to retrieve it which is a system dependent task left to a cluster closer to the operating system.
The main class used is P_DATE_TIME which itself uses P_TIME and P_DATE as clients. This class inherits from P_TEXT_OBJECT which was previously described. It is also a descendant of HASHABLE.
The creation procedure, make, does not take any parameters and initialises the default value. The date is set with set_date which takes year and month and day integer parameters in that order, and set_time which takes hour and minute and second integer values. Alternatively, set can be used to set them all at once. The date and time attributes are instances of P_DATE and P_TIME, with, respectively, integer attributes year, month, day and hour, minute, second. These classes can be manipulated directly when necessary.
The date and time class also handles the time zone. It is possible not to specify a time zone: the boolean value is_local is then set to true. The time zone is set using set_timezone_bias, specified in minutes (positive or negative depending on the side of UTC). The bias is zero for UTC (formerly known as GMT) and it has to be explicitly set -- otherwise the current instance is local time.
In addition, a few string representations are provided. The function to_iso and its synonym out return the time formatted according to the ISO 8601 standard, for instance ``18870726T140000''. A more readable variant is to_iso_long, e.g. ``1887-07-26 14:00:00''. The time zone information is added when the time is not local, as a bias in hours and minutes. A different alternative is the to_rfc format, ``26 Jul 1887'', introduced in the Internet e-mail standard RFC-822 -- the month names are always in English as RFC-822 specifies.
Various individual string representations for date and time can be obtained from the date and time attributes.