Changing view in NSWindow removes contents of view - cocoa

I am using an NSToolbar and NSWindowController to change the views of an NSWindow. When the toolbar items are selected, the view is successfully changed for the window and the window changes it's size according to the view size. Upon the initial loading of the window, the contents of the view appear as expected. However, once a toolbar item is selected the contents of the new view are not visible and when the view is switched back to the original view, it's contents are no longer visible either. Not sure what is causing this so any help would be appreciated.
#import <Cocoa/Cocoa.h>
#interface WindowController : NSWindowController {
IBOutlet NSView *firstView;
IBOutlet NSView *secondView;
int currentViewTag;
}
- (IBAction)switchView:(id)sender;
#end
and
#import "WindowController.h"
#interface WindowController ()
#end
#implementation WindowController
- (id)init {
self = [super initWithWindowNibName:#"WindowController"];
if (self) {
}
return self;
}
- (void)windowDidLoad {
[super windowDidLoad];
}
- (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 = firstView;
break;
case 1:
view = secondView;
break;
}
return view;
}
- (BOOL)validateToolbarItem:(NSToolbarItem *)item {
if ([item tag] == currentViewTag) return NO;
else return YES;
}
- (void)awakeFromNib {
[[self window] setContentSize:[firstView frame].size];
[[[self window] contentView] addSubview:firstView];
[[[self window] contentView] setWantsLayer:YES];
}
- (IBAction)switchView:(id)sender {
double 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];
}
#end

I tried out your code, and what I saw was not that the views disappeared, but that they were positioned wrongly and moved out of view. I fixed this by turning off auto layout in IB, and deselecting all the struts and springs in the size inspector. I also deselected the window's "restorable" property so that if you closed the program with view 2 visible, and reopened, the window (with view 1 inside) would be the correct size for view 1.

Related

NSButton Toggle : OnClick title get removed on OSX 10.11

