This is MiscSwitchView.m in view mode; [Download] [Up]
// Suppress compiler warning about rcsid being unused, yet prevent assembler // code for this function from being produced. inline extern const char *suppressCompilerWarning(void) { static const char *rcsid = "$Id$ cc: "__FILE__" "__DATE__" "__TIME__; return rcsid; } // // ------------------ MiscSwitchView Class Implementation --------------------- // // Yet another view that supports a switchable subview. Features a selection // of border styles including a border suitable for using the MiscTabCell to // create a file folder interface. Supports various alignments of the // switchable subview within MiscSwitchView's frame. // // Written by Art Isbell (inspired by TTools' SwitchView and UHSelectView). // Copyright 1996 by Art Isbell. // Version 1.0. All rights reserved. // // This notice may not be removed from this source code. // // This object is included in the MiscKit by permission from the author // and its use is governed by the MiscKit license, found in the file // "License.rtf" in the MiscKit distribution. Please refer to that file // for a list of all applicable permissions and restrictions. // // ---------------------------------------------------------------------------- // // ----------------------------- Header Files --------------------------------- #import <AppKit/AppKit.h> #ifndef NOMISC #import <misckit/MiscSwitchView.h> #else NOMISC #import "MiscSwitchView.h" #endif NOMISC // ---------------- Typedef, Struct, and Union Declarations ------------------- // --------------------- Constant and Enum Definitions ------------------------ int MiscNoView = -1; NSString *MiscViewWillSwitchNotification = @"MiscViewWillSwitch"; NSString *MiscViewDidSwitchNotification = @"MiscViewDidSwitch"; NSString *MiscNextViewNumberKey = @"MiscNextViewNumber"; static const unsigned MiscCurrentVersion = 2; static const MiscPosition MiscDefaultPosition = MiscCenter; static const MiscBorderType MiscDefaultBorderType = MiscTab; // ------------------------- Function Declarations ---------------------------- @interface MiscSwitchView(Private) // ---------------------- Private Method Declarations ------------------------- - (void)_positionView; @end @implementation MiscSwitchView // ---------------------- Factory Method Definitions -------------------------- + (void)initialize { [self setVersion:MiscCurrentVersion]; } // ---------------- Overridden Instance Method Definitions -------------------- - (id)initWithFrame:(NSRect)frameRect { self = [super initWithFrame:frameRect]; if (self != nil) { _position = MiscDefaultPosition; _borderType = MiscDefaultBorderType; _viewNumber = MiscNoView; _useMatrixBehavior = NO; _views = [[NSMutableArray allocWithZone:[self zone]] init]; [self setAutoresizesSubviews:YES]; } return self; } - (id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self != nil) { _viewNumber = MiscNoView; if ([aDecoder versionForClassName:NSStringFromClass([self class])] == MiscCurrentVersion) { [aDecoder decodeValuesOfObjCTypes:"iiC", &_position, &_borderType, &_useMatrixBehavior]; } else { // If viewNumber were merely unarchived, setViewNumber: wouldn't // set the view because it does nothing when its argument is // identical to viewNumber which it would be in this case. int unarchivedViewNumberL; [aDecoder decodeValuesOfObjCTypes:"iii", &_position, &_borderType, &unarchivedViewNumberL]; [self setViewNumber:unarchivedViewNumberL]; } _views = [[aDecoder decodeObject] retain]; [self setAutoresizesSubviews:YES]; } return self; } - (void)encodeWithCoder:(NSCoder *)aCoder { [super encodeWithCoder:aCoder]; [aCoder encodeValuesOfObjCTypes:"iiC", &_position, &_borderType, &_useMatrixBehavior]; [aCoder encodeObject:_views]; } - (void)dealloc { if (delegate != nil) { [[NSNotificationCenter defaultCenter] removeObserver:delegate name:nil object:self]; } [_views release]; [super dealloc]; } - (void)drawRect:(NSRect)aRect { // Here we only draw peripheral stuff. The selected view will be // displayed as a subview. [[NSColor controlColor] set]; NSRectFill(aRect); if (_borderType != MiscNone) { NSRect boundsL = [self bounds]; NSRect insideBorderRectL = NSInsetRect(boundsL, 2.0, 2.0); // Redraw border only if aRect extends into the border. if (!NSContainsRect(insideBorderRectL, aRect)) { switch (_borderType) { case MiscTab: { NSRectEdge sidesL[] = {NSMinXEdge, NSMinYEdge, NSMaxXEdge, NSMaxXEdge, NSMinYEdge}; float graysL[] = {NSWhite, NSBlack, NSBlack, NSDarkGray, NSDarkGray}; NSDrawTiledRects(boundsL , boundsL , sidesL, graysL, 5); break; } // If an unsupported borderType is specified, default to // MiscNone. case MiscNone: default: break; case MiscLine: [[NSColor blackColor] set]; NSFrameRect(boundsL); break; case MiscBezel: NSDrawGrayBezel(boundsL, boundsL); break; case MiscGroove: NSDrawGroove(boundsL, boundsL); break; case MiscButton: NSDrawButton(boundsL, boundsL); break; } } } } // -------------------- New Instance Method Definitions ----------------------- - (void)setBorderType:(MiscBorderType)aType { // MiscNone <= aType is always true because MiscBorderType is an unsigned // type and MiscNone == 0. if (aType <= MiscTab) { _borderType = aType; } else { _borderType = MiscDefaultBorderType; } [self setNeedsDisplay:YES]; } - (MiscBorderType)borderType { return _borderType; } - (void)setDelegate:(id)aDelegate { SEL delegateSelectorL; NSNotificationCenter *defaultCenterL = [NSNotificationCenter defaultCenter]; if (delegate != nil) { [defaultCenterL removeObserver:delegate name:nil object:self]; } delegate = aDelegate; delegateSelectorL = @selector(viewWillSwitch:); if ([delegate respondsToSelector:delegateSelectorL]) { [defaultCenterL addObserver:delegate selector:delegateSelectorL name:MiscViewWillSwitchNotification object:self]; } delegateSelectorL = @selector(viewDidSwitch:); if ([delegate respondsToSelector:delegateSelectorL]) { [defaultCenterL addObserver:delegate selector:delegateSelectorL name:MiscViewDidSwitchNotification object:self]; } } - (void)setPosition:(MiscPosition)aPosition { // MiscTopLeft <= aPosition is always true because MiscPosition is an // unsigned type and MiscTopLeft == 0. if (aPosition <= MiscBottomRight) { _position = aPosition; } else { _position = MiscDefaultPosition; } } - (MiscPosition)position { return _position; } - (void)setUseMatrixBehavior:(BOOL)aFlag { _useMatrixBehavior = aFlag; } - (BOOL)useMatrixBehavior { return _useMatrixBehavior; } - (void)setViewNumber:(int)aViewNumber { unsigned viewCountL = [_views count]; if (0 < viewCountL) { if ((0 <= aViewNumber) && (aViewNumber < viewCountL)) { // If the viewNumber was changed, switch the new view. if (aViewNumber != _viewNumber) { NSView *viewL; NSNotificationCenter *notificationCenterL = [NSNotificationCenter defaultCenter]; [notificationCenterL postNotificationName:MiscViewWillSwitchNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:aViewNumber], MiscNextViewNumberKey, nil]]; // This assumes that viewNumber, if not MiscNoView, must be // within range of views indices. if (_viewNumber != MiscNoView) { // Return current view to its original superview. viewL = [_views objectAtIndex:_viewNumber]; [viewL removeFromSuperview]; [_originalSuperview addSubview:viewL]; [viewL setFrame:_originalFrame]; } _viewNumber = aViewNumber; viewL = [_views objectAtIndex:_viewNumber]; _originalSuperview = [viewL superview]; _originalFrame = [viewL frame]; [viewL removeFromSuperview]; [self addSubview:viewL]; [self _positionView]; [notificationCenterL postNotificationName:MiscViewDidSwitchNotification object:self]; } } else { NSLog(@"View number, %d, is outside of range of available view numbers, 0 - %d", aViewNumber, viewCountL - 1); } } else { NSLog(@"No switchable views exist"); } } - (int)viewNumber { return _viewNumber; } - (NSArray *)views { return _views; } - (void)takeViewNumberFrom:(id)aSender { int newViewNumberL; if (aSender != nil) { SEL valueSelectorL = [self valueSelectorForSwitchSource:aSender]; if (valueSelectorL != (SEL)NULL) { newViewNumberL = (int)[aSender performSelector:valueSelectorL]; } else { newViewNumberL = MiscNoView; } } else { newViewNumberL = MiscNoView; } [self setViewNumber:newViewNumberL]; } - (void)takeTagFrom:(id)aSender { [self setViewNumber:[aSender tag]]; } - (void)takeIntValueFrom:(id)aSender { [self setViewNumber:[aSender intValue]]; } - (void)takeSelectedRowFrom:(id)aSender { [self setViewNumber:[aSender selectedRow]]; } - (void)takeSelectedColumnFrom:(id)aSender { [self setViewNumber:[aSender selectedColumn]]; } - (unsigned)count { return [_views count]; } - (NSView *)currentView { if (_viewNumber != MiscNoView) { return [_views objectAtIndex:_viewNumber]; } else { return nil; } } - (NSView *)viewAtIndex:(unsigned)anIndex { if (anIndex < [_views count]) { return [_views objectAtIndex:anIndex]; } else { return nil; } } - (unsigned)indexOfView:(NSView *)aView { return [_views indexOfObjectIdenticalTo:aView]; } - (void)addView:(NSView *)aView { if ((aView != nil) && ([_views indexOfObjectIdenticalTo:aView] == NSNotFound)) { [_views addObject:aView]; if (_viewNumber == MiscNoView) { _viewNumber = 0; } } } - (void)addView:(NSView *)aView atIndex:(unsigned)anIndex { if ((aView != nil) && ([_views indexOfObjectIdenticalTo:aView] == NSNotFound)) { if (anIndex < [_views count]) { [_views insertObject:aView atIndex:anIndex]; } else { [_views addObject:aView]; } if (_viewNumber == MiscNoView) { _viewNumber = 0; } } } - (void)removeView:(NSView *)aView { [_views removeObjectIdenticalTo:aView]; if ([_views count] == 0) { _viewNumber = MiscNoView; } } - (void)removeViewAtIndex:(unsigned)anIndex { unsigned viewCountL = [_views count]; if (anIndex < viewCountL) { [_views removeObjectAtIndex:anIndex]; if (viewCountL == 1) { _viewNumber = MiscNoView; } } } - (SEL)valueSelectorForSwitchSource:aSender { SEL valueSelectorL; if ([aSender isKindOfClass:[NSMatrix class]]) { int rowNumber; int columnNumber; [aSender getNumberOfRows:&rowNumber columns:&columnNumber]; if (columnNumber <= rowNumber) { valueSelectorL = @selector(selectedRow); } else { valueSelectorL = @selector(selectedColumn); } } else if ([aSender respondsToSelector:@selector(isEditable)] && [aSender isEditable] && [aSender respondsToSelector:@selector(intValue)]) { valueSelectorL = @selector(intValue); } else if ([aSender isKindOfClass:[NSButton class]] || [aSender isKindOfClass:[NSButtonCell class]]) { valueSelectorL = @selector(tag); } else if ([aSender respondsToSelector:@selector(intValue)]) { valueSelectorL = @selector(intValue); } else if ([aSender respondsToSelector:@selector(tag)]) { valueSelectorL = @selector(tag); } else { valueSelectorL = (SEL)NULL; } return valueSelectorL; } - (void)subviewFrameChanged:(NSNotification *)aNotification { if ([self indexOfView:[aNotification object]] == _viewNumber) { [self _positionView]; } } // ----------------- Delegate Instance Method Definitions --------------------- @end @implementation MiscSwitchView(Private) // ---------------------- Private Method Definitions -------------------------- - (void)_positionView { if (_viewNumber != MiscNoView) { float borderWidthL; NSRect boundsRectL; NSRect subviewFrameL; NSPoint frameOriginL; NSView *viewL; if (_borderType == MiscNone) { borderWidthL = 0.0; } else { borderWidthL = 2.0; } viewL = [_views objectAtIndex:_viewNumber]; boundsRectL = [self bounds]; subviewFrameL = [viewL frame]; // Cases ordered in decreasing probability. switch (_position) { // Centering is most common and is the default should an // unsupported position be specified. case MiscCenter: default: frameOriginL = NSMakePoint((NSWidth(boundsRectL) - NSWidth(subviewFrameL)) / 2.0, (NSHeight(boundsRectL) - NSHeight(subviewFrameL)) / 2.0); break; case MiscTopCenter: frameOriginL = NSMakePoint((NSWidth(boundsRectL) - NSWidth(subviewFrameL)) / 2.0, NSHeight(boundsRectL) - NSHeight(subviewFrameL) - borderWidthL); break; case MiscBottomCenter: frameOriginL = NSMakePoint((NSWidth(boundsRectL) - NSWidth(subviewFrameL)) / 2.0, borderWidthL); break; case MiscTopLeft: frameOriginL = NSMakePoint(borderWidthL, NSHeight(boundsRectL) - NSHeight(subviewFrameL) - borderWidthL); break; case MiscTopRight: frameOriginL = NSMakePoint(NSWidth(boundsRectL) - NSWidth(subviewFrameL) - borderWidthL, NSHeight(boundsRectL) - NSHeight(subviewFrameL) - borderWidthL); break; case MiscLeft: frameOriginL = NSMakePoint(borderWidthL, (NSHeight(boundsRectL) - NSHeight(subviewFrameL)) / 2.0); break; case MiscRight: frameOriginL = NSMakePoint(NSWidth(boundsRectL) - NSWidth(subviewFrameL) - borderWidthL, (NSHeight(boundsRectL) - NSHeight(subviewFrameL)) / 2.0); break; case MiscBottomLeft: frameOriginL = NSMakePoint(borderWidthL, borderWidthL); break; case MiscBottomRight: frameOriginL = NSMakePoint(NSWidth(boundsRectL) - NSWidth(subviewFrameL) - borderWidthL, borderWidthL); break; } [viewL setFrameOrigin:frameOriginL]; [viewL setNeedsDisplay:YES]; } } @end // ------------------------- Function Definitions -----------------------------
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.