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--