home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-03-19 | 23.6 KB | 391 lines | [TEXT/MMCC] |
- //------------------------------------------------------------------------------
- // File: window.cp
- // Date: 7/17/94
- // Author: Bretton Wade
- //
- // Description: this file contains the methods for the window class. a
- // window is a user interface item that descends from a widget.
- // this implementation uses a macintosh DialogRecord, and
- // stores a pointer to the window widget in the refCon field
- // of the dialog. All windows are dialogs.
- //
- //------------------------------------------------------------------------------
-
- #include "event.h"
- #include "window.h"
-
- //------------------------------------------------------------------------------
- // MyFrontWindow
- //------------------------------------------------------------------------------
- WindowPtr MyFrontWindow (void) // find the frontmost window belonging to the application
- { // begin
- WindowPtr front = FrontWindow (); // get the front window
- while (front) // loop over all the windows
- if ((WindowPeek (front))->windowKind == dialogKind) // if the window is one of mine
- break; // break the loop, this is the one I want
- else // otherwise, this window doesn't belong to me
- front = WindowPtr ((WindowPeek (front))->nextWindow); // advance to the next window
- return front; // return the window that I found
- } // end
-
- //------------------------------------------------------------------------------
- // Close all windows belonging to me
- //------------------------------------------------------------------------------
- bool CloseAllWindows (void) // attempt to close all the windows
- { // begin
- WindowPtr front; // front window
- while ((front = MyFrontWindow ()) != 0) // get the front window belonging to me
- if (!((window *) GetWRefCon (front))->Close ()) // tell the front window to close
- return FALSE; // stop the loop if the user cancelled
- return TRUE; // return the success
- } // end
-
- //------------------------------------------------------------------------------
- // constructor
- //------------------------------------------------------------------------------
- window::window (short id, short tabs, bool modeles) : widget () // constructor
- { // begin
- WindowPeek front = WindowPeek (MyFrontWindow ()); // get a pointer to the front window
- dialog = GetNewDialog (id, 0, WindowPtr (-1)); // create the new dialog
- if (front) // if there was a window already open
- { // begin
- Point pt = TopLeft ((*(front->contRgn))->rgnBBox); // figure the top left coordinate of the previous window
- MoveWindow (dialog, pt.h + 10, pt.v + 10, FALSE); // stagger the new window in relation to the old one
- } // end
- ShowWindow (dialog); // make the new window visible
- SetPort (dialog); // set the graphics port to the new window
- RectRgn (region, &(DialogPeek (dialog)->window.port.portRect)); // rectangular region the size of the window
- SetWRefCon (dialog, long (this)); // assign the widget pointer to the refcon for easy access
- modeless = modeles; // copy the modeless flag
- WStateData *zoom = (WStateData *) *(DialogPeek (dialog)->window.dataHandle); // get a pointer to the zoom sizes
- SetRect (&(zoom->stdState), 20, 60, 419, 459); // set the maximum size and location of the window
- tabstops = tabs; // copy the tabstops count
- aspect = 0; // set the aspect ratio to 0 (no constraint)
- if (tabs) // if there are any tabstops
- { // begin
- stops = new tabstop* [tabs]; // allocate the tabstops array
- for (short i = 0; i < tabs; i++) // loop over all the stops
- stops[0] = 0; // zeroing them to prevent later problems
- curstop = 0; // assign the current tabstop
- } // end
- } // end
-
- //------------------------------------------------------------------------------
- // destructor
- //------------------------------------------------------------------------------
- window::~window (void) // destructor
- { // begin
- KillControls (dialog); // remove all the controls from the window
- DisposeDialog (dialog); // release the window structure
- DiffRgn (gMouseRgn, gMouseRgn, gMouseRgn); // set the mouse moved region to be empty
- } // end
-
- //------------------------------------------------------------------------------
- // Adjust the cursor if it is inside the region
- //------------------------------------------------------------------------------
- widget *window::AdjustCursor (EventRecord &event) // method to adjust the cursor appropriately
- { // begin
- GlobalToLocal (&event.where); // convert the point to local coordinates
- widget *current = widget::AdjustCursor (event); // default adjustment
- if (!current) // if that failed
- { // begin
- GrafPtr wmgrPort; // port with all the screens in its visible region
- GetWMgrPort (&wmgrPort); // get the window manager port
- DiffRgn (wmgrPort->visRgn, DialogPeek (dialog)->window.contRgn, gMouseRgn); // subtract the window content region from the screen visible region
- InitCursor (); // set the cursor to an arrow
- } // end
- return 0; // return an unused value
- } // end
-
- //------------------------------------------------------------------------------
- // Handle a mouse down event in the window
- //------------------------------------------------------------------------------
- void window::HandleClick (EventRecord &event) // method to handle mouse down/up
- { // begin
- WindowPtr wind, front = MyFrontWindow (); // window owning the event, and the front window
- short part = FindWindow (event.where, &wind); // get the part of the window containing the event
- if (wind != front) // if the window is not the front window
- { // begin
- if (event.modifiers & cmdKey) // if the command key is down
- DragWindow (wind, event.where, &((*LMGetGrayRgn ())->rgnBBox)); // drag the window in the background
- else // otherwise
- { // begin
- if (((window *)((WindowPeek (front))->refCon))->Modeless ()) // if the front window can go to the background
- SelectWindow (wind); // bring the event window to the foreground
- else // otherwise
- SysBeep (1); // inform the user of the problem
- } // end
- } // end
- else // otherwise, the window is the front window
- { // begin
- switch (part) // take action appropriate to the click
- { // begin
- case inContent: // click in content region
- HandleClickInContent (event); // handle the click specially
- break; // end click in content
- case inDrag: // the click was in the drag region
- DragWindow (wind, event.where, &((*LMGetGrayRgn ())->rgnBBox)); // drag the window
- AdjustCursor (event); // adjust the mouse regions to reflect the moved window
- break; // end drag
- case inGrow: // click in the grow region
- MyGrowWindow (event.where); // grow the window
- Resize (event); // update the widget regions
- break; // end grow
- case inGoAway: // click in the close box
- if (TrackGoAway (wind, event.where)) // if the user really clicks the close box
- if (event.modifiers & optionKey) // if the option key is down
- CloseAllWindows (); // close all the windows
- else // otherwise
- ((window *)(WindowPeek (wind)->refCon))->Close (); // close this window
- break; // end close
- case inZoomIn: // click in the zoom box
- case inZoomOut: // click in the zoom box
- if (TrackBox (dialog, event.where, part)) // make sure the mouse up is in the zoom box
- { // begin
- EraseRect (&(DialogPeek (dialog)->window.port.portRect)); // erase the window
- ZoomWindow (dialog, part, FALSE); // zoom it appropriately
- Resize (event); // update the widget regions
- } // end
- break; // end zoom
- } // end
- } // end
- } // end
-
- //------------------------------------------------------------------------------
- // Handle a mouse down event in the content area of the window
- //------------------------------------------------------------------------------
- void window::HandleClickInContent (EventRecord &event) // method to handle mouse down/up in the content region
- { // begin
- GlobalToLocal (&event.where); // convert the mouse location to local coordinates
- widget *current = FindWidget (event); // find the owner of the click
- if (current && (current != this)) // if the current widget is valid
- { // begin
- if (tabstops) // if there are tabstops
- for (short i = 0; i < tabstops; i++) // loop over the tabstops (hopefully not many)
- if (stops[i] == current) // if the found widget is a tabstop
- if (i != curstop) // and it is not already the current tabstop
- { // begin
- stops[curstop]->Hilite (FALSE); // unhilite the old tabstop
- curstop = i; // make the found widget the current tabstop
- stops[curstop]->Hilite (TRUE); // hilite the new tabstop
- } // end
- current->HandleClick (event); // let it handle the click
- } // end
- } // end
-
- //------------------------------------------------------------------------------
- // Handle a mouse down event in the content area of the window
- //------------------------------------------------------------------------------
- void window::HandleKey (EventRecord &event) // handle key press events
- { // begin
- if (tabstops) // if there are tabstops
- { // begin
- if ((event.message & charCodeMask) == '\t') // if the key is a tab
- { // begin
- stops[curstop]->Hilite (FALSE); // unhilite the old tabstop
- if (event.modifiers & shiftKey) // if the shift key is down
- curstop = ((curstop - 1) + tabstops) % tabstops; // go to the next tabstop
- else // otherwise
- curstop = (curstop + 1) % tabstops; // go to the next tabstop
- stops[curstop]->Hilite (TRUE); // hilite the new tabstop
- } // end
- stops[curstop]->HandleKey (event); // let the current selection handle the key
- } // end
- } // end
-
- //------------------------------------------------------------------------------
- // Redraw the window contents
- //------------------------------------------------------------------------------
- void window::Update (EventRecord &event) // method to draw the widget and all of its children
- { // begin
- GrafPtr oldPort; // current port
- GetPort (&oldPort); // get the current port
- SetPort (dialog); // set the port to the window
- BeginUpdate (dialog); // set the clip region
- EraseRect (&(DialogPeek (dialog)->window.port.portRect)); // erase the update area
- widget::Update (event); // update the window contents
- EndUpdate (dialog); // restore the clip region
- SetPort (oldPort); // restore the port
- } // end
-
- //------------------------------------------------------------------------------
- // add a child widget to this window
- //------------------------------------------------------------------------------
- void window::AddChild (widget *w) // add a child widget to this one
- { // begin
- widget::AddChild (w); // do the widget thing
- EventRecord event; // a fake event
- GetMouse (&event.where); // get the location of the mouse
- LocalToGlobal (&event.where); // convert it to global coordinates
- Resize (event); // adjust the widget sizes and subtract child regions from mine
- } // end
-
- //------------------------------------------------------------------------------
- // Activate/Deactivate the window
- //------------------------------------------------------------------------------
- void window::Activate (EventRecord &event) // method to activate/deactivate the widget
- { // begin
- bool h = bool((event.modifiers & activeFlag)||(event.message & resumeFlag)); // whether this is a hilite or unhilite
- if (h) // if this window is coming to the foreground
- { // begin
- SetPort (dialog); // set the port to the window
- AdjustCursor (event); // adjust the mouse regions appropriately
- } // begin
- widget::Activate (event); // do the inherited behavior
- if (tabstops) // if there are tabstops
- stops[curstop]->Hilite (h); // hilite the current one
- DrawGrowIcon (); // show the grow icon and scroll bar areas
- } // end
-
- //------------------------------------------------------------------------------
- // resize the window and all the children accordingly
- //------------------------------------------------------------------------------
- void window::Resize (EventRecord &event) // method to recompute sizing information from parent
- { // begin
- RectRgn (region, &(DialogPeek (dialog)->window.port.portRect)); // adjust the widget region
- InvalRgn (region); // force an update of the whole window
- widget::Resize (event); // default behavior
- AdjustCursor (event); // update the mouse regions
- } // end
-
- //------------------------------------------------------------------------------
- // try to close the window, return TRUE for success
- //------------------------------------------------------------------------------
- bool window::Close (void) // method to close the window
- { // begin
- delete this; // call the destructor
- return TRUE; // return the success
- } // end
-
- //------------------------------------------------------------------------------
- // draw the grow icon
- //------------------------------------------------------------------------------
- void window::DrawGrowIcon (void) // draw the little tiddlywink in the lower right corner
- { // begin
- short variant = GetWVariant (dialog); // get the window variant code
- if ((variant == documentProc) || (variant == zoomDocProc)) // if this window is a growable window
- { // begin
- RgnHandle saveRgn = NewRgn (); // create a region for saving the current clipping region
- Rect growRect; // set up a rectangle for the grow region
- growRect.top = DialogPeek (dialog)->window.port.portRect.bottom - 15; // grow rect size
- growRect.left = DialogPeek (dialog)->window.port.portRect.right - 15; // grow rect size
- growRect.bottom = DialogPeek (dialog)->window.port.portRect.bottom; // grow rect size
- growRect.right = DialogPeek (dialog)->window.port.portRect.right; // grow rect size
- GetClip (saveRgn); // save the current clipping region
- ClipRect ( &growRect); // set the clipping to the grow rect
- ::DrawGrowIcon (dialog); // show the grow icon
- SetClip (saveRgn); // restore the old clipping region
- DisposeRgn (saveRgn); // dispose the temporary region
- } // end
- } // end
-
- //------------------------------------------------------------------------------
- // set a tabstop
- //------------------------------------------------------------------------------
- void window::SetTabStop (short stop, tabstop *tab) // set a tabstop
- { // begin
- stops[stop] = tab; // assign the given tabstop
- curstop = stop; // set the current tabstop to this one
- } // end
-
- //------------------------------------------------------------------------------
- // set the aspect ratio constraint of the window
- //------------------------------------------------------------------------------
- void window::SetAspectRatio (short x, short y) // set the aspect ratio constraint value
- { // begin
- aspect = float (x) / float (y); // do the division and set the constraint
- } // end
-
- //------------------------------------------------------------------------------
- // pull a grow rect around the screen
- //------------------------------------------------------------------------------
- void window::PullRect (Point startPt, Rect &startRect, Rect &boundRect) // grow the window rectangle correctly
- { // begin
- Rect oldRect = startRect;
- Boolean hreversed = FALSE,
- vreversed = FALSE;
- short difx = startRect.right - startPt.h,
- dify = startRect.bottom - startPt.v,
- bdifx = boundRect.right - startRect.right,
- bdify = boundRect.bottom - startRect.bottom;
- PenMode (srcXor);
- PenPat (&qd.gray);
- FrameRect (&boundRect);
- short olddragx = 0,
- olddragy = 0;
- while (StillDown ())
- {
- Point endPoint;
- GetMouse (&endPoint);
- short dragx = endPoint.h + difx,
- dragy = endPoint.v + dify;
- if (aspect != 0)
- if ((dragy - olddragy) > (dragx - olddragx))
- dragx = (aspect * (dragy - startRect.top)) + startRect.left;
- else
- dragy = ((dragx - startRect.left) / aspect) + startRect.top;
- olddragx = dragx;
- olddragy = dragy;
- if (dragx > (startRect.left + 40))
- startRect.right = dragx;
- if (dragy > (startRect.top + 40))
- startRect.bottom = dragy;
- if (!EqualRect (&startRect, &oldRect))
- {
- boundRect.right = oldRect.right + bdifx;
- boundRect.bottom = oldRect.bottom + bdify;
- FrameRect(&boundRect);
- boundRect.right = startRect.right + bdifx;
- boundRect.bottom = startRect.bottom + bdify;
- FrameRect(&boundRect);
- oldRect = startRect;
- }
- }
- FrameRect(&boundRect);
- PenMode (srcCopy);
- PenPat (&qd.black);
- } // end
-
- //------------------------------------------------------------------------------
- // grow a window my way
- //------------------------------------------------------------------------------
- void window::MyGrowWindow (Point pt) // grow a window my way
- { // begin
- PenState oldPen;
- WindowPtr WMPort;
- Rect boundRect = (*(WindowPeek (dialog))->strucRgn)->rgnBBox,
- growRect = dialog->portRect;
- SetPort (dialog);
- LocalToGlobal ((Point *) &growRect.top);
- LocalToGlobal ((Point *) &growRect.bottom);
- GetWMgrPort (&WMPort);
- SetPort (WMPort);
- GetPenState (&oldPen);
- GlobalToLocal ((Point *) &growRect.top);
- GlobalToLocal ((Point *) &growRect.bottom);
- GlobalToLocal ((Point *) &boundRect.top);
- GlobalToLocal ((Point *) &boundRect.bottom);
- RgnHandle oldRgn = NewRgn ();
- GetClip (oldRgn);
- Rect wideOpen = {-32768, -32768, 32766, 32766};
- ClipRect (&wideOpen);
- PullRect (pt, growRect, boundRect);
- SetClip (oldRgn);
- SetPenState (&oldPen);
- DisposeRgn (oldRgn);
- SetPort (dialog);
- SizeWindow (dialog, growRect.right - growRect.left, growRect.bottom - growRect.top, FALSE);
- } // end
-
- //------------------------------------------------------------------------------
- // draw the window
- //------------------------------------------------------------------------------
- void window::Draw (void) // draw the widget
- { // begin
- DrawGrowIcon (); // show the grow icon and scroll bar areas
- if (tabstops) // if there are tabstops
- stops[curstop]->Hilite (bool (dialog == MyFrontWindow ())); // hilite the current one
- } // end
-
- //------------------------------------------------------------------------------
-