Skip to content
Snippets Groups Projects
Commit 9f221e93 authored by sky@chromium.org's avatar sky@chromium.org
Browse files

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
parent bf1ca900
No related merge requests found
// 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
// 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
......@@ -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();
......
......@@ -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();
......
......@@ -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);
};
......
......@@ -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");
......
......@@ -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',
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment