Merge branch 'feature/tilet' into 'develop'

flipped off by default but only set if "touchUpInside" publisher is set

See merge request BPHV_MIPS/vds_ios!25
This commit is contained in:
Bruce, Matt R 2023-01-11 22:20:33 +00:00
commit 05a92f450d
15 changed files with 274 additions and 47 deletions

View File

@ -63,6 +63,7 @@
EA985BF9296C710100F2FF2E /* IconColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985BF8296C710100F2FF2E /* IconColor.swift */; };
EA985C1D296CD13600F2FF2E /* BundleManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C1C296CD13600F2FF2E /* BundleManager.swift */; };
EA985C23296E033A00F2FF2E /* TextArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C22296E033A00F2FF2E /* TextArea.swift */; };
EA985C2D296F03FE00F2FF2E /* TiletIconModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C2C296F03FE00F2FF2E /* TiletIconModels.swift */; };
EAA5EEB528ECBFB4003B3210 /* ImageLabelAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA5EEB428ECBFB4003B3210 /* ImageLabelAttribute.swift */; };
EAA5EEB728ECC03A003B3210 /* ToolTipLabelAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA5EEB628ECC03A003B3210 /* ToolTipLabelAttribute.swift */; };
EAA5EEB928ECD24B003B3210 /* Icons.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EAA5EEB828ECD24B003B3210 /* Icons.xcassets */; };
@ -175,6 +176,7 @@
EA985BF8296C710100F2FF2E /* IconColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconColor.swift; sourceTree = "<group>"; };
EA985C1C296CD13600F2FF2E /* BundleManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BundleManager.swift; sourceTree = "<group>"; };
EA985C22296E033A00F2FF2E /* TextArea.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextArea.swift; sourceTree = "<group>"; };
EA985C2C296F03FE00F2FF2E /* TiletIconModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TiletIconModels.swift; sourceTree = "<group>"; };
EAA5EEB428ECBFB4003B3210 /* ImageLabelAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLabelAttribute.swift; sourceTree = "<group>"; };
EAA5EEB628ECC03A003B3210 /* ToolTipLabelAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolTipLabelAttribute.swift; sourceTree = "<group>"; };
EAA5EEB828ECD24B003B3210 /* Icons.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Icons.xcassets; sourceTree = "<group>"; };
@ -498,6 +500,7 @@
EA985BE529688F6A00F2FF2E /* TiletBadgeModel.swift */,
EA985BE929689B6D00F2FF2E /* TiletSubTitleModel.swift */,
EA985BE72968951C00F2FF2E /* TiletTitleModel.swift */,
EA985C2C296F03FE00F2FF2E /* TiletIconModels.swift */,
);
path = Tilet;
sourceTree = "<group>";
@ -744,6 +747,7 @@
EAF7F0B5289C126F00B287F5 /* UILabel.swift in Sources */,
EA5E304C294CBDD00082B959 /* TileContainer.swift in Sources */,
EAF7F0A6289B0CE000B287F5 /* Resetable.swift in Sources */,
EA985C2D296F03FE00F2FF2E /* TiletIconModels.swift in Sources */,
EA89200428AECF4B006B9984 /* UITextField+Publisher.swift in Sources */,
EA3361C328902D960071C351 /* Toggle.swift in Sources */,
EAF7F0A0289AB7EC00B287F5 /* View.swift in Sources */,

View File

