XTkFriends.mesa
Copyright Ó 1990, 1991 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, April 2, 1990 2:36:07 pm PDT
Christian Jacobi, August 7, 1991 3:43 pm PDT
DIRECTORY
Atom USING [PropList],
Xl USING [Event, Geometry, MatchList, Screen, ScreenDepth, TQ],
XTk;
XTkFriends: CEDAR DEFINITIONS
SHARES XTk ~
BEGIN OPEN Xl, XTk;
Making subclasses for XTk.
Notifier handling
CallNotifiers: PROC [widget: Widget, key--LX--: REF, callData: REF ¬ NIL, event: Event ¬ NIL];
Calls all the procedures in the widgets notifier list for key.
Locking hint: Non LR postfix procedures may not invoke CallNotifiers with LR postfix keys. Note that these keys typically are not accessible by arbitrary clients.
RemoveNotifiers: PROC [widget: Widget, key: REF];
Eventually removes all the notifiers on key for efficiency of CallNotifiers on other key's.
AliasNotifierKey: PROC [key: REF, alias: REF ¬ NIL];
Used to protect arbitrary clients from miss-using restricted notifiers.
Makes "alias" look identical to "key" while using the procedure RegisterNotifier.
However, alias can not be used as a "key" in the procedure CallNotifiers.
To protect unsuspicious clients, a key must not be made an alias and an alias must not change key, except while debugging.
Using a NIL alias simply establishes a key (prevents duplicates or aliasing).
Procedures which go recursively down the widget tree
DestroyWidgetLR: PROC [widget: Widget];
Cleanly destroys a widget (delayed until drawing is quiet).
Warning: Don't forget re-considering the parent.
ConfigureLR: ConfigureProc;
Reconfigures widget.
Goes recursively down widget tree and creates or configures children.
Use inside class procedure, or, from parent widget only.
Called on root thread only.
DestroyWindowLR: TerminateProc;
Better way of unconfiguring a widget.
Destroys windows recursively down widget tree.
Use inside class procedure, or, from parent widget only.
Called on root thread only.
PreferredSizeLR: PreferredSizeProc;
Some widget classes might require connection or parent already set up.
Use inside class procedure, or, from top level widget only
Might go down widget tree.
PreStopFastAccess: TerminateProc;
Recursively goes down widget tree.
Use inside class procedure, or, from top level widget only.
Called on any thread.
FullStopFastAccessLR: PROC [w: Widget, reason: TerminationReason];
Recursively goes down widget tree.
Called on rootTQ.
PleaseResizeChild: WidgetNChildProc;
Can be called from any child on its parent.
Might be ignored, children reconfigured, or request propagated up the widget tree.
BindScreenLR: PROC [widget: Widget, rootTQ: TQ, screen: Xl.Screen, screenDepth: Xl.ScreenDepth ¬ NIL];
Internal procedure; clients see it happen automatically.
Fills in screen relative information.
ForgetScreenLR: PROC [widget: Widget];
Internal procedure; clients see it happen automatically.
Forgets screen relative information.
ReconfigureChildrenLR: PROC [widget: Widget];
Checks size and mapping whishes of widget's children and configure them if appropriate.
Internal version of XTk.StartReconfigureChildren.
RemoveChildLR: PROC [widget: Widget, child: Widget] RETURNS [done: BOOL];
Tries to remove child from widgets data structures. Returns success.
Reconfiguring parent, destruction of child up to caller!
Procedures for Widget Class implementors
About widget trees and inheritance...
widget tree:
Hierarchy of widgets; called a parent - child hierarchy.
Composed widget classes must provide the tree recursion in their class procedures.
class inheritance:
Simple inheritance; called a super-class - sub-class hierarchy.
Defaulted class procedures are copied from their super-class: [inheritance by copy].
Most stated class procedures replace the super-class procedures [see doc in ClassRec]; If a sub-class procedure wants to inherit and augment super class behaviour, it must call the super-class procedure itself; there are many ways to access those procedures.
How to access super-class procedures:
Simple way: class knows its super-class and calls the right procedure directly. (Encouraged!)
Silly way: class calls the procedure from the super-class field. This does not allways work because if a future sub-class will inherit by copy, the procedure will be executed twice. (It is believed that inheritance by copy is the most often used inheritance method). However, this is ok if further subclassing is disabled.
General way: Nothing is known about super-class except its identity. Statically find out and store the right inheritance proc.
CreateClass: PROC [basicMethods: BasicMethodsRec ¬ []] RETURNS [ImplementorClass];
Fills in the defaulted fields and prepares inheritance operations.
[computes subDataIdx, ...]
FindClass: PROC [key: ATOM] RETURNS [Class];
Usefull to play inheritance [for sub-class implementors].
Not recommended for widget clients.
InitClassField: PROC [classField: Class, class: Class] RETURNS [Class];
Usefull to initialize classField of a widgetSpec.
If classField was initialized check whether is a valid super-class of class and return it,
otherwise, if classField is not initialized returns class.
Typical usage: widgetSpec.class ← InitClassField[widgetSpec.class, realClass];
InstPart: PROC [widget: Widget, superClass: Class, iField: INT ¬ 0] RETURNS [REF] = INLINE {
Documents how to access super class data fields of a widget instance.
Since the caller has to NARROW, we do not explicitely test ancestorship of superClass.
RETURN [widget.wClassData[superClass.wDataIdx+iField]]
};
ClassPart: PROC [widget: Widget, superClass: Class, cField: INT ¬ 0] RETURNS [REF] = INLINE {
This inline documents how to access super class data fields of a widget class
Since the caller has to NARROW, we do not explicitely test ancestorship of superClass.
RETURN [widget.s.class.cClassData[superClass.cDataIdx+cField]]
};
AssignInstPart: PROC [widget: Widget, superClass: Class, val: REF, iField: INT ¬ 0] = INLINE {
This inline documents how to initialize super class data fields of a widget instance.
widget.wClassData[superClass.wDataIdx+iField] ¬ val
};
Fast inheriting of behaviour
InheritedConfigureLRProc: PROC [superClass: Class] RETURNS [ConfigureProc];
Finds right configure proc to inherit from superClass.
Goes the right amount of levels up in class hierachy if the realize proc was
already inherited itself by copy.
WHILE superClass.super#NIL AND superClass.configure=superClass.super.configure DO
<<the super-class did inherit itself...>>
superClass ← superClass.super
ENDLOOP;
RETURN [superClass.configure];
Usefull class procedure variants
Actual procedures which could be used or called from methods.
SimpleConfigureOneLevelLR: ConfigureProc;
The basic configure proc.
SimpleDestroyWindowLR: TerminateProc;
The basic destroyWindowLR proc.
Do not use in inherited classes as this procedure is chained.
IgnorePleaseResizeChild: WidgetNChildProc;
Do nothing
PropagateUpPleaseResizeChild: WidgetNChildProc;
Propagates call to PleaseResizeChild up the widget .tree
SimplePreferredSizeOneLevel: PreferredSizeProc;
Preferes a size by using the fields of the widget.
SimpleClassName: ClassNameProc;
...simply returns classNameHint field of class
Internal used utilities
OrphanizeLR: PROC [orphan: Widget, parentState: TerminationReason];
Either calls a registered OrphanProc or destroys widget if no OrphanProc is registered.
Automatically removes environment.
Typically invoked by parent widget's class, or, by process which drops widget if it does not have a parent.
DefaultActualCreateWindowLR: WidgetProc;
Creates window, assigns widget.window field, and does mapping if necessary.
DontMapCreateWindowLR: WidgetProc;
Creates window and assigns widget.window field.
AssignParentAndCheckScreenLR: PROC [child, parent: Widget];
Basically child.s.parent ← parent.
Binds screen if necessary.
CollectMatchesLR: PROC [widget: Widget] RETURNS [Xl.MatchList];
Creates a usable match list from widget.
Side effect: removes temporary matches.
SetupScreenDepth: PROC [widget: Widget];
Fills in screenDepth field.
Needs connection and parent already initialized.
END.