summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/cocoa/autofill/autofill_popup_base_view_cocoa.mm
blob: a2488345eca309a127ca8eb05cd9855c82635908 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "chrome/browser/ui/cocoa/autofill/autofill_popup_base_view_cocoa.h"

#include "chrome/browser/ui/autofill/autofill_popup_view_delegate.h"
#include "chrome/browser/ui/autofill/popup_constants.h"
#include "ui/base/cocoa/window_size_constants.h"

@implementation AutofillPopupBaseViewCocoa

#pragma mark -
#pragma mark Colors

- (NSColor*)backgroundColor {
  return [NSColor whiteColor];
}

- (NSColor*)borderColor {
  return [NSColor colorForControlTint:[NSColor currentControlTint]];
}

- (NSColor*)highlightColor {
  return [NSColor selectedControlColor];
}

- (NSColor*)nameColor {
  return [NSColor blackColor];
}

- (NSColor*)separatorColor {
  return [NSColor colorWithCalibratedWhite:220 / 255.0 alpha:1];
}

- (NSColor*)subtextColor {
  return [NSColor grayColor];
}

- (NSColor*)warningColor {
  return [NSColor grayColor];
}

#pragma mark -
#pragma mark Public methods

- (id)initWithDelegate:(autofill::AutofillPopupViewDelegate*)delegate
                 frame:(NSRect)frame {
  self = [super initWithFrame:frame];
  if (self)
    popup_delegate_ = delegate;

  return self;
}

- (void)delegateDestroyed {
  popup_delegate_ = NULL;
}

- (void)drawSeparatorWithBounds:(NSRect)bounds {
  [[self separatorColor] set];
  [NSBezierPath fillRect:bounds];
}

// A slight optimization for drawing:
// https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaViewsGuide/Optimizing/Optimizing.html
- (BOOL)isOpaque {
  return YES;
}

- (BOOL)isFlipped {
  // Flipped so that it's easier to share controller logic with other OSes.
  return YES;
}

- (void)drawBackgroundAndBorder {
  // The inset is needed since the border is centered on the |path|.
  // TODO(isherman): We should consider using asset-based drawing for the
  // border, creating simple bitmaps for the view's border and background, and
  // drawing them using NSDrawNinePartImage().
  CGFloat inset = autofill::kPopupBorderThickness / 2.0;
  NSRect borderRect = NSInsetRect([self bounds], inset, inset);
  NSBezierPath* path = [NSBezierPath bezierPathWithRect:borderRect];
  [[self backgroundColor] setFill];
  [path fill];
  [path setLineWidth:autofill::kPopupBorderThickness];
  [[self borderColor] setStroke];
  [path stroke];
}

- (void)mouseUp:(NSEvent*)theEvent {
  // If the view is in the process of being destroyed, abort.
  if (!popup_delegate_)
    return;

  // Only accept single-click.
  if ([theEvent clickCount] > 1)
    return;

  NSPoint location = [self convertPoint:[theEvent locationInWindow]
                               fromView:nil];

  if (NSPointInRect(location, [self bounds])) {
    popup_delegate_->SetSelectionAtPoint(
        gfx::Point(NSPointToCGPoint(location)));
    popup_delegate_->AcceptSelectedLine();
  }
}

- (void)mouseMoved:(NSEvent*)theEvent {
  // If the view is in the process of being destroyed, abort.
  if (!popup_delegate_)
    return;

  NSPoint location = [self convertPoint:[theEvent locationInWindow]
                               fromView:nil];

  popup_delegate_->SetSelectionAtPoint(gfx::Point(NSPointToCGPoint(location)));
}

- (void)mouseDragged:(NSEvent*)theEvent {
  [self mouseMoved:theEvent];
}

- (void)mouseExited:(NSEvent*)theEvent {
  // If the view is in the process of being destroyed, abort.
  if (!popup_delegate_)
    return;

  popup_delegate_->SelectionCleared();
}

#pragma mark -
#pragma mark Messages from AutofillPopupViewBridge:

- (void)updateBoundsAndRedrawPopup {
  NSRect frame = NSRectFromCGRect(popup_delegate_->popup_bounds().ToCGRect());

  // Flip coordinates back into Cocoa-land.  The controller's platform-neutral
  // coordinate space places the origin at the top-left of the first screen,
  // whereas Cocoa's coordinate space expects the origin to be at the
  // bottom-left of this same screen.
  NSScreen* screen = [[NSScreen screens] firstObject];
  frame.origin.y = NSMaxY([screen frame]) - NSMaxY(frame);

  // TODO(isherman): The view should support scrolling if the popup gets too
  // big to fit on the screen.
  [[self window] setFrame:frame display:YES];
  [self setNeedsDisplay:YES];
}

- (void)showPopup {
  NSWindow* window =
      [[NSWindow alloc] initWithContentRect:ui::kWindowSizeDeterminedLater
                                  styleMask:NSBorderlessWindowMask
                                    backing:NSBackingStoreBuffered
                                      defer:NO];
  [window setContentView:self];

  // Telling Cocoa that the window is opaque enables some drawing optimizations.
  [window setOpaque:YES];

  [self updateBoundsAndRedrawPopup];
  [[popup_delegate_->container_view() window] addChildWindow:window
                                                     ordered:NSWindowAbove];
}

- (void)hidePopup {
  // Remove the child window before closing, otherwise it can mess up
  // display ordering.
  NSWindow* window = [self window];
  [[window parentWindow] removeChildWindow:window];
  [window close];
}

@end