OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "ui/app_list/views/search_box_view.h" | 5 #include "ui/app_list/views/search_box_view.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "grit/ui_resources.h" | 9 #include "grit/ui_resources.h" |
10 #include "ui/app_list/app_list_model.h" | 10 #include "ui/app_list/app_list_model.h" |
| 11 #include "ui/app_list/app_list_view_delegate.h" |
11 #include "ui/app_list/search_box_model.h" | 12 #include "ui/app_list/search_box_model.h" |
12 #include "ui/app_list/views/app_list_menu_views.h" | 13 #include "ui/app_list/views/app_list_menu_views.h" |
13 #include "ui/app_list/views/search_box_view_delegate.h" | 14 #include "ui/app_list/views/search_box_view_delegate.h" |
| 15 #include "ui/base/l10n/l10n_util.h" |
14 #include "ui/base/resource/resource_bundle.h" | 16 #include "ui/base/resource/resource_bundle.h" |
15 #include "ui/events/event.h" | 17 #include "ui/events/event.h" |
| 18 #include "ui/views/controls/button/image_button.h" |
16 #include "ui/views/controls/button/menu_button.h" | 19 #include "ui/views/controls/button/menu_button.h" |
17 #include "ui/views/controls/image_view.h" | 20 #include "ui/views/controls/image_view.h" |
18 #include "ui/views/controls/textfield/textfield.h" | 21 #include "ui/views/controls/textfield/textfield.h" |
19 | 22 |
20 namespace app_list { | 23 namespace app_list { |
21 | 24 |
22 namespace { | 25 namespace { |
23 | 26 |
24 const int kPadding = 14; | 27 const int kPadding = 14; |
25 const int kIconDimension = 32; | 28 const int kIconDimension = 32; |
(...skipping 11 matching lines...) Expand all Loading... |
37 | 40 |
38 } // namespace | 41 } // namespace |
39 | 42 |
40 SearchBoxView::SearchBoxView(SearchBoxViewDelegate* delegate, | 43 SearchBoxView::SearchBoxView(SearchBoxViewDelegate* delegate, |
41 AppListViewDelegate* view_delegate, | 44 AppListViewDelegate* view_delegate, |
42 AppListModel* model) | 45 AppListModel* model) |
43 : delegate_(delegate), | 46 : delegate_(delegate), |
44 view_delegate_(view_delegate), | 47 view_delegate_(view_delegate), |
45 model_(model), | 48 model_(model), |
46 icon_view_(new views::ImageView), | 49 icon_view_(new views::ImageView), |
| 50 speech_button_(NULL), |
47 search_box_(new views::Textfield), | 51 search_box_(new views::Textfield), |
48 contents_view_(NULL) { | 52 contents_view_(NULL) { |
49 DCHECK(model_); | 53 DCHECK(model_); |
50 AddChildView(icon_view_); | 54 AddChildView(icon_view_); |
51 | 55 |
52 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 56 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
53 | 57 |
54 #if !defined(OS_CHROMEOS) | 58 #if !defined(OS_CHROMEOS) |
55 menu_button_ = new views::MenuButton(NULL, base::string16(), this, false); | 59 menu_button_ = new views::MenuButton(NULL, base::string16(), this, false); |
56 menu_button_->set_border(NULL); | 60 menu_button_->set_border(NULL); |
57 menu_button_->SetIcon(*rb.GetImageSkiaNamed(IDR_APP_LIST_TOOLS_NORMAL)); | 61 menu_button_->SetIcon(*rb.GetImageSkiaNamed(IDR_APP_LIST_TOOLS_NORMAL)); |
58 menu_button_->SetHoverIcon(*rb.GetImageSkiaNamed(IDR_APP_LIST_TOOLS_HOVER)); | 62 menu_button_->SetHoverIcon(*rb.GetImageSkiaNamed(IDR_APP_LIST_TOOLS_HOVER)); |
59 menu_button_->SetPushedIcon(*rb.GetImageSkiaNamed( | 63 menu_button_->SetPushedIcon(*rb.GetImageSkiaNamed( |
60 IDR_APP_LIST_TOOLS_PRESSED)); | 64 IDR_APP_LIST_TOOLS_PRESSED)); |
61 AddChildView(menu_button_); | 65 AddChildView(menu_button_); |
62 #endif | 66 #endif |
63 | 67 |
64 search_box_->RemoveBorder(); | 68 search_box_->RemoveBorder(); |
65 search_box_->SetFont(rb.GetFont(ui::ResourceBundle::MediumFont)); | 69 search_box_->SetFont(rb.GetFont(ui::ResourceBundle::MediumFont)); |
66 search_box_->set_placeholder_text_color(kHintTextColor); | 70 search_box_->set_placeholder_text_color(kHintTextColor); |
67 search_box_->SetController(this); | 71 search_box_->SetController(this); |
68 AddChildView(search_box_); | 72 AddChildView(search_box_); |
69 | 73 |
70 model_->search_box()->AddObserver(this); | 74 model_->search_box()->AddObserver(this); |
71 IconChanged(); | 75 IconChanged(); |
| 76 SpeechRecognitionButtonPropChanged(); |
72 HintTextChanged(); | 77 HintTextChanged(); |
73 } | 78 } |
74 | 79 |
75 SearchBoxView::~SearchBoxView() { | 80 SearchBoxView::~SearchBoxView() { |
76 model_->search_box()->RemoveObserver(this); | 81 model_->search_box()->RemoveObserver(this); |
77 } | 82 } |
78 | 83 |
79 bool SearchBoxView::HasSearch() const { | 84 bool SearchBoxView::HasSearch() const { |
80 return !search_box_->text().empty(); | 85 return !search_box_->text().empty(); |
81 } | 86 } |
(...skipping 16 matching lines...) Expand all Loading... |
98 | 103 |
99 void SearchBoxView::Layout() { | 104 void SearchBoxView::Layout() { |
100 gfx::Rect rect(GetContentsBounds()); | 105 gfx::Rect rect(GetContentsBounds()); |
101 if (rect.IsEmpty()) | 106 if (rect.IsEmpty()) |
102 return; | 107 return; |
103 | 108 |
104 gfx::Rect icon_frame(rect); | 109 gfx::Rect icon_frame(rect); |
105 icon_frame.set_width(kIconDimension + 2 * kPadding); | 110 icon_frame.set_width(kIconDimension + 2 * kPadding); |
106 icon_view_->SetBoundsRect(icon_frame); | 111 icon_view_->SetBoundsRect(icon_frame); |
107 | 112 |
| 113 // Places |speech_button_| if exists. |speech_button_frame| holds its bounds |
| 114 // to calculate the search box bounds. |
| 115 gfx::Rect speech_button_frame; |
| 116 if (speech_button_) { |
| 117 speech_button_frame = icon_frame; |
| 118 speech_button_frame.set_x(rect.right() - icon_frame.width()); |
| 119 gfx::Size button_size = speech_button_->GetPreferredSize(); |
| 120 gfx::Point button_origin = speech_button_frame.CenterPoint(); |
| 121 button_origin.Offset(-button_size.width() / 2, -button_size.height() / 2); |
| 122 speech_button_->SetBoundsRect(gfx::Rect(button_origin, button_size)); |
| 123 } |
| 124 |
108 gfx::Rect menu_button_frame(rect); | 125 gfx::Rect menu_button_frame(rect); |
109 #if !defined(OS_CHROMEOS) | 126 #if !defined(OS_CHROMEOS) |
110 menu_button_frame.set_width(kMenuButtonDimension); | 127 menu_button_frame.set_width(kMenuButtonDimension); |
111 menu_button_frame.set_x(rect.right() - menu_button_frame.width() - kPadding); | 128 menu_button_frame.set_x(rect.right() - menu_button_frame.width() - kPadding); |
112 menu_button_frame.ClampToCenteredSize(gfx::Size(menu_button_frame.width(), | 129 menu_button_frame.ClampToCenteredSize(gfx::Size(menu_button_frame.width(), |
113 kMenuButtonDimension)); | 130 kMenuButtonDimension)); |
114 menu_button_->SetBoundsRect(menu_button_frame); | 131 menu_button_->SetBoundsRect(menu_button_frame); |
115 #else | 132 #else |
116 menu_button_frame.set_width(0); | 133 menu_button_frame.set_width(0); |
117 #endif | 134 #endif |
118 | 135 |
119 gfx::Rect edit_frame(rect); | 136 gfx::Rect edit_frame(rect); |
120 edit_frame.set_x(icon_frame.right()); | 137 edit_frame.set_x(icon_frame.right()); |
121 edit_frame.set_width( | 138 int edit_frame_width = |
122 rect.width() - icon_frame.width() - kPadding - menu_button_frame.width()); | 139 rect.width() - icon_frame.width() - kPadding - menu_button_frame.width(); |
| 140 if (!speech_button_frame.IsEmpty()) |
| 141 edit_frame_width -= speech_button_frame.width() + kPadding; |
| 142 edit_frame.set_width(edit_frame_width); |
123 edit_frame.ClampToCenteredSize( | 143 edit_frame.ClampToCenteredSize( |
124 gfx::Size(edit_frame.width(), search_box_->GetPreferredSize().height())); | 144 gfx::Size(edit_frame.width(), search_box_->GetPreferredSize().height())); |
125 search_box_->SetBoundsRect(edit_frame); | 145 search_box_->SetBoundsRect(edit_frame); |
126 } | 146 } |
127 | 147 |
128 bool SearchBoxView::OnMouseWheel(const ui::MouseWheelEvent& event) { | 148 bool SearchBoxView::OnMouseWheel(const ui::MouseWheelEvent& event) { |
129 if (contents_view_) | 149 if (contents_view_) |
130 return contents_view_->OnMouseWheel(event); | 150 return contents_view_->OnMouseWheel(event); |
131 | 151 |
132 return false; | 152 return false; |
(...skipping 20 matching lines...) Expand all Loading... |
153 | 173 |
154 bool SearchBoxView::HandleKeyEvent(views::Textfield* sender, | 174 bool SearchBoxView::HandleKeyEvent(views::Textfield* sender, |
155 const ui::KeyEvent& key_event) { | 175 const ui::KeyEvent& key_event) { |
156 bool handled = false; | 176 bool handled = false; |
157 if (contents_view_ && contents_view_->visible()) | 177 if (contents_view_ && contents_view_->visible()) |
158 handled = contents_view_->OnKeyPressed(key_event); | 178 handled = contents_view_->OnKeyPressed(key_event); |
159 | 179 |
160 return handled; | 180 return handled; |
161 } | 181 } |
162 | 182 |
| 183 void SearchBoxView::ButtonPressed(views::Button* sender, |
| 184 const ui::Event& event) { |
| 185 DCHECK(!speech_button_ && sender == speech_button_); |
| 186 view_delegate_->ToggleSpeechRecognition(); |
| 187 } |
| 188 |
163 void SearchBoxView::OnMenuButtonClicked(View* source, const gfx::Point& point) { | 189 void SearchBoxView::OnMenuButtonClicked(View* source, const gfx::Point& point) { |
164 if (!menu_) | 190 if (!menu_) |
165 menu_.reset(new AppListMenuViews(view_delegate_)); | 191 menu_.reset(new AppListMenuViews(view_delegate_)); |
166 | 192 |
167 const gfx::Point menu_location = | 193 const gfx::Point menu_location = |
168 menu_button_->GetBoundsInScreen().bottom_right() + | 194 menu_button_->GetBoundsInScreen().bottom_right() + |
169 gfx::Vector2d(kMenuXOffsetFromButton, kMenuYOffsetFromButton); | 195 gfx::Vector2d(kMenuXOffsetFromButton, kMenuYOffsetFromButton); |
170 menu_->RunMenuAt(menu_button_, menu_location); | 196 menu_->RunMenuAt(menu_button_, menu_location); |
171 } | 197 } |
172 | 198 |
173 void SearchBoxView::IconChanged() { | 199 void SearchBoxView::IconChanged() { |
174 icon_view_->SetImage(model_->search_box()->icon()); | 200 icon_view_->SetImage(model_->search_box()->icon()); |
175 } | 201 } |
176 | 202 |
| 203 void SearchBoxView::SpeechRecognitionButtonPropChanged() { |
| 204 const SearchBoxModel::ToggleButtonProperty* speech_button_prop = |
| 205 model_->search_box()->speech_button(); |
| 206 if (speech_button_prop) { |
| 207 if (!speech_button_) { |
| 208 speech_button_ = new views::ToggleImageButton(this); |
| 209 AddChildView(speech_button_); |
| 210 } |
| 211 speech_button_->SetImage(views::Button::STATE_NORMAL, |
| 212 &speech_button_prop->icon); |
| 213 speech_button_->SetToggledImage(views::Button::STATE_NORMAL, |
| 214 &speech_button_prop->toggled_icon); |
| 215 speech_button_->SetTooltipText(speech_button_prop->tooltip); |
| 216 speech_button_->SetToggledTooltipText(speech_button_prop->toggled_tooltip); |
| 217 } else { |
| 218 if (speech_button_) { |
| 219 // Deleting a view will detach it from its parent. |
| 220 delete speech_button_; |
| 221 speech_button_ = NULL; |
| 222 } |
| 223 } |
| 224 } |
| 225 |
| 226 void SearchBoxView::SetSpeechRecognitionButtonState(bool toggled) { |
| 227 if (speech_button_) |
| 228 speech_button_->SetToggled(toggled); |
| 229 } |
| 230 |
177 void SearchBoxView::HintTextChanged() { | 231 void SearchBoxView::HintTextChanged() { |
178 search_box_->set_placeholder_text(model_->search_box()->hint_text()); | 232 search_box_->set_placeholder_text(model_->search_box()->hint_text()); |
179 } | 233 } |
180 | 234 |
181 void SearchBoxView::SelectionModelChanged() { | 235 void SearchBoxView::SelectionModelChanged() { |
182 search_box_->SelectSelectionModel(model_->search_box()->selection_model()); | 236 search_box_->SelectSelectionModel(model_->search_box()->selection_model()); |
183 } | 237 } |
184 | 238 |
185 void SearchBoxView::TextChanged() { | 239 void SearchBoxView::TextChanged() { |
186 search_box_->SetText(model_->search_box()->text()); | 240 search_box_->SetText(model_->search_box()->text()); |
187 NotifyQueryChanged(); | 241 NotifyQueryChanged(); |
188 } | 242 } |
189 | 243 |
190 } // namespace app_list | 244 } // namespace app_list |
OLD | NEW |