NSWindow like Quicksilver - objective-c

I am creating an app, where I want to show a "pop-up" or "notification" to the user when he press a hotkey.
I want that to be displayed as a floating message, like the one that appears when you change the volume, or the brightness, or like the Quicksilver App input window.
I want it to has alpha, to fade in, to stay there for 5-8 secs, and to fade out.
And ... the problem is that I don't know how to get started on that. I've tried:
NSRect frame = NSMakeRect(0, 0, 600, 65);
_myWindow = [[NSWindow alloc] initWithContentRect:frame
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO];
[_myWindow setBackgroundColor:[NSColor blueColor]];
[_myWindow center];
[_myWindow makeKeyAndOrderFront:NSApp];
But, of course that's not what I'm trying to do.
Any help is welcome ;-)

I believe the proper term for this is a bezel window. Quicksilver is open source (https://github.com/quicksilver/Quicksilver) so you can see how they do it, but I've accomplished something similar with a custom NSWindow subclass:
- (id) initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag
{
if((self = [super initWithContentRect:contentRect styleMask:NSBorderlessWindowMask backing:bufferingType defer:flag])) {
[self setOpaque:NO];
[self setIgnoresMouseEvents:YES];
[self setLevel:NSFloatingWindowLevel];
[self setBackgroundColor:[NSColor clearColor]];
}
return self;
}
and the animation controlled by the window controller:
- (void) windowDidLoad
{
CAAnimation *animation = [CABasicAnimation animation];
[animation setDelegate:self];
[[self window] setAnimations:[NSDictionary dictionaryWithObject:animation forKey:#"alphaValue"]];
}
to make the window fade in, code similar to the following should work:
[[self window] setAlphaValue:0.0];
[[[self window] animator] setAlphaValue:1.0];
[[self window] orderFront:self];
I realize this isn't a plug and play solution but it should get you started.

Related

UITextView doesn't disappear when removedFromSuperview

I have two UITextViews, self.instructions and self.textView, that are supposed to alternate depending on what the user selects.
I create a self.textView like so:
-(void)createSpaceToWrite
{
[self.instructions removeFromSuperview];
[self.bar removeFromSuperview];
[self createNavigationBar:#"Compose" selector:#"displayScreen" withDone:NO]; //This adds a UINavigationBar to the view.
if (!self.textView)
{
self.textView = [[UITextView alloc] initWithFrame:CGRectMake(20, 60, 280, 150)];
}
self.textView.backgroundColor = [UIColor whiteColor];
self.textView.font = [UIFont fontWithName:#"Helvetica Neue" size:14];
self.textView.text = #"";
[self.view addSubview:self.textView];
self.textView.delegate = self;
}
Then I create self.instructions like so:
-(void)haikuInstructions
{
[self.textView removeFromSuperview];
[self.bar removeFromSuperview];
[self createNavigationBar:#"Compose" selector:#"displayScreen" withDone:NO];
if (!self.instructions)
{
self.instructions = [[UITextView alloc] initWithFrame:CGRectMake(10, 125, [[UIScreen mainScreen] bounds].size.width - 10, [[UIScreen mainScreen] bounds].size.height)];
}
self.instructions.backgroundColor=[UIColor clearColor];
self.instructions.text = #"Text of instructions";
self.instructions.editable=NO;
[self.view addSubview:self.instructions];
[self resignFirstResponder];
}
The user starts with self.instructions displayed against the background image. Fine.
The user switches. The instruction text disappears, to be replaced by the editable self.textView, a white box. Fine.
The user switches back. The instruction text appears--but the white box is still there, even thought I've removed it from the superview. And not only that, it's still editable and still brings up the keyboard when the user goes to edit it!
What am I doing wrong?
EDIT: Well, I basically scrapped all the code and started the class over from scratch, trying to be cleaner about everything, and I'm no longer having this problem, so it must have been something in some other method that was affecting it. Lesson: haphazard coding is bad!
Why do you need to remove your text views interchangeably? Wouldn't it be better to just "hide" them interchangeably by setting the setHidden property like for example:
[self.textView setHidden: YES];
and additionally try the following also:
[self.textView resignFirstResponder];
[self.textView setEditable: NO];
[self.textView setBackgroundColor: [UIColor clearColor]];
[self.textView setAlpha: 0.0];

Objective C, rounded corner custom window?

I have a subclass of NSWindow to customize one of my windows for my app.
I have everything set, but I am not sure how to make the corners round.
Currently, my window is a transparent rectangular window with some buttons, labels, and a textfield in it.
The class includes:
#import "TransparentRoundRectWindow.h"
#implementation TransparentRoundRectWindow
-(id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag
{
self = [super initWithContentRect:contentRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
if (self) {
[self setAlphaValue:0.75];
[self setOpaque:YES];
[self setHasShadow:YES];
[self setBackgroundColor:[NSColor clearColor]];
}
return self;
}
-(BOOL)canBecomeKeyWindow
{
return YES;
}
I just need to make the corners round now. I tried searching for similar situations and saw some of them explaining to override the drawRect method but I couldn't get them to work.
How could I do this?
(I'm using Mac OS X Lion)
Thanks in advance.
You need to set to Your window Opaque to NO. And subclass Your window's view.
Window subclass:
-(id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag
{
self = [super initWithContentRect:contentRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
if (self) {
[self setOpaque:NO];
[self setHasShadow:YES];
[self setBackgroundColor:[NSColor clearColor]];
}
return self;
}
-(BOOL)canBecomeKeyWindow
{
return YES;
}
Window's view subclass:
- (void)drawRect:(NSRect)rect
{
NSBezierPath * path;
path = [NSBezierPath bezierPathWithRoundedRect:rect xRadius:8 yRadius:8];
[[NSColor colorWithCalibratedRed:0 green:0 blue:0 alpha:0.75] set];
[path fill];
}
Result:
More explanation how to do this:
Create new NSView class and paste "Window's view subclass" code which I wrote in it. Then go to Your window's view.
Here is window's view click on it:
Go to the Identity inspector and set class to your created class:

How to Animate a custom NSWindow

I'm having some troubles animating a custom NSWindow.
Here's my init method:
- (CustomWindow *)initWithView:(NSView *)view
{
if ((self = [super initWithContentRect:contentRect
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO])) {
[[self contentView] addSubview:view];
[self setBackgroundColor:[NSColor darkGrayColor]];
[self setMovableByWindowBackground:YES];
[self setExcludedFromWindowsMenu:YES];
[self setOpaque:NO];
[self setHasShadow:YES];
[self setDelegate:self];
}
return self;
}
When I call [self setFrame:originalFrame display:NO animate:YES]; there is a delay that corresponds to the animation duration, but the animation itself doesn't occur.
I think this is because I'm using a borderless window?
Simply use this: [self setFrame:originalFrame display:YES animate:YES];
Guess your window is resized, but view you add to content view, don't. If you have only one view, then instead of:
[[self contentView] addSubview:view];
use:
[self setContentView:view];

Cocoa App Enter Full Screen

I am developing a simple application which make use of full screen window.
Window contains view that contains button, image etc etc... , but when I enter in full screen with the follow lines:
NSWindow* tmp = [self window];
[tmp setStyleMask:NSBorderlessWindowMask];
[tmp setFrame:[tmp frameRectForContentRect:[[tmp screen] frame]]display:YES animate:NO];
[tmp setBackingType:NSBackingStoreBuffered];
screenRect = [[NSScreen mainScreen] frame];
int windowLevel = CGShieldingWindowLevel();
[self.window setLevel:windowLevel];
The view I put in the window doesn't resized automatically, I could make some operation for resize correctly that work, but there are a way to do that automatically?
I post all my AppController here:
-(id)init {
self = [super initWithWindowNibName:#"MainWindow"];
NSWindow* tmp = [self window];
[tmp setStyleMask:NSBorderlessWindowMask];
[tmp setFrame:[tmp frameRectForContentRect:[[tmp screen] frame]]display:YES animate:NO];
[tmp setBackingType:NSBackingStoreBuffered];
screenRect = [[NSScreen mainScreen] frame];
/**
// [[tmp standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
// [[tmp standardWindowButton:NSWindowZoomButton] setHidden:YES];
self.window = [[NSWindow alloc] initWithContentRect:screenRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO screen:[NSScreen mainScreen]];
**/
int windowLevel = CGShieldingWindowLevel();
[self.window setLevel:windowLevel];
return self;
}
// We need to be layer-backed to have subview transitions.
-(void)awakeFromNib {
[[self window] setContentSize:[topMenu frame].size];
[[[self window] contentView] addSubview:topMenu];
[topMenu enterFullScreenMode:[NSScreen mainScreen] withOptions:nil];
[[[self window] contentView] setWantsLayer:YES];
}
- (void)dealloc
{
[super dealloc];
}
- (void)windowDidLoad
{
[super windowDidLoad];
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
[topMenu_controller performAnimation];
return;
}
You can use the springs and struts of Interface Builder to set a view's autosizing behavior:
http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/IB_UserGuide/Layout/Layout.html

How do I create a Cocoa window programmatically?

My Cocoa app needs some small dynamically generated windows. How can I programmatically create Cocoa windows at runtime?
This is my non-working attempt so far. I see no result whatsoever.
NSRect frame = NSMakeRect(0, 0, 200, 200);
NSUInteger styleMask = NSBorderlessWindowMask;
NSRect rect = [NSWindow contentRectForFrameRect:frame styleMask:styleMask];
NSWindow * window = [[NSWindow alloc] initWithContentRect:rect styleMask:styleMask backing: NSBackingStoreRetained defer:false];
[window setBackgroundColor:[NSColor blueColor]];
[window display];
The problem is that you don't want to call display, you want to call either makeKeyAndOrderFront or orderFront depending on whether or not you want the window to become the key window. You should also probably use NSBackingStoreBuffered.
This code will create your borderless, blue window at the bottom left of the screen:
NSRect frame = NSMakeRect(0, 0, 200, 200);
NSWindow* window = [[[NSWindow alloc] initWithContentRect:frame
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO] autorelease];
[window setBackgroundColor:[NSColor blueColor]];
[window makeKeyAndOrderFront:NSApp];
//Don't forget to assign window to a strong/retaining property!
//Under ARC, not doing so will cause it to disappear immediately;
// without ARC, the window will be leaked.
You can make the sender for makeKeyAndOrderFront or orderFront whatever is appropriate for your situation.
A side note, if you want to programatically instantiate the application without a main nib, in the main.m file / you can instantiate the AppDelegate as below. Then in your apps Supporting Files / YourApp.plist Main nib base file / MainWindow.xib delete this entry. Then use Jason Coco's approach to attach the window in your AppDelegates init method.
#import "AppDelegate.h":
int main(int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
[NSApplication sharedApplication];
AppDelegate *appDelegate = [[AppDelegate alloc] init];
[NSApp setDelegate:appDelegate];
[NSApp run];
[pool release];
return 0;
}
Try
[window makeKeyAndOrderFront:self];
instead of
[window display];
Is that what you're aiming for?
Translating the top rated answer to modern swift (5) gives you something akin to this:
var mainWindow: NSWindow!
...
mainWindow = NSWindow(
contentRect: NSMakeRect(0, 0, 200, 200),
styleMask: [.titled, .resizable, .miniaturizable, .closable],
backing: .buffered,
defer: false)
mainWindow.backgroundColor = .blue
mainWindow.makeKeyAndOrderFront(mainWindow)
This is what I've come up with myself:
NSRect frame = NSMakeRect(100, 100, 200, 200);
NSUInteger styleMask = NSBorderlessWindowMask;
NSRect rect = [NSWindow contentRectForFrameRect:frame styleMask:styleMask];
NSWindow * window = [[NSWindow alloc] initWithContentRect:rect styleMask:styleMask backing: NSBackingStoreBuffered defer:false];
[window setBackgroundColor:[NSColor blueColor]];
[window makeKeyAndOrderFront: window];
This displays a blue window. I hope this is the optimal approach.