forked from organicmaps/organicmaps
[ios] Added validation for editior's fields.
This commit is contained in:
parent
225b60b872
commit
9fb9f1dbd7
5 changed files with 132 additions and 12 deletions
|
@ -1,9 +1,12 @@
|
|||
@class MWMEditorTextTableViewCell;
|
||||
|
||||
@protocol MWMEditorCellProtocol <NSObject>
|
||||
|
||||
@required
|
||||
- (void)cell:(UITableViewCell *)cell changedText:(NSString *)changeText;
|
||||
- (void)cell:(MWMEditorTextTableViewCell *)cell changedText:(NSString *)changeText;
|
||||
- (void)cell:(UITableViewCell *)cell changeSwitch:(BOOL)changeSwitch;
|
||||
- (void)cellSelect:(UITableViewCell *)cell;
|
||||
- (void)tryToChangeInvalidStateForCell:(MWMEditorTextTableViewCell *)cell;
|
||||
|
||||
@optional
|
||||
- (void)fieldIsCorrect:(BOOL)isCorrect;
|
||||
|
|
|
@ -10,4 +10,14 @@
|
|||
placeholder:(NSString *)placeholder
|
||||
keyboardType:(UIKeyboardType)keyboardType;
|
||||
|
||||
- (void)configWithDelegate:(id<MWMEditorCellProtocol>)delegate
|
||||
icon:(UIImage *)icon
|
||||
text:(NSString *)text
|
||||
placeholder:(NSString *)placeholder
|
||||
errorMessage:(NSString *)errorMessage
|
||||
isValid:(BOOL)isValid
|
||||
keyboardType:(UIKeyboardType)keyboardType;
|
||||
|
||||
@property (weak, nonatomic, readonly) IBOutlet UITextField * textField;
|
||||
|
||||
@end
|
||||
|
|
|
@ -7,10 +7,16 @@
|
|||
@interface MWMEditorTextTableViewCell () <UITextFieldDelegate>
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UIImageView * icon;
|
||||
@property (weak, nonatomic) IBOutlet UITextField * textField;
|
||||
@property (weak, nonatomic, readwrite) IBOutlet UITextField * textField;
|
||||
@property (weak, nonatomic) IBOutlet UILabel * errorLabel;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint * errorLabelTopSpace;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint * labelHeight;
|
||||
|
||||
@property (weak, nonatomic) id<MWMEditorCellProtocol> delegate;
|
||||
|
||||
@property (nonatomic) BOOL isValid;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MWMEditorTextTableViewCell
|
||||
|
@ -20,19 +26,64 @@
|
|||
text:(NSString *)text
|
||||
placeholder:(NSString *)placeholder
|
||||
keyboardType:(UIKeyboardType)keyboardType
|
||||
{
|
||||
[self configWithDelegate:delegate icon:icon text:text placeholder:placeholder
|
||||
errorMessage:nil isValid:YES keyboardType:keyboardType];
|
||||
}
|
||||
|
||||
- (void)configWithDelegate:(id<MWMEditorCellProtocol>)delegate
|
||||
icon:(UIImage *)icon
|
||||
text:(NSString *)text
|
||||
placeholder:(NSString *)placeholder
|
||||
errorMessage:(NSString *)errorMessage
|
||||
isValid:(BOOL)isValid
|
||||
keyboardType:(UIKeyboardType)keyboardType
|
||||
{
|
||||
self.delegate = delegate;
|
||||
self.icon.image = icon;
|
||||
self.icon.mwm_coloring = MWMImageColoringBlack;
|
||||
self.icon.hidden = (icon == nil);
|
||||
|
||||
self.textField.text = text;
|
||||
self.textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:placeholder attributes:
|
||||
@{NSForegroundColorAttributeName : [UIColor blackHintText]}];
|
||||
self.errorLabel.text = errorMessage;
|
||||
self.textField.keyboardType = keyboardType;
|
||||
self.textField.backgroundColor = [UIColor clearColor];
|
||||
self.isValid = isValid;
|
||||
[self processValidation];
|
||||
}
|
||||
|
||||
- (void)processValidation
|
||||
{
|
||||
if (self.isValid)
|
||||
{
|
||||
self.labelHeight.priority = UILayoutPriorityDefaultHigh;
|
||||
self.errorLabelTopSpace.constant = 0;
|
||||
self.contentView.backgroundColor = [UIColor white];
|
||||
}
|
||||
else
|
||||
{
|
||||
self.labelHeight.priority = UILayoutPriorityDefaultLow;
|
||||
self.errorLabelTopSpace.constant = 4;
|
||||
self.contentView.backgroundColor = [UIColor errorPink];
|
||||
}
|
||||
[self layoutIfNeeded];
|
||||
}
|
||||
|
||||
#pragma mark - UITextFieldDelegate
|
||||
|
||||
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
|
||||
{
|
||||
if (!self.isValid)
|
||||
{
|
||||
self.isValid = YES;
|
||||
[self processValidation];
|
||||
[self.delegate tryToChangeInvalidStateForCell:self];
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)textFieldDidEndEditing:(UITextField *)textField
|
||||
{
|
||||
[self.delegate cell:self changedText:textField.text];
|
||||
|
|
|
@ -3,15 +3,16 @@
|
|||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" id="KGk-i7-Jjw" customClass="MWMEditorTextTableViewCell">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" rowHeight="56" id="KGk-i7-Jjw" customClass="MWMEditorTextTableViewCell">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="59"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="58.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="5uK-5Q-cg0">
|
||||
|
@ -24,10 +25,11 @@
|
|||
<userDefinedRuntimeAttribute type="string" keyPath="coloring" value="MWMBlack"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</imageView>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" textAlignment="natural" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="krN-k2-9qO">
|
||||
<rect key="frame" x="60" y="0.0" width="252" height="44"/>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="krN-k2-9qO">
|
||||
<rect key="frame" x="60" y="12" width="252" height="20"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" priority="750" constant="44" id="RYF-oc-ZOx"/>
|
||||
<constraint firstAttribute="height" constant="20" id="P3n-mD-g5V"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="17"/>
|
||||
<textInputTraits key="textInputTraits"/>
|
||||
|
@ -40,12 +42,29 @@
|
|||
<outlet property="delegate" destination="KGk-i7-Jjw" id="GO4-EB-MG9"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" preferredMaxLayoutWidth="252" translatesAutoresizingMaskIntoConstraints="NO" id="Lht-i1-s0H">
|
||||
<rect key="frame" x="60" y="32" width="252" height="14"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" priority="250" id="2X4-TJ-v2V"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="12"/>
|
||||
<color key="textColor" red="0.95686274510000002" green="0.26274509800000001" blue="0.21176470589999999" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular12"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="red"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="5uK-5Q-cg0" firstAttribute="centerY" secondItem="H2p-sc-9uM" secondAttribute="centerY" id="6CB-Dy-pnd"/>
|
||||
<constraint firstItem="krN-k2-9qO" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" id="M6R-qw-860"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Lht-i1-s0H" secondAttribute="bottom" constant="12" id="DhN-vK-bTb"/>
|
||||
<constraint firstItem="Lht-i1-s0H" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="60" id="EIo-KA-vQX"/>
|
||||
<constraint firstItem="krN-k2-9qO" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" constant="12" id="M6R-qw-860"/>
|
||||
<constraint firstAttribute="trailing" secondItem="krN-k2-9qO" secondAttribute="trailing" constant="8" id="O2l-xa-4ZO"/>
|
||||
<constraint firstAttribute="bottom" secondItem="krN-k2-9qO" secondAttribute="bottom" id="mfl-oM-QaP"/>
|
||||
<constraint firstItem="Lht-i1-s0H" firstAttribute="top" secondItem="krN-k2-9qO" secondAttribute="bottom" id="WLe-gG-Nur"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Lht-i1-s0H" secondAttribute="trailing" constant="8" id="bkK-l2-xGd"/>
|
||||
<constraint firstItem="5uK-5Q-cg0" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="topMargin" id="mZL-51-0kV"/>
|
||||
<constraint firstItem="5uK-5Q-cg0" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="16" id="ufn-3T-MOd"/>
|
||||
<constraint firstItem="krN-k2-9qO" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="60" id="w8z-Hi-yGr"/>
|
||||
</constraints>
|
||||
|
@ -58,9 +77,13 @@
|
|||
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="white"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<outlet property="errorLabel" destination="Lht-i1-s0H" id="N2I-je-OSW"/>
|
||||
<outlet property="errorLabelTopSpace" destination="WLe-gG-Nur" id="shl-Rd-fU4"/>
|
||||
<outlet property="icon" destination="5uK-5Q-cg0" id="5du-LU-RmA"/>
|
||||
<outlet property="labelHeight" destination="2X4-TJ-v2V" id="5jn-qt-Ma7"/>
|
||||
<outlet property="textField" destination="krN-k2-9qO" id="Fqg-H9-JpU"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="327" y="351.5"/>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
</document>
|
||||
|
|
|
@ -89,6 +89,7 @@ NSString * reuseIdentifier(MWMPlacePageCellType cellType)
|
|||
vector<MWMEditorSection> m_sections;
|
||||
map<MWMEditorSection, vector<MWMPlacePageCellType>> m_cells;
|
||||
osm::EditableMapObject m_mapObject;
|
||||
vector<pair<MWMPlacePageCellType, NSIndexPath *>> m_invalidCells;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
|
@ -161,6 +162,14 @@ NSString * reuseIdentifier(MWMPlacePageCellType cellType)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!m_invalidCells.empty())
|
||||
{
|
||||
auto const & firstInvalid = m_invalidCells.front();
|
||||
MWMEditorTextTableViewCell * cell = [self.tableView cellForRowAtIndexPath:firstInvalid.second];
|
||||
[cell.textField becomeFirstResponder];
|
||||
return;
|
||||
}
|
||||
|
||||
auto & f = GetFramework();
|
||||
auto const & featureID = m_mapObject.GetID();
|
||||
NSDictionary * info = @{kStatEditorMWMName : @(featureID.GetMwmName().c_str()),
|
||||
|
@ -478,7 +487,22 @@ NSString * reuseIdentifier(MWMPlacePageCellType cellType)
|
|||
|
||||
#pragma mark - MWMEditorCellProtocol
|
||||
|
||||
- (void)cell:(UITableViewCell *)cell changedText:(NSString *)changeText
|
||||
- (void)tryToChangeInvalidStateForCell:(MWMEditorTextTableViewCell *)cell
|
||||
{
|
||||
[self.tableView beginUpdates];
|
||||
|
||||
NSIndexPath * indexPath = [self.tableView indexPathForCell:cell];
|
||||
|
||||
m_invalidCells.erase(remove_if(m_invalidCells.begin(), m_invalidCells.end(),
|
||||
[indexPath](pair<MWMPlacePageCellType, NSIndexPath *> const & p)
|
||||
{
|
||||
return [p.second isEqual:indexPath];
|
||||
}));
|
||||
|
||||
[self.tableView endUpdates];
|
||||
}
|
||||
|
||||
- (void)cell:(MWMEditorTextTableViewCell *)cell changedText:(NSString *)changeText
|
||||
{
|
||||
NSAssert(changeText != nil, @"String can't be nil!");
|
||||
NSIndexPath * indexPath = [self.tableView indexPathForCell:cell];
|
||||
|
@ -494,6 +518,15 @@ NSString * reuseIdentifier(MWMPlacePageCellType cellType)
|
|||
case MWMPlacePageCellTypeBuilding: m_mapObject.SetHouseNumber(val); break;
|
||||
default: NSAssert(false, @"Invalid field for changeText");
|
||||
}
|
||||
//TODO: Here we need to process validation's result. Code below performs some UI updates and we should call it
|
||||
// if validation finish with error.
|
||||
|
||||
/*
|
||||
NSIndexPath * indexPath = [self.tableView indexPathForCell:cell];
|
||||
m_invalidCells.emplace_back(cellType, indexPath);
|
||||
[self.tableView reloadRowsAtIndexPaths:@[[self.tableView indexPathForCell:cell]] withRowAnimation:UITableViewRowAnimationFade];
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
- (void)cell:(UITableViewCell *)cell changeSwitch:(BOOL)changeSwitch
|
||||
|
|
Loading…
Add table
Reference in a new issue