ImageAndTextCell.m
author Olivier Scherler <oscherler@femto-byte.com>
Tue May 12 14:38:30 2009 +0200 (2009-05-12)
changeset 30 2befbe36c746
permissions -rw-r--r--
Changed -[MYDirectoryEvent relativePath] to work on standardised paths, in case symlinks are used. Fixes issue #28 in Murky.
jens@20
     1
/*
jens@20
     2
    ImageAndTextCell.m
jens@20
     3
    Copyright (c) 2001-2006, Apple Computer, Inc., all rights reserved.
jens@20
     4
    Author: Chuck Pisula
jens@20
     5
jens@20
     6
    Milestones:
jens@20
     7
    * 03-01-2001: Initial creation by Chuck Pisula
jens@20
     8
    * 11-04-2005: Added hitTestForEvent:inRect:ofView: for better NSOutlineView support by Corbin Dunn
jens@20
     9
jens@20
    10
    Subclass of NSTextFieldCell which can display text and an image simultaneously.
jens@20
    11
*/
jens@20
    12
jens@20
    13
/*
jens@20
    14
 IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in
jens@20
    15
 consideration of your agreement to the following terms, and your use, installation, 
jens@20
    16
 modification or redistribution of this Apple software constitutes acceptance of these 
jens@20
    17
 terms.  If you do not agree with these terms, please do not use, install, modify or 
jens@20
    18
 redistribute this Apple software.
jens@20
    19
 
jens@20
    20
 In consideration of your agreement to abide by the following terms, and subject to these 
jens@20
    21
 terms, Apple grants you a personal, non-exclusive license, under AppleÕs copyrights in 
jens@20
    22
 this original Apple software (the "Apple Software"), to use, reproduce, modify and 
jens@20
    23
 redistribute the Apple Software, with or without modifications, in source and/or binary 
jens@20
    24
 forms; provided that if you redistribute the Apple Software in its entirety and without 
jens@20
    25
 modifications, you must retain this notice and the following text and disclaimers in all 
jens@20
    26
 such redistributions of the Apple Software.  Neither the name, trademarks, service marks 
jens@20
    27
 or logos of Apple Computer, Inc. may be used to endorse or promote products derived from 
jens@20
    28
 the Apple Software without specific prior written permission from Apple. Except as expressly
jens@20
    29
 stated in this notice, no other rights or licenses, express or implied, are granted by Apple
jens@20
    30
 herein, including but not limited to any patent rights that may be infringed by your 
jens@20
    31
 derivative works or by other works in which the Apple Software may be incorporated.
jens@20
    32
 
jens@20
    33
 The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO WARRANTIES, 
jens@20
    34
 EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, 
jens@20
    35
 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS 
jens@20
    36
 USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
jens@20
    37
 
jens@20
    38
 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL 
jens@20
    39
 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 
jens@20
    40
 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, 
jens@20
    41
 REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND 
jens@20
    42
 WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR 
jens@20
    43
 OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
jens@20
    44
*/
jens@20
    45
jens@20
    46
#import "ImageAndTextCell.h"
jens@20
    47
#import <AppKit/NSCell.h>
jens@20
    48
jens@20
    49
@implementation ImageAndTextCell
jens@20
    50
jens@20
    51
- (id)init {
jens@20
    52
    self = [super init];
jens@20
    53
    if( self ) {
jens@20
    54
        [self setLineBreakMode:NSLineBreakByTruncatingTail];
jens@20
    55
        [self setSelectable:YES];
jens@20
    56
    }
jens@20
    57
    return self;
jens@20
    58
}
jens@20
    59
jens@20
    60
- (void)dealloc {
jens@20
    61
    [image release];
jens@20
    62
    [super dealloc];
jens@20
    63
}
jens@20
    64
jens@20
    65
- (id)copyWithZone:(NSZone *)zone {
jens@20
    66
    ImageAndTextCell *cell = (ImageAndTextCell *)[super copyWithZone:zone];
jens@20
    67
    // The image ivar will be directly copied; we need to retain or copy it.
jens@20
    68
    cell->image = [image retain];
jens@20
    69
    return cell;
jens@20
    70
}
jens@20
    71
jens@20
    72
- (void)setImage:(NSImage *)anImage {
jens@20
    73
    if (anImage != image) {
jens@20
    74
        [image release];
jens@20
    75
        image = [anImage retain];
jens@20
    76
    }
jens@20
    77
}
jens@20
    78
jens@20
    79
- (NSImage *)image {
jens@20
    80
    return image;
jens@20
    81
}
jens@20
    82
jens@20
    83
- (NSRect)imageRectForBounds:(NSRect)cellFrame {
jens@20
    84
    NSRect result;
jens@20
    85
    if (image != nil) {
jens@20
    86
        result.size = [image size];
jens@20
    87
        result.origin = cellFrame.origin;
jens@20
    88
        result.origin.x += 3;
jens@20
    89
        result.origin.y += ceil((cellFrame.size.height - result.size.height) / 2);
jens@20
    90
    } else {
jens@20
    91
        result = NSZeroRect;
jens@20
    92
    }
jens@20
    93
    return result;
jens@20
    94
}
jens@20
    95
