* Adium is the legal property of its developers, whose names are listed in the copyright file included * with this source distribution. * This program is free software; you can redistribute it and/or modify it under the terms of the GNU * General Public License as published by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * You should have received a copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #import "AIHoveringPopUpButtonCell.h" #import <AIUtilities/AIParagraphStyleAdditions.h> #import <AIUtilities/AIBezierPathAdditions.h> #import <AIUtilities/AIColorAdditions.h> #import <AIUtilities/AIImageDrawingAdditions.h> #define ARROW_HEIGHT (ARROW_WIDTH/2.0f) @implementation AIHoveringPopUpButtonCell statusParagraphStyle = [[NSMutableParagraphStyle styleWithAlignment:NSLeftTextAlignment lineBreakMode:NSLineBreakByTruncatingTail] retain]; statusAttributes = [[NSMutableDictionary dictionaryWithObjectsAndKeys: statusParagraphStyle, NSParagraphStyleAttributeName, [NSFont systemFontOfSize:10], NSFontAttributeName, - (id)initTextCell:(NSString *)str if ((self = [super initTextCell:str])) { - (id)initImageCell:(NSImage *)image if ((self = [super initImageCell:image])) { - (id)copyWithZone:(NSZone *)zone AIHoveringPopUpButtonCell *newCell = [[self class] allocWithZone:zone]; newCell = [newCell initImageCell:[self image]]; newCell = [newCell initTextCell:[self stringValue]]; newCell = [newCell init]; //and hope for the best [newCell setMenu:[[[self menu] copy] autorelease]]; [newCell->currentImage retain]; [newCell->statusParagraphStyle retain]; [newCell->statusAttributes retain]; /* Super's implementation calls setImage:nil in 10.4; we shouldn't depend on this implementation detail but should * set our ivars to nil to ensure we don't double-release. [title release]; title = nil; [currentImage release]; currentImage = nil; [statusParagraphStyle release]; [statusAttributes release]; - (void)setTitle:(NSString *)inTitleString inTitleString = [inTitleString stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\n\r"]]; if (inTitleString && [inTitleString length]) { title = [[NSMutableAttributedString alloc] initWithString:inTitleString attributes:statusAttributes]; - (void)setFont:(NSFont *)inFont NSString *oldTitleString = [[title string] copy]; [statusAttributes setObject:inFont forKey:NSFontAttributeName]; [self setTitle:oldTitleString]; [oldTitleString release]; -(void)setImage:(NSImage *)inImage if (inImage != currentImage) { currentImage = [inImage retain]; imageSize = [currentImage size]; - (void)fadeHovered:(NSControl *)currentControlView if (hoveredFraction < 1.0) hoveredFraction += 0.05f; if (hoveredFraction > 0.0) hoveredFraction -= 0.05f; [currentControlView setNeedsDisplay:YES]; if ((hoveredFraction > 0.0) && (hoveredFraction < 1.0)) { [currentControlView retain]; [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(fadeHovered:) object:currentControlView]; [self performSelector:@selector(fadeHovered:) withObject:currentControlView [currentControlView release]; - (void)setHovered:(BOOL)inHovered animate:(BOOL)animate if (animate && (hovered != inHovered)) { hoveredFraction = (hovered ? 0.80f : 0.20f); [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(fadeHovered:) object:[self controlView]]; [self performSelector:@selector(fadeHovered:) withObject:[self controlView] hoveredFraction = (hovered ? 1.0f : 0.0f); [[self controlView] setNeedsDisplay:YES]; //for some unknown reason, NSButtonCell's -drawWithFrame:inView: draws a basic ridge border on the bottom-right if we do not override it. - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView [self drawInteriorWithFrame:cellFrame inView:controlView]; trackingWidth = LEFT_MARGIN + [title size].width + RIGHT_MARGIN; trackingWidth += ARROW_XOFFSET + ARROW_WIDTH; trackingWidth += imageSize.width + IMAGE_MARGIN; - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView NSMenu *myMenu = [self menu]; [statusParagraphStyle setMaximumLineHeight:cellFrame.size.height]; textRect = NSMakeRect(cellFrame.origin.x + LEFT_MARGIN, cellFrame.origin.y + ((cellFrame.size.height - textSize.height) / 2), maxTextWidth = (cellFrame.size.width - LEFT_MARGIN - RIGHT_MARGIN); textRect.origin.x += (imageSize.width + IMAGE_MARGIN); maxTextWidth -= (imageSize.width + IMAGE_MARGIN); maxTextWidth -= (ARROW_XOFFSET + ARROW_WIDTH); if (textRect.size.width > maxTextWidth) { textRect.size.width = maxTextWidth; if (hovered || (hoveredFraction > 0.0)) { //Draw our hovered / highlighted background first CGFloat backgroundWidth = LEFT_MARGIN + textRect.size.width + RIGHT_MARGIN; backgroundWidth += (ARROW_XOFFSET + ARROW_WIDTH); backgroundWidth += imageSize.width + IMAGE_MARGIN; path = [NSBezierPath bezierPathWithRoundedRect:NSMakeRect(cellFrame.origin.x, if ([self isHighlighted]) { [[[NSColor darkGrayColor] colorWithAlphaComponent:hoveredFraction] set]; [[[NSColor grayColor] colorWithAlphaComponent:hoveredFraction] set]; drawingColor = [NSColor whiteColor]; drawingColor = [NSColor blackColor]; drawingColor = [NSColor blackColor]; [currentImage drawInRect:NSMakeRect(cellFrame.origin.x + LEFT_MARGIN, imageSize.width + IMAGE_MARGIN, position:IMAGE_POSITION_LEFT [statusAttributes setObject:drawingColor forKey:NSForegroundColorAttributeName]; [title setAttributes:statusAttributes range:NSMakeRange(0, [title length])]; [title drawInRect:textRect]; NSBezierPath *arrowPath = [NSBezierPath bezierPath]; [arrowPath moveToPoint:NSMakePoint(NSMaxX(textRect) + ARROW_XOFFSET, (NSMaxY(cellFrame) / 2) - (ARROW_HEIGHT / 2))]; [arrowPath relativeLineToPoint:NSMakePoint(ARROW_WIDTH, 0)]; [arrowPath relativeLineToPoint:NSMakePoint(-(ARROW_WIDTH/2), (ARROW_HEIGHT))];