summaryrefslogtreecommitdiff
path: root/gtk/gtkeditable.c
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2019-02-13 20:16:33 -0500
committerMatthias Clasen <mclasen@redhat.com>2019-02-17 23:07:17 -0500
commit7325f8e2048152974a16107dfa749b171c9fa374 (patch)
treeecd32432e0eb479b1277a361f36610321dc2a3c2 /gtk/gtkeditable.c
parent76be7a50258de62048e21e3e54e8168f8125c60b (diff)
downloadgtk+-7325f8e2048152974a16107dfa749b171c9fa374.tar.gz
editable: Add more to interface
Add all the things to the GtkEditable interface that make sense for most implementations.
Diffstat (limited to 'gtk/gtkeditable.c')
-rw-r--r--gtk/gtkeditable.c848
1 files changed, 671 insertions, 177 deletions
diff --git a/gtk/gtkeditable.c b/gtk/gtkeditable.c
index 50d0df44ba..3ebc45d159 100644
--- a/gtk/gtkeditable.c
+++ b/gtk/gtkeditable.c
@@ -44,12 +44,12 @@
*
* void
* insert_text_handler (GtkEditable *editable,
- * const gchar *text,
- * gint length,
- * gint *position,
+ * const char *text,
+ * int length,
+ * int *position,
* gpointer data)
* {
- * gchar *result = g_utf8_strup (text, length);
+ * char *result = g_utf8_strup (text, length);
*
* g_signal_handlers_block_by_func (editable,
* (gpointer) insert_text_handler, data);
@@ -68,129 +68,267 @@
#include <string.h>
#include "gtkeditable.h"
+#include "gtkentrybuffer.h"
#include "gtkmarshalers.h"
#include "gtkintl.h"
+#include "gtkprivate.h"
+G_DEFINE_INTERFACE (GtkEditable, gtk_editable, GTK_TYPE_WIDGET)
-static void gtk_editable_base_init (gpointer g_class);
+static GQuark quark_editable_data;
+static GtkEditable *
+get_delegate (GtkEditable *editable)
+{
+ GtkEditableInterface *iface = GTK_EDITABLE_GET_IFACE (editable);
+
+ if (iface->get_delegate)
+ return iface->get_delegate (editable);
+
+ return NULL;
+}
-GType
-gtk_editable_get_type (void)
+static void
+gtk_editable_default_do_insert_text (GtkEditable *editable,
+ const char *text,
+ int length,
+ int *position)
{
- static GType editable_type = 0;
+ g_signal_emit_by_name (editable, "insert-text", text, length, position);
+}
- if (!editable_type)
- {
- const GTypeInfo editable_info =
- {
- sizeof (GtkEditableInterface), /* class_size */
- gtk_editable_base_init, /* base_init */
- NULL, /* base_finalize */
- };
-
- editable_type = g_type_register_static (G_TYPE_INTERFACE, I_("GtkEditable"),
- &editable_info, 0);
- }
+#define warn_no_delegate(func) \
+ g_critical ("GtkEditable %s: default implementation called without a delegate", func);
+
+static void
+gtk_editable_default_insert_text (GtkEditable *editable,
+ const char *text,
+ int length,
+ int *position)
+{
+ GtkEditable *delegate = get_delegate (editable);
- return editable_type;
+ if (delegate)
+ gtk_editable_insert_text (delegate, text, length, position);
+ else
+ warn_no_delegate ("insert_text");
}
static void
-gtk_editable_base_init (gpointer g_class)
+gtk_editable_default_do_delete_text (GtkEditable *editable,
+ int start_pos,
+ int end_pos)
{
- static gboolean initialized = FALSE;
+ g_signal_emit_by_name (editable, "delete-text", start_pos, end_pos);
+}
- if (! initialized)
- {
- /**
- * GtkEditable::insert-text:
- * @editable: the object which received the signal
- * @new_text: the new text to insert
- * @new_text_length: the length of the new text, in bytes,
- * or -1 if new_text is nul-terminated
- * @position: (inout) (type int): the position, in characters,
- * at which to insert the new text. this is an in-out
- * parameter. After the signal emission is finished, it
- * should point after the newly inserted text.
- *
- * This signal is emitted when text is inserted into
- * the widget by the user. The default handler for
- * this signal will normally be responsible for inserting
- * the text, so by connecting to this signal and then
- * stopping the signal with g_signal_stop_emission(), it
- * is possible to modify the inserted text, or prevent
- * it from being inserted entirely.
- */
- g_signal_new (I_("insert-text"),
- GTK_TYPE_EDITABLE,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkEditableInterface, insert_text),
- NULL, NULL,
- _gtk_marshal_VOID__STRING_INT_POINTER,
- G_TYPE_NONE, 3,
- G_TYPE_STRING,
- G_TYPE_INT,
- G_TYPE_POINTER);
-
- /**
- * GtkEditable::delete-text:
- * @editable: the object which received the signal
- * @start_pos: the starting position
- * @end_pos: the end position
- *
- * This signal is emitted when text is deleted from
- * the widget by the user. The default handler for
- * this signal will normally be responsible for deleting
- * the text, so by connecting to this signal and then
- * stopping the signal with g_signal_stop_emission(), it
- * is possible to modify the range of deleted text, or
- * prevent it from being deleted entirely. The @start_pos
- * and @end_pos parameters are interpreted as for
- * gtk_editable_delete_text().
- */
- g_signal_new (I_("delete-text"),
- GTK_TYPE_EDITABLE,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkEditableInterface, delete_text),
- NULL, NULL,
- _gtk_marshal_VOID__INT_INT,
- G_TYPE_NONE, 2,
- G_TYPE_INT,
- G_TYPE_INT);
- /**
- * GtkEditable::changed:
- * @editable: the object which received the signal
- *
- * The ::changed signal is emitted at the end of a single
- * user-visible operation on the contents of the #GtkEditable.
- *
- * E.g., a paste operation that replaces the contents of the
- * selection will cause only one signal emission (even though it
- * is implemented by first deleting the selection, then inserting
- * the new content, and may cause multiple ::notify::text signals
- * to be emitted).
- */
- g_signal_new (I_("changed"),
- GTK_TYPE_EDITABLE,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkEditableInterface, changed),
- NULL, NULL,
- NULL,
- G_TYPE_NONE, 0);
-
- initialized = TRUE;
- }
+static void
+gtk_editable_default_delete_text (GtkEditable *editable,
+ int start_pos,
+ int end_pos)
+{
+ GtkEditable *delegate = get_delegate (editable);
+
+ if (delegate)
+ gtk_editable_delete_text (delegate, start_pos, end_pos);
+ else
+ warn_no_delegate ("delete_text");
+}
+
+static const char *
+gtk_editable_default_get_text (GtkEditable *editable)
+{
+ GtkEditable *delegate = get_delegate (editable);
+
+ if (delegate)
+ return gtk_editable_get_text (delegate);
+ else
+ warn_no_delegate ("get_text");
+
+ return NULL;
+}
+
+static void
+gtk_editable_default_set_selection_bounds (GtkEditable *editable,
+ int start_pos,
+ int end_pos)
+{
+ GtkEditable *delegate = get_delegate (editable);
+
+ if (delegate)
+ gtk_editable_select_region (delegate, start_pos, end_pos);
+ else
+ warn_no_delegate ("select_region");
+}
+
+static gboolean
+gtk_editable_default_get_selection_bounds (GtkEditable *editable,
+ int *start_pos,
+ int *end_pos)
+{
+ GtkEditable *delegate = get_delegate (editable);
+
+ if (delegate)
+ return gtk_editable_get_selection_bounds (delegate, start_pos, end_pos);
+ else
+ warn_no_delegate ("select_region");
+
+ return FALSE;
+}
+
+static void
+gtk_editable_default_init (GtkEditableInterface *iface)
+{
+ quark_editable_data = g_quark_from_static_string ("GtkEditable-data");
+
+ iface->insert_text = gtk_editable_default_insert_text;
+ iface->delete_text = gtk_editable_default_delete_text;
+ iface->get_text = gtk_editable_default_get_text;
+ iface->do_insert_text = gtk_editable_default_do_insert_text;
+ iface->do_delete_text = gtk_editable_default_do_delete_text;
+ iface->get_selection_bounds = gtk_editable_default_get_selection_bounds;
+ iface->set_selection_bounds = gtk_editable_default_set_selection_bounds;
+
+ /**
+ * GtkEditable::insert-text:
+ * @editable: the object which received the signal
+ * @text: the new text to insert
+ * @length: the length of the new text, in bytes,
+ * or -1 if new_text is nul-terminated
+ * @position: (inout) (type int): the position, in characters,
+ * at which to insert the new text. this is an in-out
+ * parameter. After the signal emission is finished, it
+ * should point after the newly inserted text.
+ *
+ * This signal is emitted when text is inserted into
+ * the widget by the user. The default handler for
+ * this signal will normally be responsible for inserting
+ * the text, so by connecting to this signal and then
+ * stopping the signal with g_signal_stop_emission(), it
+ * is possible to modify the inserted text, or prevent
+ * it from being inserted entirely.
+ */
+ g_signal_new (I_("insert-text"),
+ GTK_TYPE_EDITABLE,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkEditableInterface, insert_text),
+ NULL, NULL,
+ _gtk_marshal_VOID__STRING_INT_POINTER,
+ G_TYPE_NONE, 3,
+ G_TYPE_STRING,
+ G_TYPE_INT,
+ G_TYPE_POINTER);
+
+ /**
+ * GtkEditable::delete-text:
+ * @editable: the object which received the signal
+ * @start_pos: the starting position
+ * @end_pos: the end position
+ *
+ * This signal is emitted when text is deleted from
+ * the widget by the user. The default handler for
+ * this signal will normally be responsible for deleting
+ * the text, so by connecting to this signal and then
+ * stopping the signal with g_signal_stop_emission(), it
+ * is possible to modify the range of deleted text, or
+ * prevent it from being deleted entirely. The @start_pos
+ * and @end_pos parameters are interpreted as for
+ * gtk_editable_delete_text().
+ */
+ g_signal_new (I_("delete-text"),
+ GTK_TYPE_EDITABLE,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkEditableInterface, delete_text),
+ NULL, NULL,
+ _gtk_marshal_VOID__INT_INT,
+ G_TYPE_NONE, 2,
+ G_TYPE_INT,
+ G_TYPE_INT);
+
+ /**
+ * GtkEditable::changed:
+ * @editable: the object which received the signal
+ *
+ * The ::changed signal is emitted at the end of a single
+ * user-visible operation on the contents of the #GtkEditable.
+ *
+ * E.g., a paste operation that replaces the contents of the
+ * selection will cause only one signal emission (even though it
+ * is implemented by first deleting the selection, then inserting
+ * the new content, and may cause multiple ::notify::text signals
+ * to be emitted).
+ */
+ g_signal_new (I_("changed"),
+ GTK_TYPE_EDITABLE,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkEditableInterface, changed),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 0);
+
+ g_object_interface_install_property (iface,
+ g_param_spec_string ("text",
+ P_("Text"),
+ P_("The contents of the entry"),
+ "",
+ GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
+
+ g_object_interface_install_property (iface,
+ g_param_spec_int ("cursor-position",
+ P_("Cursor Position"),
+ P_("The current position of the insertion cursor in chars"),
+ 0, GTK_ENTRY_BUFFER_MAX_SIZE,
+ 0,
+ GTK_PARAM_READABLE));
+
+ g_object_interface_install_property (iface,
+ g_param_spec_int ("selection-bound",
+ P_("Selection Bound"),
+ P_("The position of the opposite end of the selection from the cursor in chars"),
+ 0, GTK_ENTRY_BUFFER_MAX_SIZE,
+ 0,
+ GTK_PARAM_READABLE));
+
+ g_object_interface_install_property (iface,
+ g_param_spec_boolean ("editable",
+ P_("Editable"),
+ P_("Whether the entry contents can be edited"),
+ TRUE,
+ GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
+
+ g_object_interface_install_property (iface,
+ g_param_spec_int ("width-chars",
+ P_("Width in chars"),
+ P_("Number of characters to leave space for in the entry"),
+ -1, G_MAXINT,
+ -1,
+ GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
+
+ g_object_interface_install_property (iface,
+ g_param_spec_int ("max-width-chars",
+ P_("Maximum width in characters"),
+ P_("The desired maximum width of the entry, in characters"),
+ -1, G_MAXINT,
+ -1,
+ GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
+
+ g_object_interface_install_property (iface,
+ g_param_spec_float ("xalign",
+ P_("X align"),
+ P_("The horizontal alignment, from 0 (left) to 1 (right). Reversed for RTL layouts."),
+ 0.0, 1.0,
+ 0.0,
+ GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
}
/**
* gtk_editable_insert_text: (virtual do_insert_text)
* @editable: a #GtkEditable
- * @new_text: the text to append
- * @new_text_length: the length of the text in bytes, or -1
+ * @text: the text to append
+ * @length: the length of the text in bytes, or -1
* @position: (inout): location of the position text will be inserted at
*
- * Inserts @new_text_length bytes of @new_text into the contents of the
+ * Inserts @length bytes of @text into the contents of the
* widget, at position @position.
*
* Note that the position is in characters, not in bytes.
@@ -198,17 +336,17 @@ gtk_editable_base_init (gpointer g_class)
*/
void
gtk_editable_insert_text (GtkEditable *editable,
- const gchar *new_text,
- gint new_text_length,
- gint *position)
+ const char *text,
+ int length,
+ int *position)
{
g_return_if_fail (GTK_IS_EDITABLE (editable));
g_return_if_fail (position != NULL);
- if (new_text_length < 0)
- new_text_length = strlen (new_text);
+ if (length < 0)
+ length = strlen (text);
- GTK_EDITABLE_GET_IFACE (editable)->do_insert_text (editable, new_text, new_text_length, position);
+ GTK_EDITABLE_GET_IFACE (editable)->do_insert_text (editable, text, length, position);
}
/**
@@ -226,8 +364,8 @@ gtk_editable_insert_text (GtkEditable *editable,
*/
void
gtk_editable_delete_text (GtkEditable *editable,
- gint start_pos,
- gint end_pos)
+ int start_pos,
+ int end_pos)
{
g_return_if_fail (GTK_IS_EDITABLE (editable));
@@ -247,18 +385,73 @@ gtk_editable_delete_text (GtkEditable *editable,
*
* Note that positions are specified in characters, not bytes.
*
- * Returns: a pointer to the contents of the widget as a
+ * Returns: (transfer full): a pointer to the contents of the widget as a
* string. This string is allocated by the #GtkEditable
* implementation and should be freed by the caller.
*/
-gchar *
+char *
gtk_editable_get_chars (GtkEditable *editable,
- gint start_pos,
- gint end_pos)
+ int start_pos,
+ int end_pos)
{
+ const char *text;
+ int length;
+ int start_index,end_index;
+
g_return_val_if_fail (GTK_IS_EDITABLE (editable), NULL);
- return GTK_EDITABLE_GET_IFACE (editable)->get_chars (editable, start_pos, end_pos);
+ text = GTK_EDITABLE_GET_IFACE (editable)->get_text (editable);
+ length = g_utf8_strlen (text, -1);
+
+ if (end_pos < 0)
+ end_pos = length;
+
+ start_pos = MIN (length, start_pos);
+ end_pos = MIN (length, end_pos);
+
+ start_index = g_utf8_offset_to_pointer (text, start_pos) - text;
+ end_index = g_utf8_offset_to_pointer (text, end_pos) - text;
+
+ return g_strndup (text + start_index, end_index - start_index);
+}
+
+/**
+ * gtk_editable_get_text:
+ * @editable: a #GtkEditable
+ *
+ * Retrieves the contents of @editable. The returned string is
+ * owned by GTK and must not be modified or freed.
+ *
+ * Returns: (transfer none): a pointer to the contents of the editable.
+ */
+const char *
+gtk_editable_get_text (GtkEditable *editable)
+{
+ g_return_val_if_fail (GTK_IS_EDITABLE (editable), NULL);
+
+ return GTK_EDITABLE_GET_IFACE (editable)->get_text (editable);
+}
+
+/**
+ * gtk_editable_set_text:
+ * @editable: a #GtkEditable
+ *
+ * Sets the text in the editable to the given value,
+ * replacing the current contents.
+ */
+void
+gtk_editable_set_text (GtkEditable *editable,
+ const char *text)
+{
+ int pos;
+
+ g_return_if_fail (GTK_IS_EDITABLE (editable));
+
+ g_object_freeze_notify (G_OBJECT (editable));
+ gtk_editable_delete_text (editable, 0, -1);
+ pos = 0;
+ gtk_editable_insert_text (editable, text, -1, &pos);
+ g_object_thaw_notify (G_OBJECT (editable));
}
/**
@@ -275,12 +468,12 @@ gtk_editable_get_chars (GtkEditable *editable,
* of the editable. Note that @position is in characters, not in bytes.
*/
void
-gtk_editable_set_position (GtkEditable *editable,
- gint position)
+gtk_editable_set_position (GtkEditable *editable,
+ int position)
{
g_return_if_fail (GTK_IS_EDITABLE (editable));
- GTK_EDITABLE_GET_IFACE (editable)->set_position (editable, position);
+ GTK_EDITABLE_GET_IFACE (editable)->set_selection_bounds (editable, position, position);
}
/**
@@ -294,12 +487,16 @@ gtk_editable_set_position (GtkEditable *editable,
*
* Returns: the cursor position
*/
-gint
+int
gtk_editable_get_position (GtkEditable *editable)
{
+ int start, end;
+
g_return_val_if_fail (GTK_IS_EDITABLE (editable), 0);
- return GTK_EDITABLE_GET_IFACE (editable)->get_position (editable);
+ GTK_EDITABLE_GET_IFACE (editable)->get_selection_bounds (editable, &start, &end);
+
+ return end;
}
/**
@@ -308,20 +505,22 @@ gtk_editable_get_position (GtkEditable *editable)
* @start_pos: (out) (allow-none): location to store the starting position, or %NULL
* @end_pos: (out) (allow-none): location to store the end position, or %NULL
*
- * Retrieves the selection bound of the editable. start_pos will be filled
- * with the start of the selection and @end_pos with end. If no text was
- * selected both will be identical and %FALSE will be returned.
+ * Retrieves the selection bound of the editable.
+ *
+ * @start_pos will be filled with the start of the selection and
+ * @end_pos with end. If no text was selected both will be identical
+ * and %FALSE will be returned.
*
* Note that positions are specified in characters, not bytes.
*
- * Returns: %TRUE if an area is selected, %FALSE otherwise
+ * Returns: %TRUE if there is a non-empty selection, %FALSE otherwise
*/
gboolean
gtk_editable_get_selection_bounds (GtkEditable *editable,
- gint *start_pos,
- gint *end_pos)
+ int *start_pos,
+ int *end_pos)
{
- gint tmp_start, tmp_end;
+ int tmp_start, tmp_end;
gboolean result;
g_return_val_if_fail (GTK_IS_EDITABLE (editable), FALSE);
@@ -346,7 +545,7 @@ gtk_editable_get_selection_bounds (GtkEditable *editable,
void
gtk_editable_delete_selection (GtkEditable *editable)
{
- gint start, end;
+ int start, end;
g_return_if_fail (GTK_IS_EDITABLE (editable));
@@ -360,18 +559,19 @@ gtk_editable_delete_selection (GtkEditable *editable)
* @start_pos: start of region
* @end_pos: end of region
*
- * Selects a region of text. The characters that are selected are
- * those characters at positions from @start_pos up to, but not
- * including @end_pos. If @end_pos is negative, then the
- * characters selected are those characters from @start_pos to
- * the end of the text.
+ * Selects a region of text.
+ *
+ * The characters that are selected are those characters at positions
+ * from @start_pos up to, but not including @end_pos. If @end_pos is
+ * negative, then the characters selected are those characters from
+ * @start_pos to the end of the text.
*
* Note that positions are specified in characters, not bytes.
*/
void
gtk_editable_select_region (GtkEditable *editable,
- gint start_pos,
- gint end_pos)
+ int start_pos,
+ int end_pos)
{
g_return_if_fail (GTK_IS_EDITABLE (editable));
@@ -379,87 +579,381 @@ gtk_editable_select_region (GtkEditable *editable,
}
/**
- * gtk_editable_cut_clipboard:
+ * gtk_editable_set_editable:
* @editable: a #GtkEditable
+ * @is_editable: %TRUE if the user is allowed to edit the text
+ * in the widget
*
- * Removes the contents of the currently selected content in the editable and
- * puts it on the clipboard.
+ * Determines if the user can edit the text
+ * in the editable widget or not.
*/
void
-gtk_editable_cut_clipboard (GtkEditable *editable)
+gtk_editable_set_editable (GtkEditable *editable,
+ gboolean is_editable)
{
g_return_if_fail (GTK_IS_EDITABLE (editable));
-
- g_signal_emit_by_name (editable, "cut-clipboard");
+
+ g_object_set (editable, "editable", is_editable, NULL);
}
/**
- * gtk_editable_copy_clipboard:
+ * gtk_editable_get_editable:
* @editable: a #GtkEditable
*
- * Copies the contents of the currently selected content in the editable and
- * puts it on the clipboard.
+ * Retrieves whether @editable is editable.
+ * See gtk_editable_set_editable().
+ *
+ * Returns: %TRUE if @editable is editable.
+ */
+gboolean
+gtk_editable_get_editable (GtkEditable *editable)
+{
+ gboolean is_editable;
+
+ g_return_val_if_fail (GTK_IS_EDITABLE (editable), FALSE);
+
+ g_object_get (editable, "editable", &is_editable, NULL);
+
+ return is_editable;
+}
+
+
+/**
+ * gtk_editable_get_alignment:
+ * @editable: a #GtkEditable
+ *
+ * Gets the value set by gtk_editable_set_alignment().
+ *
+ * Returns: the alignment
+ **/
+float
+gtk_editable_get_alignment (GtkEditable *editable)
+{
+ float xalign;
+
+ g_return_val_if_fail (GTK_IS_EDITABLE (editable), 0);
+
+ g_object_get (editable, "xalign", &xalign, NULL);
+
+ return xalign;
+}
+
+/**
+ * gtk_editable_set_alignment:
+ * @editable: a #GtkEditable
+ * @xalign: The horizontal alignment, from 0 (left) to 1 (right).
+ * Reversed for RTL layouts
+ *
+ * Sets the alignment for the contents of the editable.
+ *
+ * This controls the horizontal positioning of the contents when
+ * the displayed text is shorter than the width of the editable.
*/
void
-gtk_editable_copy_clipboard (GtkEditable *editable)
+gtk_editable_set_alignment (GtkEditable *editable,
+ float xalign)
{
g_return_if_fail (GTK_IS_EDITABLE (editable));
-
- g_signal_emit_by_name (editable, "copy-clipboard");
+
+ g_object_set (editable, "xalign", xalign, NULL);
}
/**
- * gtk_editable_paste_clipboard:
+ * gtk_editable_get_width_chars:
* @editable: a #GtkEditable
*
- * Pastes the content of the clipboard to the current position of the
- * cursor in the editable.
- */
+ * Gets the value set by gtk_editable_set_width_chars().
+ *
+ * Returns: number of chars to request space for, or negative if unset
+ **/
+int
+gtk_editable_get_width_chars (GtkEditable *editable)
+{
+ int width_chars;
+
+ g_return_val_if_fail (GTK_IS_EDITABLE (editable), 0);
+
+ g_object_get (editable, "width-chars", &width_chars, NULL);
+
+ return width_chars;
+}
+
+/**
+ * gtk_editable_set_width_chars:
+ * @editable: a #GtkEditable
+ * @n_chars: width in chars
+ *
+ * Changes the size request of the editable to be about the
+ * right size for @n_chars characters.
+ *
+ * Note that it changes the size request, the size can still
+ * be affected by how you pack the widget into containers.
+ * If @n_chars is -1, the size reverts to the default size.
+ **/
void
-gtk_editable_paste_clipboard (GtkEditable *editable)
+gtk_editable_set_width_chars (GtkEditable *editable,
+ int n_chars)
{
g_return_if_fail (GTK_IS_EDITABLE (editable));
-
- g_signal_emit_by_name (editable, "paste-clipboard");
+
+ g_object_set (editable, "width-chars", n_chars, NULL);
}
/**
- * gtk_editable_set_editable:
+ * gtk_editable_get_max_width_chars:
* @editable: a #GtkEditable
- * @is_editable: %TRUE if the user is allowed to edit the text
- * in the widget
*
- * Determines if the user can edit the text in the editable
- * widget or not.
+ * Retrieves the desired maximum width of @editable, in characters.
+ * See gtk_editable_set_max_width_chars().
+ *
+ * Returns: the maximum width of the entry, in characters
+ */
+int
+gtk_editable_get_max_width_chars (GtkEditable *editable)
+{
+ int max_width_chars;
+
+ g_return_val_if_fail (GTK_IS_EDITABLE (editable), 0);
+
+ g_object_get (editable, "max-width-chars", &max_width_chars, NULL);
+
+ return max_width_chars;
+}
+
+/**
+ * gtk_editable_set_max_width_chars:
+ * @editable: a #GtkEditable
+ * @n_chars: the new desired maximum width, in characters
+ *
+ * Sets the desired maximum width in characters of @editable.
*/
void
-gtk_editable_set_editable (GtkEditable *editable,
- gboolean is_editable)
+gtk_editable_set_max_width_chars (GtkEditable *editable,
+ int n_chars)
{
g_return_if_fail (GTK_IS_EDITABLE (editable));
- g_object_set (editable,
- "editable", is_editable != FALSE,
- NULL);
+ g_object_set (editable, "max-width-chars", n_chars, NULL);
}
/**
- * gtk_editable_get_editable:
+ * gtk_editable_install_properties:
+ * @object_class: a #GObjectClass
+ * @first_prop: property ID to use for the first property
+ *
+ * Installs the GtkEditable properties for @class.
+ *
+ * This is a helper function that should be called in class_init,
+ * after installing your own properties.
+ *
+ * To handle the properties in your set_property and get_property
+ * functions, you can either use gtk_editable_delegate_set_property()
+ * and gtk_editable_delegate_get_property() (if you are using a delegate),
+ * or remember the @first_prop offset and add it to the values in the
+ * #GtkEditableProperties enumeration to get the property IDs for these
+ * properties.
+ *
+ * Returns: the number of properties that were installed
+ */
+guint
+gtk_editable_install_properties (GObjectClass *object_class,
+ guint first_prop)
+{
+ g_type_set_qdata (G_TYPE_FROM_CLASS (object_class),
+ quark_editable_data,
+ GUINT_TO_POINTER (first_prop));
+
+ g_object_class_override_property (object_class, first_prop + GTK_EDITABLE_PROP_TEXT, "text");
+ g_object_class_override_property (object_class, first_prop + GTK_EDITABLE_PROP_CURSOR_POSITION, "cursor-position");
+ g_object_class_override_property (object_class, first_prop + GTK_EDITABLE_PROP_SELECTION_BOUND, "selection-bound");
+ g_object_class_override_property (object_class, first_prop + GTK_EDITABLE_PROP_EDITABLE, "editable");
+ g_object_class_override_property (object_class, first_prop + GTK_EDITABLE_PROP_WIDTH_CHARS, "width-chars");
+ g_object_class_override_property (object_class, first_prop + GTK_EDITABLE_PROP_MAX_WIDTH_CHARS, "max-width-chars");
+ g_object_class_override_property (object_class, first_prop + GTK_EDITABLE_PROP_XALIGN, "xalign");
+
+ return GTK_EDITABLE_NUM_PROPERTIES;
+}
+
+static void
+delegate_changed (GtkEditable *delegate,
+ gpointer editable)
+{
+ g_signal_emit_by_name (editable, "changed");
+}
+
+static void
+delegate_notify (GObject *object,
+ GParamSpec *pspec,
+ gpointer data)
+{
+ gpointer iface;
+
+ iface = g_type_interface_peek (g_type_class_peek (G_OBJECT_TYPE (object)), gtk_editable_get_type ());
+ if (g_object_interface_find_property (iface, pspec->name))
+ g_object_notify (data, pspec->name);
+}
+
+/**
+ * gtk_editable_init_delegate:
* @editable: a #GtkEditable
*
- * Retrieves whether @editable is editable. See
- * gtk_editable_set_editable().
+ * Sets up a delegate for #GtkEditable, assuming that the
+ * get_delegate vfunc in the #GtkEditable interface has been
+ * set up for the @editable's type.
*
- * Returns: %TRUE if @editable is editable.
+ * This is a helper function that should be called in instance init,
+ * after creating the delegate object.
+ */
+void
+gtk_editable_init_delegate (GtkEditable *editable)
+{
+ GtkEditable *delegate = get_delegate (editable);
+ g_signal_connect (delegate, "notify", G_CALLBACK (delegate_notify), editable);
+ g_signal_connect (delegate, "changed", G_CALLBACK (delegate_changed), editable);
+}
+
+/**
+ * gtk_editable_finish_delegate:
+ * @editable: a #GtkEditable
+ *
+ * Undoes the setup done by gtk_editable_init_delegate().
+ *
+ * This is a helper function that should be called from dispose,
+ * before removing the delegate object.
+ */
+void
+gtk_editable_finish_delegate (GtkEditable *editable)
+{
+ GtkEditable *delegate = get_delegate (editable);
+ g_signal_handlers_disconnect_by_func (delegate, delegate_notify, editable);
+ g_signal_handlers_disconnect_by_func (delegate, delegate_changed, editable);
+}
+
+/**
+ * gtk_editable_set_property:
+ * @object: a #GObject
+ * @prop_id: a property ID
+ * @value: value to set
+ * @pspec: the #GParamSpec for the property
+ *
+ * Sets a property on the #GtkEditable delegate for @object.
+ *
+ * This is a helper function that should be called in set_property,
+ * before handling your own properties.
+ *
+ * Returns: %TRUE if the property was found
*/
gboolean
-gtk_editable_get_editable (GtkEditable *editable)
+gtk_editable_delegate_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
- gboolean value;
+ GtkEditable *delegate = get_delegate (GTK_EDITABLE (object));
+ GType type = G_TYPE_FROM_INSTANCE (object);
+ guint first_prop;
- g_return_val_if_fail (GTK_IS_EDITABLE (editable), FALSE);
+ first_prop = GPOINTER_TO_UINT (g_type_get_qdata (type, quark_editable_data));
- g_object_get (editable, "editable", &value, NULL);
+ if (prop_id < first_prop)
+ return FALSE;
- return value;
+ switch (prop_id - first_prop)
+ {
+ case GTK_EDITABLE_PROP_TEXT:
+ gtk_editable_set_text (delegate, g_value_get_string (value));
+ break;
+
+ case GTK_EDITABLE_PROP_EDITABLE:
+ gtk_editable_set_editable (delegate, g_value_get_boolean (value));
+ break;
+
+ case GTK_EDITABLE_PROP_WIDTH_CHARS:
+ gtk_editable_set_width_chars (delegate, g_value_get_int (value));
+ break;
+
+ case GTK_EDITABLE_PROP_MAX_WIDTH_CHARS:
+ gtk_editable_set_max_width_chars (delegate, g_value_get_int (value));
+ break;
+
+ case GTK_EDITABLE_PROP_XALIGN:
+ gtk_editable_set_alignment (delegate, g_value_get_float (value));
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * gtk_editable_get_property:
+ * @object: a #GObject
+ * @prop_id: a property ID
+ * @value: value to set
+ * @pspec: the #GParamSpec for the property
+ *
+ * Gets a property of the #GtkEditable delegate for @object.
+ *
+ * This is helper function that should be called in get_property,
+ * before handling your own properties.
+ *
+ * Returns: %TRUE if the property was found
+ */
+gboolean
+gtk_editable_delegate_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkEditable *delegate = get_delegate (GTK_EDITABLE (object));
+ int cursor_position, selection_bound;
+ GType type = G_TYPE_FROM_INSTANCE (object);
+ guint first_prop;
+
+ first_prop = GPOINTER_TO_UINT (g_type_get_qdata (type, quark_editable_data));
+
+ if (prop_id < first_prop)
+ return FALSE;
+
+ switch (prop_id - first_prop)
+ {
+ case GTK_EDITABLE_PROP_TEXT:
+ g_value_set_string (value, gtk_editable_get_text (delegate));
+ break;
+
+ case GTK_EDITABLE_PROP_CURSOR_POSITION:
+ gtk_editable_get_selection_bounds (delegate, &cursor_position, &selection_bound);
+ g_value_set_int (value, cursor_position);
+ break;
+
+ case GTK_EDITABLE_PROP_SELECTION_BOUND:
+ gtk_editable_get_selection_bounds (delegate, &cursor_position, &selection_bound);
+ g_value_set_int (value, selection_bound);
+ break;
+
+ case GTK_EDITABLE_PROP_EDITABLE:
+ g_value_set_boolean (value, gtk_editable_get_editable (delegate));
+ break;
+
+ case GTK_EDITABLE_PROP_WIDTH_CHARS:
+ g_value_set_int (value, gtk_editable_get_width_chars (delegate));
+ break;
+
+ case GTK_EDITABLE_PROP_MAX_WIDTH_CHARS:
+ g_value_set_int (value, gtk_editable_get_max_width_chars (delegate));
+ break;
+
+ case GTK_EDITABLE_PROP_XALIGN:
+ g_value_set_float (value, gtk_editable_get_alignment (delegate));
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
}
+
+