Linking Text
Volume Number: 7
Issue Number: 11
Column Tag: MacOOPs!
Related Info: TextEdit Edition Manager
Linking Text Objects
By Scott Steketee, Philadelphia, PA
Note: Source code files accompanying article are located on MacTech CD-ROM or
source code disks.
TLinkItem: A MacApp class to link the content of text objects
An injury to one is an injury to all.”
[Scott Steketee, a former teacher, has been programming the Apple II for many
years, and is now adapting his popular GradeBook Deluxe program for the Macintosh.]
Introduction
This article presents a MacApp class which allows several TEditText or
TStaticText objects to be linked, so that they always show the same contents, even while
one is being edited. It also presents a subclass of TEditText which is capable of
controlling such a link, and explains how to create subclasses of other objects so that
they too can control and be controlled by the link. The objects which share the same
text can be in the same or different windows, and there can be any number of such
objects.
Macintosh applications frequently provide several different ways of viewing or
changing some item of data. In a spreadsheet, for instance, the item may appear in a
grid cell and in a separate formula bar where it can be edited. In a color program, the
percentage of red may appear both in numeric form and as the position of a slider. In a
database, the user may be entering data in a special record entry dialog, while the data
appears in a second window as a row in a grid and in still another as an item in a report.
In my own application (a teacher’s gradebook program), the teacher can enter
information about a student in either a dialog window or a grade entry window; if both
windows are open at the same time, changes in one should be immediately reflected in
the other.
MacApp provides a good environment in which to construct this capability. The
strength of MacApp, as an object programming system combined with a large
Mac-specific class library, lies in the programmer’s ability to re-use the classes
already provided, and to create new classes by modifying the existing ones. This
strength shows up well here; the entire unit requires only one new class and relatively
minor changes to three existing classes.
Publishers and Subscribers
For the remainder of this article, the objects that initiate the updating process
by sending update information to the link are called publishers, and objects that accept
and display update information from the link are called subscribers. The function of the
link is to accept information from a publisher, and to forward the information to all
the appropriate subscribers. Any object can function as a publisher by calling the
appropriate method of the link. The present unit allows TStaticText, TEditText and
TTEView objects to function as subscribers; other classes can be added by overriding
the appropriate method.
A publisher which provides a visual representation of the data is usually also a
subscriber, so that if any other publisher changes the data, the first publisher will get
the updated information and be able to change its own visual representation of the data.
On the other hand, a subscriber which only displays data and doesn’t change it will not
be a publisher.
The unit ULinkItem provides the links between publishers and subscribers, and
allows TEditText items to publish their data while the user is entering it. This unit
allows all the subscribers to be updated each time the user changes the data, either by
typing a character or by performing some other editing action. An application could
provide several TEditText objects which can be used to enter data; as the data changes,
the link updates the subscribing views in real time. The unit allows TEditText,
TStaticText and TTEView objects to function as subscribers, with no limit to the
number of subscribers which can be linked to the same item of data. (Of course, if
you’re simultaneously updating a dozen objects on the screen with every character
typed, things could get a little slow) The classes that can function as subscribers can
easily be extended to include your own custom classes. Such subscribers might be grids
or lists showing text, or they could be objects capable of showing some other, non-text
representation of the data.
Implementing the Links
One new class (TLinkItem) is defined to serve as the repository for one item of
data and to keep track of the subscribers that display the data. Three other classes are
modified (TEditText, TDialogView, and TDialogTEView) so that a TEditText object can
function as a publisher while it is being edited. When the user edits such a TEditText
object on the screen, the object publishes each change by forwarding it to the
corresponding link item, which in turn forwards the change to all its subscribers.
The first object, TLinkItem, is fairly straight-forward. It requires three fields.
The field fText stores the data, and fLinks is a list of all the subscribers. A third field,
fUpdating, is set to TRUE whenever the item is in the process of informing its
subscribers of a change. (This field is used to avoid the situation in which the link
informs a subscriber of a change, and the subscriber, not knowing who sent the
message, sends a message right back to inform the link that it has been changed, and the
link then starts all over again informing subscribers)
There are five important methods of TLinkItem, in addition to the usual
initialization, Free, and Fields methods. AddLink adds an object to the list of
subscribers, and RemoveLink removes an object from the list. GetText supplies the
current value of the link’s text data. SetText changes the text (usually but not
necessarily as a result of the user’s typing) and initiates an update of all the
subscribers. Finally, UpdatedLink sends the changed text to one single subscriber. This
method knows how to update TEditText, TStaticText and TTEView objects; it must be
overridden in order to allow updating of other kinds of objects.
Modifying TEditText
The rest of the unit is devoted to modifying TEditText objects so they can initiate
and receive updates. It would be nice if we could modify only the TEditText class, but
TEditText depends rather closely on three other classes for its behavior, and two of
these three classes need to be modified.
(One of the principles of good object programming is to minimize the connections
between different objects. To the extent possible, each object should stand on its own,
with its methods and data as little as possible dependent on other objects. MacApp tries
to meet this objective, but doesn’t succeed very well in the case of TEditText. It
requires close and complex cooperation of four objects--the TEditText, a TDialogView,
a TScroller, and a TDialogTEView--just to edit some text.)
The main change to TEditText itself is that SetText must check to see if it’s
publishing to a TLinkItem, and if so pass the new text to the link.
TDialogTEView must also be sub-classed. This class is used in editing: when the
TEditText is clicked on, a TDialogTEView is installed to handle the actual editing. Two of
the methods must be overridden. First, InstallEditText is overridden so that when the
view is installed in the TEditText, it is linked to the same item as the TEditText is.
Second, all the changes to the text must be caught and relayed back to the TLinkItem.
These changes include the typing of characters and the edit menu commands Cut, Paste
and Clear. Fortunately, all these editing changes call SynchView to update the display,
so SynchView is overridden so that it also updates the text in the TLinkItem.
Finally, TDialogView must also be subclassed, so that when it creates the
TDialogTEView which later gets installed in the TEditText to handle editing, it creates
our new-style TDialogTEView which knows how to handle links, instead of the old style
that doesn’t.
The Source Code
The source code includes five files. Files ULinkItem.p and ULinkItem.inc1.p are
the interface and implementation respectively for the classes described in the article.
ULinkDemo.p, ULinkDemo.inc1.p, and MLinkDemo.p are the Pascal source files for a
demonstration program which allows you to create a multitude of windows with linked
EditText items. Finally, LinkDemo.r is the resource file for the demonstration program.
The program has been tested with MacApp 2.0 under both MPW Pascal and Think
Pascal. (To run under Think Pascal, the interface and implementation of each unit must
be combined into a single file using Think’s Source Converter.)
Extending the Unit
To extend this unit so that a link can forward data to other types of subscribers,
you need only override the UpdatedLink procedure. This procedure checks to see if the
subscriber currently being updated is one that it knows how to handle. If it is, the
procedure takes whatever update action is appropriate and returns TRUE; otherwise it
calls INHERITED UpdatedLink. Here is a template:
{1}
FUNCTION TMyLink.UpdatedLink
(subscriber: TObject; theText: str255): BOOLEAN; OVERRIDE;
{ Update the subscribers we know how to do }
{ & return TRUE; Otherwise call inherited }
{ UpdatedLink. }
BEGIN
IF Member (subscriber, TMyObject)
THEN { this is my type of subscriber }
BEGIN
{ Set the text or take some other appropriate
action---e.g.,