NSToolbar with custom views - objective-c

Hi so I've got a problem that i can't really figure out what the cause is. I made an app so far that has a NSToolbar that has custom views in it so that you can switch between views on the toolbar (just like safari's preference window toolbar views). I was using CCodings tutorial on youtube but i have the problem of the views moving by themselves, for example i click on view 1 and when i click on view 2 view one changes and the view moves up so that you can only see half of when i put on the view, I'm using Xcode 6 and OS X 10.10 so i don't know if that would be one cause but i thank you in advance if you can help me, heres the MainWindowController.m file:
Also the views should be setup correctly
-(NSRect)newFrameForNewContentView:(NSView*)view {
NSWindow *window = [self window];
NSRect newFrameRect = [window frameRectForContentRect:[view frame]];
NSRect oldFrameRect = [window frame];
NSSize newSize = newFrameRect.size;
NSSize oldSize = oldFrameRect.size;
NSRect frame = [window frame];
frame.size = newSize;
frame.origin.y -= (newSize.height - oldSize.height);
return frame;
}
-(NSView *)viewForTag:(int)tag {
NSView *view = nil;
switch (tag) {
case 0:
view = smallView;
break;
case 1:
view = mediumView;
break;
case 2: default:
view = largeView;
break;
}
return view;
}
- (BOOL)validateToolbarItem:(NSToolbarItem *)item {
if ([item tag] == currentViewTag) return NO;
else return YES;
}
-(void)awakeFromNib {
[[self window] setContentSize:[smallView frame].size];
[[[self window] contentView] addSubview:smallView];
[[[self window] contentView] setWantsLayer:YES];
}
-(IBAction)switchView:(id)sender {
int tag = [sender tag];
NSView *view = [self viewForTag:tag];
NSView *previousView = [self viewForTag:currentViewTag];
currentViewTag = tag;
NSRect newFrame = [self newFrameForNewContentView:view];
[NSAnimationContext beginGrouping];
if ([[NSApp currentEvent] modifierFlags] & NSShiftKeyMask)
[[NSAnimationContext currentContext] setDuration:1.0];
[[[[self window] contentView] animator] replaceSubview:previousView with:view];
[[[self window] animator] setFrame:newFrame display:YES];
[NSAnimationContext endGrouping];
}

Seems that you also need to change NSWidnow frame apart from contenView.
Also as for me for switching views by click events its better to use NSTabView.

Related

How to fade animate hide/show window with Objective C

In Objective C, is it possible to hide my application window on launch, and then at some point of time make the call to do a pleasant fade animation to show my application window?
Not that you need to know this, but the background is that I was planning to do this from my Javascript in the webkit widget. I've already established the Objective C <==> Javascript bridge. So, when my charts finish loading, I make the call from Javascript back to Objective C to tell it to show the window with pleasant fade animation.
Here's what I've tried, but this has no fade effect -- the window just waits a sec (because those charts are loading) and then just pops on the screen fast. I tried changing the NSThread delay, but it didn't help -- that just slowed it more.
// ...in my app delegate...
- (void)applicationWillFinishLaunching:(NSNotification *)aNotification
{
// NOTE THIS SAYS "WILL", NOT "DID" -- VERY IMPORTANT.
// TO DO OTHERWISE WOULD GIVE YOU A WINDOW FLASH FOR A SECOND,
// THEN FADE IN.
[self hideWindow:_window];
}
- (void)hideWindow:(NSWindow *)window
{
float alpha = 0.0;
[window setAlphaValue:alpha];
[window makeKeyAndOrderFront:self];
}
- (void)showWindow:(NSWindow *)window
{
float alpha = 1.0;
[window setAlphaValue:alpha];
[window makeKeyAndOrderFront:self];
}
- (void)fadeOutWindow:(NSWindow*)window
{
float alpha = 1.0;
[window setAlphaValue:alpha];
[window makeKeyAndOrderFront:self];
for (int x = 0; x < 10; x++) {
alpha -= 0.1;
[window setAlphaValue:alpha];
[NSThread sleepForTimeInterval:0.020];
}
}
- (void)fadeInWindow:(NSWindow*)window
{
float alpha = 0.0;
[window setAlphaValue:alpha];
[window makeKeyAndOrderFront:self];
for (int x = 0; x < 10; x++) {
alpha += 0.1;
[window setAlphaValue:alpha];
[NSThread sleepForTimeInterval:0.020];
}
}
// My javascript to ObjC bridge calls this:
- (void)callShowAppWindow;
{
[self fadeInWindow:_window];
}
In my source on the question, I almost had it. Here's the fix on two functions that causes the fade effect:
- (void)fadeOutWindow:(NSWindow*)window
{
float alpha = 1.0;
[window setAlphaValue:alpha];
[window makeKeyAndOrderFront:self];
[NSAnimationContext beginGrouping];
[[NSAnimationContext currentContext] setDuration:1.5f];
[[window animator] setAlphaValue:0.f];
[NSAnimationContext endGrouping];
}
- (void)fadeInWindow:(NSWindow*)window
{
float alpha = 0.0;
[window setAlphaValue:alpha];
[window makeKeyAndOrderFront:self];
[NSAnimationContext beginGrouping];
[[NSAnimationContext currentContext] setDuration:1.5f];
[[window animator] setAlphaValue:1.f];
[NSAnimationContext endGrouping];
}
Just use NSAnimationContext animations to animate alpha property:
- (void)fadeInWindow:(NSWindow *)window {
[window setAlphaValue:0.0];
[window makeKeyAndOrderFront:self];
[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
[context setDuration:2.0];
[window setAlphaValue: 1.0f];
} completionHandler:^{ // or put nil instead of block
NSLog(#"Completed");
}];
}
And the same method to fade out your window:
- (void)fadeOutWindow:(NSWindow*)window {
[window setAlphaValue:1.0f];
[window makeKeyAndOrderFront:self];
[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
[context setDuration:2.0];
[window setAlphaValue: 0.0f];
} completionHandler:nil];
}
You can even combine this in one method:
- (void)fadeWindow:(NSWindow *)window in:(BOOL)in {
[window setAlphaValue: in ? 0.0f : 1.0f];
[window makeKeyAndOrderFront: self];
[NSAnimationContext runAnimationGroup: ^(NSAnimationContext *context) {
[context setDuration: 2.0f]; // or whatever you need
[window setAlphaValue: in ? 1.0f : 0.0f];
} completionHandler: nil];
}
Instead of hiding the window what about creating a splash/loading page occupying the initial window real estate and then doing some fancy animations with your actual window once your data has loaded or your app is ready to go?

