[comp.sys.mac.programmer] gGopher question

palmer@tybalt.caltech.edu (David Palmer) (09/19/89)

I just upgraded to Think C 4.0 (WOW!) and am diving in to object-oriented
programming.

I am writing a special purpose drawing program in Think C 4.0, and I need
help.  (The drawing portion of the program is a major part of a 3-D simulator.)

1) Has anyone developed a class structure good for drawing that they could
    place in the public domain?

2) Should the Ancestor class of the drawn objects be CBureaucrat?
    (Drawn objects respond to commands, keys, and mice, so I guess so.)

3) The documentation for CBureaucrat says that a Bureaucrat should handle
    Keys and Commands, which are automagically passed to it when it is
    the gGopher, but it doesn't say what happens to Mouse clicks.
    Are they also sent to the gGopher?

4) What should the flow of control be?  Should the selected drawing object
    become the gGopher (or the Pane if nothing is selected), or should
    the Pane (or the Document?) handle mouse clicks and commands, passing
    them on to the currently selected object?

5) Can an Object be written-to and read-from a file in the standard
    manner? (with the Mac equivalent of
	 fwrite(*Object, sizeof(object), 1, stream)
    where *Object is the first argument and singly indirects the handle
    of Object to get a pointer.)  How are objects within objects best handled?
    (By which I mean references to objects.  For instance, each object
    may have a list of the objects touching it, etc.)
    I am currently planning to keep all objects in lists, and, at save time,
    replace the contained object's handle with an index into the list.  It
    is ugly, but I can't think of any other way to do it.

Thanks in advance.

		David Palmer
		palmer@tybalt.caltech.edu
		...rutgers!cit-vax!tybalt.caltech.edu!palmer
    "Direct quotes don't have to be exact, or even accurate.  Truth is as
    irrelevant to a newspaper as it is to a court of law"
	- Judge Alarcon, 9th circuit court of appeals (paraphrased)

fjlim@garnet.berkeley.edu (09/21/89)

In article <11945@cit-vax.Caltech.Edu> palmer@tybalt.caltech.edu.UUCP (David Palmer) writes:
>
>I am writing a special purpose drawing program in Think C 4.0, and I need
>help.  (The drawing portion of the program is a major part of a 3-D simulator.)
>
>2) Should the Ancestor class of the drawn objects be CBureaucrat?
>    (Drawn objects respond to commands, keys, and mice, so I guess so.)
>
>3) The documentation for CBureaucrat says that a Bureaucrat should handle
>    Keys and Commands, which are automagically passed to it when it is
>    the gGopher, but it doesn't say what happens to Mouse clicks.
>    Are they also sent to the gGopher?
>
>4) What should the flow of control be?  Should the selected drawing object
>    become the gGopher (or the Pane if nothing is selected), or should
>    the Pane (or the Document?) handle mouse clicks and commands, passing
>    them on to the currently selected object?

The answers to these three questions are related. It depends on how you
want to structure your program. Mouse clicks are "sent" to the Pane
which is clicked on. Your drawing objects will not receive DoClick()
messages unless you make each one a separate Pane (not a good idea).

I recommend making your drawing objects subclasses of CBureaucrat and
setting the gGopher to the current selected drawing object. The alternative
is making the Pane act as a middleman which dispatches key clicks and
menu commands to the appropriate object. This places too much knowledge
in the Pane. You would have to change code in the Pane's methods if you
added another kind of drawing object.
>
>5) Can an Object be written-to and read-from a file in the standard
>    manner? (with the Mac equivalent of
>	 fwrite(*Object, sizeof(object), 1, stream)
>    where *Object is the first argument and singly indirects the handle
>    of Object to get a pointer.)  How are objects within objects best handled?
>    (By which I mean references to objects.  For instance, each object
>    may have a list of the objects touching it, etc.)
>    I am currently planning to keep all objects in lists, and, at save time,
>    replace the contained object's handle with an index into the list.  It
>    is ugly, but I can't think of any other way to do it.
>

