How do you flip the coordinate system of an NSView? - objective-c

I have created an NSScrollView in interface builder that has a variable number of semi-unique NSViews that can be programmatically added and removed from it. When I add subViews to the documentView, they appear in the lower-left hand corner instead of the upper-left hand corner. I see that you can check the isFlipped bool to figure out if the view's coordinate system is flipped, but I cannot find a way to set it as flipped.
Anyone know what I'm missing?

In your NSView subclass, override isFlipped:
isFlipped
A Boolean value indicating whether the view uses a flipped coordinate system.
Declaration
var isFlipped: Bool { get }
Discussion
The default value of this property is false, which results in a non-flipped coordinate system.
[...]
If you want your view to use a flipped coordinate system, override this property and return true.
Source: isFlipped - NSView | Apple Developer Documentation

For anyone wishing to do this in Swift here's how you override in your custom class:
class FlippedView: NSView {
override var isFlipped {
get {
return true
}
}
}

The idea is that each individual view has its own way of drawing itself (for example, using human-calculated paths) that might get really wonky if you suddenly flip its coordinate plane (rasters might be fine while paths might draw upside-down, calculations might place things off-screen, Bézier control points might get twisted, etc.). So it's not settable, but subclasses can specify isFlipped because they should definitely know how the view is drawn.
Subclasses can also make it settable, but then they must expect it to change at any time.
As for code, here's Jay's answer in Swift 5:
open class FlippedView: NSView {
override var isFlipped: Bool { true }
}

Since Carl Carlson asked, here's Jay's answer in Objective-C:
Header (.h)
#interface XYZFlippedView: NSView
- (BOOL) isFlipped;
#end
Implementation (.m)
#implementation XYZFlippedView
- (BOOL) isFlipped
{
return YES;
}
#end

Related

Subclassing NSTextView makes undo impossible in Cocoa

I have a very simple Cocoa program. One window, with an NSTextView inside of it. In this configuration, the NSTextView operates exactly how you would expect it to. I can type, undo, redo, everything.
But then I subclass NSTextView, lets call it TextView. This new class does not override any methods, it's basically a blank subclass. I replace the NSTextView with my new subclass of it. I can type text into the TextView, but undo does not work. It just beeps at me. The undo menu item is greyed out. I would not expect this to happen, since TextView doesn't add any new code to the object inheritance structure.
What must I do to my TextView to re-enable undo?
GitHub project
XIB object hierarchy, "Text View" is my "TextView" class
Edit: upon further observation, there indeed was an edit in my subclass that caused the issue, as Mohamad Farhand opined.
overriding method : shouldChangeTextInRange cause this issue
i recommend you to check this link :
Cocoa: looking for a general strategy for programmatic manipulation of NSTextView storage without messing up undo
You may need to enable allowsUndo property of your subclassed TextView class.
#implementation TextView
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
self.allowsUndo = YES;
}
return self;
}
#end

How to create background for NSView when using storyboards with OS X

I know how I may be able to do this programmatically. I know that when creating storyboards for iOS it's very easy and is right there in the attributes inspector. However when creating storyboards for OS X, I don't see it for any of my view controllers or the view underneath it in Xcode 6.1.1
How can I change the background of the view without having to create a view controller associated with it. My application has a lot of views that are simple, but the background changes colour from one view to the next.
Here is another way to achieve the same effect.
Add NSBox under your NSView and adjust NSBox's frame as the same with the NSView.
Change Title position to None, Box type to Custom, Border Type to None
This is the screenshot:
And than add your NSView, NSButton, NSTextField or whatever as a subview of NSBox.
This is the result:
You shouldn't need a new viewController to change the background of an NSView. If you aren't subclassing NSView, then you can simply call:
myView.wantsLayer = true
myView.layer!.backgroundColor = CGColorGetConstantColor(kCGColorBlack)
I'm not sure if you can do it strictly in the storyboard, though you can likely set the wantsLayer = true in storyboard using the User Defined Runtime Attributes.
You can change a NSView's background color in the storyboard if you subclass NSView and assign the subclass to your view:
Using this subclass implementation:
import Cocoa
class ViewWithBackgroundColor : NSView {
#IBInspectable var backgroundColor: NSColor? {
get {
guard let layer = layer, backgroundColor = layer.backgroundColor else { return nil }
return NSColor(CGColor: backgroundColor)
}
set {
wantsLayer = true
layer?.backgroundColor = newValue?.CGColor
}
}
override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
}
The background color isn't shown at design time but at run-time.
Maybe somebody got an idea how to also update the view at design time (preferably without overriding the draw method).

NSScrollView how to start from top left corner

How to set scrollView document view to be pinned to top left corner? If scrollView is big enough/bigger than its content, everything is drawn from bottom to up and it not looks right. I have to override isFlipped of scrollView?
I was searching internet and overriding isFlipped to return trueis not everything. I don't want to make my documentView flipped because then I have to make changes in that class to make everything looks like I want.
I created simple NSView class as an container for elements that i want to have inside my scrollView and everything looks perfect. I hope this will help someone!
#interface FlippedView : NSView
#end
and implementation:
#implementation FlippedView
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
// Drawing code here.
}
- (BOOL) isFlipped
{
return YES;
}
#end
Swift 4 Method to invert axises :
from https://stackoverflow.com/a/40381180/5464805 thank's to Ben Leggiero :
import Cocoa
class FlippedView: NSView {
override var isFlipped: Bool { return true }
}
Then in the storyboard, set this class to the NSView below the NSClipView and it do the trick.
However it won't appear in StoryBoard so you'll have to build and run

NSStepper in NSTableCellView has no effect

I’m using a regular (not subclassed) NSTableCellView in a view-based table view. It has the initial image and text field views. I added an NSStepper to the view.
The text field is bound to tableCellView.objectValue.quantity.
The stepper’s value is bound to tableCellView.objectValue.quantity too.
The problem is that when running the app, when I click the stepper it doesn’t seem to get the mouse event, neither arrow gets highlighted, the value is not incremented or decremented.
If I set the double action of the table view it gets triggered if I double-click the stepper as if it was transparent.
What am I missing?
Thanks!
You should look at the documentation but easiest is that you need to subclass NSTableView and override this method to validate the proposed first responder. As the document states NSTableViews disallow some controls to be used unless the row is first selected. Even then it still may discard some.
- (BOOL)validateProposedFirstResponder:(NSResponder *)responder forEvent:(NSEvent *)event {
return YES;
}
Further to the correct answer from Robert Payne, with Swift you could add an extension to NSTableView and not subclass it.
extension NSTableView {
override public func validateProposedFirstResponder(responder: NSResponder, forEvent event: NSEvent?) -> Bool {
return true
}
}
And I'd like to emphasis that it's the NSTableView not the NSTableViewCell.

Changing UIPickerView row height

I'm working on a program for a class I'm taking and part of the program requires a UIPickerView with images in it. I have the picker up and running, but the height of the rows in the picker are still too small, causing the images (100x100) to overlap. I'm looking for a way to change the UIPickerView so that the images will fit in one row, without overlapping. Thanks
In the documentation for the UIPickerView, you have a link to the UIPickerViewDelegate protocol. There is a method that you can implement, pickerView:rowHeightForComponent:.
use this method,provide default as a delegete method.
objective-C
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component
{
return 40;
}
In Swift:
func pickerView(pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat
{
return 40
}
for more visit : real world implementation