112 lines
2.9 KiB
Swift
112 lines
2.9 KiB
Swift
//
|
|
// RadioBaseButton.swift
|
|
// PrivadoVPN
|
|
//
|
|
// Created by Murad Shabanov on 29.07.2021.
|
|
// Copyright © 2021 Privado LLC. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import Cocoa
|
|
|
|
// MARK: - RadioBaseButton
|
|
|
|
public class RadioBaseButton: NSButton {
|
|
|
|
/// Oberver frame change to update style
|
|
private var sizeChangeObserver: NSKeyValueObservation?
|
|
|
|
/// Allow delection for button useful in Check bok stype
|
|
internal var allowDeselection: Bool {
|
|
return false
|
|
}
|
|
|
|
/// Keep the track of Selection and deselction
|
|
@objc dynamic public var isOn = false {
|
|
didSet {
|
|
if self.isOn != oldValue {
|
|
self.updateSelectionState()
|
|
self.callDelegate()
|
|
}
|
|
}
|
|
}
|
|
|
|
required public init?(coder aDecoder: NSCoder) {
|
|
super.init(coder: aDecoder)
|
|
self.setup()
|
|
}
|
|
|
|
public override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
self.setup()
|
|
}
|
|
|
|
public convenience init?(type buttonType: NSButton.ButtonType) {
|
|
return nil
|
|
}
|
|
|
|
/// Setup intial things required
|
|
internal func setup() {
|
|
// Add action here
|
|
self.addObserverSizeChange()
|
|
self.setupLayer()
|
|
}
|
|
|
|
public override func mouseDown(with event: NSEvent) {
|
|
super.mouseDown(with: event)
|
|
guard isEnabled else { return }
|
|
self.selectionAction()
|
|
}
|
|
|
|
/// Action handler of button for internal use
|
|
///
|
|
/// - Parameter sender: RadioButton
|
|
@objc internal func selectionAction() {
|
|
// If toggle enable, change selection state
|
|
if self.allowDeselection {
|
|
self.isOn = !self.isOn
|
|
} else if !isOn {
|
|
self.isOn = true
|
|
}
|
|
}
|
|
|
|
/// Update selection stage as button selected for deselected
|
|
public func updateSelectionState() {
|
|
if self.isOn {
|
|
self.updateActiveLayer()
|
|
} else {
|
|
self.updateInactiveLayer()
|
|
}
|
|
}
|
|
|
|
/// Setup layer that will for Radio button
|
|
/// This method can be called mutliple times
|
|
/// Do the stuff by overriding, then call super class method
|
|
internal func setupLayer() {
|
|
self.updateSelectionState()
|
|
}
|
|
|
|
/// Update active layer as button is selected
|
|
internal func updateActiveLayer() { }
|
|
|
|
/// Update inative later as button is deselected
|
|
internal func updateInactiveLayer() { }
|
|
|
|
/// call delegate as button selection state changes
|
|
internal func callDelegate() { }
|
|
|
|
}
|
|
|
|
// MARK:- frame change handler
|
|
extension RadioBaseButton {
|
|
|
|
private func addObserverSizeChange() {
|
|
self.sizeChangeObserver = observe(\RadioBaseButton.frame, changeHandler: self.sizeChangeObseveHandler)
|
|
}
|
|
|
|
private func sizeChangeObseveHandler(_ object: RadioBaseButton, _ change: NSKeyValueObservedChange<CGRect>) {
|
|
self.setupLayer()
|
|
}
|
|
|
|
}
|