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

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: Replacing header with typedefs 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 "chrome/browser/ui/gtk/gtk_util.h"
10 #include "ui/base/gtk/gtk_compat.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/native_widget_types.h"
14 #include "ui/gfx/rect.h"
15
16 namespace {
17 const GdkColor kBorderColor = GDK_COLOR_RGB(0xc7, 0xca, 0xce);
18 const GdkColor kTextColor = GDK_COLOR_RGB(0x00, 0x00, 0x00);
19
20 // The amount of minimum padding between the Autofill value and label in pixels.
21 const int kMiddlePadding = 10;
22
23 // We have a 1 pixel border around the entire results popup.
24 const int kBorderThickness = 1;
25
26 gfx::Rect GetWindowRect(GdkWindow* window) {
27 return gfx::Rect(gdk_window_get_width(window),
28 gdk_window_get_height(window));
29 }
30
31 // Returns the rectangle containing the item at position |index| in the popup.
32 gfx::Rect GetRectForRow(size_t index, int width, int height) {
33 return gfx::Rect(0, (index * height), width, height);
34 }
35
36 } // namespace
9 37
10 AutofillPopupViewGtk::AutofillPopupViewGtk(content::WebContents* web_contents, 38 AutofillPopupViewGtk::AutofillPopupViewGtk(content::WebContents* web_contents,
11 GtkWidget* parent) 39 GtkWidget* parent)
12 : AutofillPopupView(web_contents), 40 : AutofillPopupView(web_contents),
13 parent_(parent), 41 parent_(parent),
14 window_(gtk_window_new(GTK_WINDOW_POPUP)) { 42 window_(gtk_window_new(GTK_WINDOW_POPUP)) {
15 CHECK(parent != NULL); 43 CHECK(parent != NULL);
16 gtk_window_set_resizable(GTK_WINDOW(window_), FALSE); 44 gtk_window_set_resizable(GTK_WINDOW(window_), FALSE);
17 gtk_widget_set_app_paintable(window_, TRUE); 45 gtk_widget_set_app_paintable(window_, TRUE);
18 gtk_widget_set_double_buffered(window_, TRUE); 46 gtk_widget_set_double_buffered(window_, TRUE);
19 47
20 // Setup the window to ensure it recieves the expose event. 48 // Setup the window to ensure it recieves the expose event.
21 gtk_widget_add_events(window_, GDK_EXPOSURE_MASK); 49 gtk_widget_add_events(window_, GDK_EXPOSURE_MASK);
22 g_signal_connect(window_, "expose-event", 50 g_signal_connect(window_, "expose-event",
23 G_CALLBACK(HandleExposeThunk), this); 51 G_CALLBACK(HandleExposeThunk), this);
52
53 // Cache the layout so we don't have to create it for every expose.
54 layout_ = gtk_widget_create_pango_layout(window_, NULL);
55
56 row_height_ = font_.GetHeight();
24 } 57 }
25 58
26 AutofillPopupViewGtk::~AutofillPopupViewGtk() { 59 AutofillPopupViewGtk::~AutofillPopupViewGtk() {
60 g_object_unref(layout_);
27 gtk_widget_destroy(window_); 61 gtk_widget_destroy(window_);
28 } 62 }
29 63
30 void AutofillPopupViewGtk::Hide() { 64 void AutofillPopupViewGtk::Hide() {
31 gtk_widget_hide(window_); 65 gtk_widget_hide(window_);
32 } 66 }
33 67
34 // TODO(csharp): Actually show the values. 68 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; 69 gint origin_x, origin_y;
41 gdk_window_get_origin(gtk_widget_get_window(parent_), &origin_x, &origin_y); 70 gdk_window_get_origin(gtk_widget_get_window(parent_), &origin_x, &origin_y);
42 71
72 // Move the popup to appear right below the text field it is using.
43 gtk_window_move(GTK_WINDOW(window_), 73 gtk_window_move(GTK_WINDOW(window_),
44 origin_x + element_bounds().x(), 74 origin_x + element_bounds().x(),
45 origin_y + element_bounds().y() + element_bounds().height()); 75 origin_y + element_bounds().y() + element_bounds().height());
46 76
77 // Find out the maximum bounds required by the popup.
78 // TODO(csharp): Once the icon is also displayed it will affect the required
79 // size so it will need to be included in the calculation.
80 int popup_width = element_bounds().width();
81 DCHECK_EQ(autofill_values().size(), autofill_labels().size());
82 for (size_t i = 0; i < autofill_values().size(); ++i) {
83 popup_width = std::max(popup_width,
84 font_.GetStringWidth(autofill_values()[i]) +
85 kMiddlePadding +
86 font_.GetStringWidth(autofill_labels()[i]));
87 }
88
47 gtk_widget_set_size_request( 89 gtk_widget_set_size_request(
48 window_, 90 window_,
49 element_bounds().width(), 91 popup_width,
50 element_bounds().height() * autofill_values.size()); 92 row_height_ * autofill_values().size());
51 93
52 gtk_widget_show(window_); 94 gtk_widget_show(window_);
53 95
54 GtkWidget* toplevel = gtk_widget_get_toplevel(parent_); 96 GtkWidget* toplevel = gtk_widget_get_toplevel(parent_);
55 CHECK(gtk_widget_is_toplevel(toplevel)); 97 CHECK(gtk_widget_is_toplevel(toplevel));
56 ui::StackPopupWindow(window_, toplevel); 98 ui::StackPopupWindow(window_, toplevel);
57 } 99 }
58 100
59 gboolean AutofillPopupViewGtk::HandleExpose(GtkWidget* widget, 101 gboolean AutofillPopupViewGtk::HandleExpose(GtkWidget* widget,
60 GdkEventExpose* event) { 102 GdkEventExpose* event) {
103 gfx::Rect window_rect = GetWindowRect(event->window);
104 gfx::Rect damage_rect = gfx::Rect(event->area);
105
106 cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(gtk_widget_get_window(widget)));
107 gdk_cairo_rectangle(cr, &event->area);
108 cairo_clip(cr);
109
110 // This assert is kinda ugly, but it would be more currently unneeded work
111 // to support painting a border that isn't 1 pixel thick. There is no point
112 // in writing that code now, and explode if that day ever comes.
113 COMPILE_ASSERT(kBorderThickness == 1, border_1px_implied);
114 // Draw the 1px border around the entire window.
115 gdk_cairo_set_source_color(cr, &kBorderColor);
116 cairo_rectangle(cr, 0, 0, window_rect.width(), window_rect.height());
117 cairo_stroke(cr);
118
119 SetupLayout(window_rect, kTextColor);
120
121 int actual_content_width, actual_content_height;
122 pango_layout_get_size(layout_, &actual_content_width, &actual_content_height);
123 actual_content_width /= PANGO_SCALE;
124 actual_content_height /= PANGO_SCALE;
125
126 for (size_t i = 0; i < autofill_values().size(); ++i) {
127 gfx::Rect line_rect = GetRectForRow(i, window_rect.width(), row_height_);
128 // Only repaint and layout damaged lines.
129 if (!line_rect.Intersects(damage_rect))
130 continue;
131
132 if (separator_index() == static_cast<int>(i)) {
133 int line_y = i * row_height_;
134
135 cairo_save(cr);
136 cairo_move_to(cr, 0, line_y);
137 cairo_line_to(cr, window_rect.width(), line_y);
138 cairo_stroke(cr);
139 cairo_restore(cr);
140 }
141
142 // Center the text within the line.
143 int content_y = std::max(
144 line_rect.y(),
145 line_rect.y() + ((row_height_ - actual_content_height) / 2));
146
147 // Draw the value.
148 gtk_util::SetLayoutText(layout_, autofill_values()[i]);
149
150 cairo_save(cr);
151 cairo_move_to(cr, 0, content_y);
152 pango_cairo_show_layout(cr, layout_);
153 cairo_restore(cr);
154
155 // Draw the label.
156 int x_align_left = window_rect.width() -
157 font_.GetStringWidth(autofill_labels()[i]);
158 gtk_util::SetLayoutText(layout_, autofill_labels()[i]);
159
160 cairo_save(cr);
161 cairo_move_to(cr, x_align_left, line_rect.y());
162 pango_cairo_show_layout(cr, layout_);
163 cairo_restore(cr);
164 }
165
166 cairo_destroy(cr);
167
61 return TRUE; 168 return TRUE;
62 } 169 }
170
171 void AutofillPopupViewGtk::SetupLayout(const gfx::Rect& window_rect,
172 const GdkColor& text_color) {
173 int allocated_content_width = window_rect.width();
174 pango_layout_set_width(layout_, allocated_content_width * PANGO_SCALE);
175 pango_layout_set_height(layout_, row_height_ * PANGO_SCALE);
176
177 PangoAttrList* attrs = pango_attr_list_new();
178
179 PangoAttribute* fg_attr = pango_attr_foreground_new(text_color.red,
180 text_color.green,
181 text_color.blue);
182 pango_attr_list_insert(attrs, fg_attr); // Ownership taken.
183
184
185 pango_layout_set_attributes(layout_, attrs); // Ref taken.
186 pango_attr_list_unref(attrs);
187 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.h ('k') | chrome/browser/ui/gtk/gtk_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698