Home | History | Annotate | Download | only in autofill
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #import "chrome/browser/ui/cocoa/autofill/autofill_textfield.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
     10 
     11 namespace {
     12 
     13 const CGFloat kGap = 6.0;  // gap between icon and text.
     14 
     15 }  // namespace
     16 
     17 @interface AutofillTextFieldCell (Internal)
     18 
     19 - (NSRect)iconFrameForFrame:(NSRect)frame;
     20 - (NSRect)textFrameForFrame:(NSRect)frame;
     21 
     22 @end
     23 
     24 @implementation AutofillTextField
     25 
     26 @synthesize delegate = delegate_;
     27 
     28 + (Class)cellClass {
     29   return [AutofillTextFieldCell class];
     30 }
     31 
     32 - (id)initWithFrame:(NSRect)frame {
     33   if (self = [super initWithFrame:frame])
     34     [super setDelegate:self];
     35   return self;
     36 }
     37 
     38 - (BOOL)becomeFirstResponder {
     39   BOOL result = [super becomeFirstResponder];
     40   if (result && delegate_)
     41     [delegate_ fieldBecameFirstResponder:self];
     42   return result;
     43 }
     44 
     45 - (void)controlTextDidEndEditing:(NSNotification*)notification {
     46   if (delegate_)
     47     [delegate_ didEndEditing:self];
     48 }
     49 
     50 - (void)controlTextDidChange:(NSNotification*)aNotification {
     51   if (delegate_)
     52     [delegate_ didChange:self];
     53 }
     54 
     55 - (NSString*)fieldValue {
     56   return [[self cell] fieldValue];
     57 }
     58 
     59 - (void)setFieldValue:(NSString*)fieldValue {
     60   [[self cell] setFieldValue:fieldValue];
     61 }
     62 
     63 - (NSString*)validityMessage {
     64   return validityMessage_;
     65 }
     66 
     67 - (void)setValidityMessage:(NSString*)validityMessage {
     68   validityMessage_.reset([validityMessage copy]);
     69   [[self cell] setInvalid:[self invalid]];
     70   [self setNeedsDisplay:YES];
     71 }
     72 
     73 - (BOOL)invalid {
     74   return [validityMessage_ length] != 0;
     75 }
     76 
     77 @end
     78 
     79 @implementation AutofillTextFieldCell
     80 
     81 @synthesize invalid = invalid_;
     82 
     83 - (NSImage*) icon{
     84   return icon_;
     85 }
     86 
     87 - (void)setIcon:(NSImage*) icon {
     88   icon_.reset([icon retain]);
     89 }
     90 
     91 - (NSString*)fieldValue {
     92   return [self stringValue];
     93 }
     94 
     95 - (void)setFieldValue:(NSString*)fieldValue {
     96   [self setStringValue:fieldValue];
     97 }
     98 
     99 - (NSRect)textFrameForFrame:(NSRect)frame {
    100   if (icon_) {
    101     NSRect textFrame, iconFrame;
    102     NSDivideRect(frame, &iconFrame, &textFrame,
    103                  kGap + [icon_ size].width, NSMaxXEdge);
    104     return textFrame;
    105   }
    106   return frame;
    107 }
    108 
    109 - (NSRect)iconFrameForFrame:(NSRect)frame {
    110   NSRect iconFrame;
    111   if (icon_) {
    112     NSRect textFrame;
    113     NSDivideRect(frame, &iconFrame, &textFrame,
    114                  kGap + [icon_ size].width, NSMaxXEdge);
    115   }
    116   return iconFrame;
    117 }
    118 
    119 - (NSSize)cellSize {
    120   NSSize cellSize = [super cellSize];
    121 
    122   if (icon_) {
    123     NSSize iconSize = [icon_ size];
    124     cellSize.width += kGap + iconSize.width;
    125     cellSize.height = std::max(cellSize.height, iconSize.height);
    126   }
    127 
    128   return cellSize;
    129 }
    130 
    131 - (void)editWithFrame:(NSRect)cellFrame
    132                inView:(NSView *)controlView
    133                editor:(NSText *)editor
    134              delegate:(id)delegate
    135                 event:(NSEvent *)event {
    136   [super editWithFrame:[self textFrameForFrame:cellFrame]
    137                 inView:controlView
    138                 editor:editor
    139               delegate:delegate
    140                  event:event];
    141 }
    142 
    143 - (void)selectWithFrame:(NSRect)cellFrame
    144                  inView:(NSView *)controlView
    145                  editor:(NSText *)editor
    146                delegate:(id)delegate
    147                   start:(NSInteger)start
    148                  length:(NSInteger)length {
    149   [super selectWithFrame:[self textFrameForFrame:cellFrame]
    150                   inView:controlView
    151                   editor:editor
    152                 delegate:delegate
    153                    start:start
    154                   length:length];
    155 }
    156 
    157 - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
    158   [super drawWithFrame:cellFrame inView:controlView];
    159 
    160   if (icon_) {
    161     NSRect iconFrame = [self iconFrameForFrame:cellFrame];
    162     iconFrame.size = [icon_ size];
    163     iconFrame.origin.y +=
    164         roundf((NSHeight(cellFrame) - NSHeight(iconFrame)) / 2.0);
    165     [icon_ drawInRect:iconFrame
    166              fromRect:NSZeroRect
    167             operation:NSCompositeSourceOver
    168              fraction:1.0
    169        respectFlipped:YES
    170                 hints:nil];
    171   }
    172 
    173   if (invalid_) {
    174     gfx::ScopedNSGraphicsContextSaveGState state;
    175 
    176     // Render red border for invalid fields.
    177     [[NSColor colorWithDeviceRed:1.0 green:0.0 blue:0.0 alpha:1.0] setStroke];
    178     [[NSBezierPath bezierPathWithRect:NSInsetRect(cellFrame, 0.5, 0.5)] stroke];
    179 
    180     // Render a dog ear to flag invalid fields.
    181     const CGFloat kDogEarSize = 10.0f;
    182 
    183     // TODO(groby): This is a temporary placeholder and will be replaced
    184     // with an image. (Pending UI/UX work).
    185     [[NSColor colorWithDeviceRed:1.0 green:0.0 blue:0.0 alpha:1.0] setFill];
    186     NSBezierPath* dog_ear = [NSBezierPath bezierPath];
    187     NSPoint corner = NSMakePoint(NSMaxX(cellFrame), NSMinY(cellFrame));
    188     [dog_ear moveToPoint:NSMakePoint(corner.x - kDogEarSize, corner.y)];
    189     [dog_ear lineToPoint:corner];
    190     [dog_ear lineToPoint:NSMakePoint(corner.x, corner.y + kDogEarSize)];
    191     [dog_ear closePath];
    192     [dog_ear fill];
    193   }
    194 }
    195 
    196 @end
    197