Merge branch 'develop' into feature/label_export_box

This commit is contained in:
Kevin G Christiano 2019-07-25 16:48:03 -04:00
commit 849a4d761a
13 changed files with 192 additions and 20 deletions

View File

@ -169,6 +169,8 @@
D2A6390522CBCE160052ED1F /* MoleculeCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */; };
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 */; };
D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */; };
D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.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 */; };
@ -347,6 +349,8 @@
D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeCollectionViewCell.swift; sourceTree = "<group>"; };
D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIViewControllerMappingObject.h; sourceTree = "<group>"; };
D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIViewControllerMappingObject.m; sourceTree = "<group>"; };
D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scroller.swift; sourceTree = "<group>"; };
D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTemplate.swift; sourceTree = "<group>"; };
D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIDelegateObject.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>"; };
@ -443,6 +447,7 @@
D2A514622213643100345BFB /* MoleculeStackCenteredTemplate.swift */,
D296E13B2295969C0051EBE7 /* MoleculeListCellProtocol.h */,
D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */,
D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */,
);
path = Templates;
sourceTree = "<group>";
@ -490,6 +495,7 @@
D260D7AF22D65BDD007E7233 /* MVMCoreUIPageControl.h */,
D260D7B022D65BDD007E7233 /* MVMCoreUIPageControl.m */,
D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */,
D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */,
);
path = Molecules;
sourceTree = "<group>";
@ -949,12 +955,14 @@
D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */,
D2A514672213885800345BFB /* StandardHeaderView.swift in Sources */,
DBEFFA04225A829700230692 /* Label.swift in Sources */,
D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */,
D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */,
D28B4F8B21FF967C00712C7A /* MVMCoreUIObject.m in Sources */,
D260D7B222D65BDD007E7233 /* MVMCoreUIPageControl.m in Sources */,
D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */,
D29DF2EF21ECEAE1003B2FB9 /* MFFonts.m in Sources */,
D282AACB2243C61700C46919 /* ButtonView.swift in Sources */,
D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */,
0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */,
D2E1FADD2268B25E00AEFD8C /* MoleculeTableViewCell.swift in Sources */,
D29DF2AE21E7B3A4003B2FB9 /* MFTextView.m in Sources */,

View File

