Removed the old osxaltest. Not needed now. I'll just design grids against master.
This commit is contained in:
parent
ac3ee981b3
commit
885e7157d7
|
@ -1,175 +0,0 @@
|
|||
// 7 august 2015
|
||||
import Cocoa
|
||||
|
||||
struct BoxControl {
|
||||
var c: Control
|
||||
var stretchy: Bool
|
||||
var horzHuggingPri: NSLayoutPriority
|
||||
var vertHuggingPri: NSLayoutPriority
|
||||
}
|
||||
|
||||
class Box : NSView, Control {
|
||||
private var controls: [BoxControl]
|
||||
private var parent: Control?
|
||||
private var vertical: Bool
|
||||
private var padded: Bool
|
||||
|
||||
private var primaryDirPrefix: String
|
||||
private var secondaryDirPrefix: String
|
||||
private var primaryOrientation: NSLayoutConstraintOrientation
|
||||
private var secondaryOrientation: NSLayoutConstraintOrientation
|
||||
|
||||
// we implement a lack of stretchy controls by adding a stretchy view at the end of the view list when we assemble layouts
|
||||
// this is that view
|
||||
private var noStretchyView: NSView
|
||||
|
||||
init(vertical: Bool, padded: Bool) {
|
||||
self.controls = []
|
||||
self.parent = nil
|
||||
self.vertical = vertical
|
||||
self.padded = padded
|
||||
|
||||
self.primaryDirPrefix = "H:"
|
||||
self.secondaryDirPrefix = "V:"
|
||||
self.primaryOrientation = NSLayoutConstraintOrientation.Horizontal
|
||||
self.secondaryOrientation = NSLayoutConstraintOrientation.Vertical
|
||||
if self.vertical {
|
||||
self.primaryDirPrefix = "V:"
|
||||
self.secondaryDirPrefix = "H:"
|
||||
self.primaryOrientation = NSLayoutConstraintOrientation.Vertical
|
||||
self.secondaryOrientation = NSLayoutConstraintOrientation.Horizontal
|
||||
}
|
||||
|
||||
self.noStretchyView = NSView(frame: NSZeroRect)
|
||||
self.noStretchyView.translatesAutoresizingMaskIntoConstraints = false
|
||||
// make the view stretchy in both directions
|
||||
// you can tell this is correct by synthesizing an Add() in your head; see below
|
||||
setHorzHuggingPri(self.noStretchyView, myNSLayoutPriorityDefaultLow)
|
||||
setVertHuggingPri(self.noStretchyView, myNSLayoutPriorityDefaultLow)
|
||||
|
||||
super.init(frame: NSZeroRect)
|
||||
self.translatesAutoresizingMaskIntoConstraints = false
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("can't use this constructor, sorry")
|
||||
}
|
||||
|
||||
func Add(control: Control, _ stretchy: Bool) {
|
||||
var c: BoxControl
|
||||
|
||||
var view = control.View()
|
||||
c = BoxControl(
|
||||
c: control,
|
||||
stretchy: stretchy,
|
||||
horzHuggingPri: horzHuggingPri(view),
|
||||
vertHuggingPri: vertHuggingPri(view))
|
||||
self.addSubview(view)
|
||||
self.controls.append(c)
|
||||
|
||||
// if a control is stretchy, it should not hug in the primary direction
|
||||
// otherwise, it should *forcibly* hug
|
||||
if c.stretchy {
|
||||
setHuggingPri(view, myNSLayoutPriorityDefaultLow, self.primaryOrientation)
|
||||
} else {
|
||||
// TODO will default high work?
|
||||
setHuggingPri(view, myNSLayoutPriorityRequired, self.primaryOrientation)
|
||||
}
|
||||
|
||||
// make sure controls don't hug their secondary direction so they fill the width of the view
|
||||
setHuggingPri(view, myNSLayoutPriorityDefaultLow, self.secondaryOrientation)
|
||||
|
||||
self.relayout()
|
||||
}
|
||||
|
||||
func View() -> NSView {
|
||||
return self
|
||||
}
|
||||
|
||||
func SetParent(p: Control) {
|
||||
self.parent = p
|
||||
}
|
||||
|
||||
// TODO do we still need to set hugging? I think we do for stretchy controls...
|
||||
// TODO try unsetting spinbox intrinsics and seeing what happens
|
||||
private func relayout() {
|
||||
var constraint: String
|
||||
|
||||
if self.controls.count == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
self.removeConstraints(self.constraints)
|
||||
|
||||
// first collect the views
|
||||
var views = [String: NSView]()
|
||||
var n = 0
|
||||
var firstStretchy = -1
|
||||
var metrics = [String: CGFloat]()
|
||||
for c in self.controls {
|
||||
views["view\(n)"] = c.c.View()
|
||||
var s = fittingAlignmentSize(c.c.View())
|
||||
metrics["view\(n)width"] = s.width
|
||||
metrics["view\(n)height"] = s.height
|
||||
if firstStretchy == -1 && c.stretchy {
|
||||
firstStretchy = n
|
||||
}
|
||||
n++
|
||||
}
|
||||
|
||||
// if there are no stretchy controls, we must add the no-stretchy view
|
||||
// if there are, we must remove it
|
||||
if firstStretchy == -1 {
|
||||
if self.noStretchyView.superview == nil {
|
||||
self.addSubview(self.noStretchyView)
|
||||
}
|
||||
views["noStretchyView"] = self.noStretchyView
|
||||
} else {
|
||||
if self.noStretchyView.superview != nil {
|
||||
self.noStretchyView.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
// next, assemble the views in the primary direction
|
||||
// they all go in a straight line
|
||||
constraint = "\(self.primaryDirPrefix)|"
|
||||
for i in 0..<n {
|
||||
if self.padded && i != 0 {
|
||||
constraint += "-"
|
||||
}
|
||||
constraint += "[view\(i)"
|
||||
// implement multiple stretchiness properly
|
||||
if self.controls[i].stretchy && i != firstStretchy {
|
||||
constraint += "(==view\(firstStretchy))"
|
||||
}
|
||||
// if the control is not stretchy, restrict it to the fitting size
|
||||
if !self.controls[i].stretchy {
|
||||
if self.vertical {
|
||||
constraint += "(==view\(i)height)"
|
||||
} else {
|
||||
constraint += "(==view\(i)width)"
|
||||
}
|
||||
}
|
||||
constraint += "]"
|
||||
}
|
||||
if firstStretchy == -1 { // don't space between the last control and the no-stretchy view
|
||||
constraint += "[noStretchyView]"
|
||||
}
|
||||
constraint += "|"
|
||||
var constraints = mkconstraints(constraint, metrics, views)
|
||||
self.addConstraints(constraints)
|
||||
|
||||
// next: assemble the views in the secondary direction
|
||||
// each of them will span the secondary direction
|
||||
for i in 0..<n {
|
||||
constraint = "\(self.secondaryDirPrefix)|[view\(i)]|"
|
||||
var constraints = mkconstraints(constraint, nil, views)
|
||||
self.addConstraints(constraints)
|
||||
}
|
||||
if firstStretchy == -1 { // and again to the no-stretchy view
|
||||
constraint = "\(self.secondaryDirPrefix)|[noStretchyView]|"
|
||||
var constraints = mkconstraints(constraint, nil, views)
|
||||
self.addConstraints(constraints)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,169 +0,0 @@
|
|||
// 31 july 2015
|
||||
import Cocoa
|
||||
|
||||
// leave a whole lot of space around the alignment rect, just to be safe
|
||||
// TODO fine tune this
|
||||
// TODO de-duplicate this from spinbox.m
|
||||
class tBoxContainer : NSView {
|
||||
override var alignmentRectInsets: NSEdgeInsets {
|
||||
get {
|
||||
return NSEdgeInsetsMake(50, 50, 50, 50)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct tBoxChild {
|
||||
var c: tControl
|
||||
var stretchy: Bool
|
||||
}
|
||||
|
||||
// the swift bridge isn't perfect; it won't recognize these properly
|
||||
// thanks to Eridius in freenode/#swift-lang
|
||||
let myNSLayoutPriorityRequired: NSLayoutPriority = 1000
|
||||
let myNSLayoutPriorityDefaultHigh: NSLayoutPriority = 750
|
||||
let myNSLayoutPriorityDragThatCanResizeWindow: NSLayoutPriority = 510
|
||||
let myNSLayoutPriorityWindowSizeStayPut: NSLayoutPriority = 500
|
||||
let myNSLayoutPriorityDragThatCannotResizeWindow: NSLayoutPriority = 490
|
||||
let myNSLayoutPriorityDefaultLow: NSLayoutPriority = 250
|
||||
let myNSLayoutPriorityFittingSizeCompression: NSLayoutPriority = 50
|
||||
|
||||
class tBox : tControl {
|
||||
private var v: NSView
|
||||
private var children: [tBoxChild]
|
||||
private var vertical: Bool
|
||||
private var parent: tControl?
|
||||
private var spaced: Bool
|
||||
|
||||
// TODO rename to padded
|
||||
init(vertical: Bool, spaced: Bool) {
|
||||
self.v = tBoxContainer(frame: NSZeroRect)
|
||||
self.v.translatesAutoresizingMaskIntoConstraints = false
|
||||
self.children = []
|
||||
self.vertical = vertical
|
||||
self.parent = nil
|
||||
self.spaced = spaced
|
||||
}
|
||||
|
||||
func tAddControl(c: tControl, stretchy: Bool) {
|
||||
c.tSetParent(self, addToView: self.v)
|
||||
self.children.append(tBoxChild(
|
||||
c: c,
|
||||
stretchy: stretchy))
|
||||
self.tRelayout()
|
||||
}
|
||||
|
||||
func tSetParent(p: tControl, addToView v: NSView) {
|
||||
self.parent = p
|
||||
v.addSubview(self.v)
|
||||
}
|
||||
|
||||
// TODO make the other dimension not hug (as an experiment)
|
||||
func tFillAutoLayout(inout p: tAutoLayoutParams) {
|
||||
var hasStretchy = false
|
||||
if self.children.count != 0 {
|
||||
hasStretchy = self.actualLayoutWork()
|
||||
}
|
||||
p.view = self.v
|
||||
p.attachLeft = true
|
||||
p.attachTop = true
|
||||
// don't attach to the end if there weren't any stretchy controls
|
||||
if self.vertical {
|
||||
p.attachRight = true
|
||||
p.attachBottom = hasStretchy
|
||||
} else {
|
||||
p.attachRight = hasStretchy
|
||||
p.attachBottom = true
|
||||
}
|
||||
}
|
||||
|
||||
func actualLayoutWork() -> Bool {
|
||||
var orientation: NSLayoutConstraintOrientation
|
||||
// TODO don't use Int
|
||||
var i, n: Int
|
||||
var nStretchy: Int
|
||||
|
||||
self.v.removeConstraints(self.v.constraints)
|
||||
|
||||
orientation = NSLayoutConstraintOrientation.Horizontal
|
||||
if self.vertical {
|
||||
orientation = NSLayoutConstraintOrientation.Vertical
|
||||
}
|
||||
|
||||
var views = [String: NSView]()
|
||||
n = 0
|
||||
var predicates = [String]()
|
||||
var pp = tAutoLayoutParams()
|
||||
for child in self.children {
|
||||
var priority: NSLayoutPriority
|
||||
|
||||
pp.nonStretchyWidthPredicate = ""
|
||||
pp.nonStretchyHeightPredicate = ""
|
||||
// this also resets the hugging priority
|
||||
// TODO do this when adding and removing controls instead
|
||||
child.c.tFillAutoLayout(&pp)
|
||||
priority = myNSLayoutPriorityDefaultHigh // forcibly hug; avoid stretching out
|
||||
if child.stretchy {
|
||||
priority = myNSLayoutPriorityDefaultLow // do not forcibly hug; freely stretch out
|
||||
}
|
||||
if self.vertical {
|
||||
predicates.append(pp.nonStretchyHeightPredicate)
|
||||
} else {
|
||||
predicates.append(pp.nonStretchyWidthPredicate)
|
||||
}
|
||||
pp.view?.setContentHuggingPriority(priority, forOrientation:orientation)
|
||||
views[tAutoLayoutKey(n)] = pp.view
|
||||
n++
|
||||
}
|
||||
|
||||
// first string the views together
|
||||
var constraint = "H:|"
|
||||
if self.vertical {
|
||||
constraint = "V:|"
|
||||
}
|
||||
var firstStretchy = true
|
||||
// swift can't tell that nStretchy isn't used until firstStretchy becomes false
|
||||
nStretchy = 0
|
||||
for i in 0..<n {
|
||||
if self.spaced && i != 0 {
|
||||
constraint += "-"
|
||||
}
|
||||
constraint += "[" + tAutoLayoutKey(i)
|
||||
if self.children[i].stretchy {
|
||||
if firstStretchy {
|
||||
firstStretchy = false
|
||||
nStretchy = i
|
||||
} else {
|
||||
constraint += "(==" + tAutoLayoutKey(nStretchy) + ")"
|
||||
}
|
||||
} else {
|
||||
constraint += predicates[i]
|
||||
}
|
||||
constraint += "]"
|
||||
}
|
||||
constraint += "|"
|
||||
self.v.addConstraints(mkconstraints(constraint, views))
|
||||
// TODO do not release constraint; it's autoreleased?
|
||||
|
||||
// next make the views span the full other dimension
|
||||
// TODO make all of these the same width/height
|
||||
for i in 0..<n {
|
||||
constraint = "V:|["
|
||||
if self.vertical {
|
||||
constraint = "H:|["
|
||||
}
|
||||
constraint += tAutoLayoutKey(i) + "]|"
|
||||
self.v.addConstraints(mkconstraints(constraint, views))
|
||||
// TODO do not release constraint; it's autoreleased?
|
||||
}
|
||||
|
||||
// the caller needs to know if a control was stretchy
|
||||
// firstStretchy is false if there was one
|
||||
return !firstStretchy
|
||||
}
|
||||
|
||||
func tRelayout() {
|
||||
if self.parent != nil {
|
||||
self.parent?.tRelayout()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
// 31 july 2015
|
||||
import Cocoa
|
||||
|
||||
class Button : NSButton, Control {
|
||||
private var parent: Control?
|
||||
|
||||
init(_ text: String) {
|
||||
self.parent = nil
|
||||
|
||||
super.init(frame: NSZeroRect)
|
||||
self.title = text
|
||||
self.setButtonType(NSButtonType.MomentaryPushInButton)
|
||||
self.bordered = true
|
||||
self.bezelStyle = NSBezelStyle.RoundedBezelStyle
|
||||
self.font = NSFont.systemFontOfSize(NSFont.systemFontSizeForControlSize(NSControlSize.RegularControlSize))
|
||||
self.translatesAutoresizingMaskIntoConstraints = false
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("can't use this constructor, sorry")
|
||||
}
|
||||
|
||||
func View() -> NSView {
|
||||
return self
|
||||
}
|
||||
|
||||
func SetParent(p: Control) {
|
||||
self.parent = p
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
// 31 july 2015
|
||||
import Cocoa
|
||||
|
||||
protocol Control : class {
|
||||
func View() -> NSView
|
||||
func SetParent(p: Control)
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
// 31 july 2015
|
||||
import Cocoa
|
||||
|
||||
class Entry : NSTextField, Control {
|
||||
private var parent: Control?
|
||||
|
||||
init() {
|
||||
var cell: NSTextFieldCell
|
||||
|
||||
self.parent = nil
|
||||
|
||||
super.init(frame: NSZeroRect)
|
||||
self.selectable = true
|
||||
self.font = NSFont.systemFontOfSize(NSFont.systemFontSizeForControlSize(NSControlSize.RegularControlSize))
|
||||
self.bordered = false
|
||||
self.bezelStyle = NSTextFieldBezelStyle.SquareBezel
|
||||
self.bezeled = true
|
||||
cell = self.cell() as! NSTextFieldCell
|
||||
cell.lineBreakMode = NSLineBreakMode.ByClipping
|
||||
cell.scrollable = true
|
||||
self.translatesAutoresizingMaskIntoConstraints = false
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("can't use this constructor, sorry")
|
||||
}
|
||||
|
||||
func View() -> NSView {
|
||||
return self
|
||||
}
|
||||
|
||||
func SetParent(p: Control) {
|
||||
self.parent = p
|
||||
}
|
||||
|
||||
// by default a text entry has no intrinsic content width
|
||||
// in order for our layout containers to work, we need to give it one
|
||||
// give it what Interface Builder uses as a default
|
||||
// TODO verify against Interface Builder
|
||||
override var intrinsicContentSize: NSSize {
|
||||
get {
|
||||
var s = super.intrinsicContentSize
|
||||
s.width = 96
|
||||
return s
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
// 31 july 2015
|
||||
import Cocoa
|
||||
|
||||
class Label : NSTextField, Control {
|
||||
private var parent: Control?
|
||||
|
||||
init() {
|
||||
var cell: NSTextFieldCell
|
||||
|
||||
self.parent = nil
|
||||
|
||||
super.init(frame: NSZeroRect)
|
||||
self.stringValue = "Label"
|
||||
self.editable = false
|
||||
self.selectable = false
|
||||
self.drawsBackground = false
|
||||
self.font = NSFont.systemFontOfSize(NSFont.systemFontSizeForControlSize(NSControlSize.RegularControlSize))
|
||||
self.bordered = false
|
||||
self.bezelStyle = NSTextFieldBezelStyle.SquareBezel
|
||||
self.bezeled = false
|
||||
cell = self.cell() as! NSTextFieldCell
|
||||
cell.lineBreakMode = NSLineBreakMode.ByClipping
|
||||
cell.scrollable = true
|
||||
self.translatesAutoresizingMaskIntoConstraints = false
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("can't use this constructor, sorry")
|
||||
}
|
||||
|
||||
func View() -> NSView {
|
||||
return self
|
||||
}
|
||||
|
||||
func SetParent(p: Control) {
|
||||
self.parent = p
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
// 8 august 2015
|
||||
import Cocoa
|
||||
|
||||
func mkconstraints(constraint: String, metrics: [String: CGFloat]?, views: [String: NSView]) -> [AnyObject] {
|
||||
return NSLayoutConstraint.constraintsWithVisualFormat(
|
||||
constraint,
|
||||
options: NSLayoutFormatOptions(0),
|
||||
metrics: metrics,
|
||||
views: views)
|
||||
}
|
||||
|
||||
// the swift bridge isn't perfect; it won't recognize these properly
|
||||
// thanks to Eridius in freenode/#swift-lang
|
||||
let myNSLayoutPriorityRequired: NSLayoutPriority = 1000
|
||||
let myNSLayoutPriorityDefaultHigh: NSLayoutPriority = 750
|
||||
let myNSLayoutPriorityDragThatCanResizeWindow: NSLayoutPriority = 510
|
||||
let myNSLayoutPriorityWindowSizeStayPut: NSLayoutPriority = 500
|
||||
let myNSLayoutPriorityDragThatCannotResizeWindow: NSLayoutPriority = 490
|
||||
let myNSLayoutPriorityDefaultLow: NSLayoutPriority = 250
|
||||
let myNSLayoutPriorityFittingSizeCompression: NSLayoutPriority = 50
|
||||
|
||||
func horzHuggingPri(view: NSView) -> NSLayoutPriority {
|
||||
return view.contentHuggingPriorityForOrientation(NSLayoutConstraintOrientation.Horizontal)
|
||||
}
|
||||
|
||||
func vertHuggingPri(view: NSView) -> NSLayoutPriority {
|
||||
return view.contentHuggingPriorityForOrientation(NSLayoutConstraintOrientation.Vertical)
|
||||
}
|
||||
|
||||
func setHuggingPri(view: NSView, priority: NSLayoutPriority, orientation: NSLayoutConstraintOrientation) {
|
||||
view.setContentHuggingPriority(priority, forOrientation: orientation)
|
||||
}
|
||||
|
||||
func setHorzHuggingPri(view: NSView, priority: NSLayoutPriority) {
|
||||
setHuggingPri(view, priority, NSLayoutConstraintOrientation.Horizontal)
|
||||
}
|
||||
|
||||
func setVertHuggingPri(view: NSView, priority: NSLayoutPriority) {
|
||||
setHuggingPri(view, priority, NSLayoutConstraintOrientation.Vertical)
|
||||
}
|
||||
|
||||
// use the fitting size, not the intrinsic content size, for the case of recursive views without an intrinsic content size
|
||||
func fittingAlignmentSize(view: NSView) -> NSSize {
|
||||
var s = view.fittingSize
|
||||
// the fitting size is for a frame rect; we need an alignment rect
|
||||
var r = NSMakeRect(0, 0, s.width, s.height)
|
||||
r = view.alignmentRectForFrame(r)
|
||||
return r.size
|
||||
}
|
|
@ -1,122 +0,0 @@
|
|||
// 31 july 2015
|
||||
import Cocoa
|
||||
|
||||
var spaced = false
|
||||
var firstvert = true
|
||||
|
||||
// keep alive
|
||||
// apparently I'm not allowed to declare a variable and then assign to it first thing in a function
|
||||
// it'd be great if people weren't so afraid of nil pointers
|
||||
var keepAliveMainwin: Window? = nil
|
||||
|
||||
func appLaunched() {
|
||||
var mainwin = Window()
|
||||
mainwin.SetMargined(spaced)
|
||||
|
||||
var box = Box(vertical: firstvert, padded: spaced)
|
||||
mainwin.SetControl(box)
|
||||
|
||||
/*
|
||||
var hbox = {(entrys: Bool, buttons: Bool) -> Box in
|
||||
var hbox = Box(vertical: !firstvert, padded: spaced)
|
||||
hbox.Add(Entry(), entrys)
|
||||
hbox.Add(Button("Button"), buttons)
|
||||
return hbox
|
||||
}
|
||||
|
||||
box.Add(hbox(true, true), false)
|
||||
box.Add(hbox(true, false), false)
|
||||
box.Add(hbox(false, true), false)
|
||||
box.Add(hbox(false, false), false)
|
||||
*/
|
||||
|
||||
box.Add(Spinbox(), false)
|
||||
|
||||
var mkhbox = {() -> Box in
|
||||
Box(vertical: !firstvert, padded: spaced)
|
||||
}
|
||||
|
||||
var hbox = mkhbox()
|
||||
hbox.Add(Button("Button"), true)
|
||||
hbox.Add(Button("Button"), true)
|
||||
box.Add(hbox, false)
|
||||
|
||||
hbox = mkhbox()
|
||||
hbox.Add(Button("Button"), true)
|
||||
hbox.Add(Button("Button"), true)
|
||||
box.Add(hbox, false)
|
||||
|
||||
hbox = mkhbox()
|
||||
hbox.Add(Button("Button"), true)
|
||||
hbox.Add(Button("A"), false)
|
||||
hbox.Add(Button("BB"), false)
|
||||
hbox.Add(Button("CCC"), false)
|
||||
box.Add(hbox, false)
|
||||
|
||||
hbox = mkhbox()
|
||||
hbox.Add(Spinbox(), false)
|
||||
hbox.Add(Spinbox(), true)
|
||||
box.Add(hbox, false)
|
||||
|
||||
hbox = mkhbox()
|
||||
hbox.Add(Entry(), true)
|
||||
hbox.Add(Entry(), false)
|
||||
box.Add(hbox, false)
|
||||
|
||||
hbox = mkhbox()
|
||||
hbox.Add(Label(), false)
|
||||
box.Add(hbox, false)
|
||||
|
||||
hbox = mkhbox()
|
||||
var vbox = Box(vertical: firstvert, padded: spaced)
|
||||
vbox.Add(Button("Button"), true)
|
||||
hbox.Add(vbox, false)
|
||||
vbox = Box(vertical: firstvert, padded: spaced)
|
||||
vbox.Add(Button("Button 2"), true)
|
||||
hbox.Add(vbox, true)
|
||||
box.Add(hbox, false)
|
||||
|
||||
hbox = Box(vertical: firstvert, padded: spaced)
|
||||
vbox = mkhbox()
|
||||
vbox.Add(Button("Button"), true)
|
||||
hbox.Add(vbox, false)
|
||||
vbox = mkhbox()
|
||||
vbox.Add(Button("Button 2"), true)
|
||||
hbox.Add(vbox, true)
|
||||
box.Add(hbox, false)
|
||||
|
||||
mainwin.Show()
|
||||
|
||||
keepAliveMainwin = mainwin
|
||||
}
|
||||
|
||||
class appDelegate : NSObject, NSApplicationDelegate {
|
||||
func applicationDidFinishLaunching(note: NSNotification) {
|
||||
appLaunched()
|
||||
}
|
||||
|
||||
func applicationShouldTerminateAfterLastWindowClosed(app: NSApplication) -> Bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
for arg in dropFirst(Process.arguments) {
|
||||
if arg == "spaced" {
|
||||
spaced = true
|
||||
} else if arg == "horizontal" {
|
||||
firstvert = false
|
||||
} else {
|
||||
fatalError("unrecognized option \(arg)")
|
||||
}
|
||||
}
|
||||
|
||||
var app = NSApplication.sharedApplication()
|
||||
app.setActivationPolicy(NSApplicationActivationPolicy.Regular)
|
||||
// NSApplication.delegate is weak; if we don't use the temporary variable, the delegate will die before it's used
|
||||
var delegate = appDelegate()
|
||||
app.delegate = delegate
|
||||
app.run()
|
||||
}
|
||||
|
||||
main()
|
|
@ -1,93 +0,0 @@
|
|||
// 31 july 2015
|
||||
import Cocoa
|
||||
|
||||
var nspinbox = 0
|
||||
|
||||
class Spinbox : NSView, Control {
|
||||
private var t: NSTextField
|
||||
private var s: NSStepper
|
||||
private var parent: Control?
|
||||
|
||||
init() {
|
||||
var cell: NSTextFieldCell
|
||||
|
||||
self.t = NSTextField(frame: NSZeroRect)
|
||||
self.t.stringValue = "\(nspinbox)"
|
||||
nspinbox++
|
||||
self.t.selectable = true
|
||||
self.t.font = NSFont.systemFontOfSize(NSFont.systemFontSizeForControlSize(NSControlSize.RegularControlSize))
|
||||
self.t.bordered = false
|
||||
self.t.bezelStyle = NSTextFieldBezelStyle.SquareBezel
|
||||
self.t.bezeled = true
|
||||
cell = self.t.cell() as! NSTextFieldCell
|
||||
cell.lineBreakMode = NSLineBreakMode.ByClipping
|
||||
cell.scrollable = true
|
||||
self.t.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
// make the textbox grow horizontally and vertically
|
||||
setHorzHuggingPri(self.t, myNSLayoutPriorityDefaultLow)
|
||||
setVertHuggingPri(self.t, myNSLayoutPriorityDefaultLow)
|
||||
|
||||
self.s = NSStepper(frame: NSZeroRect)
|
||||
self.s.increment = 1
|
||||
self.s.valueWraps = false
|
||||
self.s.autorepeat = true
|
||||
self.s.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
// make the spinner grow vertically but not horizontally
|
||||
// TODO Required instead?
|
||||
setHorzHuggingPri(self.s, myNSLayoutPriorityDefaultHigh)
|
||||
setVertHuggingPri(self.s, myNSLayoutPriorityDefaultLow)
|
||||
|
||||
self.parent = nil
|
||||
|
||||
super.init(frame: NSZeroRect)
|
||||
self.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
self.addSubview(self.t)
|
||||
self.addSubview(self.s)
|
||||
var views = [
|
||||
"t": self.t,
|
||||
"s": self.s,
|
||||
]
|
||||
var constraints = mkconstraints("H:|[t]-[s]|", nil, views)
|
||||
self.addConstraints(constraints)
|
||||
constraints = mkconstraints("V:|[t]|", nil, views)
|
||||
self.addConstraints(constraints)
|
||||
constraints = mkconstraints("V:|[s]|", nil, views)
|
||||
self.addConstraints(constraints)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("can't use this constructor, sorry")
|
||||
}
|
||||
|
||||
// TODO leave only the required amount of space around the alignment rect
|
||||
// TODO even with this the stepper sometimes gets cut off at the bottom *anyway*
|
||||
override var alignmentRectInsets: NSEdgeInsets {
|
||||
get {
|
||||
return NSEdgeInsetsMake(50, 50, 50, 50)
|
||||
}
|
||||
}
|
||||
|
||||
func View() -> NSView {
|
||||
return self
|
||||
}
|
||||
|
||||
func SetParent(p: Control) {
|
||||
self.parent = p
|
||||
}
|
||||
|
||||
// TODO justify this
|
||||
// TODO no really, is this height the right way to go?
|
||||
// TODO in particular, why is making the NSTextField an Entry insufficient?
|
||||
// TODO restrict width to the text field only?
|
||||
override var intrinsicContentSize: NSSize {
|
||||
get {
|
||||
var s = super.intrinsicContentSize
|
||||
s.width = 96
|
||||
s.height = max(self.t.intrinsicContentSize.height, self.s.intrinsicContentSize.height)
|
||||
return s
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
// 1 august 2015
|
||||
import Cocoa
|
||||
|
||||
// auto layout helpers
|
||||
func isAmbiguous(view: NSView, indent: Int) {
|
||||
var s = String(count: indent, repeatedValue: " " as Character)
|
||||
println("\(s) \(view.className) \(view.hasAmbiguousLayout)")
|
||||
if view.hasAmbiguousLayout {
|
||||
view.window?.visualizeConstraints(view.superview!.constraints)
|
||||
}
|
||||
for subview in view.subviews {
|
||||
isAmbiguous(subview as! NSView, indent + 1)
|
||||
}
|
||||
}
|
||||
|
||||
class Window : NSWindow, Control {
|
||||
private var c: Control?
|
||||
private var margined: Bool
|
||||
|
||||
init() {
|
||||
self.c = nil
|
||||
self.margined = false
|
||||
// we have to initialize our own instance variables first, unfortunately (thanks erica in irc.freenode.net/#swift-lang)
|
||||
super.init(
|
||||
contentRect: NSMakeRect(0, 0, 320, 240),
|
||||
styleMask: (NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask),
|
||||
backing: NSBackingStoreType.Buffered,
|
||||
defer: true)
|
||||
self.title = "Auto Layout Test"
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("can't use this constructor, sorry")
|
||||
}
|
||||
|
||||
func SetControl(c: Control) {
|
||||
self.c = c
|
||||
var contentView = self.contentView as! NSView
|
||||
contentView.addSubview(self.c!.View())
|
||||
self.relayout()
|
||||
}
|
||||
|
||||
func SetMargined(m: Bool) {
|
||||
self.margined = m
|
||||
self.relayout()
|
||||
}
|
||||
|
||||
func Show() {
|
||||
self.cascadeTopLeftFromPoint(NSMakePoint(20, 20))
|
||||
self.makeKeyAndOrderFront(self)
|
||||
isAmbiguous(self.contentView as! NSView, 0)
|
||||
}
|
||||
|
||||
func View() -> NSView {
|
||||
fatalError("cannot call Window.View()")
|
||||
}
|
||||
|
||||
func SetParent(p: Control) {
|
||||
fatalError("cannot call Window.SetParent()")
|
||||
}
|
||||
|
||||
private func relayout() {
|
||||
if self.c == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var contentView = self.contentView as! NSView
|
||||
contentView.removeConstraints(contentView.constraints)
|
||||
|
||||
var views = [
|
||||
"view": self.c!.View(),
|
||||
]
|
||||
var margin = ""
|
||||
if self.margined {
|
||||
margin = "-"
|
||||
}
|
||||
|
||||
var constraint = "H:|" + margin + "[view]" + margin + "|"
|
||||
var constraints = mkconstraints(constraint, nil, views)
|
||||
contentView.addConstraints(constraints)
|
||||
|
||||
constraint = "V:|" + margin + "[view]" + margin + "|"
|
||||
constraints = mkconstraints(constraint, nil, views)
|
||||
contentView.addConstraints(constraints)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue