2026-07-27 20:11:52 -07:00
|
|
|
//
|
|
|
|
|
// AudioSectionView.swift
|
|
|
|
|
// XIONControlPanel
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
import UIKit
|
|
|
|
|
|
|
|
|
|
final class AudioSectionView: UIView
|
|
|
|
|
{
|
|
|
|
|
var mixerSettingsHandler: (() -> Void)?
|
2026-07-27 20:51:39 -07:00
|
|
|
var bottomContentInset: CGFloat = 0.0
|
|
|
|
|
{
|
|
|
|
|
didSet
|
|
|
|
|
{
|
|
|
|
|
if oldValue != bottomContentInset {
|
|
|
|
|
setNeedsLayout()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-07-27 20:11:52 -07:00
|
|
|
|
|
|
|
|
private let _label = UILabel(frame: .zero)
|
|
|
|
|
private let _mixerSettingsButton = AudioActionButton(type: .custom)
|
|
|
|
|
|
|
|
|
|
override init(frame: CGRect)
|
|
|
|
|
{
|
|
|
|
|
super.init(frame: frame)
|
|
|
|
|
|
|
|
|
|
_label.font = UIFont(name: "Orbitron-Medium", size: 14.0)
|
|
|
|
|
_label.text = "audio"
|
|
|
|
|
_label.textColor = .white.withAlphaComponent(0.8)
|
|
|
|
|
addSubview(_label)
|
|
|
|
|
|
|
|
|
|
_mixerSettingsButton.setTitle("MIXER SETTINGS", for: .normal)
|
|
|
|
|
_mixerSettingsButton.titleLabel?.font = UIFont(name: "Orbitron-Medium", size: 21.0)
|
|
|
|
|
_mixerSettingsButton.setTitleColor(.white, for: .normal)
|
|
|
|
|
_mixerSettingsButton.accessibilityIdentifier = "audio.mixerSettings"
|
|
|
|
|
_mixerSettingsButton.accessibilityLabel = "Mixer Settings"
|
|
|
|
|
_mixerSettingsButton.addTarget(self, action: #selector(_showMixerSettings), for: .touchUpInside)
|
|
|
|
|
addSubview(_mixerSettingsButton)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
required init?(coder: NSCoder)
|
|
|
|
|
{
|
|
|
|
|
fatalError("unsupported")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override func layoutSubviews()
|
|
|
|
|
{
|
|
|
|
|
super.layoutSubviews()
|
|
|
|
|
|
|
|
|
|
let labelSpacing: CGFloat = 8.0
|
|
|
|
|
let labelSize = _label.sizeThatFits(bounds.size)
|
|
|
|
|
_label.frame = CGRect(
|
|
|
|
|
x: 0.0,
|
|
|
|
|
y: 0.0,
|
|
|
|
|
width: labelSize.width,
|
|
|
|
|
height: labelSize.height
|
|
|
|
|
)
|
|
|
|
|
_mixerSettingsButton.frame = CGRect(
|
|
|
|
|
x: 0.0,
|
|
|
|
|
y: _label.frame.maxY + labelSpacing,
|
|
|
|
|
width: bounds.width,
|
2026-07-27 20:51:39 -07:00
|
|
|
height: max(
|
|
|
|
|
0.0,
|
|
|
|
|
bounds.height - _label.frame.height - labelSpacing - bottomContentInset
|
|
|
|
|
)
|
2026-07-27 20:11:52 -07:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static func preferredHeight(forWidth width: CGFloat) -> CGFloat
|
|
|
|
|
{
|
|
|
|
|
let cellsPerRow: CGFloat
|
|
|
|
|
switch width {
|
|
|
|
|
case 500.0...:
|
|
|
|
|
cellsPerRow = 4.0
|
|
|
|
|
case 400.0..<500.0:
|
|
|
|
|
cellsPerRow = 3.0
|
|
|
|
|
default:
|
|
|
|
|
cellsPerRow = 2.0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let cellSpacing: CGFloat = 5.0
|
|
|
|
|
let cellDimension = floor(
|
|
|
|
|
(width / cellsPerRow) - ((cellSpacing * (cellsPerRow - 1.0)) / cellsPerRow)
|
|
|
|
|
)
|
|
|
|
|
let buttonHeight = rint(cellDimension / 1.5)
|
|
|
|
|
return 17.0 + 8.0 + buttonHeight
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@objc private func _showMixerSettings()
|
|
|
|
|
{
|
|
|
|
|
mixerSettingsHandler?()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private final class AudioActionButton: UIButton
|
|
|
|
|
{
|
|
|
|
|
private static let normalBackgroundColor = UIColor(white: 0.2, alpha: 1.0)
|
|
|
|
|
private static let highlightedBackgroundColor = UIColor(white: 0.8, alpha: 1.0)
|
|
|
|
|
|
|
|
|
|
override init(frame: CGRect)
|
|
|
|
|
{
|
|
|
|
|
super.init(frame: frame)
|
|
|
|
|
backgroundColor = Self.normalBackgroundColor
|
|
|
|
|
accessibilityTraits = .button
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
required init?(coder: NSCoder)
|
|
|
|
|
{
|
|
|
|
|
fatalError("unsupported")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override var isHighlighted: Bool
|
|
|
|
|
{
|
|
|
|
|
didSet
|
|
|
|
|
{
|
|
|
|
|
if isHighlighted {
|
|
|
|
|
backgroundColor = Self.highlightedBackgroundColor
|
|
|
|
|
} else {
|
|
|
|
|
UIView.animate(
|
|
|
|
|
withDuration: 0.35,
|
|
|
|
|
delay: 0.0,
|
|
|
|
|
options: [.allowUserInteraction, .beginFromCurrentState],
|
|
|
|
|
animations: {
|
|
|
|
|
self.backgroundColor = Self.normalBackgroundColor
|
|
|
|
|
},
|
|
|
|
|
completion: nil
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|