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.