|
|
1.1 ! root 1: ! 2: /* ! 3: GraphApp.m ! 4: ! 5: GraphApp is the delegate of the Application object. It deals with opening ! 6: new documents as initiated by the menu commands or messages from the ! 7: Workspace Manager. ! 8: ! 9: You may freely copy, distribute, and reuse the code in this example. ! 10: NeXT disclaims any warranty of any kind, expressed or implied, as to its ! 11: fitness for any particular use. ! 12: */ ! 13: ! 14: #import "Graph.h" ! 15: ! 16: static Window *findDocWindow(const char *name); ! 17: ! 18: @implementation GraphApp ! 19: ! 20: - appDidInit:sender { ! 21: /* ! 22: * If we weren't asked to open any documents at launch time, then we were ! 23: * launched by double clicking on the application instead of a document. ! 24: * In this case, we open up a new document for the user. ! 25: */ ! 26: if (!NXGetDefaultValue([NXApp appName], "NXOpen") && ! 27: !NXGetDefaultValue([NXApp appName], "NXOpenTemp") && ! 28: !NXGetDefaultValue([NXApp appName], "NXServiceLaunch")) ! 29: [self new3D:self]; ! 30: return self; ! 31: } ! 32: ! 33: /* ! 34: * Called as we are quitting. Gives the user a change to save unsaved work. ! 35: * The Draw example has a more complete implementation of this, since it does ! 36: * not give the user the "Cancel" option when logging out or powering off. ! 37: */ ! 38: - appWillTerminate:sender { ! 39: int response; ! 40: List *windowList = [NXApp windowList]; ! 41: int count; ! 42: Window *window; ! 43: BOOL dirtyDocs = NO; ! 44: id document; ! 45: NXStringTable *stringTab; ! 46: ! 47: count = [windowList count]; ! 48: while (count--) { ! 49: if ([[windowList objectAt:count] isDocEdited]) { ! 50: dirtyDocs = YES; ! 51: break; ! 52: } ! 53: } ! 54: if (dirtyDocs) { ! 55: stringTab = [self stringTable]; ! 56: response = NXRunAlertPanel([stringTab valueForStringKey:"quit alert title"], ! 57: [stringTab valueForStringKey:"quit alert message"], ! 58: [stringTab valueForStringKey:"review button"], ! 59: [stringTab valueForStringKey:"quit button"], ! 60: [stringTab valueForStringKey:"cancel button"]); ! 61: if (response == NX_ALERTALTERNATE) { ! 62: return self; ! 63: } else if (response == NX_ALERTOTHER) { ! 64: return nil; ! 65: } else { ! 66: count = [windowList count]; ! 67: while (count--) { ! 68: window = [windowList objectAt:count]; ! 69: document = [window delegate]; ! 70: if ([document isKindOfClassNamed:"GraphDoc"] || [document isKindOfClassNamed:"Graph3DDoc"]) { ! 71: if (![document windowWillClose:sender]) { ! 72: return nil; ! 73: } ! 74: } ! 75: } ! 76: return self; ! 77: } ! 78: } else { ! 79: return self; ! 80: } ! 81: } ! 82: ! 83: /* ! 84: * This method is performed whenever a user double-clicks on an icon in ! 85: * the Workspace Manager representing a Draw program document. If the file ! 86: * is already open, it just orders its window to the front; else, it opens ! 87: * a new graph document from the file. ! 88: */ ! 89: - (int)app:sender openFile:(const char *)path type:(const char *)type { ! 90: BOOL success = NO; ! 91: Window *win; ! 92: NXStringTable *stringTab; ! 93: ! 94: if (type) { ! 95: if (win = findDocWindow(path)) { ! 96: [win makeKeyAndOrderFront:self]; ! 97: success = YES; ! 98: } else if (!strcmp(type, "xygraph")) { ! 99: if ([[GraphDoc allocFromZone:[self zone]] initFromFile:path]) ! 100: success = YES; ! 101: } else if (!strcmp(type, "xyzgraph")) { ! 102: if ([[Graph3DDoc allocFromZone:[self zone]] initFromFile:path]) ! 103: success = YES; ! 104: } ! 105: } ! 106: if (!success) { ! 107: stringTab = [self stringTable]; ! 108: NXRunAlertPanel( ! 109: [stringTab valueForStringKey:"open alert title"], ! 110: [stringTab valueForStringKey:"open alert message"], ! 111: [stringTab valueForStringKey:"ok button"], ! 112: NULL, NULL, path); ! 113: } ! 114: return success; ! 115: } ! 116: ! 117: /* This says we can accept any number of app:openFile:type: messages. */ ! 118: - (BOOL)appAcceptsAnotherFile:sender { ! 119: return YES; ! 120: } ! 121: ! 122: /* action method, called when the user chooses open in the menu */ ! 123: - open:sender { ! 124: const char *const *files; ! 125: static const char *const fileType[3] = {"xygraph", "xyzgraph", NULL}; ! 126: OpenPanel *openPanel; ! 127: char fullName[MAXPATHLEN]; ! 128: const char *suffix; ! 129: ! 130: /* ! 131: * Declare that the user can select multiple files to be opened in the ! 132: * Open Panel. All apps should do this, since its so easy. ! 133: */ ! 134: openPanel = [[OpenPanel new] allowMultipleFiles:YES]; ! 135: ! 136: /* run the open panel, filtering for out types of our documents */ ! 137: if ([openPanel runModalForTypes:fileType]) { ! 138: ! 139: /* open all the files returned by the open panel */ ! 140: files = [openPanel filenames]; ! 141: for (files = [openPanel filenames]; files && *files; files++) { ! 142: strcpy(fullName, [openPanel directory]); ! 143: strcat(fullName, "/"); ! 144: strcat(fullName, *files); ! 145: suffix = strrchr(*files, '.'); ! 146: if (suffix) ! 147: [self app:NXApp openFile:fullName type:++suffix]; ! 148: } ! 149: } ! 150: return self; ! 151: } ! 152: ! 153: /* action method, called when the user chooses "New 2D" in the menu */ ! 154: - new2D:sender { ! 155: [[GraphDoc allocFromZone:[self zone]] init]; ! 156: return self; ! 157: } ! 158: ! 159: /* action method, called when the user chooses "New 3D" in the menu */ ! 160: - new3D:sender { ! 161: [[Graph3DDoc allocFromZone:[self zone]] init]; ! 162: return self; ! 163: } ! 164: ! 165: /* ! 166: * Loads the info panel from its separate nib section. We set the version ! 167: * number in the info panel on the fly, which keeps it up to date ! 168: * automatically. The VERS_NUM variable is created in the vers.c file, which ! 169: * is created by the vers_string shell command as part of the build process. ! 170: */ ! 171: - showInfoPanel:sender { ! 172: if (!infoPanel) { ! 173: extern char VERS_NUM[]; ! 174: [NXApp loadNibSection:"Info.nib" owner:self withNames:NO]; ! 175: if (strlen(VERS_NUM) > 0) { ! 176: char versionBuffer[100]; ! 177: sprintf (versionBuffer, [[self stringTable] valueForStringKey:"version"], VERS_NUM); ! 178: [versString setStringValue:versionBuffer]; ! 179: } else { ! 180: [versString setStringValue:""]; ! 181: } ! 182: } ! 183: [infoPanel makeKeyAndOrderFront:self]; ! 184: return self; ! 185: } ! 186: ! 187: /* Loads the help panel from its separate nib section. */ ! 188: - showHelpPanel:sender { ! 189: if (!helpPanel) ! 190: [NXApp loadNibSection:"Help.nib" owner:self withNames:NO]; ! 191: [helpPanel makeKeyAndOrderFront:self]; ! 192: return self; ! 193: } ! 194: ! 195: /* Loads the 3D panel from its separate nib section. */ ! 196: - showThreeDPanel:sender { ! 197: if (!threeDPanel) { ! 198: [NXApp loadNibSection:"ThreeDPanel.nib" owner:self withNames:NO]; ! 199: /* ! 200: * USE THIS METHOD CAREFULLY. It should only be used for panels that ! 201: * never or rarely need to become key. Usually this is because they ! 202: * have no areas for typing (as in this case), or else the user very ! 203: * rarely types in them (e.g., the Font panel). ! 204: */ ! 205: [threeDPanel setBecomeKeyOnlyIfNeeded:YES]; ! 206: } ! 207: [threeDPanel orderFront:self]; ! 208: return self; ! 209: } ! 210: ! 211: /* Returns the 3D Panel */ ! 212: - (ThreeDPanel *)threeDPanel { ! 213: return threeDPanel; ! 214: } ! 215: ! 216: /* Returns the string table */ ! 217: - (NXStringTable *)stringTable { ! 218: char path[MAXPATHLEN+1]; ! 219: ! 220: if (!stringTable && [[NXBundle mainBundle] getPath:path forResource:"Graph" ofType:"strings"]) { ! 221: stringTable = [[NXStringTable allocFromZone:[self zone]] init]; ! 222: [stringTable readFromFile:path]; ! 223: } ! 224: return stringTable; ! 225: } ! 226: ! 227: /* ! 228: * Returns the window for a given filename, if open. We go through the window ! 229: * list looking for an window with the given file open. Since there are many ! 230: * more windows in the window list than our document windows (panels, NXImage ! 231: * caches, the app icon,...), we check the delegate to know if its a document ! 232: * window. We use realpath() to make sure we aren't fooled by symbolic links ! 233: * that lead to a file already opened via a different path. ! 234: */ ! 235: static Window *findDocWindow(const char *name) { ! 236: int count; ! 237: id document; ! 238: Window *window; ! 239: List *windowList; ! 240: const char *realPath; ! 241: const char *otherRealPath; ! 242: char realPathBuf[MAXPATHLEN+1]; ! 243: ! 244: windowList = [NXApp windowList]; ! 245: count = [windowList count]; ! 246: realPath = realpath(name, realPathBuf) ? realPathBuf : name; ! 247: while (count--) { ! 248: window = [windowList objectAt:count]; ! 249: document = [window delegate]; ! 250: if (document && ([document isKindOf:[GraphDoc class]] ! 251: || [document isKindOf:[Graph3DDoc class]])) { ! 252: otherRealPath = [document realFilename]; ! 253: if (otherRealPath && !strcmp(otherRealPath, realPath)) ! 254: return window; ! 255: } ! 256: } ! 257: return nil; ! 258: } ! 259: ! 260: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.