text: /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   *
   *   http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing,
   * software distributed under the License is distributed on an
   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   * KIND, either express or implied.  See the License for the
   * specific language governing permissions and limitations
   * under the License.
   */
  
  #import "WXTextAreaComponent.h"
  #import "WXUtility.h"
  #import "WXComponent+Layout.h"
  #import "WXComponent_internal.h"
  
  #define CorrectX 4 //textview fill text 4 pixel from left. so placeholderlabel have 4 pixel too
  #define CorrectY 8 // textview fill text 8 pixel from top
  typedef UITextView WXTextAreaView;
  
  @interface WXTextAreaComponent()
  
  @property (nonatomic, strong) WXTextAreaView *textView;
  @property (nonatomic) NSUInteger rows;
  
  @end
  
  @implementation WXTextAreaComponent {
      UIEdgeInsets _border;
      UIEdgeInsets _padding;
  }
  
  -(void)viewDidLoad
  {
      _padding = UIEdgeInsetsZero;
      _border = UIEdgeInsetsZero;
      if (self.placeholderString) {
          self.placeHolderLabel = [[UILabel alloc] init];
          self.placeHolderLabel.numberOfLines = 0;
          [_textView addSubview:self.placeHolderLabel];
      }
      // default placeholder hide from voice over
      self.placeHolderLabel.isAccessibilityElement = NO;
      _textView.isAccessibilityElement = YES;
      _textView.delegate = self;
      [_textView setNeedsDisplay];
      [_textView setClipsToBounds:YES];
      [super viewDidLoad];
  }
  
  - (void)viewWillUnload
  {
      _textView = nil;
  }
  
  - (UIView *)loadView
  {
      _textView = [[WXTextAreaView alloc] init];
      return _textView;
  }
  
  #pragma mark measure frame
  - (CGSize (^)(CGSize))measureBlock
  {
      __weak typeof(self) weakSelf = self;
      return ^CGSize (CGSize constrainedSize) {
          
          CGSize computedSize = [[[NSString alloc] init]sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:weakSelf.textView.font.pointSize]}];
          computedSize.height = _rows? computedSize.height *weakSelf.rows + (CorrectY + CorrectY/2):0;
          if (!isnan(weakSelf.cssNode->style.minDimensions[CSS_WIDTH])) {
              computedSize.width = MAX(computedSize.width, weakSelf.cssNode->style.minDimensions[CSS_WIDTH]);
          }
          
          if (!isnan(weakSelf.cssNode->style.maxDimensions[CSS_WIDTH])) {
              computedSize.width = MIN(computedSize.width, weakSelf.cssNode->style.maxDimensions[CSS_WIDTH]);
          }
          
          if (!isnan(weakSelf.cssNode->style.minDimensions[CSS_HEIGHT])) {
              computedSize.height = MAX(computedSize.height, weakSelf.cssNode->style.minDimensions[CSS_HEIGHT]);
          }
          
          if (!isnan(weakSelf.cssNode->style.maxDimensions[CSS_HEIGHT])) {
              computedSize.height = MIN(computedSize.height, weakSelf.cssNode->style.maxDimensions[CSS_HEIGHT]);
          }
          
          return (CGSize) {
              WXCeilPixelValue(computedSize.width),
              WXCeilPixelValue(computedSize.height)
          };
      };
  }
  
  #pragma mark -Overwrite method
  -(NSString *)text
  {
      return _textView.text;
  }
  
  - (void)setText:(NSString *)text
  {
      _textView.text = text;
      if ([text length] >0) {
          self.placeHolderLabel.text = @"";
      }
  }
  
  -(void)setTextColor:(UIColor *)color
  {
      [_textView setTextColor:color];
  }
  
  -(void)setTextAlignment:(NSTextAlignment)textAlignForStyle
  {
      [_textView setTextAlignment:textAlignForStyle];
  }
  
  -(void)setUserInteractionEnabled:(BOOL)userInteractionEnabled
  {
      [_textView setUserInteractionEnabled:userInteractionEnabled];
  }
  
  -(void)setEnabled:(BOOL)enabled
  {
      _textView.editable = enabled;
      _textView.selectable = enabled;
  }
  
  -(void)setReturnKeyType:(UIReturnKeyType)returnKeyType
  {
      [_textView setReturnKeyType:returnKeyType];
  }
  
  -(void)setInputAccessoryView:(UIView *)inputAccessoryView
  {
      [_textView setInputAccessoryView:inputAccessoryView];
  }
  
  -(void)setEditSelectionRange:(NSInteger)selectionStart selectionEnd:(NSInteger)selectionEnd
  {
      [self.textView becomeFirstResponder];
      UITextPosition *startPos =  [self.textView positionFromPosition:self.textView.beginningOfDocument offset:selectionStart];
      UITextPosition *endPos = [self.textView positionFromPosition:self.textView.beginningOfDocument offset:selectionEnd];
      UITextRange *textRange = [self.textView textRangeFromPosition:startPos
                                                         toPosition:endPos];
      self.textView.selectedTextRange = textRange;
  }
  
  -(NSDictionary *)getEditSelectionRange
  {
      NSInteger selectionStart = [self.textView offsetFromPosition:self.textView.beginningOfDocument toPosition:self.textView.selectedTextRange.start];
      NSInteger selectionEnd = [self.textView offsetFromPosition:self.textView.beginningOfDocument toPosition:self.textView.selectedTextRange.end];
      NSDictionary *res = @{@"selectionStart":@(selectionStart),@"selectionEnd":@(selectionEnd)};
      return res;
  }
  
  -(void)setKeyboardType:(UIKeyboardType)keyboardType
  {
      [_textView setKeyboardType:keyboardType];
  }
  
  -(void)setSecureTextEntry:(BOOL)secureTextEntry
  {
      [_textView setSecureTextEntry:secureTextEntry];
  }
  
  -(void)setEditPadding:(UIEdgeInsets)padding
  {
      _padding = padding;
      [self _updateTextContentInset];
  }
  
  -(void)setEditBorder:(UIEdgeInsets)border
  {
      _border = border;
      [self _updateTextContentInset];
  }
  
  -(void)setAttributedPlaceholder:(NSMutableAttributedString *)attributedString font:(UIFont *)font
  {
      if ([_textView.text length] > 0) {
          self.placeHolderLabel.text = @"";
          return;
      }
  
      if (self.placeholderColor) {
          [attributedString addAttribute:NSForegroundColorAttributeName value:self.placeholderColor range:NSMakeRange(0, self.placeholderString.length)];
          [attributedString addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, self.placeholderString.length)];
      }
      self.placeHolderLabel.backgroundColor = [UIColor clearColor];
      CGRect expectedLabelSize = [attributedString boundingRectWithSize:(CGSize){self.view.frame.size.width, CGFLOAT_MAX}
                                                                options:NSStringDrawingUsesLineFragmentOrigin
                                                                context:nil];
      
      self.placeHolderLabel.clipsToBounds = NO;
      CGRect newFrame = self.placeHolderLabel.frame;
      newFrame.size.height = ceil(expectedLabelSize.size.height);
      newFrame.size.width = _textView.frame.size.width - (_padding.left + _border.left + _padding.right + _border.right) -CorrectX*2;
      newFrame.origin.x = CorrectX + _padding.left + _border.left; // the cursor origin.x
      self.placeHolderLabel.frame = newFrame;
      self.placeHolderLabel.attributedText = attributedString;
  }
  
  -(void)setFont:(UIFont *)font
  {
      [_textView setFont:font];
  }
  
  -(void)setRows:(NSUInteger)rows
  {
      _rows = rows;
      [self setNeedsLayout];
  }
  
  #pragma mark -Private Method
  - (void)_updateTextContentInset
  {
      [_textView setTextContainerInset:UIEdgeInsetsMake(_padding.top + _border.top,
                                                        _padding.left + _border.left,
                                                        _padding.bottom + _border.bottom,
                                                        _padding.right + _border.right)];
      
      //when textview update, placeHolderLabel update too
      CGRect newFrame = self.placeHolderLabel.frame;
      newFrame.size.width = self.textView.frame.size.width - (_padding.left + _border.left + _padding.right + _border.right) -CorrectX*2;
      newFrame.origin.x = CorrectX + _padding.left + _border.left; // the cursor origin.x
      newFrame.origin.y = _padding.top + _border.top;
      self.placeHolderLabel.frame = newFrame;
  }
  
  @end
  