This is InformerWindow.m in view mode; [Download] [Up]
// InformerWindow.m // // Purpose : // Handles the "document" windows, one instance per window. // // Structure : // InformerWindow is a subclass of Object. It is the delegate of // its "document" window. It is also the owner of InformerWindow.nib. // It is the delegate of the Browser. // // // History : // 9.20.1992 : Created by Max Tardiveau #import "InformerWindow.h" @implementation InformerWindow ///////////////////////////////////////////////// // - init { NXRect tmpRect; //int tmpInt; [super init]; [NXApp loadNibSection:"InformerWindow.nib" owner:self]; [myInspectorView setVertScrollerRequired:NO]; [myInspectorView getBounds:&tmpRect]; [myInspectorView setDocCursor:NXArrow]; myEmptyView = [[EmptyView new] initFrame:&tmpRect]; [myInspectorView setDocView:myEmptyView]; [myBrowser setCellClass:[InformerCell class]]; [myBrowser useScrollButtons:YES]; [myBrowser loadColumnZero]; [myWindow makeKeyAndOrderFront:self]; updatePeriod = 0; [updateText setEnabled:NO]; return self; } ///////////////////////////////////////////////// // Sets our dispatcher - setDispatcher:sender { myDispatcher = sender; return self; } ///////////////////////////////////////////////// // Target method for the Update TextItem static void updateFunc(DPSTimedEntry teNumber, double now, char *userData) { id theCell; id theObject; theCell = (id)userData; if ((theObject = [theCell updater]) != NIL) [theObject doUpdateForCell:theCell]; } ///////////////////////////////////////////////// // Target method for the Update TextItem and Scroller - setUpdate:sender { id CurrentCell; updatePeriod = [sender intValue]; [updateScroller setIntValue:updatePeriod]; [updateText setIntValue:updatePeriod]; if (updatePeriod <= 1) [updateTextSeconds setStringValue:"second"]; else [updateTextSeconds setStringValue:"seconds"]; if (myTimedEntry) { DPSRemoveTimedEntry(myTimedEntry); myTimedEntry = 0; } CurrentCell = [[myBrowser matrixInColumn:[myBrowser selectedColumn]] selectedCell]; if (updatePeriod && CurrentCell) myTimedEntry = DPSAddTimedEntry(updatePeriod, (DPSTimedEntryProc)updateFunc, CurrentCell, NX_BASETHRESHOLD); return self; } //////////////////////////////////////////////////////////////////////// // Target method for the Help button // This can only be called if a Help file exists for // the current cell. - helpClicked:sender { id CurrentCell; char tmpchar[256]; NXStream *textStream; if ([[myHelpText docView] textLength] == 0) // Not yet loaded { CurrentCell = [[myBrowser matrixInColumn: [myBrowser selectedColumn]] selectedCell]; sprintf(tmpchar, "%s/%s", [CurrentCell getDir], "HELP.rtf"); textStream = NXMapFile(tmpchar, NX_READONLY); if (textStream == NIL) { [myDispatcher showError:"Error (2) opening HELP.rtf file."]; return self; } [[myHelpText docView] readRichText:textStream]; [[myHelpText docView] setSel:0 :0]; [[myHelpText docView] scrollSelToVisible]; NXCloseMemory(textStream, NX_FREEBUFFER); } [myHelpPanel makeKeyAndOrderFront:self]; return self; } //////////////////////////////////////////////////////////////////////// // Called by modules to put up messages. - addMessage:(char *)theMessage { [[messageScrollView docView] setSel:1000000 :1000000]; [[[messageScrollView docView] replaceSel:theMessage] scrollSelToVisible]; return self; } //////////////////////////////////////////////////////////////////////// // Target method for the Clear button. Clears out all messages. - clearMessages:sender { [[messageScrollView docView] setText:""]; return self; } /////////////////////////////////////////////////////////////////////////// // This method is used by modules to run functions that do not work when // called from a dynamically loaded module. Functions having this problem : // PScountscreenlist(), PScountwindowlist(), PSostype() and probably others. - (int *) runFunction:(int * (*)())theFunction { return theFunction(); } /////////////////////////////////////////////////////////////////////////// // Target method for the browser. // // When the user clicks on a cell in the browser, it can either be a // leaf or a branch cell. If it is a branch, then we put back the Text // in the ScrollView. // If it is a leaf, then we load the Main.o file in the .inform directory, // first alone, and then with /lib/libsys_s.a if it fails. We then create // an instance of the class, which returns its view. We finally put that // view as the DocView of our ScrollView. - cellClicked:sender { id CurrentCell; id theObject; id theView; id theClass; char tmpchar[256]; struct stat myStat; CurrentCell = [[sender matrixInColumn:[sender selectedColumn]] selectedCell]; // If there is a help file, enable Help button, else hide help window sprintf(tmpchar, "%s/%s", [CurrentCell getDir], "HELP.rtf"); if (stat(tmpchar, &myStat) == 0) [helpButton setEnabled:YES]; else [helpButton setEnabled:NO]; [myHelpPanel performClose:self]; [[myHelpText docView] setText:""]; if (myTimedEntry) { DPSRemoveTimedEntry(myTimedEntry); myTimedEntry = 0; } [updateTextSeconds setStringValue:"second"]; [updateScroller setIntValue:0]; [updateText setIntValue:0]; [updateScroller setEnabled:NO]; [updateText setEnabled:NO]; updatePeriod = 0; if ((theObject = [CurrentCell updater]) != NIL) { [myWindow disableFlushWindow]; if ([theObject doUpdateForCell:CurrentCell]) { [myInspectorView setDocView:[theObject mainView]]; updatePeriod = [theObject updateInterval]; [updateScroller setIntValue:updatePeriod]; [updateText setIntValue:updatePeriod]; if (updatePeriod <= 1) [updateTextSeconds setStringValue:"second"]; else [updateTextSeconds setStringValue:"seconds"]; if (updatePeriod) { [updateScroller setEnabled:YES]; [updateText setEnabled:YES]; } else { [updateScroller setEnabled:NO]; [updateText setEnabled:NO]; } if (updatePeriod) myTimedEntry = DPSAddTimedEntry(updatePeriod, (DPSTimedEntryProc)updateFunc, CurrentCell, NX_BASETHRESHOLD); } else [myInspectorView setDocView:myEmptyView]; [[myWindow reenableFlushWindow] flushWindow]; return self; } if ( ! [CurrentCell isLeaf]) // it's only a directory { [myInspectorView setDocView:myEmptyView]; return self; } if ( ! [CurrentCell getMasterInstance]) { theClass = [myDispatcher loadClassFromCell:CurrentCell]; if (theClass) // load was successful theObject = [theClass new]; else { [self addMessage:"InformerWindow : could not create instance.\n"]; return self; } theView = [theObject loadEverythingFrom:[CurrentCell getDir]]; [theObject setMaster:self]; updatePeriod = [theObject updateInterval]; [updateScroller setIntValue:updatePeriod]; [updateText setIntValue:updatePeriod]; if (updatePeriod <= 1) [updateTextSeconds setStringValue:"second"]; else [updateTextSeconds setStringValue:"seconds"]; if (updatePeriod) { [updateScroller setEnabled:YES]; [updateText setEnabled:YES]; } else { [updateScroller setEnabled:NO]; [updateText setEnabled:NO]; } [theView removeFromSuperview]; [myInspectorView setDocView:theView]; } else theObject = [CurrentCell getMasterInstance]; [myWindow disableFlushWindow]; if ([theObject doUpdateForCell:CurrentCell]) { if (updatePeriod) myTimedEntry = DPSAddTimedEntry(updatePeriod, (DPSTimedEntryProc)updateFunc, CurrentCell, NX_BASETHRESHOLD); } else [myInspectorView setDocView:myEmptyView]; [[myWindow reenableFlushWindow] flushWindow]; return self; } ////////////////////////////////////////////////////////////////////////////// // - window { return myWindow; } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// // Delegate method for the browser - (int)browser:sender fillMatrix:matrix inColumn:(int)column { DIR *myDirStream; struct direct *myDir; id CurrentCell; id tmpCell; char tmpChar[512]; char tmpName[256]; char *tmpcharptr; char *cellDir; struct stat myStat; //NXStream *myStream; int isList; id updater; id theObject; id theClass; if ( ! [[sender cellPrototype] isMemberOf:[InformerCell class]]) return 0; if (column == 0) // First column { cellDir = baseDir; isList = NO; updater = NULL; [sender setTitle:"Informer" ofColumn:0]; } else // Not the first column { CurrentCell=[[sender matrixInColumn:[sender selectedColumn]] selectedCell]; cellDir = [CurrentCell getDir]; isList = [CurrentCell isList]; updater = [CurrentCell updater]; } if (updater) { [updater fillList:matrix fromCell:CurrentCell]; } else if (isList) // Ask the new class to fill the matrix { if ( ! [CurrentCell getMasterInstance]) { theClass = [myDispatcher loadClassFromCell:CurrentCell]; if (theClass) // load was successful { theObject = [theClass new]; [theObject loadEverythingFrom:[CurrentCell getDir]]; [theObject setMaster:self]; [[theObject mainView] removeFromSuperview]; } } else theObject = [CurrentCell getMasterInstance]; [theObject fillList:matrix fromCell:CurrentCell]; } else // for plain directories { myDirStream = opendir(cellDir); if (myDirStream == NIL) { [myDispatcher showError:"Could not find base directory."]; [self addMessage:"InformerWindow : could not find base directory.\n"]; return 0; } for (myDir = readdir(myDirStream); myDir != NULL; myDir = readdir(myDirStream)) { if (myDir->d_name[0] == '.') // Don't display "." and ".." continue; sprintf(tmpChar, "%s/%s", cellDir, myDir->d_name); stat(tmpChar, &myStat); if (myStat.st_mode & S_IFDIR) // It is a directory { [matrix addRow]; strncpy(tmpName, myDir->d_name, 511); // The name for now tmpCell = [matrix cellAt:([matrix cellCount] -1) :0]; if (strlen(myDir->d_name) > 5) // Check if .item dir { strncpy(tmpChar, myDir->d_name, 255); tmpcharptr = tmpChar; tmpcharptr += (strlen(tmpcharptr) - 5); if ( ! strncmp(tmpcharptr, ".item", 5)) // It is a .item { [tmpCell setLeaf:YES]; *tmpcharptr = '\0'; // Remove .item ending strncpy(tmpName, tmpChar, 255); } else if ( ! strncmp(tmpcharptr, ".list", 5)) // It is a .list { [tmpCell setIsList:YES]; *tmpcharptr = '\0'; // Remove .list ending strncpy(tmpName, tmpChar, 255); } } sprintf(tmpChar, "%s/%s", cellDir, myDir->d_name); [tmpCell setDir:tmpChar]; [tmpCell setStringValue:tmpName]; // Give the cell its name } } } return [matrix cellCount]; } ////////////////////////////////////////////////////////////////////////////// // Delegate methods for the window // ///////////////////////////////////////////////// // Called when our window becomes the main window. - windowDidBecomeMain:sender { [myDispatcher newFrontWindow:self]; return self; } ///////////////////////////////////////////////// // Called when our window becomes the key window. - windowDidBecomeKey:sender { [myDispatcher newFrontWindow:self]; return self; } ///////////////////////////////////////////////// // Called when our window has stopped being the key window. - windowDidResignKey:sender { [myDispatcher oldFrontWindow:self]; return self; } ///////////////////////////////////////////////// // Called when our window is going to close. - windowWillClose:sender { [myDispatcher oldFrontWindow:self]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.