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