Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / ui / views / find_bar_view.cc
blob2fe44998581d6c63fb3ec6dfc59cc9d0d6741700
1 // Copyright (c) 2012 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.
5 #include "chrome/browser/ui/views/find_bar_view.h"
7 #include <algorithm>
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/themes/theme_properties.h"
14 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
15 #include "chrome/browser/ui/find_bar/find_bar_state.h"
16 #include "chrome/browser/ui/find_bar/find_bar_state_factory.h"
17 #include "chrome/browser/ui/find_bar/find_notification_details.h"
18 #include "chrome/browser/ui/find_bar/find_tab_helper.h"
19 #include "chrome/browser/ui/view_ids.h"
20 #include "chrome/browser/ui/views/find_bar_host.h"
21 #include "chrome/browser/ui/views/frame/browser_view.h"
22 #include "chrome/grit/generated_resources.h"
23 #include "grit/theme_resources.h"
24 #include "third_party/skia/include/core/SkPaint.h"
25 #include "ui/base/ime/input_method.h"
26 #include "ui/base/ime/text_input_flags.h"
27 #include "ui/base/l10n/l10n_util.h"
28 #include "ui/base/resource/material_design/material_design_controller.h"
29 #include "ui/base/resource/resource_bundle.h"
30 #include "ui/base/theme_provider.h"
31 #include "ui/events/event.h"
32 #include "ui/gfx/canvas.h"
33 #include "ui/gfx/paint_vector_icon.h"
34 #include "ui/gfx/vector_icons_public.h"
35 #include "ui/native_theme/common_theme.h"
36 #include "ui/native_theme/native_theme.h"
37 #include "ui/resources/grit/ui_resources.h"
38 #include "ui/views/background.h"
39 #include "ui/views/border.h"
40 #include "ui/views/bubble/bubble_border.h"
41 #include "ui/views/controls/button/image_button.h"
42 #include "ui/views/controls/label.h"
43 #include "ui/views/controls/separator.h"
44 #include "ui/views/layout/box_layout.h"
45 #include "ui/views/painter.h"
46 #include "ui/views/view_targeter.h"
47 #include "ui/views/widget/widget.h"
49 namespace {
51 // The margins around the UI controls, derived from assets and design specs.
52 const int kMarginLeftOfCloseButton = 3;
53 const int kMarginRightOfCloseButton = 7;
54 const int kMarginLeftOfMatchCountLabel = 3;
55 const int kMarginRightOfMatchCountLabel = 1;
56 const int kMarginLeftOfFindTextfield = 12;
57 const int kMarginVerticalFindTextfield = 6;
59 // Constants for the MD layout, all in dp.
60 // The horizontal and vertical insets for the bar.
61 const int kInteriorPadding = 8;
62 // Default spacing between child views.
63 const int kInterChildSpacing = 4;
64 // Additional spacing around the separator.
65 const int kSeparatorLeftSpacing = 12 - kInterChildSpacing;
66 const int kSeparatorRightSpacing = 8 - kInterChildSpacing;
67 // Extra space around the buttons to increase their event target size.
68 const int kButtonExtraTouchSize = 4;
70 // The margins around the match count label (We add extra space so that the
71 // background highlight extends beyond just the text).
72 const int kMatchCountExtraWidth = 9;
74 // Minimum width for the match count label.
75 const int kMatchCountMinWidth = 30;
77 // The text color for the match count label.
78 const SkColor kTextColorMatchCount = SkColorSetRGB(178, 178, 178);
80 // The text color for the match count label when no matches are found.
81 const SkColor kTextColorNoMatch = SK_ColorBLACK;
83 // The background color of the match count label when results are found.
84 const SkColor kBackgroundColorMatch = SkColorSetARGB(0, 255, 255, 255);
86 // The background color of the match count label when no results are found.
87 const SkColor kBackgroundColorNoMatch = SkColorSetRGB(255, 102, 102);
89 // The color of the match count label for Material Design.
90 const SkColor kMatchTextColorMD = SkColorSetRGB(0x96, 0x96, 0x96);
92 // Color of the vertical separator between match count and buttons. (MD only.)
93 const SkColor kSeparatorColor = SkColorSetARGB(0x26, 0, 0, 0);
95 // The default number of average characters that the text box will be. This
96 // number brings the width on a "regular fonts" system to about 300px.
97 const int kDefaultCharWidth = 43;
99 // The match count label is like a normal label, but can process events (which
100 // makes it easier to forward events to the text input --- see
101 // FindBarView::TargetForRect).
102 class MatchCountLabel : public views::Label {
103 public:
104 MatchCountLabel() {}
105 ~MatchCountLabel() override {}
107 // views::Label overrides:
108 bool CanProcessEventsWithinSubtree() const override { return true; }
110 private:
111 DISALLOW_COPY_AND_ASSIGN(MatchCountLabel);
114 } // namespace
116 ////////////////////////////////////////////////////////////////////////////////
117 // FindBarView, public:
119 FindBarView::FindBarView(FindBarHost* host)
120 : DropdownBarView(host),
121 find_text_(NULL),
122 match_count_text_(NULL),
123 focus_forwarder_view_(NULL),
124 find_previous_button_(NULL),
125 find_next_button_(NULL),
126 close_button_(NULL) {
127 find_text_ = new views::Textfield;
128 find_text_->set_id(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD);
129 find_text_->set_default_width_in_chars(kDefaultCharWidth);
130 find_text_->set_controller(this);
131 find_text_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_FIND));
132 find_text_->SetTextInputFlags(ui::TEXT_INPUT_FLAG_AUTOCORRECT_OFF);
133 AddChildView(find_text_);
135 find_previous_button_ = new views::ImageButton(this);
136 find_previous_button_->set_tag(FIND_PREVIOUS_TAG);
137 find_previous_button_->SetFocusable(true);
138 find_previous_button_->SetTooltipText(
139 l10n_util::GetStringUTF16(IDS_FIND_IN_PAGE_PREVIOUS_TOOLTIP));
140 find_previous_button_->SetAccessibleName(
141 l10n_util::GetStringUTF16(IDS_ACCNAME_PREVIOUS));
142 AddChildView(find_previous_button_);
144 find_next_button_ = new views::ImageButton(this);
145 find_next_button_->set_tag(FIND_NEXT_TAG);
146 find_next_button_->SetFocusable(true);
147 find_next_button_->SetTooltipText(
148 l10n_util::GetStringUTF16(IDS_FIND_IN_PAGE_NEXT_TOOLTIP));
149 find_next_button_->SetAccessibleName(
150 l10n_util::GetStringUTF16(IDS_ACCNAME_NEXT));
151 AddChildView(find_next_button_);
153 close_button_ = new views::ImageButton(this);
154 close_button_->set_tag(CLOSE_TAG);
155 close_button_->SetFocusable(true);
156 close_button_->SetTooltipText(
157 l10n_util::GetStringUTF16(IDS_FIND_IN_PAGE_CLOSE_TOOLTIP));
158 close_button_->SetAccessibleName(
159 l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE));
160 close_button_->SetAnimationDuration(0);
161 AddChildView(close_button_);
163 EnableCanvasFlippingForRTLUI(true);
165 if (ui::MaterialDesignController::IsModeMaterial())
166 InitViewsForMaterial();
167 else
168 InitViewsForNonMaterial();
171 FindBarView::~FindBarView() {
174 void FindBarView::SetFindTextAndSelectedRange(
175 const base::string16& find_text,
176 const gfx::Range& selected_range) {
177 find_text_->SetText(find_text);
178 find_text_->SelectRange(selected_range);
181 base::string16 FindBarView::GetFindText() const {
182 return find_text_->text();
185 gfx::Range FindBarView::GetSelectedRange() const {
186 return find_text_->GetSelectedRange();
189 base::string16 FindBarView::GetFindSelectedText() const {
190 return find_text_->GetSelectedText();
193 base::string16 FindBarView::GetMatchCountText() const {
194 return match_count_text_->text();
197 void FindBarView::UpdateForResult(const FindNotificationDetails& result,
198 const base::string16& find_text) {
199 bool have_valid_range =
200 result.number_of_matches() != -1 && result.active_match_ordinal() != -1;
202 // http://crbug.com/34970: some IMEs get confused if we change the text
203 // composed by them. To avoid this problem, we should check the IME status and
204 // update the text only when the IME is not composing text.
205 if (find_text_->text() != find_text && !find_text_->IsIMEComposing()) {
206 find_text_->SetText(find_text);
207 find_text_->SelectAll(true);
210 if (find_text.empty() || !have_valid_range) {
211 // If there was no text entered, we don't show anything in the result count
212 // area.
213 ClearMatchCount();
214 return;
217 match_count_text_->SetText(l10n_util::GetStringFUTF16(IDS_FIND_IN_PAGE_COUNT,
218 base::IntToString16(result.active_match_ordinal()),
219 base::IntToString16(result.number_of_matches())));
221 UpdateMatchCountAppearance(result.number_of_matches() == 0 &&
222 result.final_update());
224 // The match_count label may have increased/decreased in size so we need to
225 // do a layout and repaint the dialog so that the find text field doesn't
226 // partially overlap the match-count label when it increases on no matches.
227 Layout();
228 SchedulePaint();
231 void FindBarView::ClearMatchCount() {
232 match_count_text_->SetText(base::string16());
233 UpdateMatchCountAppearance(false);
234 Layout();
235 SchedulePaint();
238 void FindBarView::SetFocusAndSelection(bool select_all) {
239 find_text_->RequestFocus();
240 GetWidget()->GetInputMethod()->ShowImeIfNeeded();
241 if (select_all && !find_text_->text().empty())
242 find_text_->SelectAll(true);
245 ///////////////////////////////////////////////////////////////////////////////
246 // FindBarView, views::View overrides:
248 void FindBarView::OnPaint(gfx::Canvas* canvas) {
249 if (ui::MaterialDesignController::IsModeMaterial())
250 return views::View::OnPaint(canvas);
252 // Paint drop down bar border and background.
253 DropdownBarView::OnPaint(canvas);
255 // Paint the background and border for the textfield.
256 const int find_text_x = kMarginLeftOfFindTextfield / 2;
257 const gfx::Rect text_bounds(find_text_x, find_next_button_->y(),
258 find_next_button_->bounds().right() - find_text_x,
259 find_next_button_->height());
260 const int kBorderCornerRadius = 2;
261 gfx::Rect background_bounds = text_bounds;
262 background_bounds.Inset(kBorderCornerRadius, kBorderCornerRadius);
263 SkPaint paint;
264 paint.setStyle(SkPaint::kFill_Style);
265 paint.setColor(find_text_->GetBackgroundColor());
266 canvas->DrawRoundRect(background_bounds, kBorderCornerRadius, paint);
267 canvas->Save();
268 canvas->ClipRect(gfx::Rect(0, 0, find_previous_button_->x(), height()));
269 views::Painter::PaintPainterAt(canvas, find_text_border_.get(), text_bounds);
270 canvas->Restore();
272 // Draw the background of the match text. We want to make sure the red
273 // "no-match" background almost completely fills up the amount of vertical
274 // space within the text box. We therefore fix the size relative to the button
275 // heights. We use the FindPrev button, which has a 1px outer whitespace
276 // margin, 1px border and we want to appear 1px below the border line so we
277 // subtract 3 for top and 3 for bottom.
278 gfx::Rect match_count_background_bounds(match_count_text_->bounds());
279 match_count_background_bounds.set_height(
280 find_previous_button_->height() - 6); // Subtract 3px x 2.
281 match_count_background_bounds.set_y(
282 (height() - match_count_background_bounds.height()) / 2);
283 canvas->FillRect(match_count_background_bounds,
284 match_count_text_->background_color());
287 void FindBarView::OnPaintBackground(gfx::Canvas* canvas) {
288 if (!ui::MaterialDesignController::IsModeMaterial())
289 return views::View::OnPaintBackground(canvas);
291 // Draw within the lines.
292 canvas->Save();
293 gfx::Rect bounds = GetLocalBounds();
294 bounds.Inset(border()->GetInsets());
295 canvas->ClipRect(bounds);
296 views::View::OnPaintBackground(canvas);
297 canvas->Restore();
300 void FindBarView::Layout() {
301 if (ui::MaterialDesignController::IsModeMaterial())
302 return views::View::Layout();
304 int panel_width = GetPreferredSize().width();
306 // Stay within view bounds.
307 int view_width = width();
308 if (view_width && view_width < panel_width)
309 panel_width = view_width;
311 // First we draw the close button on the far right.
312 gfx::Size sz = close_button_->GetPreferredSize();
313 close_button_->SetBounds(panel_width - sz.width() -
314 kMarginRightOfCloseButton,
315 (height() - sz.height()) / 2,
316 sz.width(),
317 sz.height());
318 // Set the color.
319 OnThemeChanged();
321 // Next, the FindNext button to the left the close button.
322 sz = find_next_button_->GetPreferredSize();
323 find_next_button_->SetBounds(close_button_->x() -
324 find_next_button_->width() -
325 kMarginLeftOfCloseButton,
326 (height() - sz.height()) / 2,
327 sz.width(),
328 sz.height());
330 // Then, the FindPrevious button to the left the FindNext button.
331 sz = find_previous_button_->GetPreferredSize();
332 find_previous_button_->SetBounds(find_next_button_->x() -
333 find_previous_button_->width(),
334 (height() - sz.height()) / 2,
335 sz.width(),
336 sz.height());
338 // Then the label showing the match count number.
339 sz = match_count_text_->GetPreferredSize();
340 // We extend the label bounds a bit to give the background highlighting a bit
341 // of breathing room (margins around the text).
342 sz.Enlarge(kMatchCountExtraWidth, 0);
343 sz.SetToMax(gfx::Size(kMatchCountMinWidth, 0));
344 const int match_count_x =
345 find_previous_button_->x() - kMarginRightOfMatchCountLabel - sz.width();
346 const int find_text_y = kMarginVerticalFindTextfield;
347 const gfx::Insets find_text_insets(find_text_->GetInsets());
348 match_count_text_->SetBounds(match_count_x,
349 find_text_y - find_text_insets.top() +
350 find_text_->GetBaseline() -
351 match_count_text_->GetBaseline(),
352 sz.width(), sz.height());
354 // Fill the remaining width and available height with the textfield.
355 const int left_margin = kMarginLeftOfFindTextfield - find_text_insets.left();
356 const int find_text_width = std::max(0, match_count_x - left_margin -
357 kMarginLeftOfMatchCountLabel + find_text_insets.right());
358 find_text_->SetBounds(left_margin, find_text_y, find_text_width,
359 height() - 2 * kMarginVerticalFindTextfield);
361 // The focus forwarder view is a hidden view that should cover the area
362 // between the find text box and the find button so that when the user clicks
363 // in that area we focus on the find text box.
364 const int find_text_edge = find_text_->x() + find_text_->width();
365 focus_forwarder_view_->SetBounds(
366 find_text_edge, find_previous_button_->y(),
367 find_previous_button_->x() - find_text_edge,
368 find_previous_button_->height());
371 gfx::Size FindBarView::GetPreferredSize() const {
372 if (ui::MaterialDesignController::IsModeMaterial()) {
373 // The entire bar is sized to a specific number of characters set on
374 // |find_text_|.
375 gfx::Size size = views::View::GetPreferredSize();
376 size.set_width(find_text_->GetPreferredSize().width());
377 return size;
380 gfx::Size prefsize = find_text_->GetPreferredSize();
381 prefsize.set_height(preferred_height_);
383 // Add up all the preferred sizes and margins of the rest of the controls.
384 prefsize.Enlarge(kMarginLeftOfCloseButton + kMarginRightOfCloseButton +
385 kMarginLeftOfFindTextfield -
386 find_text_->GetInsets().width(),
388 prefsize.Enlarge(find_previous_button_->GetPreferredSize().width(), 0);
389 prefsize.Enlarge(find_next_button_->GetPreferredSize().width(), 0);
390 prefsize.Enlarge(close_button_->GetPreferredSize().width(), 0);
391 return prefsize;
394 ////////////////////////////////////////////////////////////////////////////////
395 // FindBarView, views::ButtonListener implementation:
397 void FindBarView::ButtonPressed(
398 views::Button* sender, const ui::Event& event) {
399 switch (sender->tag()) {
400 case FIND_PREVIOUS_TAG:
401 case FIND_NEXT_TAG:
402 if (!find_text_->text().empty()) {
403 FindTabHelper* find_tab_helper = FindTabHelper::FromWebContents(
404 find_bar_host()->GetFindBarController()->web_contents());
405 find_tab_helper->StartFinding(find_text_->text(),
406 sender->tag() == FIND_NEXT_TAG,
407 false); // Not case sensitive.
409 // Move focus to the find textfield.
410 find_text_->RequestFocus();
411 break;
412 case CLOSE_TAG:
413 find_bar_host()->GetFindBarController()->EndFindSession(
414 FindBarController::kKeepSelectionOnPage,
415 FindBarController::kKeepResultsInFindBox);
416 break;
417 default:
418 NOTREACHED() << L"Unknown button";
419 break;
423 ////////////////////////////////////////////////////////////////////////////////
424 // FindBarView, views::TextfieldController implementation:
426 bool FindBarView::HandleKeyEvent(views::Textfield* sender,
427 const ui::KeyEvent& key_event) {
428 // If the dialog is not visible, there is no reason to process keyboard input.
429 if (!host()->IsVisible())
430 return false;
432 if (find_bar_host()->MaybeForwardKeyEventToWebpage(key_event))
433 return true; // Handled, we are done!
435 if (key_event.key_code() == ui::VKEY_RETURN) {
436 // Pressing Return/Enter starts the search (unless text box is empty).
437 base::string16 find_string = find_text_->text();
438 if (!find_string.empty()) {
439 FindBarController* controller = find_bar_host()->GetFindBarController();
440 FindTabHelper* find_tab_helper =
441 FindTabHelper::FromWebContents(controller->web_contents());
442 // Search forwards for enter, backwards for shift-enter.
443 find_tab_helper->StartFinding(find_string,
444 !key_event.IsShiftDown(),
445 false); // Not case sensitive.
447 return true;
450 return false;
453 void FindBarView::OnAfterUserAction(views::Textfield* sender) {
454 // The composition text wouldn't be what the user is really looking for.
455 // We delay the search until the user commits the composition text.
456 if (!sender->IsIMEComposing() && sender->text() != last_searched_text_)
457 Find(sender->text());
460 void FindBarView::OnAfterPaste() {
461 // Clear the last search text so we always search for the user input after
462 // a paste operation, even if the pasted text is the same as before.
463 // See http://crbug.com/79002
464 last_searched_text_.clear();
467 views::View* FindBarView::TargetForRect(View* root, const gfx::Rect& rect) {
468 DCHECK_EQ(match_count_text_, root);
469 return find_text_;
472 void FindBarView::InitViewsForNonMaterial() {
473 match_count_text_ = new views::Label();
474 AddChildView(match_count_text_);
476 // Create a focus forwarder view which sends focus to find_text_.
477 focus_forwarder_view_ = new FocusForwarderView(find_text_);
478 AddChildView(focus_forwarder_view_);
480 // The find bar textfield has a background image instead of a border.
481 find_text_->SetBorder(views::Border::NullBorder());
483 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
484 find_previous_button_->SetImage(views::CustomButton::STATE_NORMAL,
485 rb.GetImageSkiaNamed(IDR_FINDINPAGE_PREV));
486 find_previous_button_->SetImage(views::CustomButton::STATE_HOVERED,
487 rb.GetImageSkiaNamed(IDR_FINDINPAGE_PREV_H));
488 find_previous_button_->SetImage(views::CustomButton::STATE_PRESSED,
489 rb.GetImageSkiaNamed(IDR_FINDINPAGE_PREV_P));
490 find_previous_button_->SetImage(views::CustomButton::STATE_DISABLED,
491 rb.GetImageSkiaNamed(IDR_FINDINPAGE_PREV_D));
493 find_next_button_->SetImage(views::CustomButton::STATE_NORMAL,
494 rb.GetImageSkiaNamed(IDR_FINDINPAGE_NEXT));
495 find_next_button_->SetImage(views::CustomButton::STATE_HOVERED,
496 rb.GetImageSkiaNamed(IDR_FINDINPAGE_NEXT_H));
497 find_next_button_->SetImage(views::CustomButton::STATE_PRESSED,
498 rb.GetImageSkiaNamed(IDR_FINDINPAGE_NEXT_P));
499 find_next_button_->SetImage(views::CustomButton::STATE_DISABLED,
500 rb.GetImageSkiaNamed(IDR_FINDINPAGE_NEXT_D));
502 close_button_->SetImage(views::CustomButton::STATE_NORMAL,
503 rb.GetImageSkiaNamed(IDR_CLOSE_1));
504 close_button_->SetImage(views::CustomButton::STATE_HOVERED,
505 rb.GetImageSkiaNamed(IDR_CLOSE_1_H));
506 close_button_->SetImage(views::CustomButton::STATE_PRESSED,
507 rb.GetImageSkiaNamed(IDR_CLOSE_1_P));
509 SetBackground(rb.GetImageSkiaNamed(IDR_FIND_DLG_LEFT_BACKGROUND),
510 rb.GetImageSkiaNamed(IDR_FIND_DLG_RIGHT_BACKGROUND));
511 SetBorderFromIds(IDR_FIND_DIALOG_LEFT, IDR_FIND_DIALOG_MIDDLE,
512 IDR_FIND_DIALOG_RIGHT);
514 preferred_height_ = rb.GetImageSkiaNamed(IDR_FIND_DIALOG_MIDDLE)->height();
516 static const int kImages[] = IMAGE_GRID(IDR_TEXTFIELD);
517 find_text_border_.reset(views::Painter::CreateImageGridPainter(kImages));
520 void FindBarView::InitViewsForMaterial() {
521 // The background color is not used since there's no arrow.
522 SetBorder(make_scoped_ptr(new views::BubbleBorder(
523 views::BubbleBorder::NONE, views::BubbleBorder::SMALL_SHADOW,
524 SK_ColorGREEN)));
526 match_count_text_ = new MatchCountLabel();
527 match_count_text_->SetEventTargeter(
528 make_scoped_ptr(new views::ViewTargeter(this)));
529 AddChildViewAt(match_count_text_, 1);
531 views::Separator* separator =
532 new views::Separator(views::Separator::VERTICAL);
533 separator->SetColor(kSeparatorColor);
534 separator->SetBorder(views::Border::CreateEmptyBorder(
535 0, kSeparatorLeftSpacing, 0, kSeparatorRightSpacing));
536 AddChildViewAt(separator, 2);
538 find_text_->SetBorder(views::Border::NullBorder());
540 struct {
541 views::ImageButton* button;
542 gfx::VectorIconId id;
543 } button_images[] = {
544 {find_previous_button_, gfx::VectorIconId::FIND_PREV},
545 {find_next_button_, gfx::VectorIconId::FIND_NEXT},
546 {close_button_, gfx::VectorIconId::BAR_CLOSE},
549 SkColor grey;
550 ui::CommonThemeGetSystemColor(ui::NativeTheme::kColorId_ChromeIconGrey,
551 &grey);
552 for (size_t i = 0; i < arraysize(button_images); ++i) {
553 views::ImageButton* button = button_images[i].button;
554 button->SetBorder(views::Border::CreateEmptyBorder(
555 kButtonExtraTouchSize, kButtonExtraTouchSize, kButtonExtraTouchSize,
556 kButtonExtraTouchSize));
557 button->SetImageAlignment(views::ImageButton::ALIGN_CENTER,
558 views::ImageButton::ALIGN_MIDDLE);
560 gfx::ImageSkia image = gfx::CreateVectorIcon(button_images[i].id, 16, grey);
561 button->SetImage(views::CustomButton::STATE_NORMAL, &image);
562 image = gfx::CreateVectorIcon(button_images[i].id, 16,
563 SkColorSetA(grey, 0xff / 2));
564 button->SetImage(views::CustomButton::STATE_DISABLED, &image);
567 views::BoxLayout* manager =
568 new views::BoxLayout(views::BoxLayout::kHorizontal, kInteriorPadding,
569 kInteriorPadding, kInterChildSpacing);
570 SetLayoutManager(manager);
571 manager->SetFlexForView(find_text_, 1);
574 void FindBarView::Find(const base::string16& search_text) {
575 FindBarController* controller = find_bar_host()->GetFindBarController();
576 DCHECK(controller);
577 content::WebContents* web_contents = controller->web_contents();
578 // We must guard against a NULL web_contents, which can happen if the text
579 // in the Find box is changed right after the tab is destroyed. Otherwise, it
580 // can lead to crashes, as exposed by automation testing in issue 8048.
581 if (!web_contents)
582 return;
583 FindTabHelper* find_tab_helper = FindTabHelper::FromWebContents(web_contents);
585 last_searched_text_ = search_text;
587 // When the user changes something in the text box we check the contents and
588 // if the textbox contains something we set it as the new search string and
589 // initiate search (even though old searches might be in progress).
590 if (!search_text.empty()) {
591 // The last two params here are forward (true) and case sensitive (false).
592 find_tab_helper->StartFinding(search_text, true, false);
593 } else {
594 find_tab_helper->StopFinding(FindBarController::kClearSelectionOnPage);
595 UpdateForResult(find_tab_helper->find_result(), base::string16());
596 find_bar_host()->MoveWindowIfNecessary(gfx::Rect());
598 // Clearing the text box should clear the prepopulate state so that when
599 // we close and reopen the Find box it doesn't show the search we just
600 // deleted. We can't do this on ChromeOS yet because we get ContentsChanged
601 // sent for a lot more things than just the user nulling out the search
602 // terms. See http://crbug.com/45372.
603 Profile* profile =
604 Profile::FromBrowserContext(web_contents->GetBrowserContext());
605 FindBarState* find_bar_state = FindBarStateFactory::GetForProfile(profile);
606 find_bar_state->set_last_prepopulate_text(base::string16());
610 void FindBarView::UpdateMatchCountAppearance(bool no_match) {
611 bool enable_buttons = !match_count_text_->text().empty() && !no_match;
612 find_previous_button_->SetEnabled(enable_buttons);
613 find_next_button_->SetEnabled(enable_buttons);
615 if (ui::MaterialDesignController::IsModeMaterial())
616 return;
618 if (no_match) {
619 match_count_text_->SetBackgroundColor(kBackgroundColorNoMatch);
620 match_count_text_->SetEnabledColor(kTextColorNoMatch);
621 } else {
622 match_count_text_->SetBackgroundColor(kBackgroundColorMatch);
623 match_count_text_->SetEnabledColor(kTextColorMatchCount);
627 bool FindBarView::FocusForwarderView::OnMousePressed(
628 const ui::MouseEvent& event) {
629 if (view_to_focus_on_mousedown_)
630 view_to_focus_on_mousedown_->RequestFocus();
631 return true;
634 FindBarHost* FindBarView::find_bar_host() const {
635 return static_cast<FindBarHost*>(host());
638 const char* FindBarView::GetClassName() const {
639 return "FindBarView";
642 void FindBarView::OnThemeChanged() {
643 if (ui::MaterialDesignController::IsModeMaterial())
644 return;
646 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
647 if (GetThemeProvider()) {
648 close_button_->SetBackground(
649 GetThemeProvider()->GetColor(ThemeProperties::COLOR_TAB_TEXT),
650 rb.GetImageSkiaNamed(IDR_CLOSE_1),
651 rb.GetImageSkiaNamed(IDR_CLOSE_1_MASK));
655 void FindBarView::OnNativeThemeChanged(const ui::NativeTheme* theme) {
656 if (!ui::MaterialDesignController::IsModeMaterial())
657 return;
659 SkColor color =
660 theme->GetSystemColor(ui::NativeTheme::kColorId_DialogBackground);
661 set_background(views::Background::CreateSolidBackground(color));
662 match_count_text_->SetBackgroundColor(color);
663 match_count_text_->SetEnabledColor(kMatchTextColorMD);