@ -218,7 +218,7 @@ public typealias ActionBlock = () -> Void
case "strikethrough":
attributedString.addAttribute(.strikethroughStyle, value: NSUnderlineStyle.thick.rawValue, range: range)
attributedString.addAttribute(.baselineOffset, value: 0, range: range)
case "color":
if let colorHex = attribute.optionalStringForKey(KeyTextColor), !colorHex.isEmpty {
attributedString.removeAttribute(.foregroundColor, range: range)

View File

@ -22,6 +22,8 @@ import UIKit
var imageWidth: CGFloat?
var imageHeight: CGFloat?
var delegateObject: MVMCoreUIDelegateObject?
// For keeping track of current state.
private var edges: UIRectEdge?
private var spinnerHeight: CGFloat?
@ -153,6 +155,39 @@ import UIKit
return false
}
// MARK: - Constraints
func setHeight(_ height: CGFloat) {
if let heightConstraint = heightConstraint, MVMCoreGetterUtility.cgfequal(heightConstraint.multiplier, 1) {
heightConstraint.constant = height
} else {
heightConstraint?.isActive = false
heightConstraint = imageView.heightAnchor.constraint(equalToConstant: height)
heightConstraint?.priority = UILayoutPriority(rawValue: 900)
}
heightConstraint?.isActive = true
}
func setWidth(_ width: CGFloat) {
if let widthConstraint = widthConstraint, MVMCoreGetterUtility.cgfequal(widthConstraint.multiplier, 1) {
widthConstraint.constant = width
} else {
widthConstraint = imageView.widthAnchor.constraint(equalToConstant: width)
widthConstraint?.priority = UILayoutPriority(rawValue: 900)
}
widthConstraint?.isActive = true
}
func layoutWillChange(width: CGFloat?, height: CGFloat?, size: CGSize?) -> Bool {
guard addSizeConstraintsForAspectRatio else {
return false
}
let widthWillChange = !MVMCoreGetterUtility.cgfequal(widthConstraint?.constant ?? 0, width ?? 0)
let heightWillChange = !MVMCoreGetterUtility.cgfequal(heightConstraint?.constant ?? 0, height ?? 0)
let sizeWillChange = (width == nil || height == nil) && !(size?.equalTo(imageView.image?.size ?? CGSize.zero) ?? false)
return widthWillChange || heightWillChange || sizeWillChange
}
// Constrains the image view to be the size provided. Used to size it to the image to fix aspect fit defect.
func addConstraints(width: NSNumber?, height: NSNumber?, size: CGSize?) {
widthConstraint?.isActive = false
@ -162,21 +197,19 @@ import UIKit
}
if let width = width, let height = height {
heightConstraint = imageView.heightAnchor.constraint(equalToConstant: height.cgfloat())
widthConstraint = imageView.widthAnchor.constraint(equalToConstant: width.cgfloat())
setHeight(height.cgfloat())
setWidth(width.cgfloat())
} else if let width = width, let size = size {
widthConstraint = imageView.widthAnchor.constraint(equalToConstant: width.cgfloat())
setWidth(width.cgfloat())
heightConstraint = imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor, multiplier: size.height/size.width)
heightConstraint?.priority = UILayoutPriority(rawValue: 900)
heightConstraint?.isActive = true
} else if let height = height, let size = size {
heightConstraint = imageView.heightAnchor.constraint(equalToConstant: height.cgfloat())
setHeight(height.cgfloat())
widthConstraint = imageView.widthAnchor.constraint(equalTo: imageView.heightAnchor, multiplier: size.width/size.height)
widthConstraint?.priority = UILayoutPriority(rawValue: 900)
widthConstraint?.isActive = true
}
widthConstraint?.priority = UILayoutPriority(rawValue: 900)
heightConstraint?.priority = UILayoutPriority(rawValue: 900)
heightConstraint?.isActive = true
widthConstraint?.isActive = true
imageView.setContentHuggingPriority(UILayoutPriority.defaultLow, for: NSLayoutConstraint.Axis.horizontal)
imageView.setContentHuggingPriority(UILayoutPriority.defaultLow, for: NSLayoutConstraint.Axis.vertical)
}
// MARK: - MVMCoreUIMoleculeViewProtocol functions
@ -190,6 +223,7 @@ import UIKit
open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
self.delegateObject = delegateObject
if let accessibilityString = json?.optionalStringForKey("accessibilityText") {
imageView.accessibilityLabel = accessibilityString
imageView.accessibilityTraits = .staticText
@ -197,6 +231,13 @@ import UIKit
}
let width = json?.optionalCGFloatForKey("width") ?? imageWidth
let height = json?.optionalCGFloatForKey("height") ?? imageHeight
// For smoother transitions, set constraints that we know immediately.
if let width = width, addSizeConstraintsForAspectRatio {
setWidth(width)
}
if let height = height, addSizeConstraintsForAspectRatio {
setHeight(height)
}
if let imageName = json?.optionalStringForKey("image"), shouldLoadImage(withName: imageName, width: width, height: height) {
imageView.image = nil
imageView.animatedImage = nil
@ -222,7 +263,11 @@ import UIKit
self?.isFallbackImage = isFallbackImage
self?.loadingSpinnerHeightConstraint?.constant = 0
self?.loadingSpinner.pause()
let layoutWillChange = self?.layoutWillChange(width: self?.currentImageWidth, height: self?.currentImageHeight, size: image?.size) ?? false
self?.addConstraints(width: width, height: height, size: image?.size)
if layoutWillChange {
self?.delegateObject?.moleculeDelegate?.moleculeLayoutUpdated?(self!)
}
completionHandler(image,data,isFallbackImage)
})}

View File

@ -307,6 +307,9 @@
if ([self.constrainedView respondsToSelector:@selector(updateView:)]) {
[((id<MVMCoreViewProtocol>)self.constrainedView) updateView:size];
}
if (self.molecule != self.constrainedView) {
[self.molecule updateView:size];
}
[MFStyler setDefaultMarginsForView:self size:size horizontal:self.updateViewHorizontalDefaults vertical:self.updateViewVerticalDefaults];
UIEdgeInsets margins = [MVMCoreUIUtility getMarginsForView:self];
if (self.updateViewHorizontalDefaults) {

View File

@ -22,7 +22,7 @@ open class ThreeLayerViewController: ProgrammaticScrollViewController {
var bottomViewOutsideOfScroll = false
private var safeAreaView: UIView?
private var heightConstraint: NSLayoutConstraint?
var heightConstraint: NSLayoutConstraint?
open override func updateViews() {
super.updateViews()

View File

@ -62,7 +62,7 @@ open class Carousel: ViewConstrainingView {
pinView(toSuperView: collectionView)
collectionViewHeight = collectionView.heightAnchor.constraint(equalToConstant: 300)
collectionViewHeight?.isActive = true
collectionViewHeight?.isActive = false
}
open override func updateView(_ size: CGFloat) {
@ -81,12 +81,19 @@ open class Carousel: ViewConstrainingView {
// MARK: - MVMCoreUIMoleculeViewProtocol
open override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
collectionView.backgroundColor = backgroundColor
collectionView.layer.borderColor = backgroundColor?.cgColor
collectionView.layer.borderWidth = (json?.boolForKey("border") ?? false) ? 1 : 0
backgroundColor = .white
registerCells(with: json, delegateObject: delegateObject)
setupLayout(with: json)
prepareMolecules(with: json)
itemWidthPercent = (json?.optionalCGFloatForKey("itemWidthPercent") ?? 100) / 100
setAlignment(with: json?.optionalStringForKey("itemAlignment"))
collectionViewHeight?.constant = json?.optionalCGFloatForKey("height") ?? 300
if let height = json?.optionalCGFloatForKey("height") {
collectionViewHeight?.constant = height
collectionViewHeight?.isActive = true
}
setupPagingMolecule(json: json?.optionalDictionaryForKey("pagingMolecule"), delegateObject: delegateObject)
collectionView.reloadData()
}

View File

@ -0,0 +1,44 @@
//
// Scroller.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 7/23/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import UIKit
@objcMembers open class Scroller: ViewConstrainingView {
public let scrollView = UIScrollView(frame: .zero)
public let contentView = MVMCoreUICommonViewsUtility.commonView()
override open func setupView() {
super.setupView()
guard scrollView.superview == nil else {
return
}
translatesAutoresizingMaskIntoConstraints = false
scrollView.translatesAutoresizingMaskIntoConstraints = false
addConstrainedView(scrollView)
scrollView.addSubview(contentView)
NSLayoutConstraint.constraintPinSubview(toSuperview: contentView)
let constraint = contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor, multiplier: 1.0)
constraint.priority = UILayoutPriority(rawValue: 999)
constraint.isActive = true
}
open override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
guard let json = json, let moleculeJSON = json.optionalDictionaryForKey(KeyMolecule) else {
return
}
if molecule == nil {
if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject, constrainIfNeeded: true) {
contentView.addSubview(moleculeView)
pinView(toSuperView: moleculeView)
molecule = moleculeView
}
} else {
molecule?.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: additionalData)
}
}
}

