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

Side by Side Diff: chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc

Issue 10408070: Upgrade Seperator in New Autofill UI (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years, 7 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
« no previous file with comments | « chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "autofill_popup_view_gtk.h" 5 #include "autofill_popup_view_gtk.h"
6 6
7 #include <gdk/gdkkeysyms.h> 7 #include <gdk/gdkkeysyms.h>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/utf_string_conversions.h" 10 #include "base/utf_string_conversions.h"
11 #include "chrome/browser/autofill/autofill_external_delegate.h" 11 #include "chrome/browser/autofill/autofill_external_delegate.h"
12 #include "chrome/browser/ui/gtk/gtk_util.h" 12 #include "chrome/browser/ui/gtk/gtk_util.h"
13 #include "chrome/browser/ui/gtk/gtk_theme_service.h" 13 #include "chrome/browser/ui/gtk/gtk_theme_service.h"
14 #include "content/public/browser/render_view_host.h" 14 #include "content/public/browser/render_view_host.h"
15 #include "content/public/browser/web_contents.h" 15 #include "content/public/browser/web_contents.h"
16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAutofillClient.h"
16 #include "ui/base/gtk/gtk_compat.h" 17 #include "ui/base/gtk/gtk_compat.h"
17 #include "ui/base/gtk/gtk_hig_constants.h" 18 #include "ui/base/gtk/gtk_hig_constants.h"
18 #include "ui/base/gtk/gtk_windowing.h" 19 #include "ui/base/gtk/gtk_windowing.h"
19 #include "ui/gfx/native_widget_types.h" 20 #include "ui/gfx/native_widget_types.h"
20 #include "ui/gfx/rect.h" 21 #include "ui/gfx/rect.h"
21 22
23 using WebKit::WebAutofillClient;
24
22 namespace { 25 namespace {
23 const GdkColor kBorderColor = GDK_COLOR_RGB(0xc7, 0xca, 0xce); 26 const GdkColor kBorderColor = GDK_COLOR_RGB(0xc7, 0xca, 0xce);
24 const GdkColor kHoveredBackgroundColor = GDK_COLOR_RGB(0x0CD, 0xCD, 0xCD); 27 const GdkColor kHoveredBackgroundColor = GDK_COLOR_RGB(0x0CD, 0xCD, 0xCD);
25 const GdkColor kTextColor = GDK_COLOR_RGB(0x00, 0x00, 0x00); 28 const GdkColor kTextColor = GDK_COLOR_RGB(0x00, 0x00, 0x00);
26 29
27 // The vertical height of each row in pixels. 30 // The vertical height of each row in pixels.
28 const int kRowHeight = 24; 31 const int kRowHeight = 24;
29 32
33 // The vertical height of a separator in pixels.
34 const int kSeparatorHeight = 1;
35
30 // The amount of minimum padding between the Autofill value and label in pixels. 36 // The amount of minimum padding between the Autofill value and label in pixels.
31 const int kMiddlePadding = 10; 37 const int kMiddlePadding = 10;
32 38
33 // The amount of padding between the label and icon or edge and icon in pixels. 39 // The amount of padding between the label and icon or edge and icon in pixels.
34 const int kIconPadding = 5; 40 const int kIconPadding = 5;
35 41
36 // We have a 1 pixel border around the entire results popup. 42 // We have a 1 pixel border around the entire results popup.
37 const int kBorderThickness = 1; 43 const int kBorderThickness = 1;
38 44
39 // Width of the icons in pixels. 45 // Width of the icons in pixels.
40 const int kIconWidth = 25; 46 const int kIconWidth = 25;
41 47
42 // Height of the icons in pixels. 48 // Height of the icons in pixels.
43 const int kIconHeight = 16; 49 const int kIconHeight = 16;
44 50
45 gfx::Rect GetWindowRect(GdkWindow* window) { 51 gfx::Rect GetWindowRect(GdkWindow* window) {
46 return gfx::Rect(gdk_window_get_width(window), 52 return gfx::Rect(gdk_window_get_width(window),
47 gdk_window_get_height(window)); 53 gdk_window_get_height(window));
48 } 54 }
49 55
50 // Returns the rectangle containing the item at position |index| in the popup. 56 int GetRowHeight(int unique_id) {
51 gfx::Rect GetRectForRow(size_t index, int width) { 57 if (unique_id == WebAutofillClient::MenuItemIDSeparator)
52 return gfx::Rect(0, (index * kRowHeight), width, kRowHeight); 58 return kSeparatorHeight;
59
60 return kRowHeight;
53 } 61 }
54 62
55 } // namespace 63 } // namespace
56 64
57 AutofillPopupViewGtk::AutofillPopupViewGtk( 65 AutofillPopupViewGtk::AutofillPopupViewGtk(
58 content::WebContents* web_contents, 66 content::WebContents* web_contents,
59 GtkThemeService* theme_service, 67 GtkThemeService* theme_service,
60 AutofillExternalDelegate* external_delegate, 68 AutofillExternalDelegate* external_delegate,
61 GtkWidget* parent) 69 GtkWidget* parent)
62 : AutofillPopupView(web_contents, external_delegate), 70 : AutofillPopupView(web_contents, external_delegate),
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 void AutofillPopupViewGtk::InvalidateRow(size_t row) { 123 void AutofillPopupViewGtk::InvalidateRow(size_t row) {
116 GdkRectangle row_rect = GetRectForRow(row, bounds_.width()).ToGdkRectangle(); 124 GdkRectangle row_rect = GetRectForRow(row, bounds_.width()).ToGdkRectangle();
117 GdkWindow* gdk_window = gtk_widget_get_window(window_); 125 GdkWindow* gdk_window = gtk_widget_get_window(window_);
118 gdk_window_invalidate_rect(gdk_window, &row_rect, FALSE); 126 gdk_window_invalidate_rect(gdk_window, &row_rect, FALSE);
119 } 127 }
120 128
121 void AutofillPopupViewGtk::ResizePopup() { 129 void AutofillPopupViewGtk::ResizePopup() {
122 gtk_widget_set_size_request( 130 gtk_widget_set_size_request(
123 window_, 131 window_,
124 GetPopupRequiredWidth(), 132 GetPopupRequiredWidth(),
125 kRowHeight * autofill_values().size()); 133 GetPopupRequiredHeight());
126 } 134 }
127 135
128 gboolean AutofillPopupViewGtk::HandleButtonRelease(GtkWidget* widget, 136 gboolean AutofillPopupViewGtk::HandleButtonRelease(GtkWidget* widget,
129 GdkEventButton* event) { 137 GdkEventButton* event) {
130 // We only care about the left click. 138 // We only care about the left click.
131 if (event->button != 1) 139 if (event->button != 1)
132 return FALSE; 140 return FALSE;
133 141
134 DCHECK_EQ(selected_line(), LineFromY(event->y)); 142 DCHECK_EQ(selected_line(), LineFromY(event->y));
135 143
(...skipping 26 matching lines...) Expand all
162 pango_layout_get_size(layout_, &actual_content_width, &actual_content_height); 170 pango_layout_get_size(layout_, &actual_content_width, &actual_content_height);
163 actual_content_width /= PANGO_SCALE; 171 actual_content_width /= PANGO_SCALE;
164 actual_content_height /= PANGO_SCALE; 172 actual_content_height /= PANGO_SCALE;
165 173
166 for (size_t i = 0; i < autofill_values().size(); ++i) { 174 for (size_t i = 0; i < autofill_values().size(); ++i) {
167 gfx::Rect line_rect = GetRectForRow(i, window_rect.width()); 175 gfx::Rect line_rect = GetRectForRow(i, window_rect.width());
168 // Only repaint and layout damaged lines. 176 // Only repaint and layout damaged lines.
169 if (!line_rect.Intersects(damage_rect)) 177 if (!line_rect.Intersects(damage_rect))
170 continue; 178 continue;
171 179
172 if (IsSeparatorIndex(i)) { 180 if (autofill_unique_ids()[i] == WebAutofillClient::MenuItemIDSeparator)
173 int line_y = i * kRowHeight; 181 DrawSeparator(cr, line_rect);
174 182 else
175 cairo_save(cr); 183 DrawAutofillEntry(cr, i, actual_content_height, line_rect);
176 cairo_move_to(cr, 0, line_y);
177 cairo_line_to(cr, window_rect.width(), line_y);
178 cairo_stroke(cr);
179 cairo_restore(cr);
180 }
181
182 if (selected_line() == static_cast<int>(i)) {
183 gdk_cairo_set_source_color(cr, &kHoveredBackgroundColor);
184 cairo_rectangle(cr, line_rect.x(), line_rect.y(),
185 line_rect.width(), line_rect.height());
186 cairo_fill(cr);
187 }
188
189 // Center the text within the line.
190 int content_y = std::max(
191 line_rect.y(),
192 line_rect.y() + ((kRowHeight - actual_content_height) / 2));
193
194 // Draw the value.
195 gtk_util::SetLayoutText(layout_, autofill_values()[i]);
196
197 cairo_save(cr);
198 cairo_move_to(cr, 0, content_y);
199 pango_cairo_show_layout(cr, layout_);
200 cairo_restore(cr);
201
202 // Draw the label.
203 int x_align_left = window_rect.width() -
204 font_.GetStringWidth(autofill_labels()[i]);
205
206 if (!autofill_icons()[i].empty())
207 x_align_left -= 2 * kIconPadding + kIconWidth;
208
209 gtk_util::SetLayoutText(layout_, autofill_labels()[i]);
210
211 cairo_save(cr);
212 cairo_move_to(cr, x_align_left, content_y);
213 pango_cairo_show_layout(cr, layout_);
214 cairo_restore(cr);
215
216 // Draw the icon, if one exists
217 if (!autofill_icons()[i].empty()) {
218 int icon = GetIconResourceID(autofill_icons()[i]);
219 DCHECK_NE(-1, icon);
220 int icon_y = line_rect.y() + ((kRowHeight - kIconHeight) / 2);
221
222 cairo_save(cr);
223 gtk_util::DrawFullImage(cr,
224 window_,
225 theme_service_->GetImageNamed(icon),
226 window_rect.width() -
227 (kIconPadding + kIconWidth),
228 icon_y);
229 cairo_restore(cr);
230 }
231 } 184 }
232 185
233 cairo_destroy(cr); 186 cairo_destroy(cr);
234 187
235 return TRUE; 188 return TRUE;
236 } 189 }
237 190
238 gboolean AutofillPopupViewGtk::HandleMotion(GtkWidget* widget, 191 gboolean AutofillPopupViewGtk::HandleMotion(GtkWidget* widget,
239 GdkEventMotion* event) { 192 GdkEventMotion* event) {
193 // TODO(csharp): Only select a line if the motion is still inside the popup.
194 // http://www.crbug.com/129559
240 int line = LineFromY(event->y); 195 int line = LineFromY(event->y);
241 196
242 SetSelectedLine(line); 197 SetSelectedLine(line);
243 198
244 return TRUE; 199 return TRUE;
245 } 200 }
246 201
247 bool AutofillPopupViewGtk::HandleKeyPressEvent(GdkEventKey* event) { 202 bool AutofillPopupViewGtk::HandleKeyPressEvent(GdkEventKey* event) {
248 // Filter modifier to only include accelerator modifiers. 203 // Filter modifier to only include accelerator modifiers.
249 guint modifier = event->state & gtk_accelerator_get_default_mod_mask(); 204 guint modifier = event->state & gtk_accelerator_get_default_mod_mask();
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 PangoAttribute* fg_attr = pango_attr_foreground_new(text_color.red, 241 PangoAttribute* fg_attr = pango_attr_foreground_new(text_color.red,
287 text_color.green, 242 text_color.green,
288 text_color.blue); 243 text_color.blue);
289 pango_attr_list_insert(attrs, fg_attr); // Ownership taken. 244 pango_attr_list_insert(attrs, fg_attr); // Ownership taken.
290 245
291 246
292 pango_layout_set_attributes(layout_, attrs); // Ref taken. 247 pango_layout_set_attributes(layout_, attrs); // Ref taken.
293 pango_attr_list_unref(attrs); 248 pango_attr_list_unref(attrs);
294 } 249 }
295 250
251
252 void AutofillPopupViewGtk::DrawSeparator(cairo_t* cairo_context,
253 const gfx::Rect& separator_rect) {
254 cairo_save(cairo_context);
255 cairo_move_to(cairo_context, 0, separator_rect.y());
256 cairo_line_to(cairo_context,
257 separator_rect.width(),
258 separator_rect.y() + separator_rect.height());
259 cairo_stroke(cairo_context);
260 cairo_restore(cairo_context);
261 }
262
263 void AutofillPopupViewGtk::DrawAutofillEntry(cairo_t* cairo_context,
264 size_t index,
265 int actual_content_height,
266 const gfx::Rect& entry_rect) {
267 if (selected_line() == static_cast<int>(index)) {
268 gdk_cairo_set_source_color(cairo_context, &kHoveredBackgroundColor);
269 cairo_rectangle(cairo_context, entry_rect.x(), entry_rect.y(),
270 entry_rect.width(), entry_rect.height());
271 cairo_fill(cairo_context);
272 }
273
274 // Center the text within the line.
275 int content_y = std::max(
276 entry_rect.y(),
277 entry_rect.y() + ((kRowHeight - actual_content_height) / 2));
278
279 // Draw the value.
280 gtk_util::SetLayoutText(layout_, autofill_values()[index]);
281
282 cairo_save(cairo_context);
283 cairo_move_to(cairo_context, 0, content_y);
284 pango_cairo_show_layout(cairo_context, layout_);
285 cairo_restore(cairo_context);
286
287 // Draw the label.
288 int x_align_left = entry_rect.width() -
289 font_.GetStringWidth(autofill_labels()[index]);
290
291 if (!autofill_icons()[index].empty())
292 x_align_left -= 2 * kIconPadding + kIconWidth;
293
294 gtk_util::SetLayoutText(layout_, autofill_labels()[index]);
295
296 cairo_save(cairo_context);
297 cairo_move_to(cairo_context, x_align_left, content_y);
298 pango_cairo_show_layout(cairo_context, layout_);
299 cairo_restore(cairo_context);
300
301 // Draw the icon, if one exists
302 if (!autofill_icons()[index].empty()) {
303 int icon = GetIconResourceID(autofill_icons()[index]);
304 DCHECK_NE(-1, icon);
305 int icon_y = entry_rect.y() + ((kRowHeight - kIconHeight) / 2);
306
307 cairo_save(cairo_context);
308 gtk_util::DrawFullImage(cairo_context,
309 window_,
310 theme_service_->GetImageNamed(icon),
311 entry_rect.width() -
312 (kIconPadding + kIconWidth),
313 icon_y);
314 cairo_restore(cairo_context);
315 }
316 }
317
318
296 void AutofillPopupViewGtk::SetBounds() { 319 void AutofillPopupViewGtk::SetBounds() {
297 gint origin_x, origin_y; 320 gint origin_x, origin_y;
298 gdk_window_get_origin(gtk_widget_get_window(parent_), &origin_x, &origin_y); 321 gdk_window_get_origin(gtk_widget_get_window(parent_), &origin_x, &origin_y);
299 322
300 GdkScreen* screen = gtk_widget_get_screen(parent_); 323 GdkScreen* screen = gtk_widget_get_screen(parent_);
301 gint screen_height = gdk_screen_get_height(screen); 324 gint screen_height = gdk_screen_get_height(screen);
302 325
303 int bottom_of_field = origin_y + element_bounds().y() + 326 int bottom_of_field = origin_y + element_bounds().y() +
304 element_bounds().height(); 327 element_bounds().height();
305 int popup_size = kRowHeight * autofill_values().size(); 328 int popup_height = GetPopupRequiredHeight();
306 329
307 // Find the correct top position of the popup so that is doesn't go off 330 // Find the correct top position of the popup so that is doesn't go off
308 // the screen. 331 // the screen.
309 int top_of_popup = 0; 332 int top_of_popup = 0;
310 if (screen_height < bottom_of_field + popup_size) { 333 if (screen_height < bottom_of_field + popup_height) {
311 // The popup must appear above the field. 334 // The popup must appear above the field.
312 top_of_popup = origin_y + element_bounds().y() - popup_size; 335 top_of_popup = origin_y + element_bounds().y() - popup_height;
313 } else { 336 } else {
314 // The popup can appear below the field. 337 // The popup can appear below the field.
315 top_of_popup = bottom_of_field; 338 top_of_popup = bottom_of_field;
316 } 339 }
317 340
318 bounds_.SetRect( 341 bounds_.SetRect(
319 origin_x + element_bounds().x(), 342 origin_x + element_bounds().x(),
320 top_of_popup, 343 top_of_popup,
321 GetPopupRequiredWidth(), 344 GetPopupRequiredWidth(),
322 popup_size); 345 popup_height);
323 } 346 }
324 347
325 int AutofillPopupViewGtk::GetPopupRequiredWidth() { 348 int AutofillPopupViewGtk::GetPopupRequiredWidth() {
326 int popup_width = element_bounds().width(); 349 int popup_width = element_bounds().width();
327 DCHECK_EQ(autofill_values().size(), autofill_labels().size()); 350 DCHECK_EQ(autofill_values().size(), autofill_labels().size());
328 for (size_t i = 0; i < autofill_values().size(); ++i) { 351 for (size_t i = 0; i < autofill_values().size(); ++i) {
329 int row_size = font_.GetStringWidth(autofill_values()[i]) + 352 int row_size = font_.GetStringWidth(autofill_values()[i]) +
330 kMiddlePadding + 353 kMiddlePadding +
331 font_.GetStringWidth(autofill_labels()[i]); 354 font_.GetStringWidth(autofill_labels()[i]);
332 355
333 // Add the icon size if required. 356 // Add the icon size if required.
334 if (!autofill_icons()[i].empty()) 357 if (!autofill_icons()[i].empty())
335 row_size += kIconWidth + 2 * kIconPadding; 358 row_size += kIconWidth + 2 * kIconPadding;
336 359
337 popup_width = std::max(popup_width, row_size); 360 popup_width = std::max(popup_width, row_size);
338 } 361 }
339 362
340 return popup_width; 363 return popup_width;
341 } 364 }
342 365
366 int AutofillPopupViewGtk::GetPopupRequiredHeight() {
367 int popup_height = 0;
368
369 for (size_t i = 0; i < autofill_unique_ids().size(); ++i) {
370 popup_height += GetRowHeight(autofill_unique_ids()[i]);
371 }
372
373 return popup_height;
374 }
375
343 int AutofillPopupViewGtk::LineFromY(int y) { 376 int AutofillPopupViewGtk::LineFromY(int y) {
344 return y / kRowHeight; 377 int current_height = 0;
378
379 for (size_t i = 0; i < autofill_unique_ids().size(); ++i) {
380 current_height += GetRowHeight(autofill_unique_ids()[i]);
381
382 if (y <= current_height)
383 return i;
384 }
385
386 // The y value goes beyond the popup so stop the selection at the last line.
387 return autofill_unique_ids().size() - 1;
345 } 388 }
389
390 gfx::Rect AutofillPopupViewGtk::GetRectForRow(size_t row, int width) {
391 int top = 0;
392 for (size_t i = 0; i < row; ++i) {
393 top += GetRowHeight(autofill_unique_ids()[i]);
394 }
395
396 return gfx::Rect(0, top, width, GetRowHeight(autofill_unique_ids()[row]));
397 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698