From 11377011d3825a04f0898d999ff29cc4cf7c9a61 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Date: Wed, 10 Sep 2008 16:22:17 +0000 Subject: [PATCH] 2008-09-10 Alberto Garcia * doc/hildon-docs.sgml * doc/hildon.types * examples/Makefile.am * examples/hildon-text-view-example.c * src/Makefile.am * src/hildon-text-view.c * src/hildon-text-view.h * src/hildon.h: New HildonTextView widget, with example. --- ChangeLog | 12 ++ doc/hildon-docs.sgml | 1 + doc/hildon.types | 2 + examples/Makefile.am | 6 + examples/hildon-text-view-example.c | 139 +++++++++++++++++++ src/Makefile.am | 2 + src/hildon-text-view.c | 251 +++++++++++++++++++++++++++++++++++ src/hildon-text-view.h | 79 +++++++++++ src/hildon.h | 1 + 9 files changed, 493 insertions(+) create mode 100644 examples/hildon-text-view-example.c create mode 100644 src/hildon-text-view.c create mode 100644 src/hildon-text-view.h diff --git a/ChangeLog b/ChangeLog index 19a5610..bb7fb28 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2008-09-10 Alberto Garcia + + * doc/hildon-docs.sgml + * doc/hildon.types + * examples/Makefile.am + * examples/hildon-text-view-example.c + * src/Makefile.am + * src/hildon-text-view.c + * src/hildon-text-view.h + * src/hildon.h: + New HildonTextView widget, with example. + 2008-09-10 Claudio Saavedra * po/POTFILES.in: Add missing files with translatable strings. diff --git a/doc/hildon-docs.sgml b/doc/hildon-docs.sgml index 4ec8062..d95c27c 100644 --- a/doc/hildon-docs.sgml +++ b/doc/hildon-docs.sgml @@ -63,6 +63,7 @@ + diff --git a/doc/hildon.types b/doc/hildon.types index 2bac5da..52e21a8 100644 --- a/doc/hildon.types +++ b/doc/hildon.types @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -85,6 +86,7 @@ hildon_pannable_area_get_type hildon_stackable_window_get_type hildon_app_menu_get_type hildon_entry_get_type +hildon_text_view_get_type hildon_button_get_type hildon_touch_selector_get_type hildon_touch_selector_entry_get_type diff --git a/examples/Makefile.am b/examples/Makefile.am index d4fbb35..7c4e4e9 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -50,6 +50,7 @@ noinst_PROGRAMS = hildon-window-example \ hildon-app-menu-example \ hildon-stackable-window-example \ hildon-entry-example \ + hildon-text-view-example \ hildon-button-example \ hildon-dialog-example \ hildon-date-button-example \ @@ -305,6 +306,11 @@ hildon_entry_example_LDADD = $(HILDON_OBJ_LIBS) hildon_entry_example_CFLAGS = $(HILDON_OBJ_CFLAGS) hildon_entry_example_SOURCES = hildon-entry-example.c +# Hildon text view +hildon_text_view_example_LDADD = $(HILDON_OBJ_LIBS) +hildon_text_view_example_CFLAGS = $(HILDON_OBJ_CFLAGS) +hildon_text_view_example_SOURCES = hildon-text-view-example.c + # Hildon button hildon_button_example_LDADD = $(HILDON_OBJ_LIBS) hildon_button_example_CFLAGS = $(HILDON_OBJ_CFLAGS) diff --git a/examples/hildon-text-view-example.c b/examples/hildon-text-view-example.c new file mode 100644 index 0000000..bc234fa --- /dev/null +++ b/examples/hildon-text-view-example.c @@ -0,0 +1,139 @@ +/* + * This file is a part of hildon examples + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include + +HildonTextView *textview; +GtkTextBuffer *buffer; + +static void +set_text_button_clicked (GtkButton *button, + HildonEntry *entry) +{ + gtk_text_buffer_set_text (buffer, hildon_entry_get_text (entry), -1); +} + +static void +set_placeholder_button_clicked (GtkButton *button, + HildonEntry *entry) +{ + hildon_text_view_set_placeholder (textview, hildon_entry_get_text (entry)); +} + +static void +text_changed (GtkTextBuffer *buffer, + GtkLabel *label) +{ + const gchar *text; + GtkTextIter start, end; + + gtk_text_buffer_get_start_iter (buffer, &start); + gtk_text_buffer_get_end_iter (buffer, &end); + + text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE); + + if (text != NULL && *text != '\0') { + gtk_label_set_text (label, text); + } else { + gtk_label_set_text (label, "(empty)"); + } +} + +int +main (int argc, + char **argv) +{ + GtkWidget *win; + GtkWidget *label; + GtkWidget *textentry, *textbutton, *texthbox; + GtkWidget *placeholderentry, *placeholderbutton, *placeholderhbox; + GtkWidget *textviewframe; + GtkBox *vbox; + + gtk_init (&argc, &argv); + + /* Style to paint the placeholder text in red */ + gtk_rc_parse_string ("style \"placeholder\" {\n" + "text[NORMAL] = \"#C03030\"" + "}\n" + "widget \"*.hildon-text-view-placeholder\" style \"placeholder\"\n"); + + /* Window and vbox to pack everything */ + win = hildon_stackable_window_new (); + vbox = GTK_BOX (gtk_vbox_new (FALSE, 10)); + + /* Entry to modify the text of the main HildonEntry */ + textentry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH); + textbutton = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH); + gtk_button_set_label (GTK_BUTTON (textbutton), "Set text view text"); + texthbox = gtk_hbox_new (FALSE, 10); + + /* Entry to modify the placeholder of the main HildonEntry */ + placeholderentry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH); + placeholderbutton = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH); + gtk_button_set_label (GTK_BUTTON (placeholderbutton), "Set text view placeholder"); + placeholderhbox = gtk_hbox_new (FALSE, 10); + + /* The text view */ + textview = HILDON_TEXT_VIEW (hildon_text_view_new ()); + buffer = hildon_text_view_get_buffer (textview); + hildon_text_view_set_placeholder (textview, "This is a placeholder - change using the buttons above"); + textviewframe = gtk_frame_new (NULL); + + /* This label is used to show the contents -not the placeholder- of the HildonTextView */ + label = gtk_label_new (NULL); + + /* Pack all widgets */ + gtk_box_pack_start (GTK_BOX (texthbox), textentry, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (texthbox), textbutton, FALSE, FALSE, 0); + + gtk_box_pack_start (GTK_BOX (placeholderhbox), placeholderentry, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (placeholderhbox), placeholderbutton, FALSE, FALSE, 0); + + gtk_container_add (GTK_CONTAINER (textviewframe), GTK_WIDGET (textview)); + + gtk_box_pack_start (vbox, texthbox, FALSE, FALSE, 0); + gtk_box_pack_start (vbox, placeholderhbox, FALSE, FALSE, 0); + gtk_box_pack_start (vbox, textviewframe, TRUE, TRUE, 0); + gtk_box_pack_start (vbox, gtk_label_new ("Contents of the text view:"), TRUE, TRUE, 0); + gtk_box_pack_start (vbox, label, TRUE, TRUE, 0); + + gtk_container_set_border_width (GTK_CONTAINER (win), 20); + gtk_container_add (GTK_CONTAINER (win), GTK_WIDGET (vbox)); + + /* Connect signals */ + g_signal_connect (win, "destroy", G_CALLBACK (gtk_main_quit), NULL); + g_signal_connect (buffer, "changed", G_CALLBACK (text_changed), label); + g_signal_connect (textbutton, "clicked", + G_CALLBACK (set_text_button_clicked), textentry); + g_signal_connect (placeholderbutton, "clicked", + G_CALLBACK (set_placeholder_button_clicked), placeholderentry); + + /* Set the initial state of the label */ + text_changed (buffer, GTK_LABEL (label)); + + /* Run example */ + gtk_widget_show_all (win); + gtk_main (); + + return 0; +} diff --git a/src/Makefile.am b/src/Makefile.am index 0b24ea8..6afc52c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -74,6 +74,7 @@ libhildon_@API_VERSION_MAJOR@_la_SOURCES = \ hildon-calendar.c \ hildon-pannable-area.c \ hildon-entry.c \ + hildon-text-view.c \ hildon-bread-crumb-trail.c \ hildon-bread-crumb.c \ hildon-bread-crumb-widget.c \ @@ -137,6 +138,7 @@ libhildon_@API_VERSION_MAJOR@_public_headers = \ hildon-calendar.h \ hildon-pannable-area.h \ hildon-entry.h \ + hildon-text-view.h \ hildon-bread-crumb-trail.h \ hildon-bread-crumb.h \ hildon-app-menu.h \ diff --git a/src/hildon-text-view.c b/src/hildon-text-view.c new file mode 100644 index 0000000..55534ab --- /dev/null +++ b/src/hildon-text-view.c @@ -0,0 +1,251 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +/** + * SECTION:hildon-text-view + * @short_description: Widget representing a text view in the Hildon framework. + * + * The #HildonTextView is a GTK widget which represents a text + * view. It is derived from the #GtkTextView widget and provides + * additional commodities specific to the Hildon framework. + * + * Besides all the features inherited from #GtkTextView, a + * #HildonTextView can also have a placeholder text. This text will be + * shown if the text view is empty and doesn't have the input focus, + * but it's otherwise ignored. Thus, calls to + * hildon_text_view_get_buffer() will never return the placeholder + * text, not even when it's being displayed. + * + * Although #HildonTextView is derived from #GtkTextView, + * gtk_text_view_get_buffer() and gtk_text_view_set_buffer() must + * never be used to get/set the buffer in this + * widget. hildon_text_view_get_buffer() and + * hildon_text_view_set_buffer() must be used instead. + */ + +#include "hildon-text-view.h" + +G_DEFINE_TYPE (HildonTextView, hildon_text_view, GTK_TYPE_TEXT_VIEW); + +#define HILDON_TEXT_VIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_TEXT_VIEW, HildonTextViewPrivate)); + +typedef struct _HildonTextViewPrivate HildonTextViewPrivate; + +struct _HildonTextViewPrivate +{ + GtkTextBuffer *main_buffer; /* Used to show the "real" contents */ + GtkTextBuffer *placeholder_buffer; /* Internal, used to display the placeholder */ + gulong changed_id; /* ID of the main_buffer::changed signal handler */ +}; + +static const gchar *placeholder_widget_name = "hildon-text-view-placeholder"; + +/* Function used to decide whether to show the placeholder or not */ +static void +hildon_text_view_refresh_contents (GtkWidget *text_view) +{ + HildonTextViewPrivate *priv = HILDON_TEXT_VIEW_GET_PRIVATE (text_view); + gint bufsize = gtk_text_buffer_get_char_count (priv->main_buffer); + + if ((bufsize > 0) || GTK_WIDGET_HAS_FOCUS (text_view)) { + /* Display the main buffer if it contains text or the widget is focused */ + gtk_widget_set_name (text_view, NULL); + gtk_text_view_set_buffer (GTK_TEXT_VIEW (text_view), priv->main_buffer); + } else { + /* Otherwise, display the placeholder */ + gtk_widget_set_name (text_view, placeholder_widget_name); + gtk_text_view_set_buffer (GTK_TEXT_VIEW (text_view), priv->placeholder_buffer); + } +} + +/** + * hildon_text_view_set_buffer: + * @text_view: a #HildonTextView + * @buffer: a #GtkTextBuffer + * + * Sets @buffer as the buffer being displayed by @text_view. The + * previous buffer displayed by the text view is unreferenced, and a + * reference is added to @buffer. If you owned a reference to @buffer + * before passing it to this function, you must remove that reference + * yourself + * + * Note that you must never use gtk_text_view_set_buffer() to set the + * buffer of a #HildonTextView. + */ +void +hildon_text_view_set_buffer (HildonTextView *text_view, + GtkTextBuffer *buffer) +{ + HildonTextViewPrivate *priv; + + g_return_if_fail (HILDON_IS_TEXT_VIEW (text_view)); + g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer)); + + priv = HILDON_TEXT_VIEW_GET_PRIVATE (text_view); + + /* If this is the same buffer, don't do anything */ + if (buffer == priv->main_buffer) + return; + + /* Disconnect the signal handler from the old buffer */ + g_signal_handler_disconnect (priv->main_buffer, priv->changed_id); + + /* Replace the old buffer with the new one */ + g_object_unref (priv->main_buffer); + priv->main_buffer = g_object_ref (buffer); + + /* Attach a callback to the new text buffer */ + priv->changed_id = + g_signal_connect_swapped (priv->main_buffer, "changed", + G_CALLBACK (hildon_text_view_refresh_contents), text_view); + + /* Refresh textview contents */ + hildon_text_view_refresh_contents (GTK_WIDGET (text_view)); +} + +/** + * hildon_text_view_get_buffer: + * @text_view: a #HildonTextView + * + * Returns the text buffer in @text_view. The reference count is not + * incremented; the caller of this function won't own a new reference. + * + * Note that you must never use gtk_text_view_get_buffer() to get the + * buffer from a #HildonTextView. + * + * Also note that placeholder text (set using + * hildon_text_view_set_placeholder()) is never contained in this + * buffer. + * + * Returns: a #GtkTextBuffer + */ +GtkTextBuffer * +hildon_text_view_get_buffer (HildonTextView *text_view) +{ + HildonTextViewPrivate *priv; + + g_return_val_if_fail (HILDON_IS_TEXT_VIEW (text_view), NULL); + + priv = HILDON_TEXT_VIEW_GET_PRIVATE (text_view); + + /* Always return priv->main_buffer even if the placeholder is + * being displayed */ + return priv->main_buffer; +} + +/** + * hildon_text_view_set_placeholder: + * @text_view: a #HildonTextView + * @text: the new text + * + * Sets the placeholder text in @text_view to @text. + */ +void +hildon_text_view_set_placeholder (HildonTextView *text_view, + const gchar *text) +{ + HildonTextViewPrivate *priv; + + g_return_if_fail (HILDON_IS_TEXT_VIEW (text_view) && text != NULL); + + priv = HILDON_TEXT_VIEW_GET_PRIVATE (text_view); + + gtk_text_buffer_set_text (priv->placeholder_buffer, text, -1); +} + +/** + * hildon_text_view_new: + * + * Creates a new text view. + * + * Returns: a new #HildonTextView + */ +GtkWidget * +hildon_text_view_new (void) +{ + GtkWidget *entry = g_object_new (HILDON_TYPE_TEXT_VIEW, NULL); + + return entry; +} + +static gboolean +hildon_text_view_focus_in_event (GtkWidget *widget, + GdkEventFocus *event) +{ + hildon_text_view_refresh_contents (widget); + + if (GTK_WIDGET_CLASS (hildon_text_view_parent_class)->focus_in_event) { + return GTK_WIDGET_CLASS (hildon_text_view_parent_class)->focus_in_event (widget, event); + } else { + return FALSE; + } +} + +static gboolean +hildon_text_view_focus_out_event (GtkWidget *widget, + GdkEventFocus *event) +{ + hildon_text_view_refresh_contents (widget); + + if (GTK_WIDGET_CLASS (hildon_text_view_parent_class)->focus_out_event) { + return GTK_WIDGET_CLASS (hildon_text_view_parent_class)->focus_out_event (widget, event); + } else { + return FALSE; + } +} + +static void +hildon_text_view_finalize (GObject *object) +{ + HildonTextViewPrivate *priv = HILDON_TEXT_VIEW_GET_PRIVATE (object); + + g_signal_handler_disconnect (priv->main_buffer, priv->changed_id); + g_object_unref (priv->main_buffer); + g_object_unref (priv->placeholder_buffer); + + if (G_OBJECT_CLASS (hildon_text_view_parent_class)->finalize) + G_OBJECT_CLASS (hildon_text_view_parent_class)->finalize (object); +} + +static void +hildon_text_view_class_init (HildonTextViewClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass *)klass; + GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; + + gobject_class->finalize = hildon_text_view_finalize; + widget_class->focus_in_event = hildon_text_view_focus_in_event; + widget_class->focus_out_event = hildon_text_view_focus_out_event; + + g_type_class_add_private (klass, sizeof (HildonTextViewPrivate)); +} + +static void +hildon_text_view_init (HildonTextView *self) +{ + HildonTextViewPrivate *priv = HILDON_TEXT_VIEW_GET_PRIVATE (self); + + priv->main_buffer = gtk_text_buffer_new (NULL); + priv->placeholder_buffer = gtk_text_buffer_new (NULL); + + hildon_text_view_refresh_contents (GTK_WIDGET (self)); + + priv->changed_id = + g_signal_connect_swapped (priv->main_buffer, "changed", + G_CALLBACK (hildon_text_view_refresh_contents), self); +} diff --git a/src/hildon-text-view.h b/src/hildon-text-view.h new file mode 100644 index 0000000..7075204 --- /dev/null +++ b/src/hildon-text-view.h @@ -0,0 +1,79 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +#ifndef __HILDON_TEXT_VIEW_H__ +#define __HILDON_TEXT_VIEW_H__ + +#include + +G_BEGIN_DECLS + +#define HILDON_TYPE_TEXT_VIEW \ + (hildon_text_view_get_type()) + +#define HILDON_TEXT_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + HILDON_TYPE_TEXT_VIEW, HildonTextView)) + +#define HILDON_TEXT_VIEW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + HILDON_TYPE_TEXT_VIEW, HildonTextViewClass)) + +#define HILDON_IS_TEXT_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_TEXT_VIEW)) + +#define HILDON_IS_TEXT_VIEW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_TEXT_VIEW)) + +#define HILDON_TEXT_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + HILDON_TYPE_TEXT_VIEW, HildonTextViewClass)) + +typedef struct _HildonTextView HildonTextView; + +typedef struct _HildonTextViewClass HildonTextViewClass; + +struct _HildonTextViewClass +{ + GtkTextViewClass parent_class; +}; + +struct _HildonTextView +{ + GtkTextView parent; +}; + + +GType +hildon_text_view_get_type (void) G_GNUC_CONST; + +GtkWidget * +hildon_text_view_new (void); + +void +hildon_text_view_set_buffer (HildonTextView *text_view, + GtkTextBuffer *buffer); + +GtkTextBuffer * +hildon_text_view_get_buffer (HildonTextView *text_view); + +void +hildon_text_view_set_placeholder (HildonTextView *text_view, + const gchar *text); + +G_END_DECLS + +#endif /* __HILDON_TEXT_VIEW_H__ */ diff --git a/src/hildon.h b/src/hildon.h index 1947be0..f76eaa8 100644 --- a/src/hildon.h +++ b/src/hildon.h @@ -74,6 +74,7 @@ #include "hildon-bread-crumb-trail.h" #include "hildon-pannable-area.h" #include "hildon-entry.h" +#include "hildon-text-view.h" #include "hildon-app-menu.h" #include "hildon-button.h" #include "hildon-check-button.h" -- 1.7.9.5