jens@20
    96
// We could manually implement expansionFrameWithFrame:inView: and drawWithExpansionFrame:inView: or just properly implement titleRectForBounds to get expansion tooltips to automatically work for us
jens@20
    97
- (NSRect)titleRectForBounds:(NSRect)cellFrame {
jens@20
    98
    NSRect result;
jens@20
    99
    if (image != nil) {
jens@20
   100
        CGFloat imageWidth = [image size].width;
jens@20
   101
        result = cellFrame;
jens@20
   102
        result.origin.x += (3 + imageWidth);
jens@20
   103
        result.size.width -= (3 + imageWidth);
jens@20
   104
    } else {
jens@20
   105
        result = NSZeroRect;
jens@20
   106
    }
jens@20
   107
    return result;
jens@20
   108
}
jens@20
   109
jens@20
   110
jens@20
   111
- (void)editWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject event:(NSEvent *)theEvent {
jens@20
   112
    NSRect textFrame, imageFrame;
jens@20
   113
    NSDivideRect (aRect, &imageFrame, &textFrame, 3 + [image size].width, NSMinXEdge);
jens@20
   114
    [super editWithFrame: textFrame inView: controlView editor:textObj delegate:anObject event: theEvent];
jens@20
   115
}
jens@20
   116
jens@20
   117
- (void)selectWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject start:(NSInteger)selStart length:(NSInteger)selLength {
jens@20
   118
    NSRect textFrame, imageFrame;
jens@20
   119
    NSDivideRect (aRect, &imageFrame, &textFrame, 3 + [image size].width, NSMinXEdge);
jens@20
   120
    [super selectWithFrame: textFrame inView: controlView editor:textObj delegate:anObject start:selStart length:selLength];
jens@20
   121
}
jens@20
   122
jens@20
   123
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
jens@20
   124
    if (image != nil) {
jens@20
   125
        NSRect	imageFrame;
jens@20
   126
        NSSize imageSize = [image size];
jens@20
   127
        NSDivideRect(cellFrame, &imageFrame, &cellFrame, 3 + imageSize.width, NSMinXEdge);
jens@20
   128
        if ([self drawsBackground]) {
jens@20
   129
            [[self backgroundColor] set];
jens@20
   130
            NSRectFill(imageFrame);
jens@20
   131
        }
jens@20
   132
        imageFrame.origin.x += 3;
jens@20
   133
        imageFrame.size = imageSize;
jens@20
   134
jens@20
   135
        if ([controlView isFlipped])
jens@20
   136
            imageFrame.origin.y += ceil((cellFrame.size.height + imageFrame.size.height) / 2);
jens@20
   137
        else
jens@20
   138
            imageFrame.origin.y += ceil((cellFrame.size.height - imageFrame.size.height) / 2);
jens@20
   139
jens@20
   140
        [image compositeToPoint:imageFrame.origin operation:NSCompositeSourceOver];
jens@20
   141
    }
jens@20
   142
    [super drawWithFrame:cellFrame inView:controlView];
jens@20
   143
}
jens@20
   144
jens@20
   145
- (NSSize)cellSize {
jens@20
   146
    NSSize cellSize = [super cellSize];
jens@20
   147
    cellSize.width += (image ? [image size].width : 0) + 3;
jens@20
   148
    return cellSize;
jens@20
   149
}
jens@20
   150
jens@20
   151
- (NSUInteger)hitTestForEvent:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView {
jens@20
   152
    NSPoint point = [controlView convertPoint:[event locationInWindow] fromView:nil];
jens@20
   153
    // If we have an image, we need to see if the user clicked on the image portion.
jens@20
   154
    if (image != nil) {
jens@20
   155
        // This code closely mimics drawWithFrame:inView:
jens@20
   156
        NSSize imageSize = [image size];
jens@20
   157
        NSRect imageFrame;
jens@20
   158
        NSDivideRect(cellFrame, &imageFrame, &cellFrame, 3 + imageSize.width, NSMinXEdge);
jens@20
   159
        
jens@20
   160
        imageFrame.origin.x += 3;
jens@20
   161
        imageFrame.size = imageSize;
jens@20
   162
        // If the point is in the image rect, then it is a content hit
jens@20
   163
        if (NSMouseInRect(point, imageFrame, [controlView isFlipped])) {
jens@20
   164
            // We consider this just a content area. It is not trackable, nor it it editable text. If it was, we would or in the additional items.
jens@20
   165
            // By returning the correct parts, we allow NSTableView to correctly begin an edit when the text portion is clicked on.
jens@20
   166
            return NSCellHitContentArea;
jens@20
   167
        }        
jens@20
   168
    }
jens@20
   169
    // At this point, the cellFrame has been modified to exclude the portion for the image. Let the superclass handle the hit testing at this point.
jens@20
   170
    return [super hitTestForEvent:event inRect:cellFrame ofView:controlView];    
jens@20
   171
}
jens@20
   172
jens@20
   173
jens@20
   174
@end
jens@20
   175