home *** CD-ROM | disk | FTP | other *** search
/ CLIX - Fazer Clix Custa Nix / CLIX-CD.cdr / mac / lib / Mac / Lists.pm < prev    next >
Text File  |  1998-04-05  |  10KB  |  501 lines

  1. =head1 NAME
  2.  
  3. Mac::Lists - Macintosh Toolbox Interface to List Manager
  4.  
  5. =head1 SYNOPSIS
  6.  
  7.  
  8. =head1 DESCRIPTION
  9.  
  10. Access to Inside Macintosh is essential for proper use of these functions.
  11. Explanations of terms, processes and procedures are provided there.
  12. Any attempt to use these functions without guidance can cause severe errors in 
  13. your machine, including corruption of data. B<You have been warned.>
  14.  
  15. =cut
  16.     
  17. use strict;
  18.  
  19. package Mac::Lists;
  20.  
  21. BEGIN {
  22.     use Exporter   ();
  23.     use DynaLoader ();
  24.     
  25.     use vars qw(@ISA @EXPORT);
  26.     
  27.     @ISA = qw(Exporter DynaLoader);
  28.     @EXPORT = qw(
  29.         LNew
  30.         LDispose
  31.         LAddColumn
  32.         LAddRow
  33.         LDelColumn
  34.         LDelRow
  35.         LGetSelect
  36.         LLastClick
  37.         LNextCell
  38.         LSize
  39.         LSetDrawingMode
  40.         LScroll
  41.         LAutoScroll
  42.         LUpdate
  43.         LActivate
  44.         LCellSize
  45.         LClick
  46.         LAddToCell
  47.         LClrCell
  48.         LGetCell
  49.         LRect
  50.         LSetCell
  51.         LSetSelect
  52.         LDraw
  53.         
  54.         lDoVAutoscroll
  55.         lDoHAutoscroll
  56.         lOnlyOne
  57.         lExtendDrag
  58.         lNoDisjoint
  59.         lNoExtend
  60.         lNoRect
  61.         lUseSense
  62.         lNoNilHilite
  63.         lInitMsg
  64.         lDrawMsg
  65.         lHiliteMsg
  66.         lCloseMsg
  67.     );
  68. }
  69.  
  70. =head2 Constants
  71.  
  72. =over 4
  73.  
  74. =item lDoVAutoscroll
  75.  
  76. =item lDoHAutoscroll
  77.  
  78. Flags for C<listFlags>.
  79.  
  80. =cut
  81. sub lDoVAutoscroll ()              {          2; }
  82. sub lDoHAutoscroll ()              {          1; }
  83.  
  84.  
  85. =item lOnlyOne
  86.  
  87. =item lExtendDrag
  88.  
  89. =item lNoDisjoint
  90.  
  91. =item lNoExtend
  92.  
  93. =item lNoRect
  94.  
  95. =item lUseSense
  96.  
  97. =item lNoNilHilite
  98.  
  99. Flags for C<selFlags>.
  100.  
  101. =cut
  102. sub lOnlyOne ()                    {       -128; }
  103. sub lExtendDrag ()                 {         64; }
  104. sub lNoDisjoint ()                 {         32; }
  105. sub lNoExtend ()                   {         16; }
  106. sub lNoRect ()                     {          8; }
  107. sub lUseSense ()                   {          4; }
  108. sub lNoNilHilite ()                {          2; }
  109.  
  110.  
  111. =item lInitMsg
  112.  
  113. =item lDrawMsg
  114.  
  115. =item lHiliteMsg
  116.  
  117. =item lCloseMsg
  118.  
  119. =cut
  120. sub lInitMsg ()                    {          0; }
  121. sub lDrawMsg ()                    {          1; }
  122. sub lHiliteMsg ()                  {          2; }
  123. sub lCloseMsg ()                   {          3; }
  124.  
  125. =back
  126.  
  127. =cut
  128.  
  129. bootstrap Mac::Lists;
  130.  
  131. =include Lists.xs
  132.  
  133. =head2 Extension to MacWindow
  134.  
  135. =over 4
  136.  
  137. =cut
  138. package MacWindow;
  139.  
  140. BEGIN {
  141.     use Carp;
  142.     import Mac::Lists;
  143. }
  144.  
  145. =item new_list [CLASS, ] LIST
  146.  
  147. =item new_list [CLASS, ] rView, dataBounds, cSize, theProc, [, drawIt [, hasGrow [, scrollHoriz [, scrollVert]]]]
  148.  
  149. Create a new list, attach it to the window, and return it. In the first form, 
  150. registers an existing list. In the second form, calls  C<LNew>.
  151.  
  152. =cut
  153. sub new_list {
  154.     my($my) = shift @_;
  155.     my($type) = @_;
  156.     my($class,$list);
  157.  
  158.     if (ref($type)) {
  159.         $class = "MacList"
  160.     } else {
  161.         $class = shift @_;
  162.         $type  = $_[0];
  163.     }
  164.     if (ref($type) eq "ListHandle") {
  165.         $list = $type;
  166.     } else {
  167.         my @pre_ = splice(@_, 0, 4);
  168.         $list    = LNew(@pre_, $my->{port}, @_) or croak "LNew failed";
  169.     } 
  170.     $class->new($my, $list);
  171. }
  172.  
  173. =back
  174.  
  175. =head2 MacList - The object interface to a list
  176.  
  177. MacList is a List Manager list embedded into a pane.
  178.  
  179. =cut
  180. package MacList;
  181.  
  182. BEGIN {
  183.     use Mac::Hooks ();
  184.     use Mac::QuickDraw;
  185.     use Mac::Pane;
  186.     use Mac::Events;
  187.     use Mac::Windows();
  188.     import Mac::Lists;
  189.  
  190.     use vars qw(@ISA);
  191.     
  192.     @ISA = qw(Mac::Pane Mac::Hooks);
  193. }
  194.  
  195. =item new WINDOW, CONTROL
  196.  
  197. Initialize a C<MacList> (which is always created with 
  198. C<MacWindow::new_list>).
  199.  
  200. =cut
  201. sub new {
  202.     my($class, $window, $list) = @_;
  203.  
  204.     my(%vars) = (window => $window, list => $list);
  205.     
  206.     my $me = bless \%vars, $class;
  207.     
  208.     $window->add_pane($me);
  209.     $window->add_focusable($me);
  210.     
  211.     $me;
  212. }
  213.  
  214. =item dispose
  215.  
  216. Dispose of the toolbox list.
  217.  
  218. =cut
  219. sub dispose {
  220.     my($my) = @_;
  221.     LDispose($my->{list}) if $my->{list};
  222.     delete $my->{list};
  223. }
  224.  
  225. =item DESTROY
  226.  
  227. Destroys the C<MacList>.
  228.  
  229. =cut
  230. sub DESTROY {
  231.     dispose(@_);
  232. }
  233.  
  234. =item list
  235.  
  236. Get the toolbox list handle.
  237.  
  238. =cut
  239. sub list {
  240.     my($my) = @_;
  241.     
  242.     $my->{list};
  243. }
  244.  
  245. =item attach(WINDOW)
  246.  
  247. Called by MacWindow to indicate that the pane has just been attached.
  248.  
  249. =cut
  250. sub attach {
  251.     my($my, $window) = @_;
  252.     
  253.     $window->{lists}->{${$my->{list}}} = $my;
  254. }
  255.  
  256. =item detach(WINDOW)
  257.  
  258. Called by MacWindow to indicate that the pane has just been detached.
  259.  
  260. =cut
  261. sub detach {
  262.     my($my, $window) = @_;
  263.     
  264.     delete $window->{lists}->{${$my->{list}}};
  265.     dispose(@_);
  266. }
  267.  
  268. =item focus(WINDOW, FOCUS)
  269.  
  270. Called by MacWindow to indicate that the list has acquired (1) or lost (0) the 
  271. focus.
  272.  
  273. =cut
  274. sub focus {
  275.     my($my, $window, $focus) = @_;
  276.     my $list = $my->{list};
  277.     
  278.     LActivate($focus, $list);
  279.  
  280.     $my->callhook("focus", @_) and return;
  281.  
  282.     return unless scalar(@{$window->{focusable}}) > 1;
  283.     
  284.     my $pen  = GetPenState;
  285.     my $r    = InsetRect $list->bounds, -4, -4; 
  286.     PenSize(2,2);
  287.     PenMode($focus ? patOr : patBic);
  288.     FrameRect($r);
  289.     SetPenState($pen);
  290. }
  291.  
  292. =item redraw(WINDOW)
  293.  
  294. Redraw the contents of the pane.
  295.  
  296. =cut
  297. sub redraw {
  298.     my($my, $window) = @_;
  299.     my $list = $my->{list};
  300.     
  301.     LUpdate($window->window->visRgn, $list);
  302.  
  303.     my $r    = InsetRect $list->bounds, -1, -1;
  304.     FrameRect($r);
  305.  
  306.     $my->callhook("redraw", @_) && return;
  307.     
  308.     return unless $window->has_focus($my) && $window->can_focus;
  309.     
  310.     my $pen  = GetPenState;
  311.     $r    = InsetRect $list->bounds, -4, -4;
  312.  
  313.     PenSize(2,2);
  314.     FrameRect($r);
  315.     SetPenState($pen);
  316. }
  317.  
  318. sub _doselection {
  319.     my($list,$clear) = @_;
  320.     
  321.     my $sel = LGetSelect(1, new Point(0,0), $list);
  322.     
  323.     return 
  324.         ($list->dataBounds->botRight, new Point(-1,-1)) 
  325.             unless $sel;
  326.  
  327.     LSetSelect(0, $sel, $list) if $clear;
  328.     
  329.     my($first,$last) = ($sel, $sel);
  330.  
  331.     while ($sel = LNextCell(1, 1, $sel, $list)) {
  332.         last unless $sel = LGetSelect(1, $sel, $list);
  333.         LSetSelect(0, $sel, $list) if $clear;
  334.         $last = $sel;
  335.     }
  336.     
  337.     return ($first, $last);
  338. }
  339.  
  340. sub _selectionrect {
  341.     my($list, $start) = @_;
  342.     my($sel) = new Rect($start->h, $start->v, $start->h, $start->v);
  343.     if (!LGetSelect(0, $start, $list)) {
  344.         return $sel;
  345.     }
  346.     my($cell,$h,$v);
  347.     for ($v = $start->v; $v-- > 0; ) {
  348.         last unless LGetSelect(0, new Point($start->h, $v), $list);
  349.     }
  350.     $sel->top($v+1);
  351.     $v = $start->v+1;
  352.     for ($cell = $start; $cell = LNextCell(0, 1, $cell, $list); ) {
  353.         last unless LGetSelect(0, $cell, $list);
  354.         ++$v;
  355.     }
  356.     $sel->bottom($v);
  357. LEFT:
  358.     for ($h = $start->h; $h-- > 0; ) {
  359.         for ($v = $sel->top; $v < $sel->bottom; ++$v) {
  360.             last LEFT unless LGetSelect(0, new Point($h, $v), $list);
  361.         }
  362.     }
  363.     $sel->left($h+1);
  364. RIGHT:
  365.     $h = $start->h+1;
  366.     for ($cell = $start; $cell = LNextCell(1, 0, $cell, $list); ) {
  367.         for ($v = $sel->top; $v < $sel->bottom; ++$v) {
  368.             last RIGHT unless LGetSelect(0, new Point($h, $v), $list);
  369.         }
  370.         ++$h
  371.     }
  372.     $sel->right($h);
  373.     
  374.     return $sel;
  375. }
  376.  
  377. sub _selectrect {
  378.     my($list, $r, $select) = @_;
  379.     for my $h ($r->left..$r->right-1) {
  380.         for my $v ($r->top..$r->bottom-1) {
  381.             LSetSelect($select, new Point($h, $v), $list);
  382.         }
  383.     }
  384. }
  385.  
  386. =item key(WINDOW, KEY)
  387.  
  388. Handle a key stroke.
  389.  
  390. =cut
  391. sub key {
  392.     my($my, $window, $key) = @_;
  393.     my $list = $my->{list};
  394.     
  395.     $my->callhook("key", @_) and return;
  396.     
  397.     my($h,$v) = (0,0);
  398.     if ($key == 28) {       # Left arrow
  399.         $h = -1;
  400.     } elsif ($key == 29) {  # Right arrow
  401.         $h = 1;
  402.     } elsif ($key == 30) {  # Up arrow
  403.         $v = -1;
  404.     } elsif ($key == 31) {  # Down arrow
  405.         $v = 1;
  406.     } else {
  407.         return 0;
  408.     } 
  409.     my $extend = 
  410.         ($Mac::Events::CurrentEvent->modifiers & shiftKey) 
  411.      && !($list->selFlags & lNoExtend);
  412.     my $extreme = $Mac::Events::CurrentEvent->modifiers & cmdKey;
  413.     my ($first,$last) = _doselection($list, !$extend);
  414.     if (!$extend || !$my->{anchoring}) {
  415.         my $mul = $extreme ? 16380 : 1;
  416.         my $sel = ($h < 0 || $v < 0) ? $first : $last;
  417.         $last->h($sel->h + $mul*$h);
  418.         $last->v($sel->v + $mul*$v);
  419.         $last = Mac::Windows::PinRect($list->dataBounds, $last);
  420.         if ($extend) {
  421.             _selectrect(
  422.                 $list, 
  423.                 ($h>0 || $v>0) 
  424.                   ? new Rect($sel->h, $sel->v, $last->h+1, $last->v+1)
  425.                   : new Rect($last->h, $last->v, $sel->h+1, $sel->v+1),
  426.                 1);
  427.         } else {
  428.             LSetSelect(1, $last, $list);
  429.         }
  430.     }
  431. }
  432.  
  433. =item click(WINDOW, PT)
  434.  
  435. Handle a click.
  436.  
  437. =cut
  438. sub click {
  439.     my($my, $window, $pt) = @_;
  440.     my($res);
  441.     
  442.     ($res = $my->callhook("click", @_)) and return $res;
  443.     
  444.     if (LClick($pt, $Mac::Events::CurrentEvent->modifiers, $my->{list})) {
  445.         $my->hit($window);
  446.     }
  447.     return PtInRect($pt, $my->{list}->bounds);
  448. }
  449.  
  450. =item hit(WINDOW)
  451.  
  452. Handle a double click.
  453.  
  454. =cut
  455. sub hit {
  456.     defined($_[0]->callhook("hit", @_)) and return;
  457. }
  458.  
  459. =item get H, V
  460.  
  461. =item get PT
  462.  
  463. Get the list data for a cell.
  464.  
  465. =cut
  466. sub get {
  467.     my($my)   = shift @_;
  468.     my($cell) = ref($_[0]) ? shift @_ : new Point(splice(@_, 0, 2));
  469.     
  470.     LGetCell($cell, $my->{list});
  471. }
  472.  
  473. =item set H, V, DATA
  474.  
  475. =item set PT, DATA
  476.  
  477. Set the list data for a cell.
  478.  
  479. =cut
  480. sub set {
  481.     my($my)   = shift @_;
  482.     my($cell) = ref($_[0]) ? shift @_ : new Point(splice(@_, 0, 2));
  483.     my($data) = @_;
  484.     
  485.     LSetCell($data, $cell, $my->{list});
  486. }
  487.  
  488. =head1 BUGS/LIMITATIONS
  489.  
  490. =head1 FILES
  491.  
  492. =head1 AUTHOR(S)
  493.  
  494. Matthias Ulrich Neeracher <neeri@iis.ee.ethz.ch> 
  495.  
  496. =cut
  497.  
  498. 1;
  499.  
  500. __END__
  501.