Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(670)

Side by Side Diff: chrome/browser/cocoa/extensions/extension_popup_controller.mm

Issue 402077: Adds popups to browser actions, completing the feature.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2009 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/cocoa/extensions/extension_popup_controller.h"
6
7 #include <algorithm>
8
9 #include "chrome/browser/browser.h"
10 #import "chrome/browser/cocoa/browser_window_cocoa.h"
11 #import "chrome/browser/cocoa/extension_view_mac.h"
12 #import "chrome/browser/cocoa/info_bubble_window.h"
13 #include "chrome/browser/profile.h"
14
15 // The minimum/maximum dimensions of the popup.
16 // The minimum is just a little larger than the size of the button itself.
17 // The maximum is an arbitrary number that should be smaller than most screens.
18 namespace {
19 const CGFloat kMinWidth = 25;
20 const CGFloat kMinHeight = 25;
21 const CGFloat kMaxWidth = 800;
22 const CGFloat kMaxHeight = 600;
23 } // namespace
24
25 @interface ExtensionPopupController(Private)
26 // Callers should be using the public static method for initialization.
27 // NOTE: This takes ownership of |host|.
28 - (id)initWithHost:(ExtensionHost*)host
29 parentWindow:(NSWindow*)parentWindow
30 anchoredAt:(NSPoint)anchoredAt
31 arrowLocation:(BubbleArrowLocation)arrowLocation;
32
33 // Called when the extension's hosted NSView has been resized.
34 - (void)extensionViewFrameChanged;
35 @end
36
37 @implementation ExtensionPopupController
38
39 - (id)initWithHost:(ExtensionHost*)host
40 parentWindow:(NSWindow*)parentWindow
41 anchoredAt:(NSPoint)anchoredAt
42 arrowLocation:(BubbleArrowLocation)arrowLocation {
43 parentWindow_ = parentWindow;
44 anchor_ = anchoredAt;
45 host_.reset(host);
46
47 scoped_nsobject<InfoBubbleView> view([[InfoBubbleView alloc] init]);
48 if (!view.get())
49 return nil;
50 [view setArrowLocation:arrowLocation];
51 [view setBubbleType:kWhiteInfoBubble];
52
53 host->view()->set_is_toolstrip(NO);
54
55 extensionView_ = host->view()->native_view();
56 [[NSNotificationCenter defaultCenter]
57 addObserver:self
58 selector:@selector(extensionViewFrameChanged)
59 name:NSViewFrameDidChangeNotification
60 object:extensionView_];
61
62 [view addSubview:extensionView_];
63 scoped_nsobject<InfoBubbleWindow> window(
64 [[InfoBubbleWindow alloc]
65 initWithContentRect:NSZeroRect
66 styleMask:NSBorderlessWindowMask
67 backing:NSBackingStoreBuffered
68 defer:YES]);
69 if (!window.get())
70 return nil;
71
72 [window setDelegate:self];
73 [window setContentView:view];
74 self = [super initWithWindow:window];
75
76 return self;
77 }
78
79 - (void)dealloc {
80 [[NSNotificationCenter defaultCenter] removeObserver:self];
81 [super dealloc];
82 }
83
84 - (void)windowWillClose:(NSNotification *)notification {
85 [self autorelease];
86 }
87
88 - (ExtensionHost*)host {
89 return host_.get();
90 }
91
92 - (void)windowDidResignKey:(NSNotification *)notification {
93 DCHECK_EQ([notification object], [self window]);
94 [self close];
95 }
96
97 - (void)close {
98 [parentWindow_ removeChildWindow:[self window]];
99 [super close];
100 }
101
102 + (ExtensionPopupController*)showURL:(GURL)url
103 inBrowser:(Browser*)browser
104 anchoredAt:(NSPoint)anchoredAt
105 arrowLocation:(BubbleArrowLocation)arrowLocation {
106 DCHECK(browser);
107 if (!browser)
108 return nil;
109
110 ExtensionProcessManager* manager =
111 browser->profile()->GetExtensionProcessManager();
112 DCHECK(manager);
113 if (!manager)
114 return nil;
115
116 ExtensionHost* host = manager->CreatePopup(url, browser);
117 DCHECK(host);
118 if (!host)
119 return nil;
120
121 // Takes ownership of |host|. Also will autorelease itself when the popup is
122 // closed, so no need to do that here.
123 ExtensionPopupController* popup = [[ExtensionPopupController alloc]
124 initWithHost:host
125 parentWindow:browser->window()->GetNativeHandle()
126 anchoredAt:anchoredAt
127 arrowLocation:arrowLocation];
128
129 return popup;
130 }
131
132 - (void)extensionViewFrameChanged {
133 // Constrain the size of the view.
134 [extensionView_ setFrameSize:NSMakeSize(
135 std::max(kMinWidth, std::min(kMaxWidth, NSWidth([extensionView_ frame]))),
136 std::max(kMinHeight,
137 std::min(kMaxHeight, NSHeight([extensionView_ frame]))))];
138
139 // Pad the window by half of the rounded corner radius to prevent the
140 // extension's view from bleeding out over the corners.
141 CGFloat inset = kBubbleCornerRadius / 2.0;
142 [extensionView_ setFrameOrigin:NSMakePoint(inset, inset)];
143
144 NSRect frame = [extensionView_ frame];
145 frame.size.height += kBubbleArrowHeight + kBubbleCornerRadius;
146 frame.size.width += kBubbleCornerRadius;
147 // Adjust the origin according to the height and width so that the arrow is
148 // positioned correctly at the middle and slightly down from the button.
149 NSPoint windowOrigin = anchor_;
150 windowOrigin.x -= NSWidth(frame) - kBubbleArrowXOffset -
151 (kBubbleArrowWidth / 2.0);
152 windowOrigin.y -= NSHeight(frame) - (kBubbleArrowHeight / 2.0);
153 frame.origin = windowOrigin;
154 [[self window] setFrame:frame display:YES];
155
156 // A NSViewFrameDidChangeNotification won't be sent until the extension view
157 // content is loaded. The window is hidden on init, so show it the first time
158 // the notification is fired (and consequently the view contents have loaded).
159 //
160 // TODO(andybons): It seems that if the frame changes again before the
161 // animation of the window show is completed, the window size gets super
162 // janky. Fix this.
163 if (![[self window] isVisible]) {
164 [self showWindow:self];
165 }
166 }
167
168 // We want this to be a child of a browser window. addChildWindow: (called from
169 // this function) will bring the window on-screen; unfortunately,
170 // [NSWindowController showWindow:] will also bring it on-screen (but will cause
171 // unexpected changes to the window's position). We cannot have an
172 // addChildWindow: and a subsequent showWindow:. Thus, we have our own version.
173 - (void)showWindow:(id)sender {
174 [parentWindow_ addChildWindow:[self window] ordered:NSWindowAbove];
175 [[self window] makeKeyAndOrderFront:self];
176 }
177
178 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698