NSMenu's mouse over event - mouseover

I used NSMenu and NSStatusItem to display custom menu on status bar for a long time in this way:
statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:18] retain];
[statusItem setImage:[NSImage imageNamed:#"myIcon"]];
[statusItem setMenu:myMenu];
[statusItem setHighlightMode:NO];
...
It works fine by start clicking its image icon.
But I noticed that apple's menu located on status bar can be triggered simple by mouse move over, like the airport menu, power menu, language menu and date/time menu.
They are all auto pop up when you mouse walk over.
How did they get it?
I have checked the "add tracking rect" for NSView with "mouseEntered" event, but things is not as difficult as that I think.
Any advice?

I think the statusItem is not a supported mouse event,but you can set a view to the statusItem and override the mouse even method to support the mouse event, just like this:
statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];
NSButton *nb = [[NSButton alloc] init];
[nb setImage:image];
[nb setAction:#selector(statusItemClick:)];
[_statusItem setView:nb];
here just an example to set a view to statusitem, if you want to support the mouse event , your view must extend same view and create NSTrackingArea and implement the moveMoved, mouseEntered and mouseExited methods (or whichever ones you want)

Related

How to change UIImageview image by clicking on that image instead of button click in Iphone?

How to change image by click on that image in Iphone.Instead of button click I want to click on image.Which method can I use UIImageView.
Use a button and make your picture the picture for the button. You can do all this in Storyboard and then right click the button and drag to the view you want to go to. It should work just like that.
After you drag the button to the storyboard go to the property inspector. Make the button a custom button in the drop down list and then use the image field to select your image. You will need to size the button correctly and set the fill property to "size to fit." the other button behaviors are all customizable if you don't want normal button behavior, i.e. visually reacting to a touch.
This can be done by using touchevents also
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if ([[touches anyObject] view] == self.m_ImageViewObjectName) {
//Here you can change the image of UIImageView
}
}
You have to set tapRecognizer for your ImageView. It'll detect tap on your ImageView and call the method -clickEventOnImage.
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(clickEventOnImage:)];
[tapRecognizer setNumberOfTouchesRequired:1];
[tapRecognizer setDelegate:self];
//Don't forget to set the userInteractionEnabled to YES, by default It's NO.
myImageView.userInteractionEnabled = YES;
[myImageView addGestureRecognizer:tapRecognizer];
Add your clickEventOnImage: will look like this :
-(void) clickEventOnImage:(id) sender
{
[myImageView setImage:[UIImage imageNamed: #"myNewImageName.png"]];
}

How to add the Navigation Bar's view to a PopOver's PassThroughViews?

I have a PopoverController view that allows a user to download a file. On button press, the popOver view will expand in size, display download status, and the main view controller will be obscured by an unhidden "cover" view that has been added to the PopoverController's "passThroughViews" property so that the user can not accidentally dismiss the pop over while the file is downloading.
My problem is that, in storyboards, my main viewController is embedded in a Navigation Controller. I can't seem to cover the navigation controller's bar with a view in the storyboard, and if the user presses anywhere on the navigation bar then the popover will disappear and the user will lose the download's progress bar.
How do I either cover up the navigation bar with my "cover" view, or how do I add the navigation bar's view to my popOverController's passThroughViews?
Opening the Popover from the main viewController:
- (IBAction)openDataOptionsPopOver:(id)sender
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
PopOverViewController *optionsWindow = [storyboard instantiateViewControllerWithIdentifier:#"dataOptions"];
self.popUp = [[UIPopoverController alloc] initWithContentViewController:optionsWindow];
[self.popUp setDelegate:self];
[nextNavButton setEnabled:NO]; //Disabling barButtonItem on the navigationController
optionsWindow.containerPopOver = self.popUp; //Pointer to the popover, to resize it later.
optionsWindow.coverView = self.coverView; //Pointer to the coverView, to (un)hide later
[popUp presentPopoverFromRect:[sender frame] inView:[sender superview] permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
}
Setting the passThroughViews property inside of the PopoverViewController:
//Expands the popOver on press of "refreshFileButton" to display progressView
-(void) explodeWindow
{
//setting self.navigationController.view and ...visibleViewController.view here didn't seem to work ...
[containerPopOver setPassthroughViews:[NSArray arrayWithObjects:coverView, nil]];
[containerPopOver setPopoverContentSize:CGSizeMake(600, 400) animated:YES];
[titleBarItem setTitle:#"Downloading File. Please Wait ..."];
[refreshFileButton setHidden:YES];
[progressView setHidden:NO];
[downloadLabel setHidden:NO];
[coverView setHidden:NO];
[progressView setProgress:0.0 animated:NO];
}
I've tried adding self.navigationController.view to passThroughViews with no success--it actually turns out to be a null pointer. And I can't seem to place a UIView at any level in storyboards that will cover all my controls without obscuring the popOver. What am I missing here? And thanks for reading.
Edit:
As Aglaia points out below out, implementing the following, and avoiding passThroughViews, is probably the best way to do this.
- (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
//Don't dismiss our popover when the view covering our controls is present
if([coverView isHidden]){
return YES;
}else{
return NO;
}
}
Maybe there is something I am missing, but why don′t you just implement a new view controller with its navigation bar set to none and present it modally on button press? Then when the download is finished you just dismiss the view controller.
If you want the user to see the underlying view you can use a UIAlertView instead.
Alternatively set you view controller as the delegate of the popover controller and forbid the user to dismiss your popover on touch outside through
- (BOOL) popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
return NO;
}
Then when you want to dismiss it call dismissPopoverAnimated:
to cover the whole screen including navigation bar:
[myView setFrame:[[UIScreen mainScreen] bounds];
[self.navigationController.view addSubview:myView];

NSButton in NSToolbarItem (setView) when clicked in "Text only" forces mode to "Icon and Label"

I am trying to recreate the nice textured buttons like Finder, Safari and Transmission have in their toolbar. First I started by just dragging in a "Texture button" in the IB and such. All works well except for when a user sets the toolbar to "Text only" mode. When he then clicks the button the toolbar will enable "Icon and Label" on it's own. I have remove alles code and delegates from the toolbar to make sure it is not a code issue.
Then, just to make sure, I created a new project (no code at all) and I can reproduce the issue with a clean NSWindow with a NSToolbar with one NSToolbarItem with a NSButton in it.
Adding the NSButtons via code like:
- (NSArray*)toolbarAllowedItemIdentifiers:(NSToolbar*)toolbar {
return [NSArray arrayWithObject:#"myToolbarMenu"];
}
- (NSArray*)toolbarDefaultItemIdentifiers:(NSToolbar*)toolbar {
return [self toolbarAllowedItemIdentifiers:toolbar];
}
- (NSToolbarItem*)toolbar:(NSToolbar*)toolbar
itemForItemIdentifier:(NSString*)str
willBeInsertedIntoToolbar:(BOOL)flag
{
if ([str isEqualToString:#"myToolbarItem"] == YES) {
NSToolbarItem* item = [[NSToolbarItem alloc] initWithItemIdentifier:str];
[item setView:[[NSButton alloc] init]];
[item setMinSize:NSMakeSize(50,50)];
[item setMaxSize:NSMakeSize(50,50)];
[item setLabel:#"Text"];
return [item autorelease];
}
return nil;
}
But this also has the same effect: when I press a NSToolbarItem with a NSButton in it in "Text only mode" the toolbar itself forces it's mode to "Icon and Text".
Do you have any idea how I can make it work correctly or perhaps have an alternative to creating the nice looking toolbaritems like Safari etc have?
You need to add a menu representation to each NSToolbarItem that has a custom view. Below the line where you allocate the NSToolbarItem add this:
NSMenuItem *menuRep = [[NSMenuItem alloc] initWithTitle:#"Text" action:#selector(targetMethod:) keyEquivalent:#""];
[menuRep setTarget:<target>];
[item setMenuFormRepresentation:menuRep];
As long as the target is valid your items should stay as text-only buttons; otherwise they will be disabled. See Setting a Toolbar Item's Representation.
Normally you would also need to implement validateToolbarItem: in your target, but for custom view items you instead need to override validate: to do something appropriate. See Validating Toolbar Items.

NSMenu doesn't start tracking

I have a little cocoa app which usually operates in the background (as agent). Sometimes I'd like to be able to popup a contextmenu (no window or s.th. visible at this time).
As I'm only targetting Snow Leopard I tried this:
if (windows) {
NSMenu *theMenu = [[[NSMenu alloc] initWithTitle:#"test"] autorelease];
[theMenu setShowsStateColumn:NO];
[theMenu setAutoenablesItems:NO];
for (id item in windows) {
NSString *labelText = #"some text";
NSMenuItem *theMenuItem = [[[NSMenuItem alloc] initWithTitle:labelText
action:#selector(menuItemSelected:)
keyEquivalent:#""] autorelease];
[theMenuItem setTarget:self];
[theMenuItem setRepresentedObject:item];
[theMenuItem setEnabled:YES];
[theMenuItem setImage:icon];
[theMenu addItem:theMenuItem];
}
[theMenu popUpMenuPositioningItem:nil atLocation:[NSEvent mouseLocation] inView:nil];
}
The menu popsup perfectly but if I hover the items with the mouse cursor they don't highlight and I can't click them.
The menuItemSelected: method looks just like this:
-(IBAction)menuItemSelected:(id)sender {
}
Any idea what I'm doing wrong?
I suspect that the windowing system doesn't consider your application to be active, and thus doesn't send mouse events to the menu you've created.
As an experiment, try creating a dummy window before popping up the menu. I'd create an NSPanel, possibly with style NSNonActivatingPanelMask. makeKeyAndOrderFront: your window/panel, then pop up the menu and see what happens.
If this works, I'd stick with the approach and hide the window.

How do you make a Menu Bar Item display how many rows there are in a table?

I have a core data table and would like the Menu Bar item to display how many rows there are in the table. I have already created the menu bar item using this code:
-(void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSStatusItem *statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength] retain]; //Create new status item instance
[statusItem setHighlightMode:YES]; //This does something, I'm sure of it.
[statusItem setTitle:[NSString stringWithFormat:#"%C",0xff50]]; //This labels it. You can also use setImage instead to use an icon. That current code will result in a item labeled "p"
[statusItem setEnabled:YES]; //Self explanatory
[statusItem setMenu:theMenu];
[statusItem setToolTip:#"TOOLTIP HA AWESOME AMIRITE?"]; //Optional, just for kicks.
}
What do I need to add to make the Menu Bar item display how many rows there are in the table?
If you don't require live updating you can try this approach:
1) set the delegate of theMenu:
[theMenu setDelegate:self];
2) and implement the delegate methode:
- (void)menuWillOpen:(NSMenu *)menu {
NSUInteger count = [self.tableView numberOfRows];
[[menu itemAtIndex:0] setTitle: [NSString stringWithFormat:#"%d rows", count]];
}
This code will refresh the menu item every time the user opens the menu. If you want to refresh it every time something in the table changes, you will need to use KVO to observe the array controller. You will also need to use KVO if you want to display the count in the title of the StatusItem.

Resources