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

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

Issue 11636040: AutofillPopupController clarifications + simplifications. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: new workstation Created 7 years, 12 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
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 "chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.h" 5 #include "chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.h"
6 6
7 #include <gdk/gdkkeysyms.h> 7 #include <gdk/gdkkeysyms.h>
8 8
9 #include "base/i18n/rtl.h" 9 #include "base/i18n/rtl.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/utf_string_conversions.h" 11 #include "base/utf_string_conversions.h"
12 #include "chrome/browser/ui/autofill/autofill_popup_controller.h" 12 #include "chrome/browser/ui/autofill/autofill_popup_controller.h"
13 #include "chrome/browser/ui/gtk/gtk_util.h" 13 #include "chrome/browser/ui/gtk/gtk_util.h"
14 #include "grit/ui_resources.h" 14 #include "grit/ui_resources.h"
15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAutofillClient.h" 15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAutofillClient.h"
16 #include "ui/base/gtk/gtk_compat.h" 16 #include "ui/base/gtk/gtk_compat.h"
17 #include "ui/base/gtk/gtk_hig_constants.h" 17 #include "ui/base/gtk/gtk_hig_constants.h"
18 #include "ui/base/gtk/gtk_windowing.h" 18 #include "ui/base/gtk/gtk_windowing.h"
19 #include "ui/base/resource/resource_bundle.h" 19 #include "ui/base/resource/resource_bundle.h"
20 #include "ui/gfx/image/image.h" 20 #include "ui/gfx/image/image.h"
21 #include "ui/gfx/native_widget_types.h" 21 #include "ui/gfx/native_widget_types.h"
22 #include "ui/gfx/pango_util.h" 22 #include "ui/gfx/pango_util.h"
23 #include "ui/gfx/rect.h" 23 #include "ui/gfx/rect.h"
24 24
25 using WebKit::WebAutofillClient; 25 using WebKit::WebAutofillClient;
26 26
27 namespace { 27 namespace {
28
28 const GdkColor kBorderColor = GDK_COLOR_RGB(0xc7, 0xca, 0xce); 29 const GdkColor kBorderColor = GDK_COLOR_RGB(0xc7, 0xca, 0xce);
29 const GdkColor kHoveredBackgroundColor = GDK_COLOR_RGB(0xcd, 0xcd, 0xcd); 30 const GdkColor kHoveredBackgroundColor = GDK_COLOR_RGB(0xcd, 0xcd, 0xcd);
30 const GdkColor kValueTextColor = GDK_COLOR_RGB(0x00, 0x00, 0x00); 31 const GdkColor kNameColor = GDK_COLOR_RGB(0x00, 0x00, 0x00);
31 const GdkColor kLabelTextColor = GDK_COLOR_RGB(0x7f, 0x7f, 0x7f); 32 const GdkColor kSubtextColor = GDK_COLOR_RGB(0x7f, 0x7f, 0x7f);
32
33 gfx::Rect GetWindowRect(GdkWindow* window) {
34 return gfx::Rect(gdk_window_get_width(window),
35 gdk_window_get_height(window));
36 }
37 33
38 } // namespace 34 } // namespace
39 35
40 AutofillPopupViewGtk::AutofillPopupViewGtk( 36 AutofillPopupViewGtk::AutofillPopupViewGtk(
41 AutofillPopupController* controller) 37 AutofillPopupController* controller)
42 : controller_(controller), 38 : controller_(controller),
43 window_(gtk_window_new(GTK_WINDOW_POPUP)) { 39 window_(gtk_window_new(GTK_WINDOW_POPUP)) {
44 gtk_window_set_resizable(GTK_WINDOW(window_), FALSE); 40 gtk_window_set_resizable(GTK_WINDOW(window_), FALSE);
45 gtk_widget_set_app_paintable(window_, TRUE); 41 gtk_widget_set_app_paintable(window_, TRUE);
46 gtk_widget_set_double_buffered(window_, TRUE); 42 gtk_widget_set_double_buffered(window_, TRUE);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 UpdateBoundsAndRedrawPopup(); 74 UpdateBoundsAndRedrawPopup();
79 75
80 gtk_widget_show(window_); 76 gtk_widget_show(window_);
81 77
82 GtkWidget* parent_window = 78 GtkWidget* parent_window =
83 gtk_widget_get_toplevel(controller_->container_view()); 79 gtk_widget_get_toplevel(controller_->container_view());
84 ui::StackPopupWindow(window_, parent_window); 80 ui::StackPopupWindow(window_, parent_window);
85 } 81 }
86 82
87 void AutofillPopupViewGtk::InvalidateRow(size_t row) { 83 void AutofillPopupViewGtk::InvalidateRow(size_t row) {
88 GdkRectangle row_rect = controller_->GetRectForRow( 84 GdkRectangle row_rect = controller_->GetRowBounds(row).ToGdkRectangle();
89 row,
90 controller_->popup_bounds().width()).ToGdkRectangle();
91 GdkWindow* gdk_window = gtk_widget_get_window(window_); 85 GdkWindow* gdk_window = gtk_widget_get_window(window_);
92 gdk_window_invalidate_rect(gdk_window, &row_rect, FALSE); 86 gdk_window_invalidate_rect(gdk_window, &row_rect, FALSE);
93 } 87 }
94 88
95 void AutofillPopupViewGtk::UpdateBoundsAndRedrawPopup() { 89 void AutofillPopupViewGtk::UpdateBoundsAndRedrawPopup() {
96 gtk_widget_set_size_request(window_, 90 gtk_widget_set_size_request(window_,
97 controller_->popup_bounds().width(), 91 controller_->popup_bounds().width(),
98 controller_->popup_bounds().height()); 92 controller_->popup_bounds().height());
99 gtk_window_move(GTK_WINDOW(window_), 93 gtk_window_move(GTK_WINDOW(window_),
100 controller_->popup_bounds().x(), 94 controller_->popup_bounds().x(),
101 controller_->popup_bounds().y()); 95 controller_->popup_bounds().y());
102 96
103 GdkWindow* gdk_window = gtk_widget_get_window(window_); 97 GdkWindow* gdk_window = gtk_widget_get_window(window_);
104 GdkRectangle popup_rect = controller_->popup_bounds().ToGdkRectangle(); 98 GdkRectangle popup_rect = controller_->popup_bounds().ToGdkRectangle();
105 if (gdk_window != NULL) 99 if (gdk_window != NULL)
106 gdk_window_invalidate_rect(gdk_window, &popup_rect, FALSE); 100 gdk_window_invalidate_rect(gdk_window, &popup_rect, FALSE);
107 } 101 }
108 102
109 gboolean AutofillPopupViewGtk::HandleButtonRelease(GtkWidget* widget, 103 gboolean AutofillPopupViewGtk::HandleButtonRelease(GtkWidget* widget,
110 GdkEventButton* event) { 104 GdkEventButton* event) {
111 // We only care about the left click. 105 // We only care about the left click.
112 if (event->button != 1) 106 if (event->button != 1)
113 return FALSE; 107 return FALSE;
114 108
115 controller_->AcceptSelectedPosition(event->x, event->y); 109 controller_->MouseClicked(event->x, event->y);
116 return TRUE; 110 return TRUE;
117 } 111 }
118 112
119 gboolean AutofillPopupViewGtk::HandleExpose(GtkWidget* widget, 113 gboolean AutofillPopupViewGtk::HandleExpose(GtkWidget* widget,
120 GdkEventExpose* event) { 114 GdkEventExpose* event) {
121 gfx::Rect window_rect = GetWindowRect(event->window);
122 gfx::Rect damage_rect = gfx::Rect(event->area);
123
124 cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(gtk_widget_get_window(widget))); 115 cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(gtk_widget_get_window(widget)));
125 gdk_cairo_rectangle(cr, &event->area); 116 gdk_cairo_rectangle(cr, &event->area);
126 cairo_clip(cr); 117 cairo_clip(cr);
127 118
128 // This assert is kinda ugly, but it would be more currently unneeded work 119 // This assert is kinda ugly, but it would be more currently unneeded work
129 // to support painting a border that isn't 1 pixel thick. There is no point 120 // to support painting a border that isn't 1 pixel thick. There is no point
130 // in writing that code now, and explode if that day ever comes. 121 // in writing that code now, and explode if that day ever comes.
131 DCHECK_EQ(1, kBorderThickness); 122 DCHECK_EQ(1, kBorderThickness);
132 // Draw the 1px border around the entire window. 123 // Draw the 1px border around the entire window.
133 gdk_cairo_set_source_color(cr, &kBorderColor); 124 gdk_cairo_set_source_color(cr, &kBorderColor);
134 cairo_rectangle(cr, 0, 0, window_rect.width(), window_rect.height()); 125 gdk_cairo_rectangle(cr, &widget->allocation);
135 cairo_stroke(cr); 126 cairo_stroke(cr);
127 SetUpLayout();
136 128
137 SetupLayout(window_rect); 129 gfx::Rect damage_rect(event->area);
138 130
139 for (size_t i = 0; i < controller_->autofill_values().size(); ++i) { 131 for (size_t i = 0; i < controller_->names().size(); ++i) {
140 gfx::Rect line_rect = controller_->GetRectForRow(i, window_rect.width()); 132 gfx::Rect line_rect = controller_->GetRowBounds(i);
141 // Only repaint and layout damaged lines. 133 // Only repaint and layout damaged lines.
142 if (!line_rect.Intersects(damage_rect)) 134 if (!line_rect.Intersects(damage_rect))
143 continue; 135 continue;
144 136
145 if (controller_->autofill_unique_ids()[i] == 137 if (controller_->identifiers()[i] ==
146 WebAutofillClient::MenuItemIDSeparator) { 138 WebAutofillClient::MenuItemIDSeparator) {
147 DrawSeparator(cr, line_rect); 139 DrawSeparator(cr, line_rect);
148 } else { 140 } else {
149 DrawAutofillEntry(cr, i, line_rect); 141 DrawAutofillEntry(cr, i, line_rect);
150 } 142 }
151 } 143 }
152 144
153 cairo_destroy(cr); 145 cairo_destroy(cr);
154 146
155 return TRUE; 147 return TRUE;
156 } 148 }
157 149
158 gboolean AutofillPopupViewGtk::HandleLeave(GtkWidget* widget, 150 gboolean AutofillPopupViewGtk::HandleLeave(GtkWidget* widget,
159 GdkEventCrossing* event) { 151 GdkEventCrossing* event) {
160 controller_->ClearSelectedLine(); 152 controller_->MouseExitedPopup();
161 153
162 return FALSE; 154 return FALSE;
163 } 155 }
164 156
165 gboolean AutofillPopupViewGtk::HandleMotion(GtkWidget* widget, 157 gboolean AutofillPopupViewGtk::HandleMotion(GtkWidget* widget,
166 GdkEventMotion* event) { 158 GdkEventMotion* event) {
167 controller_->SetSelectedPosition(event->x, event->y); 159 controller_->MouseHovered(event->x, event->y);
168 160
169 return TRUE; 161 return TRUE;
170 } 162 }
171 163
172 void AutofillPopupViewGtk::SetupLayout(const gfx::Rect& window_rect) { 164 void AutofillPopupViewGtk::SetUpLayout() {
173 pango_layout_set_width(layout_, window_rect.width() * PANGO_SCALE); 165 pango_layout_set_width(layout_, window_->allocation.width * PANGO_SCALE);
174 pango_layout_set_height(layout_, window_rect.height() * PANGO_SCALE); 166 pango_layout_set_height(layout_, window_->allocation.height * PANGO_SCALE);
175 } 167 }
176 168
177 void AutofillPopupViewGtk::SetLayoutText(const string16& text, 169 void AutofillPopupViewGtk::SetLayoutText(const string16& text,
178 const gfx::Font& font, 170 const gfx::Font& font,
179 const GdkColor text_color) { 171 const GdkColor text_color) {
180 PangoAttrList* attrs = pango_attr_list_new(); 172 PangoAttrList* attrs = pango_attr_list_new();
181 173
182 PangoAttribute* fg_attr = pango_attr_foreground_new(text_color.red, 174 PangoAttribute* fg_attr = pango_attr_foreground_new(text_color.red,
183 text_color.green, 175 text_color.green,
184 text_color.blue); 176 text_color.blue);
(...skipping 29 matching lines...) Expand all
214 size_t index, 206 size_t index,
215 const gfx::Rect& entry_rect) { 207 const gfx::Rect& entry_rect) {
216 if (controller_->selected_line() == static_cast<int>(index)) { 208 if (controller_->selected_line() == static_cast<int>(index)) {
217 gdk_cairo_set_source_color(cairo_context, &kHoveredBackgroundColor); 209 gdk_cairo_set_source_color(cairo_context, &kHoveredBackgroundColor);
218 cairo_rectangle(cairo_context, entry_rect.x(), entry_rect.y(), 210 cairo_rectangle(cairo_context, entry_rect.x(), entry_rect.y(),
219 entry_rect.width(), entry_rect.height()); 211 entry_rect.width(), entry_rect.height());
220 cairo_fill(cairo_context); 212 cairo_fill(cairo_context);
221 } 213 }
222 214
223 // Draw the value. 215 // Draw the value.
224 SetLayoutText(controller_->autofill_values()[index], 216 SetLayoutText(controller_->names()[index],
225 controller_->value_font(), 217 controller_->name_font(),
226 kValueTextColor); 218 kNameColor);
227 int value_text_width = controller_->value_font().GetStringWidth( 219 int value_text_width =
228 controller_->autofill_values()[index]); 220 controller_->name_font().GetStringWidth(controller_->names()[index]);
229 221
230 // Center the text within the line. 222 // Center the text within the line.
231 int row_height = controller_->GetRowHeightFromId( 223 int row_height = controller_->GetRowBounds(index).height();
232 controller_->autofill_unique_ids()[index]);
233 int value_content_y = std::max( 224 int value_content_y = std::max(
234 entry_rect.y(), 225 entry_rect.y(),
235 entry_rect.y() + 226 entry_rect.y() +
236 (row_height - controller_->value_font().GetHeight()) / 2); 227 (row_height - controller_->name_font().GetHeight()) / 2);
237 228
238 bool is_rtl = base::i18n::IsRTL(); 229 bool is_rtl = base::i18n::IsRTL();
239 int value_content_x = is_rtl ? 230 int value_content_x = is_rtl ?
240 entry_rect.width() - value_text_width - kEndPadding : kEndPadding; 231 entry_rect.width() - value_text_width - kEndPadding : kEndPadding;
241 232
242 cairo_save(cairo_context); 233 cairo_save(cairo_context);
243 cairo_move_to(cairo_context, value_content_x, value_content_y); 234 cairo_move_to(cairo_context, value_content_x, value_content_y);
244 pango_cairo_show_layout(cairo_context, layout_); 235 pango_cairo_show_layout(cairo_context, layout_);
245 cairo_restore(cairo_context); 236 cairo_restore(cairo_context);
246 237
247 // Use this to figure out where all the other Autofill items should be placed. 238 // Use this to figure out where all the other Autofill items should be placed.
248 int x_align_left = is_rtl ? kEndPadding : entry_rect.width() - kEndPadding; 239 int x_align_left = is_rtl ? kEndPadding : entry_rect.width() - kEndPadding;
249 240
250 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 241 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
251 242
252 // Draw the delete icon, if one is needed. 243 // Draw the delete icon, if one is needed.
253 if (controller_->CanDelete(controller_->autofill_unique_ids()[index])) { 244 if (controller_->CanDelete(index)) {
254 x_align_left += is_rtl ? 0 : -kDeleteIconWidth; 245 x_align_left += is_rtl ? 0 : -kDeleteIconWidth;
255 246
256 gfx::Image delete_icon; 247 gfx::Image delete_icon;
257 if (static_cast<int>(index) == controller_->selected_line() && 248 if (static_cast<int>(index) == controller_->selected_line() &&
258 controller_->delete_icon_hovered()) { 249 controller_->delete_icon_hovered()) {
259 delete_icon = rb.GetImageNamed(IDR_CLOSE_BAR_H); 250 delete_icon = rb.GetImageNamed(IDR_CLOSE_BAR_H);
260 } else { 251 } else {
261 delete_icon = rb.GetImageNamed(IDR_CLOSE_BAR); 252 delete_icon = rb.GetImageNamed(IDR_CLOSE_BAR);
262 } 253 }
263 254
264 // TODO(csharp): Create a custom resource for the delete icon. 255 // TODO(csharp): Create a custom resource for the delete icon.
265 // http://crbug.com/131801 256 // http://crbug.com/131801
266 cairo_save(cairo_context); 257 cairo_save(cairo_context);
267 gtk_util::DrawFullImage( 258 gtk_util::DrawFullImage(
268 cairo_context, 259 cairo_context,
269 window_, 260 window_,
270 delete_icon, 261 delete_icon,
271 x_align_left, 262 x_align_left,
272 entry_rect.y() + 263 entry_rect.y() +
273 ((row_height - kDeleteIconHeight) / 2)); 264 ((row_height - kDeleteIconHeight) / 2));
274 cairo_restore(cairo_context); 265 cairo_restore(cairo_context);
275 cairo_save(cairo_context); 266 cairo_save(cairo_context);
276 267
277 x_align_left += is_rtl ? kDeleteIconWidth + kIconPadding : -kIconPadding; 268 x_align_left += is_rtl ? kDeleteIconWidth + kIconPadding : -kIconPadding;
278 } 269 }
279 270
280 // Draw the Autofill icon, if one exists 271 // Draw the Autofill icon, if one exists
281 if (!controller_->autofill_icons()[index].empty()) { 272 if (!controller_->icons()[index].empty()) {
282 int icon = 273 int icon = controller_->GetIconResourceID(controller_->icons()[index]);
283 controller_->GetIconResourceID(controller_->autofill_icons()[index]);
284 DCHECK_NE(-1, icon); 274 DCHECK_NE(-1, icon);
285 int icon_y = entry_rect.y() + (row_height - kAutofillIconHeight) / 2; 275 int icon_y = entry_rect.y() + (row_height - kAutofillIconHeight) / 2;
286 276
287 x_align_left += is_rtl ? 0 : -kAutofillIconWidth; 277 x_align_left += is_rtl ? 0 : -kAutofillIconWidth;
288 278
289 cairo_save(cairo_context); 279 cairo_save(cairo_context);
290 gtk_util::DrawFullImage(cairo_context, 280 gtk_util::DrawFullImage(cairo_context,
291 window_, 281 window_,
292 rb.GetImageNamed(icon), 282 rb.GetImageNamed(icon),
293 x_align_left, 283 x_align_left,
294 icon_y); 284 icon_y);
295 cairo_restore(cairo_context); 285 cairo_restore(cairo_context);
296 286
297 x_align_left += is_rtl ? kAutofillIconWidth + kIconPadding : -kIconPadding; 287 x_align_left += is_rtl ? kAutofillIconWidth + kIconPadding : -kIconPadding;
298 } 288 }
299 289
300 // Draw the label text. 290 // Draw the subtext.
301 SetLayoutText(controller_->autofill_labels()[index], 291 SetLayoutText(controller_->subtexts()[index],
302 controller_->label_font(), 292 controller_->subtext_font(),
303 kLabelTextColor); 293 kSubtextColor);
304 if (!is_rtl) { 294 if (!is_rtl) {
305 x_align_left -= controller_->label_font().GetStringWidth( 295 x_align_left -= controller_->subtext_font().GetStringWidth(
306 controller_->autofill_labels()[index]); 296 controller_->subtexts()[index]);
307 } 297 }
308 298
309 // Center the text within the line. 299 // Center the text within the line.
310 int label_content_y = std::max( 300 int subtext_content_y = std::max(
311 entry_rect.y(), 301 entry_rect.y(),
312 entry_rect.y() + 302 entry_rect.y() +
313 (row_height - controller_->label_font().GetHeight()) / 2); 303 (row_height - controller_->subtext_font().GetHeight()) / 2);
314 304
315 cairo_save(cairo_context); 305 cairo_save(cairo_context);
316 cairo_move_to(cairo_context, x_align_left, label_content_y); 306 cairo_move_to(cairo_context, x_align_left, subtext_content_y);
317 pango_cairo_show_layout(cairo_context, layout_); 307 pango_cairo_show_layout(cairo_context, layout_);
318 cairo_restore(cairo_context); 308 cairo_restore(cairo_context);
319 } 309 }
320 310
321 void AutofillPopupViewGtk::SetInitialBounds() { 311 void AutofillPopupViewGtk::SetInitialBounds() {
322 GdkScreen* screen = 312 GdkScreen* screen =
323 gtk_widget_get_screen(GTK_WIDGET(controller_->container_view())); 313 gtk_widget_get_screen(GTK_WIDGET(controller_->container_view()));
324 gint screen_height = gdk_screen_get_height(screen); 314 gint screen_height = gdk_screen_get_height(screen);
325 315
326 int x = 0; 316 int x = 0;
(...skipping 19 matching lines...) Expand all
346 x + controller_->element_bounds().x(), 336 x + controller_->element_bounds().x(),
347 top_of_popup, 337 top_of_popup,
348 controller_->GetPopupRequiredWidth(), 338 controller_->GetPopupRequiredWidth(),
349 popup_height)); 339 popup_height));
350 } 340 }
351 341
352 AutofillPopupView* AutofillPopupView::Create( 342 AutofillPopupView* AutofillPopupView::Create(
353 AutofillPopupController* controller) { 343 AutofillPopupController* controller) {
354 return new AutofillPopupViewGtk(controller); 344 return new AutofillPopupViewGtk(controller);
355 } 345 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698