Prevent sending 0-byte files. Fixes #8711.
[adiumx.git] / Source / AIHoveringPopUpButton.m
blob87f21dd21a4bec2c564985c4be8320538bd92515
1 //
2 //  AIHoveringPopUpButton.m
3 //  Adium
4 //
5 //  Created by Evan Schoenberg on 12/16/05.
6 //
8 #import "AIHoveringPopUpButton.h"
9 #import "AIHoveringPopUpButtonCell.h"
11 @implementation AIHoveringPopUpButton
13 + (void)initialize {
14         [self setCellClass:[AIHoveringPopUpButtonCell class]];
17 - (void)initHoveringPopUpButton
19         [[NSNotificationCenter defaultCenter] addObserver:self 
20                                                                                          selector:@selector(frameDidChange:)
21                                                                                                  name:NSViewFrameDidChangeNotification
22                                                                                            object:self];
23         [self setPostsFrameChangedNotifications:YES];
25         trackingTag = -1;
26         [self resetCursorRects];
28         highlightOnHoverAndClick = YES;
31 - (id)initWithFrame:(NSRect)inFrame
33         if ((self = [super initWithFrame:inFrame])) {
34                 [self initHoveringPopUpButton];
35         }
37         return self;
40 - (void)awakeFromNib
42         if ([[AIHoveringPopUpButton superclass] instancesRespondToSelector:@selector(awakeFromNib)]) {
43         [super awakeFromNib];
44         }
46         [self initHoveringPopUpButton];
50 - (id)copyWithZone:(NSZone *)zone
52         AIHoveringPopUpButton   *newButton = [[[self class] allocWithZone:zone] initWithFrame:[self frame]];
53         
54         [newButton setMenu:[[[self menu] copy] autorelease]];
55         
56         return newButton;
59 //silly NSControl...
60 - (void)setMenu:(NSMenu *)menu {
61         [super setMenu:menu];
62         [[self cell] setMenu:menu];
65 - (void)setDoubleAction:(SEL)inDoubleAction
67         doubleAction = inDoubleAction;
70 - (void)dealloc
72         [[NSNotificationCenter defaultCenter] removeObserver:self];
73         
74         if (trackingTag != -1) {
75                 [self removeTrackingRect:trackingTag];
76                 trackingTag = -1;
77         }
78         
79         [super dealloc];
82 //Mouse Tracking -------------------------------------------------------------------------------------------------------
83 #pragma mark Mouse Tracking
84 //Custom mouse down tracking to display our menu and highlight
85 - (void)mouseDown:(NSEvent *)theEvent
87         if (![self menu]) {
88                 if (doubleAction && (([theEvent clickCount] % 2) == 0)) {
89                         [[self target] performSelector:doubleAction
90                                                                 withObject:self];
91                 } else {
92                         [super mouseDown:theEvent];
93                 }
95         } else {
96                 if ([self isEnabled]) {
97                         [self highlight:YES];
98                                 
99                         [self setNeedsDisplay:YES];
101                         //2 pt down, 1 pt to the left.
102                         NSPoint point = [self convertPoint:[self bounds].origin toView:nil];
103                         point.y -= NSHeight([self frame]) + 2;
104                         point.x -= 1;
105                         
106                         NSEvent *event = [NSEvent mouseEventWithType:[theEvent type]
107                                                                                                 location:point
108                                                                                    modifierFlags:[theEvent modifierFlags]
109                                                                                            timestamp:[theEvent timestamp]
110                                                                                         windowNumber:[[theEvent window] windowNumber]
111                                                                                                  context:[theEvent context]
112                                                                                          eventNumber:[theEvent eventNumber]
113                                                                                           clickCount:[theEvent clickCount]
114                                                                                                 pressure:[theEvent pressure]];
115                         [NSMenu popUpContextMenu:[self menu] withEvent:event forView:self];
116                         
117                         [self mouseUp:[[NSApplication sharedApplication] currentEvent]];
118                 }
119         }
123  * @brief Only pass on a highlight message if we're highlighting on click or this is turning off a highlight
124  */
125 - (void)highlight:(BOOL)inFlag
127         if (!inFlag || highlightOnHoverAndClick) {
128                 [super highlight:inFlag];
129         }
132 //Remove highlight on mouse up
133 - (void)mouseUp:(NSEvent *)theEvent
135         [self highlight:NO];
136         [super mouseUp:theEvent];
139 //Ignore dragging
140 - (void)mouseDragged:(NSEvent *)theEvent
142         //Empty
145 - (NSView *)hitTest:(NSPoint)aPoint
147         NSRect  myFrame = [self frame];
148         myFrame.size.width = [[self cell] trackingWidth];
150         if (NSPointInRect(aPoint, myFrame)) {
151                 return [super hitTest:aPoint];
152         } else {
153                 return nil;
154         }
158  * @brief Set the title
159  */
160 - (void)setTitle:(NSString *)inTitle
162         [[self cell] setTitle:inTitle];
163         [self setNeedsDisplay:YES];
165         [self resetCursorRects];
168 - (void)setFont:(NSFont *)inFont
170         [[self cell] setFont:inFont];
171         [self setNeedsDisplay:YES];
174 - (void)setImage:(NSImage *)inImage
176         [[self cell] setImage:inImage];
177         [self setNeedsDisplay:YES];
178         
179         [self resetCursorRects];        
182 - (void)setHighlightOnHoverAndClick:(BOOL)inHighlightOnHoverAndClick
184         highlightOnHoverAndClick = inHighlightOnHoverAndClick;
185         
186         //If we are not going to highlight, ensure we're not currently doing so
187         if (!highlightOnHoverAndClick) {
188                 [[self cell] setHovered:NO animate:NO];
189                 [self setNeedsDisplay:YES];
190         }
193 #pragma mark Tracking rects
194 //Remove old tracking rects when we change superviews
195 - (void)viewWillMoveToSuperview:(NSView *)newSuperview
197         if (trackingTag != -1) {
198                 [self removeTrackingRect:trackingTag];
199                 trackingTag = -1;
200         }
201         
202         [super viewWillMoveToSuperview:newSuperview];
205 - (void)viewDidMoveToSuperview
207         [super viewDidMoveToSuperview];
208         
209         [self resetCursorRects];
212 - (void)viewWillMoveToWindow:(NSWindow *)newWindow
214         if (trackingTag != -1) {
215                 [self removeTrackingRect:trackingTag];
216                 trackingTag = -1;
217         }
218         
219         [super viewWillMoveToWindow:newWindow];
222 - (void)viewDidMoveToWindow
224         [super viewDidMoveToWindow];
225         
226         [self resetCursorRects];
229 - (void)frameDidChange:(NSNotification *)inNotification
231         [self resetCursorRects];
234 - (NSRect)trackingRect
236         return NSMakeRect(0, 0, [[self cell] trackingWidth], [self frame].size.height);
239 //Reset our cursor tracking
240 - (void)resetCursorRects
242         //Stop any existing tracking
243         if (trackingTag != -1) {
244                 [self removeTrackingRect:trackingTag];
245                 trackingTag = -1;
246         }
247         
248         //Add a tracking rect if our superview and window are ready
249         if ([self superview] && [self window]) {
250                 NSRect  myFrame = [self frame];
251                 NSRect  trackRect = [self trackingRect];
252                 
253                 if (trackRect.size.width > myFrame.size.width) {
254                         trackRect.size.width = myFrame.size.width;
255                 }
257                 NSPoint localPoint = [self convertPoint:[[self window] convertScreenToBase:[NSEvent mouseLocation]]
258                                                                            fromView:nil];
259                 BOOL    mouseInside = NSPointInRect(localPoint, trackRect);
261                 trackingTag = [self addTrackingRect:trackRect owner:self userData:nil assumeInside:mouseInside];
262                 if (mouseInside) {
263                         [self mouseEntered:nil];
264                 } else {
265                         [self mouseExited:nil];                 
266                 }
267         }
270 //Cursor entered our view
271 - (void)mouseEntered:(NSEvent *)theEvent
273         if (highlightOnHoverAndClick && ![[self cell] hovered]) {
274                 [[self cell] setHovered:YES animate:YES];
275                 [self setNeedsDisplay:YES];
276         }
278         [super mouseEntered:theEvent];
282 //Cursor left our view
283 - (void)mouseExited:(NSEvent *)theEvent
285         if (highlightOnHoverAndClick && [[self cell] hovered]) {
286                 [[self cell] setHovered:NO animate:YES];
287                 [self setNeedsDisplay:YES];
288         }
289         
290         [super mouseExited:theEvent];
293 @end