1. Figure Classes
      1. Figures
      2. Points
      3. Relative Point
    2. Figure Worlds
    3. Projectors
    4. Events
    5. Rotation and Scaling

Review requested: see definition.

The EiffelVision 2 figure cluster provides a high-level way of drawing on an EV_DRAWABLE descendant. It offers a number of advantages:

  • The model (tree of figures) is separated from the graphical representation by using projectors that take a "world" (an entire set of figures) and project it onto any device, not just a drawing area.
  • Instead of drawing with static APIs like draw_line, you can use real figure objects, which internally remember their location, rotation and scaling; later on you can perform limitless transformations on them, either individually or as part of an entire branch in the tree of figures: move, rotation, scaling, change of color...
  • For projection devices that support the mouse, pointer events propagate to the affected figures.

Figure Classes

Every basic figure class inherits from EV_ATOMIC_FIGURE. An atomic figure has the property of having its own graphical representation. EV_FIGURE_GROUP on the other hand is a collection of figures. Finally, EV_FIGURE is the common ancestor to those two. Since EV_FIGURE_GROUP is a collection of EV_FIGUREs, it can contain both atomic figures and subgroups, thus forming a tree of figures.

Any "branch" of that tree that wishes to be drawn (i.e. rendered to a device or file) (especially the top-level root) must be a figure group of type EV_FIGURE_WORLD. It inherits from EV_FIGURE_GROUP, and adds some features for grid and background color, required for drawing.


class open/closed points description
EV_FIGURE_ARC open 2 a segment of an open ellipse
EV_FIGURE_DOT open 1 a single point
EV_FIGURE_ELLIPSE closed 2 an ellipse inside imaginary rectangle
EV_FIGURE_EQUILATERAL closed 2 a figure with any number of sides of the same length
EV_FIGURE_LINE open 2 a straight line between two points
EV_FIGURE_PICTURE open 1 an image positioned by its top-left point
EV_FIGURE_PIE_SLICE closed 2 a part of a closed ellipse
EV_FIGURE_POLYGON closed * a figure defined by any number of points
EV_FIGURE_POLYLINE open * a figure consisting of any number of connecting lines
EV_FIGURE_RECTANGLE closed 2 a figure with four sides
EV_FIGURE_STAR open 2 any number of lines emerging from a center point
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 EV_CLOSED_FIGURE which gives them the property fill_color. Open figures inherit EV_ATOMIC_FIGURE directly, as does EV_CLOSED_FIGURE.


Central in the design of the figures are points. Figures are defined from their points. For example, an ellipse is not a center point with two radii, but is instead the largest 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 are:

These classes offer features to handle the given number of points. EV_SINGLE_POINTED_FIGURE offers the feature:


EV_DOUBLE_POINTED_FIGURE inherits EV_SINGLE_POINTED_FIGURE for its first point, which is renamed to point_a. It adds point_b, so it has the features:


EV_MULTI_POINTED_FIGURE internally holds an array of points:


Relative Point

The points that the figures use are of type EV_RELATIVE_POINT. Each point is relative to the location of the parent figure group (point), which is relative to the location of its parent figure group, and so on up to the top-level (world) figure group. Thus, each figure is defined by a set of relative points and a reference point (origin). If the reference point is not attached (as may be the case for immediate children of the top-level group, when it has no point object), the subordinate relative points are relative to point (0,0). The absolute coordinates are calculated only when needed by adding the absolute coordinates of the reference point to the relative coordinates.

Note: Even the top-level (world) figure group can be "moved" by calling its set_point feature, passing a new relative point. However, if this is done, then THAT relative point is relative to point (0,0). If you do this, do so before extend-ing it with figures and sub-groups so that they receive the point in question as their reference point.

Figure Worlds

In order to put the figures you want to display in a context, you insert them (or the figure groups that contain them) into a top-level a "figure world" object: an instance of EV_FIGURE_WORLD. This is a descendant of EV_FIGURE_GROUP and hence works in the same way. This figure world is later associated with one or more projectors. EV_FIGURE_WORLD, as previously mentioned, adds a number of features to EV_FIGURE_GROUP. These extra features are needed for graphical representation by a projector. One is the background color. This feature is used to erase the canvas for a graphical projector in the specified color. The other features are to manage the grid.


A projector is an object that knows what a figure world should look like. The figure world itself is only a hint of its representation. For example, if a line is "20" long, this might mean 20 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" of figures onto its device.

With EiffelVision come these projectors:

The first one maps figure worlds to a postscript file. The other two are descendants of EV_WIDGET_PROJECTOR, and can project on widgets that inherit from EV_DRAWABLE, two of which are EV_DRAWING_AREA and EV_PIXMAP, eventually using double-buffering, which normally results in a smoother animation but requires fast copying from memory to the video buffer (and thus can be slow if the display is remote).


The other features of drawing area and widget is that they generate pointer events. These events are translated by projectors to the map of the figure world. These projectors send the event to the appropriate figure. Every figure is set up to receive all the common pointer events, including Pick-and-Drop events:

  • pointer_motion_actions
  • pointer_button_press_actions
  • pointer_double_press_actions
  • pointer_button_release_actions
  • pointer_enter_actions
  • pointer_leave_actions
  • pick_actions
  • conforming_pick_actions
  • drop_actions

There are no events for keyboard focus and no key press events. If you need to use these events, use them from 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 "figure world". The first item of a figure group is the figure that is the farthest away. Any figure can be obscured by (visible) figures in front of it. Events are only received by a figure when the (mouse) pointer is over its exposed areas, i.e. areas not obscured by (visible) figures in front of it. If a figure is fully obscured by visible figures in front of it, then it will receive no pointer events.

Rotation and Scaling

Relative Points, which supply the location, scale and orientation for EV_FIGURE_... objects, also support rotation and scaling. Both rotation and scaling can be entered at any point in the tree of relative points. One of the most useful of these points is the point of an EV_FIGURE_GROUP, which rotation and/or scaling will then propagate down the tree to all the contained figures and sub-groups, by way of something like my_figure_group.point.set_angle (...). Rotation is in radians progressing counter-clockwise from the positive X axis. Scaling is multiplied into the chain of relative 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 the same for rotation.

The scaling factor has two components: horizontal (x) and vertical (y), which can be set separately or together. If the x/y scaling factor is 0.5, everything at that point and below in the tree is displayed at half its normal size.