summaryrefslogtreecommitdiffstats
path: root/views
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-23 17:38:03 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-23 17:38:03 +0000
commit9f221e935d57a911844598748f9fde346a96e464 (patch)
tree29cfd69f5219511e8e67a109e3f33c6b78e1b3c8 /views
parentbf1ca900cb966149e6c08a48a27d4fa2120f6631 (diff)
downloadchromium_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.cc64
-rw-r--r--views/controls/textfield/gtk_views_entry.h52
-rw-r--r--views/controls/textfield/native_textfield_gtk.cc42
-rw-r--r--views/controls/textfield/native_textfield_gtk.h6
-rw-r--r--views/controls/textfield/textfield.h15
-rw-r--r--views/examples/textfield_example.h1
-rw-r--r--views/views.gyp2
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',