Преглед изворни кода

Add a placeholder for object argument input fields

Tanner Bennett пре 7 година
родитељ
комит
156eb8cbe1

+ 47 - 19
Classes/Editing/ArgumentInputViews/FLEXArgumentInputObjectView.m

@@ -9,7 +9,7 @@
 #import "FLEXArgumentInputObjectView.h"
 #import "FLEXArgumentInputObjectView.h"
 #import "FLEXRuntimeUtility.h"
 #import "FLEXRuntimeUtility.h"
 
 
-static const CGFloat kSegmentInputMargin = 4;
+static const CGFloat kSegmentInputMargin = 10;
 
 
 typedef NS_ENUM(NSUInteger, FLEXArgInputObjectType) {
 typedef NS_ENUM(NSUInteger, FLEXArgInputObjectType) {
     FLEXArgInputObjectTypeJSON,
     FLEXArgInputObjectTypeJSON,
@@ -57,11 +57,12 @@ typedef NS_ENUM(NSUInteger, FLEXArgInputObjectType) {
         [self populateTextAreaFromValue:super.inputValue];
         [self populateTextAreaFromValue:super.inputValue];
     } else {
     } else {
         // Clear the text field
         // Clear the text field
-        self.inputValue = nil;
+        [self populateTextAreaFromValue:nil];
     }
     }
 }
 }
 
 
-- (void)setInputType:(FLEXArgInputObjectType)inputType {
+- (void)setInputType:(FLEXArgInputObjectType)inputType
+{
     if (_inputType == inputType) return;
     if (_inputType == inputType) return;
 
 
     _inputType = inputType;
     _inputType = inputType;
@@ -76,6 +77,23 @@ typedef NS_ENUM(NSUInteger, FLEXArgInputObjectType) {
             break;
             break;
     }
     }
 
 
+    // Change placeholder
+    switch (inputType) {
+        case FLEXArgInputObjectTypeJSON:
+            self.inputPlaceholderText =
+            @"You can put any valid JSON here, such as a string, number, array, or dictionary:"
+            "\n\"This is a string\""
+            "\n1234"
+            "\n{ \"name\": \"Bob\", \"age\": 47 }"
+            "\n["
+            "\n   1, 2, 3"
+            "\n]";
+            break;
+        case FLEXArgInputObjectTypeAddress:
+            self.inputPlaceholderText = @"0x0000deadb33f";
+            break;
+    }
+
     [self setNeedsLayout];
     [self setNeedsLayout];
     [self.superview setNeedsLayout];
     [self.superview setNeedsLayout];
 }
 }
@@ -106,11 +124,18 @@ typedef NS_ENUM(NSUInteger, FLEXArgInputObjectType) {
 
 
 - (void)populateTextAreaFromValue:(id)value
 - (void)populateTextAreaFromValue:(id)value
 {
 {
-    if (self.inputType == FLEXArgInputObjectTypeJSON) {
-        self.inputTextView.text = [FLEXRuntimeUtility editableJSONStringForObject:value];
-    } else if (self.inputType == FLEXArgInputObjectTypeAddress) {
-        self.inputTextView.text = [NSString stringWithFormat:@"%p", value];
+    if (!value) {
+        self.inputTextView.text = nil;
+    } else {
+        if (self.inputType == FLEXArgInputObjectTypeJSON) {
+            self.inputTextView.text = [FLEXRuntimeUtility editableJSONStringForObject:value];
+        } else if (self.inputType == FLEXArgInputObjectTypeAddress) {
+            self.inputTextView.text = [NSString stringWithFormat:@"%p", value];
+        }
     }
     }
+
+    // Delegate methods are not called for programmatic changes
+    [self textViewDidChange:self.inputTextView];
 }
 }
 
 
 - (CGSize)sizeThatFits:(CGSize)size
 - (CGSize)sizeThatFits:(CGSize)size
@@ -121,24 +146,27 @@ typedef NS_ENUM(NSUInteger, FLEXArgInputObjectType) {
     return fitSize;
     return fitSize;
 }
 }
 
 
