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.)
Related
I want to implement the functionality of pan gesture to a imageview, this imageview is a subview of a scroll view. the problem is when i try to scroll the scrollview the pan gesture of the imageview gets recognized, and the scrollview does not scroll.
please help me with this.
this is the code for initializing the pan to the uiimageview:
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(move:)];
[panRecognizer setMinimumNumberOfTouches:1];
[panRecognizer setMaximumNumberOfTouches:1];
[panRecognizer setDelegate:self];
[[[scrollView subviews] objectAtIndex:i] addGestureRecognizer:panRecognizer];
the imageview has the user set to "YES"
and the action for it
-(void)move:(UIPanGestureRecognizer *)sender
{
[[[[[sender view] superview] superview] superview] bringSubviewToFront:sender.view];
if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan) {
if ([[[sender view] superview] superview] == itemView) // adds the imageview in the item scroll
{
int tag = [[sender view] tag] / 100;
UIScrollView *tempScroll = (UIScrollView *)[itemView viewWithTag:-tag];
CGRect frame = CGRectFromString([itemFrameDict objectForKey:[NSString stringWithFormat:#"%i",[[sender view] tag]]]);
CGAffineTransform transform = temp.transform;
UIImageView *tempImageView = [[UIImageView alloc] initWithImage: [(UIImageView *) [sender view] image]];
tempImageView.tag = [[sender view] tag];
//NSLog(#"[sender view] superview] : %#", [[sender view] superview]);
tempImageView.frame = frame;
[tempImageView setTransform:transform];
[tempImageView setFrame:frame];
[tempImageView setUserInteractionEnabled:YES];
[tempScroll addSubview:tempImageView];
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(move:)];
[panRecognizer setMinimumNumberOfTouches:1];
[panRecognizer setMaximumNumberOfTouches:1];
[panRecognizer setDelegate:self];
[tempImageView addGestureRecognizer:panRecognizer];
UITapGestureRecognizer *singleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
[singleTapGestureRecognizer setNumberOfTapsRequired:1];
[tempImageView addGestureRecognizer:singleTapGestureRecognizer];
}
}
if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateChanged)
{
CGPoint translatedPoint = [sender locationInView:[[sender view] superview]] ;
newTranslatedPoint = [[[sender view] superview] convertPoint:translatedPoint toView:self.view];
if ([sender view].frame.size.width == 35 && [sender view].frame.size.height == 35)
[[sender view] sizeToFit];
[sender view].center = CGPointMake(newTranslatedPoint.x, newTranslatedPoint.y); //startFrame;
[self.view addSubview:[sender view]];
}
if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded)
{
CGPoint newPoint = [[[sender view] superview] convertPoint:newTranslatedPoint toView:itemView];
if (newPoint.y < 0)// || !viewUp)
{
//NSLog(#" baseView");
[baseView addSubview:[sender view]];
UITapGestureRecognizer *doubleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleDoubleTap:)];
[doubleTapGestureRecognizer setNumberOfTapsRequired:2];
[[sender view] addGestureRecognizer:doubleTapGestureRecognizer];
UIPinchGestureRecognizer *pinchRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(scale:)];
[pinchRecognizer setDelegate:self];
[[sender view] addGestureRecognizer:pinchRecognizer];
UIRotationGestureRecognizer *rotationRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotate:)];
[rotationRecognizer setDelegate:self];
[[sender view] addGestureRecognizer:rotationRecognizer];
}
else if (newPoint.y > 0)// && viewUp )
{
//NSLog(#" itemView");
int tag = [[sender view] tag] / 100;
UIScrollView *tempScroll = (UIScrollView *)[itemView viewWithTag:-tag];
CGRect frame = CGRectFromString([itemFrameDict objectForKey:[NSString stringWithFormat:#"%i",[[sender view] tag]]]);
CGAffineTransform transform = temp.transform;
[[sender view] setTransform:transform];
[[sender view] setFrame:frame];
[tempScroll addSubview:[sender view]];
}
}
}
I'm not sure I understand what you're trying to achieve exactly by using a UIPanGestureRecognizer on a UIImageView that is already in a UIScrollView. But from your description, it sounds like you want the UIScrollView to do it's thing and for the UIPanGestureRecognizer to not block that. I believe you need to implement this delegate method for your UIPanGestureRecognizer:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
Please read the UIGestureRecognizerDelegate Protocol reference in regards to allowing simultaneous gesture recognition. According to the documentation:
The default implementation returns NO—no two gestures can be
recognized simultaneously.
/* EDIT */
From UIPanGestureRecognizer - Only vertical or horizontal:
Implement just one direction for a UIPanGestureRecognizer. This is for a vertical pan:
- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)panGestureRecognizer {
CGPoint translation = [panGestureRecognizer translationInView:someView];
return fabs(translation.y) > fabs(translation.x);
}
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.
I'm working at a custom Window object that is displayed as child in a parent Window.
For this object I'd like to create an animation like that of an NSPopover.
My first idea is to create a Screenshot of the child Window, than animate it using Core Animation and finally showing the real Window.
Before begging the implementation I would like to know if exists a better method and what you think about my solution.
It's not trivial. Here's how I do it:
#interface ZoomWindow : NSWindow
{
CGFloat animationTimeMultiplier;
}
#property (nonatomic, readwrite, assign) CGFloat animationTimeMultiplier;
#end
#implementation ZoomWindow
#synthesize animationTimeMultiplier;
- (NSTimeInterval)animationResizeTime: (NSRect)newWindowFrame
{
float multiplier = animationTimeMultiplier;
if (([[NSApp currentEvent] modifierFlags] & NSShiftKeyMask) != 0) {
multiplier *= 10;
}
return [super animationResizeTime: newWindowFrame] * multiplier;
}
#end
#implementation NSWindow (PecuniaAdditions)
- (ZoomWindow*)createZoomWindowWithRect: (NSRect)rect
{
// Code mostly from http://www.noodlesoft.com/blog/2007/06/30/animation-in-the-time-of-tiger-part-1/
// Copyright 2007 Noodlesoft, L.L.C.. All rights reserved.
// The code is provided under the MIT license.
// The code has been extended to support layer-backed views. However, only the top view is
// considered here. The code might not produce the desired output if only a subview has its layer
// set. So better set it on the top view (which should cover most cases).
NSImageView *imageView;
NSImage *image;
NSRect frame;
BOOL isOneShot;
frame = [self frame];
isOneShot = [self isOneShot];
if (isOneShot) {
[self setOneShot: NO];
}
BOOL hasLayer = [[self contentView] wantsLayer];
if ([self windowNumber] <= 0) // <= 0 if hidden
{
// We need to temporarily switch off the backing layer of the content view or we get
// context errors on the second or following runs of this code.
[[self contentView] setWantsLayer: NO];
// Force window device. Kinda crufty but I don't see a visible flash
// when doing this. May be a timing thing wrt the vertical refresh.
[self orderBack: self];
[self orderOut: self];
[[self contentView] setWantsLayer: hasLayer];
}
// Capture the window into an off-screen bitmap.
image = [[NSImage alloc] initWithSize: frame.size];
[[self contentView] lockFocus];
NSBitmapImageRep* rep = [[NSBitmapImageRep alloc] initWithFocusedViewRect: NSMakeRect(0.0, 0.0, frame.size.width, frame.size.height)];
[[self contentView] unlockFocus];
[image addRepresentation: rep];
// If the content view is layer-backed the above initWithFocusedViewRect call won't get the content
// of the view (seems it doesn't work for CALayers). So we need a second call that captures the
// CALayer content and copies it over the captured image (compositing so the window frame and its content).
if (hasLayer)
{
NSRect contentFrame = [[self contentView] bounds];
int bitmapBytesPerRow = 4 * contentFrame.size.width;
CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
CGContextRef context = CGBitmapContextCreate (NULL,
contentFrame.size.width,
contentFrame.size.height,
8,
bitmapBytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);
[[[self contentView] layer] renderInContext: context];
CGImageRef img = CGBitmapContextCreateImage(context);
CFRelease(context);
NSImage *subImage = [[NSImage alloc] initWithCGImage: img size: contentFrame.size];
CFRelease(img);
[image lockFocus];
[subImage drawAtPoint: NSMakePoint(0, 0)
fromRect: NSMakeRect(0, 0, contentFrame.size.width, contentFrame.size.height)
operation: NSCompositeCopy
fraction: 1];
[image unlockFocus];
}
ZoomWindow *zoomWindow = [[ZoomWindow alloc] initWithContentRect: rect
styleMask: NSBorderlessWindowMask
backing: NSBackingStoreBuffered
defer: NO];
zoomWindow.animationTimeMultiplier = 0.3;
[zoomWindow setBackgroundColor: [NSColor colorWithDeviceWhite: 0.0 alpha: 0.0]];
[zoomWindow setHasShadow: [self hasShadow]];
[zoomWindow setLevel: [self level]];
[zoomWindow setOpaque: NO];
[zoomWindow setReleasedWhenClosed: NO];
[zoomWindow useOptimizedDrawing: YES];
imageView = [[NSImageView alloc] initWithFrame: [zoomWindow contentRectForFrameRect: frame]];
[imageView setImage: image];
[imageView setImageFrameStyle: NSImageFrameNone];
[imageView setImageScaling: NSScaleToFit];
[imageView setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
[zoomWindow setContentView: imageView];
[self setOneShot: isOneShot];
return zoomWindow;
}
- (void)fadeIn
{
[self setAlphaValue: 0.f];
[self orderFront: nil];
[NSAnimationContext beginGrouping];
[[NSAnimationContext currentContext] setDuration: 0.3];
[[self animator] setAlphaValue: 1.f];
[NSAnimationContext endGrouping];
}
- (void)zoomInWithOvershot: (NSRect)overshotFrame withFade: (BOOL)fade makeKey: (BOOL)makeKey
{
[self setAlphaValue: 0];
NSRect frame = [self frame];
ZoomWindow *zoomWindow = [self createZoomWindowWithRect: frame];
zoomWindow.alphaValue = 0;
[zoomWindow orderFront: self];
NSDictionary *windowResize = #{NSViewAnimationTargetKey: zoomWindow,
NSViewAnimationEndFrameKey: [NSValue valueWithRect: overshotFrame],
NSViewAnimationEffectKey: NSViewAnimationFadeInEffect};
NSArray *animations = #[windowResize];
NSViewAnimation *animation = [[NSViewAnimation alloc] initWithViewAnimations: animations];
[animation setAnimationBlockingMode: NSAnimationBlocking];
[animation setAnimationCurve: NSAnimationEaseIn];
[animation setDuration: 0.2];
[animation startAnimation];
zoomWindow.animationTimeMultiplier = 0.5;
[zoomWindow setFrame: frame display: YES animate: YES];
[self setAlphaValue: 1];
if (makeKey) {
[self makeKeyAndOrderFront: self];
} else {
[self orderFront: self];
}
[zoomWindow close];
}
This is implemented in an NSWindow category. So you can call:
- (void)zoomInWithOvershot: (NSRect)overshotFrame withFade: (BOOL)fade makeKey: (BOOL)makeKey
on any NSWindow.
I should add that I haven't been able to get both animations to run at the same time (fade and size), but the effect is quite similar to how NSPopover does it. Maybe someone else can fix the animation issue.
Needless to say this code works on 10.6 too where you don't have NSPopover (that's why I have written it in the first place).
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.
How to resize an extra box with disclosure triangle in Cocoa?
- (IBAction)disclosureTriangleClicked:(id)sender {
NSWindow *window =[sender window];
NSRect frame = [window frame];
[otherBox frame].size.height +14;
switch([sender state]) {
case NSOnState:
[otherBox setHidden:NO];
//Must resize!
break;
case NSOffState:
[otherBox setHidden:YES];
//Must resize!
break;
default:
break;
}
- (IBAction)disclosureTriangleClicked:(id)sender {
NSWindow *window =[sender window];
NSRect frameWinOld = [window frame];
CGFloat heightWinOld = frameWinOld.size.height;
NSRect frameOtherBox = [otherBox frame];
CGFloat heightOtherBoxWithMargin = frameOtherBox.size.height +14;
switch([sender state]) {
case NSOnState:
[window setFrame:NSRectMake(frameWinOld.origin.x, frameWinOld.origin.y, frameWinOld.width, frameWinOld.height + heightOtherBoxWithMargin) display:YES];
[otherBox setHidden:NO];
break;
case NSOffState:
[window setFrame:NSRectMake(frameWinOld.origin.x, frameWinOld.origin.y, frameWinOld.width, frameWinOld.height - heightOtherBoxWithMargin) display:YES];
[otherBox setHidden:YES];
break;
default:
break;
}