Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / cocoa / autofill / autofill_overlay_controller.mm
1 // Copyright 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_overlay_controller.h"
6
7 #include "base/logging.h"
8 #include "base/mac/foundation_util.h"
9 #include "base/strings/sys_string_conversions.h"
10 #include "chrome/browser/ui/autofill/autofill_dialog_types.h"
11 #include "chrome/browser/ui/autofill/autofill_dialog_view_delegate.h"
12 #include "chrome/browser/ui/cocoa/autofill/autofill_dialog_constants.h"
13 #include "skia/ext/skia_utils_mac.h"
14
15 namespace {
16
17 // Spacing around the message in the overlay view.
18 const CGFloat kOverlayLabelPadding = 34;
19
20 // Spacing below image and above text messages in overlay view.
21 const CGFloat kOverlayImageVerticalPadding = 90;
22
23 // TODO(groby): Unify colors with Views.
24 // Slight shading for mouse hover and legal document background.
25 SkColor kShadingColor = 0xfff2f2f2;
26
27 // A border color for the legal document view.
28 SkColor kSubtleBorderColor = 0xffdfdfdf;
29
30 }  // namespace
31
32 // An NSView encapsulating the message stack and its custom drawn elements.
33 @interface AutofillMessageView : NSView<AutofillLayout> {
34  @private
35   base::scoped_nsobject<NSTextField> label_;
36 }
37
38 - (id)initWithFrame:(NSRect)frame;
39 - (CGFloat)heightForWidth:(CGFloat)width;
40 - (void)setMessage:(const autofill::DialogOverlayString&)message;
41 @end
42
43
44 @implementation AutofillMessageView
45
46 - (void)drawRect:(NSRect)dirtyRect {
47   NSColor* shadingColor = gfx::SkColorToCalibratedNSColor(kShadingColor);
48   NSColor* borderColor = gfx::SkColorToCalibratedNSColor(kSubtleBorderColor);
49
50   CGFloat arrowHalfWidth = autofill::kArrowWidth / 2.0;
51   NSRect bounds = [self bounds];
52   CGFloat y = NSMaxY(bounds) - autofill::kArrowHeight;
53
54   NSBezierPath* arrow = [NSBezierPath bezierPath];
55   // Note that we purposely draw slightly outside of |bounds| so that the
56   // stroke is hidden on the sides and bottom.
57   NSRect arrowBounds = NSInsetRect(bounds, -1, -1);
58   arrowBounds.size.height--;
59   [arrow moveToPoint:NSMakePoint(NSMinX(arrowBounds), y)];
60   [arrow lineToPoint:
61       NSMakePoint(NSMidX(arrowBounds) - arrowHalfWidth, y)];
62   [arrow relativeLineToPoint:
63       NSMakePoint(arrowHalfWidth,autofill::kArrowHeight)];
64   [arrow relativeLineToPoint:
65       NSMakePoint(arrowHalfWidth, -autofill::kArrowHeight)];
66   [arrow lineToPoint:NSMakePoint(NSMaxX(arrowBounds), y)];
67   [arrow lineToPoint:NSMakePoint(NSMaxX(arrowBounds), NSMinY(arrowBounds))];
68   [arrow lineToPoint:NSMakePoint(NSMinX(arrowBounds), NSMinY(arrowBounds))];
69   [arrow closePath];
70
71   [shadingColor setFill];
72   [arrow fill];
73   [borderColor setStroke];
74   [arrow stroke];
75 }
76
77 - (id)initWithFrame:(NSRect)frame {
78   if (self = [super initWithFrame:frame]) {
79     label_.reset([[NSTextField alloc] initWithFrame:NSZeroRect]);
80     [label_ setEditable:NO];
81     [label_ setBordered:NO];
82     [label_ setDrawsBackground:NO];
83     [label_ setAlignment:NSCenterTextAlignment];
84     [self addSubview:label_];
85   }
86   return self;
87 }
88
89 - (CGFloat)heightForWidth:(CGFloat)width {
90   return NSHeight([label_ frame]) + autofill::kArrowHeight +
91       2 * kOverlayLabelPadding;
92 }
93
94 - (void)setMessage:(const autofill::DialogOverlayString&)message {
95   // We probably want to look at other multi-line messages somewhere.
96   [label_ setFont:message.font_list.GetPrimaryFont().GetNativeFont()];
97   [label_ setStringValue:base::SysUTF16ToNSString(message.text)];
98   [label_ setTextColor:[NSColor darkGrayColor]];
99
100   // Resize only height, preserve width. This guarantees text stays centered in
101   // the dialog.
102   NSSize labelSize = [label_ frame].size;
103   labelSize.height = [[label_ cell] cellSize].height;
104   [label_ setFrameSize:labelSize];
105
106   [self setHidden:message.text.empty()];
107 }
108
109 - (void)performLayout {
110   if ([self isHidden])
111     return;
112
113   CGFloat labelHeight = NSHeight([label_ frame]);
114   [label_ setFrame:NSMakeRect(0, kOverlayLabelPadding,
115                               NSWidth([self bounds]), labelHeight)];
116   // TODO(groby): useful DCHECK() goes here.
117 }
118
119 - (NSSize)preferredSize {
120   NOTREACHED();
121   return NSZeroSize;
122 }
123
124 @end
125
126
127 @implementation AutofillOverlayController
128
129 - (id)initWithDelegate:(autofill::AutofillDialogViewDelegate*)delegate {
130   if (self = [super initWithNibName:nil bundle:nil]) {
131     delegate_ = delegate;
132
133     messageView_.reset([[AutofillMessageView alloc] initWithFrame:NSZeroRect]);
134     imageView_.reset([[NSImageView alloc] initWithFrame:NSZeroRect]);
135     [imageView_ setImageAlignment:NSImageAlignCenter];
136
137     base::scoped_nsobject<NSView> view(
138         [[NSView alloc] initWithFrame:NSZeroRect]);
139     [view setSubviews:@[messageView_, imageView_]];
140     [self setView:view];
141   }
142   return self;
143 }
144
145 - (void)updateState {
146   const autofill::DialogOverlayState& state = delegate_->GetDialogOverlay();
147
148   if (state.image.IsEmpty()) {
149     [[self view] setHidden:YES];
150     return;
151   }
152
153   [[self view] setHidden:NO];
154   [imageView_ setImage:state.image.ToNSImage()];
155   [messageView_ setMessage:state.string];
156
157   NSWindowController* delegate = [[[self view] window] windowController];
158   if ([delegate respondsToSelector:@selector(requestRelayout)])
159     [delegate performSelector:@selector(requestRelayout)];
160 }
161
162 - (CGFloat)heightForWidth:(int)width {
163   return 2 * kOverlayImageVerticalPadding +
164       [messageView_ heightForWidth:width] +
165       [[imageView_ image] size].height;
166 }
167
168 - (NSSize)preferredSize {
169   NOTREACHED();  // Only implemented as part of AutofillLayout protocol.
170   return NSZeroSize;
171 }
172
173 - (void)performLayout {
174   NSRect bounds = [[self view] bounds];
175
176   int messageHeight = [messageView_ heightForWidth:NSWidth(bounds)];
177   [messageView_ setFrame:NSMakeRect(0, 0, NSWidth(bounds), messageHeight)];
178   [messageView_ performLayout];
179
180   NSSize imageSize = [[imageView_ image] size];
181   [imageView_ setFrame:NSMakeRect(
182        0, NSMaxY([messageView_ frame]) + kOverlayImageVerticalPadding,
183        NSWidth(bounds), imageSize.height)];
184 }
185
186 @end