This is IKCell.m in view mode; [Download] [Up]
#pragma .h #import <AppKit/NSActionCell.h> #pragma .h #import <AppKit/NSImage.h> #pragma .h #import <AppKit/NSCStringText.h> #pragma .h #pragma .h #import "IKIconObject.h" #pragma .h #import "IKDependency.h" #pragma .h #pragma .h enum { #pragma .h IK_NOPART, #pragma .h IK_TITLEPART, #pragma .h IK_ICONPART #pragma .h }; #pragma .h #pragma .h enum { #pragma .h IK_NOSHELF, #pragma .h IK_UNLOCKED, #pragma .h IK_LOCKED, #pragma .h IK_REALLYLOCKED #pragma .h }; #pragma .h #pragma .h typedef struct _cellflags { #pragma .h unsigned int showMiniImage:1; #pragma .h unsigned int showBranch:1; #pragma .h unsigned int draggable:1; #pragma .h unsigned int dragAccepting:1; #pragma .h unsigned int editable:1; #pragma .h unsigned int container:1; #pragma .h unsigned int locked:1; #pragma .h unsigned int reallyLocked:1; #pragma .h unsigned int multipleLines:1; #pragma .h unsigned int ghosted:1; #pragma .h } cellFlags; #import <AppKit/AppKit.h> #import "iconkit.h" #import "IKCellPS.h" @implementation IKCell : NSActionCell { id <IKIconObject, IKDependency> delegate; id image; id miniImage; cellFlags flags; } #define DX 9 #define DY 2 #define OFFSET 0 #define GAP 0 #define INSET 4 #define HYSTERESIS 4 static NSTextFieldCell *text; static id ghostImage = nil, ghostHighlightMask = nil, ghosting = nil; static void initGhostImages (NSSize); + (void)initialize { if (self == [IKCell class]) { [self setVersion:2]; text = [[NSTextFieldCell alloc] initTextCell:@""]; NSLog( @"IconKit Version 23:50 17.8.97" ); } return; } - init { if ((self = [super initTextCell:@""]) != nil) { image = nil; miniImage = nil; delegate = nil; flags.showMiniImage = NO; flags.showBranch = NO; flags.draggable = YES; flags.dragAccepting = YES; flags.editable = YES; flags.container = NO; flags.locked = YES; flags.reallyLocked = YES; flags.multipleLines = NO; flags.ghosted = NO; [self setAlignment:NSCenterTextAlignment]; } return self; } - initTextCell:(NSString *)theTitle { [self init]; [self setTitle:theTitle]; return self; } - initImageCell:(NSImage *)anImage { [self init]; [self setImage:anImage]; return self; } - initImage:(NSImage *) theImage title:(NSString *)theTitle { [self init]; [self setImage:theImage]; [self setTitle:theTitle]; return self; } - initDelegate:(id <IKIconObject, IKDependency>) theDelegate { [self init]; [self setDelegate:theDelegate]; return self; } - initFromCopy:(IKCell *) copy { [self init]; [self setBranch:[copy isBranch]]; [self setDraggable:[copy isDraggable]]; [self setDragAccepting:[copy isDragAccepting]]; [self setEditable:[copy isEditable]]; [self setContainer:[copy isContainer]]; [self setLocked:[copy isLocked]]; [self setReallyLocked:[copy isReallyLocked]]; [self setMultipleLines:[copy isMultipleLines]]; [self setGhosted:[copy isGhosted]]; [self setTitle:[copy title]]; [self setImage:[copy image]]; [self setMiniImage:[copy miniImage]]; return self; } - (void)dealloc { [delegate removeUser:self]; return [super dealloc]; self = self; } - (NSString *) inspectorClassName { return @"IKCellInspector"; } - (id)initWithCoder:(NSCoder *)aDecoder { char showBranch, draggable, dragAccepting, editable, container, locked, reallyLocked, multipleLines, showMiniImage; [super initWithCoder:aDecoder]; switch ([aDecoder versionForClassName:@"IKCell"]) { case 2: [aDecoder decodeValuesOfObjCTypes:"c", &showMiniImage]; // fall through flags.showMiniImage = showMiniImage; // wenn man es so macht, muessen die neuen ivars in write: miniImage = [[aDecoder decodeObject] retain]; // zuerst weggeschrieben werden ! case 1: image = [[aDecoder decodeObject] retain]; [aDecoder decodeValuesOfObjCTypes:"cccccccc", &showBranch, &draggable, &dragAccepting, &editable, &container, &locked, &reallyLocked, &multipleLines]; miniImage = nil; flags.showMiniImage = NO; flags.multipleLines = multipleLines; flags.ghosted = NO; break; case 0: image = [[aDecoder decodeObject] retain]; [aDecoder decodeValuesOfObjCTypes:"ccccccc", &showBranch, &draggable, &dragAccepting, &editable, &container, &locked, &reallyLocked]; miniImage = nil; flags.showMiniImage = NO; flags.multipleLines = NO; flags.ghosted = NO; break; } flags.showBranch = showBranch; flags.draggable = draggable; flags.dragAccepting = dragAccepting; flags.editable = editable; flags.container = container; flags.locked = locked; flags.reallyLocked = reallyLocked; return self; } - (void)encodeWithCoder:(NSCoder *)aCoder { char showBranch = flags.showBranch, draggable = flags.draggable, dragAccepting = flags.dragAccepting, editable = flags.editable, container = flags.container, locked = flags.locked, reallyLocked = flags.reallyLocked, multipleLines = flags.multipleLines, showMiniImage = flags.showMiniImage; [super encodeWithCoder:aCoder]; [aCoder encodeValuesOfObjCTypes:"c", &showMiniImage]; [aCoder encodeObject:miniImage]; [aCoder encodeObject:image]; [aCoder encodeValuesOfObjCTypes:"cccccccc", &showBranch, &draggable, &dragAccepting, &editable, &container, &locked, &reallyLocked, &multipleLines]; } - delegate { return delegate; } - (NSImage *)image { return image; } - (NSImage *)miniImage { return miniImage; } - (NSString *)title { return [self stringValue]; } - (BOOL) isShowMiniImage { return flags.showMiniImage; } - (BOOL) isBranch { return flags.showBranch; } - (BOOL) isContainer { return flags.container; } - (BOOL) isLocked { return flags.locked; } - (BOOL) isReallyLocked { return flags.reallyLocked; } - (BOOL) isEmptyContainer { return flags.container && !delegate; } - (BOOL) isMultipleLines { return flags.multipleLines; } - (BOOL) isGhosted { return flags.ghosted; } - (BOOL) isDraggable { return flags.draggable && (!delegate || [delegate isDraggable]); } - (BOOL) isDragAccepting { return flags.dragAccepting && (!delegate || [delegate isDragAccepting]); } - (BOOL) isEditable { return flags.editable && (!delegate || [delegate isEditable]); } - (void)setImage:(NSImage *)theImage { [image autorelease]; image = [theImage retain]; } - (void)setMiniImage:(NSImage *) theImage { [miniImage autorelease]; miniImage = [theImage retain]; } - (void)setTitle:(NSString *)theTitle { NSRect oldFrame, newFrame; id editor = [self editor]; [self setStringValue:theTitle ? theTitle : @""]; if (editor) { if (theTitle == nil) { [(IKIconPath *)[self controlView] endEditing]; } else { oldFrame = [editor frame]; [editor setString:[self stringValue]]; // if ([editor isHorizontallyResizable] || [editor isVerticallyResizable]) { // NSRect titleRect; // titleRect = [self titleRectForBounds:[self frame]]; // [editor setFrame:titleRect]; // } newFrame = [editor frame]; [[self controlView] displayRect:NSUnionRect(newFrame , oldFrame)]; } } } // <<HACK>> All thse set Methods should be converted to return void !! - setShowMiniImage:(BOOL)flag { flags.showMiniImage = flag; return self; } - setBranch:(BOOL)flag { flags.showBranch = flag; return self; } - setDraggable:(BOOL)flag { flags.draggable = flag; return self; } - setDragAccepting:(BOOL)flag { flags.dragAccepting = flag; return self; } - (void)setEditable:(BOOL)flag; { flags.editable = flag; } - setContainer:(BOOL)flag { flags.container = flag; return self; } - setLocked:(BOOL)flag { flags.locked = flag; return self; } - setReallyLocked:(BOOL)flag { flags.reallyLocked = flag; return self; } - setMultipleLines:(BOOL)flag { flags.multipleLines = flag; return self; } - setGhosted:(BOOL)flag { flags.ghosted = flag; return self; } - (void)setDelegate:(id)theDelegate { id old = delegate; // This whole delegation stuff should be changed to work with Notifiactions !! delegate = IKCheckConformance (theDelegate) ? theDelegate :nil; if(delegate) { // <<HACK>> This is UGLY !!! We are bascially creating a retain cyle here !!! [delegate retain]; [delegate addUser:self]; [self setMiniImage:[delegate miniImage]]; [self setImage:[delegate image]]; [self setTitle:[delegate name]]; } else { [self setMiniImage:nil]; [self setImage:nil]; [self setTitle:nil]; } if(old) { // <<HACK>> This is UGLY !!! We are dealing with a retain cycle here !!! [old removeUser:self]; [old release]; } } - willFree:who { if (who == delegate) { delegate = nil; [self setDelegate:nil]; [(NSMatrix *)[self controlView] updateCell:self]; } return self; } - (int) shelfMode { if (!flags.container) return IK_NOSHELF; else if (flags.reallyLocked) return IK_REALLYLOCKED; else if (flags.locked) return IK_LOCKED; else return IK_UNLOCKED; } - setShelfMode:(int) mode { switch (mode) { case IK_NOSHELF: [self setContainer:NO]; break; case IK_UNLOCKED: [self setContainer:YES]; [self setLocked:NO]; [self setReallyLocked:NO]; break; case IK_LOCKED: [self setContainer:YES]; [self setLocked:YES]; [self setReallyLocked:NO]; break; case IK_REALLYLOCKED: [self setContainer:YES]; [self setLocked:YES]; [self setReallyLocked:YES]; break; } return self; } - didChangeName:sender { if (sender == delegate) [self setTitle:[delegate name]]; return self; } - didChangeImage:sender { if (sender == delegate) { [self setImage:[delegate image]]; [(NSMatrix *)[self controlView] updateCellInside:self]; } return self; } - didChangeMiniImage:sender { if (sender == delegate) { [self setMiniImage:[delegate miniImage]]; [(NSMatrix *)[self controlView] updateCellInside:self]; } return self; } - (void)highlight:(BOOL)flag withFrame:(NSRect)cellFrame inView:(NSView *)view { id anImage = (flags.showMiniImage ? miniImage :image); if (anImage && ([self isHighlighted] != flag)) { [super highlight:flag withFrame:cellFrame inView:view]; } } - (NSImage *)_imageToDraw { NSImage *anImage = (flags.showMiniImage ? miniImage :image); if (flags.ghosted && anImage != ghosting) { NSPoint origin = { 0.0, 0.0 }; NSSize size = [anImage size]; initGhostImages (size); [ghostImage lockFocus]; [anImage compositeToPoint:origin operation:NSCompositeCopy]; [ghostHighlightMask compositeToPoint:origin operation:NSCompositeSourceAtop]; [ghostImage unlockFocus]; ghosting = anImage; } return flags.ghosted ? ghostImage : anImage; } static id controlView = nil; float background; - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)view { id anImage = (flags.showMiniImage ? miniImage : image); controlView = view; if (anImage != NULL) [self drawIcon:cellFrame]; if ([self stringValue] != NULL) [self drawTitle:cellFrame]; if (flags.showBranch) [self drawBranch:cellFrame]; } - (void)drawIcon:(NSRect) iconRect { iconRect = [self imageRectForBounds:iconRect]; PSsetgray (([self state] | [self isHighlighted]) ? NSWhite : NSLightGray); PSiconBackdrop( iconRect.origin.x - DX, iconRect.origin.y - DY, iconRect.size.width + 2.0 * DX, iconRect.size.height + 2.0 * DY ); iconRect.origin.y += iconRect.size.height; [[self _imageToDraw] compositeToPoint:iconRect.origin operation:NSCompositeSourceOver]; } - (void)drawTitle:(NSRect) titleRect { if ([self editor] == nil) { titleRect = [self titleRectForBounds:titleRect]; [text setStringValue:[self stringValue]]; [text setAlignment:[self alignment]]; [text setCellAttribute:NSCellHighlighted to:0]; [text setFont:[self font]]; [text setTextColor:[NSColor colorWithCalibratedWhite:flags.ghosted ? NSDarkGray : NSBlack alpha:1.0]]; [text setBackgroundColor:[NSColor lightGrayColor]]; [text setWraps:[self wraps]]; if (!flags.multipleLines) IKShortenTitle (text, titleRect.size.width); [text drawInteriorWithFrame:titleRect inView:controlView]; } } - (void)drawBranch:(NSRect) cellFrame { id branchIcon = [NSBrowserCell branchImage]; NSPoint origin = cellFrame.origin; NSSize size; size = [branchIcon size]; origin.x += cellFrame.size.width - size.width; origin.y += (cellFrame.size.height + size.height) / 2.0; [branchIcon compositeToPoint:origin operation:NSCompositeSourceOver]; } - (NSSize)cellSizeForBounds:(NSRect)frame { NSSize size; NSSize imageSize; id anImage = (flags.showMiniImage ? miniImage : image); int alignment = [self alignment]; size = [super cellSizeForBounds:frame]; imageSize = [anImage size]; if(alignment == NSCenterTextAlignment) { if ([[self stringValue] length] == 0) size.height = 0; size.width = MAX (size.width, imageSize.width) + 1 * DX + 1; size.height = size.height + imageSize.height + GAP + OFFSET + 1 * DY + 1; } else if(alignment == NSLeftTextAlignment) { size.width = size.width + imageSize.width + 1 * DX + 1; size.height = MAX (size.height, imageSize.height) + GAP + OFFSET + 1 * DY + 1; } return size; } - _getIconRect:(NSRect *) iconRect titleRect:(NSRect *) titleRect { NSRect bigRect = {{ 0.0, 0.0 }, { 10000.0, 10000.0 }}; NSSize title = { 0.0, 0.0 }, icon = { 0.0, 0.0 }; id anImage = (flags.showMiniImage ? miniImage : image); int alignment = [self alignment]; icon = [anImage size]; if(alignment == NSCenterTextAlignment) { iconRect->origin.y += flags.multipleLines ? INSET : (int)(iconRect->size.height - icon.height) / 2; iconRect->origin.x += /* GAP + DX + */ (int)(iconRect->size.width - icon.width) / 2; } else if(alignment == NSLeftTextAlignment) { iconRect->origin.y += (int)(iconRect->size.height - icon.height) / 2; iconRect->origin.x += GAP + DX; } if ([[self stringValue] length] > 0) { NSRect aRect, frame = *titleRect; if (flags.multipleLines) { if(alignment == NSCenterTextAlignment) { titleRect->origin.y = iconRect->origin.y + icon.height + GAP + DY; /* titleRect->origin.x += GAP + DX */; } else if(alignment == NSLeftTextAlignment) { titleRect->origin.y = iconRect->origin.y; titleRect->origin.x += icon.width + GAP + 2 * DX; } aRect = *titleRect; aRect = NSIntersectionRect(frame , aRect); title = aRect.size; } else { title = [super cellSizeForBounds:bigRect]; if(alignment == NSCenterTextAlignment) { title.width = MIN (titleRect->size.width, title.width); iconRect->origin.y += OFFSET - (int)(title.height + GAP) / 2; titleRect->origin.y = iconRect->origin.y + icon.height + GAP + DY; titleRect->origin.x += /* GAP + DX + */ (int) (titleRect->size.width - title.width) / 2; } else if(alignment == NSLeftTextAlignment) { titleRect->origin.y = iconRect->origin.y + (int)(icon.height / 2) - (int)(title.height / 2); titleRect->origin.x += icon.width + GAP + 2 * DX; title.width = titleRect->size.width - (titleRect->origin.x - iconRect->origin.x); } } } iconRect->size = icon; titleRect->size = title; return self; } - (NSRect)imageRectForBounds:(NSRect)iconRect { NSRect titleRect = iconRect; [self _getIconRect:&iconRect titleRect:&titleRect]; return iconRect; } - (NSRect)titleRectForBounds:(NSRect)titleRect { NSRect iconRect = titleRect; [self _getIconRect:&iconRect titleRect:&titleRect]; return titleRect; } - (int) hitPart:(NSPoint *) where inRect:(const NSRect *) cellFrame { NSRect iconRect = * cellFrame, titleRect = * cellFrame; iconRect = [self imageRectForBounds:iconRect]; titleRect = [self titleRectForBounds:titleRect]; return NSMouseInRect(*where , titleRect , YES) ? IK_TITLEPART: NSMouseInRect(*where , iconRect , NO) ? IK_ICONPART: IK_NOPART; } - dragIcon:(NSEvent *)event inRect:(const NSRect *) cellFrame ofView:view { NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard]; NSEvent *mouseDown = event; NSRect iconRect = * cellFrame; NSPoint offset; id old = delegate; id theImage = (flags.showMiniImage ? miniImage : image); [[view window] setAcceptsMouseMovedEvents:YES]; while ([event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantFuture] inMode:NSEventTrackingRunLoopMode dequeue:YES] type] == NSLeftMouseDragged) { offset.x = [event locationInWindow].x - [mouseDown locationInWindow].x; offset.y = [event locationInWindow].y - [mouseDown locationInWindow].y; if (abs(offset.x) + abs(offset.y) > HYSTERESIS) { [old addUser:self]; if (delegate != nil) { [delegate copyToPasteboard:pboard]; } else { [pboard declareTypes:(NSArray *)NULL owner:self]; } iconRect = [self imageRectForBounds:iconRect]; iconRect.origin.y += iconRect.size.height; if (flags.container && !flags.reallyLocked && (!flags.locked || ([event modifierFlags] & NSCommandKeyMask))) { [delegate removeUser:self]; [self setState:0]; [delegate release]; delegate = nil; //<<NOTE>> Should the lines above we replace with setDelegate:nil ? [self highlight:NO withFrame:iconRect inView:[self controlView]]; } [view dragImage:theImage at:iconRect.origin offset:NSMakeSize(offset.x,offset.y) event:mouseDown pasteboard:pboard source:view slideBack:YES]; if (delegate == nil && old != nil) [self setDelegate:nil]; [old removeUser:self]; break; } } [[view window] setAcceptsMouseMovedEvents:NO]; return self; } - (void)editorFrameChanged:(NSNotification *)arg { [[[arg object] window] invalidateCursorRectsForView:[self controlView]]; } - editTitle:(NSEvent *)event inRect:(const NSRect *)cellFrame ofView:view { NSRect titleRect = * cellFrame; NSTextView *editor = [[view window] fieldEditor:YES forObject:self]; BOOL canEdit = [self isEditable], canSelect = canEdit; int alignment = [self alignment]; if ([editor delegate] != self) { NSSize maxSize = { titleRect.size.width, titleRect.size.height }, minSize = { 0.0, titleRect.size.height }; [view endEditing]; if(alignment == NSCenterTextAlignment) { titleRect.size.width += 2000; titleRect.origin.x -= 1000; } titleRect = [self titleRectForBounds:titleRect]; [editor setDrawsBackground:YES]; [editor setAlignment:alignment]; [editor setTextColor:[NSColor blackColor]]; [editor setFont:[self font]]; [editor setEditable:canEdit]; [editor setSelectable:canSelect]; [editor setMaxSize:maxSize]; [[editor textContainer] setContainerSize:maxSize]; [editor setMinSize:minSize]; [[editor textContainer] setWidthTracksTextView:NO]; [editor setHorizontallyResizable:NO]; [[editor textContainer] setHeightTracksTextView:flags.multipleLines]; [editor setVerticallyResizable:flags.multipleLines]; [editor setString:[self stringValue]]; [editor setDelegate:self]; if(alignment == NSCenterTextAlignment) { titleRect.origin.x = cellFrame->origin.x /* + GAP + DX */; titleRect.size.width = cellFrame->size.width; } else { titleRect.origin.x -= 3; } [editor setFrame:titleRect]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(editorFrameChanged:) name:NSViewFrameDidChangeNotification object:editor]; [view addSubview:editor]; [[view window] makeFirstResponder:editor]; } if (event != NULL) { [[view window] makeFirstResponder:editor]; [editor mouseDown:event]; } return self; } - (void)textDidEndEditing:(NSNotification *)aNotification { NSString *name; if ([self isEditable]) { id sender = [aNotification object]; if(sender == [self editor]) { name = [sender string]; if([name length] == 0) name = @""; if (! [name isEqual:[self stringValue]]) { [self setStringValue:name]; } [delegate setName:name]; [sender removeFromSuperview]; [sender setDelegate:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:NSViewFrameDidChangeNotification object:sender]; } } } - editor { id editor = [[[self controlView] window] fieldEditor:NO forObject:self]; return (editor && [editor delegate] == self) ? editor : nil; } @end static void initGhostImages (NSSize size) { NSSize imageSize, maskSize; imageSize = [ghostImage size]; maskSize = [ghostHighlightMask size]; if (size.width > imageSize.width || size.height > imageSize.height) { [ghostImage release]; ghostImage = [[NSImage alloc] initWithSize:size]; } if (size.width > maskSize.width || size.height > maskSize.height) { [ghostHighlightMask release]; ghostHighlightMask = [[NSImage alloc] initWithSize:size]; [ghostHighlightMask lockFocus]; PSsetalpha (1.0 / 3.0); PSsetgray (1.0); PSrectfill (0.0, 0.0, size.width, size.height); [ghostHighlightMask unlockFocus]; } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.