pan gesture recognise button issue - objective-c

I set a pan gesture recogniser to recognise my touch on some buttons and am running into the following issue. I am trying to add an action to each of the buttons. I'm testing this by telling each different button to become highlighted when I touch them. So far when I keep my finger pressed on the screen en slide around only button1 and button2 show up (as written in the code).
But for some reason I can still see other buttons highlight the same way when I press them individually. Any idea how to solve this so that they only respond to. If button.tag == 3 etc.. Then respond? Here is the code. (This is all the code in the project and a few buttons in the interface builder.)
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Add Gesture to track the finger
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePanGesture:)];
[self.view addGestureRecognizer:pan];
}
- (void)handlePanGesture:(UIPanGestureRecognizer *)gesture
{
if (gesture.state == UIGestureRecognizerStateChanged) {
CGPoint point = [gesture locationInView:self.view];
for (UIButton *button in [self.view subviews]) {
if ([button isKindOfClass:[UIButton class]]) {
if (button.tag == 1) {
button.highlighted = CGRectContainsPoint(button.frame, point);
} else if (button.tag == 2) {
button.highlighted = CGRectContainsPoint(button.frame, point);
} //
}
}
}
else if (gesture.state == UIGestureRecognizerStateEnded)
{
for (UIButton *button in [self.view subviews]) {
if ([button isKindOfClass:[UIButton class]]) {
button.highlighted = NO;
}
}
}
}
EDIT :
[[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePanned:)];
- (void)handlePanned:(UIPanGestureRecognizer*)thePanner{
if (thePanner.state == UIGestureRecognizerStateChanged ){
//disable button
}else if (thePanner.state == UIGestureRecognizerStateEnded) {
//enable button
}else if ( thePanner.state == UIGestureRecognizerStateFailed ){
//enable button
}
}

