319 lines
8.7 KiB
C
319 lines
8.7 KiB
C
|
/*
|
||
|
* Copyright (c) 2014 Red Hat, Inc.
|
||
|
*
|
||
|
* 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 <glib/gi18n-lib.h>
|
||
|
|
||
|
#include "size-groups.h"
|
||
|
|
||
|
#include "highlightoverlay.h"
|
||
|
#include "window.h"
|
||
|
|
||
|
#include "gtkdropdown.h"
|
||
|
#include "gtkframe.h"
|
||
|
#include "gtklabel.h"
|
||
|
#include "gtklistbox.h"
|
||
|
#include "gtksizegroup.h"
|
||
|
#include "gtkswitch.h"
|
||
|
#include "gtkwidgetprivate.h"
|
||
|
#include "gtkstack.h"
|
||
|
#include "gtkstringlist.h"
|
||
|
|
||
|
|
||
|
typedef struct {
|
||
|
GtkListBoxRow parent;
|
||
|
GtkInspectorOverlay *highlight;
|
||
|
GtkWidget *widget;
|
||
|
} SizeGroupRow;
|
||
|
|
||
|
typedef struct {
|
||
|
GtkListBoxRowClass parent;
|
||
|
} SizeGroupRowClass;
|
||
|
|
||
|
enum {
|
||
|
PROP_WIDGET = 1,
|
||
|
LAST_PROPERTY
|
||
|
};
|
||
|
|
||
|
GParamSpec *properties[LAST_PROPERTY] = { NULL };
|
||
|
|
||
|
GType size_group_row_get_type (void);
|
||
|
|
||
|
G_DEFINE_TYPE (SizeGroupRow, size_group_row, GTK_TYPE_LIST_BOX_ROW)
|
||
|
|
||
|
static void
|
||
|
size_group_row_init (SizeGroupRow *row)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
size_group_row_get_property (GObject *object,
|
||
|
guint property_id,
|
||
|
GValue *value,
|
||
|
GParamSpec *pspec)
|
||
|
{
|
||
|
SizeGroupRow *row = (SizeGroupRow*)object;
|
||
|
|
||
|
switch (property_id)
|
||
|
{
|
||
|
case PROP_WIDGET:
|
||
|
g_value_set_pointer (value, row->widget);
|
||
|
break;
|
||
|
default:
|
||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
size_group_row_widget_destroyed (GtkWidget *widget, SizeGroupRow *row)
|
||
|
{
|
||
|
GtkWidget *parent;
|
||
|
|
||
|
parent = gtk_widget_get_parent (GTK_WIDGET (row));
|
||
|
if (parent)
|
||
|
gtk_box_remove (GTK_BOX (parent), GTK_WIDGET (row));
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
set_widget (SizeGroupRow *row, GtkWidget *widget)
|
||
|
{
|
||
|
if (row->widget)
|
||
|
g_signal_handlers_disconnect_by_func (row->widget,
|
||
|
size_group_row_widget_destroyed, row);
|
||
|
|
||
|
row->widget = widget;
|
||
|
|
||
|
if (row->widget)
|
||
|
g_signal_connect (row->widget, "destroy",
|
||
|
G_CALLBACK (size_group_row_widget_destroyed), row);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
size_group_row_set_property (GObject *object,
|
||
|
guint property_id,
|
||
|
const GValue *value,
|
||
|
GParamSpec *pspec)
|
||
|
{
|
||
|
SizeGroupRow *row = (SizeGroupRow*)object;
|
||
|
|
||
|
switch (property_id)
|
||
|
{
|
||
|
case PROP_WIDGET:
|
||
|
set_widget (row, g_value_get_pointer (value));
|
||
|
break;
|
||
|
default:
|
||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
static void
|
||
|
size_group_row_finalize (GObject *object)
|
||
|
{
|
||
|
SizeGroupRow *row = (SizeGroupRow *)object;
|
||
|
|
||
|
set_widget (row, NULL);
|
||
|
|
||
|
G_OBJECT_CLASS (size_group_row_parent_class)->finalize (object);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
size_group_state_flags_changed (GtkWidget *widget,
|
||
|
GtkStateFlags old_state)
|
||
|
{
|
||
|
SizeGroupRow *row = (SizeGroupRow*)widget;
|
||
|
GtkStateFlags state;
|
||
|
|
||
|
if (!row->widget)
|
||
|
return;
|
||
|
|
||
|
state = gtk_widget_get_state_flags (widget);
|
||
|
if ((state & GTK_STATE_FLAG_PRELIGHT) != (old_state & GTK_STATE_FLAG_PRELIGHT))
|
||
|
{
|
||
|
GtkInspectorWindow *iw = GTK_INSPECTOR_WINDOW (gtk_widget_get_root (widget));
|
||
|
|
||
|
if (state & GTK_STATE_FLAG_PRELIGHT)
|
||
|
{
|
||
|
row->highlight = gtk_highlight_overlay_new (row->widget);
|
||
|
gtk_inspector_window_add_overlay (iw, row->highlight);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
gtk_inspector_window_remove_overlay (iw, row->highlight);
|
||
|
g_clear_object (&row->highlight);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
size_group_row_class_init (SizeGroupRowClass *class)
|
||
|
{
|
||
|
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||
|
|
||
|
object_class->finalize = size_group_row_finalize;
|
||
|
object_class->get_property = size_group_row_get_property;
|
||
|
object_class->set_property = size_group_row_set_property;
|
||
|
|
||
|
widget_class->state_flags_changed = size_group_state_flags_changed;
|
||
|
|
||
|
properties[PROP_WIDGET] =
|
||
|
g_param_spec_pointer ("widget", NULL, NULL, G_PARAM_READWRITE);
|
||
|
|
||
|
g_object_class_install_properties (object_class, LAST_PROPERTY, properties);
|
||
|
|
||
|
}
|
||
|
|
||
|
G_DEFINE_TYPE (GtkInspectorSizeGroups, gtk_inspector_size_groups, GTK_TYPE_BOX)
|
||
|
|
||
|
static void
|
||
|
clear_view (GtkInspectorSizeGroups *sl)
|
||
|
{
|
||
|
GtkWidget *child;
|
||
|
|
||
|
while ((child = gtk_widget_get_first_child (GTK_WIDGET (sl))))
|
||
|
gtk_box_remove (GTK_BOX (sl), child);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
add_widget (GtkInspectorSizeGroups *sl,
|
||
|
GtkListBox *listbox,
|
||
|
GtkWidget *widget)
|
||
|
{
|
||
|
GtkWidget *row;
|
||
|
GtkWidget *label;
|
||
|
char *text;
|
||
|
|
||
|
row = g_object_new (size_group_row_get_type (), "widget", widget, NULL);
|
||
|
text = g_strdup_printf ("%p (%s)", widget, g_type_name_from_instance ((GTypeInstance*)widget));
|
||
|
label = gtk_label_new (text);
|
||
|
g_free (text);
|
||
|
gtk_widget_set_margin_start (label, 10);
|
||
|
gtk_widget_set_margin_end (label, 10);
|
||
|
gtk_widget_set_margin_top (label, 10);
|
||
|
gtk_widget_set_margin_bottom (label, 10);
|
||
|
gtk_widget_set_halign (label, GTK_ALIGN_START);
|
||
|
gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
|
||
|
gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), label);
|
||
|
gtk_list_box_insert (listbox, row, -1);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
add_size_group (GtkInspectorSizeGroups *sl,
|
||
|
GtkSizeGroup *group)
|
||
|
{
|
||
|
GtkWidget *frame, *box, *box2;
|
||
|
GtkWidget *label, *dropdown;
|
||
|
GSList *widgets, *l;
|
||
|
GtkWidget *listbox;
|
||
|
const char *modes[5];
|
||
|
|
||
|
modes[0] = C_("sizegroup mode", "None");
|
||
|
modes[1] = C_("sizegroup mode", "Horizontal");
|
||
|
modes[2] = C_("sizegroup mode", "Vertical");
|
||
|
modes[3] = C_("sizegroup mode", "Both");
|
||
|
modes[4] = NULL;
|
||
|
|
||
|
frame = gtk_frame_new (NULL);
|
||
|
gtk_box_append (GTK_BOX (sl), frame);
|
||
|
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||
|
gtk_widget_add_css_class (box, "view");
|
||
|
gtk_frame_set_child (GTK_FRAME (frame), box);
|
||
|
|
||
|
box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
|
||
|
gtk_box_append (GTK_BOX (box), box2);
|
||
|
|
||
|
label = gtk_label_new (_("Mode"));
|
||
|
gtk_widget_set_margin_start (label, 10);
|
||
|
gtk_widget_set_margin_end (label, 10);
|
||
|
gtk_widget_set_margin_top (label, 10);
|
||
|
gtk_widget_set_margin_bottom (label, 10);
|
||
|
gtk_widget_set_halign (label, GTK_ALIGN_START);
|
||
|
gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
|
||
|
gtk_box_append (GTK_BOX (box2), label);
|
||
|
|
||
|
dropdown = gtk_drop_down_new_from_strings (modes);
|
||
|
g_object_set (dropdown,
|
||
|
"margin-start", 10,
|
||
|
"margin-end", 10,
|
||
|
"margin-top", 10,
|
||
|
"margin-bottom", 10,
|
||
|
NULL);
|
||
|
gtk_widget_set_halign (dropdown, GTK_ALIGN_END);
|
||
|
gtk_widget_set_valign (dropdown, GTK_ALIGN_BASELINE_FILL);
|
||
|
g_object_bind_property (group, "mode",
|
||
|
dropdown, "selected",
|
||
|
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
|
||
|
gtk_box_append (GTK_BOX (box2), dropdown);
|
||
|
|
||
|
listbox = gtk_list_box_new ();
|
||
|
gtk_box_append (GTK_BOX (box), listbox);
|
||
|
gtk_list_box_set_selection_mode (GTK_LIST_BOX (listbox), GTK_SELECTION_NONE);
|
||
|
|
||
|
widgets = gtk_size_group_get_widgets (group);
|
||
|
for (l = widgets; l; l = l->next)
|
||
|
add_widget (sl, GTK_LIST_BOX (listbox), GTK_WIDGET (l->data));
|
||
|
}
|
||
|
|
||
|
void
|
||
|
gtk_inspector_size_groups_set_object (GtkInspectorSizeGroups *sl,
|
||
|
GObject *object)
|
||
|
{
|
||
|
GSList *groups, *l;
|
||
|
GtkWidget *stack;
|
||
|
GtkStackPage *page;
|
||
|
|
||
|
stack = gtk_widget_get_parent (GTK_WIDGET (sl));
|
||
|
page = gtk_stack_get_page (GTK_STACK (stack), GTK_WIDGET (sl));
|
||
|
|
||
|
g_object_set (page, "visible", FALSE, NULL);
|
||
|
|
||
|
clear_view (sl);
|
||
|
|
||
|
if (!GTK_IS_WIDGET (object))
|
||
|
return;
|
||
|
|
||
|
groups = _gtk_widget_get_sizegroups (GTK_WIDGET (object));
|
||
|
if (groups)
|
||
|
g_object_set (page, "visible", TRUE, NULL);
|
||
|
for (l = groups; l; l = l->next)
|
||
|
{
|
||
|
GtkSizeGroup *group = l->data;
|
||
|
add_size_group (sl, group);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
gtk_inspector_size_groups_init (GtkInspectorSizeGroups *sl)
|
||
|
{
|
||
|
g_object_set (sl,
|
||
|
"orientation", GTK_ORIENTATION_VERTICAL,
|
||
|
"margin-start", 60,
|
||
|
"margin-end", 60,
|
||
|
"margin-bottom", 60,
|
||
|
"margin-bottom", 30,
|
||
|
"spacing", 10,
|
||
|
NULL);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
gtk_inspector_size_groups_class_init (GtkInspectorSizeGroupsClass *klass)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
// vim: set et sw=2 ts=2:
|