Reference 11
Contents
Coding V. 5.1 and Later
Introduction
The reason for this document is that Mops has undergone some significant evolution since the last edition of the full Manual which was done for Mops version 4.0. A full Manual update will take a while, so in the meantime there's a need to provide proper documentation of the changes to the Mops system which have occurred since the 4.0 release.
Carbon
In the Apple world, ‘Carbon’ is the name given to a new set of conventions for doing system calls—the “Application Program Interface” or API. Basically, the reason for Carbon is OSX. This is really a completely new Operating System with its own API. However, completely rewriting ‘classic’ Mac applications would have been a lost cause, so Carbon provides a solution. It does this in two ways. Firstly, it provides a new API which is sufficiently similar to the classic Mac OS API that older applications can be converted to run under it without a huge amount of work (in theory at leastsee below). Secondly, it provides an implementation via the shared library CarbonLib, that runs on both OSX and OS9 (and even later versions of OS8). Thus applications that have been converted to run under Carbon (i.e. ‘Carbonized’), will run natively under both OS9 and OSX.
Now I did use the phrase “without a huge amount of work”, but having Carbonized Mops, I can only say that this is somewhat debatable! Still, the hope is that the impact on Mops source code will be minimal. Most of the changes are in the internals of different classes, and if your code hasn't been making too many assumptions about how classes are implemented, moving to Carbon Mops should be fairly painless.
An example will make this clearer. Under the classic Mac API, a Window is represented in memory as a block of information which has a Grafport as its first section. The details of both the Grafport and Window data have been documented by Apple in the early Inside Macintosh editions, and programs could freely make use of this information—and indeed, needed to in order to perform normal user interface functions.
Under OSX, however, programs don't need to know anything about the internals of windows or Grafports, and in fact these internals are no longer publicly documented. This allows Apple the freedom to implement enhancements in future, making whatever changes to the internal structures that might be necessary. Therefore, under Carbon, a Window is something that is represented to the program as a “window reference” or WindowRef. (Don't confuse this use of the word ‘reference’ to Mops references, which are a kind of pointer to an object.) We aren't allowed to know anything more about what a WindowRef is — it's just a 32-bit quantity. Any operations we want to perform on Windows are provided under Carbon by API calls which take a WindowRef as one of their parameters.
However, Mops programs using Window objects don't normally need to know anything about how the windows are implemented internally, and as long as your code just calls the usual methods to manipulate windows, the Carbonization changes won't affect your code in any way.
In moving to Carbon, however, there are a few changes that may affect your code. One obvious change is that Standard File doesn't exist any more, and has been replaced by Navigation Services Manager support. (See the file ‘Nav’ in ‘PPC Source’.) This is still rather preliminary, but provides the basic functionality we need. Thanks to Gorazd Krosl for this.
Another significant change is that TextEdit doesn't run reliably under OSX, so we now have a MLTE class (Multilingual Text Engine). Apple intends MLTE to replace TE. One immediate advantage is that the Mops editing window is no longer limited to 32k of text.
Another change is to callbacks. These have always been nasty, and have proved so again. On the PowerPC, to pass a callback to a system call, we have to use a UPP. Pre-Carbon, there was a generic NewRoutineDescriptor
call which we could use for all callbacks, and our :PPC_ENTRY
syntax was based on this mechanism. However, under Carbon, NewRoutineDescriptor
has gone away, and we have to use calls NewxxxUPP
and DisposexxxUPP
(in which xxx
is a name which is specific to the particular callback we're doing.)
This has forced a new callback syntax, :CALLBACK
and ;CALLBACK
. You have to push the addresses of the NewxxxUPP
and DisposexxxUPP
syscalls before :CALLBACK
. See the file ‘CarbonEvents’ for more comments and some actual examples you can copy.
Changed Classes
The following classes are those that have needed significant changes with Carbonization. The following descriptions should be read in place of the descriptions in Part III of the manual.
The intent has always been to minimize the impact on existing Mops programs, and hopefully we have achieved this. By far the majority of changes are in the internal implementation details; the actual methods and their parameters and results are by and large unchanged. The biggest changes are in Event handling.
Window
Window is the basic class of windows without controls:
Superclass | Object |
---|---|
Source file | zWindowMod.txt |
Status | Core |
Carbon Changes
Windows are no longer subclassed from GrafPor
t. The first ivar is theWindowRef
, which is a (MacOS) WindowRef for this window. To obtain the window's GrafPort, call the method getPort:
.
The other significant change is that the old ProcID
parameter which was passed to the New:
method is now obsolete, so we've replaced it with the (32-bit) attribute flags value. The new Carbon window attributes are many and varied, and are all described in Apple's Carbon documentation. To make things easier, we have redefined the old ProcID
constants such as DocWind
, to the appropriate attributes value. Thus calling New:
with DocWind
as the fourth parameter, will have the same effect as before, and create a generic document-style window.
Instance variables | ||
---|---|---|
var | theWindowRef | Window referenceunder Carbon this is opaque |
rect | PortRect | a local copy of window's portRectalso used to tell if the window's size has changed when we get a bounds changed event |
rect | contRect | The rectangle defining the content region |
rect | growRect | Contains the window's current grow limits |
rect | dragRect | Contains the window's current drag limits |
ool | growFlg | True if the window is growable |
bool | dragFlg | True if the window is draggable |
bool | Alive | True if the window is alive in the Toolbox |
var | Attributes | Carbon window attributes |
bool | ScrollFlg | True if window contents are to be scrollable |
bool | Color? | True if this is a color grafPort |
x-addr | Idle | The window's idle event action vector |
x-addr | Deact | The window's deactivate event action vector |
x-addr | Content | The window's content click action vector |
x-addr | Draw | The window's update event action vector |
x-addr | Enact | The window's activate event action vector |
x-addr | Close | The window's close box action vector |
int | ResID | Resource id for GetNewWindow |
bool | ClipGrowLeft | True if you want to not outline unused VScroll |
bool | ClipGrowTop | Ditto for unused HScroll |
rect | thefprect | Temporary storage to save fpRect over a Draw: ptr |
^view_in_focus | Points to view which gets keys etc |
Indexed data | |
---|---|
None | |
System objects | |
fWind | The Mops system window used by the nucleus. |
Methods | ||
---|---|---|
setting characteristics | ||
SetLimits: | ( -- ) | Sets GrowRect and DragRect to reasonable default values according to the current screen size at the time the grow or drag is done |
setContRect: | ( -- ) | Sets the content rectangle after the window has been resized. Also sets Mops's scrolling rectangle, used byCR, equal to the content rectangle |
SetColor: | (b -- ) | Sets the flag for whether the window is to be a color grafPort or a B&W one. Must be used before the window is created |
SetClipGrowLeft: | (b --) | |
SetClipGrowTop: | (b --) | A pair of methods for setting the ClipGrow flags in the ivar list |
setGrow: | ( l t r b T or F -- ) | Sets the window's grow limits. The old action was that if the boolean was true, the rectangle coordinates deter-mined the mini-mum and maximum x and y values that the window could be grown. However the current action is to ignore these coordinates and use a SCREENBITS call instead. If the boolean is false, the window will not be growable |
setDrag: | ( l t r b T or F -- ) | Sets the window's drag limits. The old action was that if the boolean was true, the rectangle coordinates deter-mined the mini-mum and maximum x and y values that the window could be dragged. However the current action is to ignore these coordinates and use a SCREENBITS call instead. If the boolean is false, the window will not be draggable |
setScroll | ( b -- ) | The passed-in boolean indicates whether scrolling is enabled for this window or not. This is primarily intended for the Mops win-dow fWind, which supports scrolling text, and uses the temporary rectangle fpRect for this purpose. If a window doesn't support scrolling, then fpRect won't be altered when that window is active, so you can use it for your own purposes without conflict. Note however, that the proper' way to support scrolling text is via a Scroller view within a Window+ |
setIdle: | ( xt -- ) | Sets the word which will execute in response to idle messages to the window |
set: | ( -- ) | Makes this window the current grafPort |
select: | ( -- ) | Makes this window the frontmost, active window |
size: | ( w h -- ) | Sets the dimensions of the window to the given width and height, without moving the window's upper-left corner |
setSize: | ( w h -- ) | The same as size:this is for naming consistency with Rects and Views |
move: | ( x y -- ) | Moves the upper-left corner of the window to global coordinates x and y without changing its size |
center: | ( -- ) | Centers the window on the screen |
show: | ( -- ) | Calls ShowWindow to make the window visible |
hide: | ( -- ) | Calls HideWindow to make the window invisible |
actions: | ( close enact draw content 4 -- ) |
Sets action vectors with the xts provided. We require an xt count (4 in this case) as this is standard for all actions: methods |
setAct: | ( enact deact -- ) | Sets the activate and deactivate vectors with the xts provided |
setDraw: | ( drawXt -- ) | Sets only the Draw action vector |
title: | ( addr len -- ) | Sets the title of the window to the passed-in string |
name: | ( addr len -- ) | An alias for title: (above) |
putRect: | ( -- l t r b ) | Sets the window's port rectangle coordinates. This and GetRect: are actually methods of the superclass GrafPort |
querying | ||
getName: | ( -- addr len ) | Returns the window's title string |
getRect: | ( -- l t r b ) | Returns the window's port rectangle coordinates |
getPort: | ( -- portAddr ) | Under Carbon , windows aren't GrafPorts any more, so this method returns the port for this window |
getVSRect: | ( -- l t r b ) | Returns the window's default vertical scroll bar rectangle coordi-nates. (Does not require a scroll bar to be present, but if it were, this is where it would be) |
getHSRect: | ( -- l t r b ) | Returns the window's default horizontal scroll bar rectangle coordinates |
maxX: | ( -- x ) | Returns the x coordinate value which the top left corner of the window would have if the window were to be moved all the way to the right of the current screen (so the window's right hand edge would coincide with the right of the screen). Thus it is the maximum x coordinate value which the window could have without being in any way obscured. Doesn't actually move the window |
maxY: | ( -- y ) | Likewise, returns the y coordinate value which the top left corner of the window would have if the window were to be moved all the way to the bottom of the current screen |
active: | ( -- b ) | Returns true if the window is currently active |
alive: | ( -- b ) | Returns true if the window is currently alive in the Toolbox |
event handling | ||
draw: | ( -- ) | This method is executed when an update event occurs for the win-dow. If the win-dow is growable, a grow icon is drawn with scroll bar delimiters. The window's Draw action vector is executed |
idle: | ( -- ) | This method may be used for background processing. Whenever fEvent gets a null event out of the event queue (for instance, while waiting for the user to type a character) a late-bound idle: message is sent to the front (active) window. That win-dow's idle: method can then do any background processing necessary (such as updat-ing a clock picture). The idle method defaults to a do-nothing method in class Window, and should be kept short enough to keep from bogging down responsive-ness to user input |
enable: | ( -- ) | This method is executed when an activate event occurs for the win-dow. The win-dow's Enact action vector is executed |
disable: | ( -- ) | This method is executed when a deactivate event occurs for the window. Does nothing in class Window |
update: | ( -- ) | Forces an update event to occur that will redraw the entire window. The window will not actually be redrawn until KEY is called and event handling is active |
close: | ( -- ) | This method is executed when the user clicks the window's close box. The window's Close action vector is executed, and the Mac API call DisposeWindow is called |
release: | ( -- ) | The same as close:this is our standard destructor name |
drag: | ( -- ) | This method is executed when a mouse-down event occurs in the window's drag region. The Toolbox is called to pull a gray outline around with the mouse. If inac-tive, the window is made active after dragging |
zoom: | ( part -- ) | This method is executed in response to a click in the zoom box. part is supplied by the system when the Event code calls FindWindowit will be 7 if the window is to be zoomed in, or 8 if it is to be zoomed out. Note that although this method is included in class Window, the remainder of zoomable window support is in class Window+, so a zoomable window should therefore be a Window+ |
grow: | ( -- ) | This method is executed when a mouse-down event occurs in the window's grow region. The Toolbox is called to pull a gray out-line around with the mouse. If inactive, the window is made active after growing |
content: | ( -- ) | This method is executed when a mouse-down event occurs in the window's content region. The window's Content action vector is executed |
key: | ( c -- ) | Called when a key is typed and this window is active. Here in class Window, we simply drop the key. In the subclass Window+, the key is sent to the view which is in focus'i.e. the view pointed to by the ^view_in_focus ivar |
initialization | ||
classinit: | ( -- ) | All objects of class Window are initially set to non-growable, draggable windows with null action vectors |
runtime control | ||
new: | ( ^rect tAddr tLen attrsvisible goAway -- ) |
Calls the Toolbox to create a new window using this object's data as the window record. STACKeters determine the window's bounds in global coordinates, the title, the attribute flags (giving the window type), and whether it is visible and has a close box |
getNew: | ( resID -- ) | Same as new:, but uses the resource template with resource id resID |
test: | ( -- ) | Creates a test object of class Window |
Error messages | ||
None |
Reference 10 | Reference | Reference 12 |
Documentation |