GUI Builders (was: More On Multiple Inheritance)

Hans-Dieter.Dreier@materna.de Hans-Dieter.Dreier@materna.de
Tue, 16 Mar 1999 15:29:40 +0100


--rIcqAo74oZLHTxPHRUcKhprrgngomPeY
Content-type: text/plain; charset="ISO-8859-1"
Content-transfer-encoding: quoted-printable

>Hans-Dieter Dreier wrote:
>
><from a separate message>
>
>>>> Example: The user decides that an edit field is no longer sufficient
>>>> in some place and he want to replace that with a combo box (edit
>>>> field + drop down list box), which is quite a different class. Here =

>>>> it would be nice if he simply could change the object's class and
>>>> all matching attributes (font, screen position, message handlers...)
>>>> would migrate.  All attributes that have no equivalent in the new
>>>> class would turn to comments (so the code is not lost in case it will
>>>> be needed later on).
>
>OK, in the light of what you said just below, this makes more sense.  A
>lot depends on whether these properties are represented underneath by
>methods (and I think they should be).  If so, the methods that will stay
>are those that are in the most specific common subtype.

Not exactly if I understand you right. Please see below.

>> Explanation: The term "template" is used here not in the C++ sense.
>> ...

First let's make some definitions (which vary a little bit from my original=
 posting):

To CONFIGURE means that it is possible to specify values of (some) instance=
 items of an instance along with a declaration. It is therefore similar to =
a declaration with initialisation (in C) like:   struct xy =3D {a; b;}.

Such a configuration is handled by the editor. The result is stored in a te=
mplate.

A TEMPLATE is a structure that contains all the neccessary information to s=
et the configured properties.

A PROPERTY is an instance item of a class that can (or must) be configured =
when an instance of that class is created by a declaration.

Thus, data flow is like this:

visual representation of properties <=3D> [editor] <=3D> Template =3D> [cre=
ation function] =3D> configured instance

The creation function is a member of the TARGET CLASS (the class which the =
configured instance belongs to). =


Properties normally are instance items, not class items, because normally o=
ne would not want to change the state of the class while declaring an insta=
nce. That could alter further operations of the class which implies that th=
e sequence of declarations becomes meaningful. But conceptually declaration=
s belong to the structure framework of a workspace which is thought to be s=
tatic (so there is no notion of "before" and "after"). Being just a matter =
of conceptual clearness, this is a design rule that might or might not be f=
ollowed; there are lots of cases where the creation of an instance might ch=
ange class items without any harm, if carefully designed (example: use coun=
ts).

If we use the instance layout of the target class for templates as well, a =
simple copy constructor can be used as a creation routine. As an additional=
 benefit, editor (and debugger) can then be used to view "live" configured =
instance items as well as templates.

Methods are almost always class items since all of the instances share the =
same method code. Message handlers are instance items, however. IMO it is a=
 major design flaw to implement message handlers as class items since this =
effectively prohits reuse of that class. Message handlers often need to acc=
ess the name space of the _instance_ rather than that of the _class_. If al=
l the contacts to the instance's environment would have to take place by dy=
namic dispatch, such a class would be rather cumbersome to use.

Dynamic creation of identically configured objects by a program is possible=
 by calling the creation routine multiple times for a given template. In th=
is case the instance created by the declaration might be unwanted;  we migh=
t want to be able to prevent automatic creation due to the declaration. We =
could do this by either adding a key word ("template") to the declaration o=
r by adding a special outline item (folder) for such templates. The latter =
is better because the former would either disrupt the instance layout or le=
ave a NULL reference gaping if used in the "instance items" section of a cl=
ass.

>OK, you're referring to a GUI editor, whereas I'm referring to GUI
>classes.

I'm referring to both since you need a GUI editor to effecively use GUI cla=
sses. Both must work together.

>So you have the window/panel/component hierachy inheritance
>(which you could use for pop-up help too).

Yes. You can inherit the usual way too.

>So do these editors allow
>you to define a control that inherits the properties of another control?

Yes. Usually that will be the surrounding window. But this concept is not l=
imited to GUI buildingas you will see. I'll show in an example:


<Window: MyToplevelWindow    // type 1 item>
  Window Position            // type 3 item - you couldn't add this comment
   Top: <0                   // type 2 item>
   Left: <0>
   Widht: <400>
   Height: <300>
  Window Style
   Border? <true>
   System Menu? <true>
   ...
  Font
   Font Name: <Arial>
   Font Size: <8>
   Bold? <false>
  Contents
   <Background Text: "hello world"      // we don't assign names to them>
    Window Position
     ...
   <Pushbutton: pbOK>
    Window Text: <"OK">
    Window Position
     ...
    Font
     Font Name: <Use Parent             // inherit from surrounding window>
     Font Size: <Use Parent>
     Bold? <Class Default               // inherit from parent class>
    Messages
     <On WM_CLICK                       // type 4 item>
      <DestroyWindow (ParentWindow);    // type 5 item>
   ...

The parts that can be entered by the user are enclosed in <> just in this e=
xample to distiguish editor generated (non-editable) parts from user input.=
 Indentation is handled by the editor and non-editable.

  You can find five different types of outline items here:

