[Date Prev][Date Next][Thread Prev][Thread Next] [Search] [Date Index] [Thread Index]

Re: [MacPerl-Toolbox] Protocols for pane objects



At 9:53 pm -0400 21/05/00, Bill S wrote:

>Where can I find a description of the protocols for creating and using
>pane objects as implemented in the Mac toolbox modules?

The best tutorial script I know of is Matthias Neeracher's 
'Calculator.pm' which can be found on his Swiss site:

	<ftp://err.ethz.ch/pub/neeri/MacPerl/Beta/>

>I want to display an animated graphic in the content area of a window.
>Reading the code in windows.pm it seems that the proper way to do this
>is to have a pane that receives idle events and an associated routine to
>handle idle events and periodically update graphic paramaters and
>refresh the window. But with so little documentation in the pane.pm
>module I don't see how to associate the pane object with the graphics
>update routine - or anything else, for that matter.

Essentially a 'pane' is just a 'hash' belonging to a name-space (i.e. 
package) you provide for it, which is registered as a 'pane' in the 
window.

If you look at Windows.pm in the subroutine 'new' of package 
MacWindow (round about line 403) you will see the window object is a 
hash which contains elements:

	panes => []     # a list where your pane 'hashes' are 'registered'
         focusable => [] # where you list any panes you declare 'focusable'
	focus => n      # contains the array index of the 'focused' pane

For any instance of a MacWindow (say $win) you can always take a peek 
at the panes from "$win->{port}->{pane}" which will return the list 
of references to each of your panes (in the reverse order of 
registration).

So to do all this you start off by defining the hash for your pane 
which can contain anything you like:

	my $pane_ref = { rect => Rect->new(X, Y, x, y),
                          text => 'hello'};

Now assign this to your package:

	bless $pane_ref, "myPackage";

Now register the pane in your MacWindow ($win) as a 'focusable object':

	$win->add_pane($pane_ref);
         $win->add_focusable($pane_ref);

These 'add' functions are routines in MacWindow circa line 466.

More often than not one would do all of this in a 'new' subroutine in 
'myPackage', (thus providing a pointer to the pane in the main part 
of the script), but it is not essential to do so.

The point of all this rigmarole is so that you can set up routines 
entirely specific for the pane, in which to handle 'events' such as 
key-strokes, updates, idle, mouse-clicks and so on. You can see how 
this happens by looking at MacWindows subroutine 'key' (for example) 
at line 700. 'Windows.pm' firsts looks to see if a 'key' routine 
exists for the window as a whole (via Hooks.pm). If one exists the 
key stroke is 'handled' there and that is the end of the matter. If 
there is no 'hook' then the 'key' is dispatched to the pane that has 
the focus. (Note in passing the in-built tab key routine which steps 
the 'focus' round the 'focusable' panes in the usual Mac fashion.)

How do you get the 'key' into the pane and in general set up event 
handlers for panes? Well, you structure the package to which the pane 
'hashes' belong in the following way:

	package myPackage;

	BEGIN {
	    use Mac::Panes;
             use                       # whatever else you need
	}

         sub key {
	    my ($me, $key) = @_;
             $me->{text} .= chr($key)  # should append to 'hello'
	}

	sub redraw {
            ...
	}

and so forth. You will see the list of possible subroutines in 
Panes.pm. If you don't write a specific routine (let's say for 
example you don't write one for 'click') the click 'point' will pass 
through the null routine in Panes.pm and thence back to Windows.pm as 
having been 'handled'. If you _do_ write a specific routine for 
'click' then the click will be handled there. Commonly one would say:

	sub click {
	    my ($me, $pt) = @_;
             PtInRect($pt, $me->{rect})
	}

which would serve to give the 'focus' to the pane in which the click 
occurred (if it were a 'focusable' pane of course).

The question of where and how to do animation depends on the 
situation. You can sometimes, as you suggest use 'idle', otherwise 
you can use the WaitNextEvent loop, putting a suitable conditional 
statement in there like for instance:
"if (something happens) { $win->redraw }". More importantly, to avoid 
'screen flicker' with animations you will almost certainly want to 
use offscreen graphics. It works brilliantly well in MacPerl, but you 
need later versions (see my site below).

There are examples of all these things in AudioCD_Player which can be 
found on my small site:

	<http://www.afco.demon.co.uk>

That has amongst other things a screen (which is a pane) updated 
every second to show elapsed track-time (using offscreen graphics). 
The re-draw time is determined in the 'WaitNextEvent' loop.

I have a smaller 'tutorial' script involving 'PICT's and movable 
objects which uses both 'panes' and 'offscreen graphics' which I will 
send privately. (It is an archive because of the picts, so 
inappropriate for this list). However if anyone else wants to play 
with it please let me know and I will be happy to send it or put it 
up on the web site.

>Is this documented somewhere else? (I see nothing about panes in Inside
>Macintosh.)

Panes are used quite widely (for example MacPerl's preferences 
window) and are mentioned in IM. However there is no other 
documentation for the MacPerl implementation other than the POD's so 
far as I know.

I hope these notes will be some help.

Alan Fry

==== Want to unsubscribe from this list?
==== Send mail with body "unsubscribe" to macperl-toolbox-request@macperl.org