This is ImportApp.m in view mode; [Download] [Up]
/*
* (a) (C) 1990 by Adobe Systems Incorporated. All rights reserved.
*
* (b) If this Sample Code is distributed as part of the Display PostScript
* System Software Development Kit from Adobe Systems Incorporated,
* then this copy is designated as Development Software and its use is
* subject to the terms of the License Agreement attached to such Kit.
*
* (c) If this Sample Code is distributed independently, then the following
* terms apply:
*
* (d) This file may be freely copied and redistributed as long as:
* 1) Parts (a), (d), (e) and (f) continue to be included in the file,
* 2) If the file has been modified in any way, a notice of such
* modification is conspicuously indicated.
*
* (e) PostScript, Display PostScript, and Adobe are registered trademarks of
* Adobe Systems Incorporated.
*
* (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO
* CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED
* AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED.
* ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY
* OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO
* WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY)
* WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY
* DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT
* OF THIRD PARTY RIGHTS.
*/
/*
* ImportApp.m
*
* This class performs some of the global functions necessary to
* manage the application.
*
* Several application wide resources are retained as
* instance variables. Examples are the hitPoint and
* upathBuffer buffers and the hitSetting value.
*
* Version: 2.0
* Author: Ken Fromm
*/
#import "ImportApp.h"
#import "Document.h"
#import "DrawingView.h"
#import "ImportPanel.h"
#import "Preferences.h"
#import "SaveAsPanel.h"
#import "DrawingViewWraps.h"
#import <appkit/NXCursor.h>
#import <appkit/NXImage.h>
#import <appkit/Matrix.h>
#import <appkit/Menu.h>
#import <appkit/MenuCell.h>
#import <appkit/defaults.h>
#import <appkit/nextstd.h>
#import <objc/List.h>
#import <sys/param.h>
#import <string.h>
struct cursorRecord {
char *name;
NXPoint hotspot;
};
const static struct cursorRecord cursors[] = {
{NULL, 0.0, 0.0}, /* Select */
{"cursorZoomUp.tiff", 8.0, 8.0},
{"cursorRotate1.tiff", 8.0, 8.0},
{"cursorZoomDown.tiff", 8.0, 8.0},
{"cursorRotate2.tiff", 6.0, 4.0},
{"cursorImport.tiff", 2.0, 1.0},
{NULL, 0.0, 0.0} /* Place */
};
char ControlFont[ ] = "ControlPointsFont";
@implementation ImportApp
/*
* Sets the updateAction for every menu item which sends to the
* First Responder (i.e. their target is nil). When autoupdate is on,
* every event will be followed by an update of each of the menu items
* which is visible. This keep all unavailable menu items dimmed out
* so that the user knows what options are available at any given time.
* Returns the activate menu if is found in this menu.
*/
static void initMenu(id menu)
{
int count;
id matrix, cell;
id matrixTarget, cellTarget;
matrix = [menu itemList];
matrixTarget = [matrix target];
count = [matrix cellCount];
while (count--)
{
cell = [matrix cellAt:count :0];
cellTarget = [cell target];
if (!matrixTarget && !cellTarget)
[cell setUpdateAction:@selector(menuItemUpdate:) forMenu:menu];
else if ([cell hasSubmenu])
initMenu(cellTarget);
}
}
/*
* Checks to see if the passed window's delegate is a Document
* instance. If it is, it returns that document, otherwise it returns nil.
*/
static id documentInWindow(id window)
{
id document = [window delegate];
return [document isKindOf:[Document class]] ? document : nil;
}
/*
* Searches the window list looking for a Document with the specified
* name. Returns the window containing the document if found.
* If name == NULL then the first document found is returned.
*/
static id findDocument(const char *name)
{
int count;
id document, window, windowList;
windowList = [NXApp windowList];
count = [windowList count];
while (count--)
{
window = [windowList objectAt:count];
document = documentInWindow(window);
if (document && (!name || !strcmp([document filename], name)))
return window;
}
return nil;
}
/*
* Opens a file with the given name in the specified directory.
* If we already have that file open, it is ordered front.
* Returns the document if successful, nil otherwise.
*/
static id openFile(const char *directory, const char *name, BOOL display)
{
id window;
char buffer[MAXPATHLEN+1], path[MAXPATHLEN+1];
if (name && *name)
{
if (!directory)
{
directory = ".";
}
else if (*directory != '/')
{
strcpy(buffer, "./");
strcat(buffer, directory);
directory = buffer;
}
if (!chdir(directory) && getwd(path))
{
strcat(path, "/");
strcat(path, name);
window = findDocument(path);
if (window)
{
if (display)
[window makeKeyAndOrderFront:window];
return [window delegate];
}
else
return [Document newFromFile:path];
}
else
NXRunAlertPanel("Open", "Invalid path: %s", "OK", NULL, NULL, directory);
}
return nil;
}
/*
* Allocate a buffer for use by any drawing view to send
* data to the PostScript server.
*
* Allocate this buffer for use by any drawing view to
* use as the hitdetection userpath. Initialize the description
* since most of the components will remain the same.
*/
+ new
{
int i;
self = [super new];
[self setAutoupdate:YES];
PSWDefineFont(ControlFont);
hitSetting = 4.0;
contextFlag = imagingFlag = YES;
NX_MALLOC(upathBuffer.pts, float, PTS_BUFFER);
NX_MALLOC(upathBuffer.ops, char, OPS_BUFFER);
NX_MALLOC(hitPoint.pts, float, PTS_HITPOINT);
NX_MALLOC(hitPoint.ops, char, OPS_HITPOINT);
for (i = 0; i < PTS_HITPOINT; i++)
hitPoint.pts[i] = 0;
hitPoint.num_pts = i;
i = 0;
hitPoint.ops[i++] = dps_setbbox;
hitPoint.ops[i++] = dps_moveto;
hitPoint.ops[i++] = dps_rlineto;
hitPoint.ops[i++] = dps_rlineto;
hitPoint.ops[i++] = dps_rlineto;
hitPoint.ops[i++] = dps_closepath;
hitPoint.num_ops = i;
return self;
}
/* Initializes the defaults. */
+ initialize
{
const NXDefaultsVector EpsfDefaults = {
{ "Quit", NULL },
{ NULL, NULL }
};
NXRegisterDefaults("Epsf", EpsfDefaults);
return self;
}
- free
{
if (upathBuffer.pts)
NX_FREE(upathBuffer.pts);
if (upathBuffer.ops)
NX_FREE(upathBuffer.ops);
if (hitPoint.pts)
NX_FREE(hitPoint.pts);
if (hitPoint.ops)
NX_FREE(hitPoint.ops);
return [super free];
}
- setToolPanel:anObject
{
toolpanelId = anObject;
return self;
}
- setToolMatrix:anObject
{
toolmatrixId = anObject;
return self;
}
- setSaveAccessory:anObject
{
[[SaveAsPanel new] setAccessoryView:anObject];
return self;
}
- setImportAccessory:anObject
{
[[ImportPanel new] setImportAccessory:anObject];
return self;
}
/* Calculate the position for the next window. */
- getPosition:(NXPoint *)location forSize:(NXSize *)winSize
{
int col, row;
col = (numWindows/NUMPERCOL) % NUMCOLUMNS;
row = numWindows % NUMPERCOL;
location->x = WINDOWSTARTX + (col * OFFSETLEFT) + (row * OFFSETX);
location->y = WINDOWSTARTY - winSize->height - (row * OFFSETY);
numWindows++;
return self;
}
/*
* Teaching aids
*/
- setContextFlag:sender
{
if (!contextFlag)
[[sender selectedCell] setTitle:"Separate Context On"];
else
[[sender selectedCell] setTitle:"Separate Context Off"];
contextFlag = !contextFlag;
return self;
}
- (BOOL) contextFlag
{
return contextFlag;
}
- setShowEpsfFlag:sender
{
if (!showEpsfFlag)
[[sender selectedCell] setTitle:"Show Epsf On"];
else
[[sender selectedCell] setTitle:"Show Epsf Off"];
showEpsfFlag = !showEpsfFlag;
return self;
}
- (BOOL) showEpsfFlag
{
return showEpsfFlag;
}
- setShowBufferFlag:sender
{
if (!showBufferFlag)
[[sender selectedCell] setTitle:"Show Buffer On"];
else
[[sender selectedCell] setTitle:"Show Buffer Off"];
showBufferFlag = !showBufferFlag;
if (showBufferFlag)
[[[self currentDocument] drawingView] showBuffer:self];
else
[[[self currentDocument] drawingView] hideBuffer:self];
return self;
}
- (BOOL) showBufferFlag
{
return showBufferFlag;
}
/* Change the menu title and toggle the trace boolean. */
- setTracingFlag:sender
{
if (!tracingFlag)
[[sender selectedCell] setTitle:"Trace On"];
else
[[sender selectedCell] setTitle:"Trace Off"];
tracingFlag = !tracingFlag;
return self;
}
- (BOOL) tracingFlag
{
return tracingFlag;
}
- setImagingFlag:sender
{
imagingFlag = [sender state];
[[[self currentDocument] drawingView] display];
return self;
}
- (BOOL) imagingFlag
{
return imagingFlag;
}
- setHitSetting:sender
{
hitSetting = [sender floatValue];
return self;
}
- (float) hitSetting
{
return hitSetting;
}
- (UPath *) hitPoint;
{
return &hitPoint;
}
- (UPath *) upathBuffer;
{
return &upathBuffer;
}
- currentDocument
{
return documentInWindow(mainWindow);
}
- (const char *)currentDirectory
{
const char *retval = [[self currentDocument] directory];
if (!retval || !*retval)
retval = [[OpenPanel new] directory];
return retval;
}
/* Open a new document. */
- new:sender
{
[Document new];
return self;
}
/*
* Called by pressing Open... in the Window menu.
*/
- open:sender
{
id openpanel;
char path[MAXPATHLEN+1];
const char *directory;
const char *const *files;
static const char *const filetype[2] = {"adb", NULL};
directory = NULL;
directory = [[self currentDocument] directory];
if (!directory)
if (getwd(path))
directory = path;
openpanel = [[ImportPanel new] setOpen];
if ([openpanel runModalForDirectory:directory file:NULL types:filetype])
{
files = [openpanel filenames];
directory = [openpanel directory];
while (files && *files)
{
openFile(directory, *files, YES);
files++;
}
}
return self;
}
/*
* Sends a windowWillClose message to all open Documents
* before the program terminates.
*/
- terminate:sender
{
int count;
id window, document;
count = [windowList count];
while (count--)
{
window = [windowList objectAt:count];
document = documentInWindow(window);
if (document)
{
if ([document windowWillClose:window])
[window close];
else
return self;
}
}
return [super terminate:sender];
}
- setTool:sender
{
[self setOperation:[sender selectedTag]];
return self;
}
- resourcePanel
{
if (!resourcePanel)
[NXApp loadNibSection:"ResourcePanel.nib" owner:self withNames:NO];
return resourcePanel;
}
/*
* Return the cursor for the appropriate index. Create
* one if non-existent.
*/
- getCursor:(int) index
{
id imageId;
if (!cursorIds[index])
{
if (cursors[index].name)
{
imageId = [NXImage newFromSection:cursors[index].name];
cursorIds[index]= [NXCursor newFromImage:imageId];
[cursorIds[index] setHotSpot:&cursors[index].hotspot];
}
}
return cursorIds[index];
}
- cursor
{
id imageId;
if (!cursorIds[operation])
{
if (cursors[operation].name)
{
imageId = [NXImage newFromSection:cursors[operation].name];
cursorIds[operation]= [NXCursor newFromImage:imageId];
[cursorIds[operation] setHotSpot:&cursors[operation].hotspot];
}
else
cursorIds[operation] = NXArrow;
}
return cursorIds[operation];
}
- (int) operation
{
return operation;
}
- setOperation:(int) newOperation
{
id currentDoc;
if (newOperation < OP_FIRST || newOperation > OP_LAST)
newOperation = OP_SELECT;
operation = newOperation;
currentDoc = [self currentDocument];
[[currentDoc window] invalidateCursorRectsForView:[currentDoc drawingView]];
return self;
}
- clearOperation
{
[self setOperation:OP_SELECT];
[toolmatrixId selectCellWithTag:OP_SELECT];
return self;
}
/*
* Application object delegate methods.
* Messages that would be sent to the delegate are sent to the Application
* object or a subclass if no delagate exists.
*/
/*
* Initialize the menus.
* Sets the tool palette so it never becomes the key window.
* Check for files to open specified on the command line.
* If there are no open documents, then open a blank one.
*/
- appDidInit:sender
{
id docId;
int i;
char buffer[MAXPATHLEN+1];
char *directory, *name, *ext;
[toolpanelId removeFromEventMask:NX_KEYDOWNMASK|NX_KEYUPMASK];
[toolpanelId orderFront:self];
initMenu([NXApp mainMenu]);
if (NXArgc > 1)
{
for (i = 1; i < NXArgc; i++)
{
strcpy(buffer, NXArgv[i]);
ext = strrchr(buffer, '.');
if (!ext || strcmp(ext, ".adb"))
strcat(buffer, ".adb");
name = strrchr(buffer, '/');
if (name)
{
*name++ = '\0';
directory = buffer;
}
else
{
name = buffer;
directory = NULL;
}
docId = openFile(directory, name, YES);
}
}
/* if none opened, open one */
if (!findDocument(NULL))
[self new:self];
if (NXGetDefaultValue([self appName], "Quit"))
{
[self activateSelf:YES];
NXPing();
[self terminate:self];
}
return self;
}
/*
* This method is performed whenever a user double-clicks on an icon
* in the Workspace Manager representing an Epsf document.
*/
- (int)appOpenFile:(const char *)path type:(const char *)type
{
char *name;
char directory[MAXPATHLEN+1];
if (type && !strcmp(type, "adb"))
{
strcpy(directory, path);
name = strrchr(directory, '/');
if (name)
{
*name++ = '\0';
return (openFile(directory, name, YES) ? YES : NO);
}
}
return NO;
}
/* We accept any number of appOpenFile:type: messages. */
- (BOOL)appAcceptsAnotherFile:sender
{
return YES;
}
/* Automatic update methods */
/*
* Method called by all menu items which send their actions to the
* First Responder. First, if the object which would respond were the
* action sent down the responder chain also responds to the message
* validateCommand:, then it is sent validateCommand: to determine
* whether that command is valid now, otherwise, if there is a responder
* to the message, then it is assumed that the item is valid.
* The method returns YES if the cell has changed its appearance (so that
* the caller (a Menu) knows to redraw it).
*/
- (BOOL)menuItemUpdate:menuCell
{
SEL action;
id responder, target;
BOOL enable;
target = [menuCell target];
enable = [menuCell isEnabled];
if (!target)
{
action = [menuCell action];
responder = [self calcTargetForAction:action];
if ([responder respondsTo:@selector(validateCommand:)])
enable = [responder validateCommand:menuCell];
else
enable = responder ? YES : NO;
}
if ([menuCell isEnabled] != enable)
{
[menuCell setEnabled:enable];
return YES;
}
else
return NO;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.