1. <ClassName>: <InstanceName>
2. <Fixed Text given by the editor> <Text given by the user>
3. <Heading given by the editor> followed by zero or more
   (indented) items of type 1, 3 or 4.
4. <Heading given by the user> followed zero or more
   (indented) items of type 5
5. Program text items.

Types 2 and 3 would correspond to (single) properties. Font is a property, =
for example.
Type 4 would correspond to a property that is represented by a list.

For each definition of a class that is intended to support property-configu=
rable declarations, there could (in fact should) be an accompanying class t=
hat includes all the stuff that the editor needs to process those declarati=
ons: What types of outline item to use in what order, how to render and syn=
tax-check user input, how to map user input to actual instance items and so=
 on. If missing, the editor would use a default that would allow a simple d=
eclaration like this:

<ClassName:> <InstanceName>

The customized (indented) part would be missing.

I would suggest to keep that editor-related stuff in a separate class to be=
 able to easily strip it for a release version of the program.


Now look at the following function declaration:

<Function: x>
 Parameters
  <Number: i>
  <String: s>
 Returns
  <String: s>             // the name is just a comment
 Local items
 Program Text
  <MakeSomethingWithThisString (s);>
  <return s.Left (i);>

You see the similarity to the GUI example above? Function declarations, cla=
ss declarations, all that stuff could be made customisable as well. IMO the=
 benefits would be huge: Everyone could make its own without having to touc=
h the editor "core". Changes even at edit time were possible. You add a pro=
perty: Just change and compile the editor supplement class and there it is,=
 ready for use. This editor core would also be a (relatively) small affair =
instead of a big monolith. (You know I'm in favour of writing frameworks an=
d filling the details in later, when actually needed).

Of course, this is just a vision. The details need to be worked out. How ex=
actly is the editor supplement class (a daft name, can you think of somethi=
ng better?) tied to its client class and how will it look like? How do we i=
nclude inheritance? A lot of conceptual work has to be done before actual c=
oding can start. And more ideas are welcome!

>> There are other (similar) ways to achive the same result. Instead of
>> tagging the instance variables, one could specify the constructor to
>> use along with the declaration. This would allow for multiple versions
>> of templates and would also have the advantage of not introducing yet
>> another keyword.
>
>I'm not sure I understand what you mean.  Could you elaborate?

Sure. The editor somehow needs to know which instance items to treat as pro=
perties. At first glance, I can think of several ways to do this:
1. Add a keyword (say, "property") to the instance item's declaration.
   Only usable for simple cases since no specific customisation info can be
   presented this way.
2. Put properties into a separate outline group.
   Not good, for the same reasons.
   Additionally, this breaks the ordering of instance items, forcing a reco=
mpile.
3. Completely rely on the editor supplement class
   Maximum flexibility, but imposes a big threshold for starters:
   Writing a keyword is much less work than writing a whole class.
4. Use a mix of the above.
   I would prefer that, but it must be carefully designed so that the simpl=
e case
   stays simple while the complex case is not compromised.

All of the above ways silently include the assumption that there is only on=
e such "customisation set" for each class. This might be sufficient in most=
 cases, but why should we accept that restriction right from the start?

Some people might prefer a simpler GUI builder that would not expose all of=
 the available properties (and complexities), but still should be able to u=
se the same underlying GUI classes. Also, legacy customisation sets could b=
e kept for a while to allow updating source files.

Customisation sets (short: CS) would be distinguished by name as usual in a=
ll such cases. There would be a default CS to be used if the name of the CS=
 was omitted.
When I was looking for a device that could be used to distinguish CSs, cons=
tructors (or "creation functions") came to mind, since there may be many of=
 them with different parameter sets and names.
But after having it thought over a little bit, I'd refrain from that approa=
ch, because we need a bidirectional mapping: The property set stored with a=
 declaration needs to be read as well as written by the editor.

The syntax for a declaration involving customisation (including the CS name=
) must be clearly recognisable by the editor. This is not as easy as one mi=
ght think at first. A normal declaration looks like this:

<expression yielding a constant of type "class"> : <new name>

The expression yielding a constant of type class must be executable at edit=
 time for customisation to work, and it must be executable at compile time =
to be legal at all. The standard case for this is a class name.

CSs will most likely be classes. Because we want to be able to declare CSs =
as well some mechanism to determine the role of that class name is needed. =
I'll refer to the class that the declaration should produce as the "target =
class".

In addition to standard declarations we could use (if we accept that colons=
 must not appear in names):

<type>:<cust set>:<name>

or simply

:<cust set>:<name>

if the name of the target class is included in the CS. But this does not co=
mletely satisfy me esthetically. The first form allows to form incompatible=
 pairs of target class and CS while the latter prevents CSs to be painlessl=
y reused by other classes.

Maybe someone has a better idea.


--

Regards,

Hans-Dieter Dreier
(Hans-Dieter.Dreier@materna.de)=

--rIcqAo74oZLHTxPHRUcKhprrgngomPeY
Content-type: text/plain; charset="ISO-8859-1"
Content-transfer-encoding: quoted-printable

IDENTIFIKATIONSANGABEN:
a20213a.txt IA5 DX-MAIL X.400 User Agent=

--rIcqAo74oZLHTxPHRUcKhprrgngomPeY--