-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
An assortment of changes and additions to help with accessibility, alerts, tables, etc #2
base: develop
Are you sure you want to change the base?
Changes from all commits
381a8a0
2302bbe
7a8440c
c1df5a6
ae2cc28
a1e4c35
bf01731
593fce1
b1c3f1f
f81047e
c4da749
b02fd22
d913e5b
4421948
0c2b5d9
30c1ab5
6d87c87
2fbb22c
3f7d56f
b5a1ba4
2909593
1f59f5d
0602b78
f5e1969
14caee4
a5c279c
de8e342
501d50c
29078de
95d8a43
a885abb
24127b9
2bd004b
f4bc84a
fe29d16
77e0db4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,17 @@ | ||
import PackageDescription | ||
|
||
let package = Package( | ||
name: "UXKit", | ||
|
||
exclude: [ | ||
"UXKit.xcodeproj", | ||
"GNUmakefile", | ||
"LICENSE", | ||
"README.md", | ||
"xcconfig" | ||
] | ||
name: "UXKit", | ||
|
||
platforms: [ | ||
.macOS(.v10_15), .iOS(.v13), .tvOS(.v13) | ||
], | ||
|
||
exclude: [ | ||
"UXKit.xcodeproj", | ||
"GNUmakefile", | ||
"LICENSE", | ||
"README.md", | ||
"xcconfig" | ||
] | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,7 +21,7 @@ | |
* | ||
* NOTE: This one doesn't actually support an image :-/ | ||
*/ | ||
open class NSTableViewCell : NSTableCellView { | ||
open class NSTableViewCell : NSTableCellView, NSTextFieldDelegate { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure what to make of that (and the related changes below, including the 1st responder changes). The behaviour added seems specific to a certain use-case, not required for UIKit/AppKit compatibility? |
||
// Note: UITableViewCell has many more views to show selection state, | ||
// regular background, etc. | ||
|
||
|
@@ -56,14 +56,62 @@ | |
} | ||
private let style = Style() | ||
|
||
// provided for compatibility, though not really used. | ||
public enum SelectionStyle : Int { | ||
case none = 0 | ||
case blue = 1 | ||
case gray = 2 | ||
@available(iOS 7.0, *) | ||
case `default` = 3 | ||
} | ||
|
||
public var selectionStyle : SelectionStyle = .default | ||
|
||
// provided for compatibility, though not really used. | ||
public enum AccessoryType : Int { | ||
case none = 0 // don't show any accessory view | ||
case disclosureIndicator = 1 // regular chevron. doesn't track | ||
case detailDisclosureButton = 2 // info button w/ chevron. tracks | ||
case checkmark = 3 // checkmark. doesn't track | ||
|
||
@available(iOS 7.0, *) | ||
case detailButton = 4 // info button. tracks | ||
} | ||
|
||
public var accessoryType : AccessoryType = .none | ||
|
||
|
||
// provided for compatibility, though not really used. | ||
public enum EditingStyle : Int { | ||
case none = 0 | ||
case delete = 1 | ||
case insert = 2 | ||
} | ||
|
||
// These are provided for UIKit compatibility. Not actively used (yet). | ||
public var backgroundColor : UXColor { | ||
get { | ||
if let col = self.layer?.backgroundColor { | ||
return UXColor(cgColor: col)! | ||
} | ||
|
||
return UXColor.textBackgroundColor | ||
} | ||
|
||
set { | ||
self.layer?.backgroundColor = newValue.cgColor | ||
} | ||
} | ||
|
||
public init(style: UXTableViewCellStyle, reuseIdentifier id: String?) { | ||
/* TODO: SETUP: | ||
default: just label, no detail | ||
value1: label on the left, gray detail on the right (same row) | ||
value1: blue lable on the left 1/4, black detail on the right (same row) | ||
subtitle: label, below gray detail (two rows) | ||
*/ | ||
|
||
editing = false | ||
|
||
super.init(frame: UXRect()) | ||
|
||
if let id = id { | ||
|
@@ -80,7 +128,7 @@ | |
} | ||
|
||
private var installedConstraintSetup = ViewSetup.none | ||
private var requiredContraintSetup : ViewSetup { | ||
private var requiredConstraintSetup : ViewSetup { | ||
switch ( _textLabel, _detailTextLabel ) { | ||
case ( .none, .none ): return .none | ||
case ( .some, .none ): return .label | ||
|
@@ -93,7 +141,7 @@ | |
override open func updateConstraints() { | ||
super.updateConstraints() | ||
|
||
let required = requiredContraintSetup | ||
let required = requiredConstraintSetup | ||
guard installedConstraintSetup != required else { return } | ||
// Swift.print("from \(installedConstraintSetup) to \(required)") | ||
|
||
|
@@ -156,7 +204,7 @@ | |
let label = makeLabel() | ||
label.font = UXFont.systemFont(ofSize: style.labelSize) | ||
label.cell?.lineBreakMode = .byTruncatingTail | ||
|
||
#if false | ||
label.verticalAlignment = .middleAlignment // TBD: do we want this? | ||
// I'm still not quite sure why we even need this. The height of the | ||
|
@@ -179,6 +227,84 @@ | |
return label | ||
} | ||
} | ||
|
||
public override var acceptsFirstResponder: Bool { | ||
get { | ||
return true | ||
} | ||
} | ||
|
||
public override func becomeFirstResponder() -> Bool { | ||
if !self.editing { | ||
self.editing = true | ||
|
||
if let label = _textLabel { | ||
if #available(macOS 10.14, *) { | ||
label.backgroundColor = .selectedContentBackgroundColor | ||
} else { | ||
// Fallback on earlier versions | ||
label.backgroundColor = .selectedMenuItemColor | ||
} | ||
|
||
label.drawsBackground = true | ||
label.isEditable = true | ||
label.target = self | ||
label.action = #selector(didEditTableRow(_ :)) | ||
label.becomeFirstResponder() | ||
|
||
if label.delegate == nil { | ||
label.delegate = self | ||
} | ||
|
||
if let del = label.delegate as? UXTextFieldDelegate { | ||
del.textFieldDidBeginEditing(label) | ||
} | ||
} | ||
|
||
return true | ||
} | ||
|
||
return false | ||
} | ||
|
||
public override func resignFirstResponder() -> Bool { | ||
if self.editing { | ||
self.editing = false | ||
|
||
if let label = _textLabel { | ||
label.drawsBackground = false | ||
label.abortEditing() | ||
label.isEditable = false | ||
|
||
if let del = label.delegate as? UXTextFieldDelegate { | ||
del.textFieldDidEndEditing(label) | ||
} | ||
} | ||
} | ||
|
||
return true | ||
} | ||
|
||
var editing : Bool | ||
|
||
@objc func didEditTableRow(_ editor: Any) { | ||
NSLog("row was edited") | ||
if let label = _textLabel { | ||
if let del = label.delegate as? UXTextFieldDelegate { | ||
if del.textFieldShouldReturn(label) { | ||
// Only actually end the editing if the delegate says to. | ||
_ = self.resignFirstResponder() | ||
} | ||
} else { | ||
// if the delegate is not an instance of UXTextFieldDelegate, meaning it | ||
// doesn't support the UIKit enhancements, then just treat this as an end | ||
// to editing. | ||
// | ||
_ = self.resignFirstResponder() | ||
} | ||
} | ||
} | ||
|
||
|
||
var _detailTextLabel : UXLabel? = nil | ||
open var detailTextLabel : UXLabel? { | ||
|
@@ -224,7 +350,6 @@ | |
} | ||
} | ||
|
||
|
||
// MARK: - Separator line (TBD: should we draw this?) | ||
|
||
open var dividerColor : UXColor { return UXColor.lightGray } | ||
|
@@ -249,19 +374,20 @@ | |
// MARK: - Label Factory | ||
|
||
open func makeLabel() -> UXLabel { | ||
let v = NSTextField(frame: UXRect()) | ||
v.translatesAutoresizingMaskIntoConstraints = false | ||
|
||
/* configure as label */ | ||
v.isEditable = false | ||
v.isBezeled = false | ||
v.drawsBackground = false | ||
v.isSelectable = false // not for raw labels | ||
|
||
/* common */ | ||
v.alignment = .left | ||
|
||
return v | ||
let v = UXLabel(frame: UXRect()) | ||
v.cell = VerticallyCenteredTextFieldCell() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the centering of all axis really what UITableView does? |
||
v.translatesAutoresizingMaskIntoConstraints = false | ||
|
||
/* configure as label */ | ||
v.isEditable = false | ||
v.isBezeled = false | ||
v.drawsBackground = false | ||
v.isSelectable = false // not for raw labels | ||
|
||
/* common */ | ||
v.alignment = .center | ||
|
||
return v | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ | |
import Cocoa | ||
|
||
public typealias UXGestureRecognizer = NSGestureRecognizer | ||
public typealias UXGestureRecognizerDelegate = NSGestureRecognizerDelegate | ||
public typealias UXRotationGestureRecognizer = NSRotationGestureRecognizer | ||
public typealias UXPanGestureRecognizer = NSPanGestureRecognizer | ||
public typealias UXTapGestureRecognizer = NSClickGestureRecognizer | ||
|
@@ -16,6 +17,14 @@ | |
|
||
public extension NSView { | ||
|
||
enum SwipeDirection { | ||
case none | ||
case left | ||
case right | ||
case up | ||
case down | ||
} | ||
|
||
@discardableResult | ||
func on(gesture gr: UXGestureRecognizer, | ||
target: AnyObject, action: Selector) -> Self | ||
|
@@ -26,6 +35,25 @@ | |
return self | ||
} | ||
|
||
// This is how macOS handles Swipe gestures. | ||
override func swipe(with event: NSEvent) { | ||
let x : CGFloat = event.deltaX | ||
let y : CGFloat = event.deltaY | ||
var direction : SwipeDirection = .none | ||
|
||
if (x != 0) { | ||
direction = (x > 0) ? .left : .right | ||
} else if (y != 0) { | ||
direction = (y > 0) ? .up : .down | ||
} | ||
|
||
self.swipeGestureRecognized(inDirection: direction) | ||
} | ||
|
||
// Override this if you want to receive swipe gestures on your NSView. | ||
func swipeGestureRecognized(inDirection direction: SwipeDirection) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't that func have to be The whole swipe thing doesn't seem to have any peer in UIKit? It is more like a convenience addition to just AppKit? |
||
} | ||
|
||
} | ||
|
||
public extension UXTapGestureRecognizer { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is quite a bump :-) But I think I'm fine w/ that. I think I've actually bumped Xcode even further.