I've been wrestling with applying my custom styles (example) to the OSX desktop app I've been building, and I'm wondering what the paradigms/idioms are for doing this.
NSTextField
, NSButton
, and NSPopUpButton
for example)viewWillDraw
in some, init?
in others and making them all wantsLayer
and setting attributes on those layersThis seems extremely clumsy at best, and some visual things are impossible to handle this way, like adding padding to an NSTextField
. Am I supposed to create a (@Willeke informed me in the comments that it's possible to select a control's cell, and therefore assign a custom cell class by clicking on the control again)NSTextFieldCell
subclass and instantiate one and set it to the cell? Doing that breaks the text field altogether. I'm seeing other places that you should subclass NSButtonCell
, but I can't assign that as the class of a button in the X/Nib.
A lot of people are describing how to do certain changes to visual components in viewDidLoad
with a reference to a component, which seems very tedious if you have button/textfield styles that apply to all in the project. It seems like every visual change I've made with subclassing has been a nightmare, and there's no pattern for what visual changes are made where for different components. Subclassing seems like the best option for any size of project if you want to make your code reusable, but am I missing something? Is there some other pattern or idiom that I'm missing?
I did end up subclassing NSTextFieldCell
, and from this answer I derived the following for the specific problem I was facing:
class TGTextFieldCell: NSTextFieldCell {
override init(imageCell image: NSImage?) {
super.init(imageCell: image)
}
override init(textCell aString: String) {
super.init(textCell: aString)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func drawingRectForBounds(theRect: NSRect) -> NSRect {
let rectInset = NSMakeRect(theRect.origin.x + 7, theRect.origin.y + 7, theRect.size.width, theRect.size.height)
return super.drawingRectForBounds(rectInset)
}
}
It still seems that customizing views is much more complicated than it needs to be (moving on to customizing focus styles, for example), but that's a question to I have yet to hear a good answer.