Objects are stored in memory as handles, so the simplest method of
storing them to disk is as resources. Just use AddResource calls.

In your case, however, you'll want to use the data fork since there
could be many drawing objects. The only data for an object is the
values of its instance variables (including those it inherits) and
an additional two bytes (BEFORE the instance variables) which is
used by the runtime environment for method dispatching.

The Mac Toolbox call
	FSWrite(fileNum, &objSize, *Object+2);
will work.

As for references to other objects, you'll need to replace the pointer
to the object (4 bytes) with some kind of index number for how you're
storing objects in your file. When you read the object back into
memory, you can replace the index number with a pointer. The Toolbox
uses a similar technique for resources within resources (see IM I-127).

---
Gregory Dow

ech@cbnewsk.ATT.COM (ned.horvath) (09/23/89)

In article <11945@cit-vax.Caltech.Edu> palmer@tybalt.caltech.edu.UUCP (David Palmer) writes:

>I am writing a special purpose drawing program in Think C 4.0, and I need
>help.  (The drawing portion of the program is a major part of a 3-D simulator.)

>2) Should the Ancestor class of the drawn objects be CBureaucrat?
>    (Drawn objects respond to commands, keys, and mice, so I guess so.)

From article <1989Sep21.050812.15192@agate.berkeley.edu>, by fjlim@garnet.berkeley.edu:
> ...Mouse clicks are "sent" to the Pane
> which is clicked on. Your drawing objects will not receive DoClick()
> messages unless you make each one a separate Pane (not a good idea).

> I recommend making your drawing objects subclasses of CBureaucrat and
> setting the gGopher to the current selected drawing object. The alternative
> is making the Pane act as a middleman which dispatches key clicks and
> menu commands to the appropriate object. This places too much knowledge
> in the Pane. You would have to change code in the Pane's methods if you
> added another kind of drawing object.

I hate to try to tell grandma how to suck eggs, but...

I'm fairly new to this object-oriented way of approaching things, so
please bear with me; if I've got my head wedged, please help me get it
loose...

If the drawn objects are themselves CViews, in the pane's "itsSubviews"
CList, then the DispatchClick() routine ought to "do the right thing"
without any special knowledge in the pane at all.

I'm presuming here that the drawn objects are themselves subclasses of
CView (but not necessarily of CPane).  By appropriately overriding
the Contains() method (and setting wantsClicks), Mr. Palmer's visual
objects should get DoClick() messages appropriately.  Setting
	gGopher = this;
in the drawn object's DoClick() method would then cause subsequent
commands to be sent to the right place.

Note that in the class library as distributed, there's no real support for
the CDirector::itsGopher variable.  It seems to me that a CBureaucrat access
method would be a good idea here.  Alternatively, you might override
DispatchClick in your Document subclass to do something like

	inherited::DispatchClick(...);
	itsGopher = gGopher;

this would be particularly sensible if CView::DoClick() was

	gGopher = this;

(presently CView::DoClick() does nothing).

As a more general comment, any CView might wish to override DispatchClick()
to record the fact that one of it's subviews (or descendants) had become
the gopher.  This is pretty straightforward as things stand: a CView
only gets a DispatchClick() message if it has wantsClicks set and it
responds TRUE to a Contains() message, i.e. it is true that a CView
gets a DispatchClick if and only if it or one of it's subviews receives
(the) DoClick message.  As a general design rule, any CView that becomes
"active" (i.e. the gopher or one of it's visual ancestors) may need to
respond in some way (typically a change in appearance).  I don't think
this is adequately reflected in the pristine class libraries, but again,
please correct me if that's a misapprehension.

Going the other way, the distributed CDirector/CDocument etc. classes
don't do anything to "get the word out" on an Activate message.  As
a general rule, one would want to not just set "gGopher = itsGopher",
one would also like to pass the Activate along to gGopher and its
ancestors.

Comments?  Suggestions?

=Ned Horvath=