merge
This commit is contained in:
commit
f1b46cb8bf
@ -159,6 +159,9 @@
|
|||||||
D2C5001821F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
D2C5001821F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */; };
|
D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */; };
|
||||||
D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */; };
|
D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */; };
|
||||||
|
D2E1FADD2268B25E00AEFD8C /* MoleculeTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADC2268B25E00AEFD8C /* MoleculeTableViewCell.swift */; };
|
||||||
|
D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */; };
|
||||||
|
D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */; };
|
||||||
DBC4391822442197001AB423 /* CaretView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391622442196001AB423 /* CaretView.swift */; };
|
DBC4391822442197001AB423 /* CaretView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391622442196001AB423 /* CaretView.swift */; };
|
||||||
DBC4391922442197001AB423 /* DashLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391722442197001AB423 /* DashLine.swift */; };
|
DBC4391922442197001AB423 /* DashLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391722442197001AB423 /* DashLine.swift */; };
|
||||||
DBC4391B224421A0001AB423 /* CaretButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391A224421A0001AB423 /* CaretButton.swift */; };
|
DBC4391B224421A0001AB423 /* CaretButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391A224421A0001AB423 /* CaretButton.swift */; };
|
||||||
@ -323,6 +326,9 @@
|
|||||||
D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIViewControllerMappingObject.m; sourceTree = "<group>"; };
|
D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIViewControllerMappingObject.m; sourceTree = "<group>"; };
|
||||||
D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIDelegateObject.swift; sourceTree = "<group>"; };
|
D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIDelegateObject.swift; sourceTree = "<group>"; };
|
||||||
DB891E822253FA8500022516 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = "<group>"; };
|
DB891E822253FA8500022516 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = "<group>"; };
|
||||||
|
D2E1FADC2268B25E00AEFD8C /* MoleculeTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
|
D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTableViewController.swift; sourceTree = "<group>"; };
|
||||||
|
D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeListTemplate.swift; sourceTree = "<group>"; };
|
||||||
DBC4391622442196001AB423 /* CaretView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretView.swift; sourceTree = "<group>"; };
|
DBC4391622442196001AB423 /* CaretView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretView.swift; sourceTree = "<group>"; };
|
||||||
DBC4391722442197001AB423 /* DashLine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DashLine.swift; sourceTree = "<group>"; };
|
DBC4391722442197001AB423 /* DashLine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DashLine.swift; sourceTree = "<group>"; };
|
||||||
DBC4391A224421A0001AB423 /* CaretButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretButton.swift; sourceTree = "<group>"; };
|
DBC4391A224421A0001AB423 /* CaretButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretButton.swift; sourceTree = "<group>"; };
|
||||||
@ -411,6 +417,7 @@
|
|||||||
01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */,
|
01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */,
|
||||||
D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */,
|
D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */,
|
||||||
D2A514622213643100345BFB /* MoleculeStackCenteredTemplate.swift */,
|
D2A514622213643100345BFB /* MoleculeStackCenteredTemplate.swift */,
|
||||||
|
D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */,
|
||||||
);
|
);
|
||||||
path = Templates;
|
path = Templates;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -448,6 +455,7 @@
|
|||||||
D274CA322236A78900B01B62 /* StandardFooterView.swift */,
|
D274CA322236A78900B01B62 /* StandardFooterView.swift */,
|
||||||
01157B93225D376D00F15D92 /* RadioButtonList.swift */,
|
01157B93225D376D00F15D92 /* RadioButtonList.swift */,
|
||||||
01004F2F22721C3800991ECC /* RadioButton.swift */,
|
01004F2F22721C3800991ECC /* RadioButton.swift */,
|
||||||
|
D2E1FADC2268B25E00AEFD8C /* MoleculeTableViewCell.swift */,
|
||||||
);
|
);
|
||||||
path = Molecules;
|
path = Molecules;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -468,6 +476,7 @@
|
|||||||
D29DF2CC21E7C104003B2FB9 /* MFLoadingViewController.h */,
|
D29DF2CC21E7C104003B2FB9 /* MFLoadingViewController.h */,
|
||||||
D29DF2CD21E7C104003B2FB9 /* MFLoadingViewController.m */,
|
D29DF2CD21E7C104003B2FB9 /* MFLoadingViewController.m */,
|
||||||
D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */,
|
D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */,
|
||||||
|
D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */,
|
||||||
);
|
);
|
||||||
path = BaseControllers;
|
path = BaseControllers;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -905,6 +914,7 @@
|
|||||||
D29DF2EF21ECEAE1003B2FB9 /* MFFonts.m in Sources */,
|
D29DF2EF21ECEAE1003B2FB9 /* MFFonts.m in Sources */,
|
||||||
D282AACB2243C61700C46919 /* ButtonView.swift in Sources */,
|
D282AACB2243C61700C46919 /* ButtonView.swift in Sources */,
|
||||||
0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */,
|
0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */,
|
||||||
|
D2E1FADD2268B25E00AEFD8C /* MoleculeTableViewCell.swift in Sources */,
|
||||||
D29DF2AE21E7B3A4003B2FB9 /* MFTextView.m in Sources */,
|
D29DF2AE21E7B3A4003B2FB9 /* MFTextView.m in Sources */,
|
||||||
01157B94225D376D00F15D92 /* RadioButtonList.swift in Sources */,
|
01157B94225D376D00F15D92 /* RadioButtonList.swift in Sources */,
|
||||||
D29DF18121E69E50003B2FB9 /* MFView.m in Sources */,
|
D29DF18121E69E50003B2FB9 /* MFView.m in Sources */,
|
||||||
@ -921,6 +931,7 @@
|
|||||||
D29DF2C721E7BF57003B2FB9 /* MFTabBarInteractor.m in Sources */,
|
D29DF2C721E7BF57003B2FB9 /* MFTabBarInteractor.m in Sources */,
|
||||||
D29DF29521E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m in Sources */,
|
D29DF29521E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m in Sources */,
|
||||||
D29DF16121E69996003B2FB9 /* MFViewController.m in Sources */,
|
D29DF16121E69996003B2FB9 /* MFViewController.m in Sources */,
|
||||||
|
D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */,
|
||||||
D22D1F47220496A30077CEC0 /* MVMCoreUISwitch.m in Sources */,
|
D22D1F47220496A30077CEC0 /* MVMCoreUISwitch.m in Sources */,
|
||||||
D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */,
|
D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */,
|
||||||
D29DF17B21E69E1F003B2FB9 /* PrimaryButton.m in Sources */,
|
D29DF17B21E69E1F003B2FB9 /* PrimaryButton.m in Sources */,
|
||||||
@ -928,6 +939,7 @@
|
|||||||
0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */,
|
0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */,
|
||||||
D29DF29821E7ADB8003B2FB9 /* MFScrollingViewController.m in Sources */,
|
D29DF29821E7ADB8003B2FB9 /* MFScrollingViewController.m in Sources */,
|
||||||
D29770C821F7C4AE00B2F0D0 /* TopLabelsView.m in Sources */,
|
D29770C821F7C4AE00B2F0D0 /* TopLabelsView.m in Sources */,
|
||||||
|
D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */,
|
||||||
D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */,
|
D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */,
|
||||||
D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */,
|
D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */,
|
||||||
D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */,
|
D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */,
|
||||||
|
|||||||
@ -13,8 +13,9 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol {
|
|||||||
// MARK: - Constants
|
// MARK: - Constants
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
|
|
||||||
private let CaretViewHeight: Float = 10.8
|
private let CARET_VIEW_HEIGHT: Float = 10.5
|
||||||
private let CaretViewWidth: Float = 6.6
|
private let CARET_VIEW_WIDTH: Float = 6.5
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
@ -25,17 +26,11 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol {
|
|||||||
@objc public var rightViewWidth: NSNumber?
|
@objc public var rightViewWidth: NSNumber?
|
||||||
|
|
||||||
@objc public var enabledColor: UIColor = .black {
|
@objc public var enabledColor: UIColor = .black {
|
||||||
didSet {
|
didSet { changeCaretColor() }
|
||||||
setTitleColor(enabledColor, for: .normal)
|
|
||||||
changeCaretColor()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc public var disabledColor: UIColor = .mfSilver() {
|
@objc public var disabledColor: UIColor = .mfSilver() {
|
||||||
didSet {
|
didSet { changeCaretColor() }
|
||||||
setTitleColor(disabledColor, for: .disabled)
|
|
||||||
changeCaretColor()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private var caretSpacingConstraint: NSLayoutConstraint?
|
private var caretSpacingConstraint: NSLayoutConstraint?
|
||||||
@ -61,10 +56,11 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol {
|
|||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
|
|
||||||
private func changeCaretColor() {
|
private func changeCaretColor() {
|
||||||
|
setTitleColor(enabledColor, for: .normal)
|
||||||
|
setTitleColor(disabledColor, for: .disabled)
|
||||||
|
|
||||||
if let rightCaretView = rightView as? CaretView {
|
if let rightCaretView = rightView as? CaretView {
|
||||||
let lineColor = isEnabled ? enabledColor : disabledColor
|
rightCaretView.setLineColor(isEnabled ? enabledColor : disabledColor)
|
||||||
rightCaretView.setLineColor(lineColor)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,8 +68,8 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol {
|
|||||||
|
|
||||||
rightView?.removeFromSuperview()
|
rightView?.removeFromSuperview()
|
||||||
|
|
||||||
let width = CGFloat(rightViewWidth?.floatValue ?? CaretViewWidth)
|
let width = CGFloat(rightViewWidth?.floatValue ?? CARET_VIEW_WIDTH)
|
||||||
let height = CGFloat(rightViewHeight?.floatValue ?? CaretViewHeight)
|
let height = CGFloat(rightViewHeight?.floatValue ?? CARET_VIEW_HEIGHT)
|
||||||
|
|
||||||
let edgeInsets: UIEdgeInsets = contentEdgeInsets
|
let edgeInsets: UIEdgeInsets = contentEdgeInsets
|
||||||
contentEdgeInsets = UIEdgeInsets(top: edgeInsets.top, left: edgeInsets.left, bottom: edgeInsets.bottom, right: 4 + width)
|
contentEdgeInsets = UIEdgeInsets(top: edgeInsets.top, left: edgeInsets.left, bottom: edgeInsets.bottom, right: 4 + width)
|
||||||
@ -131,4 +127,12 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol {
|
|||||||
disabledColor = UIColor.mfGet(forHex: disabledColorHex)
|
disabledColor = UIColor.mfGet(forHex: disabledColorHex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func needsToBeConstrained() -> Bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
open func moleculeAlignment() -> UIStackView.Alignment {
|
||||||
|
return UIStackView.Alignment.leading;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -141,4 +141,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)needsToBeConstrained {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIStackViewAlignment)moleculeAlignment {
|
||||||
|
return UIStackViewAlignmentLeading;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@ -324,7 +324,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// key used to send text value to server
|
// key used to send text value to server
|
||||||
string = [map string:@"fieldKey"];
|
string = [map string:KeyFieldKey];
|
||||||
if (string.length > 0) {
|
if (string.length > 0) {
|
||||||
self.fieldKey = string;
|
self.fieldKey = string;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,15 +13,21 @@ open class CaretView: MFView {
|
|||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Objc can't use float enum.
|
||||||
|
@objc public static let thin: CGFloat = 6.0
|
||||||
|
@objc public static let standard: CGFloat = 2.6
|
||||||
|
@objc public static let thick: CGFloat = 1.5
|
||||||
|
|
||||||
private(set) var strokeColor: UIColor?
|
private(set) var strokeColor: UIColor?
|
||||||
private var lineWidth: CGFloat?
|
private var lineWidth: CGFloat?
|
||||||
|
private var lineThickness: CGFloat?
|
||||||
|
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
// MARK: - Initialization
|
// MARK: - Initialization
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
|
|
||||||
@objc public init() {
|
@objc public init() {
|
||||||
super.init(frame: CGRect.zero)
|
super.init(frame: .zero)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc public override init(frame: CGRect) {
|
@objc public override init(frame: CGRect) {
|
||||||
@ -32,14 +38,19 @@ open class CaretView: MFView {
|
|||||||
super.init(coder: aDecoder)
|
super.init(coder: aDecoder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Can init with a specific line width.
|
||||||
@objc public init(lineWidth: CGFloat) {
|
@objc public init(lineWidth: CGFloat) {
|
||||||
super.init(frame: CGRect())
|
super.init(frame: CGRect())
|
||||||
|
|
||||||
self.lineWidth = lineWidth
|
self.lineWidth = lineWidth
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc override open func setupView() {
|
/// Can init with a specific line thickness, scales based on width and height.
|
||||||
|
@objc public init(lineThickness: CGFloat) {
|
||||||
|
super.init(frame: CGRect())
|
||||||
|
self.lineThickness = lineThickness
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc override open func setupView() {
|
||||||
defaultState()
|
defaultState()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +59,6 @@ open class CaretView: MFView {
|
|||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
|
|
||||||
private func defaultState() {
|
private func defaultState() {
|
||||||
|
|
||||||
isOpaque = false
|
isOpaque = false
|
||||||
isHidden = false
|
isHidden = false
|
||||||
backgroundColor = .clear
|
backgroundColor = .clear
|
||||||
@ -64,7 +74,7 @@ open class CaretView: MFView {
|
|||||||
let context = UIGraphicsGetCurrentContext()
|
let context = UIGraphicsGetCurrentContext()
|
||||||
context?.clear(rect)
|
context?.clear(rect)
|
||||||
|
|
||||||
let lineWidthToDraw: CGFloat = lineWidth ?? frame.size.width / 2.6
|
let lineWidthToDraw: CGFloat = lineWidth ?? frame.size.width / (lineThickness ?? 2.6)
|
||||||
|
|
||||||
let path = UIBezierPath()
|
let path = UIBezierPath()
|
||||||
path.move(to: CGPoint(x: lineWidthToDraw / 2.0, y: 0.0))
|
path.move(to: CGPoint(x: lineWidthToDraw / 2.0, y: 0.0))
|
||||||
@ -80,7 +90,6 @@ open class CaretView: MFView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@objc public func setLineColor(_ color: UIColor?) {
|
@objc public func setLineColor(_ color: UIColor?) {
|
||||||
|
|
||||||
strokeColor = color
|
strokeColor = color
|
||||||
setNeedsDisplay()
|
setNeedsDisplay()
|
||||||
}
|
}
|
||||||
@ -91,33 +100,40 @@ open class CaretView: MFView {
|
|||||||
|
|
||||||
// Default values for view.
|
// Default values for view.
|
||||||
@objc open override func setAsMolecule() {
|
@objc open override func setAsMolecule() {
|
||||||
|
|
||||||
defaultState()
|
defaultState()
|
||||||
}
|
}
|
||||||
|
|
||||||
open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) {
|
open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||||
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
||||||
// Configure class properties with JSON values
|
// Configure class properties with JSON values
|
||||||
guard let jsonDictionary = json else { return }
|
guard let dictionary = json else { return }
|
||||||
|
|
||||||
if let backgroundColorHex = jsonDictionary[KeyBackgroundColor] as? String {
|
if let backgroundColorHex = dictionary[KeyBackgroundColor] as? String {
|
||||||
backgroundColor = UIColor.mfGet(forHex: backgroundColorHex)
|
backgroundColor = UIColor.mfGet(forHex: backgroundColorHex)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let strokeColorHex = jsonDictionary["strokeColor"] as? String {
|
if let strokeColorHex = dictionary["strokeColor"] as? String {
|
||||||
strokeColor = UIColor.mfGet(forHex: strokeColorHex)
|
strokeColor = UIColor.mfGet(forHex: strokeColorHex)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let isHiddenValue = jsonDictionary[KeyIsHidden] as? Bool {
|
if let isHiddenValue = dictionary[KeyIsHidden] as? Bool {
|
||||||
isHidden = isHiddenValue
|
isHidden = isHiddenValue
|
||||||
}
|
}
|
||||||
|
|
||||||
if let isOpaqueValue = jsonDictionary[KeyIsOpaque] as? Bool {
|
if let isOpaqueValue = dictionary[KeyIsOpaque] as? Bool {
|
||||||
isOpaque = isOpaqueValue
|
isOpaque = isOpaqueValue
|
||||||
}
|
}
|
||||||
|
|
||||||
if let lineWidthValue = jsonDictionary["lineWidth"] as? CGFloat {
|
if let lineWidthValue = dictionary["lineWidth"] as? CGFloat {
|
||||||
lineWidth = lineWidthValue
|
lineWidth = lineWidthValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open override func needsToBeConstrained() -> Bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func moleculeAlignment() -> UIStackView.Alignment {
|
||||||
|
return UIStackView.Alignment.leading;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -268,7 +268,6 @@ import MVMCore
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
attributedText = attributedString
|
attributedText = attributedString
|
||||||
|
|
||||||
} else if !MVMCoreGetterUtility.fequal(a: Float(standardFontSize), b: 0.0), let sizeObject: MFSizeObject = self.sizeObject ?? MFStyler.sizeObjectGeneric(forCurrentDevice: standardFontSize) {
|
} else if !MVMCoreGetterUtility.fequal(a: Float(standardFontSize), b: 0.0), let sizeObject: MFSizeObject = self.sizeObject ?? MFStyler.sizeObjectGeneric(forCurrentDevice: standardFontSize) {
|
||||||
self.font = self.font.withSize(sizeObject.getValueBased(onSize: size))
|
self.font = self.font.withSize(sizeObject.getValueBased(onSize: size))
|
||||||
}
|
}
|
||||||
@ -298,9 +297,12 @@ import MVMCore
|
|||||||
|
|
||||||
@objc public func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) {
|
@objc public func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||||
Label.setUILabel(self, withJSON: json, delegate: delegateObject, additionalData: additionalData)
|
Label.setUILabel(self, withJSON: json, delegate: delegateObject, additionalData: additionalData)
|
||||||
|
|
||||||
originalAttributedString = attributedText
|
originalAttributedString = attributedText
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func needsToBeConstrained() -> Bool {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Label {
|
extension Label {
|
||||||
|
|||||||
@ -26,7 +26,7 @@ public typealias CoreObjectActionLoadPresentDelegate = MVMCoreActionDelegateProt
|
|||||||
|
|
||||||
public var attributedText: NSAttributedString? {
|
public var attributedText: NSAttributedString? {
|
||||||
willSet(newAttributedText) {
|
willSet(newAttributedText) {
|
||||||
if let newAttribText = newAttributedText, !newAttribText.string.isEmpty {
|
if let newAttribText = newAttributedText {
|
||||||
|
|
||||||
let mutableAttributedText = NSMutableAttributedString(attributedString: newAttribText)
|
let mutableAttributedText = NSMutableAttributedString(attributedString: newAttribText)
|
||||||
let paragraphStyle = NSMutableParagraphStyle()
|
let paragraphStyle = NSMutableParagraphStyle()
|
||||||
@ -78,9 +78,16 @@ public typealias CoreObjectActionLoadPresentDelegate = MVMCoreActionDelegateProt
|
|||||||
public var actionText: String?
|
public var actionText: String?
|
||||||
public var backText: String?
|
public var backText: String?
|
||||||
|
|
||||||
private var text: String? {
|
private var internalText: String = ""
|
||||||
willSet(newText) {
|
|
||||||
attributedText = NSAttributedString(string: newText ?? "")
|
public var text: String? {
|
||||||
|
get {
|
||||||
|
return internalText
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
guard let text = newValue else { return }
|
||||||
|
internalText = text
|
||||||
|
attributedText = NSAttributedString(string: text)
|
||||||
setAlternateNormalTextAttributes([NSAttributedString.Key.font: normalTextFont as Any])
|
setAlternateNormalTextAttributes([NSAttributedString.Key.font: normalTextFont as Any])
|
||||||
setAlternateActionTextAttributes([NSAttributedString.Key.font: actionTextFont as Any])
|
setAlternateActionTextAttributes([NSAttributedString.Key.font: actionTextFont as Any])
|
||||||
setAlternateNormalTextAttributes([NSAttributedString.Key.foregroundColor: normalTextColor as Any])
|
setAlternateNormalTextAttributes([NSAttributedString.Key.foregroundColor: normalTextColor as Any])
|
||||||
|
|||||||
@ -36,7 +36,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)setupView {
|
- (void)setupView {
|
||||||
|
self.preservesSuperviewLayoutMargins = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateView:(CGFloat)size {
|
- (void)updateView:(CGFloat)size {
|
||||||
|
|||||||
@ -20,7 +20,8 @@
|
|||||||
|
|
||||||
static const CGFloat FaultTolerance = 20.f;
|
static const CGFloat FaultTolerance = 20.f;
|
||||||
static const CGFloat CheckBoxHeightWidth = 18.0;
|
static const CGFloat CheckBoxHeightWidth = 18.0;
|
||||||
@interface MVMCoreUICheckBox ()
|
|
||||||
|
@interface MVMCoreUICheckBox () <FormValidationProtocol, MVMCoreUIMoleculeViewProtocol>
|
||||||
|
|
||||||
@property (nonatomic, readwrite) BOOL isSelected;
|
@property (nonatomic, readwrite) BOOL isSelected;
|
||||||
@property (weak, nonatomic) UIView *checkedSquare;
|
@property (weak, nonatomic) UIView *checkedSquare;
|
||||||
@ -39,10 +40,45 @@ static const CGFloat CheckBoxHeightWidth = 18.0;
|
|||||||
@property (nullable, strong, nonatomic) NSLayoutConstraint *checkboxWidth;
|
@property (nullable, strong, nonatomic) NSLayoutConstraint *checkboxWidth;
|
||||||
@property (nullable, strong, nonatomic) NSLayoutConstraint *checkboxHeight;
|
@property (nullable, strong, nonatomic) NSLayoutConstraint *checkboxHeight;
|
||||||
|
|
||||||
|
@property (nonatomic) BOOL isRequired;
|
||||||
|
@property (nullable, strong, nonatomic) NSString *fieldKey;
|
||||||
|
@property (nullable, strong, nonatomic) DelegateObject *delegate;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation MVMCoreUICheckBox
|
@implementation MVMCoreUICheckBox
|
||||||
|
|
||||||
|
#pragma mark - MVMCoreUIMoleculeViewProtocol
|
||||||
|
|
||||||
|
- (BOOL)needsToBeConstrained {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIStackViewAlignment)moleculeAlignment {
|
||||||
|
return UIStackViewAlignmentLeading;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setWithJSON:(NSDictionary *)json delegateObject:(DelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData {
|
||||||
|
|
||||||
|
[FormValidator setupValidationWithMolecule:self delegate:((MVMCoreUIDelegateObject *)delegateObject).formValidationProtocol];
|
||||||
|
self.delegate = delegateObject;
|
||||||
|
self.fieldKey = [json stringForKey:KeyFieldKey];
|
||||||
|
self.isRequired = [json boolForKey:KeyRequired];
|
||||||
|
|
||||||
|
NSString *checkedColorHex = [json string:@"checkedColor"];
|
||||||
|
NSString *unCheckedColorHex = [json string:@"unCheckedColor"];
|
||||||
|
|
||||||
|
UIColor *checkedColor = checkedColorHex ? [UIColor mfGetColorForHex:checkedColorHex]: [UIColor blackColor];
|
||||||
|
UIColor *unCheckedColor = unCheckedColorHex ? [UIColor mfGetColorForHex:unCheckedColorHex]: [UIColor clearColor];
|
||||||
|
|
||||||
|
[self setupWithCheckedColor:checkedColor
|
||||||
|
unCheckColor:unCheckedColor
|
||||||
|
label:[json dict:KeyLabel]
|
||||||
|
delegateObject:delegateObject
|
||||||
|
additionalData: additionalData];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - convenient class methods
|
#pragma mark - convenient class methods
|
||||||
|
|
||||||
+ (instancetype)mfCheckBox {
|
+ (instancetype)mfCheckBox {
|
||||||
@ -69,8 +105,33 @@ static const CGFloat CheckBoxHeightWidth = 18.0;
|
|||||||
return checkBox;
|
return checkBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - FormValidationProtocol
|
||||||
|
|
||||||
|
- (BOOL)isValidField {
|
||||||
|
if (self.isRequired) {
|
||||||
|
return self.isSelected;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (nullable NSString *)formFieldName {
|
||||||
|
return self.fieldKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (nullable id)formFieldValue {
|
||||||
|
return @(self.isSelected);
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - inits
|
#pragma mark - inits
|
||||||
|
|
||||||
|
- (instancetype)init {
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
[self setupView];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
- (instancetype)initWithCheckedColor:(UIColor *)checkedColor unCheckColor:(UIColor *)unCheckedColor text:(NSString *)text {
|
- (instancetype)initWithCheckedColor:(UIColor *)checkedColor unCheckColor:(UIColor *)unCheckedColor text:(NSString *)text {
|
||||||
if (self = [super init]) {
|
if (self = [super init]) {
|
||||||
[self setupWithCheckedColor:checkedColor unCheckColor:unCheckedColor text:text];
|
[self setupWithCheckedColor:checkedColor unCheckColor:unCheckedColor text:text];
|
||||||
@ -207,17 +268,25 @@ static const CGFloat CheckBoxHeightWidth = 18.0;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setupWithCheckedColor:(UIColor *)checkedColor unCheckColor:(UIColor *)unCheckedColor {
|
||||||
|
if (checkedColor) {
|
||||||
|
self.checkedColor = checkedColor;
|
||||||
|
}
|
||||||
|
if (unCheckedColor) {
|
||||||
|
self.unCheckedColor = unCheckedColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setupWithCheckedColor:(UIColor *)checkedColor unCheckColor:(UIColor *)unCheckedColor text:(NSString *)text {
|
- (void)setupWithCheckedColor:(UIColor *)checkedColor unCheckColor:(UIColor *)unCheckedColor text:(NSString *)text {
|
||||||
[self setupView];
|
[self setupWithCheckedColor:checkedColor unCheckColor:unCheckedColor];
|
||||||
if (checkedColor) {
|
|
||||||
self.checkedColor = checkedColor;
|
|
||||||
}
|
|
||||||
if (unCheckedColor) {
|
|
||||||
self.unCheckedColor = unCheckedColor;
|
|
||||||
}
|
|
||||||
[self setDescriptionText:text];
|
[self setDescriptionText:text];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setupWithCheckedColor:(UIColor *)checkedColor unCheckColor:(UIColor *)unCheckedColor label:(NSDictionary *)labelJson delegateObject:(DelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData {
|
||||||
|
[self setupWithCheckedColor:checkedColor unCheckColor:unCheckedColor];
|
||||||
|
[self.descriptionLabel setWithJSON:labelJson delegateObject:delegateObject additionalData:additionalData];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)updateView:(CGFloat)size {
|
- (void)updateView:(CGFloat)size {
|
||||||
[MVMCoreDispatchUtility performBlockOnMainThread:^{
|
[MVMCoreDispatchUtility performBlockOnMainThread:^{
|
||||||
[self.descriptionLabel updateView:size];
|
[self.descriptionLabel updateView:size];
|
||||||
@ -254,7 +323,7 @@ static const CGFloat CheckBoxHeightWidth = 18.0;
|
|||||||
[self setSelected:selected animated:animated runBlock:YES];
|
[self setSelected:selected animated:animated runBlock:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setSelected:(BOOL)selected animated:(BOOL)animated runBlock:(BOOL)runBlock{
|
- (void)setSelected:(BOOL)selected animated:(BOOL)animated runBlock:(BOOL)runBlock {
|
||||||
[self addAccessibilityLabel:selected];
|
[self addAccessibilityLabel:selected];
|
||||||
|
|
||||||
self.isSelected = selected;
|
self.isSelected = selected;
|
||||||
@ -272,6 +341,9 @@ static const CGFloat CheckBoxHeightWidth = 18.0;
|
|||||||
} completion:nil];
|
} completion:nil];
|
||||||
[self.checkMark updateCheckSelected:NO animated:animated];
|
[self.checkMark updateCheckSelected:NO animated:animated];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FormValidator *formValidator = ((MVMCoreUIDelegateObject *)self.delegate).formValidationProtocol.formValidatorModel;
|
||||||
|
[formValidator enableByValidation];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setColor:(nullable UIColor *)color forState:(UIControlState)state {
|
- (void)setColor:(nullable UIColor *)color forState:(UIControlState)state {
|
||||||
|
|||||||
@ -26,6 +26,9 @@
|
|||||||
// Returns a view with the provided view as a subview, pinned.
|
// Returns a view with the provided view as a subview, pinned.
|
||||||
+ (nonnull ViewConstrainingView *)viewConstrainingView:(nonnull UIView *)view;
|
+ (nonnull ViewConstrainingView *)viewConstrainingView:(nonnull UIView *)view;
|
||||||
|
|
||||||
|
// Can be initialized with a molecule to constrain
|
||||||
|
- (nullable instancetype)initWithMolecule:(nonnull UIView <MVMCoreUIMoleculeViewProtocol>*)molecule alignment:(UIStackViewAlignment)alignment;
|
||||||
|
|
||||||
// Use these to sets the constants, because subclasses may align differently.
|
// Use these to sets the constants, because subclasses may align differently.
|
||||||
- (void)setPinConstantsWithInsets:(UIEdgeInsets)insets;
|
- (void)setPinConstantsWithInsets:(UIEdgeInsets)insets;
|
||||||
- (void)setTopPinConstant:(CGFloat)top left:(CGFloat)left bottom:(CGFloat)bottom right:(CGFloat)right;
|
- (void)setTopPinConstant:(CGFloat)top left:(CGFloat)left bottom:(CGFloat)bottom right:(CGFloat)right;
|
||||||
@ -47,4 +50,7 @@
|
|||||||
// For setting up the view.
|
// For setting up the view.
|
||||||
- (void)setupView;
|
- (void)setupView;
|
||||||
|
|
||||||
|
// Add a view to be constrained in this view.
|
||||||
|
- (void)addConstrainedView:(nonnull UIView *)view;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@ -9,14 +9,27 @@
|
|||||||
#import "ViewConstrainingView.h"
|
#import "ViewConstrainingView.h"
|
||||||
@import MVMCore.MVMCoreConstants;
|
@import MVMCore.MVMCoreConstants;
|
||||||
@import MVMCore.MVMCoreDispatchUtility;
|
@import MVMCore.MVMCoreDispatchUtility;
|
||||||
|
#import "NSLayoutConstraint+MFConvenience.h"
|
||||||
#import "MFStyler.h"
|
#import "MFStyler.h"
|
||||||
|
|
||||||
@interface ViewConstrainingView ()
|
@interface ViewConstrainingView ()
|
||||||
@property (weak, nullable, nonatomic) UIView *constrainedView;
|
@property (weak, nullable, nonatomic) UIView *constrainedView;
|
||||||
|
@property (weak, nullable, nonatomic) UIView <MVMCoreUIMoleculeViewProtocol>*molecule;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation ViewConstrainingView
|
@implementation ViewConstrainingView
|
||||||
|
|
||||||
|
- (nullable instancetype)initWithMolecule:(nonnull UIView <MVMCoreUIMoleculeViewProtocol>*)molecule alignment:(UIStackViewAlignment)alignment {
|
||||||
|
if (self = [super init]) {
|
||||||
|
if (!molecule.superview) {
|
||||||
|
[self addConstrainedView:molecule alignment:alignment];
|
||||||
|
[self setAsMolecule];
|
||||||
|
}
|
||||||
|
self.molecule = molecule;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
+ (nonnull ViewConstrainingView *)emptyView {
|
+ (nonnull ViewConstrainingView *)emptyView {
|
||||||
ViewConstrainingView *view = [[ViewConstrainingView alloc] initWithFrame:CGRectZero];
|
ViewConstrainingView *view = [[ViewConstrainingView alloc] initWithFrame:CGRectZero];
|
||||||
view.translatesAutoresizingMaskIntoConstraints = NO;
|
view.translatesAutoresizingMaskIntoConstraints = NO;
|
||||||
@ -28,48 +41,16 @@
|
|||||||
ViewConstrainingView *constrainingView = [[ViewConstrainingView alloc] initWithFrame:CGRectZero];
|
ViewConstrainingView *constrainingView = [[ViewConstrainingView alloc] initWithFrame:CGRectZero];
|
||||||
constrainingView.translatesAutoresizingMaskIntoConstraints = NO;
|
constrainingView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||||
constrainingView.backgroundColor = [UIColor clearColor];
|
constrainingView.backgroundColor = [UIColor clearColor];
|
||||||
|
[constrainingView addConstrainedView:view];
|
||||||
view.translatesAutoresizingMaskIntoConstraints = NO;
|
|
||||||
[constrainingView addSubview:view];
|
|
||||||
constrainingView.constrainedView = view;
|
|
||||||
|
|
||||||
NSLayoutConstraint *leftPin = [view.leftAnchor constraintEqualToAnchor:constrainingView.leftAnchor];
|
|
||||||
constrainingView.leftPin = leftPin;
|
|
||||||
leftPin.active = YES;
|
|
||||||
|
|
||||||
NSLayoutConstraint *topPin = [view.topAnchor constraintEqualToAnchor:constrainingView.topAnchor];
|
|
||||||
constrainingView.topPin = topPin;
|
|
||||||
topPin.active = YES;
|
|
||||||
|
|
||||||
NSLayoutConstraint *bottomPin = [constrainingView.bottomAnchor constraintEqualToAnchor:view.bottomAnchor];
|
|
||||||
constrainingView.bottomPin = bottomPin;
|
|
||||||
bottomPin.active = YES;
|
|
||||||
|
|
||||||
NSLayoutConstraint *rightPin = [constrainingView.rightAnchor constraintEqualToAnchor:view.rightAnchor];
|
|
||||||
constrainingView.rightPin = rightPin;
|
|
||||||
rightPin.active = YES;
|
|
||||||
|
|
||||||
return constrainingView;
|
return constrainingView;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)pinToSuperView {
|
- (void)pinToSuperView {
|
||||||
|
NSDictionary *dictionary = [NSLayoutConstraint constraintPinSubviewToSuperview:self];
|
||||||
// Align left and right constants.
|
self.leftPin = dictionary[ConstraintLeading];
|
||||||
NSLayoutConstraint *leftPin = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0];
|
self.topPin = dictionary[ConstraintTop];
|
||||||
self.leftPin = leftPin;
|
self.bottomPin = dictionary[ConstraintBot];
|
||||||
leftPin.active = YES;
|
self.rightPin = dictionary[ConstraintTrailing];
|
||||||
|
|
||||||
NSLayoutConstraint *topPin = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
|
|
||||||
self.topPin = topPin;
|
|
||||||
topPin.active = YES;
|
|
||||||
|
|
||||||
NSLayoutConstraint *bottomPin = [NSLayoutConstraint constraintWithItem:self.superview attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];
|
|
||||||
self.bottomPin = bottomPin;
|
|
||||||
bottomPin.active = YES;
|
|
||||||
|
|
||||||
NSLayoutConstraint *rightPin = [NSLayoutConstraint constraintWithItem:self.superview attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1.0 constant:0];
|
|
||||||
self.rightPin = rightPin;
|
|
||||||
rightPin.active = YES;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setPinConstantsWithInsets:(UIEdgeInsets)insets {
|
- (void)setPinConstantsWithInsets:(UIEdgeInsets)insets {
|
||||||
@ -115,6 +96,34 @@
|
|||||||
self.backgroundColor = [UIColor clearColor];
|
self.backgroundColor = [UIColor clearColor];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)addConstrainedView:(nonnull UIView *)view alignment:(UIStackViewAlignment)alignment {
|
||||||
|
view.translatesAutoresizingMaskIntoConstraints = NO;
|
||||||
|
[self addSubview:view];
|
||||||
|
self.constrainedView = view;
|
||||||
|
|
||||||
|
NSLayoutRelation leftRelation;
|
||||||
|
if (alignment == UIStackViewAlignmentFill || alignment == UIStackViewAlignmentLeading || alignment == UIStackViewAlignmentFirstBaseline) {
|
||||||
|
leftRelation = NSLayoutRelationEqual;
|
||||||
|
} else {
|
||||||
|
leftRelation = NSLayoutRelationGreaterThanOrEqual;
|
||||||
|
}
|
||||||
|
NSLayoutRelation rightRelation;
|
||||||
|
if (alignment == UIStackViewAlignmentFill || alignment == UIStackViewAlignmentTrailing || alignment == UIStackViewAlignmentLastBaseline) {
|
||||||
|
rightRelation = NSLayoutRelationEqual;
|
||||||
|
} else {
|
||||||
|
rightRelation = NSLayoutRelationGreaterThanOrEqual;
|
||||||
|
}
|
||||||
|
NSDictionary *dictionary = [NSLayoutConstraint constraintPinSubview:view topRelation:NSLayoutRelationEqual bottomRelation:NSLayoutRelationEqual leftRelation:leftRelation rightRelation:rightRelation];
|
||||||
|
self.leftPin = dictionary[ConstraintLeading];
|
||||||
|
self.topPin = dictionary[ConstraintTop];
|
||||||
|
self.bottomPin = dictionary[ConstraintBot];
|
||||||
|
self.rightPin = dictionary[ConstraintTrailing];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)addConstrainedView:(nonnull UIView *)view {
|
||||||
|
[self addConstrainedView:view alignment:UIStackViewAlignmentFill];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setupView {
|
- (void)setupView {
|
||||||
[super setupView];
|
[super setupView];
|
||||||
self.translatesAutoresizingMaskIntoConstraints = NO;
|
self.translatesAutoresizingMaskIntoConstraints = NO;
|
||||||
@ -131,6 +140,7 @@
|
|||||||
CGFloat padding = [MFStyler defaultHorizontalPaddingForSize:size];
|
CGFloat padding = [MFStyler defaultHorizontalPaddingForSize:size];
|
||||||
[self setLeftPinConstant:padding];
|
[self setLeftPinConstant:padding];
|
||||||
[self setRightPinConstant:padding];
|
[self setRightPinConstant:padding];
|
||||||
|
[MFStyler setDefaultMarginsForView:self size:size];
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -138,6 +148,15 @@
|
|||||||
#pragma mark - MVMCoreUIMoleculeViewProtocol
|
#pragma mark - MVMCoreUIMoleculeViewProtocol
|
||||||
|
|
||||||
- (void)setAsMolecule {
|
- (void)setAsMolecule {
|
||||||
|
self.updateViewHorizontalDefaults = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setWithJSON:(NSDictionary *)json delegateObject:(DelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData {
|
||||||
|
[super setWithJSON:json delegateObject:delegateObject additionalData:additionalData];
|
||||||
|
if (self.molecule) {
|
||||||
|
[self.molecule setWithJSON:json delegateObject:delegateObject additionalData:additionalData];
|
||||||
|
self.backgroundColor = self.molecule.backgroundColor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@ -521,6 +521,10 @@
|
|||||||
} completion:completion];
|
} completion:completion];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)viewRespectsSystemMinimumLayoutMargins {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - UITextField Functions
|
#pragma mark - UITextField Functions
|
||||||
|
|
||||||
// To Remove TextFields Bug: Keyboard is not dismissing after reaching textfield max length limit
|
// To Remove TextFields Bug: Keyboard is not dismissing after reaching textfield max length limit
|
||||||
|
|||||||
255
MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift
Normal file
255
MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
//
|
||||||
|
// ThreeLayerTableViewController.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Scott Pfeil on 4/18/19.
|
||||||
|
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import MVMAnimationFramework
|
||||||
|
|
||||||
|
open class ThreeLayerTableViewController: MFProgrammaticTableViewController {
|
||||||
|
// The three main views
|
||||||
|
private var topView: UIView?
|
||||||
|
private var bottomView: UIView?
|
||||||
|
private var headerView: UIView?
|
||||||
|
private var footerView: UIView?
|
||||||
|
private var safeAreaView: UIView?
|
||||||
|
var useMargins: Bool = true
|
||||||
|
var bottomViewOutsideOfScrollArea: Bool = false
|
||||||
|
private var topViewBottomConstraint: NSLayoutConstraint?
|
||||||
|
private var bottomViewTopConstraint: NSLayoutConstraint?
|
||||||
|
|
||||||
|
//MARK: - MVMCoreViewProtocol
|
||||||
|
open override func updateViews() {
|
||||||
|
super.updateViews()
|
||||||
|
let width = view.bounds.width
|
||||||
|
MFStyler.setDefaultMarginsFor(contentView, size: width)
|
||||||
|
if let topView = topView as? MVMCoreViewProtocol {
|
||||||
|
topView.updateView(width)
|
||||||
|
showHeader()
|
||||||
|
}
|
||||||
|
if let bottomView = bottomView as? MVMCoreViewProtocol {
|
||||||
|
bottomView.updateView(width)
|
||||||
|
showFooter()
|
||||||
|
}
|
||||||
|
self.tableView?.reloadData()
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: - MFViewController
|
||||||
|
open override func newDataBuildScreen() {
|
||||||
|
super.newDataBuildScreen()
|
||||||
|
createViewForTableHeader()
|
||||||
|
createViewForTableFooter()
|
||||||
|
tableView?.reloadData()
|
||||||
|
}
|
||||||
|
|
||||||
|
override open func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
setToHaveNoSectionHeadersFooters()
|
||||||
|
// Do any additional setup after loading the view.
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: - Spacing
|
||||||
|
// If both are subclassed to return a value, then the buttons will not be pinned towards the bottom because neither spacing would try to fill the screen.
|
||||||
|
/// Space between the top view and the table sections, nil to fill. 0 default
|
||||||
|
open func spaceBelowTopView() -> CGFloat? {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Space between the bottom view and the table sections, nil to fill. nil default
|
||||||
|
open func spaceAboveBottomView() -> CGFloat? {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/// can override to return a minimum fill space.
|
||||||
|
open func minimumFillSpace() -> CGFloat {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func updateViewConstraints() {
|
||||||
|
super.updateViewConstraints()
|
||||||
|
guard let tableView = tableView else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let minimumSpace: CGFloat = minimumFillSpace()
|
||||||
|
var currentSpace: CGFloat = 0
|
||||||
|
var totalMinimumSpace: CGFloat = 0
|
||||||
|
|
||||||
|
var fillTop = false
|
||||||
|
if spaceBelowTopView() == nil, self.tableView?.tableHeaderView != nil {
|
||||||
|
fillTop = true
|
||||||
|
currentSpace += topViewBottomConstraint?.constant ?? 0
|
||||||
|
totalMinimumSpace += minimumSpace
|
||||||
|
}
|
||||||
|
|
||||||
|
var fillBottom = false
|
||||||
|
if spaceAboveBottomView() == nil, !bottomViewOutsideOfScrollArea, self.tableView?.tableFooterView != nil {
|
||||||
|
fillBottom = true
|
||||||
|
currentSpace += bottomViewTopConstraint?.constant ?? 0
|
||||||
|
totalMinimumSpace += minimumSpace
|
||||||
|
}
|
||||||
|
|
||||||
|
guard fillTop || fillBottom else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let newSpace = MVMCoreUIUtility.getVariableConstraintHeight(currentSpace, in: tableView, minimumHeight: totalMinimumSpace)
|
||||||
|
|
||||||
|
// If the bottom view is outside of the scroll, then only the top view constraint is being used, so we have to double it to account for the bottom constraint not being there when we compare to the new value.
|
||||||
|
var currentSpaceForCompare: CGFloat = currentSpace
|
||||||
|
if fillTop && bottomViewOutsideOfScrollArea {
|
||||||
|
currentSpaceForCompare = currentSpace * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !MVMCoreGetterUtility.cgfequalwiththreshold(newSpace, currentSpaceForCompare, 0.1) {
|
||||||
|
if fillTop && fillBottom {
|
||||||
|
// space both
|
||||||
|
let half = newSpace / 2
|
||||||
|
topViewBottomConstraint?.constant = half
|
||||||
|
bottomViewTopConstraint?.constant = half
|
||||||
|
showHeader()
|
||||||
|
showFooter()
|
||||||
|
} else if fillTop {
|
||||||
|
// Only top is spaced (half the size if the bottom view is out of the scroll because it needs to be sized as if there are two spacers but there is only one.
|
||||||
|
if bottomViewOutsideOfScrollArea {
|
||||||
|
topViewBottomConstraint?.constant = newSpace / 2
|
||||||
|
} else {
|
||||||
|
topViewBottomConstraint?.constant = newSpace
|
||||||
|
}
|
||||||
|
showHeader()
|
||||||
|
} else if fillBottom {
|
||||||
|
// Only bottom is spaced.
|
||||||
|
bottomViewTopConstraint?.constant = newSpace
|
||||||
|
showFooter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: - Header Footer
|
||||||
|
/// Gets the top view and adds it to a spacing view, headerView, and then calls showHeader.
|
||||||
|
open func createViewForTableHeader() {
|
||||||
|
let topView = viewForTop()
|
||||||
|
self.topView = topView
|
||||||
|
|
||||||
|
let headerView = MVMCoreUICommonViewsUtility.commonView()
|
||||||
|
headerView.addSubview(topView)
|
||||||
|
topView.topAnchor.constraint(equalTo: headerView.topAnchor).isActive = true
|
||||||
|
topView.leftAnchor.constraint(equalTo: headerView.leftAnchor).isActive = true
|
||||||
|
headerView.rightAnchor.constraint(equalTo: topView.rightAnchor).isActive = true
|
||||||
|
topViewBottomConstraint = headerView.bottomAnchor.constraint(equalTo: topView.bottomAnchor, constant: spaceBelowTopView() ?? 0)
|
||||||
|
topViewBottomConstraint?.isActive = true
|
||||||
|
self.headerView = headerView
|
||||||
|
showHeader()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the bottom view and adds it to a spacing view, footerView, and then calls showFooter.
|
||||||
|
open func createViewForTableFooter() {
|
||||||
|
let bottomView = viewForBottom()
|
||||||
|
self.bottomView = bottomView
|
||||||
|
|
||||||
|
let footerView = MVMCoreUICommonViewsUtility.commonView()
|
||||||
|
footerView.addSubview(bottomView)
|
||||||
|
bottomViewTopConstraint = bottomView.topAnchor.constraint(equalTo: footerView.topAnchor, constant: spaceAboveBottomView() ?? 0)
|
||||||
|
bottomViewTopConstraint?.isActive = true
|
||||||
|
bottomView.leftAnchor.constraint(equalTo: footerView.leftAnchor).isActive = true
|
||||||
|
footerView.rightAnchor.constraint(equalTo: bottomView.rightAnchor).isActive = true
|
||||||
|
footerView.bottomAnchor.constraint(equalTo: bottomView.bottomAnchor).isActive = true
|
||||||
|
self.footerView = footerView
|
||||||
|
showFooter()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes the current headerView and adds it to the tableHeaderView
|
||||||
|
func showHeader() {
|
||||||
|
headerView?.removeFromSuperview()
|
||||||
|
tableView?.tableHeaderView = nil
|
||||||
|
guard let headerView = headerView else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// This extra view is needed because of the wonkiness of apple's table header. Things breaks if using autolayout.
|
||||||
|
MVMCoreUIUtility.sizeView(toFit: headerView)
|
||||||
|
let tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: MVMCoreUIUtility.getWidth(), height: headerView.frame.height))
|
||||||
|
tableHeaderView.addSubview(headerView)
|
||||||
|
NSLayoutConstraint.constraintPinSubview(toSuperview: headerView)
|
||||||
|
tableView?.tableHeaderView = tableHeaderView
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes the current footerView and adds it to the tableFooterView
|
||||||
|
func showFooter() {
|
||||||
|
footerView?.removeFromSuperview()
|
||||||
|
safeAreaView?.removeFromSuperview()
|
||||||
|
guard let footerView = footerView, let tableView = tableView else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if bottomViewOutsideOfScrollArea {
|
||||||
|
// put bottom view outside of scrolling area.
|
||||||
|
bottomConstraint?.isActive = false
|
||||||
|
view.addSubview(footerView)
|
||||||
|
footerView.topAnchor.constraint(equalTo: tableView.bottomAnchor).isActive = true
|
||||||
|
footerView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
|
||||||
|
view.rightAnchor.constraint(equalTo: footerView.rightAnchor).isActive = true
|
||||||
|
if #available(iOS 11.0, *) {
|
||||||
|
view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: footerView.bottomAnchor).isActive = true
|
||||||
|
safeAreaView = MVMCoreUICommonViewsUtility.getAndSetupSafeAreaView(on: view)
|
||||||
|
safeAreaView?.backgroundColor = bottomView?.backgroundColor
|
||||||
|
} else {
|
||||||
|
view.bottomAnchor.constraint(equalTo: footerView.bottomAnchor).isActive = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bottomConstraint?.isActive = true
|
||||||
|
var y: CGFloat?
|
||||||
|
if let tableFooterView = tableView.tableFooterView {
|
||||||
|
// if footer already exists, use the same y location to avoid strange moving animation
|
||||||
|
y = tableFooterView.frame.minY
|
||||||
|
}
|
||||||
|
|
||||||
|
// This extra view is needed because of the wonkiness of apple's table footer. Things breaks if using autolayout.
|
||||||
|
MVMCoreUIUtility.sizeView(toFit: footerView)
|
||||||
|
let tableFooterView = UIView(frame: CGRect(x: 0, y: y ?? 0, width: MVMCoreUIUtility.getWidth(), height: footerView.frame.height))
|
||||||
|
tableFooterView.addSubview(footerView)
|
||||||
|
NSLayoutConstraint.constraintPinSubview(toSuperview: footerView)
|
||||||
|
tableView.tableFooterView = tableFooterView
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: - Functions to subclass
|
||||||
|
/// Subclass for a top view.
|
||||||
|
open func viewForTop() -> UIView {
|
||||||
|
let view = MVMCoreUICommonViewsUtility.commonView()
|
||||||
|
view.heightAnchor.constraint(equalToConstant: 0).isActive = true
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Subclass for a bottom view.
|
||||||
|
open func viewForBottom() -> UIView {
|
||||||
|
let view = MVMCoreUICommonViewsUtility.commonView()
|
||||||
|
view.heightAnchor.constraint(equalToConstant: 0).isActive = true
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: - Scrollview
|
||||||
|
open override func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||||
|
// To stop handscroll animation if animating after scroll
|
||||||
|
stopHandScrollAnimation(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
tableView?.delegate = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: - Animation
|
||||||
|
open override func setupIntroAnimations() {
|
||||||
|
if let topView = topView, topView.subviews.count > 0 {
|
||||||
|
introAnimationManager?.addAnimation(animation: MVMAnimations.fadeUpAnimation(view: topView))
|
||||||
|
}
|
||||||
|
if let tableView = tableView {
|
||||||
|
introAnimationManager?.addAnimation(animation: MVMAnimations.animateTableViewFadeInCells(tableView: tableView))
|
||||||
|
}
|
||||||
|
if let bottomView = bottomView, bottomView.subviews.count > 0 {
|
||||||
|
introAnimationManager?.addAnimation(animation: MVMAnimations.fadeUpAnimation(view: bottomView))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -16,7 +16,7 @@ open class ThreeLayerViewController: ProgrammaticScrollViewController {
|
|||||||
var topView: UIView?
|
var topView: UIView?
|
||||||
var middleView: UIView?
|
var middleView: UIView?
|
||||||
var bottomView: UIView?
|
var bottomView: UIView?
|
||||||
var useMargins: Bool = true
|
var useMargins: Bool = false
|
||||||
|
|
||||||
// The bottom view can be put outside of the scrolling area.
|
// The bottom view can be put outside of the scrolling area.
|
||||||
var bottomViewOutsideOfScroll = false
|
var bottomViewOutsideOfScroll = false
|
||||||
|
|||||||
@ -31,8 +31,12 @@ extern NSString * _Nonnull const ConstraintWidth;
|
|||||||
|
|
||||||
+ (nullable NSDictionary *)constraintPinSubview:(nullable UIView *)subview pinTop:(BOOL)pinTop pinBottom:(BOOL)pinBottom pinLeft:(BOOL)pinLeft pinRight:(BOOL)pinRight;
|
+ (nullable NSDictionary *)constraintPinSubview:(nullable UIView *)subview pinTop:(BOOL)pinTop pinBottom:(BOOL)pinBottom pinLeft:(BOOL)pinLeft pinRight:(BOOL)pinRight;
|
||||||
|
|
||||||
|
+ (nullable NSDictionary *)constraintPinSubview:(nullable UIView *)subview topRelation:(NSLayoutRelation)topRelation bottomRelation:(NSLayoutRelation)bottomRelation leftRelation:(NSLayoutRelation)leftRelation rightRelation:(NSLayoutRelation)rightRelation;
|
||||||
|
|
||||||
+ (nullable NSDictionary *)constraintPinSubview:(nullable UIView *)subview pinTop:(BOOL)pinTop topConstant:(CGFloat)topConstant pinBottom:(BOOL)pinBottom bottomConstant:(CGFloat)bottomConstant pinLeft:(BOOL)pinLeft leftConstant:(CGFloat)leftConstant pinRight:(BOOL)pinRight rightConstant:(CGFloat)rightConstant;
|
+ (nullable NSDictionary *)constraintPinSubview:(nullable UIView *)subview pinTop:(BOOL)pinTop topConstant:(CGFloat)topConstant pinBottom:(BOOL)pinBottom bottomConstant:(CGFloat)bottomConstant pinLeft:(BOOL)pinLeft leftConstant:(CGFloat)leftConstant pinRight:(BOOL)pinRight rightConstant:(CGFloat)rightConstant;
|
||||||
|
|
||||||
|
+ (nullable NSDictionary *)constraintPinSubview:(nullable UIView *)subview pinTop:(BOOL)pinTop topConstant:(CGFloat)topConstant topRelation:(NSLayoutRelation)topRelation pinBottom:(BOOL)pinBottom bottomConstant:(CGFloat)bottomConstant bottomRelation:(NSLayoutRelation)bottomRelation pinLeft:(BOOL)pinLeft leftConstant:(CGFloat)leftConstant leftRelation:(NSLayoutRelation)leftRelation pinRight:(BOOL)pinRight rightConstant:(CGFloat)rightConstant rightRelation:(NSLayoutRelation)rightRelation;
|
||||||
|
|
||||||
// Pin subview with 1 side
|
// Pin subview with 1 side
|
||||||
+ (nullable NSDictionary *)constraintPinTopSubview:(nonnull UIView *)subview topConstant:(CGFloat)topConstant;
|
+ (nullable NSDictionary *)constraintPinTopSubview:(nonnull UIView *)subview topConstant:(CGFloat)topConstant;
|
||||||
+ (nullable NSDictionary *)constraintPinBottomSubview:(nonnull UIView *)subview bottomConstant:(CGFloat)bottomConstant;
|
+ (nullable NSDictionary *)constraintPinBottomSubview:(nonnull UIView *)subview bottomConstant:(CGFloat)bottomConstant;
|
||||||
@ -57,6 +61,7 @@ extern NSString * _Nonnull const ConstraintWidth;
|
|||||||
|
|
||||||
#pragma mark - With Margins
|
#pragma mark - With Margins
|
||||||
|
|
||||||
|
+ (nonnull NSDictionary <NSString *, NSLayoutConstraint *>*)pinViewToSuperview:(nonnull UIView *)subview useMargins:(BOOL)useMargins;
|
||||||
+ (nonnull NSLayoutConstraint *)pinViewTopToSuperview:(nonnull UIView *)view useMargins:(BOOL)useMargins constant:(CGFloat)constant;
|
+ (nonnull NSLayoutConstraint *)pinViewTopToSuperview:(nonnull UIView *)view useMargins:(BOOL)useMargins constant:(CGFloat)constant;
|
||||||
+ (nonnull NSLayoutConstraint *)pinViewLeftToSuperview:(nonnull UIView *)view useMargins:(BOOL)useMargins constant:(CGFloat)constant;
|
+ (nonnull NSLayoutConstraint *)pinViewLeftToSuperview:(nonnull UIView *)view useMargins:(BOOL)useMargins constant:(CGFloat)constant;
|
||||||
+ (nonnull NSLayoutConstraint *)pinViewRightToSuperview:(nonnull UIView *)view useMargins:(BOOL)useMargins constant:(CGFloat)constant;
|
+ (nonnull NSLayoutConstraint *)pinViewRightToSuperview:(nonnull UIView *)view useMargins:(BOOL)useMargins constant:(CGFloat)constant;
|
||||||
|
|||||||
@ -44,29 +44,37 @@ NSString *const ConstraintWidth = @"width";
|
|||||||
return [NSLayoutConstraint constraintPinSubview:subview pinTop:pinTop topConstant:0 pinBottom:pinBottom bottomConstant:0 pinLeft:pinLeft leftConstant:0 pinRight:pinRight rightConstant:0];
|
return [NSLayoutConstraint constraintPinSubview:subview pinTop:pinTop topConstant:0 pinBottom:pinBottom bottomConstant:0 pinLeft:pinLeft leftConstant:0 pinRight:pinRight rightConstant:0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (nullable NSDictionary *)constraintPinSubview:(nullable UIView *)subview topRelation:(NSLayoutRelation)topRelation bottomRelation:(NSLayoutRelation)bottomRelation leftRelation:(NSLayoutRelation)leftRelation rightRelation:(NSLayoutRelation)rightRelation {
|
||||||
|
return [self constraintPinSubview:subview pinTop:YES topConstant:0 topRelation:topRelation pinBottom:YES bottomConstant:0 bottomRelation:bottomRelation pinLeft:YES leftConstant:0 leftRelation:leftRelation pinRight:YES rightConstant:0 rightRelation:rightRelation];
|
||||||
|
}
|
||||||
|
|
||||||
+ (NSDictionary *)constraintPinSubview:(UIView *)subview pinTop:(BOOL)pinTop topConstant:(CGFloat)topConstant pinBottom:(BOOL)pinBottom bottomConstant:(CGFloat)bottomConstant pinLeft:(BOOL)pinLeft leftConstant:(CGFloat)leftConstant pinRight:(BOOL)pinRight rightConstant:(CGFloat)rightConstant {
|
+ (NSDictionary *)constraintPinSubview:(UIView *)subview pinTop:(BOOL)pinTop topConstant:(CGFloat)topConstant pinBottom:(BOOL)pinBottom bottomConstant:(CGFloat)bottomConstant pinLeft:(BOOL)pinLeft leftConstant:(CGFloat)leftConstant pinRight:(BOOL)pinRight rightConstant:(CGFloat)rightConstant {
|
||||||
|
return [self constraintPinSubview:subview pinTop:pinTop topConstant:topConstant topRelation:NSLayoutRelationEqual pinBottom:pinBottom bottomConstant:bottomConstant bottomRelation:NSLayoutRelationEqual pinLeft:pinLeft leftConstant:leftConstant leftRelation:NSLayoutRelationEqual pinRight:pinRight rightConstant:rightConstant rightRelation:NSLayoutRelationEqual];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSDictionary *)constraintPinSubview:(UIView *)subview pinTop:(BOOL)pinTop topConstant:(CGFloat)topConstant topRelation:(NSLayoutRelation)topRelation pinBottom:(BOOL)pinBottom bottomConstant:(CGFloat)bottomConstant bottomRelation:(NSLayoutRelation)bottomRelation pinLeft:(BOOL)pinLeft leftConstant:(CGFloat)leftConstant leftRelation:(NSLayoutRelation)leftRelation pinRight:(BOOL)pinRight rightConstant:(CGFloat)rightConstant rightRelation:(NSLayoutRelation)rightRelation {
|
||||||
UIView *superview = subview.superview;
|
UIView *superview = subview.superview;
|
||||||
NSMutableDictionary *constraintDic = [[NSMutableDictionary alloc] init];
|
NSMutableDictionary *constraintDic = [[NSMutableDictionary alloc] init];
|
||||||
if (pinTop) {
|
if (pinTop) {
|
||||||
NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeTop multiplier:1 constant:topConstant];
|
NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeTop relatedBy:topRelation toItem:superview attribute:NSLayoutAttributeTop multiplier:1 constant:topConstant];
|
||||||
top.priority = 999;
|
top.priority = 999;
|
||||||
top.active = YES;
|
top.active = YES;
|
||||||
[constraintDic setObject:top forKey:ConstraintTop];
|
[constraintDic setObject:top forKey:ConstraintTop];
|
||||||
}
|
}
|
||||||
if (pinBottom) {
|
if (pinBottom) {
|
||||||
NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:superview attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:subview attribute:NSLayoutAttributeBottom multiplier:1 constant:bottomConstant];
|
NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:superview attribute:NSLayoutAttributeBottom relatedBy:bottomRelation toItem:subview attribute:NSLayoutAttributeBottom multiplier:1 constant:bottomConstant];
|
||||||
bottom.priority = 999;
|
bottom.priority = 999;
|
||||||
bottom.active = YES;
|
bottom.active = YES;
|
||||||
[constraintDic setObject:bottom forKey:ConstraintBot];
|
[constraintDic setObject:bottom forKey:ConstraintBot];
|
||||||
}
|
}
|
||||||
if (pinLeft) {
|
if (pinLeft) {
|
||||||
NSLayoutConstraint *leading = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeLeading multiplier:1 constant:leftConstant];
|
NSLayoutConstraint *leading = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeLeading relatedBy:leftRelation toItem:superview attribute:NSLayoutAttributeLeading multiplier:1 constant:leftConstant];
|
||||||
leading.priority = 999;
|
leading.priority = 999;
|
||||||
leading.active = YES;
|
leading.active = YES;
|
||||||
[constraintDic setObject:leading forKey:ConstraintLeading];
|
[constraintDic setObject:leading forKey:ConstraintLeading];
|
||||||
}
|
}
|
||||||
if (pinRight) {
|
if (pinRight) {
|
||||||
NSLayoutConstraint *trailing = [NSLayoutConstraint constraintWithItem:superview attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:subview attribute:NSLayoutAttributeTrailing multiplier:1 constant:rightConstant];
|
NSLayoutConstraint *trailing = [NSLayoutConstraint constraintWithItem:superview attribute:NSLayoutAttributeTrailing relatedBy:rightRelation toItem:subview attribute:NSLayoutAttributeTrailing multiplier:1 constant:rightConstant];
|
||||||
trailing.priority = 999;
|
trailing.priority = 999;
|
||||||
trailing.active = YES;
|
trailing.active = YES;
|
||||||
[constraintDic setObject:trailing forKey:ConstraintTrailing];
|
[constraintDic setObject:trailing forKey:ConstraintTrailing];
|
||||||
@ -152,6 +160,14 @@ NSString *const ConstraintWidth = @"width";
|
|||||||
|
|
||||||
#pragma mark - With Margins
|
#pragma mark - With Margins
|
||||||
|
|
||||||
|
+ (nonnull NSDictionary *)pinViewToSuperview:(nonnull UIView *)subview useMargins:(BOOL)useMargins {
|
||||||
|
return @{ConstraintTop:[self pinViewTopToSuperview:subview useMargins:useMargins constant:0],
|
||||||
|
ConstraintLeading:[self pinViewLeftToSuperview:subview useMargins:useMargins constant:0],
|
||||||
|
ConstraintTrailing:[self pinViewRightToSuperview:subview useMargins:useMargins constant:0],
|
||||||
|
ConstraintBot:[self pinViewBottomToSuperview:subview useMargins:useMargins constant:0],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
+ (NSLayoutConstraint *)pinViewTopToSuperview:(UIView *)view useMargins:(BOOL)useMargins constant:(CGFloat)constant {
|
+ (NSLayoutConstraint *)pinViewTopToSuperview:(UIView *)view useMargins:(BOOL)useMargins constant:(CGFloat)constant {
|
||||||
return [view.topAnchor constraintEqualToAnchor:(useMargins ? view.superview.layoutMarginsGuide.topAnchor : view.superview.topAnchor) constant:constant];
|
return [view.topAnchor constraintEqualToAnchor:(useMargins ? view.superview.layoutMarginsGuide.topAnchor : view.superview.topAnchor) constant:constant];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,6 +22,6 @@ import Foundation
|
|||||||
// The Field name key value pair for sending to server
|
// The Field name key value pair for sending to server
|
||||||
@objc optional func formFieldName() -> String?
|
@objc optional func formFieldName() -> String?
|
||||||
|
|
||||||
// The Feild value key value paid for sending to server
|
// The Field value key value pair for sending to server
|
||||||
@objc optional func formFieldValue() -> String?
|
@objc optional func formFieldValue() -> Any?
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,15 @@
|
|||||||
// Called after init to provide an early setter for any molecule specific logic
|
// Called after init to provide an early setter for any molecule specific logic
|
||||||
- (void)setAsMolecule;
|
- (void)setAsMolecule;
|
||||||
|
|
||||||
|
// Notifies the creator that the view needs to be constrained in a view.
|
||||||
|
- (BOOL)needsToBeConstrained;
|
||||||
|
|
||||||
|
// The alignment for the molecule if constrained.
|
||||||
|
- (UIStackViewAlignment)moleculeAlignment;
|
||||||
|
|
||||||
|
// For the molecule list to load more efficiently.
|
||||||
|
+ (CGFloat)estimatedHeightForRow;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -13,6 +13,7 @@ public class MoleculeStackView: MFView {
|
|||||||
var moleculesArray: [UIView]?
|
var moleculesArray: [UIView]?
|
||||||
var useMargins: Bool = false
|
var useMargins: Bool = false
|
||||||
|
|
||||||
|
// MARK: - Inits
|
||||||
public override init(frame: CGRect) {
|
public override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
}
|
}
|
||||||
@ -31,6 +32,7 @@ public class MoleculeStackView: MFView {
|
|||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - MFViewProtocol
|
||||||
public override func setupView() {
|
public override func setupView() {
|
||||||
super.setupView()
|
super.setupView()
|
||||||
translatesAutoresizingMaskIntoConstraints = false
|
translatesAutoresizingMaskIntoConstraints = false
|
||||||
@ -48,17 +50,17 @@ public class MoleculeStackView: MFView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - MVMCoreUIMoleculeViewProtocol
|
||||||
open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) {
|
open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||||
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
||||||
guard let molecules = json?.arrayForKey("molecules") as? [[String: Any]] else {
|
guard let molecules = json?.arrayForKey(KeyMolecules) as? [[String: Any]] else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the molecules and set the json.
|
// Create the molecules and set the json.
|
||||||
var moleculesArray = [] as [UIView]
|
var moleculesArray = [] as [UIView]
|
||||||
for moleculeJSON in molecules {
|
for moleculeJSON in molecules {
|
||||||
if let name = moleculeJSON.optionalStringForKey("moleculeName"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForName(name) {
|
if let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForStack(withJSON: moleculeJSON, delegateObject: delegateObject) {
|
||||||
molecule.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: additionalData)
|
|
||||||
moleculesArray.append(molecule)
|
moleculesArray.append(molecule)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,12 +72,9 @@ public class MoleculeStackView: MFView {
|
|||||||
if let spacingBlock = spacingBlock {
|
if let spacingBlock = spacingBlock {
|
||||||
MVMCoreUIStackableViewController.populateView(self, withUIArray: moleculesArray, useMargins: useMargins, withSpacingBlock: spacingBlock)
|
MVMCoreUIStackableViewController.populateView(self, withUIArray: moleculesArray, useMargins: useMargins, withSpacingBlock: spacingBlock)
|
||||||
} else {
|
} else {
|
||||||
|
let separation = json?.optionalCGFloatForKey("separation") ?? PaddingDefault
|
||||||
MVMCoreUIStackableViewController.populateView(self, withUIArray: moleculesArray, useMargins: useMargins) { (object) -> UIEdgeInsets in
|
MVMCoreUIStackableViewController.populateView(self, withUIArray: moleculesArray, useMargins: useMargins) { (object) -> UIEdgeInsets in
|
||||||
if object as AnyObject? === moleculesArray.first {
|
return UIEdgeInsets.init(top: separation, left: 0, bottom: 0, right: 0)
|
||||||
return UIEdgeInsets.zero
|
|
||||||
} else {
|
|
||||||
return UIEdgeInsets.init(top: PaddingTwo, left: 0, bottom: 0, right: 0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
152
MVMCoreUI/Molecules/MoleculeTableViewCell.swift
Normal file
152
MVMCoreUI/Molecules/MoleculeTableViewCell.swift
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
//
|
||||||
|
// MoleculeTableViewCell.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Scott Pfeil on 4/18/19.
|
||||||
|
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
@objcMembers open class MoleculeTableViewCell: UITableViewCell, MVMCoreViewProtocol, MVMCoreUIMoleculeViewProtocol {
|
||||||
|
open var molecule: (UIView & MVMCoreUIMoleculeViewProtocol)?
|
||||||
|
|
||||||
|
// For the accessory view convenience.
|
||||||
|
public var caretView: CaretView?
|
||||||
|
private var caretViewWidthSizeObject: MFSizeObject?
|
||||||
|
private var caretViewHeightSizeObject: MFSizeObject?
|
||||||
|
|
||||||
|
// For separation between cells.
|
||||||
|
public var topSeparatorView: SeparatorView?
|
||||||
|
public var bottomSeparatorView: SeparatorView?
|
||||||
|
public enum SeparatorFrequency: String {
|
||||||
|
case All = "all"
|
||||||
|
case AllExceptTop = "allExceptTop"
|
||||||
|
case AllExceptBottom = "allExceptBottom"
|
||||||
|
case Between = "between"
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Inits
|
||||||
|
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||||
|
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||||
|
setupView()
|
||||||
|
}
|
||||||
|
|
||||||
|
public required init?(coder aDecoder: NSCoder) {
|
||||||
|
super.init(coder: aDecoder)
|
||||||
|
setupView()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - MFViewProtocol
|
||||||
|
public func updateView(_ size: CGFloat) {
|
||||||
|
MFStyler.setDefaultMarginsFor(self, size: size)
|
||||||
|
if #available(iOS 11.0, *) {
|
||||||
|
contentView.directionalLayoutMargins = directionalLayoutMargins
|
||||||
|
topSeparatorView?.setLeftAndRightPinConstant(directionalLayoutMargins.leading)
|
||||||
|
bottomSeparatorView?.setLeftAndRightPinConstant(directionalLayoutMargins.leading)
|
||||||
|
} else {
|
||||||
|
contentView.layoutMargins = layoutMargins
|
||||||
|
topSeparatorView?.setLeftAndRightPinConstant(layoutMargins.left)
|
||||||
|
bottomSeparatorView?.setLeftAndRightPinConstant(layoutMargins.left)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let molecule = molecule as? MVMCoreViewProtocol {
|
||||||
|
molecule.updateView(size)
|
||||||
|
}
|
||||||
|
if let _ = accessoryView, let caretView = caretView, let widthObject = caretViewWidthSizeObject, let heightObject = caretViewHeightSizeObject {
|
||||||
|
caretView.frame = CGRect(x: 0, y: 0, width: widthObject.getValueBased(onSize: size), height: heightObject.getValueBased(onSize: size))
|
||||||
|
}
|
||||||
|
topSeparatorView?.updateView(size)
|
||||||
|
bottomSeparatorView?.updateView(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func setupView() {
|
||||||
|
preservesSuperviewLayoutMargins = false
|
||||||
|
contentView.preservesSuperviewLayoutMargins = false
|
||||||
|
selectionStyle = .none
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - MVMCoreUIMoleculeViewProtocol
|
||||||
|
public func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?) {
|
||||||
|
guard let json = json else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if molecule == nil {
|
||||||
|
if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForStack(withJSON: json, delegateObject: delegateObject) {
|
||||||
|
contentView.addSubview(moleculeView)
|
||||||
|
NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: moleculeView, useMargins: moleculeView.needsToBeConstrained?() ?? false).values))
|
||||||
|
molecule = moleculeView
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
molecule?.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
||||||
|
}
|
||||||
|
backgroundColor = molecule?.backgroundColor
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Convenience
|
||||||
|
/// Adds the standard mvm style caret to the accessory view
|
||||||
|
public func addCaretViewAccessory() {
|
||||||
|
guard accessoryView == nil else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let width: CGFloat = 6
|
||||||
|
let height: CGFloat = 10
|
||||||
|
caretView = CaretView(lineThickness: CaretView.thin)
|
||||||
|
caretView?.frame = CGRect(x: 0, y: 0, width: width, height: height)
|
||||||
|
caretViewWidthSizeObject = MFSizeObject(scalingStandardSize: width)
|
||||||
|
caretViewHeightSizeObject = MFSizeObject(scalingStandardSize: height)
|
||||||
|
accessoryView = caretView
|
||||||
|
}
|
||||||
|
|
||||||
|
func addSeparatorsIfNeeded() {
|
||||||
|
if topSeparatorView == nil {
|
||||||
|
topSeparatorView = SeparatorView.separatorAdd(to: self, position: SeparatorPositionTop)
|
||||||
|
topSeparatorView?.hide()
|
||||||
|
}
|
||||||
|
if bottomSeparatorView == nil {
|
||||||
|
bottomSeparatorView = SeparatorView.separatorAdd(to: self, position: SeparatorPositionBot)
|
||||||
|
bottomSeparatorView?.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// For when the separator between cells shows using json and frequency.
|
||||||
|
public func setSeparatorWithJSON(_ json: [AnyHashable : Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?, indexPath: IndexPath) {
|
||||||
|
guard let json = json else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
addSeparatorsIfNeeded()
|
||||||
|
topSeparatorView?.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
||||||
|
bottomSeparatorView?.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
||||||
|
if let separatorFrequencyString = json.optionalStringForKey("frequency"), let separatorFrequency = SeparatorFrequency(rawValue: separatorFrequencyString) {
|
||||||
|
setSeparatorFrequency(separatorFrequency, indexPath: indexPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// For when the separator between cells shows.
|
||||||
|
public func setSeparatorFrequency(_ separatorFrequency: SeparatorFrequency, indexPath: IndexPath) {
|
||||||
|
switch separatorFrequency {
|
||||||
|
case .All:
|
||||||
|
if indexPath.row == 0 {
|
||||||
|
topSeparatorView?.show()
|
||||||
|
} else {
|
||||||
|
topSeparatorView?.hide()
|
||||||
|
}
|
||||||
|
bottomSeparatorView?.show()
|
||||||
|
case .AllExceptBottom:
|
||||||
|
topSeparatorView?.show()
|
||||||
|
bottomSeparatorView?.hide()
|
||||||
|
case .Between:
|
||||||
|
if indexPath.row == 0 {
|
||||||
|
topSeparatorView?.hide()
|
||||||
|
} else {
|
||||||
|
topSeparatorView?.show()
|
||||||
|
}
|
||||||
|
bottomSeparatorView?.hide()
|
||||||
|
case .AllExceptTop:
|
||||||
|
fallthrough
|
||||||
|
default:
|
||||||
|
topSeparatorView?.hide()
|
||||||
|
bottomSeparatorView?.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -46,16 +46,16 @@ public class StandardFooterView: ViewConstrainingView {
|
|||||||
spaceBetweenButtons = textButton.topAnchor.constraint(equalTo: twoButtonView.bottomAnchor, constant: PaddingTwo)
|
spaceBetweenButtons = textButton.topAnchor.constraint(equalTo: twoButtonView.bottomAnchor, constant: PaddingTwo)
|
||||||
spaceBetweenButtons?.isActive = true
|
spaceBetweenButtons?.isActive = true
|
||||||
|
|
||||||
leftConstraintTwoButton = twoButtonView.leftAnchor.constraint(equalTo: leftAnchor)
|
leftConstraintTwoButton = twoButtonView.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor)
|
||||||
leftConstraintTwoButton?.isActive = true
|
leftConstraintTwoButton?.isActive = true
|
||||||
|
|
||||||
rightConstraintTwoButton = rightAnchor.constraint(equalTo: twoButtonView.rightAnchor)
|
rightConstraintTwoButton = layoutMarginsGuide.rightAnchor.constraint(equalTo: twoButtonView.rightAnchor)
|
||||||
rightConstraintTwoButton?.isActive = true
|
rightConstraintTwoButton?.isActive = true
|
||||||
|
|
||||||
leftConstraintTextButton = textButton.leftAnchor.constraint(greaterThanOrEqualTo: leftAnchor)
|
leftConstraintTextButton = textButton.leftAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.leftAnchor)
|
||||||
leftConstraintTextButton?.isActive = true
|
leftConstraintTextButton?.isActive = true
|
||||||
|
|
||||||
rightConstraintTextButton = rightAnchor.constraint(greaterThanOrEqualTo: textButton.rightAnchor)
|
rightConstraintTextButton = layoutMarginsGuide.rightAnchor.constraint(greaterThanOrEqualTo: textButton.rightAnchor)
|
||||||
rightConstraintTextButton?.isActive = true
|
rightConstraintTextButton?.isActive = true
|
||||||
|
|
||||||
centerAlignTextButton = textButton.centerXAnchor.constraint(equalTo: centerXAnchor)
|
centerAlignTextButton = textButton.centerXAnchor.constraint(equalTo: centerXAnchor)
|
||||||
@ -93,16 +93,6 @@ public class StandardFooterView: ViewConstrainingView {
|
|||||||
layoutIfNeeded()
|
layoutIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
||||||
public override func setLeftPinConstant(_ constant: CGFloat) {
|
|
||||||
leftConstraintTwoButton?.constant = constant
|
|
||||||
leftConstraintTextButton?.constant = constant
|
|
||||||
}
|
|
||||||
|
|
||||||
public override func setRightPinConstant(_ constant: CGFloat) {
|
|
||||||
rightConstraintTwoButton?.constant = constant
|
|
||||||
rightConstraintTextButton?.constant = constant
|
|
||||||
}
|
|
||||||
|
|
||||||
open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) {
|
open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||||
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
||||||
if let colorString = json?.optionalStringForKey(KeyBackgroundColor) {
|
if let colorString = json?.optionalStringForKey(KeyBackgroundColor) {
|
||||||
|
|||||||
@ -22,4 +22,7 @@
|
|||||||
- (nullable UIView <MVMCoreUIMoleculeViewProtocol>*)getMoleculeForName:(nonnull NSString *)name;
|
- (nullable UIView <MVMCoreUIMoleculeViewProtocol>*)getMoleculeForName:(nonnull NSString *)name;
|
||||||
- (nullable UIView <MVMCoreUIMoleculeViewProtocol>*)getMoleculeForJSON:(nonnull NSDictionary *)json delegateObject:(nullable DelegateObject *)delegateObject;
|
- (nullable UIView <MVMCoreUIMoleculeViewProtocol>*)getMoleculeForJSON:(nonnull NSDictionary *)json delegateObject:(nullable DelegateObject *)delegateObject;
|
||||||
|
|
||||||
|
// Similar to above but also checks if the molecule needs to be constrained for a stack.
|
||||||
|
- (nullable UIView <MVMCoreUIMoleculeViewProtocol>*)getMoleculeForStackWithJSON:(nonnull NSDictionary *)json delegateObject:(nullable DelegateObject *)delegateObject;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@ -34,7 +34,8 @@
|
|||||||
@"caretButton": CaretButton.class,
|
@"caretButton": CaretButton.class,
|
||||||
@"textField" : MFTextField.class,
|
@"textField" : MFTextField.class,
|
||||||
@"radioButtonList": RadioButtonList.class,
|
@"radioButtonList": RadioButtonList.class,
|
||||||
@"radioButton": RadioButton.class
|
@"radioButton": RadioButton.class,
|
||||||
|
@"checkbox" : MVMCoreUICheckBox.class
|
||||||
} mutableCopy];
|
} mutableCopy];
|
||||||
});
|
});
|
||||||
return mapping;
|
return mapping;
|
||||||
@ -47,18 +48,18 @@
|
|||||||
|
|
||||||
- (nullable UIView <MVMCoreUIMoleculeViewProtocol>*)getMoleculeForName:(nonnull NSString *)name {
|
- (nullable UIView <MVMCoreUIMoleculeViewProtocol>*)getMoleculeForName:(nonnull NSString *)name {
|
||||||
Class class = [self.moleculeMapping objectForKey:name];
|
Class class = [self.moleculeMapping objectForKey:name];
|
||||||
if (class) {
|
if (!class) {
|
||||||
UIView <MVMCoreUIMoleculeViewProtocol>*view = [[class alloc] init];
|
return nil;
|
||||||
if ([view respondsToSelector:@selector(setAsMolecule)]) {
|
|
||||||
[view setAsMolecule];
|
|
||||||
}
|
|
||||||
return view;
|
|
||||||
}
|
}
|
||||||
return nil;
|
UIView <MVMCoreUIMoleculeViewProtocol>*molecule = [[class alloc] init];
|
||||||
|
if ([molecule respondsToSelector:@selector(setAsMolecule)]) {
|
||||||
|
[molecule setAsMolecule];
|
||||||
|
}
|
||||||
|
return molecule;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (nullable UIView <MVMCoreUIMoleculeViewProtocol>*)getMoleculeForJSON:(nonnull NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject {
|
- (nullable UIView <MVMCoreUIMoleculeViewProtocol>*)getMoleculeForJSON:(nonnull NSDictionary *)json delegateObject:(nullable DelegateObject *)delegateObject {
|
||||||
NSString *moleculeName = [json string:@"moleculeName"];
|
NSString *moleculeName = [json string:KeyMoleculeName];
|
||||||
if (!moleculeName) {
|
if (!moleculeName) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
@ -68,4 +69,17 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (nullable UIView <MVMCoreUIMoleculeViewProtocol>*)getMoleculeForStackWithJSON:(nonnull NSDictionary *)json delegateObject:(nullable DelegateObject *)delegateObject {
|
||||||
|
NSString *moleculeName = [json string:KeyMoleculeName];
|
||||||
|
if (!moleculeName) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
UIView <MVMCoreUIMoleculeViewProtocol>*molecule = [self getMoleculeForName:moleculeName];
|
||||||
|
if ([molecule respondsToSelector:@selector(needsToBeConstrained)] && [molecule needsToBeConstrained]) {
|
||||||
|
molecule = [[ViewConstrainingView alloc] initWithMolecule:molecule alignment:[molecule respondsToSelector:@selector(moleculeAlignment)] ? [molecule moleculeAlignment] : UIStackViewAlignmentFill];
|
||||||
|
}
|
||||||
|
[molecule setWithJSON:json delegateObject:delegateObject additionalData:nil];
|
||||||
|
return molecule;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@ -21,7 +21,8 @@
|
|||||||
viewControllerMapping = [@{
|
viewControllerMapping = [@{
|
||||||
@"textFieldListForm" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[TextFieldListFormViewController class]],
|
@"textFieldListForm" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[TextFieldListFormViewController class]],
|
||||||
@"moleculeStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackTemplate class]],
|
@"moleculeStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackTemplate class]],
|
||||||
@"centerMoleculeStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackCenteredTemplate class]]
|
@"centerMoleculeStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackCenteredTemplate class]],
|
||||||
|
@"moleculeList" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeListTemplate class]]
|
||||||
} mutableCopy];
|
} mutableCopy];
|
||||||
});
|
});
|
||||||
return viewControllerMapping;
|
return viewControllerMapping;
|
||||||
|
|||||||
68
MVMCoreUI/Templates/MoleculeListTemplate.swift
Normal file
68
MVMCoreUI/Templates/MoleculeListTemplate.swift
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
//
|
||||||
|
// MoleculeListTemplate.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Scott Pfeil on 4/18/19.
|
||||||
|
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
open class MoleculeListTemplate: ThreeLayerTableViewController {
|
||||||
|
|
||||||
|
open override func registerWithTable() {
|
||||||
|
super.registerWithTable()
|
||||||
|
guard let molecules = loadObject?.pageJSON?.arrayForKey(KeyMolecules) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for case let molecule as Dictionary<AnyHashable, Any> in molecules {
|
||||||
|
if let moleculeName = molecule.optionalStringForKey(KeyMoleculeName) {
|
||||||
|
tableView?.register(MoleculeTableViewCell.self, forCellReuseIdentifier: moleculeName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func viewForTop() -> UIView {
|
||||||
|
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForStack(withJSON: moleculeJSON, delegateObject: delegateObject()) else {
|
||||||
|
return super.viewForTop()
|
||||||
|
}
|
||||||
|
return molecule
|
||||||
|
}
|
||||||
|
|
||||||
|
override open func viewForBottom() -> UIView {
|
||||||
|
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForStack(withJSON: moleculeJSON, delegateObject: delegateObject()) else {
|
||||||
|
return viewForBottom()
|
||||||
|
}
|
||||||
|
return molecule
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func newDataBuildScreen() {
|
||||||
|
super.newDataBuildScreen()
|
||||||
|
registerWithTable()
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
|
||||||
|
if let moleculeName = loadObject?.pageJSON?.stringOptionalWithChainOfKeysOrIndexes([KeyMolecules,indexPath.row,KeyMoleculeName]), let theClass = MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping?[moleculeName] as? MVMCoreUIMoleculeViewProtocol.Type,
|
||||||
|
let estimatedHeightForRow = theClass.estimatedHeightForRow {
|
||||||
|
return estimatedHeightForRow()
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||||
|
return loadObject?.pageJSON?.arrayForKey(KeyMolecules).count ?? 0
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||||
|
guard let molecule = loadObject?.pageJSON?.optionalDictionaryWithChainOfKeysOrIndexes([KeyMolecules,indexPath.row]),
|
||||||
|
let moleculeName = molecule.optionalStringForKey(KeyMoleculeName),
|
||||||
|
let cell = tableView.dequeueReusableCell(withIdentifier: moleculeName) as? MoleculeTableViewCell else {
|
||||||
|
return UITableViewCell()
|
||||||
|
}
|
||||||
|
let delegate = delegateObject()
|
||||||
|
cell.setWithJSON(molecule, delegateObject: delegate, additionalData: nil)
|
||||||
|
cell.setSeparatorWithJSON(loadObject?.pageJSON?.optionalDictionaryForKey("separator"), delegateObject: delegate, additionalData: nil, indexPath: indexPath)
|
||||||
|
cell.updateView(tableView.bounds.width)
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -18,7 +18,7 @@ public class MoleculeStackCenteredTemplate: ThreeLayerViewController {
|
|||||||
|
|
||||||
public override func viewForTop() -> UIView? {
|
public override func viewForTop() -> UIView? {
|
||||||
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"),
|
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"),
|
||||||
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON, delegateObject: delegateObject()) else {
|
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForStack(withJSON: moleculeJSON, delegateObject: delegateObject()) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return molecule
|
return molecule
|
||||||
@ -26,7 +26,7 @@ public class MoleculeStackCenteredTemplate: ThreeLayerViewController {
|
|||||||
|
|
||||||
override public func viewForBottom() -> UIView? {
|
override public func viewForBottom() -> UIView? {
|
||||||
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"),
|
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"),
|
||||||
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON, delegateObject: delegateObject()) else {
|
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForStack(withJSON: moleculeJSON, delegateObject: delegateObject()) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return molecule
|
return molecule
|
||||||
|
|||||||
@ -12,11 +12,11 @@ public class MoleculeStackTemplate: ThreeLayerViewController {
|
|||||||
|
|
||||||
|
|
||||||
public override func spaceBetweenTopAndMiddle() -> CGFloat? {
|
public override func spaceBetweenTopAndMiddle() -> CGFloat? {
|
||||||
return PaddingTwo
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
public override func viewForTop() -> UIView? {
|
public override func viewForTop() -> UIView? {
|
||||||
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON, delegateObject: delegateObject()) else {
|
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForStack(withJSON: moleculeJSON, delegateObject: delegateObject()) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return molecule
|
return molecule
|
||||||
@ -30,7 +30,7 @@ public class MoleculeStackTemplate: ThreeLayerViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override public func viewForBottom() -> UIView? {
|
override public func viewForBottom() -> UIView? {
|
||||||
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForJSON(moleculeJSON, delegateObject: delegateObject()) else {
|
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeForStack(withJSON: moleculeJSON, delegateObject: delegateObject()) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return molecule
|
return molecule
|
||||||
|
|||||||
@ -13,6 +13,9 @@
|
|||||||
|
|
||||||
extern NSString * const KeyScreenHeading;
|
extern NSString * const KeyScreenHeading;
|
||||||
|
|
||||||
|
extern NSString * const KeyMolecules;
|
||||||
|
extern NSString * const KeyMoleculeName;
|
||||||
|
|
||||||
extern NSString * const KeyDisableButton;
|
extern NSString * const KeyDisableButton;
|
||||||
|
|
||||||
extern NSString * const KeyValue;
|
extern NSString * const KeyValue;
|
||||||
@ -35,6 +38,9 @@ extern NSString * const KeyTextColor;
|
|||||||
extern NSString * const KeyIsHidden;
|
extern NSString * const KeyIsHidden;
|
||||||
extern NSString * const KeyIsOpaque;
|
extern NSString * const KeyIsOpaque;
|
||||||
|
|
||||||
|
extern NSString * const KeyFieldKey;
|
||||||
|
extern NSString * const KeyRequired;
|
||||||
|
|
||||||
#pragma mark - Values
|
#pragma mark - Values
|
||||||
|
|
||||||
extern NSString * const StringY;
|
extern NSString * const StringY;
|
||||||
|
|||||||
@ -12,12 +12,17 @@
|
|||||||
|
|
||||||
NSString * const KeyScreenHeading = @"screenHeading";
|
NSString * const KeyScreenHeading = @"screenHeading";
|
||||||
|
|
||||||
|
NSString * const KeyMolecules = @"molecules";
|
||||||
|
NSString * const KeyMoleculeName = @"moleculeName";
|
||||||
|
|
||||||
NSString * const KeyDisableButton = @"disableAction";
|
NSString * const KeyDisableButton = @"disableAction";
|
||||||
|
|
||||||
NSString * const KeyValue = @"value";
|
NSString * const KeyValue = @"value";
|
||||||
NSString * const KeyLabel = @"label";
|
NSString * const KeyLabel = @"label";
|
||||||
NSString * const KeyDisable = @"disable";
|
NSString * const KeyDisable = @"disable";
|
||||||
NSString * const KeyFieldName = @"fieldName";
|
NSString * const KeyFieldName = @"fieldName";
|
||||||
|
NSString * const KeyFieldKey = @"fieldKey";
|
||||||
|
NSString * const KeyRequired = @"required";
|
||||||
|
|
||||||
NSString * const KeyHideMainMenu = @"hideMainMenu";
|
NSString * const KeyHideMainMenu = @"hideMainMenu";
|
||||||
NSString * const KeyProgressPercent = @"progressPercent";
|
NSString * const KeyProgressPercent = @"progressPercent";
|
||||||
@ -34,6 +39,7 @@ NSString * const KeyTextColor = @"textColor";
|
|||||||
NSString * const KeyIsHidden = @"isHidden";
|
NSString * const KeyIsHidden = @"isHidden";
|
||||||
NSString * const KeyIsOpaque = @"isOpaque";
|
NSString * const KeyIsOpaque = @"isOpaque";
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - Values
|
#pragma mark - Values
|
||||||
|
|
||||||
NSString * const StringY = @"Y";
|
NSString * const StringY = @"Y";
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user