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

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

Issue 9187009: Basic Drawn text for new GTK Autofill popup. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Responding to comments Created 8 years, 11 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 "autofill_popup_view_gtk.h" 5 #include "autofill_popup_view_gtk.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/utf_string_conversions.h"
9 #include "ui/gfx/rect.h"
10 #include "ui/gfx/native_widget_types.h"
11 #include "ui/base/gtk/gtk_hig_constants.h"
8 #include "ui/base/gtk/gtk_windowing.h" 12 #include "ui/base/gtk/gtk_windowing.h"
13 #include "ui/gfx/font.h"
14
15 namespace {
16 const GdkColor kBorderColor = GDK_COLOR_RGB(0xc7, 0xca, 0xce);
17 const GdkColor kTextColor = GDK_COLOR_RGB(0x00, 0x00, 0x00);
18
19 // The amount of minimum padding between the autofill value and label in pixels.
20 const int kMiddlePadding = 10;
21
22 // We have a 1 pixel border around the entire results popup.
23 const int kBorderThickness = 1;
24
25 // Returns the |window| rectangle as a gfx::Rect.
26 gfx::Rect GetWindowRect(GdkWindow* window) {
27 gint width, height;
28 gdk_drawable_get_size(GDK_DRAWABLE(window), &width, &height);
Elliot Glaysher 2012/01/12 20:34:11 include gtk_compat.h and use gdk_window_get_width/
csharp 2012/01/13 18:09:03 Done. I moved SetTextToDraw to gtk_util and rename
29 return gfx::Rect(width, height);
30 }
31
32 // Returns the rectangle containing the item at position |index| in the popup.
33 gfx::Rect GetRectForItemByIndex(size_t index, int width, int height) {
Ilya Sherman 2012/01/13 02:45:37 nit: Another possible (shorter!) name: GetRectForR
csharp 2012/01/13 18:09:03 Done.
34 return gfx::Rect(0, (index * height), width, height);
35 }
36
37 // Sets the text to be displayed by |layout|.
38 void SetTextToDraw(PangoLayout* layout, const string16& text) {
39 // Pango is really easy to overflow and send into a computational death
40 // spiral that can corrupt the screen. Assume that we'll never have more than
41 // 2000 characters, which should be a safe assumption until we all get robot
42 // eyes. http://crbug.com/66576
43 std::string text_utf8 = UTF16ToUTF8(text);
44 if (text_utf8.length() > 2000)
45 text_utf8 = text_utf8.substr(0, 2000);
46
47 pango_layout_set_text(layout, text_utf8.data(), text_utf8.length());
48 }
49
50 } // namespace
9 51
10 AutofillPopupViewGtk::AutofillPopupViewGtk(content::WebContents* web_contents, 52 AutofillPopupViewGtk::AutofillPopupViewGtk(content::WebContents* web_contents,
11 GtkWidget* parent) 53 GtkWidget* parent)
12 : AutofillPopupView(web_contents), 54 : AutofillPopupView(web_contents),
13 parent_(parent), 55 parent_(parent),
14 window_(gtk_window_new(GTK_WINDOW_POPUP)) { 56 window_(gtk_window_new(GTK_WINDOW_POPUP)) {
15 CHECK(parent != NULL); 57 CHECK(parent != NULL);
16 gtk_window_set_resizable(GTK_WINDOW(window_), FALSE); 58 gtk_window_set_resizable(GTK_WINDOW(window_), FALSE);
17 gtk_widget_set_app_paintable(window_, TRUE); 59 gtk_widget_set_app_paintable(window_, TRUE);
18 gtk_widget_set_double_buffered(window_, TRUE); 60 gtk_widget_set_double_buffered(window_, TRUE);
19 61
20 // Setup the window to ensure it recieves the expose event. 62 // Setup the window to ensure it recieves the expose event.
21 gtk_widget_add_events(window_, GDK_EXPOSURE_MASK); 63 gtk_widget_add_events(window_, GDK_EXPOSURE_MASK);
22 g_signal_connect(window_, "expose-event", 64 g_signal_connect(window_, "expose-event",
23 G_CALLBACK(HandleExposeThunk), this); 65 G_CALLBACK(HandleExposeThunk), this);
66
67 // Cache the layout so we don't have to create it for every expose.
68 layout_ = gtk_widget_create_pango_layout(window_, NULL);
69
70 row_height_ = font_.GetHeight();
24 } 71 }
25 72
26 AutofillPopupViewGtk::~AutofillPopupViewGtk() { 73 AutofillPopupViewGtk::~AutofillPopupViewGtk() {
74 g_object_unref(layout_);
27 gtk_widget_destroy(window_); 75 gtk_widget_destroy(window_);
28 } 76 }
29 77
30 void AutofillPopupViewGtk::Hide() { 78 void AutofillPopupViewGtk::Hide() {
31 gtk_widget_hide(window_); 79 gtk_widget_hide(window_);
32 } 80 }
33 81
34 // TODO(csharp): Actually show the values. 82 void AutofillPopupViewGtk::ShowInternal() {
35 void AutofillPopupViewGtk::Show(const std::vector<string16>& autofill_values,
36 const std::vector<string16>& autofill_labels,
37 const std::vector<string16>& autofill_icons,
38 const std::vector<int>& autofill_unique_ids,
39 int separator_index) {
40 gint origin_x, origin_y; 83 gint origin_x, origin_y;
41 gdk_window_get_origin(gtk_widget_get_window(parent_), &origin_x, &origin_y); 84 gdk_window_get_origin(gtk_widget_get_window(parent_), &origin_x, &origin_y);
42 85
86 // Move the popup to appear right below the text field it is using.
43 gtk_window_move(GTK_WINDOW(window_), 87 gtk_window_move(GTK_WINDOW(window_),
44 origin_x + element_bounds().x(), 88 origin_x + element_bounds().x(),
45 origin_y + element_bounds().y() + element_bounds().height()); 89 origin_y + element_bounds().y() + element_bounds().height());
46 90
91 // Find out the maximum bounds required by the popup.
92 // TODO(csharp): Once the icon is also displayed it will affect the required
93 // size so it will need to be include in the calculation.
94 int popup_width = element_bounds().width();
95 DCHECK_EQ(autofill_values().size(), autofill_labels().size());
96 for (size_t i = 0; i < autofill_values().size(); ++i) {
97 popup_width = std::max(popup_width,
98 font_.GetStringWidth(autofill_values()[i]) +
99 kMiddlePadding +
100 font_.GetStringWidth(autofill_labels()[i]));
101 }
102
47 gtk_widget_set_size_request( 103 gtk_widget_set_size_request(
48 window_, 104 window_,
49 element_bounds().width(), 105 popup_width,
50 element_bounds().height() * autofill_values.size()); 106 row_height_ * autofill_values().size());
51 107
52 gtk_widget_show(window_); 108 gtk_widget_show(window_);
53 109
54 GtkWidget* toplevel = gtk_widget_get_toplevel(parent_); 110 GtkWidget* toplevel = gtk_widget_get_toplevel(parent_);
55 CHECK(gtk_widget_is_toplevel(toplevel)); 111 CHECK(gtk_widget_is_toplevel(toplevel));
56 ui::StackPopupWindow(window_, toplevel); 112 ui::StackPopupWindow(window_, toplevel);
57 } 113 }
58 114
59 gboolean AutofillPopupViewGtk::HandleExpose(GtkWidget* widget, 115 gboolean AutofillPopupViewGtk::HandleExpose(GtkWidget* widget,
60 GdkEventExpose* event) { 116 GdkEventExpose* event) {
117 gfx::Rect window_rect = GetWindowRect(event->window);
118 gfx::Rect damage_rect = gfx::Rect(event->area);
119
120 cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(gtk_widget_get_window(widget)));
Elliot Glaysher 2012/01/12 20:34:11 When I said above to cut GDK_DRAWABLE, please don'
121 gdk_cairo_rectangle(cr, &event->area);
122 cairo_clip(cr);
123
124 // This assert is kinda ugly, but it would be more currently unneeded work
125 // to support painting a border that isn't 1 pixel thick. There is no point
126 // in writing that code now, and explode if that day ever comes.
127 COMPILE_ASSERT(kBorderThickness == 1, border_1px_implied);
128 // Draw the 1px border around the entire window.
129 gdk_cairo_set_source_color(cr, &kBorderColor);
130 cairo_rectangle(cr, 0, 0, window_rect.width(), window_rect.height());
131 cairo_stroke(cr);
132
133 SetupLayout(window_rect, kTextColor);
134
135 int actual_content_width, actual_content_height;
136 pango_layout_get_size(layout_, &actual_content_width, &actual_content_height);
137 actual_content_width /= PANGO_SCALE;
138 actual_content_height /= PANGO_SCALE;
139
140 for (size_t i = 0; i < autofill_values().size(); ++i) {
141 gfx::Rect line_rect =
142 GetRectForItemByIndex(i, window_rect.width(), row_height_);
143 // Only repaint and layout damaged lines.
144 if (!line_rect.Intersects(damage_rect))
145 continue;
146
147 if (separator_index() == static_cast<int>(i)) {
148 int line_y = i * row_height_;
149
150 cairo_save(cr);
151 cairo_move_to(cr, 0, line_y);
152 cairo_line_to(cr, window_rect.width(), line_y);
153 cairo_stroke(cr);
154 cairo_restore(cr);
155 }
156
157 // Center the text within the line.
158 int content_y = std::max(
159 line_rect.y(),
160 line_rect.y() + ((row_height_ - actual_content_height) / 2));
161
162 // Draw the autofill value.
163 SetTextToDraw(layout_, autofill_values()[i]);
164
165 cairo_save(cr);
166 cairo_move_to(cr, 0, content_y);
167 pango_cairo_show_layout(cr, layout_);
168 cairo_restore(cr);
169
170 // Draw the autofill label.
171 int x_align_left = window_rect.width() -
172 font_.GetStringWidth(autofill_labels()[i]);
173 SetTextToDraw(layout_, autofill_labels()[i]);
174
175 cairo_save(cr);
176 cairo_move_to(cr, x_align_left, line_rect.y());
177 pango_cairo_show_layout(cr, layout_);
178 cairo_restore(cr);
179 }
180
181 cairo_destroy(cr);
182
61 return TRUE; 183 return TRUE;
62 } 184 }
185
186 void AutofillPopupViewGtk::SetupLayout(const gfx::Rect& window_rect,
187 const GdkColor& text_color) {
188 int allocated_content_width = window_rect.width();
189 pango_layout_set_width(layout_, allocated_content_width * PANGO_SCALE);
190 pango_layout_set_height(layout_, row_height_ * PANGO_SCALE);
191
192 PangoAttrList* attrs = pango_attr_list_new();
193
194 PangoAttribute* fg_attr = pango_attr_foreground_new(text_color.red,
195 text_color.green,
196 text_color.blue);
197 pango_attr_list_insert(attrs, fg_attr); // Ownership taken.
198
199
200 pango_layout_set_attributes(layout_, attrs); // Ref taken.
201 pango_attr_list_unref(attrs);
202 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698