[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.6.2 Components

The base class for windowing system is `csComponent'. `csComponent' is a very complex class with a lot of built-in functionality. This allows for easier creation of new components for specific needs. Most `csComponent' methods are virtual, allowing you to override them if needed. There are some basic methods, which are described below. Other methods are described as needed later in this document.

Drawing: csComponent::Draw()

Each component should know how to paint itself. When windowing system thinks a part of a component image or entire component image is invalid (for example, when a window is moved from the top of other components), it adds that rectangle to the dirty rectangle of the component. The dirty rectangle is initially empty, then all invalid rectangles are added to it. At the end of each frame windowing system sends a broadcast event with `cscmdRedraw' command code. When component catches this event, it calls Redraw() method which in turn calls csComponent::Draw(). After csComponent::Draw() returns control, the dirty rectangle is emptied again. Before calling the Draw() method, Redraw() sets the component's clipping rectangle to the dirty rectangle, so usually you don't have to take care to not draw outside the dirty rectangle; clipping will take care of it for you (to minimize the number of draw operations).

All draw operations are clipped first against dirty rectangle and then against all component children and neightbours. So drawing inside a component does not change even a pixel in other components, even if component is partialy covered by other components.

There are a number of drawing operations that you can use. Other operations can be synthesized from existing. All coordinates used for drawing are component-origin related, so (0,0) corresponds to component top-left corner.

Here is a list of the primitive drawing methods:

Event Handling: csComponent::HandleEvent(iEvent&)

This is the main component entry point for handling windowing system events. Each time user presses a key, moves mouse etc windowing system generates a event and sends it to appropiate component. The normal event flow is top-down, i.e. the root window receives events first, then passes them if appropiate to its children which passes it to their respective children and so on. However, there are some basical constraints on event flow that you should know about:

Aside from the exceptions above, in all other cases the events are processed from the root of the component's hierarchy (e.g. the `csApp' object) down along every branch and can reach every component in the tree (unless the event is eaten somewhere). Other than broadcast events, any "true" return code from a component's HandleEvent() method means that the event has been eaten and should not be sent to any other components. The tree-like event propagation is performed by csComponent::HandleEvent(), in addition to a lot of other important things, thus you always should call the parent class' HandleEvent() method to avoid confusing the windowing system.

There is another method called csComponent::PreHandleEvent() which is much like HandleEvent() except that it is called for each event pulled from event queue before HandleEvent(), and without rules above, i.e. any component can preprocess any hardware-generated event before it is sent along normal event handling chain. This can be used for popup menus, hot keys and so on. If PreHandleEvent() returns true, the event is considered eaten and is discarded. Be careful with this feature to avoid interfering with normal component functions.

And last method related to event processing is csComponent::PostHandleEvent(). It is called when no component handled the event and it is called for all components in parent-to-child order. It can be used to process events that nobody wants, for example it is used to process hotkeys on buttons (if active component is for example, a input line, and user presses A key it should be entered into input text, while if active component is a non text-hungry component (for example, a list box) the A key can be used by some button to activate itself).

`csComponent' Members

The `csComponent' class has a number of data fields. The most important are summarized here.

csRect bound
This defines the physical bounds of the component. All drawing operations happens inside and are clipped to this bound. Component does not have control over any other pixel outside this bound. The bounds are defined relative to parent's origin. For example, if we have a component with bounds (xmin = 20, ymin = 10, xmax = 100, ymax = 50) and it has a child at (10, 10, 30, 40) then its real (physical) pixel coordinates are (20+10, 10+10, 20+30, 10+40). A child is always clipped to the bounds of all its parents (however, there is a exception from this rule).

int state
Contains the state flags of the component. There are two types of state flags (although CSWS does not make a difference between them)--dynamic flags and option flags. Option flags usually define some static aspect of component--for example, whenever component is selectable (i.e. if it can become the focused element), or it is partially transparent (see irregularily-shaped components) etc. Dynamic flags often changes during component's life, for example component visibility flag, "component focused" flag and so on. The component state flags starts with the `CSS_' prefix.

You should never manually change state flags. Instead, there are two methods for this: SetState(mask, state) and GetState(mask). For example, if component is not selectable and you want to make it selectable, call component.SetState(CSS_SELECTABLE, true). The SetState() method is virtual and is often overriden to execute some specific functions when component state changes. For example, default SetState() handler shows or hides the component if `CSS_VISIBLE' flag state changes.

csRect dirty
Contains the dirty rectangle. If it is non-empty, the dirty area of component is redrawn just before the end-of-frame.

int DragStyle
Contains a combination of bits (defined by constants with names such as CS_DRAG_XXX) that defines which sides of component can be dragged with mouse when you call first the csComponent::Drag() method. By default it is equal to `CS_DRAG_ALL'. Note that if component won't call csComponent::Drag() you won't be able to resize the component even if `DragStyle' is equal to `CS_DRAG_ALL'.

csApp *app
This is the "main" application object; the root of entire window tree. It is a descendant of `csApp' class which is a superclass of `csComponent'. `csApp' has some application-global methods such as `CaptureMouse', `CaptureKeyboard', it contains the global mouse pointer object and many other.

csComponent *parent
Contains the parent component. Components are chained into a tree, each component knows its neightbours (through `next' and `prev' fields), each parent knows its focused child, and can traverse its list of children by starting from focused, then going to focused-to-next and so on.

csComponent *prev
csComponent *next
Contains the next and previous neightbours in parent's child list. They are never NULL, chains are always closed. If a component is the only child of another, its next and prev fields points to himself.

csComponent *focused
This is the focused child component. For example, keyboard events are sent only to components in focused chain, i.e. to `app', `app->focused', `app->focused->focused' and so on. If component does not have any child components, focused is NULL. This is the only possible case when "focused" can be NULL.

csComponent *top
This is the top component in Z-order. Mouse events are processed in Z-order unlike keyboard events. The focused event is not neccessarily the top component, although usually this is true. If component has `CSS_TOPSELECT' flag set, when user activates (focuses) a component, it is made the topmost, however if it has this flag reset, its Z-order does not change.

int id
This is component's identifier. This is a user-definable value, but it is expected to be unique within all children of a parent component. You can search for child components with given identification by calling parent->GetChild(int find_id).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

This document was generated using texi2html