Chapter 1: Overview
1.1: Notice
Except where stated explicitly, the term "Windows" does not refer to a
Microsoft product.
1.2: Purpose
The WDS is a library of derived widgets and related classes built on the EW
abstraction library.
1.3: Design
The Coral libraries exploit the class inheritance provided by C++. New widgets
can easily be derived by adding functionality to existing widgets. The EW/WDS
classes were developed to make the creation of new widgets as easy as possible
without restricting flexibility. An example of inheritance is shown here.
The derivation begins with GPL_DoubleNode, required
for the intrusive doubly-linked-list functionality. The inheritance continues
through EW_Node, which shares some members with windows, and EW_Widget, which
is the base widget functionality.
WDS_Widget adds additional
abilities that are not a part of EW and may not be shared by an alternate
widget set built on EW. All WDS widgets will assume that all other widgets are
derived from WDS_Widget and not directly from EW_Widget. WDS requires features
in WDS_Widget such as run-time type-checking, ties, optional state-change
callbacks, and inheritable look-and-feel.
1.4: Features
1.4.1: Platform Dependencies Completely Abstracted Out by EW
Since WDS is built over the EW abstraction, all the source code written for
WDS and any applications using WDS need not have any notion what platform they
are running on. This means that statements like "#ifdef __sgi" are
never needed. The windowing system and graphics language can be chosen by -D
flags to the compiler and should only be differentiated by EW source,
including headers. Recognized windowing systems are: Win32, X, and MEX
(IrisGL). Available graphics languages are: Xlib, Microsoft GDI, OpenGL, and
IrisGL.
The MEX and IrisGL systems are not current.
The Xt and Motif headers and libraries are not used, so you won't need
them. The commonly used modes are X/Xlib for Unix and Win32/GDI for Win95 or
NT. Windows NT does support OpenGL.
1.4.2: Derived Functionality
With an existing base set of widgets, new widgets do not require writing
complete functionality from scratch. C++ virtual functions can be overridden
or appended to, allowing programmers to create widgets as modifications and
extensions of existing widgets.
1.4.3: Dynamic Inheritable Look-And-Feel
Using the widget run-time type-checking, each derived widget class can
register a default look including:
- Colors including lighting effects
- Border type
- Border depth
- Drawing Inset
- Inheritance
- (etc.)
plus additional widget-specific values, like scrollbar width, stored
union-style. The Inheritance value can optionally specify another widget class
from which values can be inherited. This inheritance path does not have to
follow the C++ inheritance, but that will usually be the case. Any value
(except Inheritance and Initialization Callback) can be specified as
default. If so, other looks are searched for a non-default values. The
search order, starting with each widget instance's personal look is:
widget's instance -> widget's class -> inherited class(es) -> default look -> root window
The root window only holds colors, so any
other value not found once getting to the default look is set to NULL. You can
also map values to a different entry of another look. For example, the map
flag could be used to map the default background color as a widget's
foreground color. The inheritance step can be prevented on a per look-entry
basis. For example, your class "special-button" may wish to default to the
overall background color, but inherit the pen color from "button". This can be
useful to map directly to the overall defaults in case the inherited class has
its own undesired value.
Most of the widgets in WDS have all their
looks set up from a single function in the WDS library. But, widgets derived in
applications can't do this and need to be able to reset themselves "on the
fly" while the application is running. This is intentionally demonstrated in
the class WDS_HierarchyForm under
WDS_HierarchyForm::InitializeLookCallbackInit().
This function, called from the constructor,
sets itself as the Initialization Callback. As such, it
will be called from WDS's own initialization/reset function.
This configurability allows the system (or programmer) to set the
look-and-feel of the widgets to closely match existing systems that users may
already be familiar with, such as Motif, Microsoft Win32, and Athena. The test
example uses these and adds the additional mode, "Coral", which attempts to
expand on the positive attributes of these previous systems.
1.4.4: Dynamic Hierarchial Arrangement
Since WDS uses EW's unrestricted widget hierarchy concept, any widget can be
the child of any other widget. Also, any widget sub-hierarchy can be
instantaneously moved under any other widget (or window), and the GUI
restructures itself automatically. This approach not only makes builders
unneccessary, but exposes their shortcomings. The structure can be easily
dynamically altered The appearance is defined by user's specified (or
default) contraints, not their patience or artistic skill.
1.4.5: Layered Scoping with Event Bypassing
User events normally flow through a subset of the widget hierarchy by
following the widget bounds relative to the mouse location of the event. Many
widgets, especially ones dealing with keyboard input, require specific events
even when the mouse is not directly over them. A scope widget can be used to
bypass this descension and pass a specific subset of events directly to a
specified widget. For example, take two scopes, one each on the left and right
halves of a window. Put a WDS_GetString text entry widget somewhere
on the sub-hierarchy of each in the midst of other widgets. When either of the
text widgets is activated, it registers an exclusive bypass with it's
associated scope. If, for instance, the mouse is over the left half scope, any
keyboard event will be bypassed from that scope directly to the registered
text entry widget (assuming it is registered). After finishing (by hitting
Return, maybe), the text widget can release its bypass.
If another widget requests an exclusive bypass with an overlapping event subset
from the same scope, any widget that previously held an exclusive bypass is
notified that its bypass was degraded to non-exclusive. Non-exclusive
overlapping bypasses can be held without conflict. In the case of the
WDS_GetString text entry widget, it will respond to losing
exclusivity by deregistering anyhow. In this way, you can switch to a new text
entry widget in the same scope and the previously selected widget will finish
itself up. But, another text entry widget in a separate scope will remain
selected, but will be unresponsive until it returns to scope. When bypasses
exist in scopes with overlapping bounds (one is the ancestor of the another),
the child-most scope gets priority. But the ancestral scopes can still use the
event when the mouse is outside the child-more scope, but still inside an
ancestral scope.
An example of non-exclusive bypassing is in
WDS_Button. When pressed, it graphically holds the button down until
the left mouse button is released. But, if the mouse is moved and released
outside the button, it would miss this event and stay down. So, it registers a
non-exclusive left mouse release bypass with the root-most scope. This way, it
sees the release as long as it occurs in the root-most scope, even if that
event is also used by some other widget. For this reason, it is highly
prefered (but not required) that widget hierarchies are based on a scope
directly over the window object.
1.4.6: Widget Ties
Ties are used to set up a dependency on some setting of any number of widgets.
For example, you can tie scrollbars together so that when one changes value,
any other scrollbars tied to that WDS_Tie will change as well, automatically.
The tied widgets can be of different types. Virtual tie functionality is
defined in WDS_Widget, so any widget can be tied. But, not all
widgets will recognize and participate in the tie since the default virtual is
to only print a warning message. Each widget can only participate in one tie,
but each tie can contain a list of values.
1.4.7: Tool Tips
Any widget can have a text message trigger to pop-up when the mouse is held
over it for short period of time. The intention is to place a word or small
phrase that alludes to what the widget will do.
1.4.8: Online Help
Help uses the Win32 WinHelp().
For Unix, WDS ties into the Bristol "port" of WinHelp() using provided
Bristol code that instigates their HyperHelp product.
If the Bristol HyperHelp software is not installed,
attempts to spawn help will have no effect.
1.4.9: No Unusual Dependencies
Other than a minimal set of typical development software (C++, base
libraries), all you need to compile are the header files and libraries for
OSD, GPL, EW, and WDS, available together. No other third party software is
used. None of these Coral Tree modules require daemons or run-time
dependencies. The stand alone executables work by themselves; unless, of
course, your application has its own run-time dependencies.
1.4.10: Widget Types
Our concept is to provide a minimal number of widgets that are flexible enough
to cover many different needs.
1.4.10.1: Implemented
- WDS_Button label and/or graphic; press and release
- WDS_Divider selectively views one of many children by switching using a row of divider tabs along the divider's edge.
- WDS_Form general container; manual, column, or row alignment; fixed, manual, or auto sizing; child selectability
- WDS_GetString text entry; smart focus
- WDS_HierForm used by WDS_HierNode only
- WDS_HierarchyFile derived from WDS_HierNodeto list filesystems
- WDS_HierarchyNode base class that can build more WDS_HierNode's as its children;
good for displaying hierarchial information like file systems
- WDS_HierarchyTest example how to derive from WDS_HierNode
- WDS_Menubar pop-down menus
- WDS_Partition area divider; horizontal or vertical
- WDS_PointerEntry extension of WDS_GetString allowing automatic update using a shared pointer
- WDS_PopUp pop-up windows
- WDS_RadioButton choice-of-many button
- WDS_Scope bypass control
- WDS_ScrollBar sliding bar with button; horizontal or vertical
- WDS_ScrollButton separate class from WDS_Button for independent look entries
- WDS_Table two-dimensional scrollable array of editable text fields; much more efficient than m*n entry widgets
- WDS_Textlist editable list of text fields
- WDS_ToggleButton on/off button
- WDS_ScrollRegion clipped/scanable containment of children whose bounds exceed the parent;
scrollable in both or either horizontal or vertical directions
- WDS_Widget base from which all WDS widgets must be derived (directly or indirectly)
1.4.10.2: Proposed or Not Current
- Number Entry some slick way to enter/adjust numbers fast
1.4.10.3: Related Classes
- WDS_Help help context
- WDS_Look single Look-And-Feel specification
- WDS_Image loads and displays images
- WDS_String EW_String with some styling abilities (still needs more functionality)
- WDS_Tie used to connect settings between widgets
1.5: WDS Screen Shots
These are screen shots of a example test interface in different "look and
feel" modes during the same running of a single execution. These modes are
not constrained to compile or execution flags. The interface can
instantaneously change while running. In this case, these changes are wired
into the buttons along the right side of the interface.
These snapshot
images may be fuzzy due to dithering in the image format or the browser. The
pallettes and methods used in the actual interfaces are chosen to prevent
dithering which would otherwise make details difficult to read. Also, some of
the widgets are configured in unusual ways for testing. For example, the
button in the left-most partitioned area is normal. Most of the rest,
such as in the scroll regions at high center, use a
variety of other border modes.
The top two circular dials on a test widget run off
EW timer events, set to different frequencies. The other dial is connected to
the work-function event which is turned on and off coordinated by a timer.
The widget near the upper right is a hierarchy. Each hierarchy node has it
own hierarchy form and can instantiate more hierarchy nodes within it. The
hierarchy builds as containers of containers. This can be used to visualize
and affect hierarchial information such as file systems. A derived file
hierarchy class has been created to do this.
Most, but not all, of the
"Look-And-Feel" differences are basically "Look" differences. You may
note that the Hybrid picture has two text entry widgets with cursors, one of
which is highlighted green which has keyboard focus, the other red which doesn't.
The layered scoping allows for multiple widgets to
request exclusive access to the same subset of possible events. In this case,
two widgets request all keyboard events. But since they are in different
scopes, the position of the mouse relative to the bounds of the scopes
determines who gets the event. With overlapping scopes, the child-most widget
gets priority, but ancestral scopes can still get event when the mouse is
outside the child-more scope. Since the Look-And-Feel modes are completely
configurable, you can activate this ability with any look. But, by default,
these other modes will use the root-most scopes in order to more closely
emulate their namesakes.
Another image (captured off Windows NT 4.0)
shows a partially editable table.
The grey-boxed entries in the table are the editable ones,
even some of the headers.
The various data fields (date, time, phone, SSN) use "Confirmation"
functions to automatically correct data.
1.6: Notes
WDS extends EW's EW_Widget class to WDS_Widget
to provide some extra functionality that
WDS widgets will expect the other widgets to have.
For example, WDS_Widget
implements run-time type-checking on derived objects.
This is used for look-and-feel inheritance and for use of widgets like
WDS_Scope and WDS_PopUp
who must be identifiable so that other widgets can search the
widget hierarchy for them.
This means you should not use any EW_Widget-derived
widgets with WDS widgets unless they are in fact derived from
WDS_Widget.
Most widgets are fairly self-contained and reside in a matching header
and source file.
Nearly all widgets in the WDS system use the wdsBevelBox()
function to draw their geometry.
Generally, class member data is private and not directly accessible,
but can only be altered through member functions.
In some cases, there may be public data members,
but application programs should never attempt to access this data directly.
In general, applications should only access classes through
published member functions.
WDS widgets will use member functions inherited from EW for their operations.
It is acceptable, and probably neccessary,
for applications to use some of these inherited functions as well.
But, in many cases, an application is capable of corrupting the functionality
of a widget with negligent use of these inherited functions.