• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Showing a button's menu after a delay
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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


References: 
 >Showing a button's menu after a delay (From: Graham Cox <email@hidden>)

  • Prev by Date: Re: Is there a more efficient way to get the first 4 bytes off a NSInputStream to compare
  • Next by Date: Re: Modal Sheet without Spaghetti?
  • Previous by thread: Showing a button's menu after a delay
  • Next by thread: XCode Debugger - a couple of questions from newbie
  • Index(es):
    • Date
    • Thread