NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / autofill / autofill_textfield.mm
blobd0e3ea54ab61ddad1fa8f01ae8667cfb38f8edbc
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.
5 #import "chrome/browser/ui/cocoa/autofill/autofill_textfield.h"
7 #include <algorithm>
8 #include <cmath>
10 #include "base/logging.h"
11 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
13 namespace {
15 const CGFloat kGap = 6.0;  // gap between icon and text.
16 const CGFloat kMinimumHeight = 27.0;  // Enforced minimum height for text cells.
18 }  // namespace
20 @interface AutofillTextFieldCell (Internal)
22 - (NSRect)textFrameForFrame:(NSRect)frame;
24 @end
26 @implementation AutofillTextField
28 @synthesize inputDelegate = inputDelegate_;
30 + (Class)cellClass {
31   return [AutofillTextFieldCell class];
34 - (id)initWithFrame:(NSRect)frame {
35   if (self = [super initWithFrame:frame])
36     [super setDelegate:self];
37   return self;
40 - (BOOL)becomeFirstResponder {
41   BOOL result = [super becomeFirstResponder];
42   if (result && inputDelegate_) {
43     [inputDelegate_ fieldBecameFirstResponder:self];
44     shouldFilterClick_ = YES;
45   }
46   return result;
49 - (void)onEditorMouseDown:(id)sender {
50   // Since the dialog does not care about clicks that gave firstResponder
51   // status, swallow those.
52   if (!handlingFirstClick_)
53     [inputDelegate_ onMouseDown: self];
56 - (NSRect)decorationFrame {
57   return [[self cell] decorationFrameForFrame:[self frame]];
60 - (void)mouseDown:(NSEvent*)theEvent {
61   // mouseDown: is only invoked for a click that actually gave firstResponder
62   // status to the NSTextField, and clicks to the border area. Further clicks
63   // into the content are are handled by the field editor instead.
64   handlingFirstClick_ = shouldFilterClick_;
65   [super mouseDown:theEvent];
66   handlingFirstClick_ = NO;
67   shouldFilterClick_ = NO;
70 - (void)controlTextDidEndEditing:(NSNotification*)notification {
71   if (inputDelegate_)
72     [inputDelegate_ didEndEditing:self];
75 - (void)controlTextDidChange:(NSNotification*)aNotification {
76   if (inputDelegate_)
77     [inputDelegate_ didChange:self];
80 - (NSString*)fieldValue {
81   return [[self cell] fieldValue];
84 - (void)setFieldValue:(NSString*)fieldValue {
85   [[self cell] setFieldValue:fieldValue];
88 - (NSString*)defaultValue {
89   return [[self cell] defaultValue];
92 - (void)setDefaultValue:(NSString*)defaultValue {
93   [[self cell] setDefaultValue:defaultValue];
96 - (BOOL)isDefault {
97   return [[[self cell] fieldValue] isEqualToString:[[self cell] defaultValue]];
100 - (NSString*)validityMessage {
101   return validityMessage_;
104 - (void)setValidityMessage:(NSString*)validityMessage {
105   validityMessage_.reset([validityMessage copy]);
106   [[self cell] setInvalid:[self invalid]];
109 - (BOOL)invalid {
110   return [validityMessage_ length] != 0;
113 @end
116 @implementation AutofillTextFieldCell
118 @synthesize invalid = invalid_;
119 @synthesize defaultValue = defaultValue_;
120 @synthesize decorationSize = decorationSize_;
122 - (void)setInvalid:(BOOL)invalid {
123   invalid_ = invalid;
124   [[self controlView] setNeedsDisplay:YES];
127 - (NSImage*) icon{
128   return icon_;
131 - (void)setIcon:(NSImage*)icon {
132   icon_.reset([icon retain]);
133   [self setDecorationSize:[icon_ size]];
134   [[self controlView] setNeedsDisplay:YES];
137 - (NSString*)fieldValue {
138   return [self stringValue];
141 - (void)setFieldValue:(NSString*)fieldValue {
142   [self setStringValue:fieldValue];
145 - (NSRect)textFrameForFrame:(NSRect)frame {
146   // Ensure text height is original cell height, and the text frame is centered
147   // vertically in the cell frame.
148   NSSize originalSize = [super cellSize];
149   if (originalSize.height < NSHeight(frame)) {
150     CGFloat delta = NSHeight(frame) - originalSize.height;
151     frame.origin.y += std::floor(delta / 2.0);
152     frame.size.height -= delta;
153   }
154   DCHECK_EQ(originalSize.height, NSHeight(frame));
156   if (decorationSize_.width > 0) {
157     NSRect textFrame, decorationFrame;
158     NSDivideRect(frame, &decorationFrame, &textFrame,
159                  kGap + decorationSize_.width, NSMaxXEdge);
160     return textFrame;
161   }
162   return frame;
165 - (NSRect)decorationFrameForFrame:(NSRect)frame {
166   NSRect decorationFrame;
167   if (decorationSize_.width > 0) {
168     NSRect textFrame;
169     NSDivideRect(frame, &decorationFrame, &textFrame,
170                  kGap + decorationSize_.width, NSMaxXEdge);
171     decorationFrame.size = decorationSize_;
172     decorationFrame.origin.y +=
173         roundf((NSHeight(frame) - NSHeight(decorationFrame)) / 2.0);
174   }
175   return decorationFrame;
178 - (NSSize)cellSize {
179   NSSize cellSize = [super cellSize];
181   if (decorationSize_.width > 0) {
182     cellSize.width += kGap + decorationSize_.width;
183     cellSize.height = std::max(cellSize.height, decorationSize_.height);
184   }
185   cellSize.height = std::max(cellSize.height, kMinimumHeight);
186   return cellSize;
189 - (void)editWithFrame:(NSRect)cellFrame
190                inView:(NSView *)controlView
191                editor:(NSText *)editor
192              delegate:(id)delegate
193                 event:(NSEvent *)event {
194   [super editWithFrame:[self textFrameForFrame:cellFrame]
195                 inView:controlView
196                 editor:editor
197               delegate:delegate
198                  event:event];
201 - (void)selectWithFrame:(NSRect)cellFrame
202                  inView:(NSView *)controlView
203                  editor:(NSText *)editor
204                delegate:(id)delegate
205                   start:(NSInteger)start
206                  length:(NSInteger)length {
207   [super selectWithFrame:[self textFrameForFrame:cellFrame]
208                   inView:controlView
209                   editor:editor
210                 delegate:delegate
211                    start:start
212                   length:length];
215 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
216   NSRect textFrame = [self textFrameForFrame:cellFrame];
217   [super drawInteriorWithFrame:textFrame inView:controlView];
220 - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
221   [super drawWithFrame:cellFrame inView:controlView];
223   if (icon_) {
224     NSRect iconFrame = [self decorationFrameForFrame:cellFrame];
225     [icon_ drawInRect:iconFrame
226              fromRect:NSZeroRect
227             operation:NSCompositeSourceOver
228              fraction:1.0
229        respectFlipped:YES
230                 hints:nil];
231   }
233   if (invalid_) {
234     gfx::ScopedNSGraphicsContextSaveGState state;
236     // Render red border for invalid fields.
237     [[NSColor colorWithDeviceRed:1.0 green:0.0 blue:0.0 alpha:1.0] setStroke];
238     [[NSBezierPath bezierPathWithRect:NSInsetRect(cellFrame, 0.5, 0.5)] stroke];
239   }
242 @end