Shadow is drawn in "main" Storyboard but not in any other storyboard - macos

I try to write my own comboBox as NSComboBox does not has features I need.
So, I subclassed an NSTextField and monitor the textinput and depending of the stringValue a TableView will get it's data.
So when the TableView should be displayed the TextFields superview will add the NSScrollView and adjust it's height and so on.
All of that works fine.
What goes not so well is the DropShadow.
So, I create a new Xcode-Project an in the main.Storyboard add a NSTextField and change the class to my Subclass.
As soon as I type text the TableView appears and has a the dropShadow.
Next I create a new Storyboard, add a new WindowController and do the same steps as in the main.Storyboard: Adding an NSTextField, change the class to my subclass.
Now I add a Button in the main.Storyboard which has an action to present the new Storyboard.
In the new storyboard the textfield and tableView behave as expected except that the TableView/ScrollView does not have any shadow.
Even when I change MainInterface in the Generals tab to the new Storyboard, no DropShadow for the TableView.
The Settings in the IB for both Storyboards look equal.
So, any hint how I can fix this?
Here is the code for adding and displaying the scrollView:
self.scrollView = NSScrollView(frame: NSRect.zero)
self.scrollView!.documentView = self.tableView
self.scrollView!.translatesAutoresizingMaskIntoConstraints = false
self.scrollViewHeightConstraint = NSLayoutConstraint(item: self.scrollView!, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100)
let topConstraint = NSLayoutConstraint(item: self.scrollView!, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 0)
let widthConstraint = NSLayoutConstraint(item: self.scrollView!, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.width, multiplier: 1, constant: 0)
let leadinghConstraint = NSLayoutConstraint(item: self.scrollView!, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.leading, multiplier: 1, constant: 0)
superview.addSubview(self.scrollView!)
superview.addConstraints([self.scrollViewHeightConstraint!,topConstraint,widthConstraint,leadinghConstraint])
let dropShadow = NSShadow()
dropShadow.shadowColor = NSColor.darkGray
dropShadow.shadowOffset = NSMakeSize(0, 10.0)
dropShadow.shadowBlurRadius = 3.0
self.scrollView!.wantsLayer = true
self.scrollView!.shadow = dropShadow

After a quick test … I found the "problem".
For the new ViewControllers view I had to set
self.view.wantsLayer = true

Related

NSScrollView truncate text and no scroll bar

I'm having difficult to set up NSScrollView for my text file display.
Defined a window with proper size:
......
let contentRect = NSMakeRect(0.0, 0.0, 800, 600)
let styleMask:NSWindow.StyleMask = [.titled, .closable, .miniaturizable, .resizable]
let window = NSWindow(contentRect:contentRect, styleMask:styleMask, backing:.buffered, defer:true)
window.minSize = NSMakeSize(800.0, 600.0)
window.isReleasedWhenClosed = false
window.tabbingMode = .disallowed
window.makeKeyAndOrderFront(nil)
window.center() // Wait until after makeKeyAndOrderFront so the window sizes properly first
window.title = NSLocalizedString("GCode File", comment:"GCode File window")
......
set up scrollview and put it into windows and then set up window constraints:
......
let scrollView = NSScrollView(frame: (window.contentView?.frame)!)
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.borderType = .noBorder
scrollView.backgroundColor = NSColor.gray
scrollView.hasVerticalScroller = true
window.contentView?.addSubview(scrollView)
window.contentView?.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[scrollView]|", options: [], metrics: nil, views: ["scrollView": scrollView]))
window.contentView?.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[scrollView]|", options: [], metrics: nil, views: ["scrollView": scrollView]))
......
set up clipview and put clipview as scrollview's content view and then configure scrollview and clipview's constraints:
......
let clipView = NSClipView()
clipView.translatesAutoresizingMaskIntoConstraints = false
scrollView.contentView = clipView
scrollView.addConstraint(NSLayoutConstraint(item: clipView, attribute: .left, relatedBy: .equal, toItem: scrollView, attribute: .left, multiplier: 1.0, constant: 0))
scrollView.addConstraint(NSLayoutConstraint(item: clipView, attribute: .top, relatedBy: .equal, toItem: scrollView, attribute: .top, multiplier: 1.0, constant: 0))
scrollView.addConstraint(NSLayoutConstraint(item: clipView, attribute: .right, relatedBy: .equal, toItem: scrollView, attribute: .right, multiplier: 1.0, constant: 0))
scrollView.addConstraint(NSLayoutConstraint(item: clipView, attribute: .bottom, relatedBy: .equal, toItem: scrollView, attribute: .bottom, multiplier: 1.0, constant: 0))
......
setup nstextview and load file content into nstextview:
......
var textView: NSTextView!
var textStorage: NSTextStorage!
textStorage = NSTextStorage()
let layoutManager = NSLayoutManager()
textStorage.addLayoutManager(layoutManager)
let textContainer = NSTextContainer(containerSize: window.contentView!.bounds.size)
layoutManager.addTextContainer(textContainer)
textView = NSTextView(frame: window.contentView!.bounds, textContainer: textContainer)
textView.isEditable = true
textView.isSelectable = true
textView.textStorage?.append(file)
scrollView.documentView = textView
......
Then I run the application, I got windows and content rendering up as:
What's wrong? I don't see the full text (truncated) that load from file and there is no vertical scroll bar shows as well. I believe there are some thing missed in my constraints configuration.
If any one have the experience, please advise!

How to add a custom UIView programmatically with Swift and see it in Interface Builder