You aren't checking to see if where you are touching is where a button is located.
Quickest solution I see is:
Create properties for each of your buttons, we'll call them button1, button2 and button3.
Create your panGestureRecognizer
- (void)viewDidLoad
{
[super viewDidLoad];
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePanGesture:)];
[self.view addGestureRecognizer:pan];
}
Your method to handle the pan:
-(void)handlePanGesture:(UIPanGestureRecognizer *)gesture
{
//create a CGpoint so you know where you are touching
CGPoint touchPoint = [gesture locationInView:self.view];
//just to show you where you are touching...
NSLog(#"%#", NSStringFromCGPoint(touchPoint));
//check your button frame's individually to see if you are touching inside it
if (CGRectContainsPoint(self.button1.frame, touchPoint))
{
NSLog(#"you're panning button1");
}
else if(CGRectContainsPoint(self.button2.frame, touchPoint))
{
NSLog(#"you're panning button2");
}
else if (CGRectContainsPoint(self.button3.frame, touchPoint))
{
NSLog(#"you're panning button3");
}
And that should be it.

Related

Capture dragging outside of UIControl -- UILongPressGestureRecognizer

I'm trying to implement an async voice recording feature. There's a button that has a UILongPressGestureRecognizer and this starts the recording. Right now, when they let go, the recording is saved and sent.
#pragma mark - Actions
- (void) recordButtonPressed:(UILongPressGestureRecognizer *)gesture
{
if (gesture.state == UIGestureRecognizerStateBegan) {
[self.voiceRecorderView.recordButton setImage:[UIImage imageNamed:kWSGreyDotXLarge] forState:UIControlStateNormal];
[self startRecording];
}
if (gesture.state == UIGestureRecognizerStateEnded) {
[self stopRecording];
[self.voiceRecorderView.recordButton setImage:[UIImage imageNamed:kWSPinkDotXLarge] forState:UIControlStateNormal];
}
}
This works, but now I need to copy the now standard feature of allowing the user to drag their finger off the button while it's pressed to cancel the recording.
How to add a gestureRecognizer to tell if a user drags outside the control but is still pressing it?
I hope it will work for you....
BOOL cancelflag;
UIButton *recordBtn;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleLongPress:)];
[longPress setDelegate:self];
[recordBtn addGestureRecognizer:longPress];
}
-(void)handleLongPress:(UILongPressGestureRecognizer *)longPressRecognizer
{
if(longPressRecognizer.state == UIGestureRecognizerStateBegan)
{
if (!stopBtnFlag)
{
if (!audioRecorder.recording)
{
[self performSelectorOnMainThread:#selector(setUpAudioRecorder) withObject:nil waitUntilDone:YES];
[audioRecorder record];
NSLog(#"Recording...");
}
stopBtnFlag = YES;
cancelflag =YES;
}
}
else if (longPressRecognizer.state == UIGestureRecognizerStateChanged)
{
[audioRecorder stop];
stopBtnFlag = NO;
NSLog(#"moved");
}
else if (longPressRecognizer.state == UIGestureRecognizerStateEnded)
{
if(cancelflag)
{
[audioRecorder stop];
[self playmusic];
}
}
}
#Jaleel's answer gave me a start. Here's a complete working version:
- (void) recordButtonPressed:(UILongPressGestureRecognizer *)gesture
{
if (gesture.state == UIGestureRecognizerStateBegan) {
[self.voiceRecorderView setCancelText:WSCancelLabelTextStart];
if (!audioRecorder.recording)
{
[self startRecording];
}
cancelflag = NO;
}
else if (gesture.state == UIGestureRecognizerStateChanged)
{
CGPoint touchPoint = [gesture locationInView:self.voiceRecorderView];
if (!CGRectContainsPoint(self.voiceRecorderView.recordButton.frame, touchPoint )) {
cancelflag = YES;
[self.voiceRecorderView.recordButton setImage:[UIImage imageNamed:kWSGreyDotXLarge] forState:UIControlStateNormal];
[self.voiceRecorderView setCancelText:WSCancelLabelTextCancelling];
}
else {
cancelflag = NO;
[self.voiceRecorderView.recordButton setImage:[UIImage imageNamed:kWSPinkDotXLarge] forState:UIControlStateNormal];
[self.voiceRecorderView setCancelText:WSCancelLabelTextStart];
}
}
else if (gesture.state == UIGestureRecognizerStateEnded) {
[self stopRecording];
if(!cancelflag)
{
[self sendRecording:self.recordingURL];
}
else {
[self.voiceRecorderView setCancelText:WSCancelLabelTextCancelled];
}
[self.voiceRecorderView resetView];
}
}

UITABLEVIEW call insert method when tapped

I already have my insert method as well as editing. But what I wanted to know is how to recognise a touch event when tapping only the tablview to insert? This is similar to the Reminders app where you could touch anywhere within the UITableView to insert a new record.
UITableView *tableView = mytableview;
CGPoint tableLocation = [touch locationInView:tableView];
// this one recognises when I edit a record on a UITableview
if([touch.view isKindOfClass:[UITableViewCell class]]) {
return NO;
}
if([touch.view.superview isKindOfClass:[UITableViewCell class]]) {
return NO;
}
if([touch.view.superview.superview isKindOfClass:[UITableViewCell class]]) {
return NO;
}
// this one recognises if I tap on a UITableView
if ([tableView hitTest:tableLocation withEvent:Nil]) {
//differentiate scrolling from tapping to invoke add method
}
else
{
}
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
//check if your gesture is only TAP so you could scroll the uitableview
if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
//making sure when you tap, you only tap within the uitableview
UITableView *lemak_table = datetable;
CGPoint tapaw_Kopi = [gestureRecognizer locationInView:lemak_table];
if ([lemak_table hitTest:tapaw_Kopi withEvent:Nil]) {
//Check if table is in editmode so you could tap buttons like "delete"
if (![lemak_table isEditing]) {
//INSERT METHOD HERE and NOWHERE ELSE FOR THAT MATTER.
}
}
}
return YES;
}
// I also added this method so you could edit exisiting records per row/cell thus differentiating TAP to Add from TAP to edit.
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch: (UITouch *)touch
{
if([touch.view isKindOfClass:[UITableViewCell class]]) {
return NO;
}
if([touch.view.superview isKindOfClass:[UITableViewCell class]]) {
return NO;
}
if([touch.view.superview.superview isKindOfClass:[UITableViewCell class]]) {
return NO;
}
return YES;
}

UIWebView addSubview:UIImageView not displaying when triggered by touch events

A new day, a new question!
I have been working on an app that requires I show a circle where the users finger(s) is(are) when they are touching the screen.
I have followed a tutorial I found on subclassing UIWindow, and my comment explains how to pass on those touches if you are using Storyboards and ARC.
I am using the following code (which is based on this tutorial) to make a touch indicator to display:
#pragma mark - Touch Events
- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
NSArray *subviews = [self.webView subviews];
for (UIView *view in subviews)
{
// Check if view is scrollview
if ([view isKindOfClass:[UserTouchImageView class]])
{
[view removeFromSuperview];
}
}
// Enumerate over all the touches and draw a red dot on the screen where the touches were
[touches enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
// Get a single touch and it's location
UITouch *touch = obj;
CGPoint touchPoint = [touch locationInView:self.webView];
// Add touch indicator
UserTouchImageView *touchView = [[UserTouchImageView alloc] initWithFrame:CGRectMake(touchPoint.x -15, touchPoint.y -15, 30, 30)];
[self.webView addSubview:touchView];
}];
NSLog(#"Touches began");
}
- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
NSArray *subviews = [self.webView subviews];
for (UIView *view in subviews)
{
// Check if view is scrollview
if ([view isKindOfClass:[UserTouchImageView class]])
{
[view removeFromSuperview];
}
}
// Enumerate over all the touches and draw a red dot on the screen where the touches were
[touches enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
// Get a single touch and it's location
UITouch *touch = obj;
CGPoint touchPoint = [touch locationInView:self.webView];
// Draw a red circle where the touch occurred
UserTouchImageView *touchView = [[UserTouchImageView alloc] initWithFrame:CGRectMake(touchPoint.x -15, touchPoint.y -15, 30, 30)];
[self.webView addSubview:touchView];
}];
NSLog(#"Touches moved");
}
- (void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
NSArray *subviews = [self.webView subviews];
for (UIView *view in subviews)
{
// Check if view is scrollview
if ([view isKindOfClass:[UserTouchImageView class]])
{
[UIView animateWithDuration:0.5f
animations:^{
view.alpha = 0.0;
}
completion:^(BOOL finished) {
[view removeFromSuperview];
}];
}
}
NSLog(#"Touches ended");
}
- (void) touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event {
NSArray *subviews = [self.webView subviews];
for (UIView *view in subviews)
{
// Check if view is scrollview
if ([view isKindOfClass:[UserTouchImageView class]])
{
[view removeFromSuperview];
}
}
NSLog(#"Touches cancelled");
}
UserTouchImageView is a subclass of UIImageView, with the change to the default being:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
self.image = [UIImage imageNamed:#"greyCircle.png"];
self.alpha = 0.5f;
}
return self;
}
I've tested this code without a UIWebview (replacing the self.webView with self.view), and it works fine, drawing the circle where I click and drag, then fading out when I release the button.
I have also succeeded in instantiating the UserTouchImageView and adding it to the webView from the viewDidLoad method of the viewController.
As soon as I put the UIWebview in with the code above, the same line ([self.webView addSubview:touchView];) doesn't work. I still get the NSLog messages to the console, but the subview doesn't get visibly added.
Can anyone help me figure out why this doesn't appear? Is there any other code I need to be aware of, or any reason why I cannot do this?
Many thanks!
EDIT
I have uploaded my source so far here (MediaFire)
EDIT 2
I've added two methods as below:
-(void)listWebViewSubViews
{
NSLog(#"BEGIN LISTING SUBVIEWS");
for (UIView *view in [self.webView subviews]) {
NSLog(#"Subview: %#", view.description);
}
NSLog(#"END LISTING SUBVIEWS");
}
-(void)view:(UIView *)view addTouchIndicatorWithCentreAtPoint:(CGPoint)point
{
NSLog(#"View: %#, x: %f, y: %f", view.description, point.x, point.y);
// Add touch indicator
UserTouchImageView *touchView = [[UserTouchImageView alloc] initWithFrame:CGRectMake(point.x -15, point.y -15, 30, 30)];
[view addSubview:touchView];
}
These are called from two buttons outside the UIWebView, and from within the touchesbegan method:
- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
NSArray *subviews = [self.webView subviews];
for (UIView *view in subviews)
{
if ([view isKindOfClass:[UserTouchImageView class]])
{
[view removeFromSuperview];
}
}
[touches enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
UITouch *touch = obj;
CGPoint touchPoint = [touch locationInView:self.webView];
[self view:self.webView addTouchIndicatorWithCentreAtPoint:touchPoint];
[self listWebViewSubViews];
}];
NSLog(#"Touches began");
}
The logging seems to indicate that the webview referenced by self.webView WITHIN the touches began method is an entirely seperate instance than the one when referenced from the two buttons. I can add multiple subviews via the button, and then list them, and they all show up in the logging, yet when I click to touch on the simulator, none of these extra subviews get listed.
Does anyone know of any special functionality in a UIWebView to have a duplicate instance on touch events?
A UIWebView is not one view but a collection of views. When you add a subview to a UIWebView the new subview is added to a hierarchy of subviews. Your new subview is probably being added behind other opaque views. It's there, but hidden. I'd recommend adding this indicator view to a different view in the hierarchy.
The default value of userInteractionEnabled for UIImageView is NO. You may need to set it to YES.
Problem solved:
Unfortunately this was caused by somethign entirely different, so thank you everyone for the help you've given.
The problem for this arose from my attempt to fix the code to run with storyboards. I had tried to access the view controller from the storyboard, and add that as the view to receive touch events as a priority (see the tutorial I linked to, and my comment, which I have also responded to). Where as I should have been using self.window.rootViewController.
My updated comment is here

Is there any notification that gets sent when the Keyboard changes (like from NumberPad to Default)

I am trying to figure out how I can get notified when the keyboard changes. What I am trying to do is add a DONE button to keyboard of type 4 & 5 (NumberPad and PhonePad), everything is working fine, except when I transition from a TextField using a Default KB type, The notification that the KeyboardDidAppear isn't being fired.
Here is what I got:
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardDidShow:)
name:UIKeyboardDidShowNotification
object:nil];
}
Then I added a Property for the current KB type and the current TextField being edited:
#pragma mark - Delegate Methods
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
self.currentKBType = textField.keyboardType;
self.curTextField = textField;
return YES;
}
I then make a decision on whether or not to add that DONE button based on the current KB type:
- (void)keyboardDidShow:(NSNotification *)note {
if (self.currentKBType == 4 || self.currentKBType == 5) {
[self addButtonToKeyboard];
}
}
Problem is that the notification fires when the keyboard is displayed, but not when it changes (transitions from one TextField to another that specifies a different KB type.
Any suggestions? Am I missing something?
Got this figured out. Took a little logic, but it works flawlessly. Here is what I did:
Added private properties for:
#property (nonatomic) UIKeyboardType currentKBType;
#property(nonatomic,strong) UITextField *curTextField;
#property(nonatomic,strong) UIButton *doneButton;
#property(nonatomic) BOOL doneButtonDisplayed;
Then added the following logic in the both the TextField delegate method:
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
self.currentKBType = textField.keyboardType;
if (textField.keyboardType == 4 || textField.keyboardType == 5) {
if (!doneButtonDisplayed) {
[self addButtonToKeyboard];
}
} else {
if (doneButtonDisplayed) {
[self removeButtonFromKeyboard];
}
}
self.curTextField = textField;
return YES;
}
And in the KeyboardDidShowNotification that I signed the VC up for in the viewDidLoad:
- (void)keyboardDidShow:(NSNotification *)note {
if (self.currentKBType == 4 || self.currentKBType == 5) {
if (!doneButtonDisplayed) {
[self addButtonToKeyboard];
}
} else {
if (doneButtonDisplayed) {
[self removeButtonFromKeyboard];
}
}
}
And the two methods referenced in these methods:
- (void)addButtonToKeyboard {
// create custom button
doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
doneButton.frame = CGRectMake(0, 163, 106, 53);
doneButton.adjustsImageWhenHighlighted = NO;
[doneButton setImage:[UIImage imageNamed:#"DoneNormal.png"] forState:UIControlStateNormal];
[doneButton setImage:[UIImage imageNamed:#"DoneHL.png"] forState:UIControlStateHighlighted];
[doneButton addTarget:self action:#selector(resignKeyboard) forControlEvents:UIControlEventTouchUpInside];
// locate keyboard view
if ([[[UIApplication sharedApplication] windows] count] > 1) {
UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
UIView* keyboard;
for(int i=0; i<[tempWindow.subviews count]; i++) {
keyboard = [tempWindow.subviews objectAtIndex:i];
// keyboard found, add the button
if([[keyboard description] hasPrefix:#"<UIPeripheralHost"] == YES) {
[keyboard addSubview:doneButton];
self.doneButtonDisplayed = YES;
}
}
}
}
- (void)removeButtonFromKeyboard {
[doneButton removeFromSuperview];
self.doneButtonDisplayed = NO;
}
And finally, the resignKeyboard method that is called whenever the Done button is touched:
-(void)resignKeyboard {
[self.curTextField resignFirstResponder];
self.doneButtonDisplayed = NO;
}
This will add that Done button whenever a NumberPad or PhonePad type keyboard is displayed and remove it (only when it has been added) from the other keyboard types.
Tested and works great.

NSStatusItem right click menu

I'm working on a status bar app that has a left and right click. I've got the start of this working by following the tips from other posts but I'm not sure how to go about showing a menu on right click.
I use a subclassed NSView as the custom view of my NSStatusItem and have the right and left clicks executing different functions:
- (void)mouseDown:(NSEvent *)theEvent{
[super mouseDown:theEvent];
if ([theEvent modifierFlags] & NSCommandKeyMask){
[self.target performSelectorOnMainThread:self.rightAction withObject:nil waitUntilDone:NO];
}else{
[self.target performSelectorOnMainThread:self.action withObject:nil waitUntilDone:NO];
}
}
- (void)rightMouseDown:(NSEvent *)theEvent{
[super rightMouseDown:theEvent];
[self.target performSelectorOnMainThread:self.rightAction withObject:nil waitUntilDone:NO];
}
How can I show a menu on right click, the same way the standard NSStatusItem does on left click?
NSStatusItem popUpStatusItemMenu: did the trick. I am calling it from my right click action and passing in the menu I want to show and it's showing it! This is not what I would have expected this function to do, but it's working.
Here's the important parts of what my code looks like:
- (void)showMenu{
// check if we are showing the highlighted state of the custom status item view
if(self.statusItemView.clicked){
// show the right click menu
[self.statusItem popUpStatusItemMenu:self.rightClickMenu];
}
}
// menu delegate method to unhighlight the custom status bar item view
- (void)menuDidClose:(NSMenu *)menu{
[self.statusItemView setHighlightState:NO];
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification{
// setup custom view that implements mouseDown: and rightMouseDown:
self.statusItemView = [[ISStatusItemView alloc] init];
self.statusItemView.image = [NSImage imageNamed:#"menu.png"];
self.statusItemView.alternateImage = [NSImage imageNamed:#"menu_alt.png"];
self.statusItemView.target = self;
self.statusItemView.action = #selector(mainAction);
self.statusItemView.rightAction = #selector(showMenu);
// set menu delegate
[self.rightClickMenu setDelegate:self];
// use the custom view in the status bar item
self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
[self.statusItem setView:self.statusItemView];
}
Here is the implementation for the custom view:
#implementation ISStatusItemView
#synthesize image = _image;
#synthesize alternateImage = _alternateImage;
#synthesize clicked = _clicked;
#synthesize action = _action;
#synthesize rightAction = _rightAction;
#synthesize target = _target;
- (void)setHighlightState:(BOOL)state{
if(self.clicked != state){
self.clicked = state;
[self setNeedsDisplay:YES];
}
}
- (void)drawImage:(NSImage *)aImage centeredInRect:(NSRect)aRect{
NSRect imageRect = NSMakeRect((CGFloat)round(aRect.size.width*0.5f-aImage.size.width*0.5f),
(CGFloat)round(aRect.size.height*0.5f-aImage.size.height*0.5f),
aImage.size.width,
aImage.size.height);
[aImage drawInRect:imageRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0f];
}
- (void)drawRect:(NSRect)rect{
if(self.clicked){
[[NSColor selectedMenuItemColor] set];
NSRectFill(rect);
if(self.alternateImage){
[self drawImage:self.alternateImage centeredInRect:rect];
}else if(self.image){
[self drawImage:self.image centeredInRect:rect];
}
}else if(self.image){
[self drawImage:self.image centeredInRect:rect];
}
}
- (void)mouseDown:(NSEvent *)theEvent{
[super mouseDown:theEvent];
[self setHighlightState:!self.clicked];
if ([theEvent modifierFlags] & NSCommandKeyMask){
[self.target performSelectorOnMainThread:self.rightAction withObject:nil waitUntilDone:NO];
}else{
[self.target performSelectorOnMainThread:self.action withObject:nil waitUntilDone:NO];
}
}
- (void)rightMouseDown:(NSEvent *)theEvent{
[super rightMouseDown:theEvent];
[self setHighlightState:!self.clicked];
[self.target performSelectorOnMainThread:self.rightAction withObject:nil waitUntilDone:NO];
}
- (void)dealloc{
self.target = nil;
self.action = nil;
self.rightAction = nil;
[super dealloc];
}
#end
One option is to just fake the left mouse down:
- (void)rightMouseDown: (NSEvent *)event {
NSEvent * newEvent;
newEvent = [NSEvent mouseEventWithType:NSLeftMouseDown
location:[event locationInWindow]
modifierFlags:[event modifierFlags]
timestamp:CFAbsoluteTimeGetCurrent()
windowNumber:[event windowNumber]
context:[event context]
eventNumber:[event eventNumber]
clickCount:[event clickCount]
pressure:[event pressure]];
[self mouseDown:newEvent];
}
Added little something for when you need title in your view
- (void)drawRect:(NSRect)rect{
if(self.clicked){
[[NSColor selectedMenuItemColor] set];
NSRectFill(rect);
if(self.alternateImage){
[self drawImage:self.alternateImage centeredInRect:rect];
}else if(self.image){
[self drawImage:self.image centeredInRect:rect];
} else {
[self drawTitleInRect:rect];
}
} else if(self.image){
[self drawImage:self.image centeredInRect:rect];
} else {
[self drawTitleInRect:rect];
}
}
-(void)drawTitleInRect:(CGRect)rect
{
CGSize size = [_title sizeWithAttributes:nil];
CGRect newRect = CGRectMake(MAX((rect.size.width - size.width)/2.f,0.f),
MAX((rect.size.height - size.height)/2.f,0.f),
size.width,
size.height);
NSDictionary *attributes = #{NSForegroundColorAttributeName : self.clicked?[NSColor highlightColor]:[NSColor textColor]
};
[_title drawInRect:newRect withAttributes:attributes];
}
- (void)statusItemAction {
NSEvent *event = NSApp.currentEvent;
if (event.type == NSEventTypeRightMouseDown || (event.modifierFlags & NSEventModifierFlagControl)) {
[self toggleMenu];
} else {
[self togglePopOver];
}
}