NSStatusItem (cocoa) location on screen - cocoa

I am trying to get the on screen location of an NSStatusItem so that I can perform a click on that area via code like below. I am doing this so that my users can press a hotkey to see the menu.
event = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, newLocation, kCGMouseButtonLeft);
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
Does anyone know of a way to get the location?, I have been trying ideas and searching for days and have found several ideas but none of them seem to work in leopard/snow leopard
The NSStatusItem is using an NSMenu not a custom view.

Don't do this by simulating a mouse event, that is completely the wrong way to go.
You can use the -popUpStatusItemMenu: method of NSStatusItem to show the menu. You can call this method from a hot key by using a CGEventTap to capture global events that your NSStatusItem can respond to.
On 10.6 you can use the +addGlobalMonitorForEventsMatchingMask:handler: method of NSEvent to capture global events instead of using CGEventTap directly.

Thinking out loud you could create your own custom view for the NSStatusItem. Then for example from the AppController:
- (void)awakeFromNib {
float width = 30.0;
float height = [[NSStatusBar systemStatusBar] thickness];
NSRect viewFrame = NSMakeRect(0, 0, width, height);
statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:width] retain];
[statusItem setView:[[[MyCustomView alloc] initWithFrame:viewFrame controller:self] autorelease]];
And to simulate the highlight you'd send a message to your custom view. Then when drawing MyCustomView:
// In MyCustomView.m
- (void)drawRect:(NSRect)rect {
if (clicked) {
[[NSColor selectedMenuItemColor] set];
NSRectFill(rect);
}
As well as using -popUpStatusItemMenu:.

Related

How to make a NSTextField added to a NSView Draggable

Let me elaborate the steps i am doing
Create Mac 10.9 Project
Drag a CustomView (Let's call it myView) to the .xib
Drag a NSButton to the .xib but out side the CustomView
Now programatically (using a other class) i add a NSTextField to the CustomView when the button is clicked by this code
NSTextField *textField = [[NSTextField alloc] init];
[textField setBezeled:NO];
[textField setEditable:NO];
[textField setSelectable:NO];
[textField setFont:[NSFont fontWithName:#"Arial" size:20]];
[textField setStringValue:#"Hello World!"];
int textWidth = textField.fittingSize.width;
int textHeight = textField.fittingSize.height;
[textField setFrame:NSMakeRect(0, 0, textWidth, textHeight)];
[myView addSubview:textField];
Now i see that the TestField is added to myView
All i want is the user can drag the textField movable inside myView
i added the following code
- (void)mouseDown:(NSEvent *)event{
NSLog(#"Hi");
}
But the NSLog is not getting shown
How do i make the NSTextField draggable?
Note: Because mouse-moved events occur so frequently that they can
quickly flood the event-dispatch machinery, an NSWindow object by
default does not receive them from the global NSApplication object.
However, you can specifically request these events by sending the
NSWindow object an setAcceptsMouseMovedEvents: message with an
argument of YES.
From Apple Docset

Float an NSView above a window being used by DVDPlayback framework

I am trying to write a simple DVD player using Mac OS X's DVDPlayback.framework. I can get the DVD to play within a window, but ultimately I want this to run as a full-screen app.
I'm having difficulty adding a sub-view to display media controls whilst the DVD is playing (pause / play, progress slider to scroll through the movie, change chapter etc).
It seems that if I create a sub-view (NSView) within the window being used by the DVD framework, it always seems to fall behind the DVD content, even if I tell the NSView to be at the top-most level.
Here's the simplified code, which just tries to create a white sub-view within a region of the window:
(I've tried the code on 10.6 and 10.7 with the same results).
const BOOL PLAY_DVD = YES;
#interface ControlsView : NSView {
}
#end
#implementation ControlsView
- (void)drawRect:(NSRect)rect {
[[NSColor whiteColor] set];
NSRectFill(rect);
}
#end
#implementation AppDelegate
#synthesize window = _window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSView *view = self.window.contentView;
if (PLAY_DVD) {
NSLog(#"%# Playing DVD video", [self class]);
// Register error handler
OSStatus err;
err = DVDInitialize();
if (err != noErr) {
NSLog(#"DVDInitialise failed with error code %d", err);
[NSApp terminate:self];
}
// Set window to be the main window
err = DVDSetVideoWindowID([self.window windowNumber]);
// Set the display...
CGDirectDisplayID display = (CGDirectDisplayID) [[[[self.window screen] deviceDescription] valueForKey:#"NSScreenNumber"] intValue];
Boolean isSupported;
err = DVDSwitchToDisplay(display, &isSupported);
// Set video bounds
NSRect frame = [self.window frame];
CGRect rect = CGRectMake(0, 0, frame.size.width, frame.size.height);
err = DVDSetVideoCGBounds(&rect);
FSRef ref;
DVDOpenMediaFileWithURL([NSURL URLWithString:#"file:///Path/to/my/TestDVD/VIDEO_TS"]);
DVDOpenMediaFile(&ref);
DVDPlay();
}
// Attempt to add a subview to show the controls...
ControlsView *controls = [[ControlsView alloc] initWithFrame:NSMakeRect(20, 20, 100, 50)];
[view addSubview:controls positioned:NSWindowAbove relativeTo:nil];
}
#end
If PLAY_DVD is NO, the subview is correctly rendered (and I can create other sub-views and show that the ordering is correct).
If PLAY_DVD is YES, the media starts playing, but the sub-view is never visible because it always seems to fall behind the video.
The only examples of DVD playback I've been able to find have had the controls in a second window, but for a full-screen application I'd like the controls to be part of the full-screen view and to fade in/out when required.
Does anyone know how best to do this? Do my full-screen controls have to be in a separate window which floats above the full-screen window? I've not been able to find an example which has the controls and the DVD playback in the same window.
Thanks in advance for your help!

Xcode mouse and NSView basic help?

I am making an app for school and I would love to change the cursor picture when the mouse is clicked in a certain NSView area.
I know that you can use mousedown, mouseup and other events, but I don't really know how to put them in my code in order for the cursor picture change to work.
Have the custom NSView and override resetCursorRect,
Refer the example code below
-(void)resetCursorRects{
//[self log:#"Inside Reset Cursor Rect"];
NSRect viewRect = [self frame];// change it accordingly
[self addCursorRect:viewRect cursor:[NSCursor pointingHandCursor]];
viewRect = [self.pMailImageView frame];
[self addCursorRect:viewRect cursor:[NSCursor pointingHandCursor]];
viewRect = [self.pDialImageView frame];
[self addCursorRect:viewRect cursor:[NSCursor pointingHandCursor]];
}

CGGradient isn't visible (not using interface builder) and UIButtons can't be triggered

I have created a view that contains a CGGradient:
// Bar ContextRef
CGRect bar = CGRectMake(0, screenHeight-staffAlignment, screenWidth, barWidth);
CGContextRef barContext = UIGraphicsGetCurrentContext();
CGContextSaveGState(barContext);
CGContextClipToRect(barContext,bar);
// Bar GradientRef
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGFloat components[16] = { 1.0,1.0,1.0,0.0, 0.0,0.0,0.0,1.0, 0.0,0.0,0.0,1.0, 1.0,1.0,1.0,0.0};
CGFloat locations[4] = {0.95,0.85,0.15,0.05};
size_t count = 4;
CGGradientRef gradientRef = CGGradientCreateWithColorComponents(colorSpace, components, locations, count);
// Draw Bar
CGPoint startPoint = {0.0,0.0};
CGPoint endPoint = {screenWidth,0.0};
CGContextDrawLinearGradient(barContext, gradientRef, startPoint, endPoint, 0);
CGContextRestoreGState(barContext);
This code is called in the drawRect method of the UIView. I then use a UIViewController to access the created view.
- (void)loadView {
MainPageView *mpView = [[MainPageView alloc] initWithFrame:[window bounds]];
[self setView:mpView];
[mpView release];
}
and displayed on the screen through the appDelegate:
mpViewController = [[MainPageViewController alloc] init];
[window addSubview:[mpViewController view]];
[window makeKeyAndVisible];
The UIView contains more objects, such as UIButtons, that are visible. I am assuming because they are added as a subview. But I can't work out how to add the CGGradient as a subview? Does it need to be? Is there another reason CGGradient is not visible?
I also don't get the functionality on the UIButtons. I guess that is because of where I have added the UIButtons to the view. Do the buttons need to be added in the UIViewController or the appDelegate to have functionality. Sorry to ask what would seem like simple questions but I am trying to accomplish the programming without the Interface Builder and material on that is scarce. If anyone could point me in the right direction on both these problems I would really appreciate it.
Thanks!
The functionality on the buttons was lost because the frame was too large but the buttons were still visible because the background was clearColor

How to create an OSD-like window with Cocoa on Mac OSX?

Please keep in mind that I'm a really newbie Cocoa developer
Scenario: I've a search the when reaches the end of document restarts from begin, a so called "wrap around".
When I do the wrap I want to show a window that flashes on screen for some time (one second??) like and OSD (On Screen Display) control window, TextWrangler and XCode do that when text search restarts from the begin.
How can I implement a similar window?
Implementing a view to do this would be relatively simple. The following code in an NSView subclass would display a partially transparent rounded rect which ignores events when placed in a window.
- (void)drawRect:(NSRect)dirtyRect {
[[NSColor colorWithDeviceWhite:0 alpha:.7] set];
[[NSBezierPath bezierPathWithRoundedRect:self.bounds xRadius:10 yRadius:10] fill];
//Additional drawing
}
- (NSView *)hitTest:(NSPoint)aPoint {
return nil;
}
- (BOOL)acceptsFirstResponder {
return NO;
}
- (BOOL)isOpaque {
return NO;
}
If you do want to do this in a window, you will need to create a borderless, non-opaque window and set this as the content view. Also, you will need to have the view fill it's bounds with a clear color at the start of the drawRect: method.
//Create and display window
NSPanel *panel = [[NSPanel alloc] initWithFrame:NSMakeRect(0,0,300,200) styleMask:NSBorderlessWindowMask|NSNonactivatingPanelMask backing:NSBackingStoreBuffered defer:YES];
[panel setOpaque:NO];
MyViewSubview *view = [MyViewSubview new];
[panel setContentView:view];
[view release];
[p setLevel:NSScreenSaverWindowLevel];
[p orderFront:nil];
//Add these two lines to the beginning of the drawRect: method
[[NSColor clearColor set];
NSRectFill(self.bounds);
However, this window will intercept events and I have not been able to disable this using standard methods.
To fade the view, check out NSViewAnimation, or use an NSTimer object and do it manually.

Resources