diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 031f4ba4..26d52bb7 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -52,6 +52,8 @@ 0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */; }; 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */; }; 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; }; + 943784F5236B77BB006A1E82 /* GraphView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F3236B77BB006A1E82 /* GraphView.swift */; }; + 943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */; }; 9455B19C234F8A0400A574DB /* MVMAnimationFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */; }; 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 948DB67D2326DCD90011F916 /* MultiProgress.swift */; }; D206997721FB8A0B00CAE0DE /* MVMCoreUINavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = D206997521FB8A0B00CAE0DE /* MVMCoreUINavigationController.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -271,6 +273,8 @@ 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyButton.swift; sourceTree = ""; }; 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = ""; }; 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxWithLabelView.swift; sourceTree = ""; }; + 943784F3236B77BB006A1E82 /* GraphView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphView.swift; sourceTree = ""; }; + 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphViewAnimationHandler.swift; sourceTree = ""; }; 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MVMAnimationFramework.framework; path = ../SharedFrameworks/MVMAnimationFramework.framework; sourceTree = ""; }; 948DB67D2326DCD90011F916 /* MultiProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiProgress.swift; sourceTree = ""; }; D206997521FB8A0B00CAE0DE /* MVMCoreUINavigationController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUINavigationController.h; sourceTree = ""; }; @@ -845,6 +849,8 @@ 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */, 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */, 01004F2F22721C3800991ECC /* RadioButton.swift */, + 943784F3236B77BB006A1E82 /* GraphView.swift */, + 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */, ); path = Views; sourceTree = ""; @@ -1134,6 +1140,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 943784F5236B77BB006A1E82 /* GraphView.swift in Sources */, D29DF32121ED0CBA003B2FB9 /* LabelView.m in Sources */, DBC4391822442197001AB423 /* CaretView.swift in Sources */, D29770F221F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.m in Sources */, @@ -1240,6 +1247,7 @@ D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */, D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */, D2B1E3E522F37D6A0065F95C /* ImageHeadlineBody.swift in Sources */, + 943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */, D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */, 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */, 01EB3682236092AE006832FA /* HolderManager.swift in Sources */, diff --git a/MVMCoreUI/Atoms/Buttons/PrimaryButton.m b/MVMCoreUI/Atoms/Buttons/PrimaryButton.m index 35395557..3b1802e5 100644 --- a/MVMCoreUI/Atoms/Buttons/PrimaryButton.m +++ b/MVMCoreUI/Atoms/Buttons/PrimaryButton.m @@ -669,7 +669,7 @@ - (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { - self.validationRequired = [json boolForKey:@"validationRequired"]; + self.validationRequired = [json boolForKey:@"required"]; self.requiredGroupsList = [json array:@"requiredGroups"]; [FormValidator setupValidationWithMolecule:self delegate:delegateObject.formValidationProtocol]; diff --git a/MVMCoreUI/Atoms/Views/Checkbox.swift b/MVMCoreUI/Atoms/Views/Checkbox.swift index e5a82b1d..370f5826 100644 --- a/MVMCoreUI/Atoms/Views/Checkbox.swift +++ b/MVMCoreUI/Atoms/Views/Checkbox.swift @@ -19,6 +19,7 @@ import MVMCore // Form Validation var isRequired = false var fieldKey: String? + var fieldValue: String? var groupName: String? var delegateObject: MVMCoreUIDelegateObject? @@ -407,6 +408,7 @@ import MVMCore guard let dictionary = json else { return } groupName = dictionary.optionalStringForKey("groupName") + fieldValue = dictionary.optionalStringForKey("value") if let fieldKey = dictionary[KeyFieldKey] as? String { self.fieldKey = fieldKey } @@ -475,6 +477,6 @@ extension Checkbox: FormValidationFormFieldProtocol { } public func formFieldValue() -> Any? { - return NSNumber(value: isSelected) + return isSelected ? fieldValue : nil } } diff --git a/MVMCoreUI/Atoms/Views/GraphView.swift b/MVMCoreUI/Atoms/Views/GraphView.swift new file mode 100644 index 00000000..ebd074a0 --- /dev/null +++ b/MVMCoreUI/Atoms/Views/GraphView.swift @@ -0,0 +1,280 @@ +// +// GraphView.swift +// MobileFirstFramework +// +// Created by Ryan on 10/24/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + + +enum GraphSize: String { + case small, medium, large +} + +enum GraphStyle: String { + case unlimited, safetyMode +} + +///Graph Object contains properties +public struct GraphObject { + + var style: GraphStyle { + didSet { + updateStyle() + } + } + var size: GraphSize { + didSet { + updateSize() + } + } + var diameter: CGFloat = 24 + var lineWidth: CGFloat = 5 + var clockwise: Bool = true + var duration : Double = 1.0 + var colors = [CGColor]() + + public init(_ json: [AnyHashable : Any]?) { + style = .unlimited + size = .small + guard let json = json else { + return + } + if let styleString = json.optionalStringForKey("style") { + style = GraphStyle(rawValue: styleString) ?? .unlimited + } + if let sizeString = json.optionalStringForKey("size") { + size = GraphSize(rawValue: sizeString) ?? .small + } + updateStyle() + updateSize() + if let diameter = json.optionalCGFloatForKey("diameter") { + self.diameter = diameter + } + if let lineWidth = json.optionalCGFloatForKey("lineWidth") { + self.lineWidth = lineWidth + } + if let clockwise = json.optionalBoolForKey("clockwise") { + self.clockwise = clockwise + } + if let duration = json["duration"] as? Double { + self.duration = duration + } + if let colorArray = json.optionalArrayForKey("colors") as? [String] { + colors = getCGColorsFromArray(colorArray) + } + } + + func getCGColorsFromArray(_ colorArray: [String]) -> [CGColor] { + return colorArray.map { (colorString) -> CGColor in + return UIColor.mfGet(forHex: colorString).cgColor + } + } + + mutating func updateStyle() { + switch style { + case .unlimited: + duration = 1.0 + clockwise = true + //current style, only the end part shows darker look + colors = getCGColorsFromArray(["#007AB8","#007AB8","#033554"]) + break + case .safetyMode: + duration = 1.5 + clockwise = true + colors = getCGColorsFromArray(["#CC4D0F","#CC4D0F","AB0309"]) + break + } + } + + //those are + mutating func updateSize() { + switch size { + case .small: + diameter = MFSizeObject(standardSize: 24)?.getValueBasedOnApplicationWidth() ?? 24 + lineWidth = MFSizeObject(standardSize: 5)?.getValueBasedOnApplicationWidth() ?? 5 + break + case .medium: + diameter = MFSizeObject(standardSize: 100)?.getValueBasedOnApplicationWidth() ?? 100 + lineWidth = MFSizeObject(standardSize: 8)?.getValueBasedOnApplicationWidth() ?? 8 + break + case .large: + diameter = MFSizeObject(standardSize: 180)?.getValueBasedOnApplicationWidth() ?? 180 + lineWidth = MFSizeObject(standardSize: 12)?.getValueBasedOnApplicationWidth() ?? 12 + break + } + } +} + + +@objcMembers open class GraphView: View { + + var heightConstraint: NSLayoutConstraint? + var gradientLayer: CALayer? + var graphObject: GraphObject? + + +// MARK: setup + open override func setupView() { + super.setupView() + //avoid adding height constraint multiple times + guard heightConstraint == nil else { return } + heightConstraint = heightAnchor.constraint(equalToConstant: 0) + heightConstraint?.isActive = true + widthAnchor.constraint(equalTo: heightAnchor).isActive = true + } + + override open func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + let object = GraphObject(json) + graphObject = object + createGraphCircle(object) + rotationAnimation(object) + } + + class func getAngle(_ piValue: Double) -> Double { + return piValue / (2.0 * Double.pi) * 360.0 + } + + class func getPiValue(_ angle: Double) -> Double { + return angle / 360.0 * 2.0 * Double.pi + } + +// MARK: circle + open func createGraphCircle(_ graphObject: GraphObject) { + if let sublayers = layer.sublayers { + for sublayer in sublayers { + sublayer.removeAllAnimations() + sublayer.removeFromSuperlayer() + } + } + heightConstraint?.constant = graphObject.diameter + + //create circle path + let radius = graphObject.diameter / 2.0 + + //begin point will be at the bottom, clockwise direction + let path = UIBezierPath(arcCenter: CGPoint(x: radius + , y: radius), radius: radius - graphObject.lineWidth/2.0, startAngle: CGFloat(GraphView.getPiValue(90.0)), endAngle: CGFloat(GraphView.getPiValue(90.0 + 360.0)), clockwise: true) + path.lineWidth = graphObject.lineWidth + + let circleLayer = CAShapeLayer() + circleLayer.path = path.cgPath + circleLayer.lineCap = .round + circleLayer.lineWidth = graphObject.lineWidth + circleLayer.fillColor = UIColor.clear.cgColor + circleLayer.strokeColor = UIColor.black.cgColor + + //create gradient layer + let gradientLayer = createGradientLayer(graphObject) + gradientLayer.mask = circleLayer + layer.addSublayer(gradientLayer) + self.gradientLayer = gradientLayer + } + +/* + create three gradient layer for circle layout. + _____________ + | → | top layer for smooth gradient + ------------- + | | | + | ↑ | ↓ | + | | | + ------------- +*/ + func createGradientLayer(_ graphObject: GraphObject) -> CALayer { + let containLayer = CALayer() + containLayer.frame = CGRect(x: 0, y: 0, width: graphObject.diameter, height: graphObject.diameter) + let radius = graphObject.diameter / 2.0 + + //create graident layers + guard graphObject.colors.count > 1 else { + containLayer.backgroundColor = graphObject.colors.first + return containLayer + } + var topGradientHeight : CGFloat = 0.0 + var leftColors = graphObject.colors.prefix(through: graphObject.colors.count/2) + let rightColors = graphObject.colors.suffix(from: graphObject.colors.count/2) + + // make the top layer higher than line width for smooth look + topGradientHeight = min(max(graphObject.lineWidth, 1.0/(1.0+CGFloat(graphObject.colors.count))*graphObject.diameter), graphObject.diameter) + let topLayer = CAGradientLayer() + topLayer.frame = CGRect(x: 0.0, y: 0.0, width: graphObject.diameter, height: topGradientHeight) + //make the graident edge more smoothy + topLayer.startPoint = CGPoint(x: 0.25, y: 0.0) + topLayer.endPoint = CGPoint(x: 0.75, y: 0.0) + //if number of colors is even, need to display gradient layer, otherwise make top layer as solid color layer + if graphObject.colors.count % 2 == 0 { + leftColors.removeLast() + topLayer.colors = [leftColors.last!, rightColors.first!] + } else { + topLayer.backgroundColor = leftColors.last + } + containLayer.addSublayer(topLayer) + + let leftLayer = CAGradientLayer() + leftLayer.frame = CGRect(x: 0, y: topGradientHeight, width: radius, height: graphObject.diameter - topGradientHeight) + leftLayer.startPoint = CGPoint(x: 0, y: 1) + leftLayer.endPoint = CGPoint(x: 0, y: 0) + + //count of graidentLayer.colors must be bigger than 1, otherwise set backgroundColor + if leftColors.count > 1 { + leftLayer.colors = Array(leftColors) + } else { + leftLayer.backgroundColor = leftColors.first + } + containLayer.addSublayer(leftLayer) + + let rightLayer = CAGradientLayer() + rightLayer.frame = CGRect(x: radius, y: topGradientHeight, width: radius, height: graphObject.diameter - topGradientHeight) + rightLayer.startPoint = CGPoint(x: 0, y: 0) + rightLayer.endPoint = CGPoint(x: 0, y: 1) + if rightColors.count > 1 { + rightLayer.colors = Array(rightColors) + } else { + rightLayer.backgroundColor = rightColors.first + } + containLayer.addSublayer(rightLayer) + + return containLayer + } + +//MARK: Animation + func rotationAnimation(_ object: GraphObject) { + MVMCoreDispatchUtility.performBlock(onMainThread:{ + let rotation = CABasicAnimation(keyPath: "transform.rotation") + let animationHandler = GraphViewAnimationHandler.shared + let startAngle = animationHandler.getAnimationStartAngle(object.duration, CACurrentMediaTime()) + if startAngle == 0.0 { + animationHandler.storeAnimation(object.duration, CACurrentMediaTime()) + } + var fromValue = GraphView.getPiValue(0.0 + startAngle), toValue = GraphView.getPiValue(360.0 + startAngle) + if !object.clockwise { + fromValue = GraphView.getPiValue(360.0 - startAngle) + toValue = GraphView.getPiValue(0.0 - startAngle) + } + rotation.fromValue = fromValue + rotation.toValue = toValue + rotation.duration = object.duration + rotation.timingFunction = CAMediaTimingFunction(name: .linear) + rotation.fillMode = .both + rotation.isRemovedOnCompletion = false + + //avoid infinity animation take high CPU momery usage when layer is not displayed + rotation.delegate = self + rotation.repeatCount = 1 + self.gradientLayer?.add(rotation, forKey: "rotation") + }) + } +} + + +extension GraphView: CAAnimationDelegate { + public func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { + if let object = graphObject { + rotationAnimation(object) + } + } +} diff --git a/MVMCoreUI/Atoms/Views/GraphViewAnimationHandler.swift b/MVMCoreUI/Atoms/Views/GraphViewAnimationHandler.swift new file mode 100644 index 00000000..2d7489dc --- /dev/null +++ b/MVMCoreUI/Atoms/Views/GraphViewAnimationHandler.swift @@ -0,0 +1,32 @@ +// +// GraphViewAnimationHandler.swift +// MobileFirstFramework +// +// Created by Ryan on 10/29/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +@objcMembers open class GraphViewAnimationHandler: NSObject { + + /// duration : CACurrentMediaTime() + private var animations = [Double: Double]() + + static let shared = GraphViewAnimationHandler() + + open func storeAnimation(_ duration: Double, _ currentTime: CFTimeInterval) { + guard animations[duration] == nil else { + return + } + animations[duration] = currentTime + } + + open func getAnimationStartAngle(_ duration: Double, _ currentTime: CFTimeInterval) -> Double { + if let time = animations[duration] { + return (currentTime - time) / duration * 360 + 90 + } + return 0.0 + } + +} diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUISwitch.m b/MVMCoreUI/Atoms/Views/MVMCoreUISwitch.m index ae0db4a7..8ec71241 100644 --- a/MVMCoreUI/Atoms/Views/MVMCoreUISwitch.m +++ b/MVMCoreUI/Atoms/Views/MVMCoreUISwitch.m @@ -423,6 +423,10 @@ const CGFloat SwitchShakeIntensity = 2; return UIAccessibilityTraitButton; } +- (NSString * _Nullable)formFieldGroupName { + return [self.json string:@"groupName"]; +} + - (NSString *)accessibilityHint { return [MVMCoreUIUtility hardcodedStringWithKey:@"AccToggleHint"]; } diff --git a/MVMCoreUI/BaseControllers/MFProgrammaticTableViewController.h b/MVMCoreUI/BaseControllers/MFProgrammaticTableViewController.h index 01ab9820..a568a27a 100644 --- a/MVMCoreUI/BaseControllers/MFProgrammaticTableViewController.h +++ b/MVMCoreUI/BaseControllers/MFProgrammaticTableViewController.h @@ -12,8 +12,6 @@ @interface MFProgrammaticTableViewController : MFScrollingViewController @property (nullable, weak, nonatomic) UITableView *tableView; -@property (nullable, nonatomic, strong) NSLayoutConstraint *topConstraint; -@property (nullable, nonatomic, strong) NSLayoutConstraint *bottomConstraint; // Registers classes and nibs. Can subclass for different nibs. Can call super and then add new ones after as well. - (void)registerWithTable; diff --git a/MVMCoreUI/BaseControllers/MFScrollingViewController.h b/MVMCoreUI/BaseControllers/MFScrollingViewController.h index 52799769..f44de6c4 100644 --- a/MVMCoreUI/BaseControllers/MFScrollingViewController.h +++ b/MVMCoreUI/BaseControllers/MFScrollingViewController.h @@ -13,6 +13,9 @@ @property (nullable, weak, nonatomic) IBOutlet UIScrollView *scrollView; @property (nullable, weak, nonatomic) IBOutlet UIView *contentView; +@property (nullable, nonatomic, strong) NSLayoutConstraint *topConstraint; +@property (nullable, nonatomic, strong) NSLayoutConstraint *bottomConstraint; + // Recognizes single tap/touches to screen for dismissing keyboard @property (nonnull, strong, nonatomic) UITapGestureRecognizer *dismissKeyboardTapGesture; diff --git a/MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.h b/MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.h index f9f32f69..9e486066 100644 --- a/MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.h +++ b/MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.h @@ -10,7 +10,5 @@ @interface ProgrammaticScrollViewController : MFScrollingViewController -@property (nullable, nonatomic, strong) NSLayoutConstraint *topConstraint; -@property (nullable, nonatomic, strong) NSLayoutConstraint *bottomConstraint; @end diff --git a/MVMCoreUI/LegacyControllers/TopLabelsAndBottomButtonsTableViewController.m b/MVMCoreUI/LegacyControllers/TopLabelsAndBottomButtonsTableViewController.m index 5d6a6778..8b0a23bf 100644 --- a/MVMCoreUI/LegacyControllers/TopLabelsAndBottomButtonsTableViewController.m +++ b/MVMCoreUI/LegacyControllers/TopLabelsAndBottomButtonsTableViewController.m @@ -427,13 +427,13 @@ if ([self.bottomView isKindOfClass:[TwoButtonView class]]) { TwoButtonView *buttonView = (TwoButtonView *)self.bottomView; if (right && !left) { - [buttonView hidePrimaryRightButton]; + [buttonView hideRightButton]; } else if (!right && left) { - [buttonView hidePrimaryLeftButton]; + [buttonView hideLeftButton]; } else if (right && left) { - [buttonView hideBothPrimaryButtons]; + [buttonView hideBothButtons]; } else if (!right && !left) { - [buttonView showBothPrimaryButtons]; + [buttonView showBothButtons]; } } } diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift index 28ad6dc4..2c5f0fe5 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/TwoButtonView.swift @@ -98,7 +98,7 @@ import UIKit } func setupWithTwoButtons() { - guard self.viewForButtons == nil else { + guard viewForButtons == nil else { return } let viewForButtons = MVMCoreUICommonViewsUtility.commonView() @@ -114,7 +114,7 @@ import UIKit } open func setupWithPrimaryButton() { - guard self.primaryButton == nil else { + guard primaryButton == nil && secondaryButton == nil else { return } createPrimaryButton() @@ -125,21 +125,37 @@ import UIKit } } - // Sets up the number of buttons based on the maps. Doesn't set the buttons with the maps because legacy code handles differently from modern code... - func setupUI(withPrimaryButtonMap primaryButtonMap: [AnyHashable: Any]?, secondaryButtonMap: [AnyHashable: Any]?, legacy: Bool) { + open func setupWithSecondaryButton() { + guard secondaryButton == nil && primaryButton == nil else { + return + } + createSecondaryButton() + if let secondaryButton = secondaryButton { + addSubview(secondaryButton) + pinView(toSuperView: secondaryButton) + alignCenterHorizontal() + } + } + + func setupUI(withPrimaryButtonMap primaryButtonMap: [AnyHashable: Any]?, secondaryButtonMap: [AnyHashable: Any]?) { if primaryButtonMap != nil, secondaryButtonMap != nil { heightConstraint?.isActive = false if primaryButton == nil || secondaryButton == nil { removeButtons() setupWithTwoButtons() } - } else if primaryButtonMap != nil || (secondaryButtonMap != nil && legacy) { - // Only legacy sets up the primary button with a secondary map + } else if primaryButtonMap != nil { heightConstraint?.isActive = false if primaryButton == nil || secondaryButton != nil { removeButtons() setupWithPrimaryButton() } + } else if secondaryButtonMap != nil { + heightConstraint?.isActive = false + if secondaryButton == nil || primaryButton != nil { + removeButtons() + setupWithSecondaryButton() + } } else { removeButtons() if heightConstraint == nil { @@ -150,7 +166,7 @@ import UIKit } open func set(primaryButtonJSON: [AnyHashable: Any]?, secondaryButtonJSON: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - setupUI(withPrimaryButtonMap: primaryButtonJSON, secondaryButtonMap: secondaryButtonJSON, legacy: false) + setupUI(withPrimaryButtonMap: primaryButtonJSON, secondaryButtonMap: secondaryButtonJSON) setDefaultCustom() primaryButton?.setWithJSON(primaryButtonJSON, delegateObject: delegateObject, additionalData: additionalData) secondaryButton?.setWithJSON(secondaryButtonJSON, delegateObject: delegateObject, additionalData: additionalData) @@ -178,7 +194,7 @@ import UIKit } open func setup(primaryButtonMap: [AnyHashable: Any]?, secondaryButtonMap: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) { - setupUI(withPrimaryButtonMap: primaryButtonMap, secondaryButtonMap: secondaryButtonMap, legacy: true) + setupUI(withPrimaryButtonMap: primaryButtonMap, secondaryButtonMap: secondaryButtonMap) if primaryButtonMap != nil, secondaryButtonMap != nil { primaryButton?.setWithActionMap(primaryButtonMap, delegateObject: delegateObject, additionalData: additionalData) secondaryButton?.setWithActionMap(secondaryButtonMap, delegateObject: delegateObject, additionalData: additionalData) @@ -186,8 +202,8 @@ import UIKit primaryButton?.setWithActionMap(primaryButtonMap, delegateObject: delegateObject, additionalData: additionalData) primaryButton?.bordered = false } else if secondaryButtonMap != nil { - primaryButton?.setWithActionMap(secondaryButtonMap, delegateObject: delegateObject, additionalData: additionalData) - primaryButton?.bordered = true + secondaryButton?.setWithActionMap(secondaryButtonMap, delegateObject: delegateObject, additionalData: additionalData) + secondaryButton?.bordered = true } } @@ -197,7 +213,7 @@ import UIKit setup(primaryButtonMap: primaryButtonMap, secondaryButtonMap: secondaryButtonMap, delegateObject: delegateObject, additionalData: additionalData) } - public func hidePrimaryLeftButton() { + public func hideLeftButton() { guard let secondaryButton = secondaryButton, !secondaryButton.isHidden else { return } @@ -209,7 +225,7 @@ import UIKit } } - public func hidePrimaryRightButton() { + public func hideRightButton() { guard let primaryButton = primaryButton, !primaryButton.isHidden else { return } @@ -221,7 +237,7 @@ import UIKit } } - public func showBothPrimaryButtons() { + public func showBothButtons() { primaryButton?.isHidden = false secondaryButton?.isHidden = false if let primaryButton = primaryButton, let secondaryButton = secondaryButton { @@ -231,7 +247,7 @@ import UIKit } } - public func hideBothPrimaryButtons() { + public func hideBothButtons() { primaryButton?.isHidden = true secondaryButton?.isHidden = true } @@ -241,7 +257,7 @@ import UIKit extension TwoButtonView { @available(*, deprecated) open func setup(primaryButtonMap: [AnyHashable: Any]?, secondaryButtonMap: [AnyHashable: Any]?, actionDelegate: NSObjectProtocol?, additionalData: [AnyHashable: Any]?, buttonDelegate: Any?) { - setupUI(withPrimaryButtonMap: primaryButtonMap, secondaryButtonMap: secondaryButtonMap, legacy: true) + setupUI(withPrimaryButtonMap: primaryButtonMap, secondaryButtonMap: secondaryButtonMap) if primaryButtonMap != nil, secondaryButtonMap != nil { primaryButton?.setWithActionMap(primaryButtonMap, actionDelegate: actionDelegate as? MVMCoreActionDelegateProtocol & NSObjectProtocol, additionalData: additionalData, buttonDelegate: buttonDelegate as? ButtonDelegateProtocol) secondaryButton?.setWithActionMap(secondaryButtonMap, actionDelegate: actionDelegate as? MVMCoreActionDelegateProtocol & NSObjectProtocol, additionalData: additionalData, buttonDelegate: buttonDelegate as? ButtonDelegateProtocol) @@ -249,8 +265,8 @@ extension TwoButtonView { primaryButton?.setWithActionMap(primaryButtonMap, actionDelegate: actionDelegate as? MVMCoreActionDelegateProtocol & NSObjectProtocol, additionalData: additionalData, buttonDelegate: buttonDelegate as? ButtonDelegateProtocol) primaryButton?.bordered = false } else if secondaryButtonMap != nil { - primaryButton?.setWithActionMap(secondaryButtonMap, actionDelegate: actionDelegate as? MVMCoreActionDelegateProtocol & NSObjectProtocol, additionalData: additionalData, buttonDelegate: buttonDelegate as? ButtonDelegateProtocol) - primaryButton?.bordered = true + secondaryButton?.setWithActionMap(secondaryButtonMap, actionDelegate: actionDelegate as? MVMCoreActionDelegateProtocol & NSObjectProtocol, additionalData: additionalData, buttonDelegate: buttonDelegate as? ButtonDelegateProtocol) + secondaryButton?.bordered = true } } diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 28471139..388ee47e 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -40,9 +40,10 @@ @"textField" : MFTextField.class, @"digitTextField" : MFDigitTextField.class, @"checkbox" : Checkbox.class, - @"checkboxWithLabelView" : CheckboxWithLabelView.class, + @"checkboxWithLabel" : CheckboxWithLabelView.class, @"cornerLabels" : CornerLabels.class, @"progressbar": ProgressBar.class, + @"circleProgress": GraphView.class, @"multiProgressBar": MultiProgress.class, @"checkbox": MVMCoreUICheckBox.class, @"radioButton": RadioButton.class, diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 8c97b427..e6182bf7 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -9,7 +9,7 @@ import UIKit open class MoleculeListTemplate: ThreeLayerTableViewController { - var moleculesInfo: [(identifier: String, class: AnyClass, molecule: [AnyHashable: Any])]? + public var moleculesInfo: [(identifier: String, class: AnyClass, molecule: [AnyHashable: Any])]? var observer: NSKeyValueObservation? open override var loadObject: MVMCoreLoadObject? {