diff --git a/VDS/Components/InputStepper/InputStepper.swift b/VDS/Components/InputStepper/InputStepper.swift index 3637723d..92730f20 100644 --- a/VDS/Components/InputStepper/InputStepper.swift +++ b/VDS/Components/InputStepper/InputStepper.swift @@ -138,12 +138,7 @@ open class InputStepper: EntryFieldBase { } /// The size of the input stepper. Defaults to 'large'. - open var size: Size = .large { - didSet { - updateStepperContainerViewSize() - setNeedsUpdate() - } - } + open var size: Size = .large { didSet { setNeedsUpdate() } } /// Accepts any text or character to appear next to input stepper value. open var trailingText: String? { didSet { setNeedsUpdate() } } @@ -205,10 +200,7 @@ open class InputStepper: EntryFieldBase { // MARK: - Configuration Properties //-------------------------------------------------- internal override var containerSize: CGSize { CGSize(width: size.minWidth, height: size.minHeight) } - - internal let labelColorConfiguration = SurfaceColorConfiguration(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark) - internal let labelDisabledColorConfiguration = SurfaceColorConfiguration(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark) - + //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- @@ -216,12 +208,19 @@ open class InputStepper: EntryFieldBase { /// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations. open override func setup() { super.setup() - // Set initial states defaultValue = 0 containerView.isEnabled = false statusIcon.isHidden = true + //override the default settings since the containerView + //fieldStackView relationShip needs to be updated + //we are not applying spacing either in the edges since this + //is the view that will take place of the containerView for the + //design of the original "containerView". This will get refactored at + //some point. + fieldStackView.applyAlignment(.leading) + // Add listeners decrementButton.onClick = { _ in self.decrementButtonClick() } incrementButton.onClick = { _ in self.incrementButtonClick() } @@ -238,17 +237,15 @@ open class InputStepper: EntryFieldBase { // Set space between decrement button, label, and increment button relative to input Stepper size. stepperStackView.setCustomSpacing(size.space, after: decrementButton) stepperStackView.setCustomSpacing(size.space, after: textLabel) - - // Update Edge insets relative to input Stepper size. - stepperStackView.pinToSuperView(.uniform(size.padding)) - + // stepperContainerView for controls in EntryFieldBase.controlContainerView stepperContainerView.addSubview(stepperStackView) - stepperWidthConstraint = stepperContainerView.widthAnchor.constraint(equalToConstant: containerSize.width) - stepperWidthConstraint?.deactivate() - stepperHeightConstraint = stepperContainerView.heightAnchor.constraint(equalToConstant: containerSize.height) - stepperHeightConstraint?.deactivate() + // Update Edge insets relative to input Stepper size. + stepperStackView.pinToSuperView(.uniform(size.padding)) + + stepperWidthConstraint = stepperContainerView.width(constant: containerSize.width, priority: .required) + stepperHeightConstraint = stepperContainerView.height(constant: containerSize.height, priority: .required) return stepperContainerView } @@ -259,19 +256,12 @@ open class InputStepper: EntryFieldBase { statusIcon.isHidden = true // Update label text, style, color, ande surface. + textLabel.isEnabled = isEnabled + textLabel.surface = surface textLabel.text = "\(_defaultValue) " + (trailingText ?? "") textLabel.textStyle = size.textStyle - textLabel.textColorConfiguration = !isEnabled ? labelDisabledColorConfiguration.eraseToAnyColorable() : labelColorConfiguration.eraseToAnyColorable() - textLabel.surface = surface - // Update increment and decrement button. updateButtonStates() - - // Update stepper container border and corner radius. - updateContainerWidthWithPercentage() - updateInputStepperWidth() - updateStepperView() - setNeedsLayout() } open override var accessibilityElements: [Any]? { @@ -314,29 +304,89 @@ open class InputStepper: EntryFieldBase { //-------------------------------------------------- // MARK: - Overrides //-------------------------------------------------- + override func updateContainerView() { + //we are not calling super since we + //are using the fieldStackView as the "containerView" + //which will get the look/feel of the containerView. + //this will get refactored in the future. + fieldStackView.backgroundColor = containerBackgroundColor + fieldStackView.layer.borderColor = borderColorConfiguration.getColor(self).cgColor + fieldStackView.layer.borderWidth = VDSFormControls.borderWidth + } + internal override func updateContainerWidth() { + + defer { + fieldStackView.layer.cornerRadius = containerSize.height / 2 + } + + //we are not calling super here since + //we are changing how the widths are getting calculated + //now by including a percentage. stepperWidthConstraint?.deactivate() widthConstraint?.deactivate() trailingLessThanEqualsConstraint?.deactivate() trailingEqualsConstraint?.deactivate() + + var widthConstraintConstant: CGFloat? - if let width, width >= minWidth, width <= maxWidth { - widthConstraint?.constant = width - widthConstraint?.activate() - trailingLessThanEqualsConstraint?.activate() + if let widthPercentage, let superWidth = horizontalPinnedWidth() { + // test value vs minimum width and take the greater value + widthConstraintConstant = max(superWidth * (widthPercentage / 100), minWidth) + } else if let width, width >= minWidth, width <= maxWidth { + widthConstraintConstant = width } else if let parentWidth = width, parentWidth >= maxWidth { - width = maxWidth - widthConstraint?.constant = maxWidth - widthConstraint?.activate() - trailingLessThanEqualsConstraint?.activate() + widthConstraintConstant = maxWidth } else if let parentWidth = width, parentWidth <= minWidth { - width = minWidth - widthConstraint?.constant = minWidth + widthConstraintConstant = minWidth + } + + if let widthConstraintConstant { + widthConstraint?.constant = widthConstraintConstant widthConstraint?.activate() trailingLessThanEqualsConstraint?.activate() } else { trailingEqualsConstraint?.activate() } + + // Update Edge insets if size changes applied. + stepperStackView.applyAlignment(.fill, edges: .uniform(size.padding)) + + // Update height if size changes applied. + stepperHeightConstraint?.constant = containerSize.height + + //update the stepper's widthConstraint if + //controlWidth was set + guard let controlWidth else { + return + } + + var stepperWidthConstant: CGFloat? + var stepperWidth: CGFloat + var containerWidth: CGFloat + + switch controlWidth { + case .percentage(let percentage): + // Set the inputStepper's controlWidth based on percentage received relative to its parentView's frame. + containerWidth = widthConstraintConstant ?? CGFloat(containerView.frame.size.width) + stepperWidth = max(containerWidth * ((percentage) / 100), minWidth) + + case .value(let value): + containerWidth = widthConstraintConstant ?? CGFloat(containerView.frame.size.width) + stepperWidth = value + } + + //get the value of the stepperWidthConstant + if stepperWidth >= containerSize.width && stepperWidth <= containerWidth { + stepperWidthConstant = stepperWidth + } else if stepperWidth >= containerWidth { + stepperWidthConstant = containerWidth + } + + if let stepperWidthConstant { + stepperWidthConstraint?.constant = stepperWidthConstant + stepperWidthConstraint?.activate() + } } //-------------------------------------------------- @@ -370,78 +420,5 @@ open class InputStepper: EntryFieldBase { incrementButton.isEnabled = (defaultValue ?? _defaultMinValue) < maxValue ? true : false } } - - // Update edge insets and height when size changes. - internal func updateStepperContainerViewSize() { - updateButtonStates() - - // Update Edge insets if size changes applied. - stepperStackView.removeFromSuperview() - stepperContainerView.addSubview(stepperStackView) - stepperStackView.pinToSuperView(.uniform(size.padding)) - - // Update height if size changes applied. - stepperHeightConstraint?.deactivate() - stepperHeightConstraint = stepperContainerView.heightAnchor.constraint(equalToConstant: containerSize.height) - stepperHeightConstraint?.activate() - } - - // Set control width to input stepper. - private func updateInputStepperWidth() { - guard let controlWidth else { - return - } - - switch controlWidth { - case .percentage(let percentage): - // Set the inputStepper's controlWidth based on percentage received relative to its parentView's frame. - let superWidth = width ?? CGFloat(containerView.frame.size.width) - let value = max(superWidth * ((percentage) / 100), minWidth) - updateStepperContainerWidth(controlWidth: value, width: superWidth) - - case .value(let value): - let superWidth = width ?? CGFloat(containerView.frame.size.width) - updateStepperContainerWidth(controlWidth: value, width: superWidth) - } - } - - // Handling the controlwidth without exceeding the width of the parent container. - private func updateStepperContainerWidth(controlWidth: CGFloat, width: CGFloat) { - if controlWidth >= containerSize.width && controlWidth <= width { - stepperWidthConstraint?.deactivate() - stepperWidthConstraint?.constant = controlWidth - stepperWidthConstraint?.activate() - } else if controlWidth >= width { - stepperWidthConstraint?.deactivate() - stepperWidthConstraint?.constant = width - stepperWidthConstraint?.activate() - } - } - - // Update the container view width based on the percentage received. - private func updateContainerWidthWithPercentage() { - guard let superWidth = horizontalPinnedWidth() else { - return - } - - // Set width of Parent container based on width perecentage received relative to its superview frame. - if let widthPercentage { - // test value vs minimum width and take the greater value - width = max(superWidth * (widthPercentage / 100), minWidth) - } - } - - // Add border and update constratints to stepper view. - private func updateStepperView() { - fieldStackView.removeConstraints() - fieldStackView.pinTop().pinLeading().pinBottom().pinTrailingLessThanOrEqualTo() - containerView.backgroundColor = .clear - containerView.layer.borderColor = nil - containerView.layer.borderWidth = 0 - containerView.layer.cornerRadius = 0 - fieldStackView.backgroundColor = containerBackgroundColor - fieldStackView.layer.borderColor = borderColorConfiguration.getColor(self).cgColor - fieldStackView.layer.borderWidth = VDSFormControls.borderWidth - fieldStackView.layer.cornerRadius = containerView.frame.size.height / 2 - } + }