I'm trying to add a UserView with controller to a view with Xcode 7 / Swift 2.0.
I was not able to figure out how to do this using Interface Builder, instead I added a NSView as a placeholder view and then add the view in code.
Is it possible to do it with the Interface Builder?
In the image, the orange is the place holder and the green is the user view:
When adding the view in code, I assume I have to add the constraints. I tried to use the constraintsWithVisualFormat like below, but when I add this, the view cannot be resized. I think it might be related to the priorities.
How do I get the green subview to fill the place holder container and be resizable?
override func windowDidLoad() {
super.windowDidLoad()
print("MainWindowController.windowDidLoad");
let view = UserView01();
self.m_viewPlaceHolder.addSubview(view.view);
let hor = NSLayoutConstraint.constraintsWithVisualFormat("H:|-10-[view]-10-|", options: .AlignAllLeft, metrics: nil, views: ["view" : view.view]);
let ver = NSLayoutConstraint.constraintsWithVisualFormat("V:|-10-[view]-10-|", options: .AlignAllLeft, metrics: nil, views: ["view" : view.view]);
NSLayoutConstraint.activateConstraints(hor);
NSLayoutConstraint.activateConstraints(ver);
}
First of all, there is no need to add any placeholders for the view you create programmatically. If you want to see it in the storyboard, I'd suggest you make the view class #IBDesignable:
#IBDesignable class UserView01: UIView {
// class declaration
}
The properties you want to be changing as you code should be declared as #IBInspectable similarly to class declaration.
To ensure the programmatically set constraints are executed you have to add the following line before the constraints code:
view.translatesAutoresizingMaskIntoConstraints = false
It tells Xcode to use the constraints you set without trying to add any automatically, which normally Xcode does. Other than that - your code should work fine.
There is also another way to add relative constraints which you might use as well:
let leadingConstraint = NSLayoutConstraint(item: view, attribute: .Leading, relatedBy: .Equal, toItem: placeholder, attribute: .Leading, multiplier: 1, constant: 20)
let trailingConstraint = NSLayoutConstraint(item: view, attribute: .Trailing, relatedBy: .Equal, toItem: placeholder, attribute: .Trailing, multiplier: 1, constant: 20)
let topConstraint = NSLayoutConstraint(item: view, attribute: .Top, relatedBy: .Equal, toItem: placeholder, attribute: .Top, multiplier: 1, constant: 20)
let bottomConstraint = NSLayoutConstraint(item: view, attribute: .Bottom, relatedBy: .Equal, toItem: placeholder, attribute: .Bottom, multiplier: 1, constant: 20)
view.addConstraints([leadingConstraint, trailingConstraint, topConstraint, bottomConstraint])
Just change the view and placeholder to the names you use for the view and its superview in your project.

Mac OS X use auto layout with view controller and allow window resize

I'm trying to add a view to fill the entire window in Mac OS X like so:
func viewDidLoad() {
sparkView = NSView(frame: CGRectMake(0, 0, 600,400))
self.view.addConstraint(NSLayoutConstraint(item: sparkView!, attribute: NSLayoutAttribute.Left, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Left, multiplier: 1, constant: 0))
self.view.addConstraint(NSLayoutConstraint(item: sparkView!, attribute: NSLayoutAttribute.Right, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Right, multiplier: 1, constant: 0))
self.view.addConstraint(NSLayoutConstraint(item: sparkView!, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 0))
self.view.addConstraint(NSLayoutConstraint(item: sparkView!, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 0))
sparkView?.contentCompressionResistancePriorityForOrientation(NSLayoutConstraintOrientation(rawValue: 499)!)
}
Why does this constrain the window size? If i do this I can't make the window bigger. I want sparkView to always fill the window. For context, this is created in the view controller that comes inside the NSWindow in storyboard.
I tried not setting the frame of sparkView, but then the window just collapses and there is no height at all.
Whenever you create a view programmatically and want to use auto layout to position it, you need to turn its translatesAutoresizingMaskIntoConstraints property to false.

Adding the WebView to NSPopover doesn't show the WebView, just the NSView

In the AppDelegate init() I have
popover = NSPopover()
popover.behavior = .Transient
popover.contentViewController = ContentViewController()
Now in the ContentViewController : NSViewController
override func loadView() {
view = NSView()
view.translatesAutoresizingMaskIntoConstraints = false
view.addConstraint(NSLayoutConstraint(
item: view, attribute: .Width, relatedBy: .Equal,
toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 580))
view.addConstraint(NSLayoutConstraint(
item: view, attribute: .Height, relatedBy: .Equal,
toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 425))
NSUserDefaults.standardUserDefaults().registerDefaults(["UserAgent": "Tick Mac App"])
let url = NSURL(string: tickExtensionURL )!
var request = NSURLRequest(URL: url)
var webView = WebView(frame: view.bounds)
webView.mainFrame.loadRequest(request)
view.addSubview(webView)
}
As you can see the view appears but not the WebView. What am i doing wrong?
you have to tell the controller whats its view so add this at the end of load view
self.view = view

how to instantiate an NSLayoutConstraint in swift? (Xcode 6.1.1)

I'm getting an error "Extra argument in call" pointing at the first parameter.
let imageView = UIImageView()
let imageHeight = 10.0
let heightConstraint = NSLayoutConstraint(imageView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .Height, multiplier: 1.0, constant: imageHeight)
I've also tried using item: imageView,..., but I get the same error.
I think the problem is that imageHeight is double, but the constructor expects a CGFloat, so try
let imageHeight: CGFloat = 10.0
and looks like there is one more little thing:
NSLayoutConstraint(item: imageView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .Height, multiplier: 1.0, constant: imageHeight)
you left the item before imageView, but you've mentioned that.

Resources