This is MiscSwapView.m in view mode; [Download] [Up]
/* MiscSwapView.m * * This subclass of View is able to swap different views into itself. It's * used to implement any kind of multipage windows. (Inspectors, Prefs...) * * For more interface-info see the header file. More in depth information * can be found here in the source-code. * * Notes: There is one Cateogry for this class includes automatic swapping. * * Improved by: Thomas Engel * First changes: 24.01.1994 (Copyleft) * Last modified: 25.09.1994 */ //#import <misckit/misckit.h> #import <apps/InterfaceBuilder.h> #import "MiscSwapView.h" // The following are for keeping track of versions when archiving instances // of this class. If you change the write: method, make sure to // bump up the version below and make the appropriate changes to the read: // method so all previously archived instances will be unarchivable. #define MISC_SV_VERSION 0 #define MISC_SV_CLASSNAME "MiscSwapView" @implementation MiscSwapView + initialize { // Initialize the current version number which is used when archiving // objects. This way we will be able to read all versions if we are // careful. if (self == [MiscSwapView class]) [self setVersion: MISC_SV_VERSION]; return self; } - init { NXRect theFrame = {{0.0, 0.0}, {0.0, 0.0}}; return [self initFrame:&theFrame]; } - initFrame:(const NXRect *)frameRect { // Designated initilizer. We will set allow resizing by default and // we will draw in Lightgray if we have to swap 'nil' in. self = [super initFrame:frameRect]; if( !self ) return self; contentView = nil; contentViewsHomeView = nil; [self setDelegate: nil]; trigger = nil; currentController = nil; backgroundGray = NX_LTGRAY; [self setAutoresizeSubviews:YES]; useBuffering = NO; // Well the ByObject Category want's some other defaults too. controllers = [List new]; [self setTagComparison:YES]; return self; } - free { // We do not free the contentsControllers of this list! Well we didin't // allocate them..but maybe we should free them...hmmm. I'm not sure yet. [controllers free]; return [super free]; } - setDelegate:(id)anObject { delegate = anObject; return self; } - delegate { return delegate; } - setBackgroundGray:(float)aGray { backgroundGray = aGray; return self; } - (float)backgroundGray { return backgroundGray; } - setUseBuffering:(BOOL)flag { useBuffering = flag; return self; } - (BOOL)doesUseBuffering { return useBuffering; } - setContentView:aView { // This is the real method !! // Here we process the finding of the swapping and resizing. // If the new view is different from our current contentView we should // put the current back where it came from. NXRect theFrame; id contentViewsHomeWindow; int gState = 0; if( aView != contentView ) { if( contentView && contentViewsHomeView ) { [contentView removeFromSuperview]; [contentViewsHomeView addSubview:contentView]; [contentView moveTo:contentViewsHomeRect.origin.x :contentViewsHomeRect.origin.y]; [contentView sizeTo:contentViewsHomeRect.size.width :contentViewsHomeRect.size.height]; } // No real subview? So clean up the background. This is done by // filling the view bounds with the backgroundGray we did set. contentView = aView; // if( !contentView ) // { // contentViewsHomeView = nil; // } [self lockFocus]; PSsetgray( backgroundGray ); NXRectFill(&bounds); [self unlockFocus]; if( !contentView ) { contentViewsHomeView = nil; } // Otherwise we have a new subview so lets remove it form its home- // window, resize it and align it to our 0,0 corner. // If we have to use buffered composing we will now display our self // but we will compose into the screen. This might cause problems with // views that have to be resized. else { // If we use buffering then lets compose the views offscreen // if they have no gState which meant that they haven't been // drawn yet. // Let's ensure the windows are always retained and non deffered. // This make easy-offscreen drawing possible. contentViewsHomeWindow = [contentView window]; contentViewsHomeView = [contentView superview]; [contentView getFrame:&contentViewsHomeRect]; if( useBuffering ) { [contentViewsHomeWindow setBackingType:NX_RETAINED]; // Now lets get the views position inside its home. // We also need a gState to be able to do the fast copying. [contentView getFrame:&theFrame]; gState = [contentViewsHomeView gState]; if( !gState ) { [contentViewsHomeView allocateGState]; [contentViewsHomeView display]; gState = [contentViewsHomeView gState]; } NXPing(); } // The view reorganication is always the same. // Resizing is only applyed when we don't use buffering! [contentView removeFromSuperview]; [self addSubview:contentView]; [contentView moveTo:0.0 :0.0]; // The displaying might come with a simple redraw or a quick // composing by copying from the offscreen buffer. if( useBuffering && gState ) { // We will fill our background first to allow swapping of // views that don't have the same size. // Because they are not resized here to cover the whole // area its a must to clear the whole scene before! [self lockFocus]; PSsetgray(backgroundGray); NXRectFill(&bounds); PScomposite( (float)theFrame.origin.x, (float)theFrame.origin.y, (float)theFrame.size.width, (float)theFrame.size.height, (int)gState, (float)0.0, (float)0.0, (int)NX_COPY ); [self unlockFocus]; } else { [contentView sizeTo:bounds.size.width :bounds.size.height]; [self display]; } } // Let the windowServer catch up to the changes we made (yawn...) // And show our nice new window NXPing(); [[self window] flushWindow]; } return self; } - contentView { return contentView; } - contentViewsHomeView; { return contentViewsHomeView; } - write:(NXTypedStream *)stream { [super write: stream]; NXWriteObjectReference (stream, contentView); NXWriteObjectReference (stream, contentViewsHomeView); NXWriteObjectReference (stream, delegate); NXWriteTypes (stream, "fc", &backgroundGray, &useBuffering); NXWriteObjectReference (stream, trigger); NXWriteType (stream, "c", &tagComparison); return self; } - read:(NXTypedStream *)stream { int version; [super read: stream]; version = NXTypedStreamClassVersion(stream, MISC_SV_CLASSNAME); switch (version) { case 0: contentView = NXReadObject (stream); contentViewsHomeView = NXReadObject (stream); delegate = NXReadObject (stream); NXReadTypes (stream, "fc", &backgroundGray, &useBuffering); trigger = NXReadObject (stream); NXReadType (stream, "c", &tagComparison); break; default: break; } return self; } - awake { [super awake]; currentController = nil; controllers = [List new]; return self; } // As long as you have a trigger connected to the trigger outlet, this // should select an initial view for you. - drawSelf: (const NXRect *)rects :(int)rectCount { [self swapContentView: [self trigger] ]; return self; } @end /* * History: 25.09.94 Added archiving. (read:, write: awake, initialize) * Also added drawSelf:: so it would select an initial view. * * 24.02.94 Added Greg's quick composing. * * 24.01.94 Redesign from my old swapView. Added Buffering. * * 21.01.94 Added the resizing job the Greg's swapView. * * * Bugs: - Could be. Yes. */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.