-- (void)layoutSubviews {
-    // Must be called first since we are overriding self.inputTextView's position
-    [super layoutSubviews];
-
+- (void)layoutSubviews
+{
     CGFloat segmentHeight = [self.objectTypeSegmentControl sizeThatFits:self.frame.size].height;
     CGFloat segmentHeight = [self.objectTypeSegmentControl sizeThatFits:self.frame.size].height;
-
-    self.inputTextView.frame = CGRectMake(
-        0.0,
-        segmentHeight + self.topInputFieldVerticalLayoutGuide + kSegmentInputMargin,
-        self.inputTextView.frame.size.width,
-        self.inputTextView.frame.size.height
-    );
     self.objectTypeSegmentControl.frame = CGRectMake(
     self.objectTypeSegmentControl.frame = CGRectMake(
         0.0,
         0.0,
-        self.topInputFieldVerticalLayoutGuide,
+        // Our segmented control is taking the position
+        // of the text view, as far as super is concerned,
+        // and we override this property to be different
+        super.topInputFieldVerticalLayoutGuide,
         self.frame.size.width,
         self.frame.size.width,
         segmentHeight
         segmentHeight
     );
     );
+
+    [super layoutSubviews];
+}
+
+- (CGFloat)topInputFieldVerticalLayoutGuide
+{
+    // Our text view is offset from the segmented control
+    CGFloat segmentHeight = [self.objectTypeSegmentControl sizeThatFits:self.frame.size].height;
+    return segmentHeight + super.topInputFieldVerticalLayoutGuide + kSegmentInputMargin;
 }
 }
 
 
 + (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value
 + (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value

+ 3 - 2
Classes/Editing/ArgumentInputViews/FLEXArgumentInputTextView.h

@@ -8,10 +8,11 @@
 
 
 #import "FLEXArgumentInputView.h"
 #import "FLEXArgumentInputView.h"
 
 
-@interface FLEXArgumentInputTextView : FLEXArgumentInputView
+@interface FLEXArgumentInputTextView : FLEXArgumentInputView <UITextViewDelegate>
 
 
 // For subclass eyes only
 // For subclass eyes only
 
 
-@property (nonatomic, strong, readonly) UITextView *inputTextView;
+@property (nonatomic, readonly) UITextView *inputTextView;
+@property (nonatomic) NSString *inputPlaceholderText;
 
 
 @end
 @end

+ 53 - 10
Classes/Editing/ArgumentInputViews/FLEXArgumentInputTextView.m

@@ -10,9 +10,10 @@
 #import "FLEXArgumentInputTextView.h"
 #import "FLEXArgumentInputTextView.h"
 #import "FLEXUtility.h"
 #import "FLEXUtility.h"
 
 
-@interface FLEXArgumentInputTextView () <UITextViewDelegate>
+@interface FLEXArgumentInputTextView ()
 
 
-@property (nonatomic, strong) UITextView *inputTextView;
+@property (nonatomic) UITextView *inputTextView;
+@property (nonatomic) UILabel *placeholderLabel;
 @property (nonatomic, readonly) NSUInteger numberOfInputLines;
 @property (nonatomic, readonly) NSUInteger numberOfInputLines;
 
 
 @end
 @end
@@ -23,23 +24,31 @@
 {
 {
     self = [super initWithArgumentTypeEncoding:typeEncoding];
     self = [super initWithArgumentTypeEncoding:typeEncoding];
     if (self) {
     if (self) {
-        self.inputTextView = [[UITextView alloc] init];
+        self.inputTextView = [UITextView new];
         self.inputTextView.font = [[self class] inputFont];
         self.inputTextView.font = [[self class] inputFont];
         self.inputTextView.backgroundColor = [FLEXColor primaryBackgroundColor];
         self.inputTextView.backgroundColor = [FLEXColor primaryBackgroundColor];
         self.inputTextView.layer.borderColor = [[FLEXColor borderColor] CGColor];
         self.inputTextView.layer.borderColor = [[FLEXColor borderColor] CGColor];
-        self.inputTextView.layer.borderWidth = 1.0;
+        self.inputTextView.layer.borderWidth = 1.f;
+        self.inputTextView.layer.cornerRadius = 5.f;
         self.inputTextView.autocapitalizationType = UITextAutocapitalizationTypeNone;
         self.inputTextView.autocapitalizationType = UITextAutocapitalizationTypeNone;
         self.inputTextView.autocorrectionType = UITextAutocorrectionTypeNo;
         self.inputTextView.autocorrectionType = UITextAutocorrectionTypeNo;
         self.inputTextView.delegate = self;
         self.inputTextView.delegate = self;
         self.inputTextView.inputAccessoryView = [self createToolBar];
         self.inputTextView.inputAccessoryView = [self createToolBar];
         [self addSubview:self.inputTextView];
         [self addSubview:self.inputTextView];
+
+        self.placeholderLabel = [UILabel new];
+        self.placeholderLabel.font = self.inputTextView.font;
+        self.placeholderLabel.textColor = [FLEXColor deemphasizedTextColor];
+        self.placeholderLabel.numberOfLines = 0;
+        [self.inputTextView addSubview:self.placeholderLabel];
+
     }
     }
     return self;
     return self;
 }
 }
 
 
-#pragma mark - private
+#pragma mark - Private
 
 
-- (UIToolbar*)createToolBar
+- (UIToolbar *)createToolBar
 {
 {
     UIToolbar *toolBar = [UIToolbar new];
     UIToolbar *toolBar = [UIToolbar new];
     [toolBar sizeToFit];
     [toolBar sizeToFit];
@@ -54,12 +63,25 @@
     [self.inputTextView resignFirstResponder];
     [self.inputTextView resignFirstResponder];
 }
 }
 
 
+- (void)setInputPlaceholderText:(NSString *)placeholder
+{
+    self.placeholderLabel.text = placeholder;
+    if (placeholder.length) {
+        if (!self.inputTextView.text.length) {
+            self.placeholderLabel.hidden = NO;
+        } else {
+            self.placeholderLabel.hidden = YES;
+        }
+    } else {
+        self.placeholderLabel.hidden = YES;
+    }
 
 
-#pragma mark - Text View Changes
+    [self setNeedsLayout];
+}
 
 
-- (void)textViewDidChange:(UITextView *)textView
+- (NSString *)inputPlaceholderText
 {
 {
-    [self.delegate argumentInputViewValueDidChange:self];
+    return self.placeholderLabel.text;
 }
 }
 
 
 
 
@@ -78,6 +100,16 @@
     [super layoutSubviews];
     [super layoutSubviews];
     
     
     self.inputTextView.frame = CGRectMake(0, self.topInputFieldVerticalLayoutGuide, self.bounds.size.width, [self inputTextViewHeight]);
     self.inputTextView.frame = CGRectMake(0, self.topInputFieldVerticalLayoutGuide, self.bounds.size.width, [self inputTextViewHeight]);
+    // Placeholder label is positioned by insetting origin,
+    // which is the line fragment padding for X and 0 for Y,
+    // by the content inset then the text container inset
+    CGFloat leading = self.inputTextView.textContainer.lineFragmentPadding;
+    CGSize s = self.inputTextView.frame.size;
+    self.placeholderLabel.frame = CGRectMake(leading, 0, s.width, s.height);
+    self.placeholderLabel.frame = UIEdgeInsetsInsetRect(
+        UIEdgeInsetsInsetRect(self.placeholderLabel.frame, self.inputTextView.contentInset),
+        self.inputTextView.textContainerInset
+    );
 }
 }
 
 
 - (NSUInteger)numberOfInputLines
 - (NSUInteger)numberOfInputLines
@@ -104,9 +136,11 @@
     return fitSize;
     return fitSize;
 }
 }
 
 
+
 #pragma mark - Trait collection changes
 #pragma mark - Trait collection changes
 
 
-- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
+- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
+{
 #if FLEX_AT_LEAST_IOS13_SDK
 #if FLEX_AT_LEAST_IOS13_SDK
     if (@available(iOS 13.0, *)) {
     if (@available(iOS 13.0, *)) {
         if (previousTraitCollection.userInterfaceStyle != self.traitCollection.userInterfaceStyle) {
         if (previousTraitCollection.userInterfaceStyle != self.traitCollection.userInterfaceStyle) {
@@ -124,4 +158,13 @@
     return [FLEXUtility defaultFontOfSize:14.0];
     return [FLEXUtility defaultFontOfSize:14.0];
 }
 }
 
 
+
+#pragma mark - UITextViewDelegate
+
+- (void)textViewDidChange:(UITextView *)textView
+{
+    [self.delegate argumentInputViewValueDidChange:self];
+    self.placeholderLabel.hidden = !(self.inputPlaceholderText.length && !textView.text.length);
+}
+
 @end
 @end