Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Design

Borland's CLX Component Framework


Feb02: Programmer's Toolchest

Ray is the author of Delphi In a Nutshell (ISBN 1-56592-659-5) and other books. You can contact him at [email protected].


CLX (pronounced "clicks") is a component framework for cross-platform development from Borland Software (http://www.borland.com/kylix/). Although CLX originated in Kylix, Borland's rapid application development tool for Linux, it is also available for Windows in Delphi 6.

CLX is written in Borland's version of Object Pascal, which has evolved over the years. Its current incarnation in Kylix and Delphi is a modern, object-oriented language with a Java-like object model (single inheritance of classes, and a class can implement multiple interfaces), resizeable arrays, copy-on-write strings, Unicode support, exception handling (see "Exception Handling in Kylix," by Eli Boling and Chuck Jazdzewski, DDJ, November 2001), and other conveniences programmers now expect. (Generic types are an exception, but then you can't have everything.)

CLX has four major parts:

  • BaseCLX, the core run-time library, which contains utility classes and routines, the standard exception classes, date and time manipulation, I/O and streaming, string manipulation, and so on.
  • VisualCLX, the widget library, which uses Qt for drawing and user interaction. It is not a mere layer above Qt, though. VisualCLX introduces its own event-handling mechanism and widget set. Some VisualCLX widgets are wrappers around Qt widgets, but there is no attempt to make VisualCLX Qt-like. Instead, VisualCLX closely resembles the Visual Component Library (VCL), the Windows-specific component framework in Borland's Delphi and C++ Builder.

  • DataCLX, the database interface library, which uses dbExpress, Borland's cross-platform database engine. Currently, dbExpress supports Oracle, DB/2, Interbase, and MySQL.

  • NetCLX, the Internet and socket library. Part of NetCLX includes the Indy Internet component suite, a freeware project from Nevrona Designs (http://www.nevrona.com/indy). NetCLX also includes web server components that make it easy to write CGI applications and Apache modules.

Kylix Pascal Features

Borland designed its Object Pascal implementation specifically for use in Delphi and Kylix. Two of its key features are published declarations and properties:

  • In addition to fields (also called "data members" or "instance variables") and methods ("member functions"), Kylix classes can have properties. A property has syntax similar to a field, but with the semantics of a method (or more accurately, several methods). In their simplest form, properties have a name and type and map to a field or method. Reading the property value gets the value from the field or calls a function method. Setting the property value assigns the new value to a field or passes the value to a procedure method. A property can also be read-only by omitting the writer.
  • A common idiom is for a property's reader to map directly to a field, and the writer maps to a method that checks the validity of the new value before storing it. Properties are the preferred mechanism for accessing an object's state or other attributes.

Listing One is a typical property declaration for a property named Color, of type TColor. (A common Delphi and Kylix convention is to name types with a leading T.) The reader maps to the field FColor (another convention is to name fields with a leading F), and the writer uses the SetColor method.

Kylix's GUI builder relies on properties for manipulating components at design time. Every component class declares properties for the attributes that can be manipulated at design time, such as caption, color, size, and position. Events (such as a button's OnClick, or an edit box's OnKeyDown) are also properties, where the property type is a method pointer. Thus, event handlers are ordinary methods.

The GUI builder knows which properties are important because you declare these properties as published. Published declarations have the same visibility and access rules as public declarations; the difference is that the compiler stores run-time type information (RTTI) for all published declarations. The GUI builder reads the RTTI to know which properties to present at design time and how to get and set those properties.

Fields and methods can also be published. When designing a form (which is the Kylix term for a window or dialog box), the form is represented by a form class. Every component you drop on the form has a corresponding published field declaration. At run time, the field stores an object reference for the component. The field name is the same as the component name. When you change the name in the GUI builder, Kylix automatically updates your source code. Published methods are eligible for use as event handlers. When you assign event handlers in the GUI builder, you can pick an existing method in the form class or create a new method.

To further enhance Kylix's extensibility, you can install custom property editors by writing a class that implements the IEditor interface. Each property has an associated property editor. The property editor maps property values to strings so the strings can be displayed in the property editor, then maps user-edited strings back to property values, such as integers (Height, for instance), dates and times, and so on. Utility routines in BaseCLX provide additional routines for working with RTTI, such as mapping enumerated literals to/from strings.

A property editor can also display a drop-down list of choices, open a dialog box, or do almost anything in response to a user's mouse click.

Components

The root of the component class hierarchy is TComponent, which publishes two properties: Name and Tag. Every component must have a name, and the name must be unique on the form. The tag is an integer that is not used by Kylix. You can freely use it for any use.

TComponent also declares a number of methods to support the component framework. In particular, any component can be the owner of any number of other components. The owner is responsible for managing the lifetime of its components. In other words, when the owner is freed, it must free its children. Every component you drop on a form at design time is owned by the form class. Thus, when the form is freed, it automatically frees all the controls and other components that are on the form.

Independent of the ownership hierarchy, the component framework supports a parentage hierarchy. Widget controls implement parentage visually. That is, a button can be a child of a panel, in which case the button appears on top of the panel and the button's position is relative to the panel. Move the panel in the form editor, and the button moves with it. Menus implement parentage to reflect the menu item hierarchy: Each menu item is represented by a TMenuItem component, which can have a submenu with child TMenuItem components. Similarly, a data set can have child components to represent the database fields (columns). Different classes implement the notion of parentage differently, but they all use the same mechanism defined by the TComponent class.

BaseCLX

BaseCLX is the core run-time library. It includes the Pascal run-time library (a suite of utility routines) and classes that form the foundation of CLX. The rest of CLX depends on BaseCLX. For example, BaseCLX declares TComponent, which is the base class for all other components.

The most important elements of BaseCLX are:

  • Component foundation (the TComponent and related classes). A form description is stored in a separate file (with the extension .xfm). BaseCLX takes care of saving and loading form descriptions. The Kylix linker includes the form descriptions in the program file, so you never need to worry about deploying or configuring the form descriptions. Everything is handled automatically. (And if you wish, you can customize it by storing any additional information you want.)
  • String manipulation routines, including support for Unicode strings, UTF-8, and plain ANSI strings. (Most routines work with ANSI and UTF-8 strings. The language supports Unicode strings, but the run-time library is taking longer to catch up.)

  • Date and time manipulation routines. Dates and times are represented by a double-precision floating-point number, storing the number of days since the start of the day on December 30, 1899, thereby preserving compatibility with Delphi and Windows. The fractional part of the date/time value stores fractional days to your desired precision. Many routines exist to extract parts of a date or time, build a date or time from constituent parts, test for leap year, and perform other date/time manipulation. Borland didn't include routines to convert between local time and UTC, but has included routines to convert to/from UNIX time_t values.

  • Filename manipulation routines. Build a path from parts, or extract parts of a path. Declarations, such as PathDelim for the directory delimiter in a path name, provide portability between Delphi and Kylix.

  • Standard exception classes and other error-handling routines. The Kylix Pascal language lets you raise any object in an exception. By convention, exception classes derive from Exception or one of its children. The Exception class holds a string message and various constructors let you create the message as a plain or formatted string, possibly with an associated help topic. Another useful routine is RaiseLastOSError, which raises an exception that incorporates the error code from errno.

  • Formatting routines. Kylix automatically queries the locale for information on formatting numbers, currency, and dates and times. Various routines give you flexibility in formatting numbers with different precision, padding, and so on. Several routines exist to format dates and times, using names and formatting information from the locale.

  • Operator overloading with custom Variants. Pascal is a statically typed language, but Kylix Pascal also supports Variant types, which have dynamic types. A Variant-typed variable can change its type at run time. Kylix comes with predefined Variants for integers, strings, objects, and more. You can also declare custom Variant types, which confers a form of operator overloading. Commercial editions of Kylix come with a CD-ROM that has an example of a custom Variant that adds support for rational numbers.

VisualCLX

VisualCLX, the visual part of the framework, contains the forms and controls you drop on a form. It also contains some nonvisual components that support visual interfaces such as timers, image lists, and action lists.

Visual controls derive from TControl, which is a child of TComponent. TControl introduces numerous methods for managing visual control such as handling mouse events, drag and drop actions, moving and alignment, and resizing (including constraints on the control's size). TControl publishes some properties that are common to all visual controls such as Left, Top, Width, and Height.

Control classes do not derive directly from TControl, but from other, more derived classes. There are two kinds of visual controls: graphic controls (which have no keyboard interface) and widget controls (which do). Thus, a control class typically derives from TGraphicControl or TCustomControl (which is a subclass of TWidgetControl).

Graphic controls cannot get the keyboard focus, so they cannot respond to keyboard events, but they can respond to mouse events. Most important, a graphic control must draw itself on the form, so TGraphicControl provides support for a canvas and derived classes must override the Paint method.

A TCanvas object is the CLX way of drawing on the screen or off screen. A canvas manages a graphical state (pen, brush, and font), and it has methods for drawing primitives (arcs, lines, text, and so on), clipping, bitblts, and so on. Any control that is visible on a form must paint itself on a canvas.

TWidgetControl declares additional methods for managing the keyboard focus and keyboard events. TCustomControl derives from TWidgetControl and adds support for a canvas, so most widget controls derive from TCustomControl.

Kylix supports standard widgets: buttons, labels, edit boxes, checkboxes, and so on. Many of the controls are wrappers around Qt widgets. Others are more complicated. An important component is TActionList, which contains a set of actions. An action takes care of common behavior for multiple, related user-interface elements. For example, you can tie a menu item and a toolbar button to the same action. Instead of defining event handlers for the menu item and toolbar button, you use a single event handler for the action. You can also enable/disable the action, and it automatically updates all controls that are tied to it. Actions and action lists simplify the implementation of complex UIs.

One area where Kylix shows a weakness is in layout control. Positions are specified in terms of pixels. To compensate for different screen resolutions, you set the form's Scaled property, which attempts to scale the form and its contents according to the local screen resolution (relative to the developer's screen resolution). Designing UIs that look good at multiple screen resolutions is feasible, but remains a challenge.

DataCLX

DataCLX is the database interface. The Desktop Developer edition has support for MySQL and Interbase, while the Server Developer edition adds native interfaces for Oracle and DB/2. In both editions, DataCLX includes data-aware controls and data-management components.

The data-aware controls mirror the ordinary visual controls; for instance, TEdit is an edit box and TDbEdit a data-aware edit box. Data-aware controls are tied directly to a specific field in a specific data set (a table or a query). The value to display in the edit box is obtained from the data set, and when the user edits the text, the edited text is copied into the database record. A database navigator control lets the end user choose which record to edit, post changes to the database, or abandon changes to the current record. Depending on your UI needs, you might not use the navigator and define other ways to choose records, post changes, and so on. It's simply a matter of calling a few methods of the data-source object.

dbExpress, the database interface layer, is a cross-platform library that provides a thin, fast interface to native database drivers. One omission is the lack of a PostgreSQL driver.

The database control and management components use the same component framework. Obviously, a table or query component is not a visual control, so they derive from TComponent instead of TControl. The mechanism of using published properties and events is the same, though. To help write database applications, you can use a data module, which is like a form that's visible only at design time. When developing the application, you can drop nonvisual components on the data module. At run time, those components behave normally, but there is no form. That way you can cleanly separate the visual aspects of your application (using one or more forms) from the database management aspects (using data modules).

NetCLX

NetCLX is the network and socket interface, and includes Indy (a suite of open-source Internet components) that supports most of the popular Internet protocols. NetCLX also has web server components and wizards for CGI and Apache development.

Indy components come with the commercial releases of Kylix and are also available separately from Nevrona Designs for use in Delphi, C++ Builder, and Kylix. They support most of the popular Internet protocols, including FTP, NNTP, POP3, and HTTP, for clients and servers. Additional components provide MIME and UU encoding and decoding, MD4 and MD5 hashing, and other miscellaneous utilities. The suite comes with plenty of demo projects. (If you purchased a commercial edition of Kylix, you should download the demos to replace the ones that come on the CD.)

Web server components only come with the Server Developer edition. The key component is the web module, which is like a data module, but handles the details of CGI or Apache modules. There are several ways to generate HTML pages for web server projects, the simplest being to use a page producer component. You mark up an HTML template with ordinary HTML tags and special tags that are decoded at run time. You supply the code to handle the special tags by writing ordinary Pascal code. This has the advantage of being much faster than interpreted solutions (PHP, ASP, or whatever), but is slightly harder to code because you must keep the HTML template separate from the Pascal code.

Consider a CGI application that displays all the environment variables it knows about. This is a useful debugging tool, in spite of its simplicity. With NetCLX, start by creating a new CGI project. Choose a CGI or Apache module; the former is simpler because it is a standalone program. An Apache module is built as a dynamic shared object (DSO) and is a little more complicated. Once Kylix sets up the web module, though, they work the same. Drop a page producer component on the web module, and set up the HTML template. Listing Two is the HTML template. The <#env> tag is a special tag that is replaced at run time with the actual environment variable list.

At run time, the web module calls the page producer's OnHTMLTag event. This event handler is just like any other event handler, but the "event" in this case is not a user interaction but the HTML parser encountering a special tag. The event handler (Listing Three) examines the environment variables and formats them as simple HTML text. Hook up the page producer as the default action for the web module, compile, and go. NetCLX handles the details, leaving you to program the important guts of the CGI application.

FreeCLX

Borland licenses the commercial releases of Kylix under a dual license. You can write closed-source proprietary applications, or release the application and source code under the GNU Public License (GPL). In either case, you do not need to pay any additional fees to Borland or TrollTech — Borland has arranged a license so you can use Qt as part of CLX, even in a commercial, closed-source application.

To facilitate open-source development under the GPL, Borland released Kylix Open Edition (OE) as a free download from http://www.borland.com/. All applications developed with Kylix OE must be released under the GPL. Kylix OE comes with a small set of components, but you can download the Indy components (from http://www.nevrona.com/indy), and web sites are springing up to offer a variety of Kylix components.

Borland has also placed the source code to BaseCLX, VisualCLX, and the data-aware controls of DataCLX on Source Forge under the name FreeCLX (http://freeclx.sf.net/). Developers with a commercial Kylix license can use the updated source code. Kylix OE and other users can use the source code under the GPL.

DDJ

Listing One

type
  TPrettyInPink = class(TComponent)
  private
    FColor: TColor;
    procedure SetColor(NewColor: TColor);
    ...
  published
    property Color: TColor read FColor write SetColor;
    ...

Back to Article

Listing Two

<html>
<head>
<title>Environment Variables</title>
</html>
<body>
<h1>Kylix Example</h1>
<p>This page was produced by
<a href="http://www.borland.com/kylix">Kylix</a>,
Borland's Rapid Application Development tool for Linux.</p>
<p><#env></p>
</body>
</html>

Back to Article

Listing Three

procedure TWebModule1.PageProducer1HTMLTag(Sender: TObject;
  Tag: TTag; const TagString: string; TagParams: TStrings;
  var ReplaceText: String);
var
  Env: PPChar;
begin
  if TagString = 'env' then
  begin
    ReplaceText := '';
    Env := envp;
    while Assigned(Env^) do
    begin
      ReplaceText := ReplaceText + Env^ + '<br>'#13#10;
      Inc(Env);
    end;
  end
end;

Back to Article


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.