This is MiscTabCell.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; } // // ------------------- MiscTabCell Class Implementation ----------------------- // // NSMatrix cell designed to draw itself as a horizontal file folder tab across // the top of a MiscSwitchView with a "file folder" border. // // Written by Art Isbell (derived from UITabActionCell by Bill Edney, // Sean Hill, Mark Onyschuk). // 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/MiscTabCell.h> #import <misckit/drawTab.h> #else NOMISC #import "MiscTabCell.h" #import "drawTab.h" // pswrap that draws tab ends. #endif NOMISC // ---------------- Typedef, Struct, and Union Declarations ------------------- // --------------------- Constant and Enum Definitions ------------------------ // Minimum constant tab end width that results in a nicely-curved tab end. static const int MiscTabEndWidth = 12; // Left border gray on color systems (empirically determined) static const float MiscLeftBorderGray = 21.0 / 25.0; static NSString *MiscDefaultTabLabel = @"Label"; // ------------------------- Function Declarations ---------------------------- @interface MiscTabCell(Private) // ---------------------- Private Method Declarations ------------------------- - (void)_finishInitializing; @end @implementation MiscTabCell // ---------------------- Factory Method Definitions -------------------------- // ---------------- Overridden Instance Method Definitions -------------------- - (id)init { return [self initTextCell:MiscDefaultTabLabel]; } - (id)initTextCell:(NSString *)aString { self = [super initTextCell:aString]; if (self != nil) { // Finish the initialization process. [self _finishInitializing]; } return self; } // Initializes a new instance after being unarchived. - (id)awakeAfterUsingCoder:(NSCoder *)aDecoder { // Finish the initialization process. [self _finishInitializing]; return self; } - (BOOL)isOpaque { return YES; } // Draws the receiver inside cellFrame in aControlView. The tab is composed of // ends drawn by a pswrap and shaped like right triangles with a Bezier curve // hypotenuse plus a rectangular text cell between the ends. The tab ends of // interior tabs extend beyond the ends of the cellFrame to create overlapping // tabs if the intercell distance is small. Because the leftmost and rightmost // tabs cannot draw their left and right ends, respectively, in adjacent cells, // they are narrower by half the width of an end than interior tabs. - (void)drawWithFrame:(NSRect)aCellFrame inView:(NSView *)aControlView { BOOL isResizingL = (BOOL)(aControlView == nil || ![aControlView isKindOfClass:[NSMatrix class]]); BOOL isSelectedL = (BOOL)(!isResizingL && ([(NSMatrix *)aControlView selectedCell] == self)); // If self is selected, draw all other cells starting with rightmost, then // draw self. if (isSelectedL) { [self redrawCellsInView:(NSMatrix *)aControlView]; } // If self _canDraw or self is resizing in IB, draw self. if (_canDraw || isResizingL) { [self eraseWithFrame:aCellFrame inView:aControlView isSelected:isSelectedL]; [self drawTabEndsWithFrame:aCellFrame inView:aControlView isSelected:isSelectedL]; [self drawInteriorWithFrame:aCellFrame inView:aControlView isSelected:(isResizingL || isSelectedL)]; [self drawUpperBezelWithFrame:aCellFrame inView:aControlView isSelected:isSelectedL]; // If aControlView is resizing or self isn't selected, draw lower // bezel. if (!isSelectedL) { [self drawLowerBezelWithFrame:aCellFrame inView:aControlView isResizing:isResizingL]; } // Prevent redraws. _canDraw = NO; [aControlView setNeedsDisplay:YES]; } } - (void)drawInteriorWithFrame:(NSRect)aCellFrame inView:(NSView *)aControlView { // isSelected will be true if aControlView is being resized in IB or if // self is selected. [self drawInteriorWithFrame:aCellFrame inView:aControlView isSelected:(BOOL)(aControlView == nil || ![aControlView isKindOfClass:[NSMatrix class]] || [(NSMatrix *)aControlView selectedCell] == self)]; } - (void)highlight:(BOOL)aFlag withFrame:(NSRect)aCellFrame inView:(NSView *)aView { // Always passing a NO flag to super redraws the key view indication over // the cell's top border upon mouse up, so invoke _cmd with super only if // aFlag is YES which happens upon mouse down. Sending // highlight:withFrame:inView: with a YES flag from // trackMouse:inRect:ofView:untilMouseUp: seems necessary to prevent // highlighting. if (aFlag) { [super highlight:NO withFrame:[self drawingRectForBounds:aCellFrame inView:aView] inView:aView]; } } - (NSSize)cellSizeForBounds:(NSRect)aRect { NSSize superSizeL = [super cellSizeForBounds:aRect]; // Add 1.5 tabEndWidths to width that super returns so that first and last // cells will be wide enough to display the text. return NSMakeSize((float)((((3 * MiscTabEndWidth) + 1) / 2) + (unsigned)superSizeL.width), superSizeL.height); } // Limit the drawing rectangle to the text rectangle. - (NSRect)drawingRectForBounds:(NSRect)aRect { return [self drawingRectForBounds:(NSRect)aRect inView:[self controlView]]; } - (NSRect)titleRectForBounds:(NSRect)aRect { return [self drawingRectForBounds:aRect]; } - (BOOL)trackMouse:(NSEvent *)theEvent inRect:(NSRect)aCellFrame ofView:(NSView *)aControlView untilMouseUp:(BOOL)aFlag { [self highlight:YES withFrame:aCellFrame inView:aControlView]; return [super trackMouse:theEvent inRect:aCellFrame ofView:aControlView untilMouseUp:aFlag]; } // -------------------- New Instance Method Definitions ----------------------- // Sets the _canDraw ivar that's used to minimize cell drawing. - (void)setCanDraw:(BOOL)aFlag { _canDraw = aFlag; } - (NSColor *)cellGrayWithIsSelected:(BOOL)aFlag { if (aFlag) { return [NSColor lightGrayColor]; } else { // If the window default depth limit is 2-bit grayscale or less, return // dark gray. if ([NSWindow defaultDepthLimit] <= NSBestDepth(NSCalibratedWhiteColorSpace, 2, 2, YES, NULL)) { return [NSColor darkGrayColor]; } // The window default depth limit is deeper than 2-bit grayscale, so // return gray. else { return [NSColor grayColor]; } } } - (NSColor *)textGrayWithIsSelected:(BOOL)aFlag { // If self is enabled, use black text. if ([self isEnabled]) { return [NSColor blackColor]; } // Self is disabled, so use grayscale text appropriate to color depth. else { // If this is a 2-bit grayscale system, set appropriate grays. if ([NSWindow defaultDepthLimit] <= NSBestDepth(NSCalibratedWhiteColorSpace, 2, 2, YES, NULL)) { return [NSColor lightGrayColor]; } // This is not a 2-bit grayscale system, so set appropriate grays. else { return [NSColor darkGrayColor]; } } } - (NSColor *)leftBorderGrayWithIsSelected:(BOOL)aFlag { if (aFlag) { return [NSColor whiteColor]; } else { return [NSColor colorWithCalibratedWhite:MiscLeftBorderGray alpha:1.0]; } } - (NSColor *)rightBorderGrayWithIsSelected:(BOOL)aFlag { return [NSColor blackColor]; } - (NSColor *)upperBezelGrayWithIsSelected:(BOOL)aFlag { return [self leftBorderGrayWithIsSelected:aFlag]; } - (NSColor *)lowerBezelGrayWithIsSelected:(BOOL)aFlag { return [NSColor whiteColor]; } - (void)redrawCellsInView:(NSMatrix *)aMatrix { NSEnumerator *cellsL = [[aMatrix cells] reverseObjectEnumerator]; // Draw each cell starting with the rightmost. while (YES) { MiscTabCell *cellL = [cellsL nextObject]; // Loop termination test if (cellL == nil) break; // If cell isn't self, set its _canDraw flag and draw it. if (cellL != self) { [cellL setCanDraw:YES]; [aMatrix drawCell:cellL]; } } // Set self's _canDraw flag so it will draw last. _canDraw = YES; } // Limit the drawing rectangle to the text rectangle whose size is determined // by the cell's position in aControlView, if it exists. - (NSRect)drawingRectForBounds:(NSRect)aRect inView:(NSView *)aControlView { NSRect drawingRectL; float halfTabEndWidthL = (float)((MiscTabEndWidth + 1) / 2); NSSize textCellSizeL = [self cellSizeForBounds:aRect]; drawingRectL.origin.y = NSMinY(aRect) + (float)((unsigned)(NSHeight(aRect) - textCellSizeL.height) / 2); drawingRectL.size.height = textCellSizeL.height; // If aControlView isn't being resized in IB, return the correct drawing // rectangle. if ((aControlView != nil) && [aControlView isKindOfClass:[NSMatrix class]]) { NSArray *controlCellsL = [(NSMatrix *)aControlView cells]; BOOL isFirstCellL = (BOOL)([controlCellsL objectAtIndex:0] == self); // If self is first cell, set drawingRect origin tabEndWidth to the // right of the cell frame origin. if (isFirstCellL) { drawingRectL.origin.x = NSMinX(aRect) + (float)MiscTabEndWidth; } // self isn't first cell, so set drawingRect origin halfTabEndWidth to // the right of the cell frame origin. else { drawingRectL.origin.x = NSMinX(aRect) + halfTabEndWidthL; } // If self is first or last cell, set drawingRect width to 1.5 // tabEndWidth less than that of cell to accommodate tab ends. if (isFirstCellL || ([controlCellsL lastObject] == self)) { drawingRectL.size.width = NSWidth(aRect) - (float)MiscTabEndWidth - halfTabEndWidthL; } // self is interior cell, so set drawingRect width to tabEndWidth less // than that of cell to accommodate tab ends. else { drawingRectL.size.width = NSWidth(aRect) - (float)MiscTabEndWidth; } } // aControlView is being resized in IB, so return the drawing rectangle of // an interior cell. else { drawingRectL.origin.x = NSMinX(aRect) + halfTabEndWidthL; drawingRectL.size.width = NSWidth(aRect) - (float)MiscTabEndWidth; } return drawingRectL; } - (void)eraseWithFrame:(NSRect)aCellFrame inView:(NSView *)aControlView isSelected:(BOOL)aFlag { NSRect textFrameL = [self drawingRectForBounds:aCellFrame inView:aControlView]; // Erase self. [[self cellGrayWithIsSelected:aFlag] set]; NSRectFill(NSMakeRect(NSMinX(textFrameL), NSMinY(aCellFrame), NSWidth(textFrameL), NSHeight(aCellFrame))); } - (void)drawTabEndsWithFrame:(NSRect)aCellFrame inView:(NSView *)aControlView isSelected:(BOOL)aFlag { float cellGrayL = [[self cellGrayWithIsSelected:aFlag] whiteComponent]; NSRect textFrameL = [self drawingRectForBounds:aCellFrame inView:aControlView]; // Draw tab ends. drawLeftTabEndX_y_w_h_borderGray_cellGray((int)NSMinX(textFrameL), (int)NSMaxY(aCellFrame), MiscTabEndWidth, (int)NSHeight(aCellFrame), [[self leftBorderGrayWithIsSelected: aFlag] whiteComponent], cellGrayL); drawRightTabEndX_y_w_h_borderGray_cellGray((int)NSMinX(textFrameL) + (int)NSWidth(textFrameL), (int)NSMaxY(aCellFrame), MiscTabEndWidth, (int)NSHeight(aCellFrame), [[self rightBorderGrayWithIsSelected: aFlag] whiteComponent], cellGrayL); } - (void)drawInteriorWithFrame:(NSRect)aCellFrame inView:(NSView *)aControlView isSelected:(BOOL)aFlag { NSRect textFrameL = [self drawingRectForBounds:aCellFrame inView:aControlView]; // If aControlView is being resized in IB or self is selected, let super // draw cell interior. if (aFlag) { [super drawInteriorWithFrame:textFrameL inView:aControlView]; } // aControlView is being resized in IB or self isn't selected, so draw cell // interior because NSCell doesn't support setting text or cell background // colors. else { float ascenderL; float descenderL; float lineHeightL; NSFont *cellFontL; NSFont *screenFontL; NSString *stringValueL; // Draw the text by first filling the cell with cellGray. [[self cellGrayWithIsSelected:NO] set]; NSRectFill(textFrameL); [[self textGrayWithIsSelected:NO] set]; // Set the font. cellFontL = [self font]; screenFontL = [cellFontL screenFont]; if ([[NSDPSContext currentContext] isDrawingToScreen] && (screenFontL != nil)) { [screenFontL set]; } else { [cellFontL set]; } stringValueL = [self stringValue]; // Display text centered horizontally in the text cell and vertically, // with the bottom of the font descender at the text cell edge. NSTextFontInfo(cellFontL, &ascenderL, &descenderL, &lineHeightL); PSmoveto(NSMinX(textFrameL) + (float)(((unsigned)NSWidth(textFrameL) - (unsigned)[cellFontL widthOfString:stringValueL] - 1) / 2), NSMaxY(textFrameL) - descenderL); PSshow([stringValueL cString]); } } - (void)drawUpperBezelWithFrame:(NSRect)aCellFrame inView:(NSView *)aControlView isSelected:(BOOL)aFlag { NSRect textFrameL = [self drawingRectForBounds:aCellFrame inView:aControlView]; // Draw the upper bezel by using the drawing color that reflects the // selected state. [[self upperBezelGrayWithIsSelected:aFlag] set]; NSRectFill(NSMakeRect(NSMinX(textFrameL), NSMinY(aCellFrame), NSWidth(textFrameL), 1.0)); } - (void)drawLowerBezelWithFrame:(NSRect)aCellFrame inView:(NSView *)aControlView isResizing:(BOOL)aFlag { NSRect lowerBezelFrameL; // Set up the lowerBezelFrame that will be used for drawing the bottom // bezel. lowerBezelFrameL.origin.y = NSMaxY(aCellFrame) - 1.0; lowerBezelFrameL.size.height = 1.0; if (!aFlag) { float halfTabEndWidthL = (float)((MiscTabEndWidth + 1) / 2); NSSize intercellL = [(NSMatrix *)aControlView intercellSpacing]; NSArray *controlCellsL = [(NSMatrix *)aControlView cells]; // If self is the first cell, start the lower bezel at self's right // edge and set lowerBezelFrame's width to that of the self plus // halfTabEndWidth. if ([controlCellsL objectAtIndex:0] == self) { lowerBezelFrameL.origin.x = NSMinX(aCellFrame); lowerBezelFrameL.size.width = NSWidth(aCellFrame) + halfTabEndWidthL; } // self is the last cell so start the lower bezel at the right // edge of the cell to the left plus halfTabEndWidth and set // lowerBezelFrame's width to that of self plus the intercell less // halfTabEndWidth. else if ([controlCellsL lastObject] == self) { lowerBezelFrameL.origin.x = NSMinX(aCellFrame) - (intercellL.width - halfTabEndWidthL); lowerBezelFrameL.size.width = NSWidth(aCellFrame) + (intercellL.width - halfTabEndWidthL); } // self is an interior cell so start the lower bezel at the // right edge of the cell to the left plus halfTabEndWidth and set // lowerBezelFrame's width to that of self plus the intercell. else { lowerBezelFrameL.origin.x = NSMinX(aCellFrame) - (intercellL.width - halfTabEndWidthL); lowerBezelFrameL.size.width = NSWidth(aCellFrame) + intercellL.width; } } else { lowerBezelFrameL.origin.x = NSMinX(aCellFrame); lowerBezelFrameL.size.width = NSWidth(aCellFrame); } // Fill in lowerBezelFrame. [[self lowerBezelGrayWithIsSelected:NO] set]; NSRectFill(lowerBezelFrameL); } // ----------------- Delegate Instance Method Definitions --------------------- @end @implementation MiscTabCell(Private) // ---------------------- Private Method Definitions -------------------------- - (void)_finishInitializing { _canDraw = NO; [self setShowsFirstResponder:YES]; [self setAlignment:NSCenterTextAlignment]; } @end // ------------------------- Function Definitions -----------------------------
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.