@ -29,7 +29,7 @@ open class Control: UIControl, Handlerable, ViewProtocol, Resettable {
open override var isSelected: Bool { didSet { didChange() } }
internal var enabledHighlight: Bool = true
internal var enabledHighlight: Bool = false
var isHighlightAnimating = false
open override var isHighlighted: Bool {

View File

@ -21,8 +21,6 @@ public struct IconName: RawRepresentable {
self.rawValue = name
}
internal static let paginationLeftArrow = IconName(name: "pagination-left-arrow")
internal static let paginationRightArrow = IconName(name: "pagination-right-arrow")
public static let checkmark = IconName(name: "checkmark")
internal static let checkmarkBold = IconName(name: "checkmark-bold")
public static let checkmarkAlt = IconName(name: "checkmark-alt")
@ -33,10 +31,18 @@ public struct IconName: RawRepresentable {
internal static let errorBold = IconName(name: "error-bold")
public static let info = IconName(name: "info")
internal static let infoBold = IconName(name: "info-bold")
public static let multipleDocuments = IconName(name: "multiple-documents")
public static let leftArrow = IconName(name: "left-arrow")
public static let leftCaret = IconName(name: "left-caret")
internal static let leftCaretBold = IconName(name: "left-caret-bold")
internal static let paginationLeftArrow = IconName(name: "pagination-left-arrow")
public static let rightArrow = IconName(name: "right-arrow")
public static let rightCaret = IconName(name: "right-caret")
internal static let rightCaretBold = IconName(name: "right-caret-bold")
internal static let paginationRightArrow = IconName(name: "pagination-right-arrow")
public static let warning = IconName(name: "warning")
internal static let warningBold = IconName(name: "warning-bold")
}

View File

@ -76,14 +76,14 @@ open class TileContainer: Control {
public var imageFallbackColor: Surface = .light { didSet{ didChange() } }
private var _width: CGFloat = 100
public var width: CGFloat {
private var _width: CGFloat?
public var width: CGFloat? {
get { return _width }
set {
if newValue > 100 {
if let newValue, newValue > 100 {
_width = newValue
} else {
_width = 100
_width = nil
}
didChange()
}
@ -152,14 +152,12 @@ open class TileContainer: Control {
addSubview(containerView)
addSubview(highlightView)
widthConstraint = widthAnchor.constraint(equalToConstant: width)
widthConstraint?.isActive = true
widthConstraint = widthAnchor.constraint(equalToConstant: 0)
heightGreaterThanConstraint = heightAnchor.constraint(greaterThanOrEqualToConstant: 44.0)
heightGreaterThanConstraint?.isActive = false
heightConstraint = heightAnchor.constraint(equalToConstant: width)
heightConstraint?.isActive = true
heightConstraint = heightAnchor.constraint(equalToConstant: 0)
backgroundImageView.pinToSuperView()
backgroundImageView.isUserInteractionEnabled = false
@ -219,7 +217,7 @@ open class TileContainer: Control {
//--------------------------------------------------
// MARK: - State
//--------------------------------------------------
var ratioSize: CGSize {
private func ratioSize(for width: CGFloat) -> CGSize {
var height: CGFloat = width
switch aspectRatio {
@ -272,21 +270,27 @@ open class TileContainer: Control {
containerBottomConstraint?.constant = -padding
containerTrailingConstraint?.constant = -padding
if aspectRatio == .none && height == nil{
if let width, aspectRatio == .none && height == nil{
widthConstraint?.constant = width
widthConstraint?.isActive = true
heightConstraint?.isActive = false
heightGreaterThanConstraint?.isActive = true
} else if let height {
} else if let height, let width {
widthConstraint?.constant = width
heightConstraint?.constant = height
heightConstraint?.isActive = true
widthConstraint?.isActive = true
heightGreaterThanConstraint?.isActive = false
} else {
let size = ratioSize
} else if let width {
let size = ratioSize(for: width)
widthConstraint?.constant = size.width
heightConstraint?.constant = size.height
widthConstraint?.isActive = true
heightConstraint?.isActive = true
heightGreaterThanConstraint?.isActive = false
} else {
widthConstraint?.isActive = false
heightConstraint?.isActive = false
}
}

View File

@ -13,6 +13,11 @@ import UIKit
@objc(VDSTilet)
open class Tilet: TileContainer {
public enum TextPosition {
case top
case bottom
}
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
@ -114,6 +119,16 @@ open class Tilet: TileContainer {
$0.fillColor = .red
}
private let iconContainerView = UIView().with {
$0.translatesAutoresizingMaskIntoConstraints = false
$0.backgroundColor = .clear
}
private var descriptiveIcon = Icon()
private var directionalIcon = Icon().with {
$0.name = .rightArrow
}
//--------------------------------------------------
// MARK: - Public Properties
//--------------------------------------------------
@ -122,7 +137,7 @@ open class Tilet: TileContainer {
open var textWidth: CGFloat? {
get { _textWidth }
set {
if let newValue, newValue > 44.0 && newValue <= width {
if let newValue, newValue > 44.0 {
_textWidth = newValue
if _textPercentage != nil {
_textPercentage = nil
@ -151,11 +166,33 @@ open class Tilet: TileContainer {
}
}
open var textPostion: TextPosition = .top { didSet { didChange() }}
//models
public var badgeModel: TiletBadgeModel? { didSet { didChange() }}
public var titleModel: TiletTitleModel? { didSet { didChange() }}
public var subTitleModel: TiletSubTitleModel? { didSet { didChange() }}
//only 1 Icon can be active
private var _descriptiveIconModel: TiletDescriptiveIcon?
public var descriptiveIconModel: TiletDescriptiveIcon? {
get { _descriptiveIconModel }
set {
_descriptiveIconModel = newValue;
_directionalIconModel = nil
didChange()
}
}
private var _directionalIconModel: TiletDirectionalIcon?
public var directionalIconModel: TiletDirectionalIcon? {
get { _directionalIconModel }
set {
_directionalIconModel = newValue;
_descriptiveIconModel = nil
didChange()
}
}
//icons
@ -174,8 +211,15 @@ open class Tilet: TileContainer {
width = 100
aspectRatio = .none
containerBackgroundColor = .black
addContentView(stackView)
let view = UIView().with {
$0.translatesAutoresizingMaskIntoConstraints = false
}
view.addSubview(stackView)
stackView.pinTop()
stackView.pinLeading()
stackView.pinTrailing()
stackView.bottomAnchor.constraint(lessThanOrEqualTo: view.bottomAnchor).isActive = true
addContentView(view)
//badge
badgeContainerView.addSubview(badge)
@ -193,8 +237,18 @@ open class Tilet: TileContainer {
titleLockupTrailingConstraint = titleLockup.trailingAnchor.constraint(equalTo: titleLockupContainerView.trailingAnchor)
titleLockupTrailingConstraint?.isActive = true
//stackView.addArrangedSubview(badgeContainerView)
//stackView.addArrangedSubview(titleLockupContainerView)
iconContainerView.addSubview(descriptiveIcon)
iconContainerView.addSubview(directionalIcon)
descriptiveIcon
.pinLeading()
.pinTop()
.pinBottom()
directionalIcon
.pinTrailing()
.pinTop()
.pinBottom()
}
@ -204,43 +258,33 @@ open class Tilet: TileContainer {
surface = .light
containerBackgroundColor = .black
//badge
badge.reset()
//models
badgeModel = nil
//titleLockup
titleLockup.reset()
titleModel = nil
subTitleModel = nil
descriptiveIconModel = nil
directionalIconModel = nil
}
//--------------------------------------------------
// MARK: - State
//--------------------------------------------------
open override func updateView() {
super.updateView()
//flip the surface for the titleLockup
let titleLockupSurface: Surface = containerBackgroundColor == .black ? .dark : .light
titleLockup.surface = titleLockupSurface
//update constraints
//badge
fileprivate func updateBadge() {
if let badgeModel {
if badgeContainerView.superview == nil {
stackView.insertArrangedSubview(badgeContainerView, at: 0)
}
badge.text = badgeModel.text
badge.fillColor = badgeModel.fillColor
badge.numberOfLines = badgeModel.numberOfLines
badge.surface = badgeModel.surface
badge.maxWidth = badgeModel.maxWidth
if badgeContainerView.superview == nil {
stackView.insertArrangedSubview(badgeContainerView, at: 0)
}
} else {
badge.reset()
badgeContainerView.removeFromSuperview()
}
}
fileprivate func updateTitleLockup() {
var showTitleLockup = false
@ -251,11 +295,10 @@ open class Tilet: TileContainer {
if let subTitleModel, !subTitleModel.text.isEmpty {
showTitleLockup = true
}
if showTitleLockup {
if titleLockupContainerView.superview == nil {
stackView.insertArrangedSubview(titleLockupContainerView, at: badgeContainerView.superview == nil ? 0 : 1)
}
//flip the surface for the titleLockup
titleLockup.surface = containerBackgroundColor == .black ? .dark : .light
//titleLockup
if let textWidth {
@ -288,11 +331,78 @@ open class Tilet: TileContainer {
if let style = subTitleModel?.typographicalStyle.value {
titleLockup.otherTypograpicalStyle = style
}
if titleLockupContainerView.superview == nil {
stackView.insertArrangedSubview(titleLockupContainerView, at: badgeContainerView.superview == nil ? 0 : 1)
}
} else {
titleLockupContainerView.removeFromSuperview()
}
}
fileprivate func updateIcons() {
//icons
var showIconContainerView = false
if let descriptiveIconModel {
descriptiveIcon.name = descriptiveIconModel.name
descriptiveIcon.size = descriptiveIconModel.size
descriptiveIcon.surface = descriptiveIconModel.surface
showIconContainerView = true
}
if let directionalIconModel {
directionalIcon.size = directionalIconModel.size
directionalIcon.surface = directionalIconModel.surface
showIconContainerView = true
}
//iconContainer
descriptiveIcon.isHidden = descriptiveIconModel == nil
directionalIcon.isHidden = directionalIconModel == nil
if showIconContainerView {
//spacing before iconContainerView
var view: UIView?
if badgeContainerView.superview != nil {
view = badgeContainerView
}
if titleLockupContainerView.superview != nil {
view = titleLockupContainerView
}
if let view {
stackView.setCustomSpacing(containerPadding.tiletSpacing, after: view)
}
if iconContainerView.superview == nil {
stackView.addArrangedSubview(iconContainerView)
}
} else {
iconContainerView.removeFromSuperview()
}
}
open override func updateView() {
super.updateView()
updateBadge()
updateTitleLockup()
updateIcons()
}
}
extension TileContainer.ContainerPadding {
fileprivate var tiletSpacing: CGFloat {
switch self {
case .twelve:
return 16
case .sixteen:
return 24
case .twentyFour:
return 32
case .thirtyTwo:
return 48
case .fourtyEight:
return 16
}
}
}

View File

@ -0,0 +1,31 @@
//
// TiletDescriptiveIconModel.swift
// VDS
//
// Created by Matt Bruce on 1/11/23.
//
import Foundation
import UIKit
public struct TiletDescriptiveIcon {
public var name: IconName
public var size: IconSize
public var surface: Surface
public init(name: IconName = .multipleDocuments, size: IconSize, surface: Surface) {
self.name = name
self.size = size
self.surface = surface
}
}
public struct TiletDirectionalIcon {
public var size: IconSize
public var surface: Surface
public init(size: IconSize, surface: Surface) {
self.size = size
self.surface = surface
}
}

View File

@ -17,6 +17,12 @@ public final class UIControlSubscription<SubscriberType: Subscriber, Control: UI
public init(subscriber: SubscriberType, control: Control, event: UIControl.Event) {
self.subscriber = subscriber
self.control = control
//allow highlight for VDS.Controls on "onClick" events
if let c = control as? VDS.Control, event == .touchUpInside {
c.enabledHighlight = true
}
control.addTarget(self, action: #selector(eventHandler), for: event)
}

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "left-arrow.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,3 @@
<svg id="Left_Arrow" data-name="Left Arrow" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 21.6 21.6">
<path d="M19.8,11.37251H4.01466l7.68305,7.61761-.817.80988L1.8,10.8l9.08069-9,.817.80988-7.683,7.61761H19.8Z"/>
</svg>

After

Width:  |  Height:  |  Size: 225 B

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "multiple-documents.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 21.6 21.6" style="enable-background:new 0 0 21.6 21.6;" xml:space="preserve">
<path d="M9.2,10.7L7.9,9.4l0.8-0.8l0.5,0.5l1.4-1.4l0.8,0.8L9.2,10.7z M17.2,8.5h-4.7v1.1h4.7V8.5z M11.4,11.9l-0.8-0.8l-1.4,1.4
L8.7,12l-0.8,0.8L9.2,14L11.4,11.9z M17.2,11.9h-4.7V13h4.7V11.9z M11.4,15.3l-0.8-0.8l-1.4,1.4l-0.5-0.5l-0.8,0.8l1.3,1.3
L11.4,15.3z M17.2,15.3h-4.7v1.1h4.7V15.3z M19.8,5.4v14.4H5.4v-3.6H1.8V1.8h14.4v3.6C16.2,5.4,19.8,5.4,19.8,5.4z M5.4,5.4h9.7V2.9
H2.9V15h2.5V5.4z M18.7,6.5H6.5v12.1h12.2V6.5z"/>
</svg>

After

Width:  |  Height:  |  Size: 785 B

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "right-arrow.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,3 @@
<svg id="Ebene_1" data-name="Ebene 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 21.6 21.6">
<path d="M10.71933,19.8l-.817-.80985,7.683-7.61765H1.8v-1.145H17.58533l-7.683-7.61765.817-.80985L19.8,10.8Z"/>
</svg>

After

Width:  |  Height:  |  Size: 218 B

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "right-caret.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,3 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 21.6 21.6">
<polygon points="6.71 19.8 5.89 18.981 14.07 10.799 5.89 2.619 6.71 1.8 15.71 10.799 6.71 19.8"/>
</svg>

After

Width:  |  Height:  |  Size: 205 B