Re: Showing a button's menu after a delay
Re: Showing a button's menu after a delay
- Subject: Re: Showing a button's menu after a delay
- From: Graham Cox <email@hidden>
- Date: Wed, 28 Jan 2009 14:38:29 +1100
On 28 Jan 2009, at 12:33 pm, Graham Cox wrote:
I have a matrix of buttons. One of the buttons has some options in a
pop-up menu. I can right-click to show this menu, but I think it
would be nicer if I could also show the menu after a short delay
even on a left-click, as it would then be more obvious that the
options are there. The delay is needed because the buttons are
selected in radio fashion, and merely clicking the button shouldn't
immediately show the menu.
I'm sure I've seen this done, but it's not clear how to go about it.
I have got it almost working in a custom button cell subclass, but
there's a problem with dealing with the mouse up at the end of
tracking. Here's the relevant code:
- (BOOL) startTrackingAt:(NSPoint) startPoint inView:(NSView*)
controlView
{
// if there is a menu and show after delay is YES, start a timer for
showing the menu
if([self menu] && [self showsMenuAfterDelay])
{
NSTimer* menuTimer = [NSTimer timerWithTimeInterval:1.0 target:self
selector:@selector(menuDelayCallback:) userInfo:nil repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:menuTimer
forMode:NSEventTrackingRunLoopMode];
[[NSRunLoop currentRunLoop] addTimer:menuTimer
forMode:NSDefaultRunLoopMode];
mMouseDownPoint = [controlView convertPoint:startPoint toView:nil];
}
return [super startTrackingAt:startPoint inView:controlView];
}
- (void) menuDelayCallback:(NSTimer*) timer
{
#pragma unused(timer)
// show the cell's menu if still highlighted
if([self isHighlighted])
{
// pop up the menu and switch tracking to it.
NSMenu* menu = [self menu];
NSEvent* event = [NSApp currentEvent];
[NSMenu popUpContextMenu:menu withEvent:event forView:[self
controlView]];
NSWindow* window = [[self controlView] window];
// on return, post a mouse-up so that the cell tracking completes as
normal.
NSEvent* fakeMouseUp = [NSEvent mouseEventWithType:NSLeftMouseUp
location:mMouseDownPoint
modifierFlags:0
timestamp:[NSDate timeIntervalSinceReferenceDate]
windowNumber:[window windowNumber]
context:[NSGraphicsContext currentContext]
eventNumber:0
clickCount:1
pressure:0.0];
[window postEvent:fakeMouseUp atStart:YES];
}
}
NSMatrix appears to have its own tracking loop, which highlights the
buttons as you drag. This is what is triggering -startTrackingAt: I
start a timer and in the callback I directly pop-up the menu. The menu
starts
another tracking loop so now I have two nested tracking loops. The
menu shows and works as normal. When the menu tracking loop returns, I
need to pass a mouse up to the outer (matrix) tracking loop to cause
it to exit properly (there is only one mouse up in reality, but the
menu tracking discarded that event). So I fake up a mouse up and post
it, and that seems to do the trick.
The problem I'm having is that the matrix doesn't select my button.
The fake mouse up uses the same mouse location as the original mouse
down, so it should see the mouse up as being within the button, but it
just unhighlights it leaving no selection in the matrix. In fact the
controller code that makes use of the button selection works normally
so all I'm lacking is this piece of user feedback.
I have tried simply forcing the cell's state to ON, or sending the
cell's action to its target, but to no avail. The mouse-up event gets
processed after these so they have no effect.
I feel I'm fumbling in the dark trying to understand what's going on
inside NSMatrix's tracking loop so I can do this cleanly (the fake
mouse up is a wee bit nasty but I can't discover an alternative that
comes close to doing the right thing).
Anyone able to push me in the right direction here?
--Graham
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden