home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Apple Macintosh Developer Technical Support
- **
- ** File: Window.c
- ** Written by: Eric Soldan
- **
- ** Copyright © 1990-1993 Apple Computer, Inc.
- ** All rights reserved.
- */
-
- /* You may incorporate this sample code into your applications without
- ** restriction, though the sample code has been provided "AS IS" and the
- ** responsibility for its operation is 100% yours. However, what you are
- ** not permitted to do is to redistribute the source as "DSC Sample Code"
- ** after having made changes. If you're going to re-distribute the source,
- ** we require that you make it clear in the source that the code was
- ** descended from Apple Sample Code, but that you've made changes. */
-
- /* This file contains the code for the document procedure pointers for the main DTS.Draw
- ** document. DTS.Draw currently only supports one type of file-based documents,
- ** type 'DDOC'. */
-
- /* For more information on this file, please read the read.me file "=How to write your app". */
-
-
-
- /*****************************************************************************/
-
-
-
- #include "App.h" /* Get the application includes/typedefs, etc. */
- #include "App.defs.h" /* Get various application definitions. */
- #include "App.protos.h" /* Get the prototypes for application. */
-
- #ifndef __ERRORS__
- #include <Errors.h>
- #endif
-
- #ifndef __FONTS__
- #include <Fonts.h>
- #endif
-
- #ifndef __RESOURCES__
- #include <Resources.h>
- #endif
-
- #ifndef __TOOLUTILS__
- #include <ToolUtils.h>
- #endif
-
- #ifndef __TREEOBJ2__
- #include "TreeObj2.h"
- #endif
-
- #ifndef __UTILITIES__
- #include "Utilities.h"
- #endif
-
-
-
- /*****************************************************************************/
-
-
-
- typedef struct {
- TreeObjHndl root;
- short cnum;
- } LayerDrawInfo;
-
- Boolean gNoDefaultDocument = false;
- /* Set to true if app should boot with no default document. */
- /* This tells DTS.Lib..framework what you want. */
-
- OSType gAppWindowType = kDocFileType; /* Main document type. */
- long gAppWindowAttr = kwAppWindow; /* Main window attributes. */
- long gToolPaletteMenuFlags; /* Remember what items are enabled at startup. */
-
- short gMinVersion = kMinVersion; /* Minimum document version app can support. */
- short gMaxVersion = kMaxVersion; /* Maximum document version app can support. */
- /* More informing DTS.Lib..framework. */
-
- extern short gPrintPage; /* Non-zero means we are printing. */
- /* DTS.Lib..framework global. */
-
- extern RgnHandle gCursorRgn; /* We handle cursors here, so we need */
- extern CursPtr gCursorPtr; /* to know about these things. */
- /* Above are DTS.Lib..framework globals. */
-
- static void AddOrSizeObj(FileRecHndl frHndl, TreeObjHndl hndl, ClickInfo *click);
- static void SlideSelection(FileRecHndl frHndl, ClickInfo *click);
- static OSErr WindowLayerProc(LayerObj theLayer, short message);
- static OSErr WorkLayerProc(LayerObj theLayer, short message);
- static OSErr BackLayerProc(LayerObj theLayer, short message);
- static void DrawPageGrid(void);
-
- #define kDataAreaPadding 0
-
-
- /*****************************************************************************/
- /*****************************************************************************/
-
-
-
- /* •• You don't call this. DTS.Lib..framework does for appropriate document type(s). •• */
-
- /* Calculate application specific frame area (Called by DoCalcFrameRgn).
- ** You are passed an empty region. You are supposed to add any custom frame
- ** parts that this document uses. Typically there are no frame portions, as
- ** they are accounted for in other ways. The scrollbars and grow icon will
- ** automatically be contributed to the calculation of the frame region.
- ** If you use sidebars, these are also added in automatically. This is only
- ** used if the frame region is more complicated than can automatically be
- ** handled. So, almost always, you will simply leave the region empty. */
-
- #pragma segment TheDoc
- void CalcFrameRgn(FileRecHndl frHndl, WindowPtr window, RgnHandle rgn)
- {
- #ifndef __MWERKS__
- #pragma unused (frHndl, window, rgn)
- #endif
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* •• You don't call this. DTS.Lib..framework does for appropriate document type(s). •• */
-
- /* This is called (by DoContentClick()) when a mouse-down event occurs in the content of
- ** a window. Other applications might want to call FindControl, TEClick, etc., to
- ** further process the click. */
-
- #pragma segment TheDoc
- void ContentClick(WindowPtr window, EventRecord *event, Boolean firstClick)
- {
- #ifndef __MWERKS__
- #pragma unused (firstClick)
- #endif
-
- FileRecHndl frHndl;
- ControlHandle ctl;
- short dblClick, shiftMod;
- Point contOrg;
- Boolean selected;
- TreeObjHndl hitObj, root;
- ClickInfo click;
-
- SetPort(window);
-
- if (IsCtlEvent(window, event, &ctl, &dblClick)) return;
- /* That was easy. Scrolling was just handled. Other stuff would be handled
- ** by IsCtlEvent, if we had other stuff to do. We don't have any other
- ** controls in the content besides the document scrollbars. */
-
- frHndl = (FileRecHndl)GetWRefCon(window);
- if ((*frHndl)->fileState.readOnly) return;
- /* Don't allow changes if read-only. */
-
- /* If none of the above resolved why we are here, then the click was in the
- ** actual drawing area of the content, and we have some serious work to do. */
-
- GetContentOrigin(window, &contOrg);
- SetOrigin(contOrg.h, contOrg.v);
- /* This sets the origin of the document area of the content to the position
- ** indicated by the document scrollbars. */
-
- click.localEvent = *event;
- GlobalToLocal(&click.localEvent.where);
- /* Who wants to work in global coordinates, anyway... */
-
- if (!GetTool()) { /* If no specific tool (arrow tool)... */
-
- click.message = HITTESTGRABBER;
- hitObj = DoTreeHitTest(root = (*frHndl)->d.doc.root, &click);
- /* See if the user clicked on a grabber for a selected object. */
-
- if (!hitObj) { /* If user didn't click on a grabber, see if they hit an object. */
- click.message = HITTESTOBJ;
- hitObj = DoTreeHitTest(root = (*frHndl)->d.doc.root, &click);
- }
-
- shiftMod = click.localEvent.modifiers & shiftKey;
- /* Find out if the user was holding down the shift key. */
-
- if (click.message == HITTESTGRABBER)
- shiftMod = 0;
- /* Pretent that the shift key isn't held down if they are on a grabber. If
- ** they are on a grabber, you want to do a constrain with the shift key. */
-
- if (hitObj) { /* User hit either a grabber or the object itself. */
-
- selected = mDerefCommon(hitObj)->selected;
- /* See if the object hit, independent of type, was selected. */
-
- if ((!selected) && (!shiftMod)) /* The object isn't selected, and */
- DoTreeSelect(root, SELECTOFF); /* the shift key isn't held down, */
- /* so deselect all other objects. */
-
- click.message = CLICKSELECT;
- if ((!selected) || (shiftMod))
- DoTreeObjMethodClipped(hitObj, CLICKMESSAGE, (long)&click);
- /* If the object isn't selected, or if the shift key is down, change
- ** the select state of the object that was clicked on. */
-
- click.localEvent.modifiers ^= shiftMod;
- /* Turn off the shift modifier, which makes the rest of the
- ** handling of the object easier. */
-
- if (mDerefCommon(hitObj)->selected) { /* If object selected, do something with it. */
- if (click.grabber == -1)
- SlideSelection(frHndl, &click);
- else
- AddOrSizeObj(frHndl, hitObj, &click);
- } /* The click could have been used to shift-click deselect an object,
- ** so only do something with the object if it is selected. We either
- ** resize the object (if a grabber was clicked on) or slide the selected
- ** objects (if an object was clicked on). */
-
- }
- else { /* No object was clicked on... */
-
- if (!shiftMod) /* If not a shift-click, */
- DoTreeSelect(root, SELECTOFF); /* deselect everything. */
-
- AddOrSizeObj(frHndl, hitObj, &click); /* Do extend select. */
- }
- }
- else {
- click.message = HITTESTGRABBER;
- hitObj = DoTreeHitTest(root = (*frHndl)->d.doc.root, &click);
- /* See if the user clicked on a grabber for a selected object. */
- AddOrSizeObj(frHndl, hitObj, &click);
- /* No object clicked on, so add an object. */
- }
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* •• You don't call this. DTS.Lib..framework does for appropriate document type(s). •• */
-
- /* DoKeyDown() is first called by the application. Then if the key isn't a menu
- ** key, DoKeyDown() calls this code. Here are the rules for this function:
- **
- ** 1) If you handle the key, return(true). This completes the key handling.
- ** 2) If you don't handle the key, you return false. However, there are two
- ** situations for not handling the key:
- ** a) You want someone else to.
- ** b) You want nobody else to look at the key.
- ** This is what the boolean passThrough is for. If you wish the next window
- ** to have a look at the key, set the boolean passThrough to true. passThrough
- ** is already initialized to false, which is the common case, so you only have
- ** to worry about setting it true.
- **
- ** If you have a window that never processes keys and always passes them through,
- ** just set the contentKeyProc to nil. This will indicate to the application
- ** framework that all keys should be passed through this window. DTS.Draw has
- ** such a window. Its palette window doesn't accept keys. They are passed through
- ** to document windows. */
-
- #pragma segment TheDoc
- Boolean ContentKey(WindowPtr window, EventRecord *event, Boolean *passThrough)
- {
- #ifndef __MWERKS__
- #pragma unused (passThrough)
- #endif
-
- char key;
- FileRecHndl frHndl;
-
- key = event->message & charCodeMask;
- if (key != 8) return(false);
- /* The only key we handle is the delete key. leave for all the rest. */
-
- SetPort(window);
-
- frHndl = (FileRecHndl)GetWRefCon(window);
- if ((*frHndl)->fileState.readOnly) return(false);
- /* Don't allow changes if read-only. */
-
- DoDelete(frHndl);
-
- return(true);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* •• You don't call this. DTS.Lib..framework does for appropriate document type(s). •• */
-
- /* Draw application specific content (Called by DoDrawFrame).
- **
- ** If your application has any custom frame areas, or if it uses sidebars,
- ** this is the function that you would put the frame drawing code. The
- ** document scrollbars and grow icon drawing is handled by DTS.framework.
- ** Just do the sidebar and custom areas here. */
-
- #pragma segment TheDoc
- void DrawFrame(FileRecHndl frHndl, WindowPtr window, Boolean activate)
- {
- MoveTo(0, (*frHndl)->fileState.topSidebar - 1);
- LineTo((*frHndl)->fileState.leftSidebar - 1 - 16384, (*frHndl)->fileState.topSidebar - 1);
- LineTo((*frHndl)->fileState.leftSidebar - 1 - 16384, 16383);
-
- BeginFrame(window);
- DoDrawControls(window, activate);
- EndFrame(window);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* •• You don't call this. DTS.Lib..framework does for appropriate document type(s). •• */
-
- /* Frees up any application-specific memory in the document. This is called by
- ** DoFreeDocument, which is called by DisposeDocument(). The application would
- ** call DisposeDocument(), not DoFreeDocument() or FreeDocument() directly.
- **
- ** The document may have a bunch of handles off the main handle of the document.
- ** This is where they are freed. DisposeDocument calls this prior to releasing
- ** the ram for the main handle of the document, so release everything else
- ** here, or you will have a memory leak.
- **
- ** NOTE: Calling DefaultFreeDocument() frees up all memory used by a
- ** hierarchical document (see TreeObj package). */
-
- #pragma segment TheDoc
- OSErr FreeDocument(FileRecHndl frHndl)
- {
- return(DefaultFreeDocument(frHndl));
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* •• You don't call this. DTS.Lib..framework does for appropriate document type(s). •• */
-
- /* Any additional window disposal tasks can be handled here. */
-
- #pragma segment TheDoc
- OSErr FreeWindow(FileRecHndl frHndl, WindowPtr window)
- {
- #ifndef __MWERKS__
- #pragma unused (window)
- #endif
-
- WindowPtr ww;
- FileRecHndl ff;
-
- if ((*frHndl)->fileState.sfType == kDocFileType) {
- ManageDragHandlers(window, false);
- for (ww = nil; (ww = GetNextWindow(ww, 0)) != nil;) {
- ff = (FileRecHndl)GetWRefCon(ww);
- if ((*ff)->fileState.sfType == kViewHierFileType) {
- if ((*frHndl)->d.doc.root == (*ff)->d.doc.root) {
- DisposeOneWindow(ww, kClose);
- ww = nil;
- }
- }
- }
- }
-
- return(noErr);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* •• You don't call this. DTS.Lib..framework does for appropriate document type(s). •• */
-
- /* Image the document into the current port.
- **
- ** The only thing tricky about this function is that it needs to key off of
- ** the global variable gPrintPage. gPrintPage is the current page that is
- ** being printed. If gPrintPage is 0, then you are drawing to the window.
- **
- ** For when printing:
- **
- ** If gPrintPage is non-0, that is the page to be printed. If after imaging
- ** the page there are no more pages, you should set gPrintPage to 0. This
- ** indicates to the print loop that the end of the document has been reached.
- ** Even if the user indicated in the job dialog to print more pages, setting
- ** gPrintPage to 0 states that the last page has been printed. This is necessary
- ** because the print loop can't know when printing is done. The imaging procedure
- ** is the logical one to state when everything has been imaged. */
-
- #pragma segment TheDoc
- OSErr ImageDocument(FileRecHndl frHndl)
- {
- LayerDrawInfo drawInfo;
- LayerObj wlyr, blyr;
-
- drawInfo.root = (*frHndl)->d.doc.root;
- /* If there isn't a background layer, then all objects are drawn into
- ** the work layer, and therefore we don't need to fill in the cnum field
- ** of the drawInfo. The WorkLayerProc will notice that there isn't a
- ** layer behind it and will automatically do the right thing. */
-
- if (gPrintPage) {
- DoTreeDraw(drawInfo.root, DRAWOBJ); /* Draw the page. */
- gPrintPage = 0; /* We only support one page in this sample. */
- return(noErr);
- }
-
- NewLayer(&wlyr, nil, WindowLayerProc, (*frHndl)->fileState.window, 0, (long)&drawInfo);
- /* Create a layer object for the window. */
-
- NewLayer(&blyr, wlyr, WorkLayerProc, nil, 0, (long)&drawInfo);
- /* Create a background layer for drawing of all of the objects. */
-
- InvalLayer(wlyr, GetEffectiveDstRect(wlyr), false);
- /* We want to draw the entire contents. */
-
- UpdateLayer(wlyr);
- /* Update what's invalid, which is everything. All the objects are drawn into
- ** the background layer, and then the background layer is transferred into the
- ** window. */
-
- DisposeThisAndBelowLayers(wlyr);
- /* Clean up what we created. */
-
- return(noErr);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* •• You don't call this. DTS.Lib..framework does for appropriate document type(s). •• */
-
- /* This function does the remaining window initialization.
- **
- ** There may be additional content initialization for the window. At this point,
- ** you have a window, but it is currently invisible. If you return noErr, then
- ** the window will be set to the state indicated for that window. Why this function?
- ** You may wish to add controls to the content of the window. You may have a
- ** TextEdit record in the content. All of these sort of things can't be created
- ** until there is a window to contain them. First a document is read in, and then
- ** if the document creation succeeds, a window is created for that document.
- ** At this point we have a document, and we are on our way to having a window.
- ** All that remains is any additional content initialization. Do it, return
- ** noErr, and everybody's happy. If something goes wrong here, return the error,
- ** and the incomplete window will be disposed of. */
-
- #pragma segment TheDoc
- OSErr InitContent(FileRecHndl frHndl, WindowPtr window)
- {
- OSErr err;
- Rect rct;
- TreeObjHndl root;
-
- err = AddControlSet(window, (*frHndl)->fileState.sfType, kwStandardVis, 0, 0, nil);
-
- rct = GetDataArea(root = (*frHndl)->d.doc.root);
- SetDataArea(root, rct.right, rct.bottom);
- ManageDragHandlers(window, true);
-
- return(err);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* •• You don't call this. DTS.Lib..framework does for appropriate document type(s). •• */
-
- /* The code below assumes that you are using the hierarchical document package.
- ** If you are, the entire hierarchical document is read in with just these two
- ** calls. If you don't use it, you are on your own. See DTS.Chat for an
- ** example of an application that uses the DTS.framework without the hierarchical
- ** document package. */
-
- #pragma segment TheDoc
- OSErr ReadDocument(FileRecHndl frHndl)
- {
- OSErr err;
- TreeObjHndl root;
-
- err = DefaultReadDocument(frHndl);
- root = (*frHndl)->d.doc.root;
- mDerefRoot(root)->numSelected = 0; /* User may have saved when objects were selected. */
- if (!err)
- DefaultReadDocumentFixup(frHndl);
-
- return(err);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* •• You don't call this. DTS.Lib..framework does for appropriate document type(s). •• */
-
- /* Resize application specific content (Called by ResizeWindow).
- **
- ** This gets called when a user does a zoom or window resizing operation.
- ** It is possible that things in the content need to be resized in conjunction
- ** with the resizing of the window. */
-
- #pragma segment TheDoc
- void ResizeContent(WindowPtr window, short oldh, short oldv)
- {
- #ifndef __MWERKS__
- #pragma unused (window, oldh, oldv)
- #endif
-
- /* See DTS.Chat for a sample usage of this function. */
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* •• You don't call this. DTS.Lib..framework does for appropriate document type(s). •• */
-
- /* Scroll application specific frame (Called by DoScrollFrame).
- **
- ** Some applications may need to scroll the "frame" of the document along
- ** with the document contents. This is common for applications with rulers,
- ** or other similar sidebar items. */
-
- #pragma segment TheDoc
- void ScrollFrame(FileRecHndl frHndl, WindowPtr window, long dh, long dv)
- {
- #ifndef __MWERKS__
- #pragma unused (frHndl, window, dh, dv)
- #endif
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* •• You don't call this. DTS.Lib..framework does for appropriate document type(s). •• */
-
- /* This gets called just prior to and just after an undo/redo operation is done. */
-
- #pragma segment TheDoc
- void UndoFixup(FileRecHndl frHndl, Point contOrg, Boolean afterUndo)
- {
- WindowPtr window;
- TreeObjHndl root;
- Rect rct;
-
- window = (*frHndl)->fileState.window;
- root = (*frHndl)->d.doc.root;
-
- if (!afterUndo) /* Before an undo operation we deselect everything. */
- DoTreeSelect(root, SELECTOFF); /* Only what was undone should end up selected. */
-
- if (afterUndo) {
- rct = GetDataArea(root);
- SetDataArea(root, rct.right, rct.bottom);
- SetContentOrigin(window, contOrg.h, contOrg.v);
- /* Undo may have a different document origin than where the user was.
- ** Scroll the document back to where the edit we are undoing took place. */
-
- BeginContent(window); /* Redraw the document to display */
- DoImageDocument(frHndl); /* the changes due to undo. */
- EndContent(window);
- }
-
- DoSetCursor(nil);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* •• You don't call this. DTS.Lib..framework does for appropriate document type(s). •• */
-
- /* This function is where you adjust the cursor to reflect the location in the
- ** document or window. You have the additional input of gCursorRgn to deal
- ** with. The way that the cursor handling works is as follows:
- ** 1) The application calls DoWindowCursor().
- ** 2) DoWindowCursor() works its way through the windows/documents, front to back.
- ** It looks at the document's windowCursorProc and checks to see if the document
- ** has one. If the document doesn't have one, then it assumes that that window
- ** always wants an arrow. If the cursor is over that window, the cursor is set
- ** to an arrow, and we're done. If the cursor isn't over the window, then the next
- ** window is tried. If all documents don't have a windowCursorProc, then the cursor
- ** is set to an arrow (for the non-document area of the screen).
- ** 3) If a document has a windowCursorProc, then the proc is called. The proc's
- ** job is as follows:
- ** a) If the cursor is over a position that is determined by the window, then
- ** the proc removes other areas from gCursorRgn. Note that it should not
- ** simply set the area to what it "thinks" is the correct area. This window
- ** may not be the front-most. Other windows will have already been subtracted
- ** from gCursorRgn. The resultant gCursorRgn is the correct cursor area,
- ** and should be passed to WaitNextEvent calls in the application (already the case
- ** in EventLoop.c). Also, the cursor should be set to the correct cursor, of course.
- ** You should also return true, as the cursor has been determined.
- ** b) If the cursor is not over a position for this window, then you should
- ** return. You will either pass back true or false. If you don't wish
- ** windows behind this window to have a shot at cursor determination, then
- ** return true. This states that the cursor is "determined". It is, in the
- ** sense that no further determination will occur. If you return false, then
- ** other windows get a shot at determining the cursor.
- **
- ** Setting the cursor to the correct cursor isn't as easy as you would expect.
- ** DTS.Lib..framework uses the global gCursorPtr as the reference to the cursor. This is
- ** fine if the cursor is pointer-based, but if the cursor is resource-based, it is a bit
- ** more of a problem. What you will need to do is to call DoSetResCursor() to make the
- ** resource cursor pointer-based. DoSetResCursor() will set gCursorPtr to nil, and it
- ** also returns the pointer to the permanent copy of the cursor resource. Just set gCursorPtr
- ** to the return result of DoSetResCursor(), and you will be set. */
-
- #pragma segment TheDoc
- Boolean WindowCursor(FileRecHndl frHndl, WindowPtr window, Point globalPt)
- {
- #ifndef __MWERKS__
- #pragma unused (frHndl)
- #endif
-
- RgnHandle frameRgn, contRgn;
-
- if (GetTool()) {
- frameRgn = DoCalcFrameRgn(window);
- contRgn = NewRgn();
- DiffRgn(((WindowPeek)window)->contRgn, frameRgn, contRgn);
- DisposeRgn(frameRgn);
- if (PtInRgn(globalPt, contRgn)) {
- gCursorPtr = DoSetResCursor(addObjCursor);
- SectRgn(gCursorRgn, contRgn, gCursorRgn);
- DisposeRgn(contRgn);
- return(true);
- }
- DiffRgn(((WindowPeek)window)->strucRgn, contRgn, contRgn);
- SectRgn(gCursorRgn, contRgn, gCursorRgn);
- DisposeRgn(contRgn);
- }
-
- SetCursor(gCursorPtr = &qd.arrow);
- return(true);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* •• You don't call this. DTS.Lib..framework does for appropriate document type(s). •• */
-
- /* After the DTS.Lib framework disposes of a window, it calls here. This is
- ** to give the application a chance to do any additional tasks related to
- ** a window closing. DTS.Chat doesn't have anything else extra to do. */
-
- #pragma segment TheDoc
- void WindowGoneFixup(WindowPtr window)
- {
- #ifndef __MWERKS__
- #pragma unused (window)
- #endif
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* •• You don't call this. DTS.Lib..framework does for appropriate document type(s). •• */
-
- /* The reverse function of ReadDocument. */
-
- #pragma segment TheDoc
- OSErr WriteDocument(FileRecHndl frHndl)
- {
- return(DefaultWriteDocument(frHndl));
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* •• You don't call this. DTS.Lib..framework does at open-application time. •• */
-
- #pragma segment TheDoc
- OSErr DoOpenApplication(void)
- {
- MenuHandle menu;
-
- menu = GetMenuHandle(mToolPalette);
- if (menu)
- gToolPaletteMenuFlags = (*menu)->enableFlags;
-
- return(noErr);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* •• You don't call this. DTS.Lib..framework does for appropriate document type(s). •• */
-
- #pragma segment TheDoc
- Boolean AdjustMenuItems(WindowPtr window, short menuID)
- {
- Boolean redrawMenuBar;
- MenuHandle menu;
-
- redrawMenuBar = false;
-
- switch (menuID) {
- case mFile:
- redrawMenuBar = DoAdjustFileMenu(window);
- break;
- case mEdit:
- redrawMenuBar = DoAdjustEditMenu(window);
- break;
- case mArrange:
- redrawMenuBar = DoAdjustArrangeMenu(window);
- break;
- case mToolPalette:
- menu = GetMenuHandle(menuID);
- if (menu)
- (*menu)->enableFlags = gToolPaletteMenuFlags;
- break;
- case mOther:
- redrawMenuBar = DoAdjustOtherMenu(window);
- break;
- default:
- menu = GetMenuHandle(menuID);
- if (menu)
- (*menu)->enableFlags |= 0xFFFFFFFEL;
- break;
- }
-
- return(redrawMenuBar);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* •• You don't call this. DTS.Lib..framework does for appropriate document type(s). •• */
-
- #pragma segment TheDoc
- Boolean DoMenuItem(WindowPtr window, short menuID, short menuItem)
- {
- #ifndef __MWERKS__
- #pragma unused (window)
- #endif
-
- return(DoMenuCommand(menuID, menuItem));
- }
-
-
-
- /*****************************************************************************/
- /*****************************************************************************/
- /*****************************************************************************/
-
-
-
- #pragma segment DrawDoc
- OSErr DuplicateDocument(FileRecHndl oldFrHndl, FileRecHndl *newFrHndl)
- {
- OSErr err;
- TreeObjHndl root;
-
- err = NewDocument(newFrHndl, (*oldFrHndl)->fileState.sfType, true);
- /* Create a document and root object to copy the file data into. */
-
- if (!err)
- err = CopyChildren((*oldFrHndl)->d.doc.root, (**newFrHndl)->d.doc.root);
- /* Copy the hierarchical data into the new file. */
-
- if (!err) {
- root = (**newFrHndl)->d.doc.root;
- DoFTreeMethod(root, UNDOMESSAGE, UNDOFROMDOC);
- mDerefRoot(root)->numSelected = 0;
- } /* We have to be careful to use methods that don't try to draw
- ** anything, as we don't have a window to draw into yet. */
-
- return(err);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* This is called when a key event occurs and it is determined that it isn't
- ** a menu key. */
-
- #pragma segment DrawDoc
- void DoDelete(FileRecHndl frHndl)
- {
- WindowPtr window;
- TreeObjHndl root;
- short cnum;
- Boolean didDelete;
-
- root = (*frHndl)->d.doc.root;
- /* All of the selected objects are children of the root, so all we have to do
- ** is walk the children of the root looking for selected objects. If the
- ** document has grouping objects, which have sub-children, only the group
- ** object is selected. */
-
- for (didDelete = false, cnum = (*root)->numChildren; cnum;) {
- if (mDerefCommon(GetChildHndl(root, --cnum))->selected) {
- if (!didDelete)
- NewDocumentUndo(frHndl);
- /* Make sure this delete event is posted in a separate undo from
- ** a possible previous delete event. */
- DisposeChild(DELETE_EDIT, root, cnum);
- /* Post the delete of the child into the undo hierarchy. */
- didDelete = true;
- /* Yes, we did change the document. */
- }
- }
-
- if (didDelete) { /* If something got deleted... */
- window = (*frHndl)->fileState.window;
- SetWindowDirty(window); /* Flag the document as dirty. */
- BeginContent(window); /* Redraw the contents. */
- DoImageDocument(frHndl);
- EndContent(window);
- }
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment DrawDoc
- void DoArrange(FileRecHndl frHndl, short menuItem)
- {
- TreeObjHndl root;
- short cnum, cdir, cend;
- WindowPtr window;
-
- if (menuItem >= kGroup) {
- switch (menuItem) {
- case kGroup:
- DoGroup(frHndl);
- break;
- case kUngroup:
- DoUngroup(frHndl);
- break;
- }
- }
- else {
- root = (*frHndl)->d.doc.root;
-
- cnum = 0;
- cdir = 1;
- cend = (*root)->numChildren;
-
- if (cend)
- NewDocumentUndo(frHndl);
-
- if (menuItem >= kMoveBackward) {
- cnum = cend - 1;
- cdir = -1;
- cend = -1;
- }
-
- for (; cnum != cend; cnum += cdir) {
- if (DoTreeObjMethod(GetChildHndl(root, cnum), GETSELECTMESSAGE, 0)) {
- switch (menuItem) {
- case kMoveForward:
- if (cnum)
- MoveChild(MOVEFORWARD_EDIT, root, cnum, root, cnum - 1);
- break;
- case kMoveToFront:
- MoveChild(MOVETOFRONT_EDIT, root, cnum, root, 0);
- break;
- case kMoveBackward:
- MoveChild(MOVEBACKWARD_EDIT, root, cnum, root, cnum + 1);
- break;
- case kMoveToBack:
- MoveChild(MOVETOBACK_EDIT, root, cnum, root, -1);
- break;
- }
- }
- }
- }
- SetWindowDirty(window = (*frHndl)->fileState.window);
-
- BeginContent(window);
- DoImageDocument(frHndl);
- EndContent(window);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment DrawDoc
- Rect GetSelectedArea(TreeObjHndl root)
- {
- TreeObjHndl child;
- short cnum;
- Rect selectRct, rct;
- Boolean first;
-
- SetRect(&selectRct, 0, 0, 0, 0);
- for (first = true, cnum = (*root)->numChildren; cnum;) {
- child = GetChildHndl(root, --cnum);
- if (DoTreeObjMethod(child, GETSELECTMESSAGE, 0)) {
- DoTreeObjMethod(child, GETBBOXMESSAGE, (long)&rct);
- if (!EmptyRect(&rct)) {
- if (first) {
- selectRct = rct;
- first = false;
- }
- else UnionRect(&selectRct, &rct, &selectRct);
- }
- }
- }
- return(selectRct);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment DrawDoc
- Rect GetDataArea(TreeObjHndl root)
- {
- TreeObjHndl child;
- short cnum;
- Rect areaRct, rct;
- Boolean first;
-
- SetRect(&areaRct, 0, 0, 0, 0);
- for (first = true, cnum = (*root)->numChildren; cnum;) {
- child = GetChildHndl(root, --cnum);
- DoTreeObjMethod(child, GETBBOXMESSAGE, (long)&rct);
- if (!EmptyRect(&rct)) {
- if (first) {
- areaRct = rct;
- first = false;
- }
- else UnionRect(&areaRct, &rct, &areaRct);
- }
- }
- return(areaRct);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment DrawDoc
- void SetDataArea(TreeObjHndl root, short h, short v)
- {
- if (h != kwNoChange) {
- h /= (7 * 72);
- ++h;
- h *= (7 * 72);
- }
-
- if (v != kwNoChange) {
- v /= (10 * 72);
- ++v;
- v *= (10 * 72);
- }
-
- SetDocSize(mDerefRoot(root)->frHndl, h, v);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment DrawDoc
- void DoGroup(FileRecHndl frHndl)
- {
- TreeObjHndl root, group, child;
- short gnum, cnum;
- Rect groupRct;
-
- NewDocumentUndo(frHndl);
-
- root = (*frHndl)->d.doc.root;
- for (gnum = 0; gnum < (*root)->numChildren; ++gnum)
- if (DoTreeObjMethod(GetChildHndl(root, gnum), GETSELECTMESSAGE, 0)) break;
-
- if (!(group = NewChild(GROUP_EDIT, root, gnum, GROUPOBJ, 0))) return;
-
- groupRct = GetSelectedArea(root);
- for (cnum = (*root)->numChildren - 1; cnum > gnum; --cnum) {
- if (DoTreeObjMethod(child = GetChildHndl(root, cnum), GETSELECTMESSAGE, 0)) {
- DoTreeObjMethodClipped(child, SETSELECTMESSAGE, SELECTOFF);
- MoveChild(GROUP_EDIT, root, cnum, group, 0);
- }
- }
-
- mDerefGroup(group)->group = groupRct;
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment DrawDoc
- void DoUngroup(FileRecHndl frHndl)
- {
- TreeObjHndl root, group;
- short gnum, cnum;
-
- NewDocumentUndo(frHndl);
-
- root = (*frHndl)->d.doc.root;
- for (gnum = (*root)->numChildren; gnum;) {
- if (DoTreeObjMethod(group = GetChildHndl(root, --gnum), GETSELECTMESSAGE, 0)) {
- if ((*group)->type == GROUPOBJ) {
- DoTreeSelect(group, SELECTOFF);
- for (cnum = (*group)->numChildren; cnum;) {
- MoveChild(UNGROUP_EDIT, group, --cnum, root, gnum + 1);
- DoTreeSelect(GetChildHndl(root, gnum + 1), SELECTON);
- }
- DisposeChild(UNGROUP_EDIT, root, gnum);
- }
- }
- }
- }
-
-
-
- /*****************************************************************************/
- /*****************************************************************************/
- /*****************************************************************************/
-
-
-
- #pragma segment DrawDoc
- void AddOrSizeObj(FileRecHndl frHndl, TreeObjHndl hndl, ClickInfo *click)
- {
- TreeObjHndl root, cobj, origHndl, oldHndl;
- WindowPtr window;
- short cnum, h, w, i;
- short adding, extSelect;
- LayerObj wlyr, wklyr, blyr;
- Rect oldRct, newRct, rct, extRct1, extRct2, extRct3;
- OSErr err;
- LayerDrawInfo drawInfo;
- Boolean tool, keepTool, newTool;
- Point curMouse, org, oldOrg;
-
- root = (*frHndl)->d.doc.root;
- window = (*frHndl)->fileState.window;
-
- tool = GetTool();
- keepTool = GetToolPersistence();
- adding = false;
- extSelect = false;
- newTool = false;
-
- if (!hndl) { /* If hndl == nil, then we are adding a new object. */
- adding = true;
- if (!tool)
- extSelect = true;
- else
- DoTreeSelect(root, SELECTOFF); /* Turn off all old selections. */
- click->offset.h = 0;
- click->offset.v = 0;
- click->grabber = 0;
- click->oldFlip = 0;
- click->newFlip = 0;
-
- i = (extSelect) ? EXTSELECTOBJ : ((RECTOBJ - 1) + tool);
- hndl = NewChild(NO_EDIT, root, cnum = 0, i, 0);
- /* The child gets created selected, ready to go, except that it's rect is
- ** empty. As the user drags the object out, this will change. */
-
- if (!keepTool) {
- tool = 0;
- newTool = true;
- } /* If the tool is a one-use tool, dispose it. */
-
- if (hndl) { /* If we succeeded at creating something... */
- rct.top = rct.bottom = click->localEvent.where.v;
- rct.left = rct.right = click->localEvent.where.h;
- DoTreeObjMethod(hndl, SETOBJRECTMESSAGE, (long)&rct);
- DoTreeObjMethod(hndl, SETSELECTMESSAGE, (SELECTOFF | SELECTNODRAW));
- }
- }
- else {
- NewDocumentUndo(frHndl);
- cnum = GetChildNum(hndl);
- if (ModifyChild(SIZE_EDIT, root, cnum, false)) return;
- /* Out of memory. I would handle this case better if it weren't just sample code.
- ** Given that there are no complex objects, we actually can't run out of memory
- ** due to this operation. However, there may someday be a pixmap type of object,
- ** whose memory hit could be substantial. */
- }
-
- drawInfo.root = root; /* The tree we are operating with. */
- drawInfo.cnum = cnum; /* The backmost object that is changing. */
-
- if (hndl) {
- NewLayer(&wlyr, nil, WindowLayerProc, window, 0, (long)&drawInfo);
- err = NewLayer(&wklyr, wlyr, WorkLayerProc, nil, 0, (long)&drawInfo);
- if (!err)
- err = NewLayer(&blyr, wklyr, BackLayerProc, nil, 0, (long)&drawInfo);
- if (err) DisposeThisAndBelowLayers(wklyr);
- /* The above code creates the necessary offscreen layers for the following editing.
- ** The window layer is bound to succeed at getting created, as it uses the window,
- ** instead of creating an offscreen GWorld. The work layer and back layer creations
- ** may fail. If they do, then we will only have a window layer. The window layer
- ** is smart enough to notice that it is alone, and if it is, then it will do the
- ** drawing directly to the window. Drawing directly to the window means that there
- ** will be a bunch of flicker, but what else is there to do when there is not enough
- ** ram? Drawing nothing is even worse. */
-
- DoTreeObjMethod(hndl, GETBBOXMESSAGE, (long)&rct);
- /* Bounding rect of the object getting created or resized. */
-
- if (click->grabber)
- InsetRect(&rct, -3, -3);
- InvalLayer(wlyr, rct, true);
- /* If getting resized, then the object has grabbers, and we have to make sure
- ** that the area getting redrawn is large enough for the grabbers. */
-
- origHndl = hndl;
- HandToHand((Handle *)&origHndl);
- while (StillDown()) {
- DoTreeObjMethod(hndl, GETOBJRECTMESSAGE, (long)&oldRct);
- oldHndl = hndl;
- HandToHand((Handle *)&oldHndl);
- if (DoTreeObjMethod(hndl, SIZEMESSAGE, (long)click)) { /* If new size... */
- DoTreeObjMethod(hndl, GETOBJRECTMESSAGE, (long)&newRct);
- if (!err) { /* If we have all offscreen layers... */
- DoTreeObjMethod(hndl, GETBBOXMESSAGE, (long)&rct);
- if (click->grabber)
- InsetRect(&rct, -3, -3);
- InvalLayer(wlyr, rct, true);
- UpdateLayer(wlyr);
- }
- else { /* If we only have wlyr... */
- SwapTreeObjData(hndl, oldHndl);
- if (!EqualTreeObjData(hndl, origHndl))
- DoTreeObjMethodClipped(hndl, DRAWMESSAGE, DRAWGHOST);
- SwapTreeObjData(hndl, oldHndl);
- if (!EqualTreeObjData(hndl, origHndl))
- DoTreeObjMethodClipped(hndl, DRAWMESSAGE, DRAWGHOST);
- }
- }
- DisposeHandle((Handle)oldHndl);
-
- GetMouse(&curMouse);
- GetContentRect(window, &rct);
- if (!PtInRect(curMouse, &rct)) {
-
- GetContentOrigin(window, &org);
- oldOrg = org;
- if (curMouse.h < rct.left) curMouse.h = rct.left - 36;
- if (curMouse.h > rct.right) curMouse.h = rct.right + 36;
- if (curMouse.v < rct.top) curMouse.v = rct.top - 36;
- if (curMouse.v > rct.bottom) curMouse.v = rct.bottom + 36;
-
- if (curMouse.h < rct.left) org.h += (curMouse.h - rct.left);
- if (curMouse.h > rct.right) org.h += (curMouse.h - rct.right);
- if (curMouse.v < rct.top) org.v += (curMouse.v - rct.top);
- if (curMouse.v > rct.bottom) org.v += (curMouse.v - rct.bottom);
-
- rct = GetDataArea(root);
- if (rct.right < curMouse.h)
- rct.right = curMouse.h;
- if (rct.bottom < curMouse.v)
- rct.bottom = curMouse.v;
- SetDataArea(root, rct.right, rct.bottom);
-
- SetContentOrigin(window, org.h, org.v);
- GetContentOrigin(window, &org);
-
- if (!err) {
- if ((org.h != oldOrg.h) || (org.v != oldOrg.v)) {
- DisposeThisAndBelowLayers(wlyr);
- DoImageDocument(frHndl);
- NewLayer(&wlyr, nil, WindowLayerProc, window, 0, (long)&drawInfo);
- err = NewLayer(&wklyr, wlyr, WorkLayerProc, nil, 0, (long)&drawInfo);
- if (!err)
- err = NewLayer(&blyr, wklyr, BackLayerProc, nil, 0, (long)&drawInfo);
- if (err) DisposeThisAndBelowLayers(wklyr);
- GetContentRect(window, &rct);
- InvalLayer(wlyr, rct, false); /* Force full redraw. */
- }
- }
- else
- DoImageDocument(frHndl);
- }
- else {
- rct = GetDataArea(root);
- SetDataArea(root, rct.right, rct.bottom);
- }
- }
- if (origHndl)
- DisposeHandle((Handle)origHndl);
-
- rct = GetDataArea(root);
- SetDataArea(root, rct.right, rct.bottom);
-
- DoTreeObjMethod(hndl, GETOBJRECTMESSAGE, (long)&rct);
- h = rct.bottom - rct.top;
- w = rct.right - rct.left;
- /* This is how big the final product is. It may now be unacceptably small.
- ** If we were adding a new object and it is too small, get rid of it entirely
- ** and use this to deselect the tool. If we were resizing an existing object,
- ** then force the object to be a minimum size. */
-
- if (((!h) || (!w)) || ((h < 8) && (w < 8))) { /* If smaller than minimum... */
- if (adding) {
- DisposeChild(NO_EDIT, root, 0); /* Don't create a new object that's too small. */
- hndl = nil; /* We didn't change anything, so flag this situation. */
- SetPaletteTool(0);
- newTool = false;
- }
- else {
- rct.bottom = rct.top + 8; /* Don't let them shrink it too small. */
- rct.right = rct.left + 8;
- DoTreeObjMethod(hndl, SETOBJRECTMESSAGE, (long)&rct); /* Make it minimum. */
- }
- DoImageDocument(frHndl);
- }
-
- if (hndl) { /* If we added or changed something... */
-
-
- if (adding) { /* If we are adding, we haven't handled posting the addition
- ** for undo. The reason for this is that the user may not
- ** actually add an object. If they just click and release,
- ** there is no object added. If we add the child with undo
- ** posting, and then remove it if the user doesn't grow it
- ** out, then we may lose some old undo info. If the user
- ** doesn't grow out the object, the operation is a NOP, and
- ** so old undo information shouldn't be lost. */
- if (extSelect) { /* We only created the object for extend-select purposes. */
- DoTreeObjMethod(hndl, GETBBOXMESSAGE, (long)&extRct1);
- for (i = (*root)->numChildren - 1; i; --i) {
- cobj = GetChildHndl(root, i);
- DoTreeObjMethod(cobj, GETBBOXMESSAGE, (long)&extRct2);
- SectRect(&extRct1, &extRct2, &extRct3);
- if (EqualRect(&extRct2, &extRct3))
- DoTreeObjMethodClipped(cobj, SETSELECTMESSAGE, SELECTTOGGLE);
- }
- DisposeChild(NO_EDIT, root, 0); /* We're done with it, so kill it. */
- }
- else {
- NewDocumentUndo(frHndl);
- hndl = CopyChild(NEW_EDIT, root, 0, root, 0, false);
- DisposeChild(NO_EDIT, root, 1);
- } /* We just created a posted copy of the child, just as if we had called
- ** NewChild. We also disposed of the temporary unposted copy of the child.
- ** The only problem is that objects entering the document get flagged as
- ** selected. This means that when we select the object, nothing happens
- ** on the screen because the object thinks it is already selected. */
- if (!extSelect)
- if (hndl)
- DoTreeObjMethod(hndl, SETSELECTMESSAGE, (SELECTOFF | SELECTNODRAW));
- /* Now the select grabbers can be drawn. */
- }
-
- rct = GetDataArea(root);
- SetDataArea(root, rct.right, rct.bottom);
-
- SetWindowDirty(window);
- if (err)
- DoImageDocument(frHndl);
- /* If we have only a wlyr, then we haven't really been generating a
- ** complete image. Redraw the document so that a full image is shown. */
-
- if (!extSelect)
- DoTreeObjMethodClipped(hndl, SETSELECTMESSAGE, SELECTON);
- /* Make sure the object is selected. */
- }
-
- DisposeThisAndBelowLayers(wlyr); /* Clean up. */
- }
-
- if (extSelect)
- DoImageDocument(frHndl);
- /* Since we have killed the extend-select object, erase it from the screen. */
-
- if (newTool)
- SetPaletteTool(tool);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment DrawDoc
- static OSErr WindowLayerProc(LayerObj theLayer, short message)
- {
- OSErr err;
- WindowPtr oldPort, window;
- Point contOrg;
- Rect contRct, thisUpdate;
- LayerDrawInfo drawInfo;
- RgnHandle oldClip, newClip;
-
- err = noErr;
-
- drawInfo = *(LayerDrawInfo *)(*theLayer)->layerData;
-
- switch (message) {
- case kLayerInit:
- err = DefaultLayerProc(theLayer, message);
- GetPort(&oldPort);
- SetPort(window = (*theLayer)->layerPort);
- GetContentOrigin(window, &contOrg);
- SetOrigin(contOrg.h, contOrg.v);
- GetContentRect(window, &contRct);
- (*theLayer)->dstRect = contRct;
- /* The above calculates the content rect (less tool palette and scrollbars).
- ** By setting the dstRect to this smaller rect, work layer and back layer
- ** will be created the size of dstRect, instead of the portRect of the
- ** window. This in turn will keep the GWLayers code from drawing over
- ** the tool palette and scrollbars. */
- SetPort(oldPort);
- break;
- case kLayerUpdate:
- BeginContent((*theLayer)->layerPort);
- if ((*theLayer)->belowLayer)
- DefaultLayerProc(theLayer, message);
- else { /* If offscreen layers couldn't be made, then do it by hand. */
- thisUpdate = UpdateUpdateRects(theLayer);
- oldClip = NewRgn();
- newClip = NewRgn();
- RectRgn(newClip, &thisUpdate);
- GetClip(oldClip);
- SetClip(newClip);
- EraseRect(&thisUpdate);
- DoTreeDraw(drawInfo.root, DRAWOBJ);
- DoTreeDraw(drawInfo.root, DRAWSELECT);
- SetClip(oldClip);
- DisposeRgn(oldClip);
- DisposeRgn(newClip);
- DrawPageGrid();
- }
- EndContent((*theLayer)->layerPort);
- break;
-
- default:
- err = DefaultLayerProc(theLayer, message);
- /* Default behavior for everything else. */
- break;
- }
-
- return(err);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment DrawDoc
- static OSErr WorkLayerProc(LayerObj theLayer, short message)
- {
- OSErr err;
- Rect rct;
- LayerDrawInfo drawInfo;
- short cnum;
- TreeObjHndl chndl;
-
- err = noErr;
-
- switch (message) {
- case kLayerInit:
- err = DefaultLayerProc(theLayer, message);
- break;
- case kLayerUpdate:
- SetLayerWorld(theLayer);
- drawInfo = *(LayerDrawInfo *)(*theLayer)->layerData;
- if ((*theLayer)->belowLayer)
- DefaultLayerProc(theLayer, message);
- else {
- rct = GetEffectiveDstRect(theLayer);
- EraseRect(&rct);
- drawInfo.cnum = (*drawInfo.root)->numChildren - 1;
- }
- for (cnum = drawInfo.cnum; cnum > -1; --cnum) {
- chndl = GetChildHndl(drawInfo.root, cnum);
- DoTreeDraw(chndl, DRAWOBJ);
- }
- for (cnum = drawInfo.cnum; cnum > -1; --cnum) {
- chndl = GetChildHndl(drawInfo.root, cnum);
- DoTreeDraw(chndl, DRAWSELECT);
- }
- DrawPageGrid();
- ResetLayerWorld(theLayer);
- break;
- default:
- err = DefaultLayerProc(theLayer, message);
- /* Default behavior for everything else. */
- break;
- }
-
- return(err);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment DrawDoc
- static OSErr BackLayerProc(LayerObj theLayer, short message)
- {
- OSErr err;
- Rect rct;
- LayerDrawInfo drawInfo;
- short cnum;
- TreeObjHndl chndl;
-
- err = noErr;
-
- switch (message) {
- case kLayerInit:
- err = DefaultLayerProc(theLayer, message);
- if (!err) {
- SetLayerWorld(theLayer);
- rct = GetEffectiveDstRect(theLayer);
- EraseRect(&rct);
- drawInfo = *(LayerDrawInfo *)(*theLayer)->layerData;
- for (cnum = (*drawInfo.root)->numChildren - 1; cnum > drawInfo.cnum; --cnum) {
- chndl = GetChildHndl(drawInfo.root, cnum);
- DoTreeDraw(chndl, DRAWOBJ);
- }
- for (cnum = (*drawInfo.root)->numChildren - 1; cnum > drawInfo.cnum; --cnum) {
- chndl = GetChildHndl(drawInfo.root, cnum);
- DoTreeDraw(chndl, DRAWSELECT);
- }
- ResetLayerWorld(theLayer);
- }
- break;
- default:
- err = DefaultLayerProc(theLayer, message);
- /* Default behavior for everything else. */
- break;
- }
-
- return(err);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment DrawDoc
- void DrawPageGrid(void)
- {
- WindowPtr curPort;
- short x1, x2, y1, y2, i;
-
- if (!gPrintPage) {
- GetPort(&curPort);
- PenPat((ConstPatternParam)&qd.gray);
- x1 = curPort->portRect.left / (7 * 72);
- x1 *= (7 * 72);
- x2 = curPort->portRect.right / (7 * 72);
- x2 *= (7 * 72);
- y1 = curPort->portRect.top / (10 * 72);
- y1 *= (10 * 72);
- y2 = curPort->portRect.bottom / (10 * 72);
- y2 *= (10 * 72);
- for (i = x1; i <= x2; i += (7 * 72)) {
- MoveTo(i - 1, -1);
- Line (0, 16383);
- }
- for (i = y1; i <= y2; i += (10 * 72)) {
- MoveTo(-1, i - 1);
- Line (16383, 0);
- }
- PenNormal();
- }
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment DrawDoc
- void SlideSelection(FileRecHndl frHndl, ClickInfo *click)
- {
- LayerDrawInfo drawInfo;
- WindowPtr window;
- LayerObj wlyr, wklyr, blyr;
- Point lastMouse, curMouse;
- short cnum, dh, dv;
- TreeObjHndl root, chndl;
- Rect newLoc, selectRct, rct;
- Point oldOrg, org;
- Boolean changed, autoScroll, dragDrop;
- OSErr err;
- EventRecord event;
- long as, autoScrollTick;
-
- autoScrollTick = 0;
-
- changed = false;
- NewDocumentUndo(frHndl);
-
- root = (*frHndl)->d.doc.root;
- for (cnum = (*root)->numChildren;;) {
- if (DoTreeObjMethod(GetChildHndl(root, --cnum), GETSELECTMESSAGE, 0)) break;
- if (!cnum) return;
- }
-
- drawInfo.root = root;
- drawInfo.cnum = cnum;
- window = (*frHndl)->fileState.window;
-
- NewLayer(&wlyr, nil, WindowLayerProc, window, 0, (long)&drawInfo);
- err = NewLayer(&wklyr, wlyr, WorkLayerProc, nil, 0, (long)&drawInfo);
- if (!err) err = NewLayer(&blyr, wklyr, BackLayerProc, nil, 0, (long)&drawInfo);
-
- selectRct = GetSelectedArea(root);
- InsetRect(&selectRct, -3, -3);
- InvalLayer(wlyr, selectRct, false);
- lastMouse = click->localEvent.where;
-
- autoScroll = dragDrop = false;
- while (StillDown()) {
- GetMouse(&curMouse);
- GetContentRect(window, &rct);
- rct.top += 16;
- rct.left += 16;
- as = autoScroll;
- autoScroll = !PtInRect(curMouse, &rct);
- if (autoScroll) {
- if (!autoScrollTick) autoScrollTick = TickCount();
- dh = lastMouse.h - curMouse.h;
- if (dh < 0) dh = -dh;
- dv = lastMouse.v - curMouse.v;
- if (dv < 0) dv = -dv;
- if ((dh + dv > 6) && (!as)) autoScrollTick = TickCount();
- if (autoScrollTick + 15 > TickCount()) autoScroll = false;
- }
- if (DragDropAvailable()) {
- InsetRect(&rct, -16, -16);
- dragDrop = !PtInRect(curMouse, &rct);
- InsetRect(&rct, 16, 16);
- }
-
- if ((dragDrop) || (click->localEvent.modifiers & optionKey)) {
- if (changed) RevertEdit(root, true);
- event = click->localEvent;
- LocalToGlobal(&event.where);
- if (DoDrag(frHndl, &event) != paramErr) break;
- }
-
- click->offset.h = (curMouse.h - lastMouse.h);
- click->offset.v = (curMouse.v - lastMouse.v);
- click->message = CLICKDRAG;
-
- if ((autoScroll) || (click->offset.h) || (click->offset.v)) {
- changed = true;
- if ((click->offset.h) || (click->offset.v)) {
- for (cnum = 0; cnum < (*root)->numChildren; ++cnum) {
- chndl = GetChildHndl(root, cnum);
- if (mDerefCommon(chndl)->selected) {
- ModifyChild(MOVE_EDIT, root, cnum, true);
- DoFTreeMethod(chndl, CLICKMESSAGE, (long)click);
- DoTreeObjMethod(chndl, GETBBOXMESSAGE, (long)&newLoc);
- InsetRect(&newLoc, -3, -3);
- InvalLayer(wlyr, newLoc, true);
- }
- }
- UpdateLayer(wlyr);
- }
- lastMouse = curMouse;
-
- if (autoScroll) {
- GetContentOrigin(window, &org);
- oldOrg = org;
- if (curMouse.h < rct.left) curMouse.h = rct.left - 36;
- if (curMouse.h > rct.right) curMouse.h = rct.right + 36;
- if (curMouse.v < rct.top) curMouse.v = rct.top - 36;
- if (curMouse.v > rct.bottom) curMouse.v = rct.bottom + 36;
-
- if (curMouse.h < rct.left) org.h += (curMouse.h - rct.left);
- if (curMouse.h > rct.right) org.h += (curMouse.h - rct.right);
- if (curMouse.v < rct.top) org.v += (curMouse.v - rct.top);
- if (curMouse.v > rct.bottom) org.v += (curMouse.v - rct.bottom);
-
- rct = GetDataArea(root);
- if (rct.right < curMouse.h)
- rct.right = curMouse.h;
- if (rct.bottom < curMouse.v)
- rct.bottom = curMouse.v;
- SetDataArea(root, rct.right, rct.bottom);
-
- SetContentOrigin(window, org.h, org.v);
- GetContentOrigin(window, &org);
- if ((org.h != oldOrg.h) || (org.v != oldOrg.v)) {
- DisposeThisAndBelowLayers(wlyr);
- DoImageDocument(frHndl);
- NewLayer(&wlyr, nil, WindowLayerProc, window, 0, (long)&drawInfo);
- err = NewLayer(&wklyr, wlyr, WorkLayerProc, nil, 0, (long)&drawInfo);
- if (!err) err = NewLayer(&blyr, wklyr, BackLayerProc, nil, 0, (long)&drawInfo);
- if (err) DisposeThisAndBelowLayers(wklyr);
- GetContentRect(window, &rct);
- InvalLayer(wlyr, rct, false); /* Force full redraw. */
- }
- }
- else {
- rct = GetDataArea(root);
- SetDataArea(root, rct.right, rct.bottom);
- }
- }
- }
-
- rct = GetDataArea(root);
- SetDataArea(root, rct.right, rct.bottom);
-
- if (changed)
- SetWindowDirty(window);
-
- DisposeThisAndBelowLayers(wlyr);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment DrawDoc
- void NewDocumentUndo(FileRecHndl frHndl)
- {
- NewUndo((*frHndl)->d.doc.root);
- }
-
-
-
-