Compare commits

...

3 Commits

Author SHA1 Message Date
Matthias Clasen
a0a3e6ffaa constraint editor: Various minor fixes 2019-07-02 22:41:07 +00:00
Matthias Clasen
bc1f2ded84 constraint editor: Allow editing children
Just name and size, for now.
2019-07-02 22:21:07 +00:00
Matthias Clasen
a5a6e90105 constraint editor: Better guide visualization
Replace the frame with a custom widget to avoid
interference from the frames own min size.
2019-07-02 21:46:38 +00:00
11 changed files with 695 additions and 50 deletions

View File

@@ -0,0 +1,262 @@
/*
* Copyright © 2019 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.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, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#include "config.h"
#include "child-editor.h"
struct _ChildEditor
{
GtkWidget parent_instance;
GtkWidget *grid;
GtkWidget *name;
GtkWidget *min_width;
GtkWidget *min_height;
GtkWidget *button;
GtkWidget *child;
gboolean constructed;
};
enum {
PROP_CHILD = 1,
LAST_PROP
};
static GParamSpec *pspecs[LAST_PROP];
enum {
DONE,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
G_DEFINE_TYPE(ChildEditor, child_editor, GTK_TYPE_WIDGET);
void
child_editor_serialize_child (GString *str,
int indent,
GtkWidget *child)
{
int min_width, min_height;
const char *name;
name = gtk_widget_get_name (child);
if (!name)
name = "";
gtk_widget_get_size_request (child, &min_width, &min_height);
g_string_append_printf (str, "%*s<child>\n", indent, "");
g_string_append_printf (str, "%*s <object class=\"GtkLabel\" id=\"%s\">\n", indent, "", name);
g_string_append_printf (str, "%*s <property name=\"label\">%s</property>\n", indent, "", name);
if (min_width != -1)
g_string_append_printf (str, "%*s <property name=\"width-request\">%d</property>\n", indent, "", min_width);
if (min_height != -1)
g_string_append_printf (str, "%*s <property name=\"height-request\">%d</property>\n", indent, "", min_height);
g_string_append_printf (str, "%*s </object>\n", indent, "");
g_string_append_printf (str, "%*s</child>\n", indent, "");
}
static void
apply (GtkButton *button,
ChildEditor *editor)
{
const char *name;
int w, h;
name = gtk_editable_get_text (GTK_EDITABLE (editor->name));
w = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->min_width));
h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->min_height));
gtk_widget_set_size_request (editor->child, w, h);
gtk_widget_set_name (editor->child, name);
g_signal_emit (editor, signals[DONE], 0, editor->child);
}
static void
child_editor_init (ChildEditor *editor)
{
gtk_widget_init_template (GTK_WIDGET (editor));
}
static int
min_input (GtkSpinButton *spin_button,
double *new_val)
{
if (strcmp (gtk_editable_get_text (GTK_EDITABLE (spin_button)), "") == 0)
{
*new_val = 0.0;
return TRUE;
}
return FALSE;
}
static gboolean
min_output (GtkSpinButton *spin_button)
{
GtkAdjustment *adjustment;
double value;
GtkWidget *box, *text;
adjustment = gtk_spin_button_get_adjustment (spin_button);
value = gtk_adjustment_get_value (adjustment);
box = gtk_widget_get_first_child (GTK_WIDGET (spin_button));
text = gtk_widget_get_first_child (box);
if (value <= 0.0)
{
gtk_editable_set_text (GTK_EDITABLE (spin_button), "");
gtk_text_set_placeholder_text (GTK_TEXT (text), "unset");
return TRUE;
}
else
{
gtk_text_set_placeholder_text (GTK_TEXT (text), "");
return FALSE;
}
}
static void
child_editor_constructed (GObject *object)
{
ChildEditor *editor = CHILD_EDITOR (object);
const char *nick;
int w, h;
g_signal_connect (editor->min_width, "input", G_CALLBACK (min_input), NULL);
g_signal_connect (editor->min_width, "output", G_CALLBACK (min_output), NULL);
g_signal_connect (editor->min_height, "input", G_CALLBACK (min_input), NULL);
g_signal_connect (editor->min_height, "output", G_CALLBACK (min_output), NULL);
nick = gtk_widget_get_name (editor->child);
if (nick)
gtk_editable_set_text (GTK_EDITABLE (editor->name), nick);
gtk_widget_get_size_request (editor->child, &w, &h);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->min_width), w);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->min_height), h);
editor->constructed = TRUE;
}
static void
child_editor_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
ChildEditor *self = CHILD_EDITOR (object);
switch (property_id)
{
case PROP_CHILD:
self->child = g_value_dup_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
child_editor_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
ChildEditor *self = CHILD_EDITOR (object);
switch (property_id)
{
case PROP_CHILD:
g_value_set_object (value, self->child);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
child_editor_dispose (GObject *object)
{
ChildEditor *self = (ChildEditor *)object;
g_clear_pointer (&self->grid, gtk_widget_unparent);
g_clear_object (&self->child);
G_OBJECT_CLASS (child_editor_parent_class)->dispose (object);
}
static void
child_editor_class_init (ChildEditorClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->constructed = child_editor_constructed;
object_class->dispose = child_editor_dispose;
object_class->set_property = child_editor_set_property;
object_class->get_property = child_editor_get_property;
pspecs[PROP_CHILD] =
g_param_spec_object ("child", "child", "child",
GTK_TYPE_WIDGET,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_properties (object_class, LAST_PROP, pspecs);
signals[DONE] =
g_signal_new ("done",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
NULL,
G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gtk/gtk4/constraint-editor/child-editor.ui");
gtk_widget_class_bind_template_child (widget_class, ChildEditor, grid);
gtk_widget_class_bind_template_child (widget_class, ChildEditor, name);
gtk_widget_class_bind_template_child (widget_class, ChildEditor, min_width);
gtk_widget_class_bind_template_child (widget_class, ChildEditor, min_height);
gtk_widget_class_bind_template_child (widget_class, ChildEditor, button);
gtk_widget_class_bind_template_callback (widget_class, apply);
}
ChildEditor *
child_editor_new (GtkWidget *child)
{
return g_object_new (CHILD_EDITOR_TYPE,
"child", child,
NULL);
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright © 2019 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.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, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#pragma once
#include <gtk/gtk.h>
#define CHILD_EDITOR_TYPE (child_editor_get_type ())
G_DECLARE_FINAL_TYPE (ChildEditor, child_editor, CHILD, EDITOR, GtkWidget)
ChildEditor * child_editor_new (GtkWidget *child);
void child_editor_serialize_child (GString *str,
int indent,
GtkWidget *child);

View File

@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkAdjustment" id="min_width_adj">
<property name="lower">0</property>
<property name="upper">2147483647</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
<property name="page-size">0</property>
</object>
<object class="GtkAdjustment" id="min_height_adj">
<property name="lower">0</property>
<property name="upper">2147483647</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
<property name="page-size">0</property>
</object>
<template class="ChildEditor" parent="GtkWidget">
<child>
<object class="GtkGrid" id="grid">
<property name="margin">20</property>
<property name="row-spacing">10</property>
<property name="column-spacing">10</property>
<child>
<object class="GtkLabel">
<property name="label">Name</property>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkEntry" id="name">
<property name="max-width-chars">20</property>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
<property name="column-span">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Min Size</property>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkSpinButton" id="min_width">
<property name="adjustment">min_width_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkSpinButton" id="min_height">
<property name="adjustment">min_height_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="left-attach">2</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkButton" id="button">
<property name="label">Apply</property>
<signal name="clicked" handler="apply"/>
<layout>
<property name="left-attach">2</property>
<property name="top-attach">5</property>
</layout>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -23,6 +23,7 @@
#include "constraint-view.h"
#include "constraint-editor.h"
#include "guide-editor.h"
#include "child-editor.h"
struct _ConstraintEditorWindow
{
@@ -368,6 +369,7 @@ add_guide (ConstraintEditorWindow *win)
name = g_strdup_printf ("Guide %d", guide_counter);
guide = gtk_constraint_guide_new ();
gtk_constraint_guide_set_name (guide, name);
gtk_constraint_guide_set_min_size (guide, 100, 25);
g_free (name);
constraint_view_add_guide (CONSTRAINT_VIEW (win->view), guide);
@@ -452,6 +454,33 @@ edit_guide (ConstraintEditorWindow *win,
gtk_widget_show (window);
}
static void
child_editor_done (ChildEditor *editor,
GtkWidget *child,
ConstraintEditorWindow *win)
{
gtk_widget_destroy (gtk_widget_get_ancestor (GTK_WIDGET (editor), GTK_TYPE_WINDOW));
}
static void
edit_child (ConstraintEditorWindow *win,
GtkWidget *child)
{
GtkWidget *window;
ChildEditor *editor;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (win));
gtk_window_set_title (GTK_WINDOW (window), "Edit Child");
editor = child_editor_new (child);
gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (editor));
g_signal_connect (editor, "done", G_CALLBACK (child_editor_done), win);
gtk_widget_show (window);
}
static void
row_activated (GtkListBox *list,
GtkListBoxRow *row,
@@ -465,6 +494,8 @@ row_activated (GtkListBox *list,
edit_constraint (win, GTK_CONSTRAINT (item));
else if (GTK_IS_CONSTRAINT_GUIDE (item))
edit_guide (win, GTK_CONSTRAINT_GUIDE (item));
else if (GTK_IS_WIDGET (item))
edit_child (win, GTK_WIDGET (item));
}
static void
@@ -505,6 +536,8 @@ row_edit (GtkButton *button,
edit_constraint (win, GTK_CONSTRAINT (item));
else if (GTK_IS_CONSTRAINT_GUIDE (item))
edit_guide (win, GTK_CONSTRAINT_GUIDE (item));
else if (GTK_IS_WIDGET (item))
edit_child (win, GTK_WIDGET (item));
}
static void
@@ -593,25 +626,15 @@ create_widget_func (gpointer item,
gtk_container_add (GTK_CONTAINER (row), box);
gtk_container_add (GTK_CONTAINER (box), label);
if (GTK_IS_CONSTRAINT (item) || GTK_IS_CONSTRAINT_GUIDE (item))
{
button = gtk_button_new_from_icon_name ("document-edit-symbolic");
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
g_signal_connect (button, "clicked", G_CALLBACK (row_edit), win);
g_object_set_data (G_OBJECT (row), "edit", button);
gtk_container_add (GTK_CONTAINER (box), button);
button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
g_signal_connect (button, "clicked", G_CALLBACK (row_delete), win);
gtk_container_add (GTK_CONTAINER (box), button);
}
else if (GTK_IS_WIDGET (item))
{
button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
g_signal_connect (button, "clicked", G_CALLBACK (row_delete), win);
gtk_container_add (GTK_CONTAINER (box), button);
}
button = gtk_button_new_from_icon_name ("document-edit-symbolic");
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
g_signal_connect (button, "clicked", G_CALLBACK (row_edit), win);
g_object_set_data (G_OBJECT (row), "edit", button);
gtk_container_add (GTK_CONTAINER (box), button);
button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
g_signal_connect (button, "clicked", G_CALLBACK (row_delete), win);
gtk_container_add (GTK_CONTAINER (box), button);
g_free (freeme);

View File

@@ -212,6 +212,19 @@ get_relation_nick (GtkConstraintRelation relation)
return nick;
}
static const char *
get_relation_to_string (GtkConstraintRelation relation)
{
switch (relation)
{
case GTK_CONSTRAINT_RELATION_LE: return "";
case GTK_CONSTRAINT_RELATION_EQ: return "=";
case GTK_CONSTRAINT_RELATION_GE: return "";
default:
g_assert_not_reached ();
}
}
static GtkConstraintStrength
get_strength (const char *id)
{
@@ -290,9 +303,17 @@ create_constraint (GtkButton *button,
target_attr = get_target_attr (id);
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source));
source = get_target (editor->model, id);
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source_attr));
source_attr = get_target_attr (id);
if (id != NULL)
{
source = get_target (editor->model, id);
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source_attr));
source_attr = get_target_attr (id);
}
else
{
source = NULL;
source_attr = GTK_CONSTRAINT_ATTRIBUTE_NONE;
}
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->relation));
relation = get_relation (id);
@@ -347,7 +368,7 @@ constraint_editor_constraint_to_string (GtkConstraint *constraint)
name = get_target_name (gtk_constraint_get_target (constraint));
attr = get_attr_nick (gtk_constraint_get_target_attribute (constraint));
relation = get_relation_nick (gtk_constraint_get_relation (constraint));
relation = get_relation_to_string (gtk_constraint_get_relation (constraint));
if (name == NULL)
name = "[ ]";
@@ -408,14 +429,20 @@ update_preview (ConstraintEditor *editor)
g_free (relation);
constant = gtk_editable_get_text (GTK_EDITABLE (editor->constant));
c = g_ascii_strtod (constant, NULL);
if (constant[0] != '\0')
c = g_ascii_strtod (constant, NULL);
else
c = 0.0;
attr = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source_attr));
if (strcmp (attr, "none") != 0)
{
name = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source));
multiplier = gtk_editable_get_text (GTK_EDITABLE (editor->multiplier));
m = g_ascii_strtod (multiplier, NULL);
if (multiplier[0] != '\0')
m = g_ascii_strtod (multiplier, NULL);
else
m = 1.0;
if (name == NULL)
name = "[ ]";
@@ -441,8 +468,7 @@ update_preview (ConstraintEditor *editor)
static void
update_button (ConstraintEditor *editor)
{
if (gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->target)) != NULL &&
gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source)) != NULL)
if (gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->target)) != NULL)
gtk_widget_set_sensitive (editor->button, TRUE);
else
gtk_widget_set_sensitive (editor->button, FALSE);

View File

@@ -7,6 +7,7 @@ constraintview .child {
background: red;
}
constraintview .guide {
constraintview guide {
background: blue;
border: 1px solid white;
}

View File

@@ -4,6 +4,7 @@
<file preprocess="xml-stripblanks">constraint-editor-window.ui</file>
<file preprocess="xml-stripblanks">constraint-editor.ui</file>
<file preprocess="xml-stripblanks">guide-editor.ui</file>
<file preprocess="xml-stripblanks">child-editor.ui</file>
<file>constraint-editor.css</file>
</gresource>
</gresources>

View File

@@ -16,6 +16,7 @@
#include <gtk/gtk.h>
#include "constraint-view.h"
#include "guide-placeholder.h"
struct _ConstraintView
{
@@ -111,16 +112,19 @@ drag_begin (GtkGestureDrag *drag,
ConstraintView *self)
{
GtkWidget *widget;
GtkWidget *target;
widget = gtk_widget_pick (GTK_WIDGET (self), start_x, start_y, GTK_PICK_DEFAULT);
if (GTK_IS_LABEL (widget))
if (widget)
{
widget = gtk_widget_get_ancestor (widget, GTK_TYPE_FRAME);
if (widget &&
gtk_widget_get_parent (widget) == (GtkWidget *)self)
target = gtk_widget_get_ancestor (widget, GUIDE_PLACEHOLDER_TYPE);
if (!target)
target = gtk_widget_get_ancestor (widget, GTK_TYPE_FRAME);
if (target &&
gtk_widget_get_parent (target) == (GtkWidget *)self)
{
self->drag_widget = widget;
self->drag_widget = target;
}
}
}
@@ -212,11 +216,16 @@ constraint_view_add_child (ConstraintView *view,
GtkWidget *frame;
GtkWidget *label;
label = gtk_label_new (name);
frame = gtk_frame_new (NULL);
gtk_style_context_add_class (gtk_widget_get_style_context (frame), "child");
gtk_widget_set_name (frame, name);
gtk_widget_set_size_request (frame, 100, 25);
label = gtk_label_new (name);
gtk_container_add (GTK_CONTAINER (frame), label);
g_object_bind_property (frame, "name",
label, "label",
G_BINDING_DEFAULT);
gtk_widget_set_parent (frame, GTK_WIDGET (view));
update_weak_position (view, frame, 100, 100);
@@ -235,8 +244,7 @@ constraint_view_add_guide (ConstraintView *view,
GtkConstraintGuide *guide)
{
GtkConstraintLayout *layout;
GtkWidget *frame;
GtkWidget *label;
GtkWidget *placeholder;
const char *name;
GtkConstraint *constraint;
struct {
@@ -251,25 +259,24 @@ constraint_view_add_guide (ConstraintView *view,
int i;
name = gtk_constraint_guide_get_name (guide);
label = gtk_label_new (name);
placeholder = guide_placeholder_new (guide);
gtk_widget_set_tooltip_text (placeholder, name);
g_object_bind_property (guide, "name",
label, "label",
placeholder, "tooltip-text",
G_BINDING_DEFAULT);
frame = gtk_frame_new (NULL);
gtk_style_context_add_class (gtk_widget_get_style_context (frame), "guide");
g_object_set_data (G_OBJECT (frame), "internal", "yes");
gtk_container_add (GTK_CONTAINER (frame), label);
gtk_widget_insert_after (frame, GTK_WIDGET (view), NULL);
g_object_set_data (G_OBJECT (placeholder), "internal", "yes");
gtk_widget_insert_after (placeholder, GTK_WIDGET (view), NULL);
g_object_set_data (G_OBJECT (guide), "frame", frame);
g_object_set_data (G_OBJECT (guide), "placeholder", placeholder);
layout = GTK_CONSTRAINT_LAYOUT (gtk_widget_get_layout_manager (GTK_WIDGET (view)));
gtk_constraint_layout_add_guide (layout, g_object_ref (guide));
for (i = 0; i < G_N_ELEMENTS (names); i++)
{
constraint = gtk_constraint_new (frame,
constraint = gtk_constraint_new (placeholder,
names[i].attr,
GTK_CONSTRAINT_RELATION_EQ,
guide,
@@ -281,7 +288,7 @@ constraint_view_add_guide (ConstraintView *view,
g_object_set_data (G_OBJECT (guide), names[i].name, constraint);
}
update_weak_position (view, frame, 150, 150);
update_weak_position (view, placeholder, 150, 150);
}
void
@@ -289,7 +296,7 @@ constraint_view_remove_guide (ConstraintView *view,
GtkConstraintGuide *guide)
{
GtkConstraintLayout *layout;
GtkWidget *frame;
GtkWidget *placeholder;
GtkConstraint *constraint;
const char *names[] = {
"left-constraint",
@@ -307,9 +314,9 @@ constraint_view_remove_guide (ConstraintView *view,
gtk_constraint_layout_remove_constraint (layout, constraint);
}
frame = (GtkWidget *)g_object_get_data (G_OBJECT (guide), "frame");
update_weak_position (view, frame, -100, -100);
gtk_widget_unparent (frame);
placeholder = (GtkWidget *)g_object_get_data (G_OBJECT (guide), "placeholder");
update_weak_position (view, placeholder, -100, -100);
gtk_widget_unparent (placeholder);
gtk_constraint_layout_remove_guide (layout, guide);
}

View File

@@ -0,0 +1,179 @@
/*
* Copyright © 2019 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.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, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#include "config.h"
#include "guide-placeholder.h"
struct _GuidePlaceholder {
GtkWidget parent_instance;
GtkWidget *label;
GtkConstraintGuide *guide;
};
enum {
PROP_GUIDE = 1,
LAST_PROP
};
static GParamSpec *props[LAST_PROP];
G_DEFINE_TYPE (GuidePlaceholder, guide_placeholder, GTK_TYPE_WIDGET);
static void
guide_placeholder_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
GuidePlaceholder *self = GUIDE_PLACEHOLDER (widget);
int min_width, min_height;
int nat_width, nat_height;
gtk_constraint_guide_get_min_size (self->guide, &min_width, &min_height);
gtk_constraint_guide_get_nat_size (self->guide, &nat_width, &nat_height);
gtk_widget_measure (self->label, orientation, for_size, minimum, natural, NULL, NULL);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
*minimum = min_width;
*natural = nat_width;
}
else
{
*minimum = min_height;
*natural = nat_height;
}
}
static void
guide_placeholder_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
GuidePlaceholder *self = GUIDE_PLACEHOLDER (widget);
gtk_widget_allocate (self->label, width, height, baseline, NULL);
}
static void
guide_changed (GObject *obj, GParamSpec *pspec, GuidePlaceholder *self)
{
gtk_label_set_label (GTK_LABEL (self->label), gtk_constraint_guide_get_name (self->guide));
gtk_widget_queue_resize (GTK_WIDGET (self));
}
static void
guide_placeholder_dispose (GObject *object)
{
GuidePlaceholder *self = GUIDE_PLACEHOLDER (object);
g_signal_handlers_disconnect_by_func (self->guide, guide_changed, self);
g_object_unref (self->guide);
gtk_widget_unparent (self->label);
G_OBJECT_CLASS (guide_placeholder_parent_class)->dispose (object);
}
static void
guide_placeholder_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GuidePlaceholder *self = GUIDE_PLACEHOLDER (object);
switch (prop_id)
{
case PROP_GUIDE:
self->guide = g_value_dup_object (value);
g_signal_connect (self->guide, "notify", G_CALLBACK (guide_changed), self);
guide_changed ((GObject *)self->guide, NULL, self);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
guide_placeholder_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GuidePlaceholder *self = GUIDE_PLACEHOLDER (object);
switch (prop_id)
{
case PROP_GUIDE:
g_value_set_object (value, self->guide);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
guide_placeholder_class_init (GuidePlaceholderClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = guide_placeholder_dispose;
object_class->set_property = guide_placeholder_set_property;
object_class->get_property = guide_placeholder_get_property;
widget_class->measure = guide_placeholder_measure;
widget_class->size_allocate = guide_placeholder_size_allocate;
props[PROP_GUIDE] =
g_param_spec_object ("guide", "guide", "guide",
GTK_TYPE_CONSTRAINT_GUIDE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_properties (object_class, LAST_PROP, props);
gtk_widget_class_set_css_name (widget_class, "guide");
}
static void
guide_placeholder_init (GuidePlaceholder *self)
{
self->label = gtk_label_new ("");
gtk_widget_set_parent (self->label, GTK_WIDGET (self));
}
GtkWidget *
guide_placeholder_new (GtkConstraintGuide *guide)
{
return g_object_new (guide_placeholder_get_type (),
"guide", guide,
NULL);
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright © 2019 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.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, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#pragma once
#include <gtk/gtk.h>
#define GUIDE_PLACEHOLDER_TYPE (guide_placeholder_get_type ())
G_DECLARE_FINAL_TYPE (GuidePlaceholder, guide_placeholder, GUIDE, PLACEHOLDER, GtkWidget)
GtkWidget * guide_placeholder_new (GtkConstraintGuide *guide);

View File

@@ -5,6 +5,8 @@ constraint_editor_sources = [
'constraint-view.c',
'constraint-editor.c',
'guide-editor.c',
'child-editor.c',
'guide-placeholder.c',
]
constraint_editor_resources = gnome.compile_resources('constraint_editor_resources',