I am using a Toggle button in XIB,
in AwakeFromNib :I set title and BG image of the button.
Code works very well till OSX 10.10.5 and below but on higher versions when I click on button the text gets removed.
Set attributed Title
[self.deleteButton setWantsLayer:YES];
self.deleteButton.layer.backgroundColor = [self setButtonBGColor];
[self setButtonTitleFor:self.deleteButton
toString:#"Delete"];
[self.deleteButton setLayerContentsRedrawPolicy:NSViewLayerContentsRedrawOnSetNeedsDisplay];
- (void)setButtonTitleFor:(NSButton*)button toString:(NSString*)title
{
NSAttributedString *attrString = [self getAttributedStringForString:title];
[button setAttributedTitle:attrString];
}
Any idea hat should be done.
So finally got it right
Subclassing NSButtonCell helped me out
RPButtonTextTopCell.h
#interface RPButtonTextTopCell : NSButtonCell
#end
RPButtonTextTopCell.m
#implementation RPButtonTextTopCell
-(id) init
{
self = [super init];
if (self) {
}
return self;
}
-(id) initWithCoder:(NSCoder *)decoder
{
return [super initWithCoder:decoder];
}
-(id) initTextCell:(NSString *)string
{
return [super initTextCell:string];
}
-(NSRect)titleRectForBounds:(NSRect)theRect
{
NSRect titleFrame = [super titleRectForBounds:theRect];
NSSize titleSize = [[self attributedStringValue] size];
titleFrame.origin.y = (theRect.origin.y - (theRect.size.height-titleSize.height)*0.5) + 5;
return titleFrame;
}
#end
Utilizing This Custom Class
RPButtonTextTopCell *deleteCell = [[RPButtonTextTopCell alloc] init];
deleteCell.backgroundColor = [self setNSButtonBGColor];
[self.deleteButton setCell:deleteCell];
[self setButtonTitleFor:self.deleteButton
toString:#"Delete"];
[self.deleteButton setAction:#selector(deleteButtonClicked:)];
[self.deleteButton setTarget:self];
and its solved....

Cocoa: NSToolBar with Custom Views. Animation issues

So I got a Window:
Window.xib
I got a WindowController too:
WindowController.h reads:
#import <Cocoa/Cocoa.h>
#interface MainWindowController : NSWindowController
{
IBOutlet NSView *firstView;
IBOutlet NSView *secondView;
IBOutlet NSView *thirdView;
int currentViewTag;
}
-(IBAction)switchView:(id)sender;
#end
And the WindowController.m reads:
#import "MainWindowController.h"
#interface MainWindowController ()
#end
#implementation MainWindowController
-(id)init
{
self = [super initWithWindowNibName:#"MainWindow"];
if (self){
// Initialization code here
}
return self;
}
//- (void)windowDidLoad {
// [super windowDidLoad];
//
// // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
//}
#pragma mark - Custom view drawing
-(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;
if (tag == 0) {
view = firstView;
} else if (tag == 1) {
view = secondView;
} else {
view = thirdView;
}
return view;
}
-(BOOL) validateToolbarItem:(NSToolbarItem *)item
{
if ([item tag] == currentViewTag) return NO;
else return YES;
}
-(void)awakeFromNib
{
[[self window] setContentSize:[firstView frame].size];
[[[self window] contentView]addSubview:firstView];
[[[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];
}
#end
The problem I have is that when i switch tabs in my app, the custom view (and there are three of different sizes) draw differently each time. Look at the screenshots, all of the numbers should be centre aligned but they are sometimes and others not. Can anyone see what my error is please?
I will also add that all of the actions have been correctly configured + the code works perfectly if the custom view size is the same all the time.
The view that works
The view that almost works
Again pointing out that in my .xib all of the numbers are aligned to 0x and 0y axis.
Appdelegate.h
#import <Cocoa/Cocoa.h>
#class MainWindowController;
#interface AppDelegate : NSObject <NSApplicationDelegate> {
MainWindowController *mainWindowController;
}
#end
Appdelegate.m
#interface AppDelegate ()
#property (nonatomic) IBOutlet NSWindow *window;
#end
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
// Insert code here to tear down your application
}
-(void)awakeFromNib
{
if(!mainWindowController){
mainWindowController = [[MainWindowController alloc]init];
}
[mainWindowController showWindow:nil];
}
#end
In Interface Builder, make sure to disable the "autoresizes subviews" checkbox of the default view of your window

Label/Text in Xcode Appears Blurry

I am trying to make a preferences view with lots of text. I cannot figure out why the text is blurry when i run the project, even though the interface builder is very sharp and clear. Here is a picture. [1]: http://i.stack.imgur.com/EQl6D.png
here is the code for the views:
#implementation SKMainWindowController
-(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: default:
view = welcome;
break;
case 1:
view = status;
break;
case 2:
view = power;
break;
case 3:
view = preferences;
break;
case 4:
view = about;
break;
}
return view;
}
- (BOOL)validateToolbarItem:(NSToolbarItem *)item {
if ([item tag] == currentViewTag) return NO;
else return YES;
}
-(void)awakeFromNib {
[[self window] setContentSize:[welcome frame].size];
[[[self window] contentView] addSubview:welcome];
[[[self window] contentView] setWantsLayer:NO];
}
-(IBAction)switchWelcome:(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];
[welcomeButton setState:NSOnState];
[statsButton setState:NSOffState];
[powerButton setState:NSOffState];
}
I've tried changing the text fields into code by doing things like [textField setStringValue:#""];, but with no luck it is still blurry. Thanks for any help. PS: This is for cocoa, not iOS.
Found the answer, ended up being the stupid visual effect view not cooperating. Simple fix was to set the visual effect view to within the window, and set as inactive. (although there is now no point in having a visual effect view.)

drawRect not called on PDFView subclass

I have a custom PDFView subclass and have overridden -mouseDown, -mouseDragged etc to draw a rectangle over the view. Here is the code I am using:
#implementation MyPDFView {
NSPoint clickLocation;
NSRect selection;
}
- (void)mouseDown:(NSEvent *)theEvent {
NSPoint clickLocationOnWindow = [self.window mouseLocationOutsideOfEventStream];
clickLocation = [self convertPoint:clickLocationOnWindow fromView:nil];
NSLog(#"%#", NSStringFromPoint(clickLocation));
}
- (void)mouseDragged:(NSEvent *)theEvent {
NSPoint mouseLocationOnWindow = [self.window mouseLocationOutsideOfEventStream];
NSPoint currentLocation = [self convertPoint:mouseLocationOnWindow fromView:nil];
CGFloat lowerX = fmin(clickLocation.x, currentLocation.x);
CGFloat lowerY = fmin(clickLocation.y, currentLocation.y);
CGFloat upperX = fmax(clickLocation.x, currentLocation.x);
CGFloat upperY = fmax(clickLocation.y, currentLocation.y);
selection = NSMakeRect(lowerX, lowerY, upperX-lowerX, upperY-lowerY);
[self setNeedsDisplay:YES];
NSLog(#"%#", NSStringFromRect(selection));
}
- (void)drawRect:(NSRect)dirtyRect
{
// Drawing code here.
NSLog(#"drawRect");
NSBezierPath *bp = [NSBezierPath bezierPathWithRect:selection];
[[NSColor blueColor] set];
[bp fill];
}
#end
The NSRect is calculated correctly, but when I call [self setNeedsDisplay], -drawRect is never called, and the rectangle is never drawn.
Is there any reason why -drawRect is never called on a PDFView subclass?
I have a similar use case. According to the docs, override PDFView's drawPage method instead. Continue to call setNeedsDisplay on the PDFView. It works, but it's a little slow. Working on overlaying a view right now instead.

Draggable NSTextField in Cocoa

I am developing an application to print Invoices. I write the following code to make the NSTextFields Draggable and match with Invoice-fields. It Works, but when a resize the window, the NSTextField, return to initial position. What can i do?
#interface DragTextField : NSTextField <NSWindowDelegate>
#property (readwrite) NSPoint location;
#end
#implementation DragTextField
#synthesize location;
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect
{
[super drawRect:dirtyRect];
}
- (BOOL) acceptsFirstMouse:(NSEvent *)theEvent
{
return YES;
}
- (void)mouseDown:(NSEvent *)theEvent
{
location = [theEvent locationInWindow];
self.location = [[self superview] convertPoint:[theEvent locationInWindow] fromView:nil];
}
- (void)mouseDragged:(NSEvent *)theEvent
{
NSPoint newDragLocation = [[self superview] convertPoint:[theEvent locationInWindow] fromView:nil];
NSPoint thisOrigin = [self frame].origin;
thisOrigin.x += (-self.location.x + newDragLocation.x);
thisOrigin.y += (-self.location.y + newDragLocation.y);
[self setFrameOrigin:thisOrigin];
self.location = newDragLocation;
}
- (void)mouseUp:(NSEvent *)theEvent {
[self setNeedsDisplay:YES];
}
You have to re-position your textfield whenever the window resizes by using delegate functions.
- (void)windowDidResize:(NSNotification *)notification{
//Change the position of your textfield depending on the window size
}

Resources