* 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 "AIHoveringPopUpButton.h" #import "AIHoveringPopUpButtonCell.h" @interface AIHoveringPopUpButton () - (void)frameDidChange:(NSNotification *)inNotification; @implementation AIHoveringPopUpButton if (self == [AIHoveringPopUpButton class]) [self setCellClass:[AIHoveringPopUpButtonCell class]]; - (void)initHoveringPopUpButton [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(frameDidChange:) name:NSViewFrameDidChangeNotification [self setPostsFrameChangedNotifications:YES]; highlightOnHoverAndClick = YES; - (id)initWithFrame:(NSRect)inFrame if ((self = [super initWithFrame:inFrame])) { [self initHoveringPopUpButton]; if ([[AIHoveringPopUpButton superclass] instancesRespondToSelector:@selector(awakeFromNib)]) { [self initHoveringPopUpButton]; - (id)copyWithZone:(NSZone *)zone AIHoveringPopUpButton *newButton = [[[self class] allocWithZone:zone] initWithFrame:[self frame]]; [newButton setMenu:[[[self menu] copy] autorelease]]; - (void)setMenu:(NSMenu *)menu { [[self cell] setMenu:menu]; - (void)setDoubleAction:(SEL)inDoubleAction doubleAction = inDoubleAction; [[NSNotificationCenter defaultCenter] removeObserver:self]; [self removeTrackingRect:trackingTag]; //Mouse Tracking ------------------------------------------------------------------------------------------------------- #pragma mark Mouse Tracking //Custom mouse down tracking to display our menu and highlight - (void)mouseDown:(NSEvent *)theEvent if (doubleAction && (([theEvent clickCount] % 2) == 0)) { [[self target] performSelector:doubleAction [super mouseDown:theEvent]; [self setNeedsDisplay:YES]; //2 pt down, 1 pt to the left. NSPoint point = [self convertPoint:[self bounds].origin toView:nil]; point.y -= NSHeight([self frame]) + 2; NSEvent *event = [NSEvent mouseEventWithType:[theEvent type] modifierFlags:[theEvent modifierFlags] timestamp:[theEvent timestamp] windowNumber:[[theEvent window] windowNumber] context:[theEvent context] eventNumber:[theEvent eventNumber] clickCount:[theEvent clickCount] pressure:[theEvent pressure]]; [NSMenu popUpContextMenu:[self menu] withEvent:event forView:self]; [self mouseUp:[[NSApplication sharedApplication] currentEvent]]; * @brief Only pass on a highlight message if we're highlighting on click or this is turning off a highlight - (void)highlight:(BOOL)inFlag if (!inFlag || highlightOnHoverAndClick) { [super highlight:inFlag]; //Remove highlight on mouse up - (void)mouseUp:(NSEvent *)theEvent [super mouseUp:theEvent]; - (void)mouseDragged:(NSEvent *)theEvent - (NSView *)hitTest:(NSPoint)aPoint NSRect myFrame = [self frame]; myFrame.size.width = [[self cell] trackingWidth]; if (NSPointInRect(aPoint, myFrame)) { return [super hitTest:aPoint]; - (void)setTitle:(NSString *)inTitle [[self cell] setTitle:inTitle]; [self setNeedsDisplay:YES]; - (void)setFont:(NSFont *)inFont [[self cell] setFont:inFont]; [self setNeedsDisplay:YES]; - (void)setImage:(NSImage *)inImage [[self cell] setImage:inImage]; [self setNeedsDisplay:YES]; - (void)setHighlightOnHoverAndClick:(BOOL)inHighlightOnHoverAndClick highlightOnHoverAndClick = inHighlightOnHoverAndClick; //If we are not going to highlight, ensure we're not currently doing so if (!highlightOnHoverAndClick) { [[self cell] setHovered:NO animate:NO]; [self setNeedsDisplay:YES]; #pragma mark Tracking rects //Remove old tracking rects when we change superviews - (void)viewWillMoveToSuperview:(NSView *)newSuperview [self removeTrackingRect:trackingTag]; [super viewWillMoveToSuperview:newSuperview]; - (void)viewDidMoveToSuperview [super viewDidMoveToSuperview]; - (void)viewWillMoveToWindow:(NSWindow *)newWindow [self removeTrackingRect:trackingTag]; [super viewWillMoveToWindow:newWindow]; - (void)viewDidMoveToWindow [super viewDidMoveToWindow]; - (void)frameDidChange:(NSNotification *)inNotification return NSMakeRect(0, 0, [[self cell] trackingWidth], [self frame].size.height); //Reset our cursor tracking //Stop any existing tracking [self removeTrackingRect:trackingTag]; //Add a tracking rect if our superview and window are ready if ([self superview] && [self window]) { NSRect myFrame = [self frame]; NSRect trackRect = [self trackingRect]; if (trackRect.size.width > myFrame.size.width) { trackRect.size.width = myFrame.size.width; NSPoint localPoint = [self convertPoint:[[self window] convertScreenToBase:[NSEvent mouseLocation]] BOOL mouseInside = NSPointInRect(localPoint, trackRect); trackingTag = [self addTrackingRect:trackRect owner:self userData:nil assumeInside:mouseInside]; //Cursor entered our view - (void)mouseEntered:(NSEvent *)theEvent if (highlightOnHoverAndClick && ![[self cell] hovered]) { [[self cell] setHovered:YES animate:YES]; [self setNeedsDisplay:YES]; [super mouseEntered:theEvent]; - (void)mouseExited:(NSEvent *)theEvent if (highlightOnHoverAndClick && [[self cell] hovered]) { [[self cell] setHovered:NO animate:YES]; [self setNeedsDisplay:YES]; [super mouseExited:theEvent];