Custom Component Editors in Delphi - #2 - Sub-events and Sub-properties

By: Serge Dosyukov

Abstract: Second article in a seria - This article shows how to make visible event handlers for component sub-properties

    Abstract

Events became common part of modern programming languages. Ten years ago it was "new word" of development style to use events while creating application code. But now it is everywhere.

In Delphi events are exposed in Object Inspector and could be created in one click.

Problem appears when programmer decided to introduce sub-level structures for component properties. Only events for main level (belong to a component itself) are visible in Object Inspector. Delphi IDE does not allow seeing published events for any of sub-levels.

For example, when property is descendants of TPersistent class you would see "plus" sign next to a property and able to expand/collapse defined sub-property structure. But even it is true for properties itself, it is not working for events of this class - they are not visible by default.

This paper will focus on this problem and will illustrate how to solve it.

    Background

What exactly is an event?

Accordingly Delphi online help:

"An event is a mechanism that links an occurrence to some code. More specifically, an event is a method pointer that points to a method in a specific class instance. From the application developer's perspective, an event is just a name related to a system occurrence, such as OnClick, to which specific code can be attached"

So only difference between regular property and event is a type of method (ex. TNotifyEvent).

You would think that Delphi should recognize method type on any level it defined, but this is not true. For every (almost) type of property there is a Property editor. Dr. Bob making a good introduction for property editor concept and discuss existing editors here. For the purpose of our discussion please read an article before continue.

    Problem

At some point of component development you could realize that mixing standard and custom events and properties is not very good way of extending a component there is always a risk of using the same property name and it is also not very readable to determine where are standard and where are custom properties. Yes, there is a way to separate them by using custom categories, but is there a big chance that category sorting is enabled in all Delphi IDE configurations.

There is more elegant way - grouping custom properties and events as nested. Then it is very easy to distinguish between means behind properties:

Let's look at sample component:

type
  TMySubProperty = class(TPersistent)
  private
    fSomeProperty: integer;
    fMyEvent: TNotifyEvent;
  protected
  public
  published
    property SomeProperty: integer read fSomeProperty write fSomeProperty;
    property MyEvent: TNotifyEvent read fMyEvent write fMyEvent;
  end;

  TMyComponent = class(TComponent)
  private
    fProperties: TMySubProperty;
  protected
  public
     constructor Create(aOwner: TComponent); override;
     destructor Destroy; override;
  published
     property Properties: TMySubProperty read fProperties write fProperties;
  end;

It seems as regular code, except one thing - sub-property class has an event.

If we register this component and drop it on a form we would see Properties property of the component and it will have nested level with SomeProperty sub-property but no nested MyEvent visible.

    Solution

Solution for the problem is simple but also tricky.

Problem is in nature of Property Editor. It only has one "face" - it could be either a property or an event editor.

One way to overcome this limitation is to use fake event property on a main level and then use it to trigger logic to show nested events.

To implement desired functionality we will need to implement two special Property Editors:

  • TNestedProperty - A property editor that uses the parent's Designer, PropList and PropCount.
  • TMethodProperty - Property editor for all method properties

Inherited TNestedProperty property editor will allow to handle regular properties and Inherited TMethodProperty will handle events.

Special situation is that there is a new property - "PropertiesEvents" event. This new property is only used to use new method property editor and then link it with "Properties" property so events of "Properties" appear on the same nested level.

Because no particular link between these two properties, only possibility to link them together is by property type or by property name - in our example we will be using name to identify the link. But you can easily modify a code to do enumerate properties of the component and find one of specific type.

Rest of information you can find in provided sample. I hope provided example will be useful and will allow making your components more organized and easier to maintain.

    Links

    Contact

Author's web-site: http://www.dragonsoftru.com
Full list of Articles available in Articles section.


Server Response from: ETNASC03