Switching between custom views using Toolbar

I have a single MainMenu.xib file and I have a window by the name "Preferences"
Also I have four different Custom Views with different Heights. and a Toolbar on that window.
I have linked every toolbar item to the -(void) switchViews:(id)sender; function. The views are linked and are showing up and are also changing but the problem is that if I change from one view to another and then back or to another, the content i.e. buttons, labels, checkboxes on the views keep moving upwards, the window still keeps on changing to right heights, but if I switch enough times the content would disappear from the view.. Any kind of help would be useful.
http://imgur.com/bV3NHa0,zgJCacA
http://imgur.com/bV3NHa0,zgJCacA#1
// FOR CHANGING VIEWS IN THE PREFERENCES WINDOW
- (IBAction)switchView:(id)sender {
long int tag = [sender tag];
NSView *view = [self viewForTag:tag];
NSView *previousView = [self viewForTag:currentViewTag];
currentViewTag = tag;
NSRect newFrame = [self newFrameForNewContentView:view];
[NSAnimationContext beginGrouping];
if ([[NSApp currentEvent] modifierFlags] & NSShiftKeyMask) {
[[NSAnimationContext currentContext] setDuration:1.0];
}
[[[[self preferences] contentView] animator] replaceSubview:previousView with:view];
[[[self preferences] animator] setFrame:newFrame display:YES];
[NSAnimationContext endGrouping];
}
- (NSView *)viewForTag:(long int)tag {
NSView *view = nil;
switch (tag) {
case 0:
view = generalView;
break;
case 1:
view = timesView;
break;
case 2:
view = menubarView;
break;
case 3: default: view = aboutView;
break;
}
return view;
}
- (NSRect)newFrameForNewContentView:(NSView *)view {
NSWindow *window = [self preferences];
NSRect newFrameRect = [window frameRectForContentRect:[view frame]];
NSRect oldFrameRect = [window frame];
NSSize newSize = newFrameRect.size;
NSSize oldSize = oldFrameRect.size;
NSRect frame = [window frame];
frame.size = newSize;
frame.origin.y -= (newSize.height - oldSize.height);
return frame;
}
with the problem you're describing and glancing at your code i would start to suspect this line...
frame.origin.y -= (newSize.height - oldSize.height);

Animate NSSplitview and window size

