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: 27.07.1997 * Copyright (C) 1995 Thomas Engel */ #import "MiscSwapView.h" #import "MiscSwapViewItem.h" // The following are for keeping track of versions when archiving instances // of this class. If you change the encodeWithCoder: method, make sure to // bump up the version below and make the appropriate changes to the initWithCoder: // method so all previously archived instances will be unarchivable. #define MISC_SV_VERSION 2 #define MISC_SV_CLASSNAME @"MiscSwapView" @implementation MiscSwapView + (void)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]; } - (id)init { NSRect theFrame = {{0.0, 0.0}, {0.0, 0.0}}; return [self initWithFrame: theFrame]; } - (id)initWithFrame:(NSRect)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 initWithFrame:frameRect]; if( !self ) return nil; // All instances can remain nil .. we just have a few settings to make. backgroundColor = [NSColor controlBackgroundColor]; [self setDrawsBackground:NO]; // Well the ByObject Category want's some other defaults too. itemArray = [NSMutableArray new]; [self setTagComparison:YES]; [self awake]; return self; } - (void)dealloc { // We do not free the contentsitemArray of this list! Well we didin't // allocate them..but maybe we should free them...hmmm. I'm not sure yet. [contentView release]; [contentViewsHomeView release]; [self _unregisterNotificationObserver:delegate]; [delegate release]; [backgroundColor release]; [identifier release]; // Before release our items...we will first remove them... this ensures that they are properly removed // from all our notifications. [self removeAllSwapViewItems]; [itemArray release]; [currentSwapItem release]; [super dealloc]; } - (id)initWithCoder:(NSCoder *)aDecoder { int version; [super initWithCoder:aDecoder]; version = [aDecoder versionForClassName:MISC_SV_CLASSNAME]; switch (version) { case 0: // <<HACK>> We should never get that one since this was the encoding of the NeXTSTEP version of this class. break; case 1: // We skip this version so that we can start of with encoding #2 since this is // mapping a lot better MiscKit 2.0 break; case 2: contentView = [[aDecoder decodeObject] retain]; // These usually should be nil !! contentViewsHomeView = [[aDecoder decodeObject] retain]; // These usually should be nil !! delegate = [[aDecoder decodeObject] retain]; backgroundColor = [[aDecoder decodeObject] retain]; identifier = [[aDecoder decodeObject] retain]; [aDecoder decodeValueOfObjCType:"c" at:&tagComparison]; [aDecoder decodeValueOfObjCType:"c" at:&backgroundDrawing]; [aDecoder decodeValueOfObjCType:"i" at:&alignment]; currentSwapItem = nil; itemArray = [NSMutableArray new]; default: break; } return self; } - (void)encodeWithCoder:(NSCoder *)aCoder { [super encodeWithCoder:aCoder]; [aCoder encodeConditionalObject:contentView]; [aCoder encodeConditionalObject:contentViewsHomeView]; [aCoder encodeConditionalObject:delegate]; [aCoder encodeObject:backgroundColor]; [aCoder encodeConditionalObject:identifier]; [aCoder encodeValueOfObjCType:"c" at:&tagComparison]; [aCoder encodeValueOfObjCType:"c" at:&backgroundDrawing]; [aCoder encodeValueOfObjCType:"i" at:&alignment]; } - (void)awake /*" This is a general awake method which can be reused by all different awake methods. "*/ { // <<HACK>> This is a really evil and mean hack. I have not had the time to check out the details. // But for some strage reasons our autoresize state is NO after we get unarchived from a NIB. // This caused the UI's not to resize properly. However...since the default NSView subclass should be // autoresizign its subviews by default...I really have no clue what is going wrong where. // Ergo: This is a fix...but definitly uncool. [self setAutoresizesSubviews:YES]; } - (void)awakeFromNib /*" Awake the object after getting instantiated from a NIB. "*/ { // Nothing to do here...we already handle the coder based awaking so that does a proper awake in our case. } - (id)awakeAfterUsingCoder:(NSCoder *)aCoder /*" Perform awaking after unarchiving from a stream controlled by aCoder. "*/ { [self awake]; return self; } - (void)setDelegate:(id)anObject /*" Sets our delegate and registers it with all our notifications. "*/ { if( delegate == anObject ) return; [self _unregisterNotificationObserver:delegate]; [self _registerNotificationObserver:anObject]; // Changing of the guards... [delegate release]; delegate = [anObject retain]; } - (id)delegate /*" Returns our current delegate. "*/ { return delegate; } - (void)setBackgroundColor:(NSColor *)aColor /*" Sets our background color to aColor. The default is NSColor's controlBackgroundColor. "*/ { // <<NOTE>> There was something about releasing colors. ?? [backgroundColor autorelease]; backgroundColor = [aColor retain]; } - (NSColor *)backgroundColor /*" Returns our background color. "*/ { return backgroundColor; } - (void)setDrawsBackground:(BOOL)flag /*" Returns our background color. By default this is set to NO. "*/ { backgroundDrawing = flag; } - (BOOL)drawsBackground /*" Returns YES if we have to draw our background and NO otherwise. "*/ { return backgroundDrawing; } - (BOOL)isOpaque { if( backgroundDrawing && [backgroundColor alphaComponent] == 1.0 ) return YES; return NO; } - (void)setContentView:(NSView *)aView /*" This method explicitly puts in a new subview and puts the current content view back to were it came from. "*/ { // This is the real method !! // Here we process the swapping and resizing. // If the new view is different from our current contentView we should // put the current back where it came from. if( aView != contentView ) { // This is the place to fire off some notifications since we will be changing our contentView if( contentView && contentViewsHomeView ) { //<<BUG>> this actually needs some different handling if our views do _not_ have // a superview !! This currently is a hack that works perfectly if you set up things inside // IB and don't create views programatically. [contentViewsHomeView addSubview:contentView]; [contentView setFrame:contentViewsHomeRect]; // We don't need that one...but all these retain release lines make sure that the views stay around // In a later version we might go through the code an remove the unnecessary ones...but since I don't // want to possible break this class I'll just keep it that way for now. [contentViewsHomeView release]; [contentView release]; contentViewsHomeView = nil; contentView = nil; } // If we really have a subview we will take care of it. if( aView ) { NSSize newSize; contentView = [aView retain]; contentViewsHomeView = [[contentView superview] retain]; contentViewsHomeRect = [contentView frame]; [self addSubview:contentView]; // <<HACK>> This needs some additional work since we have not yet considered the alignment // settings. [contentView setFrameOrigin:NSMakePoint(0.0, 0.0)]; newSize = [self bounds].size; if( !([contentView autoresizingMask] & NSViewWidthSizable) ) newSize.width = contentViewsHomeRect.size.width; if( !([contentView autoresizingMask] & NSViewHeightSizable) ) newSize.height = contentViewsHomeRect.size.height; [contentView setFrameSize:newSize]; } [self display]; } } - (NSView *)contentView { return contentView; } - (void)drawRect:(NSRect)rect { if( [self drawsBackground] ) { [backgroundColor set]; NSRectFill( rect ); } // As long as you have a identifier (e.g. button) connected to the identifier outlet, this // should select an initial view for you automatically on the first draw. // IMHO there should be a better place to drop this ! if( contentView == nil ) [self swapContentView:identifier]; } @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.