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

Side by Side Diff: chrome/browser/cocoa/bookmark_bubble_controller.mm

Issue 333017: Fixes up bookmark bubbles and the browser window so that they shut down corre... (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
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "app/l10n_util_mac.h" 5 #include "app/l10n_util_mac.h"
6 #include "base/mac_util.h" 6 #include "base/mac_util.h"
7 #include "base/sys_string_conversions.h" 7 #include "base/sys_string_conversions.h"
8 #include "chrome/browser/bookmarks/bookmark_model.h" 8 #include "chrome/browser/bookmarks/bookmark_model.h"
9 #import "chrome/browser/cocoa/bookmark_bubble_controller.h" 9 #import "chrome/browser/cocoa/bookmark_bubble_controller.h"
10 #import "chrome/browser/cocoa/bookmark_bubble_window.h" 10 #import "chrome/browser/cocoa/bookmark_bubble_window.h"
11 #include "chrome/browser/metrics/user_metrics.h" 11 #include "chrome/browser/metrics/user_metrics.h"
12 #include "grit/generated_resources.h" 12 #include "grit/generated_resources.h"
13 13
14
15 @interface BookmarkBubbleController(PrivateAPI)
16 - (void)closeWindow;
17 @end
18
19 @implementation BookmarkBubbleController 14 @implementation BookmarkBubbleController
20 15
21 @synthesize delegate = delegate_;
22 @synthesize folderComboBox = folderComboBox_;
23
24 - (id)initWithDelegate:(id<BookmarkBubbleControllerDelegate>)delegate 16 - (id)initWithDelegate:(id<BookmarkBubbleControllerDelegate>)delegate
25 parentWindow:(NSWindow*)parentWindow 17 parentWindow:(NSWindow*)parentWindow
26 topLeftForBubble:(NSPoint)topLeftForBubble 18 topLeftForBubble:(NSPoint)topLeftForBubble
27 model:(BookmarkModel*)model 19 model:(BookmarkModel*)model
28 node:(const BookmarkNode*)node 20 node:(const BookmarkNode*)node
29 alreadyBookmarked:(BOOL)alreadyBookmarked { 21 alreadyBookmarked:(BOOL)alreadyBookmarked {
30 if ((self = [super initWithNibName:@"BookmarkBubble" 22 NSString* nibPath =
31 bundle:mac_util::MainAppBundle()])) { 23 [mac_util::MainAppBundle() pathForResource:@"BookmarkBubble"
32 // All these are weak... 24 ofType:@"nib"];
25 if ((self = [super initWithWindowNibPath:nibPath owner:self])) {
33 delegate_ = delegate; 26 delegate_ = delegate;
34 parentWindow_ = parentWindow; 27 parentWindow_ = parentWindow;
35 topLeftForBubble_ = topLeftForBubble; 28 topLeftForBubble_ = topLeftForBubble;
36 model_ = model; 29 model_ = model;
37 node_ = node; 30 node_ = node;
38 alreadyBookmarked_ = alreadyBookmarked; 31 alreadyBookmarked_ = alreadyBookmarked;
39 // But this is strong. 32 // But this is strong.
40 titleMapping_.reset([[NSMutableDictionary alloc] init]); 33 titleMapping_.reset([[NSMutableDictionary alloc] init]);
41 } 34 }
42 return self; 35 return self;
43 } 36 }
44 37
45 - (void)dealloc { 38 - (void)windowWillClose:(NSNotification *)notification {
46 [self closeWindow]; 39 [self autorelease];
47 [super dealloc];
48 } 40 }
49 41
50 - (void)showWindow { 42 - (void)windowDidLoad {
51 [self view]; // force nib load and window_ allocation 43 NSWindow* window = [self window];
52 [window_ makeKeyAndOrderFront:self]; 44 NSPoint origin = [parentWindow_ convertBaseToScreen:topLeftForBubble_];
53 } 45 origin.y -= NSHeight([window frame]);
54 46 [window setFrameOrigin:origin];
55 // Actually close the window. Do nothing else. 47 [parentWindow_ addChildWindow:window ordered:NSWindowAbove];
56 - (void)closeWindow {
57 [parentWindow_ removeChildWindow:window_];
58 [window_ close];
59 }
60
61 - (void)awakeFromNib {
62 window_.reset([self createBubbleWindow]);
63 [parentWindow_ addChildWindow:window_ ordered:NSWindowAbove];
64
65 // Fill in inital values for text, controls, ...
66
67 // Default is IDS_BOOMARK_BUBBLE_PAGE_BOOKMARK; "Bookmark". 48 // Default is IDS_BOOMARK_BUBBLE_PAGE_BOOKMARK; "Bookmark".
68 // If adding for the 1st time the string becomes "Bookmark Added!" 49 // If adding for the 1st time the string becomes "Bookmark Added!"
69 if (!alreadyBookmarked_) { 50 if (!alreadyBookmarked_) {
70 NSString* title = 51 NSString* title =
71 l10n_util::GetNSString(IDS_BOOMARK_BUBBLE_PAGE_BOOKMARKED); 52 l10n_util::GetNSString(IDS_BOOMARK_BUBBLE_PAGE_BOOKMARKED);
72 [bigTitle_ setStringValue:title]; 53 [bigTitle_ setStringValue:title];
73 } 54 }
74 55
75 [self fillInFolderList]; 56 [self fillInFolderList];
76 } 57 }
77 58
59 - (void)close {
60 [parentWindow_ removeChildWindow:[self window]];
61 [super close];
62 }
63
78 // Shows the bookmark editor sheet for more advanced editing. 64 // Shows the bookmark editor sheet for more advanced editing.
79 - (void)showEditor { 65 - (void)showEditor {
80 [self updateBookmarkNode]; 66 [self updateBookmarkNode];
81 [self closeWindow];
82 [delegate_ editBookmarkNode:node_]; 67 [delegate_ editBookmarkNode:node_];
83 [delegate_ doneWithBubbleController:self]; 68 [self close];
84 } 69 }
85 70
86 - (IBAction)edit:(id)sender { 71 - (IBAction)edit:(id)sender {
87 UserMetrics::RecordAction(L"BookmarkBubble_Edit", model_->profile()); 72 UserMetrics::RecordAction(L"BookmarkBubble_Edit", model_->profile());
88 [self showEditor]; 73 [self showEditor];
89 } 74 }
90 75
91 - (IBAction)close:(id)sender { 76 - (IBAction)ok:(id)sender {
92 if (node_) { 77 [self updateBookmarkNode];
93 // no node_ if the bookmark was just removed 78 [self close];
94 [self updateBookmarkNode];
95 }
96 [self closeWindow];
97 [delegate_ doneWithBubbleController:self];
98 } 79 }
99 80
100 // By implementing this, ESC causes the window to go away. If clicking the 81 // By implementing this, ESC causes the window to go away. If clicking the
101 // star was what prompted this bubble to appear (i.e., not already bookmarked), 82 // star was what prompted this bubble to appear (i.e., not already bookmarked),
102 // remove the bookmark. 83 // remove the bookmark.
103 - (IBAction)cancel:(id)sender { 84 - (IBAction)cancel:(id)sender {
104 if (!alreadyBookmarked_) { 85 if (!alreadyBookmarked_) {
105 // |-remove:| calls |-close| so we don't have to bother. 86 // |-remove:| calls |-close| so we don't have to bother.
106 [self remove:sender]; 87 [self remove:sender];
107 } else { 88 } else {
108 [self close:sender]; 89 [self ok:sender];
Scott Hess - ex-Googler 2009/10/26 19:45:21 Having -cancel: call -close: made reasonable sense
109 } 90 }
110 } 91 }
111 92
112 - (IBAction)remove:(id)sender { 93 - (IBAction)remove:(id)sender {
113 model_->SetURLStarred(node_->GetURL(), node_->GetTitle(), false); 94 model_->SetURLStarred(node_->GetURL(), node_->GetTitle(), false);
114 UserMetrics::RecordAction(L"BookmarkBubble_Unstar", model_->profile()); 95 UserMetrics::RecordAction(L"BookmarkBubble_Unstar", model_->profile());
115 node_ = NULL; // no longer valid 96 node_ = NULL; // no longer valid
116 [self close:self]; 97 [self ok:sender];
Scott Hess - ex-Googler 2009/10/26 19:45:21 Same here, -ok: feels odd.
117 } 98 }
118 99
119 // We are the delegate of the combo box so we can tell when "choose 100 // We are the delegate of the combo box so we can tell when "choose
120 // another folder" was picked. 101 // another folder" was picked.
121 - (void)comboBoxSelectionDidChange:(NSNotification*)notification { 102 - (void)comboBoxSelectionDidChange:(NSNotification*)notification {
122 NSString* selected = [folderComboBox_ objectValueOfSelectedItem]; 103 NSString* selected = [folderComboBox_ objectValueOfSelectedItem];
123 if ([selected isEqual:chooseAnotherFolder_.get()]) { 104 if ([selected isEqual:chooseAnotherFolder_.get()]) {
124 UserMetrics::RecordAction(L"BookmarkBubble_EditFromCombobox", 105 UserMetrics::RecordAction(L"BookmarkBubble_EditFromCombobox",
125 model_->profile()); 106 model_->profile());
126 [self showEditor]; 107 [self showEditor];
127 } 108 }
128 } 109 }
129 110
130 // We are the delegate of our own window so we know when we lose key. 111 // We are the delegate of our own window so we know when we lose key.
131 // When we lose key status we close, mirroring Windows behaivor. 112 // When we lose key status we close, mirroring Windows behavior.
132 - (void)windowDidResignKey:(NSNotification*)notification { 113 - (void)windowDidResignKey:(NSNotification*)notification {
114 DCHECK_EQ([notification object], [self window]);
133 115
134 // If we get here, we are done with this window and controller. The 116 // Can't call close from within a window delegate method. We can call
135 // call of close: may destroy us which destroys the window. But the 117 // close after it's finished though. So this will call close for us next
136 // window is in the middle of processing resignKeyWindow. We 118 // time through the event loop.
137 // retain/autorelease the window to insure it lasts until the end of 119 [self performSelector:@selector(ok:) withObject:self afterDelay:0];
138 // this event.
139 [[window_ retain] autorelease];
140
141 if ([window_ isVisible])
142 [self close:self];
143 } 120 }
144 121
145 @end // BookmarkBubbleController 122 @end // BookmarkBubbleController
146 123
147 124
148 @implementation BookmarkBubbleController(ExposedForUnitTesting) 125 @implementation BookmarkBubbleController(ExposedForUnitTesting)
149 126
150 // Create and return a retained NSWindow for this bubble.
151 - (NSWindow*)createBubbleWindow {
152 NSRect contentRect = [[self view] frame];
153 NSPoint origin = topLeftForBubble_;
154 origin.y -= contentRect.size.height; // since it'll be our bottom-left
155 contentRect.origin = origin;
156 // Now convert to global coordinates since it'll be used for a window.
157 contentRect.origin = [parentWindow_ convertBaseToScreen:contentRect.origin];
158 NSWindow* window = [[BookmarkBubbleWindow alloc]
159 initWithContentRect:contentRect];
160 [window setDelegate:self];
161 [window setContentView:[self view]];
162 return window;
163 }
164 127
165 // Fill in all information related to the folder combo box. 128 // Fill in all information related to the folder combo box.
166 // 129 //
167 // TODO(jrg): make sure nested folders that have the same name are 130 // TODO(jrg): make sure nested folders that have the same name are
168 // handled properly. 131 // handled properly.
169 // http://crbug.com/19408 132 // http://crbug.com/19408
170 - (void)fillInFolderList { 133 - (void)fillInFolderList {
171 [nameTextField_ setStringValue:base::SysWideToNSString(node_->GetTitle())]; 134 [nameTextField_ setStringValue:base::SysWideToNSString(node_->GetTitle())];
172 [self addFolderNodes:model_->root_node() toComboBox:folderComboBox_]; 135 [self addFolderNodes:model_->root_node() toComboBox:folderComboBox_];
173 136
174 // Add "Choose another folder...". Remember it for later to compare against. 137 // Add "Choose another folder...". Remember it for later to compare against.
175 chooseAnotherFolder_.reset( 138 chooseAnotherFolder_.reset(
176 [l10n_util::GetNSStringWithFixup(IDS_BOOMARK_BUBBLE_CHOOSER_ANOTHER_FOLDER) 139 [l10n_util::GetNSStringWithFixup(IDS_BOOMARK_BUBBLE_CHOOSER_ANOTHER_FOLDER)
177 retain]); 140 retain]);
178 [folderComboBox_ addItemWithObjectValue:chooseAnotherFolder_.get()]; 141 [folderComboBox_ addItemWithObjectValue:chooseAnotherFolder_.get()];
179 142
180 // Finally, select the current parent. 143 // Finally, select the current parent.
181 NSString* parentTitle = base::SysWideToNSString( 144 NSString* parentTitle = base::SysWideToNSString(
182 node_->GetParent()->GetTitle()); 145 node_->GetParent()->GetTitle());
183 [folderComboBox_ selectItemWithObjectValue:parentTitle]; 146 [folderComboBox_ selectItemWithObjectValue:parentTitle];
184 } 147 }
185 148
186 - (BOOL)windowHasBeenClosed {
187 return ![window_ isVisible];
188 }
189
190 // For the given folder node, walk the tree and add folder names to 149 // For the given folder node, walk the tree and add folder names to
191 // the given combo box. 150 // the given combo box.
192 // 151 //
193 // TODO(jrg): no distinction is made among folders with the same name. 152 // TODO(jrg): no distinction is made among folders with the same name.
194 - (void)addFolderNodes:(const BookmarkNode*)parent toComboBox:(NSComboBox*)box { 153 - (void)addFolderNodes:(const BookmarkNode*)parent toComboBox:(NSComboBox*)box {
195 NSString* title = base::SysWideToNSString(parent->GetTitle()); 154 NSString* title = base::SysWideToNSString(parent->GetTitle());
196 if ([title length]) { // no title if root 155 if ([title length]) { // no title if root
197 [box addItemWithObjectValue:title]; 156 [box addItemWithObjectValue:title];
198 [titleMapping_ setValue:[NSValue valueWithPointer:parent] forKey:title]; 157 [titleMapping_ setValue:[NSValue valueWithPointer:parent] forKey:title];
199 } 158 }
200 for (int i = 0; i < parent->GetChildCount(); i++) { 159 for (int i = 0; i < parent->GetChildCount(); i++) {
201 const BookmarkNode* child = parent->GetChild(i); 160 const BookmarkNode* child = parent->GetChild(i);
202 if (child->is_folder()) 161 if (child->is_folder())
203 [self addFolderNodes:child toComboBox:box]; 162 [self addFolderNodes:child toComboBox:box];
204 } 163 }
205 } 164 }
206 165
207 // Look at the dialog; if the user has changed anything, update the 166 // Look at the dialog; if the user has changed anything, update the
208 // bookmark node to reflect this. 167 // bookmark node to reflect this.
209 - (void)updateBookmarkNode { 168 - (void)updateBookmarkNode {
169 if (!node_) return;
170
210 // First the title... 171 // First the title...
211 NSString* oldTitle = base::SysWideToNSString(node_->GetTitle()); 172 NSString* oldTitle = base::SysWideToNSString(node_->GetTitle());
212 NSString* newTitle = [nameTextField_ stringValue]; 173 NSString* newTitle = [nameTextField_ stringValue];
213 if (![oldTitle isEqual:newTitle]) { 174 if (![oldTitle isEqual:newTitle]) {
214 model_->SetTitle(node_, base::SysNSStringToWide(newTitle)); 175 model_->SetTitle(node_, base::SysNSStringToWide(newTitle));
215 UserMetrics::RecordAction(L"BookmarkBubble_ChangeTitleInBubble", 176 UserMetrics::RecordAction(L"BookmarkBubble_ChangeTitleInBubble",
216 model_->profile()); 177 model_->profile());
217 } 178 }
218 // Then the parent folder. 179 // Then the parent folder.
219 NSString* oldParentTitle = base::SysWideToNSString( 180 NSString* oldParentTitle = base::SysWideToNSString(
(...skipping 14 matching lines...) Expand all
234 195
235 - (void)setTitle:(NSString*)title parentFolder:(NSString*)folder { 196 - (void)setTitle:(NSString*)title parentFolder:(NSString*)folder {
236 [nameTextField_ setStringValue:title]; 197 [nameTextField_ setStringValue:title];
237 [folderComboBox_ selectItemWithObjectValue:folder]; 198 [folderComboBox_ selectItemWithObjectValue:folder];
238 } 199 }
239 200
240 - (NSString*)chooseAnotherFolderString { 201 - (NSString*)chooseAnotherFolderString {
241 return chooseAnotherFolder_.get(); 202 return chooseAnotherFolder_.get();
242 } 203 }
243 204
205 - (NSComboBox*)folderComboBox {
206 return folderComboBox_;
207 }
208
244 @end // implementation BookmarkBubbleController(ExposedForUnitTesting) 209 @end // implementation BookmarkBubbleController(ExposedForUnitTesting)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698