home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / BSP Tree 1.2 / Sources / Core / source / window.cp < prev   
Encoding:
Text File  |  1995-03-19  |  23.6 KB  |  391 lines  |  [TEXT/MMCC]

  1. //------------------------------------------------------------------------------
  2. //    File:                    window.cp
  3. //    Date:                    7/17/94
  4. //    Author:                Bretton Wade
  5. //
  6. //    Description:    this file contains the methods for the window class. a
  7. //                                window is a user interface item that descends from a widget.
  8. //                                this implementation uses a macintosh DialogRecord, and
  9. //                                stores a pointer to the window widget in the refCon field
  10. //                                of the dialog. All windows are dialogs.
  11. //
  12. //------------------------------------------------------------------------------
  13.  
  14. #include "event.h"
  15. #include "window.h"
  16.  
  17. //------------------------------------------------------------------------------
  18. //    MyFrontWindow
  19. //------------------------------------------------------------------------------
  20. WindowPtr    MyFrontWindow (void)                                                                                                    //    find the frontmost window belonging to the application
  21. {                                                                                                                                                                //    begin
  22.     WindowPtr    front = FrontWindow ();                                                                                            //    get the front window
  23.     while (front)                                                                                                                                    //    loop over all the windows
  24.         if ((WindowPeek (front))->windowKind == dialogKind)                                                    //    if the window is one of mine
  25.             break;                                                                                                                                        //    break the loop, this is the one I want
  26.         else                                                                                                                                                //    otherwise, this window doesn't belong to me
  27.             front = WindowPtr ((WindowPeek (front))->nextWindow);                                            //    advance to the next window
  28.     return front;                                                                                                                                    //    return the window that I found
  29. }                                                                                                                                                                //    end
  30.  
  31. //------------------------------------------------------------------------------
  32. //    Close all windows belonging to me
  33. //------------------------------------------------------------------------------
  34. bool    CloseAllWindows (void)                                                                                                        //    attempt to close all the windows
  35. {                                                                                                                                                                //    begin
  36.     WindowPtr    front;                                                                                                                            //    front window
  37.     while ((front = MyFrontWindow ()) != 0)                                                                                //    get the front window belonging to me
  38.         if (!((window *) GetWRefCon (front))->Close ())                                                            //    tell the front window to close
  39.             return FALSE;                                                                                                                            //    stop the loop if the user cancelled
  40.     return TRUE;                                                                                                                                    //    return the success
  41. }                                                                                                                                                                //    end
  42.  
  43. //------------------------------------------------------------------------------
  44. //    constructor
  45. //------------------------------------------------------------------------------
  46. window::window (short id, short tabs, bool modeles) : widget ()                                    //    constructor
  47. {                                                                                                                                                                //    begin
  48.     WindowPeek    front = WindowPeek (MyFrontWindow ());                                                        //    get a pointer to the front window
  49.     dialog = GetNewDialog (id, 0, WindowPtr (-1));                                                                //    create the new dialog
  50.     if (front)                                                                                                                                        //    if there was a window already open
  51.     {                                                                                                                                                            //    begin
  52.         Point    pt = TopLeft ((*(front->contRgn))->rgnBBox);                                                    //    figure the top left coordinate of the previous window
  53.         MoveWindow (dialog, pt.h + 10, pt.v + 10, FALSE);                                                        //    stagger the new window in relation to the old one
  54.     }                                                                                                                                                            //    end
  55.     ShowWindow (dialog);                                                                                                                    //    make the new window visible
  56.     SetPort (dialog);                                                                                                                            //    set the graphics port to the new window
  57.     RectRgn (region, &(DialogPeek (dialog)->window.port.portRect));                                //    rectangular region the size of the window
  58.     SetWRefCon (dialog, long (this));                                                                                            //    assign the widget pointer to the refcon for easy access
  59.     modeless = modeles;                                                                                                                        //    copy the modeless flag
  60.     WStateData    *zoom = (WStateData *) *(DialogPeek (dialog)->window.dataHandle);    //    get a pointer to the zoom sizes
  61.     SetRect (&(zoom->stdState), 20, 60, 419, 459);                                                                //    set the maximum size and location of the window
  62.     tabstops = tabs;                                                                                                                            //    copy the tabstops count
  63.     aspect = 0;                                                                                                                                        //    set the aspect ratio to 0 (no constraint)
  64.     if (tabs)                                                                                                                                            //    if there are any tabstops
  65.     {                                                                                                                                                            //    begin
  66.         stops = new tabstop* [tabs];                                                                                                //    allocate the tabstops array
  67.         for (short i = 0; i < tabs; i++)                                                                                        //    loop over all the stops
  68.             stops[0] = 0;                                                                                                                            //    zeroing them to prevent later problems
  69.         curstop = 0;                                                                                                                                //    assign the current tabstop
  70.     }                                                                                                                                                            //    end
  71. }                                                                                                                                                                //    end
  72.  
  73. //------------------------------------------------------------------------------
  74. //    destructor
  75. //------------------------------------------------------------------------------
  76. window::~window (void)                                                                                                                    //    destructor
  77. {                                                                                                                                                                //    begin
  78.     KillControls (dialog);                                                                                                                //    remove all the controls from the window
  79.     DisposeDialog (dialog);                                                                                                                //    release the window structure
  80.     DiffRgn (gMouseRgn, gMouseRgn, gMouseRgn);                                                                        //    set the mouse moved region to be empty
  81. }                                                                                                                                                                //    end
  82.  
  83. //------------------------------------------------------------------------------
  84. //    Adjust the cursor if it is inside the region
  85. //------------------------------------------------------------------------------
  86. widget    *window::AdjustCursor (EventRecord &event)                                                            //    method to adjust the cursor appropriately
  87. {                                                                                                                                                                //    begin
  88.     GlobalToLocal (&event.where);                                                                                                    //    convert the point to local coordinates
  89.     widget *current = widget::AdjustCursor (event);                                                                //    default adjustment
  90.     if (!current)                                                                                                                                    //    if that failed
  91.     {                                                                                                                                                            //    begin
  92.         GrafPtr    wmgrPort;                                                                                                                        //    port with all the screens in its visible region
  93.         GetWMgrPort (&wmgrPort);                                                                                                        //    get the window manager port
  94.         DiffRgn (wmgrPort->visRgn, DialogPeek (dialog)->window.contRgn, gMouseRgn);    //    subtract the window content region from the screen visible region
  95.         InitCursor ();                                                                                                                            //    set the cursor to an arrow
  96.     }                                                                                                                                                            //    end
  97.     return 0;                                                                                                                                            //    return an unused value
  98. }                                                                                                                                                                //    end
  99.  
  100. //------------------------------------------------------------------------------
  101. //    Handle a mouse down event in the window
  102. //------------------------------------------------------------------------------
  103. void    window::HandleClick (EventRecord &event)                                                                    //    method to handle mouse down/up
  104. {                                                                                                                                                                //    begin
  105.     WindowPtr    wind, front = MyFrontWindow ();                                                                            //    window owning the event, and the front window
  106.     short    part = FindWindow (event.where, &wind);                                                                    //    get the part of the window containing the event
  107.     if (wind != front)                                                                                                                        //    if the window is not the front window
  108.     {                                                                                                                                                            //    begin
  109.         if (event.modifiers & cmdKey)                                                                                                //    if the command key is down
  110.             DragWindow (wind, event.where, &((*LMGetGrayRgn ())->rgnBBox));                        //    drag the window in the background
  111.         else                                                                                                                                                //    otherwise
  112.         {                                                                                                                                                        //    begin
  113.             if (((window *)((WindowPeek (front))->refCon))->Modeless ())                            //    if the front window can go to the background
  114.                 SelectWindow (wind);                                                                                                        //    bring the event window to the foreground
  115.             else                                                                                                                                            //    otherwise
  116.                 SysBeep (1);                                                                                                                        //    inform the user of the problem
  117.         }                                                                                                                                                        //    end
  118.     }                                                                                                                                                            //    end
  119.     else                                                                                                                                                    //    otherwise, the window is the front window
  120.     {                                                                                                                                                            //    begin
  121.         switch (part)                                                                                                                                //    take action appropriate to the click
  122.         {                                                                                                                                                        //    begin
  123.             case inContent:                                                                                                                        //    click in content region
  124.                 HandleClickInContent (event);                                                                                        //    handle the click specially
  125.                 break;                                                                                                                                    //    end click in content
  126.             case inDrag:                                                                                                                            //    the click was in the drag region
  127.                 DragWindow (wind, event.where, &((*LMGetGrayRgn ())->rgnBBox));                    //    drag the window
  128.                 AdjustCursor (event);                                                                                                        //    adjust the mouse regions to reflect the moved window
  129.                 break;                                                                                                                                    //    end drag
  130.             case inGrow:                                                                                                                            //    click in the grow region
  131.                 MyGrowWindow (event.where);                                                                                            //    grow the window
  132.                 Resize (event);                                                                                                                    //    update the widget regions
  133.                 break;                                                                                                                                    //    end grow
  134.             case inGoAway:                                                                                                                        //    click in the close box
  135.                 if (TrackGoAway (wind, event.where))                                                                        //    if the user really clicks the close box
  136.                     if (event.modifiers & optionKey)                                                                            //    if the option key is down
  137.                         CloseAllWindows ();                                                                                                    //    close all the windows
  138.                     else                                                                                                                                    //    otherwise
  139.                         ((window *)(WindowPeek (wind)->refCon))->Close ();                                    //    close this window
  140.                 break;                                                                                                                                    //    end close
  141.             case inZoomIn:                                                                                                                        //    click in the zoom box
  142.             case inZoomOut:                                                                                                                        //    click in the zoom box
  143.                 if (TrackBox (dialog, event.where, part))                                                                //    make sure the mouse up is in the zoom box
  144.                 {                                                                                                                                                //    begin
  145.                     EraseRect (&(DialogPeek (dialog)->window.port.portRect));                            //    erase the window
  146.                     ZoomWindow (dialog, part, FALSE);                                                                            //    zoom it appropriately
  147.                     Resize (event);                                                                                                                //    update the widget regions
  148.                 }                                                                                                                                                //    end
  149.                 break;                                                                                                                                    //    end zoom
  150.         }                                                                                                                                                        //    end
  151.     }                                                                                                                                                            //    end
  152. }                                                                                                                                                                //    end
  153.  
  154. //------------------------------------------------------------------------------
  155. //    Handle a mouse down event in the content area of the window
  156. //------------------------------------------------------------------------------
  157. void    window::HandleClickInContent (EventRecord &event)                                                    //    method to handle mouse down/up in the content region
  158. {                                                                                                                                                                //    begin
  159.     GlobalToLocal (&event.where);                                                                                                    //    convert the mouse location to local coordinates
  160.     widget    *current = FindWidget (event);                                                                                //    find the owner of the click
  161.     if (current && (current != this))                                                                                            //    if the current widget is valid
  162.     {                                                                                                                                                            //    begin
  163.         if (tabstops)                                                                                                                                //    if there are tabstops
  164.             for (short i = 0; i < tabstops; i++)                                                                            //    loop over the tabstops (hopefully not many)
  165.                 if (stops[i] == current)                                                                                                //    if the found widget is a tabstop
  166.                     if (i != curstop)                                                                                                            //    and it is not already the current tabstop
  167.                     {                                                                                                                                            //    begin
  168.                         stops[curstop]->Hilite (FALSE);                                                                            //    unhilite the old tabstop
  169.                         curstop = i;                                                                                                                //    make the found widget the current tabstop
  170.                         stops[curstop]->Hilite (TRUE);                                                                            //    hilite the new tabstop
  171.                     }                                                                                                                                            //    end
  172.         current->HandleClick (event);                                                                                                //    let it handle the click
  173.     }                                                                                                                                                            //    end
  174. }                                                                                                                                                                //    end
  175.  
  176. //------------------------------------------------------------------------------
  177. //    Handle a mouse down event in the content area of the window
  178. //------------------------------------------------------------------------------
  179. void    window::HandleKey (EventRecord &event)                                                                        //    handle key press events
  180. {                                                                                                                                                                //    begin
  181.     if (tabstops)                                                                                                                                    //    if there are tabstops
  182.     {                                                                                                                                                            //    begin
  183.         if ((event.message & charCodeMask) == '\t')                                                                    //    if the key is a tab
  184.         {                                                                                                                                                        //    begin
  185.             stops[curstop]->Hilite (FALSE);                                                                                        //    unhilite the old tabstop
  186.             if (event.modifiers & shiftKey)                                                                                        //    if the shift key is down
  187.                 curstop = ((curstop - 1) + tabstops) % tabstops;                                                //    go to the next tabstop
  188.             else                                                                                                                                            //    otherwise
  189.                 curstop = (curstop + 1) % tabstops;                                                                            //    go to the next tabstop
  190.             stops[curstop]->Hilite (TRUE);                                                                                        //    hilite the new tabstop
  191.         }                                                                                                                                                        //    end
  192.         stops[curstop]->HandleKey (event);                                                                                    //    let the current selection handle the key
  193.     }                                                                                                                                                            //    end
  194. }                                                                                                                                                                //    end
  195.  
  196. //------------------------------------------------------------------------------
  197. //    Redraw the window contents
  198. //------------------------------------------------------------------------------
  199. void    window::Update (EventRecord &event)                                                                                //    method to draw the widget and all of its children
  200. {                                                                                                                                                                //    begin
  201.     GrafPtr    oldPort;                                                                                                                            //    current port
  202.     GetPort (&oldPort);                                                                                                                        //    get the current port
  203.     SetPort (dialog);                                                                                                                            //    set the port to the window
  204.     BeginUpdate (dialog);                                                                                                                    //    set the clip region
  205.     EraseRect (&(DialogPeek (dialog)->window.port.portRect));                                            //    erase the update area
  206.     widget::Update (event);                                                                                                                //    update the window contents
  207.     EndUpdate (dialog);                                                                                                                        //    restore the clip region
  208.     SetPort (oldPort);                                                                                                                        //    restore the port
  209. }                                                                                                                                                                //    end
  210.  
  211. //------------------------------------------------------------------------------
  212. //    add a child widget to this window
  213. //------------------------------------------------------------------------------
  214. void    window::AddChild (widget *w)                                                                                            //    add a child widget to this one
  215. {                                                                                                                                                                //    begin
  216.     widget::AddChild (w);                                                                                                                    //    do the widget thing
  217.     EventRecord    event;                                                                                                                        //    a fake event
  218.     GetMouse (&event.where);                                                                                                            //    get the location of the mouse
  219.     LocalToGlobal (&event.where);                                                                                                    //    convert it to global coordinates
  220.     Resize (event);                                                                                                                                //    adjust the widget sizes and subtract child regions from mine
  221. }                                                                                                                                                                //    end
  222.  
  223. //------------------------------------------------------------------------------
  224. //    Activate/Deactivate the window
  225. //------------------------------------------------------------------------------
  226. void    window::Activate (EventRecord &event)                                                                            //    method to activate/deactivate the widget
  227. {                                                                                                                                                                //    begin
  228.     bool    h = bool((event.modifiers & activeFlag)||(event.message & resumeFlag));    //    whether this is a hilite or unhilite
  229.     if (h)                                                                                                                                                //    if this window is coming to the foreground
  230.     {                                                                                                                                                            //    begin
  231.         SetPort (dialog);                                                                                                                        //    set the port to the window
  232.         AdjustCursor (event);                                                                                                                //    adjust the mouse regions appropriately
  233.     }                                                                                                                                                            //    begin
  234.     widget::Activate (event);                                                                                                            //    do the inherited behavior
  235.     if (tabstops)                                                                                                                                    //    if there are tabstops
  236.         stops[curstop]->Hilite (h);                                                                                                    //    hilite the current one
  237.     DrawGrowIcon ();                                                                                                                            //    show the grow icon and scroll bar areas
  238. }                                                                                                                                                                //    end
  239.  
  240. //------------------------------------------------------------------------------
  241. //    resize the window and all the children accordingly
  242. //------------------------------------------------------------------------------
  243. void    window::Resize (EventRecord &event)                                                                                //    method to recompute sizing information from parent
  244. {                                                                                                                                                                //    begin
  245.     RectRgn (region, &(DialogPeek (dialog)->window.port.portRect));                                //    adjust the widget region
  246.     InvalRgn (region);                                                                                                                        //    force an update of the whole window
  247.     widget::Resize (event);                                                                                                                //    default behavior
  248.     AdjustCursor (event);                                                                                                                    //    update the mouse regions
  249. }                                                                                                                                                                //    end
  250.  
  251. //------------------------------------------------------------------------------
  252. //    try to close the window, return TRUE for success
  253. //------------------------------------------------------------------------------
  254. bool        window::Close (void)                                                                                                        //    method to close the window
  255. {                                                                                                                                                                //    begin
  256.     delete this;                                                                                                                                    //    call the destructor
  257.     return TRUE;                                                                                                                                    //    return the success
  258. }                                                                                                                                                                //    end
  259.  
  260. //------------------------------------------------------------------------------
  261. //    draw the grow icon
  262. //------------------------------------------------------------------------------
  263. void        window::DrawGrowIcon (void)                                                                                            //    draw the little tiddlywink in the lower right corner
  264. {                                                                                                                                                                //    begin
  265.     short variant = GetWVariant (dialog);                                                                                    //    get the window variant code
  266.     if ((variant == documentProc) || (variant == zoomDocProc))                                        //    if this window is a growable window
  267.     {                                                                                                                                                            //    begin
  268.         RgnHandle    saveRgn = NewRgn ();                                                                                            //    create a region for saving the current clipping region
  269.         Rect    growRect;                                                                                                                            //    set up a rectangle for the grow region
  270.         growRect.top = DialogPeek (dialog)->window.port.portRect.bottom - 15;                //    grow rect size
  271.         growRect.left = DialogPeek (dialog)->window.port.portRect.right - 15;                //    grow rect size
  272.         growRect.bottom = DialogPeek (dialog)->window.port.portRect.bottom;                    //    grow rect size
  273.         growRect.right = DialogPeek (dialog)->window.port.portRect.right;                        //    grow rect size
  274.         GetClip (saveRgn);                                                                                                                    //    save the current clipping region
  275.         ClipRect ( &growRect);                                                                                                            //    set the clipping to the grow rect
  276.         ::DrawGrowIcon (dialog);                                                                                                        //    show the grow icon
  277.         SetClip (saveRgn);                                                                                                                    //    restore the old clipping region
  278.         DisposeRgn (saveRgn);                                                                                                                //    dispose the temporary region
  279.     }                                                                                                                                                            //    end
  280. }                                                                                                                                                                //    end
  281.  
  282. //------------------------------------------------------------------------------
  283. //    set a tabstop
  284. //------------------------------------------------------------------------------
  285. void        window::SetTabStop (short stop, tabstop *tab)                                                        //    set a tabstop
  286. {                                                                                                                                                                //    begin
  287.     stops[stop] = tab;                                                                                                                        //    assign the given tabstop
  288.     curstop = stop;                                                                                                                                //    set the current tabstop to this one
  289. }                                                                                                                                                                //    end
  290.  
  291. //------------------------------------------------------------------------------
  292. //    set the aspect ratio constraint of the window
  293. //------------------------------------------------------------------------------
  294. void        window::SetAspectRatio (short x, short y)                                                                //    set the aspect ratio constraint value
  295. {                                                                                                                                                                //    begin
  296.     aspect = float (x) / float (y);                                                                                                //    do the division and set the constraint
  297. }                                                                                                                                                                //    end
  298.  
  299. //------------------------------------------------------------------------------
  300. //    pull a grow rect around the screen
  301. //------------------------------------------------------------------------------
  302. void        window::PullRect (Point startPt, Rect &startRect, Rect &boundRect)            //    grow the window rectangle correctly
  303. {                                                                                                                                                                //    begin
  304.   Rect        oldRect = startRect;
  305.   Boolean    hreversed = FALSE,
  306.                   vreversed = FALSE;
  307.   short        difx = startRect.right - startPt.h,
  308.                   dify = startRect.bottom - startPt.v,
  309.                   bdifx = boundRect.right - startRect.right,
  310.                   bdify = boundRect.bottom - startRect.bottom;
  311.   PenMode (srcXor);
  312.   PenPat (&qd.gray);
  313.   FrameRect (&boundRect);
  314.   short    olddragx = 0,
  315.               olddragy = 0;
  316.   while (StillDown ())
  317.   {
  318.       Point    endPoint;
  319.       GetMouse (&endPoint);
  320.       short    dragx = endPoint.h + difx,
  321.                   dragy = endPoint.v + dify;
  322.       if (aspect != 0)
  323.           if ((dragy - olddragy) > (dragx - olddragx))
  324.               dragx = (aspect * (dragy - startRect.top)) + startRect.left;
  325.           else
  326.               dragy = ((dragx - startRect.left) / aspect) + startRect.top;
  327.       olddragx = dragx;
  328.         olddragy = dragy;
  329.       if (dragx > (startRect.left + 40))
  330.             startRect.right = dragx;
  331.       if (dragy > (startRect.top + 40))
  332.             startRect.bottom = dragy;
  333.         if (!EqualRect (&startRect, &oldRect))
  334.         {
  335.             boundRect.right = oldRect.right + bdifx;
  336.             boundRect.bottom = oldRect.bottom + bdify;
  337.         FrameRect(&boundRect);
  338.             boundRect.right = startRect.right + bdifx;
  339.             boundRect.bottom = startRect.bottom + bdify;
  340.         FrameRect(&boundRect);
  341.         oldRect = startRect;
  342.         }
  343.     }    
  344.   FrameRect(&boundRect);
  345.     PenMode (srcCopy);
  346.     PenPat (&qd.black);
  347. }                                                                                                                                                                //    end
  348.  
  349. //------------------------------------------------------------------------------
  350. //    grow a window my way
  351. //------------------------------------------------------------------------------
  352. void        window::MyGrowWindow (Point pt)                                                                                    //    grow a window my way
  353. {                                                                                                                                                                //    begin
  354.   PenState    oldPen;
  355.   WindowPtr    WMPort;
  356.   Rect             boundRect = (*(WindowPeek (dialog))->strucRgn)->rgnBBox,
  357.                       growRect = dialog->portRect;
  358.     SetPort (dialog);
  359.   LocalToGlobal ((Point *) &growRect.top);
  360.   LocalToGlobal ((Point *) &growRect.bottom);
  361.   GetWMgrPort (&WMPort);
  362.   SetPort (WMPort);
  363.   GetPenState (&oldPen);
  364.   GlobalToLocal ((Point *) &growRect.top);
  365.   GlobalToLocal ((Point *) &growRect.bottom);
  366.   GlobalToLocal ((Point *) &boundRect.top);
  367.   GlobalToLocal ((Point *) &boundRect.bottom);
  368.   RgnHandle    oldRgn = NewRgn ();
  369.   GetClip (oldRgn);
  370.   Rect             wideOpen = {-32768, -32768, 32766, 32766};
  371.   ClipRect (&wideOpen);
  372.   PullRect (pt, growRect, boundRect);
  373.   SetClip (oldRgn);
  374.   SetPenState (&oldPen);
  375.   DisposeRgn (oldRgn);
  376.     SetPort (dialog);
  377.   SizeWindow (dialog, growRect.right - growRect.left, growRect.bottom - growRect.top, FALSE);
  378. }                                                                                                                                                                //    end
  379.  
  380. //------------------------------------------------------------------------------
  381. //    draw the window
  382. //------------------------------------------------------------------------------
  383. void        window::Draw (void)                                                                                                            //    draw the widget
  384. {                                                                                                                                                                //    begin
  385.     DrawGrowIcon ();                                                                                                                            //    show the grow icon and scroll bar areas
  386.     if (tabstops)                                                                                                                                    //    if there are tabstops
  387.         stops[curstop]->Hilite (bool (dialog == MyFrontWindow ()));                                    //    hilite the current one
  388. }                                                                                                                                                                //    end
  389.  
  390. //------------------------------------------------------------------------------
  391.