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

Side by Side Diff: chrome/browser/ui/cocoa/find_bar_cocoa_controller.mm

Issue 6366001: [Mac] Move the associated find bar files into a subdir of c/b/ui/cocoa/... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 11 months 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
(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 <Cocoa/Cocoa.h>
6
7 #include "base/mac/mac_util.h"
8 #include "base/sys_string_conversions.h"
9 #include "chrome/browser/renderer_host/render_view_host.h"
10 #include "chrome/browser/tab_contents/tab_contents.h"
11 #include "chrome/browser/ui/cocoa/browser_window_cocoa.h"
12 #import "chrome/browser/ui/cocoa/find_bar_cocoa_controller.h"
13 #import "chrome/browser/ui/cocoa/find_bar_bridge.h"
14 #import "chrome/browser/ui/cocoa/find_bar_text_field.h"
15 #import "chrome/browser/ui/cocoa/find_bar_text_field_cell.h"
16 #import "chrome/browser/ui/cocoa/find_pasteboard.h"
17 #import "chrome/browser/ui/cocoa/focus_tracker.h"
18 #import "chrome/browser/ui/cocoa/tab_strip_controller.h"
19 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
20 #import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h"
21
22 namespace {
23 const float kFindBarOpenDuration = 0.2;
24 const float kFindBarCloseDuration = 0.15;
25 }
26
27 @interface FindBarCocoaController (PrivateMethods)
28 // Returns the appropriate frame for a hidden find bar.
29 - (NSRect)hiddenFindBarFrame;
30
31 // Sets the frame of |findBarView_|. |duration| is ignored if |animate| is NO.
32 - (void)setFindBarFrame:(NSRect)endFrame
33 animate:(BOOL)animate
34 duration:(float)duration;
35
36 // Optionally stops the current search, puts |text| into the find bar, and
37 // enables the buttons, but doesn't start a new search for |text|.
38 - (void)prepopulateText:(NSString*)text stopSearch:(BOOL)stopSearch;
39 @end
40
41 @implementation FindBarCocoaController
42
43 - (id)init {
44 if ((self = [super initWithNibName:@"FindBar"
45 bundle:base::mac::MainAppBundle()])) {
46 [[NSNotificationCenter defaultCenter]
47 addObserver:self
48 selector:@selector(findPboardUpdated:)
49 name:kFindPasteboardChangedNotification
50 object:[FindPasteboard sharedInstance]];
51 }
52 return self;
53 }
54
55 - (void)dealloc {
56 // All animations should be explicitly stopped by the TabContents before a tab
57 // is closed.
58 DCHECK(!currentAnimation_.get());
59 [[NSNotificationCenter defaultCenter] removeObserver:self];
60 [super dealloc];
61 }
62
63 - (void)setFindBarBridge:(FindBarBridge*)findBarBridge {
64 DCHECK(!findBarBridge_); // should only be called once.
65 findBarBridge_ = findBarBridge;
66 }
67
68 - (void)awakeFromNib {
69 [findBarView_ setFrame:[self hiddenFindBarFrame]];
70
71 // Stopping the search requires a findbar controller, which isn't valid yet
72 // during setup. Furthermore, there is no active search yet anyway.
73 [self prepopulateText:[[FindPasteboard sharedInstance] findText]
74 stopSearch:NO];
75 }
76
77 - (IBAction)close:(id)sender {
78 if (findBarBridge_)
79 findBarBridge_->GetFindBarController()->EndFindSession(
80 FindBarController::kKeepSelection);
81 }
82
83 - (IBAction)previousResult:(id)sender {
84 if (findBarBridge_)
85 findBarBridge_->GetFindBarController()->tab_contents()->StartFinding(
86 base::SysNSStringToUTF16([findText_ stringValue]),
87 false, false);
88 }
89
90 - (IBAction)nextResult:(id)sender {
91 if (findBarBridge_)
92 findBarBridge_->GetFindBarController()->tab_contents()->StartFinding(
93 base::SysNSStringToUTF16([findText_ stringValue]),
94 true, false);
95 }
96
97 - (void)findPboardUpdated:(NSNotification*)notification {
98 if (suppressPboardUpdateActions_)
99 return;
100 [self prepopulateText:[[FindPasteboard sharedInstance] findText]
101 stopSearch:YES];
102 }
103
104 - (void)positionFindBarViewAtMaxY:(CGFloat)maxY maxWidth:(CGFloat)maxWidth {
105 static const CGFloat kRightEdgeOffset = 25;
106 NSView* containerView = [self view];
107 CGFloat containerHeight = NSHeight([containerView frame]);
108 CGFloat containerWidth = NSWidth([containerView frame]);
109
110 // Adjust where we'll actually place the find bar.
111 CGFloat maxX = maxWidth - kRightEdgeOffset;
112 DLOG_IF(WARNING, maxX < 0) << "Window too narrow for find bar";
113 maxY += 1;
114
115 NSRect newFrame = NSMakeRect(maxX - containerWidth, maxY - containerHeight,
116 containerWidth, containerHeight);
117 [containerView setFrame:newFrame];
118 }
119
120 // NSControl delegate method.
121 - (void)controlTextDidChange:(NSNotification *)aNotification {
122 if (!findBarBridge_)
123 return;
124
125 TabContents* tab_contents =
126 findBarBridge_->GetFindBarController()->tab_contents();
127 if (!tab_contents)
128 return;
129
130 NSString* findText = [findText_ stringValue];
131 suppressPboardUpdateActions_ = YES;
132 [[FindPasteboard sharedInstance] setFindText:findText];
133 suppressPboardUpdateActions_ = NO;
134
135 if ([findText length] > 0) {
136 tab_contents->StartFinding(base::SysNSStringToUTF16(findText), true, false);
137 } else {
138 // The textbox is empty so we reset.
139 tab_contents->StopFinding(FindBarController::kClearSelection);
140 [self updateUIForFindResult:tab_contents->find_result()
141 withText:string16()];
142 }
143 }
144
145 // NSControl delegate method
146 - (BOOL)control:(NSControl*)control
147 textView:(NSTextView*)textView
148 doCommandBySelector:(SEL)command {
149 if (command == @selector(insertNewline:)) {
150 // Pressing Return
151 NSEvent* event = [NSApp currentEvent];
152
153 if ([event modifierFlags] & NSShiftKeyMask)
154 [previousButton_ performClick:nil];
155 else
156 [nextButton_ performClick:nil];
157
158 return YES;
159 } else if (command == @selector(insertLineBreak:)) {
160 // Pressing Ctrl-Return
161 if (findBarBridge_) {
162 findBarBridge_->GetFindBarController()->EndFindSession(
163 FindBarController::kActivateSelection);
164 }
165 return YES;
166 } else if (command == @selector(pageUp:) ||
167 command == @selector(pageUpAndModifySelection:) ||
168 command == @selector(scrollPageUp:) ||
169 command == @selector(pageDown:) ||
170 command == @selector(pageDownAndModifySelection:) ||
171 command == @selector(scrollPageDown:) ||
172 command == @selector(scrollToBeginningOfDocument:) ||
173 command == @selector(scrollToEndOfDocument:) ||
174 command == @selector(moveUp:) ||
175 command == @selector(moveDown:)) {
176 TabContents* contents =
177 findBarBridge_->GetFindBarController()->tab_contents();
178 if (!contents)
179 return NO;
180
181 // Sanity-check to make sure we got a keyboard event.
182 NSEvent* event = [NSApp currentEvent];
183 if ([event type] != NSKeyDown && [event type] != NSKeyUp)
184 return NO;
185
186 // Forward the event to the renderer.
187 // TODO(rohitrao): Should this call -[BaseView keyEvent:]? Is there code in
188 // that function that we want to keep or avoid? Calling
189 // |ForwardKeyboardEvent()| directly ignores edit commands, which breaks
190 // cmd-up/down if we ever decide to include |moveToBeginningOfDocument:| in
191 // the list above.
192 RenderViewHost* render_view_host = contents->render_view_host();
193 render_view_host->ForwardKeyboardEvent(NativeWebKeyboardEvent(event));
194 return YES;
195 }
196
197 return NO;
198 }
199
200 // Methods from FindBar
201 - (void)showFindBar:(BOOL)animate {
202 // Save the currently-focused view. |findBarView_| is in the view
203 // hierarchy by now. showFindBar can be called even when the
204 // findbar is already open, so do not overwrite an already saved
205 // view.
206 if (!focusTracker_.get())
207 focusTracker_.reset(
208 [[FocusTracker alloc] initWithWindow:[findBarView_ window]]);
209
210 // Animate the view into place.
211 NSRect frame = [findBarView_ frame];
212 frame.origin = NSMakePoint(0, 0);
213 [self setFindBarFrame:frame animate:animate duration:kFindBarOpenDuration];
214 }
215
216 - (void)hideFindBar:(BOOL)animate {
217 NSRect frame = [self hiddenFindBarFrame];
218 [self setFindBarFrame:frame animate:animate duration:kFindBarCloseDuration];
219 }
220
221 - (void)stopAnimation {
222 if (currentAnimation_.get()) {
223 [currentAnimation_ stopAnimation];
224 currentAnimation_.reset(nil);
225 }
226 }
227
228 - (void)setFocusAndSelection {
229 [[findText_ window] makeFirstResponder:findText_];
230
231 // Enable the buttons if the find text is non-empty.
232 BOOL buttonsEnabled = ([[findText_ stringValue] length] > 0) ? YES : NO;
233 [previousButton_ setEnabled:buttonsEnabled];
234 [nextButton_ setEnabled:buttonsEnabled];
235 }
236
237 - (void)restoreSavedFocus {
238 if (!(focusTracker_.get() &&
239 [focusTracker_ restoreFocusInWindow:[findBarView_ window]])) {
240 // Fall back to giving focus to the tab contents.
241 findBarBridge_->GetFindBarController()->tab_contents()->Focus();
242 }
243 focusTracker_.reset(nil);
244 }
245
246 - (void)setFindText:(NSString*)findText {
247 [findText_ setStringValue:findText];
248
249 // Make sure the text in the find bar always ends up in the find pasteboard
250 // (and, via notifications, in the other find bars too).
251 [[FindPasteboard sharedInstance] setFindText:findText];
252 }
253
254 - (void)clearResults:(const FindNotificationDetails&)results {
255 // Just call updateUIForFindResult, which will take care of clearing
256 // the search text and the results label.
257 [self updateUIForFindResult:results withText:string16()];
258 }
259
260 - (void)updateUIForFindResult:(const FindNotificationDetails&)result
261 withText:(const string16&)findText {
262 // If we don't have any results and something was passed in, then
263 // that means someone pressed Cmd-G while the Find box was
264 // closed. In that case we need to repopulate the Find box with what
265 // was passed in.
266 if ([[findText_ stringValue] length] == 0 && !findText.empty()) {
267 [findText_ setStringValue:base::SysUTF16ToNSString(findText)];
268 [findText_ selectText:self];
269 }
270
271 // Make sure Find Next and Find Previous are enabled if we found any matches.
272 BOOL buttonsEnabled = result.number_of_matches() > 0 ? YES : NO;
273 [previousButton_ setEnabled:buttonsEnabled];
274 [nextButton_ setEnabled:buttonsEnabled];
275
276 // Update the results label.
277 BOOL validRange = result.active_match_ordinal() != -1 &&
278 result.number_of_matches() != -1;
279 NSString* searchString = [findText_ stringValue];
280 if ([searchString length] > 0 && validRange) {
281 [[findText_ findBarTextFieldCell]
282 setActiveMatch:result.active_match_ordinal()
283 of:result.number_of_matches()];
284 } else {
285 // If there was no text entered, we don't show anything in the results area.
286 [[findText_ findBarTextFieldCell] clearResults];
287 }
288
289 [findText_ resetFieldEditorFrameIfNeeded];
290
291 // If we found any results, reset the focus tracker, so we always
292 // restore focus to the tab contents.
293 if (result.number_of_matches() > 0)
294 focusTracker_.reset(nil);
295 }
296
297 - (BOOL)isFindBarVisible {
298 // Find bar is visible if any part of it is on the screen.
299 return NSIntersectsRect([[self view] bounds], [findBarView_ frame]);
300 }
301
302 - (BOOL)isFindBarAnimating {
303 return (currentAnimation_.get() != nil);
304 }
305
306 // NSAnimation delegate methods.
307 - (void)animationDidEnd:(NSAnimation*)animation {
308 // Autorelease the animation (cannot use release because the animation object
309 // is still on the stack.
310 DCHECK(animation == currentAnimation_.get());
311 [currentAnimation_.release() autorelease];
312
313 // If the find bar is not visible, make it actually hidden, so it'll no longer
314 // respond to key events.
315 [findBarView_ setHidden:![self isFindBarVisible]];
316 }
317
318 @end
319
320 @implementation FindBarCocoaController (PrivateMethods)
321
322 - (NSRect)hiddenFindBarFrame {
323 NSRect frame = [findBarView_ frame];
324 NSRect containerBounds = [[self view] bounds];
325 frame.origin = NSMakePoint(NSMinX(containerBounds), NSMaxY(containerBounds));
326 return frame;
327 }
328
329 - (void)setFindBarFrame:(NSRect)endFrame
330 animate:(BOOL)animate
331 duration:(float)duration {
332 // Save the current frame.
333 NSRect startFrame = [findBarView_ frame];
334
335 // Stop any existing animations.
336 [currentAnimation_ stopAnimation];
337
338 if (!animate) {
339 [findBarView_ setFrame:endFrame];
340 [findBarView_ setHidden:![self isFindBarVisible]];
341 currentAnimation_.reset(nil);
342 return;
343 }
344
345 // If animating, ensure that the find bar is not hidden. Hidden status will be
346 // updated at the end of the animation.
347 [findBarView_ setHidden:NO];
348
349 // Reset the frame to what was saved above.
350 [findBarView_ setFrame:startFrame];
351 NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
352 findBarView_, NSViewAnimationTargetKey,
353 [NSValue valueWithRect:endFrame], NSViewAnimationEndFrameKey, nil];
354
355 currentAnimation_.reset(
356 [[NSViewAnimation alloc]
357 initWithViewAnimations:[NSArray arrayWithObjects:dict, nil]]);
358 [currentAnimation_ gtm_setDuration:duration
359 eventMask:NSLeftMouseUpMask];
360 [currentAnimation_ setDelegate:self];
361 [currentAnimation_ startAnimation];
362 }
363
364 - (void)prepopulateText:(NSString*)text stopSearch:(BOOL)stopSearch{
365 [self setFindText:text];
366
367 // End the find session, hide the "x of y" text and disable the
368 // buttons, but do not close the find bar or raise the window here.
369 if (stopSearch && findBarBridge_) {
370 TabContents* contents =
371 findBarBridge_->GetFindBarController()->tab_contents();
372 if (contents) {
373 contents->StopFinding(FindBarController::kClearSelection);
374 findBarBridge_->ClearResults(contents->find_result());
375 }
376 }
377
378 // Has to happen after |ClearResults()| above.
379 BOOL buttonsEnabled = [text length] > 0 ? YES : NO;
380 [previousButton_ setEnabled:buttonsEnabled];
381 [nextButton_ setEnabled:buttonsEnabled];
382 }
383
384 @end
OLDNEW
« no previous file with comments | « chrome/browser/ui/cocoa/find_bar_cocoa_controller.h ('k') | chrome/browser/ui/cocoa/find_bar_cocoa_controller_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698