View File

@ -15,11 +15,6 @@ public class StandardHeaderView: ViewConstrainingView {
open override func updateView(_ size: CGFloat) {
super.updateView(size)
separatorView?.updateView(size)
if separatorView?.isHidden ?? true {
let margins = MVMCoreUIUtility.getMarginsFor(self)
MVMCoreUIUtility.setMarginsFor(self, leading: margins.left, top: margins.top, trailing: margins.right, bottom: 0)
bottomPin?.constant = 0
}
}
public override func setupView() {

View File

@ -53,6 +53,7 @@
@"carousel": Carousel.class,
@"carouselItem": MoleculeCollectionViewCell.class,
@"barsPager": MVMCoreUIPageControl.class,
@"scroller": Scroller.class
} mutableCopy];
});
return mapping;

View File

@ -22,7 +22,9 @@
@"textFieldListForm" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[TextFieldListFormViewController class]],
@"moleculeStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackTemplate class]],
@"centerMoleculeStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackCenteredTemplate class]],
@"moleculeList" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeListTemplate class]]
@"moleculeList" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeListTemplate class]],
@"threeLayer" :
[[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[ThreeLayerTemplate class]]
} mutableCopy];
});
return viewControllerMapping;

View File

@ -12,4 +12,8 @@
/// returns a module for the corresponding module name.
- (nullable NSDictionary *)getModuleWithName:(nullable NSString *)name;
@optional
/// Notifies the delegate that the molecule layout update. Should be called when the layout may change due to an async method.
- (void)moleculeLayoutUpdated:(nonnull UIView <MVMCoreUIMoleculeViewProtocol>*)molecule;
@end

View File

@ -106,6 +106,17 @@ open class MoleculeListTemplate: ThreeLayerTableViewController {
return loadObject?.requestParameters?.modules
}
// MARK: - MoleculeDelegateProtocol
open override func moleculeLayoutUpdated(_ molecule: UIView & MVMCoreUIMoleculeViewProtocol) {
if let tableView = tableView {
let point = molecule.convert(molecule.bounds.origin, to: tableView)
if let indexPath = tableView.indexPathForRow(at: point), tableView.indexPathsForVisibleRows?.contains(indexPath) ?? false {
tableView.beginUpdates()
tableView.endUpdates()
}
}
}
// MARK: - Convenience
/// Returns the (identifier, class) of the molecule for the given map.
func getMoleculeInfo(with molecule: [AnyHashable: Any]?) -> (identifier: String, class: AnyClass, molecule: [AnyHashable: Any])? {

View File

@ -0,0 +1,52 @@
//
// ThreeLayerTemplate.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 7/23/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import UIKit
@objcMembers open class ThreeLayerTemplate: ThreeLayerViewController {
override open func viewDidLoad() {
super.viewDidLoad()
bottomViewOutsideOfScroll = true
// Do any additional setup after loading the view.
}
open override func newDataBuildScreen() {
super.newDataBuildScreen()
heightConstraint?.isActive = true
}
open override func viewForTop() -> UIView? {
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else {
return nil
}
return molecule
}
open override func viewForMiddle() -> UIView? {
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("middle"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else {
return nil
}
return molecule
}
override open func viewForBottom() -> UIView? {
guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else {
return nil
}
return molecule
}
open override func spaceBetweenMiddleAndBottom() -> CGFloat? {
return 0
}
open override func spaceBetweenTopAndMiddle() -> CGFloat? {
return 0
}
}