- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / cocoa / autofill / autofill_textfield.mm
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 #include <cmath>
9
10 #include "base/logging.h"
11 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
12
13 namespace {
14
15 const CGFloat kGap = 6.0;  // gap between icon and text.
16 const CGFloat kMinimumHeight = 27.0;  // Enforced minimum height for text cells.
17
18 }  // namespace
19
20 @interface AutofillTextFieldCell (Internal)
21
22 - (NSRect)iconFrameForFrame:(NSRect)frame;
23 - (NSRect)textFrameForFrame:(NSRect)frame;
24
25 @end
26
27 @implementation AutofillTextField
28
29 @synthesize delegate = delegate_;
30
31 + (Class)cellClass {
32   return [AutofillTextFieldCell class];
33 }
34
35 - (id)initWithFrame:(NSRect)frame {
36   if (self = [super initWithFrame:frame])
37     [super setDelegate:self];
38   return self;
39 }
40
41 - (BOOL)becomeFirstResponder {
42   BOOL result = [super becomeFirstResponder];
43   if (result && delegate_)
44     [delegate_ fieldBecameFirstResponder:self];
45   return result;
46 }
47
48 - (void)controlTextDidEndEditing:(NSNotification*)notification {
49   if (delegate_)
50     [delegate_ didEndEditing:self];
51 }
52
53 - (void)controlTextDidChange:(NSNotification*)aNotification {
54   if (delegate_)
55     [delegate_ didChange:self];
56 }
57
58 - (NSString*)fieldValue {
59   return [[self cell] fieldValue];
60 }
61
62 - (void)setFieldValue:(NSString*)fieldValue {
63   [[self cell] setFieldValue:fieldValue];
64 }
65
66 - (NSString*)defaultValue {
67   return [[self cell] defaultValue];
68 }
69
70 - (void)setDefaultValue:(NSString*)defaultValue {
71   [[self cell] setDefaultValue:defaultValue];
72 }
73
74 - (BOOL)isDefault {
75   return [[[self cell] fieldValue] isEqualToString:[[self cell] defaultValue]];
76 }
77
78 - (NSString*)validityMessage {
79   return validityMessage_;
80 }
81
82 - (void)setValidityMessage:(NSString*)validityMessage {
83   validityMessage_.reset([validityMessage copy]);
84   [[self cell] setInvalid:[self invalid]];
85 }
86
87 - (BOOL)invalid {
88   return [validityMessage_ length] != 0;
89 }
90
91 @end
92
93 @implementation AutofillTextFieldCell
94
95 @synthesize invalid = invalid_;
96 @synthesize defaultValue = defaultValue_;
97
98 - (void)setInvalid:(BOOL)invalid {
99   invalid_ = invalid;
100   [[self controlView] setNeedsDisplay:YES];
101 }
102
103 - (NSImage*) icon{
104   return icon_;
105 }
106
107 - (void)setIcon:(NSImage*) icon {
108   icon_.reset([icon retain]);
109   [[self controlView] setNeedsDisplay:YES];
110 }
111
112 - (NSString*)fieldValue {
113   return [self stringValue];
114 }
115
116 - (void)setFieldValue:(NSString*)fieldValue {
117   [self setStringValue:fieldValue];
118 }
119
120 - (NSRect)textFrameForFrame:(NSRect)frame {
121   // Ensure text height is original cell height, and the text frame is centered
122   // vertically in the cell frame.
123   NSSize originalSize = [super cellSize];
124   if (originalSize.height < NSHeight(frame)) {
125     CGFloat delta = NSHeight(frame) - originalSize.height;
126     frame.origin.y += std::floor(delta / 2.0);
127     frame.size.height -= delta;
128   }
129   DCHECK_EQ(originalSize.height, NSHeight(frame));
130
131   if (icon_) {
132     NSRect textFrame, iconFrame;
133     NSDivideRect(frame, &iconFrame, &textFrame,
134                  kGap + [icon_ size].width, NSMaxXEdge);
135     return textFrame;
136   }
137   return frame;
138 }
139
140 - (NSRect)iconFrameForFrame:(NSRect)frame {
141   NSRect iconFrame;
142   if (icon_) {
143     NSRect textFrame;
144     NSDivideRect(frame, &iconFrame, &textFrame,
145                  kGap + [icon_ size].width, NSMaxXEdge);
146   }
147   return iconFrame;
148 }
149
150 - (NSSize)cellSize {
151   NSSize cellSize = [super cellSize];
152
153   if (icon_) {
154     NSSize iconSize = [icon_ size];
155     cellSize.width += kGap + iconSize.width;
156     cellSize.height = std::max(cellSize.height, iconSize.height);
157   }
158   cellSize.height = std::max(cellSize.height, kMinimumHeight);
159   return cellSize;
160 }
161
162 - (void)editWithFrame:(NSRect)cellFrame
163                inView:(NSView *)controlView
164                editor:(NSText *)editor
165              delegate:(id)delegate
166                 event:(NSEvent *)event {
167   [super editWithFrame:[self textFrameForFrame:cellFrame]
168                 inView:controlView
169                 editor:editor
170               delegate:delegate
171                  event:event];
172 }
173
174 - (void)selectWithFrame:(NSRect)cellFrame
175                  inView:(NSView *)controlView
176                  editor:(NSText *)editor
177                delegate:(id)delegate
178                   start:(NSInteger)start
179                  length:(NSInteger)length {
180   [super selectWithFrame:[self textFrameForFrame:cellFrame]
181                   inView:controlView
182                   editor:editor
183                 delegate:delegate
184                    start:start
185                   length:length];
186 }
187
188 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
189   NSRect textFrame = [self textFrameForFrame:cellFrame];
190   [super drawInteriorWithFrame:textFrame inView:controlView];
191 }
192
193 - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
194   [super drawWithFrame:cellFrame inView:controlView];
195
196   if (icon_) {
197     NSRect iconFrame = [self iconFrameForFrame:cellFrame];
198     iconFrame.size = [icon_ size];
199     iconFrame.origin.y +=
200         roundf((NSHeight(cellFrame) - NSHeight(iconFrame)) / 2.0);
201     [icon_ drawInRect:iconFrame
202              fromRect:NSZeroRect
203             operation:NSCompositeSourceOver
204              fraction:1.0
205        respectFlipped:YES
206                 hints:nil];
207   }
208
209   if (invalid_) {
210     gfx::ScopedNSGraphicsContextSaveGState state;
211
212     // Render red border for invalid fields.
213     [[NSColor colorWithDeviceRed:1.0 green:0.0 blue:0.0 alpha:1.0] setStroke];
214     [[NSBezierPath bezierPathWithRect:NSInsetRect(cellFrame, 0.5, 0.5)] stroke];
215   }
216 }
217
218 @end