diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-23 17:38:03 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-23 17:38:03 +0000 |
commit | 9f221e935d57a911844598748f9fde346a96e464 (patch) | |
tree | 29cfd69f5219511e8e67a109e3f33c6b78e1b3c8 /views | |
parent | bf1ca900cb966149e6c08a48a27d4fa2120f6631 (diff) | |
download | chromium_src-9f221e935d57a911844598748f9fde346a96e464.zip chromium_src-9f221e935d57a911844598748f9fde346a96e464.tar.gz chromium_src-9f221e935d57a911844598748f9fde346a96e464.tar.bz2 |
Adds the ability to display text in a textfield when the text is
empty.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/1155008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42353 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
-rw-r--r-- | views/controls/textfield/gtk_views_entry.cc | 64 | ||||
-rw-r--r-- | views/controls/textfield/gtk_views_entry.h | 52 | ||||
-rw-r--r-- | views/controls/textfield/native_textfield_gtk.cc | 42 | ||||
-rw-r--r-- | views/controls/textfield/native_textfield_gtk.h | 6 | ||||
-rw-r--r-- | views/controls/textfield/textfield.h | 15 | ||||
-rw-r--r-- | views/examples/textfield_example.h | 1 | ||||
-rw-r--r-- | views/views.gyp | 2 |
7 files changed, 165 insertions, 17 deletions
diff --git a/views/controls/textfield/gtk_views_entry.cc b/views/controls/textfield/gtk_views_entry.cc new file mode 100644 index 0000000..dbb0be4 --- /dev/null +++ b/views/controls/textfield/gtk_views_entry.cc @@ -0,0 +1,64 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "views/controls/textfield/gtk_views_entry.h" + +#include "app/gfx/canvas_paint.h" +#include "base/utf_string_conversions.h" +#include "gfx/insets.h" +#include "gfx/skia_utils_gtk.h" +#include "views/controls/textfield/native_textfield_gtk.h" +#include "views/controls/textfield/textfield.h" + +G_BEGIN_DECLS + +G_DEFINE_TYPE(GtkViewsEntry, gtk_views_entry, GTK_TYPE_ENTRY) + +static gint gtk_views_entry_expose_event(GtkWidget *widget, + GdkEventExpose *event) { + gint result = GTK_WIDGET_CLASS(gtk_views_entry_parent_class)->expose_event( + widget, event); + + GtkEntry* entry = GTK_ENTRY(widget); + views::NativeTextfieldGtk* host = GTK_VIEWS_ENTRY(widget)->host; + + // Internally GtkEntry creates an additional window (text_area) that the + // text is drawn to. We only need paint after that window has painted. + if (host && event->window == entry->text_area && + !host->textfield()->text_to_display_when_empty().empty() && + g_utf8_strlen(gtk_entry_get_text(entry), -1) == 0) { + gfx::CanvasPaint canvas(event); + if (!canvas.is_empty()) { + gfx::Insets insets = + views::NativeTextfieldGtk::GetEntryInnerBorder(entry); + gfx::Font font = host->textfield()->font(); + const string16 text = host->textfield()->text_to_display_when_empty(); + canvas.DrawStringInt( + UTF16ToWide(text), font, + gfx::GdkColorToSkColor(widget->style->text[GTK_STATE_INSENSITIVE]), + insets.left(), insets.top(), + widget->allocation.width - insets.width(), font.height()); + } + } + + return result; +} + +static void gtk_views_entry_class_init(GtkViewsEntryClass* views_entry_class) { + GtkWidgetClass* widget_class = + reinterpret_cast<GtkWidgetClass*>(views_entry_class); + widget_class->expose_event = gtk_views_entry_expose_event; +} + +static void gtk_views_entry_init(GtkViewsEntry* entry) { + entry->host = NULL; +} + +GtkWidget* gtk_views_entry_new(views::NativeTextfieldGtk* host) { + gpointer entry = g_object_new(GTK_TYPE_VIEWS_ENTRY, NULL); + GTK_VIEWS_ENTRY(entry)->host = host; + return GTK_WIDGET(entry); +} + +G_END_DECLS diff --git a/views/controls/textfield/gtk_views_entry.h b/views/controls/textfield/gtk_views_entry.h new file mode 100644 index 0000000..e5b370d --- /dev/null +++ b/views/controls/textfield/gtk_views_entry.h @@ -0,0 +1,52 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef VIEWS_WIDGET_GTK_VIEWS_ENTRY_H_ +#define VIEWS_WIDGET_GTK_VIEWS_ENTRY_H_ + +#include <gdk/gdk.h> +#include <gtk/gtkentry.h> + +namespace views { +class NativeTextfieldGtk; +} + +// GtkViewsEntry is a subclass of GtkEntry that can draw text when the text in +// the entry is empty. For example, this could show the text 'password' in a +// password field when the text is empty. GtkViewsEntry is used internally by +// NativeTextfieldGtk. + +G_BEGIN_DECLS + +#define GTK_TYPE_VIEWS_ENTRY (gtk_views_entry_get_type ()) +#define GTK_VIEWS_ENTRY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_VIEWS_ENTRY, GtkViewsEntry)) +#define GTK_VIEWS_ENTRY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_VIEWS_ENTRY, GtkViewsEntryClass)) +#define GTK_IS_VIEWS_ENTRY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_VIEWS_ENTRY)) +#define GTK_IS_VIEWS_ENTRY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_VIEWS_ENTRY)) +#define GTK_VIEWS_ENTRY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_VIEWS_ENTRY, GtkViewsEntry)) + +typedef struct _GtkViewsEntry GtkViewsEntry; +typedef struct _GtkViewsEntryClass GtkViewsEntryClass; + +struct _GtkViewsEntry { + GtkEntry entry; + views::NativeTextfieldGtk* host; +}; + +struct _GtkViewsEntryClass { + GtkEntryClass parent_class; +}; + +GtkWidget* gtk_views_entry_new(views::NativeTextfieldGtk* host); + +GType gtk_views_entry_get_type(); + +G_END_DECLS + +#endif // VIEWS_WIDGET_GTK_VIEWS_ENTRY_H diff --git a/views/controls/textfield/native_textfield_gtk.cc b/views/controls/textfield/native_textfield_gtk.cc index 4aef06f..1d4dd23 100644 --- a/views/controls/textfield/native_textfield_gtk.cc +++ b/views/controls/textfield/native_textfield_gtk.cc @@ -11,11 +11,13 @@ #include "gfx/gtk_util.h" #include "gfx/insets.h" #include "gfx/skia_utils_gtk.h" +#include "views/controls/textfield/gtk_views_entry.h" #include "views/controls/textfield/textfield.h" namespace views { + // A character used to hide a text in password mode. -const char kPasswordChar = '*'; +static const char kPasswordChar = '*'; //////////////////////////////////////////////////////////////////////////////// // NativeTextfieldGtk, public: @@ -33,6 +35,26 @@ NativeTextfieldGtk::NativeTextfieldGtk(Textfield* textfield) NativeTextfieldGtk::~NativeTextfieldGtk() { } +// Returns the inner border of an entry. +// static +gfx::Insets NativeTextfieldGtk::GetEntryInnerBorder(GtkEntry* entry) { + const GtkBorder* inner_border = gtk_entry_get_inner_border(entry); + if (inner_border) + return gfx::Insets(*inner_border); + + // No explicit border set, try the style. + GtkBorder* style_border; + gtk_widget_style_get(GTK_WIDGET(entry), "inner-border", &style_border, NULL); + if (style_border) { + gfx::Insets insets = gfx::Insets(*style_border); + gtk_border_free(style_border); + return insets; + } + + // If border is null, Gtk uses 2 on all sides. + return gfx::Insets(2, 2, 2, 2); +} + //////////////////////////////////////////////////////////////////////////////// // NativeTextfieldGtk, NativeTextfieldWrapper implementation: @@ -150,21 +172,7 @@ gfx::Insets NativeTextfieldGtk::CalculateInsets() { GtkEntry* entry = GTK_ENTRY(widget); gfx::Insets insets; - const GtkBorder* inner_border = gtk_entry_get_inner_border(entry); - if (inner_border) { - insets += gfx::Insets(*inner_border); - } else { - // No explicit border set, try the style. - GtkBorder* style_border; - gtk_widget_style_get(widget, "inner-border", &style_border, NULL); - if (style_border) { - insets += gfx::Insets(*style_border); - gtk_border_free(style_border); - } else { - // If border is null, Gtk uses 2 on all sides. - insets += gfx::Insets(2, 2, 2, 2); - } - } + insets += GetEntryInnerBorder(entry); if (entry->has_frame) { insets += gfx::Insets(widget->style->ythickness, @@ -240,7 +248,7 @@ gboolean NativeTextfieldGtk::OnChanged() { // NativeTextfieldGtk, NativeControlGtk overrides: void NativeTextfieldGtk::CreateNativeControl() { - NativeControlCreated(gtk_entry_new()); + NativeControlCreated(gtk_views_entry_new(this)); gtk_entry_set_invisible_char(GTK_ENTRY(native_view()), static_cast<gunichar>(kPasswordChar)); textfield_->UpdateAllProperties(); diff --git a/views/controls/textfield/native_textfield_gtk.h b/views/controls/textfield/native_textfield_gtk.h index 7622521..0e4a1b5 100644 --- a/views/controls/textfield/native_textfield_gtk.h +++ b/views/controls/textfield/native_textfield_gtk.h @@ -19,6 +19,12 @@ class NativeTextfieldGtk : public NativeControlGtk, explicit NativeTextfieldGtk(Textfield* parent); ~NativeTextfieldGtk(); + // Returns the textfield this NativeTextfieldGtk wraps. + Textfield* textfield() const { return textfield_; } + + // Returns the inner border of the entry. + static gfx::Insets GetEntryInnerBorder(GtkEntry* entry); + // Overridden from NativeTextfieldWrapper: virtual string16 GetText() const; virtual void UpdateText(); diff --git a/views/controls/textfield/textfield.h b/views/controls/textfield/textfield.h index eed9feb..4b8076c 100644 --- a/views/controls/textfield/textfield.h +++ b/views/controls/textfield/textfield.h @@ -13,6 +13,7 @@ #include "base/basictypes.h" #include "base/keyboard_codes.h" +#include "base/logging.h" #include "base/string16.h" #include "gfx/font.h" #include "views/view.h" @@ -184,6 +185,17 @@ class Textfield : public View { bool draw_border() const { return draw_border_; } void RemoveBorder(); + // Sets the text to display when empty. + void set_text_to_display_when_empty(const string16& text) { + text_to_display_when_empty_ = text; +#if !defined(OS_LINUX) + NOTIMPLEMENTED(); +#endif + } + const string16& text_to_display_when_empty() { + return text_to_display_when_empty_; + } + // Updates all properties on the textfield. This is invoked internally. // Users of Textfield never need to invoke this directly. void UpdateAllProperties(); @@ -274,6 +286,9 @@ class Textfield : public View { // The storage string for the accessibility name associated with this control. std::wstring accessible_name_; + // Text to display when empty. + string16 text_to_display_when_empty_; + DISALLOW_COPY_AND_ASSIGN(Textfield); }; diff --git a/views/examples/textfield_example.h b/views/examples/textfield_example.h index a348cd3..1a03b05 100644 --- a/views/examples/textfield_example.h +++ b/views/examples/textfield_example.h @@ -32,6 +32,7 @@ class TextfieldExample : public ExampleBase, virtual void CreateExampleView(views::View* container) { name_ = new Textfield(); password_ = new Textfield(Textfield::STYLE_PASSWORD); + password_->set_text_to_display_when_empty(ASCIIToUTF16("password")); show_password_ = new views::TextButton(this, L"Show password"); clear_all_ = new views::TextButton(this, L"Clear All"); append_ = new views::TextButton(this, L"Append"); diff --git a/views/views.gyp b/views/views.gyp index 5981083..d6c420d 100644 --- a/views/views.gyp +++ b/views/views.gyp @@ -198,6 +198,8 @@ 'controls/table/table_view2.cc', 'controls/table/table_view2.h', 'controls/table/table_view_observer.h', + 'controls/textfield/gtk_views_entry.cc', + 'controls/textfield/gtk_views_entry.h', 'controls/textfield/textfield.cc', 'controls/textfield/textfield.h', 'controls/textfield/native_textfield_gtk.cc', |