Add a simple validation demo. Make it possible to add arbitrary children
2007-04-26 Matthias Clasen <mclasen@redhat.com> * demo/gtk-demo/combobox.c: Add a simple validation demo. * gtk/gtkcomboboxentry.c: Make it possible to add arbitrary children to a GtkComboBoxEntry. (#426401, Paul Pogonyshev) svn path=/trunk/; revision=17657
This commit is contained in:
parent
a63d6b564b
commit
790b009703
@ -1,3 +1,9 @@
|
||||
2007-04-26 Matthias Clasen <mclasen@redhat.com>
|
||||
|
||||
* demo/gtk-demo/combobox.c: Add a simple validation demo.
|
||||
* gtk/gtkcomboboxentry.c: Make it possible to add arbitrary
|
||||
children to a GtkComboBoxEntry. (#426401, Paul Pogonyshev)
|
||||
|
||||
2007-04-26 Tor Lillqvist <tml@novell.com>
|
||||
|
||||
* gtk/gtkinputdialog.c (gtk_input_dialog_fill_axes)
|
||||
|
@ -246,11 +246,87 @@ fill_combo_entry (GtkWidget *entry)
|
||||
gtk_combo_box_append_text (GTK_COMBO_BOX (entry), "Three");
|
||||
}
|
||||
|
||||
|
||||
/* A simple validating entry */
|
||||
|
||||
#define TYPE_MASK_ENTRY (mask_entry_get_type ())
|
||||
#define MASK_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_MASK_ENTRY, MaskEntry))
|
||||
#define MASK_ENTRY_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), TYPE_MASK_ENTRY, MaskEntryClass))
|
||||
#define IS_MASK_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_MASK_ENTRY))
|
||||
#define IS_MASK_ENTRY_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), TYPE_MASK_ENTRY))
|
||||
#define MASK_ENTRY_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), TYPE_MASK_ENTRY, MaskEntryClass))
|
||||
|
||||
|
||||
typedef struct _MaskEntry MaskEntry;
|
||||
struct _MaskEntry
|
||||
{
|
||||
GtkEntry entry;
|
||||
gchar *mask;
|
||||
};
|
||||
|
||||
typedef struct _MaskEntryClass MaskEntryClass;
|
||||
struct _MaskEntryClass
|
||||
{
|
||||
GtkEntryClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
static void mask_entry_editable_init (GtkEditableClass *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (MaskEntry, mask_entry, GTK_TYPE_ENTRY,
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
|
||||
mask_entry_editable_init));
|
||||
|
||||
|
||||
static void
|
||||
mask_entry_set_background (MaskEntry *entry)
|
||||
{
|
||||
static const GdkColor error_color = { 0, 65535, 60000, 60000 };
|
||||
|
||||
if (entry->mask)
|
||||
{
|
||||
if (!g_regex_match_simple (entry->mask, gtk_entry_get_text (GTK_ENTRY (entry)), 0, 0))
|
||||
{
|
||||
gtk_widget_modify_base (GTK_WIDGET (entry), GTK_STATE_NORMAL, &error_color);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_widget_modify_base (GTK_WIDGET (entry), GTK_STATE_NORMAL, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
mask_entry_changed (GtkEditable *editable)
|
||||
{
|
||||
mask_entry_set_background (MASK_ENTRY (editable));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
mask_entry_init (MaskEntry *entry)
|
||||
{
|
||||
entry->mask = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
mask_entry_class_init (MaskEntryClass *klass)
|
||||
{ }
|
||||
|
||||
|
||||
static void
|
||||
mask_entry_editable_init (GtkEditableClass *iface)
|
||||
{
|
||||
iface->changed = mask_entry_changed;
|
||||
}
|
||||
|
||||
|
||||
GtkWidget *
|
||||
do_combobox (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
GtkWidget *vbox, *frame, *box, *combo;
|
||||
GtkWidget *vbox, *frame, *box, *combo, *entry;
|
||||
GtkTreeModel *model;
|
||||
GtkCellRenderer *renderer;
|
||||
GtkTreePath *path;
|
||||
@ -343,7 +419,7 @@ do_combobox (GtkWidget *do_widget)
|
||||
gtk_tree_path_free (path);
|
||||
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo), &iter);
|
||||
|
||||
/* A GtkComboBoxEntry
|
||||
/* A GtkComboBoxEntry with validation.
|
||||
*/
|
||||
frame = gtk_frame_new ("Editable");
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
@ -356,6 +432,12 @@ do_combobox (GtkWidget *do_widget)
|
||||
fill_combo_entry (combo);
|
||||
gtk_container_add (GTK_CONTAINER (box), combo);
|
||||
|
||||
entry = g_object_new (TYPE_MASK_ENTRY, NULL);
|
||||
MASK_ENTRY (entry)->mask = "^([0-9]*|One|Two|2\302\275|Three)$";
|
||||
|
||||
gtk_container_remove (GTK_CONTAINER (combo), GTK_BIN (combo)->child);
|
||||
gtk_container_add (GTK_CONTAINER (combo), entry);
|
||||
|
||||
}
|
||||
|
||||
if (!GTK_WIDGET_VISIBLE (window))
|
||||
|
@ -1,3 +1,8 @@
|
||||
2007-04-26 Matthias Clasen <mclasen@redhat.com>
|
||||
|
||||
* gtk/tmpl/gtkcomboboxentry.sgml: Mention that the entry
|
||||
can be replaced.
|
||||
|
||||
2007-04-25 Matthias Clasen <mclasen@redhat.com>
|
||||
|
||||
* gtk/tmpl/gtkdialog.sgml: Fix a wrong cross reference.
|
||||
|
@ -15,25 +15,34 @@ allow modifying it.
|
||||
<para>
|
||||
In contrast to a #GtkComboBox, the underlying model of a #GtkComboBoxEntry
|
||||
must always have a text column (see gtk_combo_box_entry_set_text_column()),
|
||||
and the entry will show the content of the text column in the selected row. To
|
||||
get the text from the entry, use gtk_combo_box_get_active_text().
|
||||
and the entry will show the content of the text column in the selected row.
|
||||
To get the text from the entry, use gtk_combo_box_get_active_text().
|
||||
</para>
|
||||
|
||||
<para>The changed signal will be emitted while typing into a GtkComboBoxEntry,
|
||||
<para>
|
||||
The changed signal will be emitted while typing into a GtkComboBoxEntry,
|
||||
as well as when selecting an item from the GtkComboBoxEntry's list. Use
|
||||
gtk_combo_box_get_active() or gtk_combo_box_get_active_iter() to discover
|
||||
whether an item was actually selected from the list.
|
||||
</para>
|
||||
|
||||
<para>Connect to the activate signal of the GtkEntry (use gtk_bin_get_child()) to
|
||||
detect when the user actually finishes entering text.</para>
|
||||
<para>
|
||||
Connect to the activate signal of the GtkEntry (use gtk_bin_get_child())
|
||||
to detect when the user actually finishes entering text.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The convenience API to construct simple text-only #GtkComboBox<!-- -->es can
|
||||
also be used with #GtkComboBoxEntry<!-- -->s which have been constructed
|
||||
The convenience API to construct simple text-only #GtkComboBox<!-- -->es
|
||||
can also be used with #GtkComboBoxEntry<!-- -->s which have been constructed
|
||||
with gtk_combo_box_entry_new_text().
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you have special needs that go beyond a simple entry (e.g. input validation),
|
||||
it is possible to replace the child entry by a different widget using
|
||||
gtk_container_remove() and gtk_container_add().
|
||||
</para>
|
||||
|
||||
<!-- ##### SECTION See_Also ##### -->
|
||||
<para>
|
||||
#GtkComboBox
|
||||
|
@ -32,8 +32,6 @@
|
||||
|
||||
struct _GtkComboBoxEntryPrivate
|
||||
{
|
||||
GtkWidget *entry;
|
||||
|
||||
GtkCellRenderer *text_renderer;
|
||||
gint text_column;
|
||||
};
|
||||
@ -46,6 +44,10 @@ static void gtk_combo_box_entry_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void gtk_combo_box_entry_add (GtkContainer *container,
|
||||
GtkWidget *child);
|
||||
static void gtk_combo_box_entry_remove (GtkContainer *container,
|
||||
GtkWidget *child);
|
||||
|
||||
static gchar *gtk_combo_box_entry_get_active_text (GtkComboBox *combo_box);
|
||||
static void gtk_combo_box_entry_active_changed (GtkComboBox *combo_box,
|
||||
@ -72,6 +74,7 @@ gtk_combo_box_entry_class_init (GtkComboBoxEntryClass *klass)
|
||||
{
|
||||
GObjectClass *object_class;
|
||||
GtkWidgetClass *widget_class;
|
||||
GtkContainerClass *container_class;
|
||||
GtkComboBoxClass *combo_class;
|
||||
|
||||
object_class = (GObjectClass *)klass;
|
||||
@ -82,6 +85,10 @@ gtk_combo_box_entry_class_init (GtkComboBoxEntryClass *klass)
|
||||
widget_class->mnemonic_activate = gtk_combo_box_entry_mnemonic_activate;
|
||||
widget_class->grab_focus = gtk_combo_box_entry_grab_focus;
|
||||
|
||||
container_class = (GtkContainerClass *)klass;
|
||||
container_class->add = gtk_combo_box_entry_add;
|
||||
container_class->remove = gtk_combo_box_entry_remove;
|
||||
|
||||
combo_class = (GtkComboBoxClass *)klass;
|
||||
combo_class->get_active_text = gtk_combo_box_entry_get_active_text;
|
||||
|
||||
@ -102,15 +109,14 @@ gtk_combo_box_entry_class_init (GtkComboBoxEntryClass *klass)
|
||||
static void
|
||||
gtk_combo_box_entry_init (GtkComboBoxEntry *entry_box)
|
||||
{
|
||||
GtkWidget *entry;
|
||||
|
||||
entry_box->priv = GTK_COMBO_BOX_ENTRY_GET_PRIVATE (entry_box);
|
||||
entry_box->priv->text_column = -1;
|
||||
|
||||
entry_box->priv->entry = gtk_entry_new ();
|
||||
/* this flag is a hack to tell the entry to fill its allocation.
|
||||
*/
|
||||
GTK_ENTRY (entry_box->priv->entry)->is_cell_renderer = TRUE;
|
||||
gtk_container_add (GTK_CONTAINER (entry_box), entry_box->priv->entry);
|
||||
gtk_widget_show (entry_box->priv->entry);
|
||||
entry = gtk_entry_new ();
|
||||
gtk_widget_show (entry);
|
||||
gtk_container_add (GTK_CONTAINER (entry_box), entry);
|
||||
|
||||
entry_box->priv->text_renderer = gtk_cell_renderer_text_new ();
|
||||
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (entry_box),
|
||||
@ -118,12 +124,8 @@ gtk_combo_box_entry_init (GtkComboBoxEntry *entry_box)
|
||||
|
||||
gtk_combo_box_set_active (GTK_COMBO_BOX (entry_box), -1);
|
||||
|
||||
g_signal_connect (entry_box->priv->entry, "changed",
|
||||
G_CALLBACK (gtk_combo_box_entry_contents_changed),
|
||||
entry_box);
|
||||
g_signal_connect (entry_box, "changed",
|
||||
G_CALLBACK (gtk_combo_box_entry_active_changed), NULL);
|
||||
has_frame_changed (entry_box, NULL, NULL);
|
||||
g_signal_connect (entry_box, "notify::has-frame", G_CALLBACK (has_frame_changed), NULL);
|
||||
}
|
||||
|
||||
@ -167,6 +169,47 @@ gtk_combo_box_entry_get_property (GObject *object,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_combo_box_entry_add (GtkContainer *container,
|
||||
GtkWidget *child)
|
||||
{
|
||||
GtkComboBoxEntry *entry_box = GTK_COMBO_BOX_ENTRY (container);
|
||||
|
||||
if (!GTK_IS_ENTRY (child))
|
||||
{
|
||||
g_warning ("Attempting to add a widget with type %s to a GtkComboBoxEntry "
|
||||
"(need an instance of GtkEntry or of a subclass)",
|
||||
G_OBJECT_TYPE_NAME (child));
|
||||
return;
|
||||
}
|
||||
|
||||
GTK_CONTAINER_CLASS (gtk_combo_box_entry_parent_class)->add (container, child);
|
||||
|
||||
/* this flag is a hack to tell the entry to fill its allocation.
|
||||
*/
|
||||
GTK_ENTRY (child)->is_cell_renderer = TRUE;
|
||||
|
||||
g_signal_connect (child, "changed",
|
||||
G_CALLBACK (gtk_combo_box_entry_contents_changed),
|
||||
entry_box);
|
||||
has_frame_changed (entry_box, NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_combo_box_entry_remove (GtkContainer *container,
|
||||
GtkWidget *child)
|
||||
{
|
||||
if (child && child == GTK_BIN (container)->child)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (child,
|
||||
gtk_combo_box_entry_contents_changed,
|
||||
container);
|
||||
GTK_ENTRY (child)->is_cell_renderer = FALSE;
|
||||
}
|
||||
|
||||
GTK_CONTAINER_CLASS (gtk_combo_box_entry_parent_class)->remove (container, child);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_combo_box_entry_active_changed (GtkComboBox *combo_box,
|
||||
gpointer user_data)
|
||||
@ -178,21 +221,26 @@ gtk_combo_box_entry_active_changed (GtkComboBox *combo_box,
|
||||
|
||||
if (gtk_combo_box_get_active_iter (combo_box, &iter))
|
||||
{
|
||||
g_signal_handlers_block_by_func (entry_box->priv->entry,
|
||||
gtk_combo_box_entry_contents_changed,
|
||||
combo_box);
|
||||
GtkEntry *entry = GTK_ENTRY (GTK_BIN (combo_box)->child);
|
||||
|
||||
model = gtk_combo_box_get_model (combo_box);
|
||||
if (entry)
|
||||
{
|
||||
g_signal_handlers_block_by_func (entry,
|
||||
gtk_combo_box_entry_contents_changed,
|
||||
combo_box);
|
||||
|
||||
gtk_tree_model_get (model, &iter,
|
||||
entry_box->priv->text_column, &str,
|
||||
-1);
|
||||
gtk_entry_set_text (GTK_ENTRY (entry_box->priv->entry), str);
|
||||
g_free (str);
|
||||
model = gtk_combo_box_get_model (combo_box);
|
||||
|
||||
g_signal_handlers_unblock_by_func (entry_box->priv->entry,
|
||||
gtk_combo_box_entry_contents_changed,
|
||||
combo_box);
|
||||
gtk_tree_model_get (model, &iter,
|
||||
entry_box->priv->text_column, &str,
|
||||
-1);
|
||||
gtk_entry_set_text (entry, str);
|
||||
g_free (str);
|
||||
|
||||
g_signal_handlers_unblock_by_func (entry,
|
||||
gtk_combo_box_entry_contents_changed,
|
||||
combo_box);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,11 +249,14 @@ has_frame_changed (GtkComboBoxEntry *entry_box,
|
||||
GParamSpec *pspec,
|
||||
gpointer data)
|
||||
{
|
||||
gboolean has_frame;
|
||||
if (GTK_BIN (entry_box)->child)
|
||||
{
|
||||
gboolean has_frame;
|
||||
|
||||
g_object_get (entry_box, "has-frame", &has_frame, NULL);
|
||||
g_object_get (entry_box, "has-frame", &has_frame, NULL);
|
||||
|
||||
gtk_entry_set_has_frame (GTK_ENTRY (entry_box->priv->entry), has_frame);
|
||||
gtk_entry_set_has_frame (GTK_ENTRY (GTK_BIN (entry_box)->child), has_frame);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -323,9 +374,10 @@ static gboolean
|
||||
gtk_combo_box_entry_mnemonic_activate (GtkWidget *widget,
|
||||
gboolean group_cycling)
|
||||
{
|
||||
GtkComboBoxEntry *entry_box = GTK_COMBO_BOX_ENTRY (widget);
|
||||
GtkBin *entry_box = GTK_BIN (widget);
|
||||
|
||||
gtk_widget_grab_focus (entry_box->priv->entry);
|
||||
if (entry_box->child)
|
||||
gtk_widget_grab_focus (entry_box->child);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -333,9 +385,10 @@ gtk_combo_box_entry_mnemonic_activate (GtkWidget *widget,
|
||||
static void
|
||||
gtk_combo_box_entry_grab_focus (GtkWidget *widget)
|
||||
{
|
||||
GtkComboBoxEntry *entry_box = GTK_COMBO_BOX_ENTRY (widget);
|
||||
GtkBin *entry_box = GTK_BIN (widget);
|
||||
|
||||
gtk_widget_grab_focus (entry_box->priv->entry);
|
||||
if (entry_box->child)
|
||||
gtk_widget_grab_focus (entry_box->child);
|
||||
}
|
||||
|
||||
|
||||
@ -372,10 +425,10 @@ gtk_combo_box_entry_new_text (void)
|
||||
static gchar *
|
||||
gtk_combo_box_entry_get_active_text (GtkComboBox *combo_box)
|
||||
{
|
||||
GtkComboBoxEntry *combo = GTK_COMBO_BOX_ENTRY (combo_box);
|
||||
GtkBin *combo = GTK_BIN (combo_box);
|
||||
|
||||
if (combo->priv->entry)
|
||||
return g_strdup (gtk_entry_get_text (GTK_ENTRY (combo->priv->entry)));
|
||||
if (combo->child)
|
||||
return g_strdup (gtk_entry_get_text (GTK_ENTRY (combo->child)));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user