What I'm trying to achieve is that when the user press a button the window grows and the extra space is taken by a panel of NSSplitview that uncollapses and grows to fill the space.
I can easily animate the window resize and the splitview growing independently but when I try to put the two animation together one inevitably happens before the other or by steps. First the window partly resize, then the splitview resize follow, then the window finish resizing and finally the splitview finishes as well. Any ides on why that might be happening?
Here is the code I use:
- (IBAction)helpButtonPressed:(id)sender
{
if ([sender isKindOfClass:[NSMenuItem class]]) [sender setState:![sender state]];
NSWindow *window = [[[self windowControllers] objectAtIndex:0] window];
NSRect oldFrame = [window frame];
CGFloat windowWidthAdd;
if ([sender state]) windowWidthAdd = HELP_WIDTH; else windowWidthAdd = -HELP_WIDTH;
NSRect newFrame = NSMakeRect(oldFrame.origin.x, oldFrame.origin.y,oldFrame.size.width+windowWidthAdd, oldFrame.size.height);
[[NSAnimationContext currentContext] setDuration:0.3f];
[NSAnimationContext beginGrouping];
[[window animator] setFrame:newFrame display:YES];
if ([sender state]) [self uncollapseRightView]; else [self collapseRightView];
[NSAnimationContext endGrouping];
}
-(void)collapseRightView
{
NSView *right = [[self.splitView subviews] objectAtIndex:1];
NSView *left = [[self.splitView subviews] objectAtIndex:0];
NSRect leftFrame = [left frame];
NSRect overallFrame = [self.splitView frame];
[right setHidden:YES];
[[left animator] setFrameSize:NSMakeSize(overallFrame.size.width,leftFrame.size.height)];
}
-(void)uncollapseRightView
{
NSView *left = [[self.splitView subviews] objectAtIndex:0];
NSView *right = [[self.splitView subviews] objectAtIndex:1];
[right setHidden:NO];
CGFloat dividerThickness = [self.splitView dividerThickness];
// get the different frames
NSRect leftFrame = [left frame];
// Adjust left frame size
leftFrame.size.width = (leftFrame.size.width-HELP_WIDTH-dividerThickness);
NSRect rightFrame = [right frame];
rightFrame.origin.x = leftFrame.size.width + dividerThickness;
rightFrame.size.width = HELP_WIDTH;
[[left animator] setFrameSize:leftFrame.size];
[[right animator] setFrame:rightFrame];
}
If you are looking a little closer at the class reference of NSSplitView, you will recognize it conforms to NSAnimatablePropertyContainer. That means NSSplitView will provide you with an "animating proxy of itself". If you call animator on your NSSplitView you'll get this proxy, on which you should be able to change properties in an animated fashion.
For adjusting the animation duration and timing function, use NSAnimationContext the same way you already did.
Last but not least: Did you recognize NSSplitView's minPossiblePositionOfDividerAtIndex: and maxPossiblePositionOfDividerAtIndex:?

UIImagePickerController how to hide the flip camera button?

is there a way to hide the flip camera button inside the UIImagePickerController?
thanks for reading
!^_^!
I ended up using a custom subclass of UIImagePickerController to fix this (and other) issues:
#import "SMImagePickerController.h"
#implementation SMImagePickerController
void hideFlipButtonInSubviews(UIView *view) {
if ([[[view class] description] isEqualToString:#"CAMFlipButton"]) {
[view setHidden:YES];
} else {
for (UIView *subview in [view subviews]) {
hideFlipButtonInSubviews(subview);
}
}
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
hideFlipButtonInSubviews(self.view);
}
#end
You should be able to create an empty button inside an overlayview that you float on top of the flip camera button. I hacked the code below to test and it seemed to work. Give it a try.
UIView *cameraOverlayView = [[UIView alloc] initWithFrame:CGRectMake(screenSize.width - 100.0f, 5.0f, 100.0f, 35.0f)];
[cameraOverlayView setBackgroundColor:[UIColor blackColor]];
UIButton *emptyBlackButton = [[UIButton alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 100.0f, 35.0f)];
[emptyBlackButton setBackgroundColor:[UIColor blackColor]];
[emptyBlackButton setEnabled:YES];
[cameraOverlayView addSubview:emptyBlackButton];
cameraUI.allowsEditing = YES;
cameraUI.showsCameraControls = YES;
cameraUI.delegate = self;
cameraUI.cameraOverlayView = cameraOverlayView;

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