123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- //
- // KMCustomStepperView.swift
- // PDF Reader Pro
- //
- // Created by tangchao on 2023/6/8.
- //
- // 自定义步进器
- class KMCustomStepperView: KMHoverView {
- // private lazy var content_stackView: NSStackView = {
- // let view = NSStackView()
- // // 排列方向 默认为水平(horizontal)
- // view.orientation = .horizontal
- //// view.distribution = .fillProportionally
- // // 对齐方式
- //// view.alignment = .centerY
- // view.spacing = 1
- //
- // return view
- // }()
-
- private var _contentView = NSView()
- private var _backgroundView = NSView()
- var backgroundView: NSView {
- get {
- return self._backgroundView
- }
- }
-
- private var _textField = KMTextField()
- var textField: KMTextField {
- get {
- return self._textField
- }
- }
- private var _right_v_line = NSView()
- private var _right_up_button = NSButton()
- private var _right_h_line = NSView()
- private var _right_down_button = NSButton()
-
- private var _right_up_hover = KMHoverView()
- private var _right_down_hover = KMHoverView()
-
- var contentInset: NSEdgeInsets = NSEdgeInsetsZero {
- didSet {
- self.needsLayout = true
- }
- }
- var contentOffset: CGFloat = 8 {
- didSet {
- self.needsLayout = true
- }
- }
-
- var upItemImage: NSImage? {
- didSet {
- self._right_up_button.image = self.upItemImage
- }
- }
- var downItemImage: NSImage? {
- didSet {
- self._right_down_button.image = self.downItemImage
- }
- }
- var itemWidth: CGFloat = 20 {
- didSet {
- self.needsLayout = true
- }
- }
- var itemHeight: CGFloat = 14 {
- didSet {
- self.needsLayout = true
- }
- }
- var horizontalDividerHeight: CGFloat = 1 {
- didSet {
- self.needsLayout = true
- }
- }
- var horizontalDividerColor: NSColor = .lightGray {
- didSet {
- self._right_h_line.wantsLayer = true
- self._right_h_line.layer?.backgroundColor = self.horizontalDividerColor.cgColor
- }
- }
- var verticalDividerWidth: CGFloat = 1 {
- didSet {
- self.needsLayout = true
- }
- }
- var verticalDividerColor: NSColor = .lightGray {
- didSet {
- self._right_v_line.wantsLayer = true
- self._right_v_line.layer?.backgroundColor = self.verticalDividerColor.cgColor
- }
- }
-
- var kmEnabled = true {
- didSet {
- self.textField.isEnabled = self.kmEnabled
- self._right_up_button.isEnabled = self.kmEnabled
- self._right_down_button.isEnabled = self.kmEnabled
- }
- }
-
- var minValue: Double = CGFloat.leastNormalMagnitude
- var maxValue: Double = CGFloat.greatestFiniteMagnitude
- var increment: Double = 1
- var autorepeat = true
- // var valueWraps = false
- private var _kmValue: Double = 0
- var kmValue: Double {
- get {
- return self._kmValue
- }
- set {
- self._kmValue = newValue
- self.textField.stringValue = String(format: "%.f", self._kmValue)
- }
- }
-
- var rightHoverAction: ((NSButton, KMHoverAction)->Void)?
- weak var delegate: KMTextFieldDelegate?
-
- override var isFlipped: Bool {
- return true
- }
-
- override init(frame frameRect: NSRect) {
- super.init(frame: frameRect)
-
- self.initSubViews()
- self.initDefaultValue()
- }
-
- required init?(coder: NSCoder) {
- super.init(coder: coder)
-
- self.initSubViews()
- self.initDefaultValue()
- }
-
- func initSubViews() {
- self.addSubview(self._contentView)
-
- self._contentView.addSubview(self._backgroundView)
- self._contentView.addSubview(self._textField)
- self._contentView.addSubview(self._right_v_line)
- self._contentView.addSubview(self._right_up_button)
- self._contentView.addSubview(self._right_h_line)
- self._contentView.addSubview(self._right_down_button)
-
- self._right_up_button.target = self
- self._right_up_button.action = #selector(_right_up_button_action)
- self._right_down_button.target = self
- self._right_down_button.action = #selector(_right_down_button_action)
-
- self._textField.firstResponderHandler = { [unowned self] result in
- self.delegate?.km_didBecomeFirstResponder(textField: self)
- }
-
- self._contentView.addSubview(self._right_up_hover, positioned: .below, relativeTo: self._right_up_button)
- self._contentView.addSubview(self._right_down_hover, positioned: .below, relativeTo: self._right_down_button)
- self._right_up_hover.hoverAction = { [unowned self] _, action in
- guard let callback = self.rightHoverAction else {
- return
- }
- callback(self._right_up_button, action)
- }
- self._right_down_hover.hoverAction = { [unowned self] _, action in
- guard let callback = self.rightHoverAction else {
- return
- }
- callback(self._right_down_button, action)
- }
- }
-
- func initDefaultValue() {
- self.horizontalDividerColor = .lightGray
- self.verticalDividerColor = .lightGray
-
- self._textField.isBezeled = false
- self._textField.focusRingType = .none
- self._textField.lineBreakMode = .byTruncatingTail
- self._textField.drawsBackground = false
- self._textField.delegate = self
- self._textField.formatter = TextFieldFormatter()
-
- self._right_up_button.isBordered = false
- self._right_up_button.title = ""
- self._right_down_button.isBordered = false
- self._right_down_button.title = ""
-
- if let _image = NSImage(named: "btn_arrow_gray_up_s_norm_on") {
- self.upItemImage = _image
- }
- if let _image = NSImage(named: "btn_arrow_gray_down_s_norm_on") {
- self.downItemImage = _image
- }
- }
-
- override func layout() {
- super.layout()
-
- let width: CGFloat = NSWidth(self.bounds)
- let height: CGFloat = NSHeight(self.bounds)
-
- let leftMargin: CGFloat = self.contentInset.left
- let topMargin: CGFloat = self.contentInset.top
- let rightMargin: CGFloat = self.contentInset.right
- let bottomMargin: CGFloat = self.contentInset.bottom
- let contentW: CGFloat = width - leftMargin - rightMargin
- let contentH: CGFloat = height - topMargin - bottomMargin
-
- self._contentView.frame = self.bounds
- self._backgroundView.frame = NSMakeRect(leftMargin, topMargin, contentW, contentH)
-
- let itemW = self.itemWidth
- let itemH = self.itemHeight
- var tfH: CGFloat = 22
- if let font = self._textField.font {
- tfH = font.pointSize * 1.5
- }
- let tfX = leftMargin + self.contentOffset
- self._textField.frame = NSMakeRect(tfX, (height-tfH)*0.5, width-tfX-rightMargin-itemW-self.verticalDividerWidth-self.contentOffset, tfH)
-
- let itemX: CGFloat = width-rightMargin-itemW-1
- self._right_v_line.frame = NSMakeRect(itemX-self.verticalDividerWidth*0.5, 0, self.verticalDividerWidth, contentH)
- self._right_up_button.frame = NSMakeRect(itemX, height*0.5+self.horizontalDividerHeight*0.5, itemW, itemH)
- self._right_h_line.frame = NSMakeRect(itemX, (height-self.horizontalDividerHeight)*0.5, itemW, self.horizontalDividerHeight)
- self._right_down_button.frame = NSMakeRect(itemX, 1.5, itemW, itemH)
-
- self._right_up_hover.frame = self._right_up_button.frame
- self._right_down_hover.frame = self._right_down_button.frame
- }
-
- @objc private func _right_up_button_action() {
- let value = self.kmValue + self.increment
- if (value > self.maxValue) {
- self.kmValue = self.autorepeat ? self.minValue : self.maxValue
- } else {
- self.kmValue = value
- }
-
- self.delegate?.km_controlTextDidChange(textField: self)
- }
-
- @objc private func _right_down_button_action() {
- let value = self.kmValue - self.increment
- if (value < self.minValue) {
- self.kmValue = self.autorepeat ? self.maxValue : self.minValue
- } else {
- self.kmValue = value
- }
-
- self.delegate?.km_controlTextDidChange(textField: self)
- }
- }
- extension KMCustomStepperView: NSTextFieldDelegate {
- func control(_ control: NSControl, textShouldBeginEditing fieldEditor: NSText) -> Bool {
- if let should = self.delegate?.km_controlTextShouldBeginEditing(textField: self) {
- return should
- }
- return true
- }
-
- func controlTextDidBeginEditing(_ obj: Notification) {
- if (!self._textField.isEqual(to: obj.object)) {
- return
- }
-
- self.delegate?.km_controlTextDidBeginEditing(textField: self)
- }
-
- func controlTextDidChange(_ obj: Notification) {
- if (!self._textField.isEqual(to: obj.object)) {
- return
- }
-
- if (self._textField.doubleValue > self.maxValue) {
- self.kmValue = self.maxValue
- } else if (self._textField.doubleValue < self.minValue) {
- self.kmValue = self.minValue
- } else {
- self.kmValue = self.textField.doubleValue
- }
-
- self.delegate?.km_controlTextDidChange(textField: self)
- }
-
- func control(_ control: NSControl, textShouldEndEditing fieldEditor: NSText) -> Bool {
- if let should = self.delegate?.km_controlTextShouldEndEditing(textField: self) {
- return should
- }
- return true
- }
-
- func controlTextDidEndEditing(_ obj: Notification) {
- if (!self._textField.isEqual(to: obj.object)) {
- return
- }
-
- self.delegate?.km_controlTextDidEndEditing(textField: self)
- }
- }
|