Compare commits

...

4 Commits

Author SHA1 Message Date
Matthias Clasen
776d34e94a Add test to build 2019-02-22 13:57:15 -05:00
Matthias Clasen
a01faa714a include generated css 2019-02-22 12:46:33 -05:00
Matthias Clasen
9fffecdbfb We're not using private apis 2019-02-22 12:38:00 -05:00
Matthias Clasen
c2429bfa9c wip: Add a tagged entry
Not polished in any form, yet.
2019-02-22 12:29:42 -05:00
9 changed files with 791 additions and 0 deletions

View File

@@ -212,6 +212,7 @@
#include <gtk/gtkstylecontext.h>
#include <gtk/gtkstyleprovider.h>
#include <gtk/gtkswitch.h>
#include <gtk/gtktaggedentry.h>
#include <gtk/gtktext.h>
#include <gtk/gtktextbuffer.h>
#include <gtk/gtktextchild.h>

524
gtk/gtktaggedentry.c Normal file
View File

@@ -0,0 +1,524 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2019 Red Hat, Inc.
*
* Authors:
* - Matthias Clasen <mclasen@redhat.com>
*
* 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; either
* version 2 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, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gtktaggedentry.h"
#include "gtkaccessible.h"
#include "gtktext.h"
#include "gtkeditable.h"
#include "gtklabel.h"
#include "gtkbutton.h"
#include "gtkbox.h"
#include "gtkimage.h"
#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtkmarshalers.h"
#include "gtkstylecontext.h"
#include "gtkgesturemultipress.h"
#include "a11y/gtkentryaccessible.h"
/**
* SECTION:gtktaggedhentry
* @Short_description: An entry that can show tags
* @Title: GtkTaggedEntry
*
* #GtkTaggedEntry is an entry that can show tags in
* addition to text.
*/
typedef struct {
GtkWidget *box;
GtkWidget *entry;
} GtkTaggedEntryPrivate;
static void gtk_tagged_entry_editable_init (GtkEditableInterface *iface);
G_DEFINE_TYPE_WITH_CODE (GtkTaggedEntry, gtk_tagged_entry, GTK_TYPE_WIDGET,
G_ADD_PRIVATE (GtkTaggedEntry)
G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE, gtk_tagged_entry_editable_init))
static void
gtk_tagged_entry_init (GtkTaggedEntry *entry)
{
GtkTaggedEntryPrivate *priv = gtk_tagged_entry_get_instance_private (entry);
gtk_widget_set_has_surface (GTK_WIDGET (entry), FALSE);
priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_set_parent (priv->box, GTK_WIDGET (entry));
priv->entry = gtk_text_new ();
gtk_widget_set_hexpand (priv->entry, TRUE);
gtk_widget_set_vexpand (priv->entry, TRUE);
gtk_widget_set_hexpand (priv->box, FALSE);
gtk_widget_set_vexpand (priv->box, FALSE);
gtk_container_add (GTK_CONTAINER (priv->box), priv->entry);
gtk_editable_init_delegate (GTK_EDITABLE (entry));
}
static void
gtk_tagged_entry_dispose (GObject *object)
{
GtkTaggedEntry *entry = GTK_TAGGED_ENTRY (object);
GtkTaggedEntryPrivate *priv = gtk_tagged_entry_get_instance_private (entry);
if (priv->entry)
gtk_editable_finish_delegate (GTK_EDITABLE (entry));
g_clear_pointer (&priv->entry, gtk_widget_unparent);
g_clear_pointer (&priv->box, gtk_widget_unparent);
G_OBJECT_CLASS (gtk_tagged_entry_parent_class)->dispose (object);
}
static void
gtk_tagged_entry_finalize (GObject *object)
{
G_OBJECT_CLASS (gtk_tagged_entry_parent_class)->finalize (object);
}
static void
gtk_tagged_entry_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
if (gtk_editable_delegate_set_property (object, prop_id, value, pspec))
return;
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
static void
gtk_tagged_entry_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
if (gtk_editable_delegate_get_property (object, prop_id, value, pspec))
return;
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
static void
gtk_tagged_entry_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
GtkTaggedEntry *entry = GTK_TAGGED_ENTRY (widget);
GtkTaggedEntryPrivate *priv = gtk_tagged_entry_get_instance_private (entry);
gtk_widget_measure (priv->box, orientation, for_size,
minimum, natural,
minimum_baseline, natural_baseline);
}
static void
gtk_tagged_entry_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
GtkTaggedEntry *entry = GTK_TAGGED_ENTRY (widget);
GtkTaggedEntryPrivate *priv = gtk_tagged_entry_get_instance_private (entry);
gtk_widget_size_allocate (priv->box,
&(GtkAllocation) { 0, 0, width, height },
baseline);
}
static void
gtk_tagged_entry_grab_focus (GtkWidget *widget)
{
GtkTaggedEntry *entry = GTK_TAGGED_ENTRY (widget);
GtkTaggedEntryPrivate *priv = gtk_tagged_entry_get_instance_private (entry);
gtk_widget_grab_focus (priv->entry);
}
static void
gtk_tagged_entry_class_init (GtkTaggedEntryClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = gtk_tagged_entry_dispose;
object_class->finalize = gtk_tagged_entry_finalize;
object_class->get_property = gtk_tagged_entry_get_property;
object_class->set_property = gtk_tagged_entry_set_property;
widget_class->measure = gtk_tagged_entry_measure;
widget_class->size_allocate = gtk_tagged_entry_size_allocate;
widget_class->grab_focus = gtk_tagged_entry_grab_focus;
gtk_editable_install_properties (object_class, 1);
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_ENTRY_ACCESSIBLE);
gtk_widget_class_set_css_name (widget_class, I_("entry"));
}
static GtkEditable *
gtk_tagged_entry_get_delegate (GtkEditable *editable)
{
GtkTaggedEntry *entry = GTK_TAGGED_ENTRY (editable);
GtkTaggedEntryPrivate *priv = gtk_tagged_entry_get_instance_private (entry);
return GTK_EDITABLE (priv->entry);
}
static void
gtk_tagged_entry_editable_init (GtkEditableInterface *iface)
{
iface->get_delegate = gtk_tagged_entry_get_delegate;
}
/**
* gtk_tagged_entry_new:
*
* Creates a #GtkTaggedEntry.
*
* Returns: a new #GtkTaggedEntry
*/
GtkWidget *
gtk_tagged_entry_new (void)
{
return GTK_WIDGET (g_object_new (GTK_TYPE_TAGGED_ENTRY, NULL));
}
void
gtk_tagged_entry_add_tag (GtkTaggedEntry *entry,
GtkWidget *tag)
{
GtkTaggedEntryPrivate *priv = gtk_tagged_entry_get_instance_private (entry);
g_return_if_fail (GTK_IS_TAGGED_ENTRY (entry));
gtk_container_add (GTK_CONTAINER (priv->box), tag);
}
void
gtk_tagged_entry_insert_tag (GtkTaggedEntry *entry,
GtkWidget *tag,
int position)
{
GtkTaggedEntryPrivate *priv = gtk_tagged_entry_get_instance_private (entry);
g_return_if_fail (GTK_IS_TAGGED_ENTRY (entry));
if (position == -1)
gtk_container_add (GTK_CONTAINER (priv->box), tag);
else
{
GList *children = gtk_container_get_children (GTK_CONTAINER (priv->box));
GtkWidget *sibling = g_list_nth_data (children, position);
gtk_box_insert_child_after (GTK_BOX (priv->box), tag, sibling);
g_list_free (children);
}
}
void
gtk_tagged_entry_remove_tag (GtkTaggedEntry *entry,
GtkWidget *tag)
{
GtkTaggedEntryPrivate *priv = gtk_tagged_entry_get_instance_private (entry);
g_return_if_fail (GTK_IS_TAGGED_ENTRY (entry));
gtk_container_remove (GTK_CONTAINER (priv->box), tag);
}
#define GTK_TYPE_ENTRY_TAG (gtk_entry_tag_get_type ())
#define GTK_ENTRY_TAG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_ENTRY_TAG, GtkEntryTag))
#define GTK_ENTRY_TAG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_ENTRY_TAG, GtkEntryTag))
#define GTK_IS_ENTRY_TAG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_ENTRY_TAG))
#define GTK_IS_ENTRY_TAG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_ENTRY_TAG))
#define GTK_ENTRY_TAG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_ENTRY_TAG, GtkEntryTagClass))
typedef struct _GtkEntryTag GtkEntryTag;
typedef struct _GtkEntryTagClass GtkEntryTagClass;
struct _GtkEntryTag
{
GtkWidget parent;
GtkWidget *box;
GtkWidget *label;
GtkWidget *button;
gboolean has_close_button;
char *style;
};
struct _GtkEntryTagClass
{
GtkWidgetClass parent_class;
};
enum {
PROP_0,
PROP_LABEL,
PROP_HAS_CLOSE_BUTTON,
};
enum {
SIGNAL_CLICKED,
SIGNAL_BUTTON_CLICKED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE (GtkEntryTag, gtk_entry_tag, GTK_TYPE_WIDGET)
static void
on_released (GtkGestureMultiPress *gesture,
int n_press,
double x,
double y,
GtkEntryTag *tag)
{
g_signal_emit (tag, signals[SIGNAL_CLICKED], 0);
}
static void
gtk_entry_tag_init (GtkEntryTag *tag)
{
GtkGesture *gesture;
gtk_widget_set_has_surface (GTK_WIDGET (tag), FALSE);
tag->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_set_parent (tag->box, GTK_WIDGET (tag));
tag->label = gtk_label_new ("");
gtk_container_add (GTK_CONTAINER (tag->box), tag->label);
gesture = gtk_gesture_multi_press_new ();
g_signal_connect (gesture, "released", G_CALLBACK (on_released), tag);
gtk_widget_add_controller (GTK_WIDGET (tag), GTK_EVENT_CONTROLLER (gesture));
}
static void
gtk_entry_tag_dispose (GObject *object)
{
GtkEntryTag *tag = GTK_ENTRY_TAG (object);
g_clear_pointer (&tag->box, gtk_widget_unparent);
G_OBJECT_CLASS (gtk_entry_tag_parent_class)->dispose (object);
}
static void
gtk_entry_tag_finalize (GObject *object)
{
GtkEntryTag *tag = GTK_ENTRY_TAG (object);
g_clear_pointer (&tag->box, gtk_widget_unparent);
g_clear_pointer (&tag->style, g_free);
G_OBJECT_CLASS (gtk_entry_tag_parent_class)->finalize (object);
}
static void
gtk_entry_tag_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkEntryTag *tag = GTK_ENTRY_TAG (object);
switch (prop_id)
{
case PROP_LABEL:
gtk_entry_tag_set_label (tag, g_value_get_string (value));
break;
case PROP_HAS_CLOSE_BUTTON:
gtk_entry_tag_set_has_close_button (tag, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_entry_tag_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkEntryTag *tag = GTK_ENTRY_TAG (object);
switch (prop_id)
{
case PROP_LABEL:
g_value_set_string (value, gtk_entry_tag_get_label (tag));
break;
case PROP_HAS_CLOSE_BUTTON:
g_value_set_boolean (value, gtk_entry_tag_get_has_close_button (tag));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_entry_tag_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
GtkEntryTag *tag = GTK_ENTRY_TAG (widget);
gtk_widget_measure (tag->box, orientation, for_size,
minimum, natural,
minimum_baseline, natural_baseline);
}
static void
gtk_entry_tag_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
GtkEntryTag *tag = GTK_ENTRY_TAG (widget);
gtk_widget_size_allocate (tag->box,
&(GtkAllocation) { 0, 0, width, height },
baseline);
}
static void
gtk_entry_tag_class_init (GtkEntryTagClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->dispose = gtk_entry_tag_dispose;
object_class->finalize = gtk_entry_tag_finalize;
object_class->set_property = gtk_entry_tag_set_property;
object_class->get_property = gtk_entry_tag_get_property;
widget_class->measure = gtk_entry_tag_measure;
widget_class->size_allocate = gtk_entry_tag_size_allocate;
signals[SIGNAL_CLICKED] =
g_signal_new ("clicked",
GTK_TYPE_ENTRY_TAG,
G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL,
G_TYPE_NONE, 0);
signals[SIGNAL_BUTTON_CLICKED] =
g_signal_new ("button-clicked",
GTK_TYPE_ENTRY_TAG,
G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL,
G_TYPE_NONE, 0);
g_object_class_install_property (object_class, PROP_LABEL,
g_param_spec_string ("label", "Label", "Label",
NULL, GTK_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_HAS_CLOSE_BUTTON,
g_param_spec_boolean ("has-close-button", "Has close button", "Whether this tag has a close button",
FALSE, GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
gtk_widget_class_set_css_name (widget_class, I_("tag"));
}
GtkEntryTag *
gtk_entry_tag_new (const char *label)
{
return GTK_ENTRY_TAG (g_object_new (GTK_TYPE_ENTRY_TAG, "label", label, NULL));
}
const char *
gtk_entry_tag_get_label (GtkEntryTag *tag)
{
g_return_val_if_fail (GTK_IS_ENTRY_TAG (tag), NULL);
return gtk_label_get_label (GTK_LABEL (tag->label));
}
void
gtk_entry_tag_set_label (GtkEntryTag *tag,
const char *label)
{
g_return_if_fail (GTK_IS_ENTRY_TAG (tag));
gtk_label_set_label (GTK_LABEL (tag->label), label);
}
static void
on_button_clicked (GtkButton *button, GtkEntryTag *tag)
{
g_signal_emit (tag, signals[SIGNAL_BUTTON_CLICKED], 0);
}
void
gtk_entry_tag_set_has_close_button (GtkEntryTag *tag,
gboolean has_close_button)
{
g_return_if_fail (GTK_IS_ENTRY_TAG (tag));
if ((tag->button != NULL) == has_close_button)
return;
if (!has_close_button && tag->button)
{
gtk_container_remove (GTK_CONTAINER (tag->box), tag->button);
tag->button = NULL;
}
else if (has_close_button && tag->button == NULL)
{
GtkWidget *image;
image = gtk_image_new_from_icon_name ("window-close-symbolic");
gtk_image_set_pixel_size (GTK_IMAGE (image), 16);
tag->button = gtk_button_new ();
gtk_container_add (GTK_CONTAINER (tag->button), image);
gtk_button_set_relief (GTK_BUTTON (tag->button), GTK_RELIEF_NONE);
gtk_container_add (GTK_CONTAINER (tag->box), tag->button);
g_signal_connect (tag->button, "clicked", G_CALLBACK (on_button_clicked), tag);
}
g_object_notify (G_OBJECT (tag), "has-close-button");
}
gboolean
gtk_entry_tag_get_has_close_button (GtkEntryTag *tag)
{
g_return_val_if_fail (GTK_IS_ENTRY_TAG (tag), FALSE);
return tag->button != NULL;
}

104
gtk/gtktaggedentry.h Normal file
View File

@@ -0,0 +1,104 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2019 Red Hat, Inc.
*
* Authors:
* - MAtthias Clasen <mclasen@redhat.com>
*
* 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; either
* version 2 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GTK_TAGGED_ENTRY_H__
#define __GTK_TAGGED_ENTRY_H__
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk.h> can be included directly."
#endif
#include <gtk/gtkentry.h>
G_BEGIN_DECLS
#define GTK_TYPE_TAGGED_ENTRY (gtk_tagged_entry_get_type ())
#define GTK_TAGGED_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_TAGGED_ENTRY, GtkTaggedEntry))
#define GTK_TAGGED_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_TAGGED_ENTRY, GtkTaggedEntryClass))
#define GTK_IS_TAGGED_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_TAGGED_ENTRY))
#define GTK_IS_TAGGED_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_TAGGED_ENTRY))
#define GTK_TAGGED_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_TAGGED_ENTRY, GtkTaggedEntryClass))
typedef struct _GtkTaggedEntry GtkTaggedEntry;
typedef struct _GtkTaggedEntryClass GtkTaggedEntryClass;
struct _GtkTaggedEntry
{
GtkWidget parent;
};
struct _GtkTaggedEntryClass
{
GtkWidgetClass parent_class;
};
#define GTK_TYPE_ENTRY_TAG (gtk_entry_tag_get_type ())
#define GTK_ENTRY_TAG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_ENTRY_TAG, GtkEntryTag))
#define GTK_ENTRY_TAG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_ENTRY_TAG, GtkEntryTag))
#define GTK_IS_ENTRY_TAG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_ENTRY_TAG))
#define GTK_IS_ENTRY_TAG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_ENTRY_TAG))
#define GTK_ENTRY_TAG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_ENTRY_TAG, GtkEntryTagClass))
typedef struct _GtkEntryTag GtkEntryTag;
typedef struct _GtkEntryTagClass GtkEntryTagClass;
GDK_AVAILABLE_IN_ALL
GType gtk_tagged_entry_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GType gtk_entry_tag_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GtkWidget * gtk_tagged_entry_new (void);
GDK_AVAILABLE_IN_ALL
void gtk_tagged_entry_add_tag (GtkTaggedEntry *entry,
GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_tagged_entry_insert_tag (GtkTaggedEntry *entry,
GtkWidget *widget,
int position);
GDK_AVAILABLE_IN_ALL
void gtk_tagged_entry_remove_tag (GtkTaggedEntry *entry,
GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
GtkEntryTag * gtk_entry_tag_new (const char *label);
GDK_AVAILABLE_IN_ALL
const char * gtk_entry_tag_get_label (GtkEntryTag *tag);
GDK_AVAILABLE_IN_ALL
void gtk_entry_tag_set_label (GtkEntryTag *tag,
const char *label);
GDK_AVAILABLE_IN_ALL
gboolean gtk_entry_tag_get_has_close_button (GtkEntryTag *tag);
GDK_AVAILABLE_IN_ALL
void gtk_entry_tag_set_has_close_button (GtkEntryTag *tag,
gboolean has_close_button);
G_END_DECLS
#endif /* __GTK_TAGGED_ENTRY_H__ */

View File

@@ -352,6 +352,7 @@ gtk_public_sources = files([
'gtkstylecontext.c',
'gtkstyleprovider.c',
'gtkswitch.c',
'gtktaggedentry.c',
'gtktestutils.c',
'gtktext.c',
'gtktextattributes.c',

View File

@@ -4704,3 +4704,30 @@ popover.emoji-completion contents row box {
popover.emoji-completion .emoji:hover {
background-color: $popover_hover_color;
}
entry tag {
background: blue;
border-radius: 12px;
margin: 6px 3px;
}
entry tag label {
color: white;
}
entry tag button {
color: white;
padding: 0;
}
entry tag box {
border-spacing: 4px;
}
entry tag label.first-child {
margin-left: 10px;
}
entry tag label.last-child {
margin-right: 10px;
}

View File

@@ -2022,6 +2022,16 @@ popover.emoji-completion contents row box { border-spacing: 10px; padding: 2px 1
popover.emoji-completion .emoji:hover { background-color: #424242; }
entry tag { background: blue; border-radius: 12px; margin: 6px 3px; }
entry tag label { color: white; }
entry tag box { border-spacing: 4px; }
entry tag label.first-child { margin-left: 10px; }
entry tag label.last-child { margin-right: 10px; }
/* GTK NAMED COLORS ---------------- use responsibly! */
/*
widget text/foreground color */

View File

@@ -2042,6 +2042,16 @@ popover.emoji-completion contents row box { border-spacing: 10px; padding: 2px 1
popover.emoji-completion .emoji:hover { background-color: white; }
entry tag { background: blue; border-radius: 12px; margin: 6px 3px; }
entry tag label { color: white; }
entry tag box { border-spacing: 4px; }
entry tag label.first-child { margin-left: 10px; }
entry tag label.last-child { margin-right: 10px; }
/* GTK NAMED COLORS ---------------- use responsibly! */
/*
widget text/foreground color */

View File

@@ -130,6 +130,7 @@ gtk_tests = [
['testoutsetshadowdrawing'],
['testblur'],
['testtexture'],
['test-tagged-entry']
]
if os_unix

113
tests/test-tagged-entry.c Normal file
View File

@@ -0,0 +1,113 @@
#include <gtk/gtk.h>
static GtkEntryTag *toggle_tag;
static void
on_tag_clicked (GtkEntryTag *tag,
gpointer useless)
{
g_print ("tag clicked: %s\n", gtk_entry_tag_get_label (tag));
}
static void
on_tag_button_clicked (GtkEntryTag *tag,
GtkTaggedEntry *entry)
{
g_print ("tag button clicked: %s\n", gtk_entry_tag_get_label (tag));
gtk_tagged_entry_remove_tag (entry, tag);
}
static void
on_toggle_visible (GtkButton *button,
GtkWidget *entry)
{
gboolean active;
active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
g_print ("%s tagged entry\n", active ? "show" : "hide");
gtk_widget_set_visible (entry, active);
}
static void
on_toggle_tag (GtkButton *button,
GtkTaggedEntry *entry)
{
gboolean active;
active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
if (active)
{
g_print ("adding tag 'Toggle Tag'\n");
gtk_tagged_entry_insert_tag (entry, toggle_tag, 0);
}
else
{
g_print ("removing tag 'Toggle Tag'\n");
gtk_tagged_entry_remove_tag (entry, toggle_tag);
}
}
gint
main (gint argc,
gchar ** argv)
{
GtkWidget *window, *box, *entry, *toggle_visible_button, *toggle_tag_button;
GtkEntryTag *tag;
gtk_init ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_size_request (window, 300, 20);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add (GTK_CONTAINER (window), box);
entry = GTK_WIDGET (gtk_tagged_entry_new ());
gtk_container_add (GTK_CONTAINER (box), entry);
tag = gtk_entry_tag_new ("Blah1");
g_object_set (tag, "has-close-button", TRUE, NULL);
g_signal_connect(tag, "clicked", G_CALLBACK (on_tag_clicked), NULL);
g_signal_connect(tag, "button-clicked", G_CALLBACK (on_tag_button_clicked), entry);
gtk_tagged_entry_add_tag (GTK_TAGGED_ENTRY (entry), tag);
tag = gtk_entry_tag_new ("Blah2");
g_object_set (tag, "has-close-button", TRUE, NULL);
g_signal_connect(tag, "clicked", G_CALLBACK (on_tag_clicked), NULL);
g_signal_connect(tag, "button-clicked", G_CALLBACK (on_tag_button_clicked), entry);
gtk_tagged_entry_insert_tag (GTK_TAGGED_ENTRY (entry), tag, -1);
tag = gtk_entry_tag_new ("Blah3");
g_signal_connect(tag, "clicked", G_CALLBACK (on_tag_clicked), NULL);
g_signal_connect(tag, "button-clicked", G_CALLBACK (on_tag_button_clicked), entry);
gtk_tagged_entry_insert_tag (GTK_TAGGED_ENTRY (entry), tag, 0);
toggle_visible_button = gtk_toggle_button_new_with_label ("Visible");
gtk_widget_set_vexpand (toggle_visible_button, TRUE);
gtk_widget_set_valign (toggle_visible_button, GTK_ALIGN_END);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle_visible_button), TRUE);
g_signal_connect (toggle_visible_button, "toggled",
G_CALLBACK (on_toggle_visible), entry);
gtk_container_add (GTK_CONTAINER (box), toggle_visible_button);
gtk_tagged_entry_add_tag (entry, g_object_new (GTK_TYPE_SPINNER, "active", TRUE, NULL));
toggle_tag = gtk_entry_tag_new ("Toggle Tag");
g_signal_connect(toggle_tag, "clicked", G_CALLBACK (on_tag_clicked), NULL);
g_signal_connect(toggle_tag, "button-clicked", G_CALLBACK (on_tag_button_clicked), NULL);
g_object_ref_sink (toggle_tag);
toggle_tag_button = gtk_toggle_button_new_with_label ("Toggle Tag");
g_signal_connect (toggle_tag_button, "toggled",
G_CALLBACK (on_toggle_tag), entry);
gtk_container_add (GTK_CONTAINER (box), toggle_tag_button);
gtk_widget_show (window);
gtk_main ();
gtk_widget_destroy (window);
return 0;
}