Compare commits
107 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a0a3e6ffaa | |||
| bc1f2ded84 | |||
| a5a6e90105 | |||
| b5aee936a9 | |||
| aa8687316f | |||
| 5a3cf5a194 | |||
| c5e1b00994 | |||
| 377f0c1a0a | |||
| a442e6e8de | |||
| 274c47e5ba | |||
| b2f15a622d | |||
| 04aaf02881 | |||
| d5f8e1bf29 | |||
| 33bd7051f2 | |||
| 61345b3216 | |||
| 129691f3a6 | |||
| 4eaf860e86 | |||
| 72814c54a8 | |||
| 4d4e02c9d0 | |||
| 8ab609e4e7 | |||
| 6bc156c237 | |||
| b435dc4366 | |||
| 4dd1de4129 | |||
| 48e6cd4255 | |||
| 658397fad0 | |||
| 670fc5bb94 | |||
| b224df8109 | |||
| c88e7c180d | |||
| 2aabd64f1a | |||
| 7990b24287 | |||
| c76c1a46e4 | |||
| 68fed63eac | |||
| 46403bac12 | |||
| 74c626f835 | |||
| d45a662679 | |||
| f6019f1a16 | |||
| 514de0b91a | |||
| 9a463056d0 | |||
| 035baa092c | |||
| 499738c903 | |||
| f2d7433bf6 | |||
| 405121bccc | |||
| cb96b34315 | |||
| 9edf6fb6cb | |||
| e3c4fb67ca | |||
| a9dfca04e4 | |||
| 71b52f485e | |||
| f62fc4e2f2 | |||
| 511e2b435e | |||
| 3f36340921 | |||
| b1f0f4478e | |||
| 90f8dcc5e1 | |||
| 5a019bfccd | |||
| b39a5fe5dc | |||
| c7ef8411bd | |||
| dab8a8b5c5 | |||
| 8b9c5e3a04 | |||
| 3d3a672deb | |||
| 2f97134a08 | |||
| 47237d32eb | |||
| 139a59cae3 | |||
| 60fb9092fe | |||
| 61b4febbaf | |||
| 4f4ba8c4f6 | |||
| 651adbfb39 | |||
| 3204347bb0 | |||
| b929846cc1 | |||
| fe65da05be | |||
| 06c825df90 | |||
| 46430ea85b | |||
| 859c95b435 | |||
| 5ea8167802 | |||
| 92d3d55164 | |||
| ba2125d8e1 | |||
| 7c96326c18 | |||
| 38d353dc1a | |||
| 7ae04ba36b | |||
| 39c284c490 | |||
| 895e8e25a8 | |||
| 04562a76e3 | |||
| b6781e06c1 | |||
| 54104b6676 | |||
| 21450d5f23 | |||
| a39bbb2041 | |||
| 176d9c6baf | |||
| 64afa765c8 | |||
| a246d8c926 | |||
| 0531e663ee | |||
| bd2349c0a0 | |||
| 636fbc0f1a | |||
| cdf80f1d65 | |||
| e7b2c530c5 | |||
| e07098da03 | |||
| 98a21bf498 | |||
| c694dd6049 | |||
| 6b308cd71e | |||
| 3b6ee32f83 | |||
| 3bc3e140dd | |||
| a6a9853676 | |||
| 6b42e5b433 | |||
| 99c01607f1 | |||
| 071748592d | |||
| 8dd74eac2e | |||
| f6a2678486 | |||
| e28ec2a3eb | |||
| c4fd786866 | |||
| 8fa7de5563 |
+1
-1
@@ -105,7 +105,7 @@ pages:
|
||||
image: registry.gitlab.gnome.org/gnome/gtk/master:v6
|
||||
stage: deploy
|
||||
script:
|
||||
- meson -Ddocumentation=true _build .
|
||||
- meson -Dgtk_doc=true _build .
|
||||
- ninja -C _build
|
||||
- ninja -C _build gdk4-doc gsk4-doc gtk4-doc
|
||||
|
||||
|
||||
@@ -56,12 +56,6 @@
|
||||
/* Define if GStreamer support is available */
|
||||
#mesondefine HAVE_GSTREAMER
|
||||
|
||||
/* Define to 1 if you have the `httpGetAuthString' function. */
|
||||
#mesondefine HAVE_HTTPGETAUTHSTRING
|
||||
|
||||
/* Define if cups http_t authstring field is accessible */
|
||||
#mesondefine HAVE_HTTP_AUTHSTRING
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#mesondefine HAVE_INTTYPES_H
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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>
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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 "constraint-editor-application.h"
|
||||
#include "constraint-editor-window.h"
|
||||
|
||||
struct _ConstraintEditorApplication
|
||||
{
|
||||
GtkApplication parent_instance;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(ConstraintEditorApplication, constraint_editor_application, GTK_TYPE_APPLICATION);
|
||||
|
||||
static void
|
||||
constraint_editor_application_init (ConstraintEditorApplication *app)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
quit_activated (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer data)
|
||||
{
|
||||
g_application_quit (G_APPLICATION (data));
|
||||
}
|
||||
|
||||
static GActionEntry app_entries[] =
|
||||
{
|
||||
{ "quit", quit_activated, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static void
|
||||
constraint_editor_application_startup (GApplication *app)
|
||||
{
|
||||
const char *quit_accels[2] = { "<Ctrl>Q", NULL };
|
||||
const char *open_accels[2] = { "<Ctrl>O", NULL };
|
||||
GtkCssProvider *provider;
|
||||
|
||||
G_APPLICATION_CLASS (constraint_editor_application_parent_class)->startup (app);
|
||||
|
||||
g_action_map_add_action_entries (G_ACTION_MAP (app),
|
||||
app_entries, G_N_ELEMENTS (app_entries),
|
||||
app);
|
||||
gtk_application_set_accels_for_action (GTK_APPLICATION (app), "app.quit", quit_accels);
|
||||
gtk_application_set_accels_for_action (GTK_APPLICATION (app), "win.open", open_accels);
|
||||
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_resource (provider, "/org/gtk/gtk4/constraint-editor/constraint-editor.css");
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_application_activate (GApplication *app)
|
||||
{
|
||||
ConstraintEditorWindow *win;
|
||||
|
||||
win = constraint_editor_window_new (CONSTRAINT_EDITOR_APPLICATION (app));
|
||||
gtk_window_present (GTK_WINDOW (win));
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_application_open (GApplication *app,
|
||||
GFile **files,
|
||||
gint n_files,
|
||||
const gchar *hint)
|
||||
{
|
||||
ConstraintEditorWindow *win;
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < n_files; i++)
|
||||
{
|
||||
win = constraint_editor_window_new (CONSTRAINT_EDITOR_APPLICATION (app));
|
||||
constraint_editor_window_load (win, files[i]);
|
||||
gtk_window_present (GTK_WINDOW (win));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_application_class_init (ConstraintEditorApplicationClass *class)
|
||||
{
|
||||
GApplicationClass *application_class = G_APPLICATION_CLASS (class);
|
||||
|
||||
application_class->startup = constraint_editor_application_startup;
|
||||
application_class->activate = constraint_editor_application_activate;
|
||||
application_class->open = constraint_editor_application_open;
|
||||
}
|
||||
|
||||
ConstraintEditorApplication *
|
||||
constraint_editor_application_new (void)
|
||||
{
|
||||
return g_object_new (CONSTRAINT_EDITOR_APPLICATION_TYPE,
|
||||
"application-id", "org.gtk.gtk4.ConstraintEditor",
|
||||
"flags", G_APPLICATION_HANDLES_OPEN,
|
||||
NULL);
|
||||
}
|
||||
@@ -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 CONSTRAINT_EDITOR_APPLICATION_TYPE (constraint_editor_application_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ConstraintEditorApplication, constraint_editor_application, CONSTRAINT, EDITOR_APPLICATION, GtkApplication)
|
||||
|
||||
ConstraintEditorApplication *constraint_editor_application_new (void);
|
||||
@@ -0,0 +1,662 @@
|
||||
/*
|
||||
* 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 "constraint-editor-window.h"
|
||||
#include "constraint-view.h"
|
||||
#include "constraint-editor.h"
|
||||
#include "guide-editor.h"
|
||||
#include "child-editor.h"
|
||||
|
||||
struct _ConstraintEditorWindow
|
||||
{
|
||||
GtkApplicationWindow parent_instance;
|
||||
|
||||
GtkWidget *paned;
|
||||
GtkWidget *view;
|
||||
GtkWidget *list;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(ConstraintEditorWindow, constraint_editor_window, GTK_TYPE_APPLICATION_WINDOW);
|
||||
|
||||
static GtkConstraintTarget *
|
||||
find_target (GListModel *model,
|
||||
GtkConstraintTarget *orig)
|
||||
{
|
||||
const char *name;
|
||||
const char *model_name;
|
||||
gpointer item;
|
||||
int i;
|
||||
|
||||
if (orig == NULL)
|
||||
return NULL;
|
||||
|
||||
if (GTK_IS_LABEL (orig))
|
||||
name = gtk_label_get_label (GTK_LABEL (orig));
|
||||
else if (GTK_IS_CONSTRAINT_GUIDE (orig))
|
||||
name = gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (orig));
|
||||
else
|
||||
{
|
||||
g_warning ("Don't know how to handle %s targets", G_OBJECT_TYPE_NAME (orig));
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < g_list_model_get_n_items (model); i++)
|
||||
{
|
||||
item = g_list_model_get_item (model, i);
|
||||
g_object_unref (item);
|
||||
if (GTK_IS_WIDGET (item))
|
||||
model_name = gtk_widget_get_name (GTK_WIDGET (item));
|
||||
else
|
||||
model_name = gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (item));
|
||||
|
||||
if (strcmp (name, model_name) == 0)
|
||||
return GTK_CONSTRAINT_TARGET (item);
|
||||
}
|
||||
g_warning ("Failed to find target '%s'", name);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
constraint_editor_window_load (ConstraintEditorWindow *self,
|
||||
GFile *file)
|
||||
{
|
||||
char *path;
|
||||
GtkBuilder *builder;
|
||||
GError *error = NULL;
|
||||
GtkWidget *view;
|
||||
GtkLayoutManager *layout;
|
||||
GtkWidget *child;
|
||||
const char *name;
|
||||
gpointer item;
|
||||
int i;
|
||||
GListModel *list;
|
||||
|
||||
path = g_file_get_path (file);
|
||||
|
||||
builder = gtk_builder_new ();
|
||||
if (!gtk_builder_add_from_file (builder, path, &error))
|
||||
{
|
||||
g_print ("Could not load %s: %s", path, error->message);
|
||||
g_error_free (error);
|
||||
g_free (path);
|
||||
g_object_unref (builder);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
view = GTK_WIDGET (gtk_builder_get_object (builder, "view"));
|
||||
if (!GTK_IS_BOX (view))
|
||||
{
|
||||
g_print ("Could not load %s: No GtkBox named 'view'", path);
|
||||
g_free (path);
|
||||
g_object_unref (builder);
|
||||
return FALSE;
|
||||
}
|
||||
layout = gtk_widget_get_layout_manager (view);
|
||||
if (!GTK_IS_CONSTRAINT_LAYOUT (layout))
|
||||
{
|
||||
g_print ("Could not load %s: Widget 'view' does not use GtkConstraintLayout", path);
|
||||
g_free (path);
|
||||
g_object_unref (builder);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (child = gtk_widget_get_first_child (view);
|
||||
child;
|
||||
child = gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
if (!GTK_IS_LABEL (child))
|
||||
{
|
||||
g_print ("Skipping non-GtkLabel child\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
name = gtk_label_get_label (GTK_LABEL (child));
|
||||
constraint_view_add_child (CONSTRAINT_VIEW (self->view), name);
|
||||
}
|
||||
|
||||
list = gtk_constraint_layout_observe_guides (GTK_CONSTRAINT_LAYOUT (layout));
|
||||
for (i = 0; i < g_list_model_get_n_items (list); i++)
|
||||
{
|
||||
GtkConstraintGuide *guide, *clone;
|
||||
int w, h;
|
||||
|
||||
item = g_list_model_get_item (list, i);
|
||||
guide = GTK_CONSTRAINT_GUIDE (item);
|
||||
|
||||
/* need to clone here, to attach to the right targets */
|
||||
clone = gtk_constraint_guide_new ();
|
||||
gtk_constraint_guide_set_name (clone, gtk_constraint_guide_get_name (guide));
|
||||
gtk_constraint_guide_set_strength (clone, gtk_constraint_guide_get_strength (guide));
|
||||
gtk_constraint_guide_get_min_size (guide, &w, &h);
|
||||
gtk_constraint_guide_set_min_size (clone, w, h);
|
||||
gtk_constraint_guide_get_nat_size (guide, &w, &h);
|
||||
gtk_constraint_guide_set_nat_size (clone, w, h);
|
||||
gtk_constraint_guide_get_max_size (guide, &w, &h);
|
||||
gtk_constraint_guide_set_max_size (clone, w, h);
|
||||
constraint_view_add_guide (CONSTRAINT_VIEW (self->view), clone);
|
||||
g_object_unref (guide);
|
||||
g_object_unref (clone);
|
||||
}
|
||||
g_object_unref (list);
|
||||
|
||||
list = gtk_constraint_layout_observe_constraints (GTK_CONSTRAINT_LAYOUT (layout));
|
||||
for (i = 0; i < g_list_model_get_n_items (list); i++)
|
||||
{
|
||||
GtkConstraint *constraint;
|
||||
GtkConstraint *clone;
|
||||
GtkConstraintTarget *target;
|
||||
GtkConstraintTarget *source;
|
||||
|
||||
item = g_list_model_get_item (list, i);
|
||||
constraint = GTK_CONSTRAINT (item);
|
||||
|
||||
target = gtk_constraint_get_target (constraint);
|
||||
source = gtk_constraint_get_source (constraint);
|
||||
clone = gtk_constraint_new (find_target (constraint_view_get_model (CONSTRAINT_VIEW (self->view)), target),
|
||||
gtk_constraint_get_target_attribute (constraint),
|
||||
gtk_constraint_get_relation (constraint),
|
||||
find_target (constraint_view_get_model (CONSTRAINT_VIEW (self->view)), source),
|
||||
gtk_constraint_get_target_attribute (constraint),
|
||||
gtk_constraint_get_multiplier (constraint),
|
||||
gtk_constraint_get_constant (constraint),
|
||||
gtk_constraint_get_strength (constraint));
|
||||
|
||||
constraint_view_add_constraint (CONSTRAINT_VIEW (self->view), clone);
|
||||
|
||||
g_object_unref (constraint);
|
||||
g_object_unref (clone);
|
||||
}
|
||||
g_object_unref (list);
|
||||
|
||||
g_free (path);
|
||||
g_object_unref (builder);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
open_response_cb (GtkNativeDialog *dialog,
|
||||
gint response,
|
||||
ConstraintEditorWindow *self)
|
||||
{
|
||||
gtk_native_dialog_hide (dialog);
|
||||
|
||||
if (response == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
GFile *file;
|
||||
|
||||
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
|
||||
constraint_editor_window_load (self, file);
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
gtk_native_dialog_destroy (dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
open_cb (GtkWidget *button,
|
||||
ConstraintEditorWindow *self)
|
||||
{
|
||||
GtkFileChooserNative *dialog;
|
||||
|
||||
dialog = gtk_file_chooser_native_new ("Open file",
|
||||
GTK_WINDOW (self),
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
"_Load",
|
||||
"_Cancel");
|
||||
|
||||
gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (dialog), TRUE);
|
||||
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), ".");
|
||||
g_signal_connect (dialog, "response", G_CALLBACK (open_response_cb), self);
|
||||
gtk_native_dialog_show (GTK_NATIVE_DIALOG (dialog));
|
||||
}
|
||||
|
||||
static void
|
||||
serialize_child (GString *str,
|
||||
int indent,
|
||||
GtkWidget *child)
|
||||
{
|
||||
const char *name;
|
||||
|
||||
name = gtk_widget_get_name (child);
|
||||
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);
|
||||
g_string_append_printf (str, "%*s </object>\n", indent, "");
|
||||
g_string_append_printf (str, "%*s</child>\n", indent, "");
|
||||
}
|
||||
|
||||
static char *
|
||||
serialize_model (GListModel *list)
|
||||
{
|
||||
GString *str = g_string_new ("");
|
||||
int i;
|
||||
|
||||
g_string_append (str, "<interface>\n");
|
||||
g_string_append (str, " <object class=\"GtkBox\" id=\"view\">\n");
|
||||
g_string_append (str, " <property name=\"layout-manager\">\n");
|
||||
g_string_append (str, " <object class=\"GtkConstraintLayout\">\n");
|
||||
g_string_append (str, " <constraints>\n");
|
||||
for (i = 0; i < g_list_model_get_n_items (list); i++)
|
||||
{
|
||||
gpointer item = g_list_model_get_item (list, i);
|
||||
g_object_unref (item);
|
||||
if (GTK_IS_CONSTRAINT (item))
|
||||
constraint_editor_serialize_constraint (str, 10, GTK_CONSTRAINT (item));
|
||||
else if (GTK_IS_CONSTRAINT_GUIDE (item))
|
||||
guide_editor_serialize_guide (str, 10, GTK_CONSTRAINT_GUIDE (item));
|
||||
}
|
||||
g_string_append (str, " </constraints>\n");
|
||||
g_string_append (str, " </object>\n");
|
||||
g_string_append (str, " </property>\n");
|
||||
for (i = 0; i < g_list_model_get_n_items (list); i++)
|
||||
{
|
||||
gpointer item = g_list_model_get_item (list, i);
|
||||
g_object_unref (item);
|
||||
if (GTK_IS_WIDGET (item))
|
||||
serialize_child (str, 4, GTK_WIDGET (item));
|
||||
}
|
||||
g_string_append (str, " </object>\n");
|
||||
g_string_append (str, "</interface>\n");
|
||||
|
||||
return g_string_free (str, FALSE);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
save_response_cb (GtkNativeDialog *dialog,
|
||||
gint response,
|
||||
ConstraintEditorWindow *self)
|
||||
{
|
||||
gtk_native_dialog_hide (dialog);
|
||||
|
||||
if (response == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
GListModel *model;
|
||||
char *text, *filename;
|
||||
GError *error = NULL;
|
||||
|
||||
model = constraint_view_get_model (CONSTRAINT_VIEW (self->view));
|
||||
text = serialize_model (model);
|
||||
|
||||
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
|
||||
if (!g_file_set_contents (filename, text, -1, &error))
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
|
||||
dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self))),
|
||||
GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_INFO,
|
||||
GTK_BUTTONS_OK,
|
||||
"Saving failed");
|
||||
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
|
||||
"%s", error->message);
|
||||
g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
|
||||
gtk_widget_show (dialog);
|
||||
g_error_free (error);
|
||||
}
|
||||
g_free (filename);
|
||||
}
|
||||
|
||||
gtk_native_dialog_destroy (dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
save_cb (GtkWidget *button,
|
||||
ConstraintEditorWindow *self)
|
||||
{
|
||||
GtkFileChooserNative *dialog;
|
||||
|
||||
dialog = gtk_file_chooser_native_new ("Save constraints",
|
||||
GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (button))),
|
||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
"_Save",
|
||||
"_Cancel");
|
||||
|
||||
gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (dialog), TRUE);
|
||||
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), ".");
|
||||
g_signal_connect (dialog, "response", G_CALLBACK (save_response_cb), self);
|
||||
gtk_native_dialog_show (GTK_NATIVE_DIALOG (dialog));
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_window_finalize (GObject *object)
|
||||
{
|
||||
//ConstraintEditorWindow *self = (ConstraintEditorWindow *)object;
|
||||
|
||||
G_OBJECT_CLASS (constraint_editor_window_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static int child_counter;
|
||||
static int guide_counter;
|
||||
|
||||
static void
|
||||
add_child (ConstraintEditorWindow *win)
|
||||
{
|
||||
char *name;
|
||||
|
||||
child_counter++;
|
||||
name = g_strdup_printf ("Child %d", child_counter);
|
||||
constraint_view_add_child (CONSTRAINT_VIEW (win->view), name);
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
static void
|
||||
add_guide (ConstraintEditorWindow *win)
|
||||
{
|
||||
char *name;
|
||||
GtkConstraintGuide *guide;
|
||||
|
||||
guide_counter++;
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_done (ConstraintEditor *editor,
|
||||
GtkConstraint *constraint,
|
||||
ConstraintEditorWindow *win)
|
||||
{
|
||||
GtkConstraint *old_constraint;
|
||||
|
||||
g_object_get (editor, "constraint", &old_constraint, NULL);
|
||||
|
||||
if (old_constraint)
|
||||
constraint_view_remove_constraint (CONSTRAINT_VIEW (win->view), old_constraint);
|
||||
|
||||
constraint_view_add_constraint (CONSTRAINT_VIEW (win->view), constraint);
|
||||
|
||||
g_clear_object (&old_constraint);
|
||||
|
||||
gtk_widget_destroy (gtk_widget_get_ancestor (GTK_WIDGET (editor), GTK_TYPE_WINDOW));
|
||||
}
|
||||
|
||||
static void
|
||||
edit_constraint (ConstraintEditorWindow *win,
|
||||
GtkConstraint *constraint)
|
||||
{
|
||||
GtkWidget *window;
|
||||
ConstraintEditor *editor;
|
||||
GListModel *model;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (win));
|
||||
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
|
||||
if (constraint)
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Edit Constraint");
|
||||
else
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Create Constraint");
|
||||
|
||||
model = constraint_view_get_model (CONSTRAINT_VIEW (win->view));
|
||||
|
||||
editor = constraint_editor_new (model, constraint);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (editor));
|
||||
|
||||
g_signal_connect (editor, "done", G_CALLBACK (constraint_editor_done), win);
|
||||
|
||||
gtk_widget_show (window);
|
||||
}
|
||||
|
||||
static void
|
||||
add_constraint (ConstraintEditorWindow *win)
|
||||
{
|
||||
edit_constraint (win, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
guide_editor_done (GuideEditor *editor,
|
||||
GtkConstraintGuide *guide,
|
||||
ConstraintEditorWindow *win)
|
||||
{
|
||||
gtk_widget_destroy (gtk_widget_get_ancestor (GTK_WIDGET (editor), GTK_TYPE_WINDOW));
|
||||
}
|
||||
|
||||
static void
|
||||
edit_guide (ConstraintEditorWindow *win,
|
||||
GtkConstraintGuide *guide)
|
||||
{
|
||||
GtkWidget *window;
|
||||
GuideEditor *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 Guide");
|
||||
|
||||
editor = guide_editor_new (guide);
|
||||
gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (editor));
|
||||
|
||||
g_signal_connect (editor, "done", G_CALLBACK (guide_editor_done), 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,
|
||||
ConstraintEditorWindow *win)
|
||||
{
|
||||
GObject *item;
|
||||
|
||||
item = G_OBJECT (g_object_get_data (G_OBJECT (row), "item"));
|
||||
|
||||
if (GTK_IS_CONSTRAINT (item))
|
||||
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
|
||||
constraint_editor_window_class_init (ConstraintEditorWindowClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
|
||||
g_type_ensure (CONSTRAINT_VIEW_TYPE);
|
||||
|
||||
object_class->finalize = constraint_editor_window_finalize;
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class,
|
||||
"/org/gtk/gtk4/constraint-editor/constraint-editor-window.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditorWindow, paned);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditorWindow, view);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditorWindow, list);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, open_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, save_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, add_child);
|
||||
gtk_widget_class_bind_template_callback (widget_class, add_guide);
|
||||
gtk_widget_class_bind_template_callback (widget_class, add_constraint);
|
||||
gtk_widget_class_bind_template_callback (widget_class, row_activated);
|
||||
}
|
||||
|
||||
static void
|
||||
row_edit (GtkButton *button,
|
||||
ConstraintEditorWindow *win)
|
||||
{
|
||||
GtkWidget *row;
|
||||
GObject *item;
|
||||
|
||||
row = gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_LIST_BOX_ROW);
|
||||
item = (GObject *)g_object_get_data (G_OBJECT (row), "item");
|
||||
if (GTK_IS_CONSTRAINT (item))
|
||||
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
|
||||
mark_constraints_invalid (ConstraintEditorWindow *win,
|
||||
gpointer removed)
|
||||
{
|
||||
GtkWidget *child;
|
||||
GObject *item;
|
||||
|
||||
for (child = gtk_widget_get_first_child (win->list);
|
||||
child;
|
||||
child = gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
item = (GObject *)g_object_get_data (G_OBJECT (child), "item");
|
||||
if (GTK_IS_CONSTRAINT (item))
|
||||
{
|
||||
GtkConstraint *constraint = GTK_CONSTRAINT (item);
|
||||
|
||||
if (gtk_constraint_get_target (constraint) == (GtkConstraintTarget *)removed ||
|
||||
gtk_constraint_get_source (constraint) == (GtkConstraintTarget *)removed)
|
||||
{
|
||||
GtkWidget *button;
|
||||
button = (GtkWidget *)g_object_get_data (G_OBJECT (child), "edit");
|
||||
gtk_button_set_icon_name (GTK_BUTTON (button), "dialog-warning-symbolic");
|
||||
gtk_widget_set_tooltip_text (button, "Constraint is invalid");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
row_delete (GtkButton *button,
|
||||
ConstraintEditorWindow *win)
|
||||
{
|
||||
GtkWidget *row;
|
||||
GObject *item;
|
||||
|
||||
row = gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_LIST_BOX_ROW);
|
||||
item = (GObject *)g_object_get_data (G_OBJECT (row), "item");
|
||||
if (GTK_IS_CONSTRAINT (item))
|
||||
constraint_view_remove_constraint (CONSTRAINT_VIEW (win->view),
|
||||
GTK_CONSTRAINT (item));
|
||||
else if (GTK_IS_CONSTRAINT_GUIDE (item))
|
||||
{
|
||||
mark_constraints_invalid (win, item);
|
||||
constraint_view_remove_guide (CONSTRAINT_VIEW (win->view),
|
||||
GTK_CONSTRAINT_GUIDE (item));
|
||||
}
|
||||
else if (GTK_IS_WIDGET (item))
|
||||
{
|
||||
mark_constraints_invalid (win, item);
|
||||
constraint_view_remove_child (CONSTRAINT_VIEW (win->view),
|
||||
GTK_WIDGET (item));
|
||||
}
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
create_widget_func (gpointer item,
|
||||
gpointer user_data)
|
||||
{
|
||||
ConstraintEditorWindow *win = user_data;
|
||||
const char *name;
|
||||
char *freeme = NULL;
|
||||
GtkWidget *row, *box, *label, *button;
|
||||
|
||||
if (GTK_IS_WIDGET (item))
|
||||
name = gtk_widget_get_name (GTK_WIDGET (item));
|
||||
else if (GTK_IS_CONSTRAINT_GUIDE (item))
|
||||
name = gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (item));
|
||||
else if (GTK_IS_CONSTRAINT (item))
|
||||
name = freeme = constraint_editor_constraint_to_string (GTK_CONSTRAINT (item));
|
||||
else
|
||||
name = "";
|
||||
|
||||
row = gtk_list_box_row_new ();
|
||||
g_object_set_data_full (G_OBJECT (row), "item", g_object_ref (item), g_object_unref);
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
label = gtk_label_new (name);
|
||||
if (GTK_IS_WIDGET (item) || GTK_IS_CONSTRAINT_GUIDE (item))
|
||||
g_object_bind_property (item, "name",
|
||||
label, "label",
|
||||
G_BINDING_DEFAULT);
|
||||
g_object_set (label, "margin", 10, NULL);
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
|
||||
gtk_widget_set_hexpand (label, TRUE);
|
||||
gtk_container_add (GTK_CONTAINER (row), box);
|
||||
gtk_container_add (GTK_CONTAINER (box), label);
|
||||
|
||||
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);
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_window_init (ConstraintEditorWindow *self)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
|
||||
gtk_list_box_bind_model (GTK_LIST_BOX (self->list),
|
||||
constraint_view_get_model (CONSTRAINT_VIEW (self->view)),
|
||||
create_widget_func,
|
||||
self,
|
||||
NULL);
|
||||
}
|
||||
|
||||
ConstraintEditorWindow *
|
||||
constraint_editor_window_new (ConstraintEditorApplication *application)
|
||||
{
|
||||
return g_object_new (CONSTRAINT_EDITOR_WINDOW_TYPE,
|
||||
"application", application,
|
||||
NULL);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
#include "constraint-editor-application.h"
|
||||
|
||||
|
||||
#define CONSTRAINT_EDITOR_WINDOW_TYPE (constraint_editor_window_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ConstraintEditorWindow, constraint_editor_window, CONSTRAINT, EDITOR_WINDOW, GtkApplicationWindow)
|
||||
|
||||
ConstraintEditorWindow * constraint_editor_window_new (ConstraintEditorApplication *application);
|
||||
|
||||
gboolean constraint_editor_window_load (ConstraintEditorWindow *self,
|
||||
GFile *file);
|
||||
@@ -0,0 +1,82 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="ConstraintEditorWindow" parent="GtkApplicationWindow">
|
||||
<style>
|
||||
<class name="devel"/>
|
||||
</style>
|
||||
<property name="title" translatable="yes">GTK Constraint Editor</property>
|
||||
<property name="default-width">1024</property>
|
||||
<property name="default-height">768</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="title" translatable="yes">GTK Constraint Editor</property>
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="start">
|
||||
<object class="GtkButton">
|
||||
<property name="icon-name">document-open-symbolic</property>
|
||||
<property name="tooltip-text">Open ui file</property>
|
||||
<signal name="clicked" handler="open_cb"/>
|
||||
</object>
|
||||
</child>
|
||||
<child type="start">
|
||||
<object class="GtkButton">
|
||||
<property name="icon-name">document-save-symbolic</property>
|
||||
<property name="tooltip-text">Save to ui file</property>
|
||||
<signal name="clicked" handler="save_cb"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkPaned" id="paned">
|
||||
<property name="orientation">horizontal</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">horizontal</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label">Add Child</property>
|
||||
<signal name="clicked" handler="add_child" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label">Add Guide</property>
|
||||
<signal name="clicked" handler="add_guide" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label">Add Constraint</property>
|
||||
<signal name="clicked" handler="add_constraint" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="vscrollbar-policy">automatic</property>
|
||||
<property name="vexpand">1</property>
|
||||
<child>
|
||||
<object class="GtkListBox" id="list">
|
||||
<property name="show-separators">1</property>
|
||||
<property name="selection-mode">none</property>
|
||||
<signal name="row-activated" handler="row_activated"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="ConstraintView" id="view">
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
@@ -0,0 +1,682 @@
|
||||
/*
|
||||
* 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 "constraint-editor.h"
|
||||
|
||||
struct _ConstraintEditor
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GtkWidget *grid;
|
||||
GtkWidget *target;
|
||||
GtkWidget *target_attr;
|
||||
GtkWidget *relation;
|
||||
GtkWidget *source;
|
||||
GtkWidget *source_attr;
|
||||
GtkWidget *multiplier;
|
||||
GtkWidget *constant;
|
||||
GtkWidget *strength;
|
||||
GtkWidget *preview;
|
||||
GtkWidget *button;
|
||||
|
||||
GtkConstraint *constraint;
|
||||
GListModel *model;
|
||||
|
||||
gboolean constructed;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_MODEL = 1,
|
||||
PROP_CONSTRAINT,
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
static GParamSpec *pspecs[LAST_PROP];
|
||||
|
||||
enum {
|
||||
DONE,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
G_DEFINE_TYPE(ConstraintEditor, constraint_editor, GTK_TYPE_WIDGET);
|
||||
|
||||
static const char *
|
||||
get_target_name (GtkConstraintTarget *target)
|
||||
{
|
||||
if (target == NULL)
|
||||
return "super";
|
||||
else if (GTK_IS_WIDGET (target))
|
||||
return gtk_widget_get_name (GTK_WIDGET (target));
|
||||
else if (GTK_IS_CONSTRAINT_GUIDE (target))
|
||||
return gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (target));
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_target_combo (GListModel *model,
|
||||
GtkWidget *combo,
|
||||
gboolean is_source)
|
||||
{
|
||||
int i;
|
||||
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "super", "Super");
|
||||
|
||||
if (model)
|
||||
{
|
||||
for (i = 0; i < g_list_model_get_n_items (model); i++)
|
||||
{
|
||||
GObject *item = g_list_model_get_object (model, i);
|
||||
const char *name;
|
||||
|
||||
if (GTK_IS_CONSTRAINT (item))
|
||||
continue;
|
||||
|
||||
name = get_target_name (GTK_CONSTRAINT_TARGET (item));
|
||||
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), name, name);
|
||||
g_object_unref (item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_attribute_combo (GtkWidget *combo,
|
||||
gboolean is_source)
|
||||
{
|
||||
if (is_source)
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "none", "None");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "left", "Left");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "right", "Right");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "top", "Top");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "bottom", "Bottom");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "start", "Start");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "end", "End");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "width", "Width");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "height", "Height");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "center-x", "Center X");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "center-y", "Center Y");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "baseline", "Baseline");
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_relation_combo (GtkWidget *combo)
|
||||
{
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "le", "≤");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "eq", "=");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "ge", "≥");
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_strength_combo (GtkWidget *combo)
|
||||
{
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "weak", "Weak");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "medium", "Medium");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "strong", "Strong");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "required", "Required");
|
||||
}
|
||||
|
||||
static gpointer
|
||||
get_target (GListModel *model,
|
||||
const char *id)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (strcmp ("super", id) == 0)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < g_list_model_get_n_items (model); i++)
|
||||
{
|
||||
GObject *item = g_list_model_get_object (model, i);
|
||||
g_object_unref (item);
|
||||
if (GTK_IS_CONSTRAINT (item))
|
||||
continue;
|
||||
else if (GTK_IS_WIDGET (item))
|
||||
{
|
||||
if (strcmp (id, gtk_widget_get_name (GTK_WIDGET (item))) == 0)
|
||||
return item;
|
||||
}
|
||||
else if (GTK_IS_CONSTRAINT_GUIDE (item))
|
||||
{
|
||||
if (strcmp (id, gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (item))) == 0)
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GtkConstraintAttribute
|
||||
get_target_attr (const char *id)
|
||||
{
|
||||
GtkConstraintAttribute attr;
|
||||
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_ATTRIBUTE);
|
||||
GEnumValue *value = g_enum_get_value_by_nick (class, id);
|
||||
attr = value->value;
|
||||
g_type_class_unref (class);
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_attr_nick (GtkConstraintAttribute attr)
|
||||
{
|
||||
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_ATTRIBUTE);
|
||||
GEnumValue *value = g_enum_get_value (class, attr);
|
||||
const char *nick = value->value_nick;
|
||||
g_type_class_unref (class);
|
||||
|
||||
return nick;
|
||||
}
|
||||
|
||||
static GtkConstraintRelation
|
||||
get_relation (const char *id)
|
||||
{
|
||||
GtkConstraintRelation relation;
|
||||
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_RELATION);
|
||||
GEnumValue *value = g_enum_get_value_by_nick (class, id);
|
||||
relation = value->value;
|
||||
g_type_class_unref (class);
|
||||
|
||||
return relation;
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_relation_nick (GtkConstraintRelation relation)
|
||||
{
|
||||
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_RELATION);
|
||||
GEnumValue *value = g_enum_get_value (class, relation);
|
||||
const char *nick = value->value_nick;
|
||||
g_type_class_unref (class);
|
||||
|
||||
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)
|
||||
{
|
||||
GtkConstraintStrength strength;
|
||||
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_STRENGTH);
|
||||
GEnumValue *value = g_enum_get_value_by_nick (class, id);
|
||||
strength = value->value;
|
||||
g_type_class_unref (class);
|
||||
|
||||
return strength;
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_strength_nick (GtkConstraintStrength strength)
|
||||
{
|
||||
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_STRENGTH);
|
||||
GEnumValue *value = g_enum_get_value (class, strength);
|
||||
const char *nick = value->value_nick;
|
||||
g_type_class_unref (class);
|
||||
|
||||
return nick;
|
||||
}
|
||||
|
||||
void
|
||||
constraint_editor_serialize_constraint (GString *str,
|
||||
int indent,
|
||||
GtkConstraint *constraint)
|
||||
{
|
||||
const char *target;
|
||||
const char *target_attr;
|
||||
const char *relation;
|
||||
const char *source;
|
||||
const char *source_attr;
|
||||
double multiplier;
|
||||
double constant;
|
||||
const char *strength;
|
||||
|
||||
target = get_target_name (gtk_constraint_get_target (constraint));
|
||||
target_attr = get_attr_nick (gtk_constraint_get_target_attribute (constraint));
|
||||
relation = get_relation_nick (gtk_constraint_get_relation (constraint));
|
||||
source = get_target_name (gtk_constraint_get_source (constraint));
|
||||
source_attr = get_attr_nick (gtk_constraint_get_source_attribute (constraint));
|
||||
multiplier = gtk_constraint_get_multiplier (constraint);
|
||||
constant = gtk_constraint_get_constant (constraint);
|
||||
strength = get_strength_nick (gtk_constraint_get_strength (constraint));
|
||||
|
||||
g_string_append_printf (str, "%*s<constraint target=\"%s\" target-attribute=\"%s\"\n", indent, "", target, target_attr);
|
||||
g_string_append_printf (str, "%*s relation=\"%s\"\n", indent, "", relation);
|
||||
if (strcmp (source_attr, "none") != 0)
|
||||
{
|
||||
g_string_append_printf (str, "%*s source=\"%s\" source-attribute=\"%s\"\n", indent, "", source, source_attr);
|
||||
g_string_append_printf (str, "%*s multiplier=\"%g\"\n", indent, "", multiplier);
|
||||
}
|
||||
g_string_append_printf (str, "%*s constant=\"%g\"\n", indent, "", constant);
|
||||
g_string_append_printf (str, "%*s strength=\"%s\" />\n", indent, "", strength);
|
||||
}
|
||||
|
||||
static void
|
||||
create_constraint (GtkButton *button,
|
||||
ConstraintEditor *editor)
|
||||
{
|
||||
const char *id;
|
||||
gpointer target;
|
||||
GtkConstraintAttribute target_attr;
|
||||
gpointer source;
|
||||
GtkConstraintAttribute source_attr;
|
||||
GtkConstraintRelation relation;
|
||||
double multiplier;
|
||||
double constant;
|
||||
int strength;
|
||||
GtkConstraint *constraint;
|
||||
|
||||
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->target));
|
||||
target = get_target (editor->model, id);
|
||||
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->target_attr));
|
||||
target_attr = get_target_attr (id);
|
||||
|
||||
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source));
|
||||
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);
|
||||
|
||||
multiplier = g_ascii_strtod (gtk_editable_get_text (GTK_EDITABLE (editor->multiplier)), NULL);
|
||||
|
||||
constant = g_ascii_strtod (gtk_editable_get_text (GTK_EDITABLE (editor->constant)), NULL);
|
||||
|
||||
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->strength));
|
||||
strength = get_strength (id);
|
||||
|
||||
constraint = gtk_constraint_new (target, target_attr,
|
||||
relation,
|
||||
source, source_attr,
|
||||
multiplier,
|
||||
constant,
|
||||
strength);
|
||||
g_signal_emit (editor, signals[DONE], 0, constraint);
|
||||
g_object_unref (constraint);
|
||||
}
|
||||
|
||||
static void
|
||||
source_attr_changed (ConstraintEditor *editor)
|
||||
{
|
||||
const char *id;
|
||||
|
||||
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source_attr));
|
||||
if (strcmp (id, "none") == 0)
|
||||
{
|
||||
gtk_combo_box_set_active (GTK_COMBO_BOX (editor->source), -1);
|
||||
gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), "");
|
||||
gtk_widget_set_sensitive (editor->source, FALSE);
|
||||
gtk_widget_set_sensitive (editor->multiplier, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_set_sensitive (editor->source, TRUE);
|
||||
gtk_widget_set_sensitive (editor->multiplier, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
constraint_editor_constraint_to_string (GtkConstraint *constraint)
|
||||
{
|
||||
GString *str;
|
||||
const char *name;
|
||||
const char *attr;
|
||||
const char *relation;
|
||||
double c, m;
|
||||
|
||||
str = g_string_new ("");
|
||||
|
||||
name = get_target_name (gtk_constraint_get_target (constraint));
|
||||
attr = get_attr_nick (gtk_constraint_get_target_attribute (constraint));
|
||||
relation = get_relation_to_string (gtk_constraint_get_relation (constraint));
|
||||
|
||||
if (name == NULL)
|
||||
name = "[ ]";
|
||||
|
||||
g_string_append_printf (str, "%s.%s %s ", name, attr, relation);
|
||||
|
||||
c = gtk_constraint_get_constant (constraint);
|
||||
|
||||
attr = get_attr_nick (gtk_constraint_get_source_attribute (constraint));
|
||||
if (strcmp (attr, "none") != 0)
|
||||
{
|
||||
name = get_target_name (gtk_constraint_get_source (constraint));
|
||||
m = gtk_constraint_get_multiplier (constraint);
|
||||
|
||||
if (name == NULL)
|
||||
name = "[ ]";
|
||||
|
||||
g_string_append_printf (str, "%s.%s", name, attr);
|
||||
|
||||
if (m != 1.0)
|
||||
g_string_append_printf (str, " × %g", m);
|
||||
|
||||
if (c > 0.0)
|
||||
g_string_append_printf (str, " + %g", c);
|
||||
else if (c < 0.0)
|
||||
g_string_append_printf (str, " - %g", -c);
|
||||
}
|
||||
else
|
||||
g_string_append_printf (str, "%g", c);
|
||||
|
||||
return g_string_free (str, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
update_preview (ConstraintEditor *editor)
|
||||
{
|
||||
GString *str;
|
||||
const char *name;
|
||||
const char *attr;
|
||||
char *relation;
|
||||
const char *multiplier;
|
||||
const char *constant;
|
||||
double c, m;
|
||||
|
||||
if (!editor->constructed)
|
||||
return;
|
||||
|
||||
str = g_string_new ("");
|
||||
|
||||
name = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->target));
|
||||
attr = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->target_attr));
|
||||
relation = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (editor->relation));
|
||||
|
||||
if (name == NULL)
|
||||
name = "[ ]";
|
||||
|
||||
g_string_append_printf (str, "%s.%s %s ", name, attr, relation);
|
||||
g_free (relation);
|
||||
|
||||
constant = gtk_editable_get_text (GTK_EDITABLE (editor->constant));
|
||||
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));
|
||||
if (multiplier[0] != '\0')
|
||||
m = g_ascii_strtod (multiplier, NULL);
|
||||
else
|
||||
m = 1.0;
|
||||
|
||||
if (name == NULL)
|
||||
name = "[ ]";
|
||||
|
||||
g_string_append_printf (str, "%s.%s", name, attr);
|
||||
|
||||
if (m != 1.0)
|
||||
g_string_append_printf (str, " × %g", m);
|
||||
|
||||
if (c > 0.0)
|
||||
g_string_append_printf (str, " + %g", c);
|
||||
else if (c < 0.0)
|
||||
g_string_append_printf (str, " - %g", -c);
|
||||
}
|
||||
else
|
||||
g_string_append_printf (str, "%g", c);
|
||||
|
||||
gtk_label_set_label (GTK_LABEL (editor->preview), str->str);
|
||||
|
||||
g_string_free (str, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
update_button (ConstraintEditor *editor)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_init (ConstraintEditor *editor)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (editor));
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_constructed (GObject *object)
|
||||
{
|
||||
ConstraintEditor *editor = CONSTRAINT_EDITOR (object);
|
||||
|
||||
constraint_target_combo (editor->model, editor->target, FALSE);
|
||||
constraint_attribute_combo (editor->target_attr, FALSE);
|
||||
constraint_relation_combo (editor->relation);
|
||||
constraint_target_combo (editor->model, editor->source, TRUE);
|
||||
constraint_attribute_combo (editor->source_attr, TRUE);
|
||||
|
||||
constraint_strength_combo (editor->strength);
|
||||
|
||||
if (editor->constraint)
|
||||
{
|
||||
GtkConstraintTarget *target;
|
||||
GtkConstraintAttribute attr;
|
||||
GtkConstraintRelation relation;
|
||||
GtkConstraintStrength strength;
|
||||
const char *nick;
|
||||
char *val;
|
||||
double multiplier;
|
||||
double constant;
|
||||
|
||||
target = gtk_constraint_get_target (editor->constraint);
|
||||
nick = get_target_name (target);
|
||||
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->target), nick);
|
||||
|
||||
attr = gtk_constraint_get_target_attribute (editor->constraint);
|
||||
nick = get_attr_nick (attr);
|
||||
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->target_attr), nick);
|
||||
|
||||
target = gtk_constraint_get_source (editor->constraint);
|
||||
nick = get_target_name (target);
|
||||
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->source), nick);
|
||||
|
||||
attr = gtk_constraint_get_source_attribute (editor->constraint);
|
||||
nick = get_attr_nick (attr);
|
||||
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->source_attr), nick);
|
||||
|
||||
relation = gtk_constraint_get_relation (editor->constraint);
|
||||
nick = get_relation_nick (relation);
|
||||
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->relation), nick);
|
||||
|
||||
multiplier = gtk_constraint_get_multiplier (editor->constraint);
|
||||
val = g_strdup_printf ("%g", multiplier);
|
||||
gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), val);
|
||||
g_free (val);
|
||||
|
||||
constant = gtk_constraint_get_constant (editor->constraint);
|
||||
val = g_strdup_printf ("%g", constant);
|
||||
gtk_editable_set_text (GTK_EDITABLE (editor->constant), val);
|
||||
g_free (val);
|
||||
|
||||
strength = gtk_constraint_get_strength (editor->constraint);
|
||||
nick = get_strength_nick (strength);
|
||||
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->strength), nick);
|
||||
|
||||
gtk_button_set_label (GTK_BUTTON (editor->button), "Apply");
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->target_attr), "left");
|
||||
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->source_attr), "left");
|
||||
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->relation), "eq");
|
||||
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->strength), "required");
|
||||
|
||||
gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), "1.0");
|
||||
gtk_editable_set_text (GTK_EDITABLE (editor->constant), "0.0");
|
||||
|
||||
gtk_button_set_label (GTK_BUTTON (editor->button), "Create");
|
||||
}
|
||||
|
||||
editor->constructed = TRUE;
|
||||
update_preview (editor);
|
||||
update_button (editor);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ConstraintEditor *self = CONSTRAINT_EDITOR (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_MODEL:
|
||||
self->model = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
case PROP_CONSTRAINT:
|
||||
self->constraint = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ConstraintEditor *self = CONSTRAINT_EDITOR (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_MODEL:
|
||||
g_value_set_object (value, self->model);
|
||||
break;
|
||||
|
||||
case PROP_CONSTRAINT:
|
||||
g_value_set_object (value, self->constraint);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_dispose (GObject *object)
|
||||
{
|
||||
ConstraintEditor *self = (ConstraintEditor *)object;
|
||||
|
||||
g_clear_pointer (&self->grid, gtk_widget_unparent);
|
||||
g_clear_object (&self->model);
|
||||
g_clear_object (&self->constraint);
|
||||
|
||||
G_OBJECT_CLASS (constraint_editor_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_class_init (ConstraintEditorClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
|
||||
object_class->constructed = constraint_editor_constructed;
|
||||
object_class->dispose = constraint_editor_dispose;
|
||||
object_class->set_property = constraint_editor_set_property;
|
||||
object_class->get_property = constraint_editor_get_property;
|
||||
|
||||
pspecs[PROP_CONSTRAINT] =
|
||||
g_param_spec_object ("constraint", "constraint", "constraint",
|
||||
GTK_TYPE_CONSTRAINT,
|
||||
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
pspecs[PROP_MODEL] =
|
||||
g_param_spec_object ("model", "model", "model",
|
||||
G_TYPE_LIST_MODEL,
|
||||
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_CONSTRAINT);
|
||||
|
||||
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/constraint-editor.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, grid);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, target);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, target_attr);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, relation);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, source);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, source_attr);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, multiplier);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, constant);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, strength);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, preview);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, button);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, update_preview);
|
||||
gtk_widget_class_bind_template_callback (widget_class, update_button);
|
||||
gtk_widget_class_bind_template_callback (widget_class, create_constraint);
|
||||
gtk_widget_class_bind_template_callback (widget_class, source_attr_changed);
|
||||
}
|
||||
|
||||
ConstraintEditor *
|
||||
constraint_editor_new (GListModel *model,
|
||||
GtkConstraint *constraint)
|
||||
{
|
||||
return g_object_new (CONSTRAINT_EDITOR_TYPE,
|
||||
"model", model,
|
||||
"constraint", constraint,
|
||||
NULL);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
constraintview {
|
||||
background: black;
|
||||
color: white;
|
||||
}
|
||||
|
||||
constraintview .child {
|
||||
background: red;
|
||||
}
|
||||
|
||||
constraintview guide {
|
||||
background: blue;
|
||||
border: 1px solid white;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/org/gtk/gtk4/constraint-editor">
|
||||
<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>
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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 CONSTRAINT_EDITOR_TYPE (constraint_editor_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ConstraintEditor, constraint_editor, CONSTRAINT, EDITOR, GtkWidget)
|
||||
|
||||
ConstraintEditor * constraint_editor_new (GListModel *model,
|
||||
GtkConstraint *constraint);
|
||||
|
||||
void constraint_editor_serialize_constraint (GString *str,
|
||||
int indent,
|
||||
GtkConstraint *constraint);
|
||||
char *constraint_editor_constraint_to_string (GtkConstraint *constraint);
|
||||
@@ -0,0 +1,163 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="ConstraintEditor" 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">Target</property>
|
||||
<layout>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="target">
|
||||
<signal name="changed" handler="update_preview" swapped="yes"/>
|
||||
<signal name="changed" handler="update_button" swapped="yes"/>
|
||||
<layout>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="target_attr">
|
||||
<signal name="changed" handler="update_preview" swapped="yes"/>
|
||||
<layout>
|
||||
<property name="left-attach">2</property>
|
||||
<property name="top-attach">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Relation</property>
|
||||
<layout>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="relation">
|
||||
<signal name="changed" handler="update_preview" swapped="yes"/>
|
||||
<layout>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Source</property>
|
||||
<layout>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="source">
|
||||
<signal name="changed" handler="update_preview" swapped="yes"/>
|
||||
<signal name="changed" handler="update_button" swapped="yes"/>
|
||||
<layout>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="source_attr">
|
||||
<signal name="changed" handler="update_preview" swapped="yes"/>
|
||||
<signal name="changed" handler="source_attr_changed" swapped="yes"/>
|
||||
<layout>
|
||||
<property name="left-attach">2</property>
|
||||
<property name="top-attach">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Multiplier</property>
|
||||
<layout>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">4</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="multiplier">
|
||||
<signal name="changed" handler="update_preview" swapped="yes"/>
|
||||
<layout>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">4</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Constant</property>
|
||||
<layout>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">5</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="constant">
|
||||
<signal name="changed" handler="update_preview" swapped="yes"/>
|
||||
<layout>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">5</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Strength</property>
|
||||
<layout>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">6</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="strength">
|
||||
<layout>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">6</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="preview">
|
||||
<property name="xalign">0</property>
|
||||
<layout>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">7</property>
|
||||
<property name="column-span">2</property>
|
||||
</layout>
|
||||
<attributes>
|
||||
<attribute name="scale" value="1.44"/>
|
||||
</attributes>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button">
|
||||
<property name="label">Create</property>
|
||||
<signal name="clicked" handler="create_constraint"/>
|
||||
<layout>
|
||||
<property name="left-attach">2</property>
|
||||
<property name="top-attach">8</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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 "constraint-view-child.h"
|
||||
|
||||
struct _ConstraintViewChild
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
char *name;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_NAME = 1,
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
static GParamSpec props[LAST_PROP];
|
||||
|
||||
G_DEFINE_TYPE (ConstraintViewChild, constraint_view_child, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
constraint_view_child_init (ConstraintViewChild *child)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_view_child_finalize (GObject *object)
|
||||
{
|
||||
ConstraintViewChild *child = CONSTRAINT_VIEW_CHILD (object);
|
||||
|
||||
g_free (child->name);
|
||||
|
||||
G_OBJECT_CLASS (constraint_view_child_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_view_child_set_property (GObject *object,
|
||||
|
||||
static void
|
||||
constraint_view_child_class_init (ConstraintViewChildClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
object_class->finalize = constraint_view_child_finalize;
|
||||
object_class->get_property = constraint_view_child_get_property;
|
||||
object_class->set_property = constraint_view_child_set_property;
|
||||
|
||||
props[PROP_NAME] =
|
||||
g_param_spec_string ("name", "name", "name",
|
||||
NULL,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_properties (object_class, LAST_PROP, props);
|
||||
}
|
||||
|
||||
#define CONSTRAINT_VIEW_CHILD_TYPE (constraint_view_get_type ())
|
||||
|
||||
G_DECLARE_TYPE (ConstraintViewChild, constraint_view_child, CONSTRAINT, VIEW_CHILD, GObject)
|
||||
|
||||
#define CONSTRAINT_VIEW_WIDGET_TYPE (constraint_view_widget_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ConstraintViewWidget, constraint_view_widget, CONSTRAINT, VIEW_WIDGET, ConstraintViewChild)
|
||||
|
||||
ConstraintViewWidget * constraint_view_widget_new (void);
|
||||
|
||||
#define CONSTRAINT_VIEW_GUIDE_TYPE (constraint_view_guide_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ConstraintViewGuide, constraint_view_guide, CONSTRAINT, VIEW_GUIDE, ConstraintViewChild)
|
||||
|
||||
ConstraintViewGuide * constraint_view_guide_new (void);
|
||||
|
||||
#define CONSTRAINT_VIEW_CONSTRAINT_TYPE (constraint_view_constraint_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ConstraintViewConstraint, constraint_view_constraint, CONSTRAINT, VIEW_CONSTRAINT, ConstraintViewChild)
|
||||
|
||||
ConstraintViewGuide * constraint_view_constraint_new (void);
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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 CONSTRAINT_VIEW_CHILD_TYPE (constraint_view_get_type ())
|
||||
|
||||
G_DECLARE_TYPE (ConstraintViewChild, constraint_view_child, CONSTRAINT, VIEW_CHILD, GObject)
|
||||
|
||||
#define CONSTRAINT_VIEW_WIDGET_TYPE (constraint_view_widget_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ConstraintViewWidget, constraint_view_widget, CONSTRAINT, VIEW_WIDGET, ConstraintViewChild)
|
||||
|
||||
ConstraintViewWidget * constraint_view_widget_new (void);
|
||||
|
||||
#define CONSTRAINT_VIEW_GUIDE_TYPE (constraint_view_guide_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ConstraintViewGuide, constraint_view_guide, CONSTRAINT, VIEW_GUIDE, ConstraintViewChild)
|
||||
|
||||
ConstraintViewGuide * constraint_view_guide_new (void);
|
||||
|
||||
#define CONSTRAINT_VIEW_CONSTRAINT_TYPE (constraint_view_constraint_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ConstraintViewConstraint, constraint_view_constraint, CONSTRAINT, VIEW_CONSTRAINT, ConstraintViewChild)
|
||||
|
||||
ConstraintViewGuide * constraint_view_constraint_new (void);
|
||||
@@ -0,0 +1,350 @@
|
||||
/* Copyright (C) 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 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 <gtk/gtk.h>
|
||||
#include "constraint-view.h"
|
||||
#include "guide-placeholder.h"
|
||||
|
||||
struct _ConstraintView
|
||||
{
|
||||
GtkWidget parent;
|
||||
|
||||
GListModel *model;
|
||||
|
||||
GtkWidget *drag_widget;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (ConstraintView, constraint_view, GTK_TYPE_WIDGET);
|
||||
|
||||
static void
|
||||
constraint_view_dispose (GObject *object)
|
||||
{
|
||||
ConstraintView *view = CONSTRAINT_VIEW (object);
|
||||
GtkWidget *child;
|
||||
|
||||
while ((child = gtk_widget_get_first_child (GTK_WIDGET (view))) != NULL)
|
||||
gtk_widget_unparent (child);
|
||||
|
||||
g_clear_object (&view->model);
|
||||
|
||||
G_OBJECT_CLASS (constraint_view_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_view_class_init (ConstraintViewClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->dispose = constraint_view_dispose;
|
||||
|
||||
gtk_widget_class_set_css_name (widget_class, "constraintview");
|
||||
}
|
||||
|
||||
static void
|
||||
update_weak_position (ConstraintView *self,
|
||||
GtkWidget *child,
|
||||
double x,
|
||||
double y)
|
||||
{
|
||||
GtkLayoutManager *manager;
|
||||
GtkConstraint *constraint;
|
||||
|
||||
manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
|
||||
constraint = (GtkConstraint *)g_object_get_data (G_OBJECT (child), "x-constraint");
|
||||
if (constraint)
|
||||
{
|
||||
gtk_constraint_layout_remove_constraint (GTK_CONSTRAINT_LAYOUT (manager),
|
||||
constraint);
|
||||
g_object_set_data (G_OBJECT (child), "x-constraint", NULL);
|
||||
}
|
||||
if (x != -100)
|
||||
{
|
||||
constraint = gtk_constraint_new_constant (child,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_CENTER_X,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
x,
|
||||
GTK_CONSTRAINT_STRENGTH_WEAK);
|
||||
g_object_set_data (G_OBJECT (constraint), "internal", "yes");
|
||||
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (manager),
|
||||
constraint);
|
||||
g_object_set_data (G_OBJECT (child), "x-constraint", constraint);
|
||||
}
|
||||
|
||||
constraint = (GtkConstraint *)g_object_get_data (G_OBJECT (child), "y-constraint");
|
||||
if (constraint)
|
||||
{
|
||||
gtk_constraint_layout_remove_constraint (GTK_CONSTRAINT_LAYOUT (manager),
|
||||
constraint);
|
||||
g_object_set_data (G_OBJECT (child), "y-constraint", NULL);
|
||||
}
|
||||
if (y != -100)
|
||||
{
|
||||
constraint = gtk_constraint_new_constant (child,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_CENTER_Y,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
y,
|
||||
GTK_CONSTRAINT_STRENGTH_WEAK);
|
||||
g_object_set_data (G_OBJECT (constraint), "internal", "yes");
|
||||
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (manager),
|
||||
constraint);
|
||||
g_object_set_data (G_OBJECT (child), "y-constraint", constraint);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
drag_begin (GtkGestureDrag *drag,
|
||||
double start_x,
|
||||
double start_y,
|
||||
ConstraintView *self)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GtkWidget *target;
|
||||
|
||||
widget = gtk_widget_pick (GTK_WIDGET (self), start_x, start_y, GTK_PICK_DEFAULT);
|
||||
|
||||
if (widget)
|
||||
{
|
||||
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 = target;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
drag_update (GtkGestureDrag *drag,
|
||||
double offset_x,
|
||||
double offset_y,
|
||||
ConstraintView *self)
|
||||
{
|
||||
double x, y;
|
||||
|
||||
if (!self->drag_widget)
|
||||
return;
|
||||
|
||||
gtk_gesture_drag_get_start_point (drag, &x, &y);
|
||||
update_weak_position (self, self->drag_widget, x + offset_x, y + offset_y);
|
||||
}
|
||||
|
||||
static void
|
||||
drag_end (GtkGestureDrag *drag,
|
||||
double offset_x,
|
||||
double offset_y,
|
||||
ConstraintView *self)
|
||||
{
|
||||
self->drag_widget = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
omit_internal (gpointer item, gpointer user_data)
|
||||
{
|
||||
if (g_object_get_data (G_OBJECT (item), "internal"))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_view_init (ConstraintView *self)
|
||||
{
|
||||
GtkLayoutManager *manager;
|
||||
GtkEventController *controller;
|
||||
GListStore *list;
|
||||
GListModel *all_children;
|
||||
GListModel *all_constraints;
|
||||
GListModel *guides;
|
||||
GListModel *children;
|
||||
GListModel *constraints;
|
||||
|
||||
manager = gtk_constraint_layout_new ();
|
||||
gtk_widget_set_layout_manager (GTK_WIDGET (self), manager);
|
||||
|
||||
all_children = gtk_widget_observe_children (GTK_WIDGET (self));
|
||||
all_constraints = gtk_constraint_layout_observe_constraints (GTK_CONSTRAINT_LAYOUT (manager));
|
||||
guides = gtk_constraint_layout_observe_guides (GTK_CONSTRAINT_LAYOUT (manager));
|
||||
constraints = (GListModel *)gtk_filter_list_model_new (all_constraints, omit_internal, NULL, NULL);
|
||||
children = (GListModel *)gtk_filter_list_model_new (all_children, omit_internal, NULL, NULL);
|
||||
|
||||
list = g_list_store_new (G_TYPE_LIST_MODEL);
|
||||
g_list_store_append (list, children);
|
||||
g_list_store_append (list, guides);
|
||||
g_list_store_append (list, constraints);
|
||||
self->model = G_LIST_MODEL (gtk_flatten_list_model_new (G_TYPE_OBJECT, G_LIST_MODEL (list)));
|
||||
g_object_unref (children);
|
||||
g_object_unref (guides);
|
||||
g_object_unref (constraints);
|
||||
g_object_unref (all_children);
|
||||
g_object_unref (all_constraints);
|
||||
g_object_unref (list);
|
||||
|
||||
|
||||
controller = (GtkEventController *)gtk_gesture_drag_new ();
|
||||
g_signal_connect (controller, "drag-begin", G_CALLBACK (drag_begin), self);
|
||||
g_signal_connect (controller, "drag-update", G_CALLBACK (drag_update), self);
|
||||
g_signal_connect (controller, "drag-end", G_CALLBACK (drag_end), self);
|
||||
gtk_widget_add_controller (GTK_WIDGET (self), controller);
|
||||
}
|
||||
|
||||
ConstraintView *
|
||||
constraint_view_new (void)
|
||||
{
|
||||
return g_object_new (CONSTRAINT_VIEW_TYPE, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
constraint_view_add_child (ConstraintView *view,
|
||||
const char *name)
|
||||
{
|
||||
GtkWidget *frame;
|
||||
GtkWidget *label;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
constraint_view_remove_child (ConstraintView *view,
|
||||
GtkWidget *child)
|
||||
{
|
||||
update_weak_position (view, child, -100, -100);
|
||||
gtk_widget_unparent (child);
|
||||
}
|
||||
|
||||
void
|
||||
constraint_view_add_guide (ConstraintView *view,
|
||||
GtkConstraintGuide *guide)
|
||||
{
|
||||
GtkConstraintLayout *layout;
|
||||
GtkWidget *placeholder;
|
||||
const char *name;
|
||||
GtkConstraint *constraint;
|
||||
struct {
|
||||
const char *name;
|
||||
GtkConstraintAttribute attr;
|
||||
} names[] = {
|
||||
{ "left-constraint", GTK_CONSTRAINT_ATTRIBUTE_LEFT },
|
||||
{ "top-constraint", GTK_CONSTRAINT_ATTRIBUTE_TOP },
|
||||
{ "width-constraint", GTK_CONSTRAINT_ATTRIBUTE_WIDTH },
|
||||
{ "height-constraint", GTK_CONSTRAINT_ATTRIBUTE_HEIGHT },
|
||||
};
|
||||
int i;
|
||||
|
||||
name = gtk_constraint_guide_get_name (guide);
|
||||
|
||||
placeholder = guide_placeholder_new (guide);
|
||||
gtk_widget_set_tooltip_text (placeholder, name);
|
||||
g_object_bind_property (guide, "name",
|
||||
placeholder, "tooltip-text",
|
||||
G_BINDING_DEFAULT);
|
||||
|
||||
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), "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 (placeholder,
|
||||
names[i].attr,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
guide,
|
||||
names[i].attr,
|
||||
1.0, 0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
g_object_set_data (G_OBJECT (constraint), "internal", "yes");
|
||||
gtk_constraint_layout_add_constraint (layout, constraint);
|
||||
g_object_set_data (G_OBJECT (guide), names[i].name, constraint);
|
||||
}
|
||||
|
||||
update_weak_position (view, placeholder, 150, 150);
|
||||
}
|
||||
|
||||
void
|
||||
constraint_view_remove_guide (ConstraintView *view,
|
||||
GtkConstraintGuide *guide)
|
||||
{
|
||||
GtkConstraintLayout *layout;
|
||||
GtkWidget *placeholder;
|
||||
GtkConstraint *constraint;
|
||||
const char *names[] = {
|
||||
"left-constraint",
|
||||
"top-constraint",
|
||||
"width-constraint",
|
||||
"height-constraint"
|
||||
};
|
||||
int i;
|
||||
|
||||
layout = GTK_CONSTRAINT_LAYOUT (gtk_widget_get_layout_manager (GTK_WIDGET (view)));
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (names); i++)
|
||||
{
|
||||
constraint = (GtkConstraint*)g_object_get_data (G_OBJECT (guide), names[i]);
|
||||
gtk_constraint_layout_remove_constraint (layout, constraint);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
constraint_view_add_constraint (ConstraintView *view,
|
||||
GtkConstraint *constraint)
|
||||
{
|
||||
GtkLayoutManager *manager;
|
||||
|
||||
manager = gtk_widget_get_layout_manager (GTK_WIDGET (view));
|
||||
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (manager),
|
||||
g_object_ref (constraint));
|
||||
}
|
||||
|
||||
void
|
||||
constraint_view_remove_constraint (ConstraintView *view,
|
||||
GtkConstraint *constraint)
|
||||
{
|
||||
GtkLayoutManager *manager;
|
||||
|
||||
manager = gtk_widget_get_layout_manager (GTK_WIDGET (view));
|
||||
gtk_constraint_layout_remove_constraint (GTK_CONSTRAINT_LAYOUT (manager),
|
||||
constraint);
|
||||
}
|
||||
|
||||
GListModel *
|
||||
constraint_view_get_model (ConstraintView *view)
|
||||
{
|
||||
return view->model;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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 CONSTRAINT_VIEW_TYPE (constraint_view_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ConstraintView, constraint_view, CONSTRAINT, VIEW, GtkWidget)
|
||||
|
||||
ConstraintView * constraint_view_new (void);
|
||||
|
||||
void constraint_view_add_child (ConstraintView *view,
|
||||
const char *name);
|
||||
void constraint_view_remove_child (ConstraintView *view,
|
||||
GtkWidget *child);
|
||||
void constraint_view_add_guide (ConstraintView *view,
|
||||
GtkConstraintGuide *guide);
|
||||
void constraint_view_remove_guide (ConstraintView *view,
|
||||
GtkConstraintGuide *guide);
|
||||
void constraint_view_guide_changed (ConstraintView *view,
|
||||
GtkConstraintGuide *guide);
|
||||
void constraint_view_add_constraint (ConstraintView *view,
|
||||
GtkConstraint *constraint);
|
||||
void constraint_view_remove_constraint (ConstraintView *view,
|
||||
GtkConstraint *constraint);
|
||||
GListModel * constraint_view_get_model (ConstraintView *view);
|
||||
@@ -0,0 +1,411 @@
|
||||
/*
|
||||
* 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-editor.h"
|
||||
|
||||
struct _GuideEditor
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GtkWidget *grid;
|
||||
GtkWidget *name;
|
||||
GtkWidget *min_width;
|
||||
GtkWidget *min_height;
|
||||
GtkWidget *nat_width;
|
||||
GtkWidget *nat_height;
|
||||
GtkWidget *max_width;
|
||||
GtkWidget *max_height;
|
||||
GtkWidget *strength;
|
||||
GtkWidget *button;
|
||||
|
||||
GtkConstraintGuide *guide;
|
||||
|
||||
gboolean constructed;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_GUIDE = 1,
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
static GParamSpec *pspecs[LAST_PROP];
|
||||
|
||||
enum {
|
||||
DONE,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
G_DEFINE_TYPE(GuideEditor, guide_editor, GTK_TYPE_WIDGET);
|
||||
|
||||
static void
|
||||
guide_strength_combo (GtkWidget *combo)
|
||||
{
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "weak", "Weak");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "medium", "Medium");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "strong", "Strong");
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "required", "Required");
|
||||
}
|
||||
|
||||
static GtkConstraintStrength
|
||||
get_strength (const char *id)
|
||||
{
|
||||
GtkConstraintStrength strength;
|
||||
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_STRENGTH);
|
||||
GEnumValue *value = g_enum_get_value_by_nick (class, id);
|
||||
strength = value->value;
|
||||
g_type_class_unref (class);
|
||||
|
||||
return strength;
|
||||
}
|
||||
|
||||
const char *
|
||||
get_strength_nick (GtkConstraintStrength strength)
|
||||
{
|
||||
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_STRENGTH);
|
||||
GEnumValue *value = g_enum_get_value (class, strength);
|
||||
const char *nick = value->value_nick;
|
||||
g_type_class_unref (class);
|
||||
|
||||
return nick;
|
||||
}
|
||||
|
||||
void
|
||||
guide_editor_serialize_guide (GString *str,
|
||||
int indent,
|
||||
GtkConstraintGuide *guide)
|
||||
{
|
||||
int min_width, min_height;
|
||||
int nat_width, nat_height;
|
||||
int max_width, max_height;
|
||||
const char *name;
|
||||
const char *strength;
|
||||
|
||||
gtk_constraint_guide_get_min_size (guide, &min_width, &min_height);
|
||||
gtk_constraint_guide_get_nat_size (guide, &nat_width, &nat_height);
|
||||
gtk_constraint_guide_get_max_size (guide, &max_width, &max_height);
|
||||
name = gtk_constraint_guide_get_name (guide);
|
||||
strength = get_strength_nick (gtk_constraint_guide_get_strength (guide));
|
||||
|
||||
g_string_append_printf (str, "%*s<guide min-width=\"%d\" min-height=\"%d\"\n", indent, "", min_width, min_height);
|
||||
g_string_append_printf (str, "%*s nat-width=\"%d\" nat-height=\"%d\"\n", indent, "", nat_width, nat_height);
|
||||
g_string_append_printf (str, "%*s max-width=\"%d\" max-height=\"%d\"\n", indent, "", max_width, max_height);
|
||||
g_string_append_printf (str, "%*s name=\"%s\" strength=\"%s\" />\n", indent, "", name, strength);
|
||||
}
|
||||
|
||||
static void
|
||||
create_guide (GtkButton *button,
|
||||
GuideEditor *editor)
|
||||
{
|
||||
const char *id;
|
||||
int strength;
|
||||
const char *name;
|
||||
int w, h;
|
||||
GtkConstraintGuide *guide;
|
||||
|
||||
if (editor->guide)
|
||||
guide = g_object_ref (editor->guide);
|
||||
else
|
||||
guide = gtk_constraint_guide_new ();
|
||||
|
||||
name = gtk_editable_get_text (GTK_EDITABLE (editor->name));
|
||||
gtk_constraint_guide_set_name (guide, 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_constraint_guide_set_min_size (guide, w, h);
|
||||
|
||||
w = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->nat_width));
|
||||
h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->nat_height));
|
||||
gtk_constraint_guide_set_nat_size (guide, w, h);
|
||||
|
||||
w = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->max_width));
|
||||
h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->max_height));
|
||||
gtk_constraint_guide_set_max_size (guide, w, h);
|
||||
|
||||
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->strength));
|
||||
strength = get_strength (id);
|
||||
gtk_constraint_guide_set_strength (guide, strength);
|
||||
|
||||
g_signal_emit (editor, signals[DONE], 0, guide);
|
||||
g_object_unref (guide);
|
||||
}
|
||||
|
||||
static void
|
||||
guide_editor_init (GuideEditor *editor)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (editor));
|
||||
}
|
||||
|
||||
static int guide_counter;
|
||||
|
||||
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 int
|
||||
max_input (GtkSpinButton *spin_button,
|
||||
double *new_val)
|
||||
{
|
||||
if (strcmp (gtk_editable_get_text (GTK_EDITABLE (spin_button)), "") == 0)
|
||||
{
|
||||
*new_val = G_MAXINT;
|
||||
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 gboolean
|
||||
max_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 == (double)G_MAXINT)
|
||||
{
|
||||
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
|
||||
guide_editor_constructed (GObject *object)
|
||||
{
|
||||
GuideEditor *editor = GUIDE_EDITOR (object);
|
||||
|
||||
guide_strength_combo (editor->strength);
|
||||
|
||||
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);
|
||||
|
||||
g_signal_connect (editor->max_width, "input", G_CALLBACK (max_input), NULL);
|
||||
g_signal_connect (editor->max_width, "output", G_CALLBACK (max_output), NULL);
|
||||
|
||||
g_signal_connect (editor->max_height, "input", G_CALLBACK (max_input), NULL);
|
||||
g_signal_connect (editor->max_height, "output", G_CALLBACK (max_output), NULL);
|
||||
|
||||
if (editor->guide)
|
||||
{
|
||||
GtkConstraintStrength strength;
|
||||
const char *nick;
|
||||
int w, h;
|
||||
|
||||
nick = gtk_constraint_guide_get_name (editor->guide);
|
||||
if (nick)
|
||||
gtk_editable_set_text (GTK_EDITABLE (editor->name), nick);
|
||||
|
||||
gtk_constraint_guide_get_min_size (editor->guide, &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);
|
||||
|
||||
gtk_constraint_guide_get_nat_size (editor->guide, &w, &h);
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->nat_width), w);
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->nat_height), h);
|
||||
|
||||
gtk_constraint_guide_get_max_size (editor->guide, &w, &h);
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_width), w);
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_height), h);
|
||||
|
||||
strength = gtk_constraint_guide_get_strength (editor->guide);
|
||||
nick = get_strength_nick (strength);
|
||||
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->strength), nick);
|
||||
|
||||
gtk_button_set_label (GTK_BUTTON (editor->button), "Apply");
|
||||
}
|
||||
else
|
||||
{
|
||||
char *name;
|
||||
|
||||
guide_counter++;
|
||||
name = g_strdup_printf ("Guide %d", guide_counter);
|
||||
gtk_editable_set_text (GTK_EDITABLE (editor->name), name);
|
||||
g_free (name);
|
||||
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->min_width), 0.0);
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->min_height), 0.0);
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->nat_width), 0.0);
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->nat_height), 0.0);
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_width), G_MAXINT);
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_height), G_MAXINT);
|
||||
|
||||
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->strength), "medium");
|
||||
|
||||
gtk_button_set_label (GTK_BUTTON (editor->button), "Create");
|
||||
}
|
||||
|
||||
editor->constructed = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
guide_editor_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GuideEditor *self = GUIDE_EDITOR (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_GUIDE:
|
||||
self->guide = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
guide_editor_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GuideEditor *self = GUIDE_EDITOR (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_GUIDE:
|
||||
g_value_set_object (value, self->guide);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
guide_editor_dispose (GObject *object)
|
||||
{
|
||||
GuideEditor *self = (GuideEditor *)object;
|
||||
|
||||
g_clear_pointer (&self->grid, gtk_widget_unparent);
|
||||
g_clear_object (&self->guide);
|
||||
|
||||
G_OBJECT_CLASS (guide_editor_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
guide_editor_class_init (GuideEditorClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
|
||||
object_class->constructed = guide_editor_constructed;
|
||||
object_class->dispose = guide_editor_dispose;
|
||||
object_class->set_property = guide_editor_set_property;
|
||||
object_class->get_property = guide_editor_get_property;
|
||||
|
||||
pspecs[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, 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_CONSTRAINT_GUIDE);
|
||||
|
||||
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/guide-editor.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, GuideEditor, grid);
|
||||
gtk_widget_class_bind_template_child (widget_class, GuideEditor, name);
|
||||
gtk_widget_class_bind_template_child (widget_class, GuideEditor, min_width);
|
||||
gtk_widget_class_bind_template_child (widget_class, GuideEditor, min_height);
|
||||
gtk_widget_class_bind_template_child (widget_class, GuideEditor, nat_width);
|
||||
gtk_widget_class_bind_template_child (widget_class, GuideEditor, nat_height);
|
||||
gtk_widget_class_bind_template_child (widget_class, GuideEditor, max_width);
|
||||
gtk_widget_class_bind_template_child (widget_class, GuideEditor, max_height);
|
||||
gtk_widget_class_bind_template_child (widget_class, GuideEditor, strength);
|
||||
gtk_widget_class_bind_template_child (widget_class, GuideEditor, button);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, create_guide);
|
||||
}
|
||||
|
||||
GuideEditor *
|
||||
guide_editor_new (GtkConstraintGuide *guide)
|
||||
{
|
||||
return g_object_new (GUIDE_EDITOR_TYPE,
|
||||
"guide", guide,
|
||||
NULL);
|
||||
}
|
||||
@@ -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 GUIDE_EDITOR_TYPE (guide_editor_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GuideEditor, guide_editor, GUIDE, EDITOR, GtkWidget)
|
||||
|
||||
GuideEditor * guide_editor_new (GtkConstraintGuide *guide);
|
||||
|
||||
void guide_editor_serialize_guide (GString *str,
|
||||
int indent,
|
||||
GtkConstraintGuide *guide);
|
||||
@@ -0,0 +1,188 @@
|
||||
<?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>
|
||||
<object class="GtkAdjustment" id="nat_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="nat_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>
|
||||
<object class="GtkAdjustment" id="max_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="max_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="GuideEditor" 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="GtkLabel">
|
||||
<property name="label">Nat Size</property>
|
||||
<layout>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="nat_width">
|
||||
<property name="adjustment">nat_width_adj</property>
|
||||
<property name="max-width-chars">5</property>
|
||||
<layout>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="nat_height">
|
||||
<property name="adjustment">nat_height_adj</property>
|
||||
<property name="max-width-chars">5</property>
|
||||
<layout>
|
||||
<property name="left-attach">2</property>
|
||||
<property name="top-attach">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Max Size</property>
|
||||
<layout>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="max_width">
|
||||
<property name="adjustment">max_width_adj</property>
|
||||
<property name="max-width-chars">5</property>
|
||||
<layout>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="max_height">
|
||||
<property name="adjustment">max_height_adj</property>
|
||||
<property name="max-width-chars">5</property>
|
||||
<layout>
|
||||
<property name="left-attach">2</property>
|
||||
<property name="top-attach">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Strength</property>
|
||||
<layout>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">4</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="strength">
|
||||
<layout>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">4</property>
|
||||
<property name="column-span">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button">
|
||||
<property name="label">Create</property>
|
||||
<signal name="clicked" handler="create_guide"/>
|
||||
<layout>
|
||||
<property name="left-attach">2</property>
|
||||
<property name="top-attach">5</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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 <mclasen@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <constraint-editor-application.h>
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
return g_application_run (G_APPLICATION (constraint_editor_application_new ()), argc, argv);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
constraint_editor_sources = [
|
||||
'main.c',
|
||||
'constraint-editor-application.c',
|
||||
'constraint-editor-window.c',
|
||||
'constraint-view.c',
|
||||
'constraint-editor.c',
|
||||
'guide-editor.c',
|
||||
'child-editor.c',
|
||||
'guide-placeholder.c',
|
||||
]
|
||||
|
||||
constraint_editor_resources = gnome.compile_resources('constraint_editor_resources',
|
||||
'constraint-editor.gresource.xml',
|
||||
source_dir: '.')
|
||||
|
||||
executable('gtk4-constraint-editor',
|
||||
constraint_editor_sources, constraint_editor_resources,
|
||||
dependencies: libgtk_dep,
|
||||
include_directories: confinc,
|
||||
gui_app: true,
|
||||
install: false)
|
||||
@@ -0,0 +1,289 @@
|
||||
/* Constraints/Simple
|
||||
*
|
||||
* GtkConstraintLayout provides a layout manager that uses relations
|
||||
* between widgets (also known as "constraints") to compute the position
|
||||
* and size of each child.
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_DECLARE_FINAL_TYPE (SimpleGrid, simple_grid, SIMPLE, GRID, GtkWidget)
|
||||
|
||||
struct _SimpleGrid
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GtkWidget *button1, *button2;
|
||||
GtkWidget *button3;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (SimpleGrid, simple_grid, GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
simple_grid_destroy (GtkWidget *widget)
|
||||
{
|
||||
SimpleGrid *self = SIMPLE_GRID (widget);
|
||||
|
||||
g_clear_pointer (&self->button1, gtk_widget_destroy);
|
||||
g_clear_pointer (&self->button2, gtk_widget_destroy);
|
||||
g_clear_pointer (&self->button3, gtk_widget_destroy);
|
||||
|
||||
GTK_WIDGET_CLASS (simple_grid_parent_class)->destroy (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
simple_grid_class_init (SimpleGridClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
widget_class->destroy = simple_grid_destroy;
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
|
||||
}
|
||||
|
||||
/* Layout:
|
||||
*
|
||||
* +-------------------------------------+
|
||||
* | +-----------++-------++-----------+ |
|
||||
* | | Child 1 || Space || Child 2 | |
|
||||
* | +-----------++-------++-----------+ |
|
||||
* | +---------------------------------+ |
|
||||
* | | Child 3 | |
|
||||
* | +---------------------------------+ |
|
||||
* +-------------------------------------+
|
||||
*
|
||||
* Constraints:
|
||||
*
|
||||
* super.start = child1.start - 8
|
||||
* child1.width = child2.width
|
||||
* child1.end = space.start
|
||||
* space.end = child2.start
|
||||
* child2.end = super.end - 8
|
||||
* super.start = child3.start - 8
|
||||
* child3.end = super.end - 8
|
||||
* super.top = child1.top - 8
|
||||
* super.top = child2.top - 8
|
||||
* child1.bottom = child3.top - 12
|
||||
* child2.bottom = child3.top - 12
|
||||
* child3.height = child1.height
|
||||
* child3.height = child2.height
|
||||
* child3.bottom = super.bottom - 8
|
||||
*
|
||||
* To add some flexibility, we make the space
|
||||
* stretchable:
|
||||
*
|
||||
* space.width >= 10
|
||||
* space.width = 100
|
||||
* space.width <= 200
|
||||
*/
|
||||
static void
|
||||
build_constraints (SimpleGrid *self,
|
||||
GtkConstraintLayout *manager)
|
||||
{
|
||||
GtkConstraintGuide *guide;
|
||||
|
||||
guide = gtk_constraint_guide_new ();
|
||||
gtk_constraint_guide_set_name (guide, "space");
|
||||
gtk_constraint_guide_set_min_size (guide, 10, 10);
|
||||
gtk_constraint_guide_set_nat_size (guide, 100, 10);
|
||||
gtk_constraint_guide_set_max_size (guide, 200, 20);
|
||||
gtk_constraint_guide_set_strength (guide, GTK_CONSTRAINT_STRENGTH_STRONG);
|
||||
gtk_constraint_layout_add_guide (manager, guide);
|
||||
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new_constant (GTK_CONSTRAINT_TARGET (self->button1),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
|
||||
GTK_CONSTRAINT_RELATION_LE,
|
||||
200.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button1,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button1,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button2,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button1,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
guide,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (guide,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button2,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button2,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button3,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button3,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button1,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button2,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button1,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button3,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
1.0,
|
||||
-12.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button2,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button3,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
1.0,
|
||||
-12.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button3,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button1,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button3,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button2,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button3,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
}
|
||||
|
||||
static void
|
||||
simple_grid_init (SimpleGrid *self)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (self);
|
||||
|
||||
self->button1 = gtk_button_new_with_label ("Child 1");
|
||||
gtk_widget_set_parent (self->button1, widget);
|
||||
gtk_widget_set_name (self->button1, "button1");
|
||||
|
||||
self->button2 = gtk_button_new_with_label ("Child 2");
|
||||
gtk_widget_set_parent (self->button2, widget);
|
||||
gtk_widget_set_name (self->button2, "button2");
|
||||
|
||||
self->button3 = gtk_button_new_with_label ("Child 3");
|
||||
gtk_widget_set_parent (self->button3, widget);
|
||||
gtk_widget_set_name (self->button3, "button3");
|
||||
|
||||
GtkLayoutManager *manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
|
||||
build_constraints (self, GTK_CONSTRAINT_LAYOUT (manager));
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_constraints (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *header, *box, *grid, *button;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_title (GTK_HEADER_BAR (header), "Constraints");
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
||||
gtk_container_add (GTK_CONTAINER (window), box);
|
||||
|
||||
grid = g_object_new (simple_grid_get_type (), NULL);
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
gtk_widget_set_vexpand (grid, TRUE);
|
||||
gtk_container_add (GTK_CONTAINER (box), grid);
|
||||
|
||||
button = gtk_button_new_with_label ("Close");
|
||||
gtk_container_add (GTK_CONTAINER (box), button);
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
g_signal_connect_swapped (button, "clicked",
|
||||
G_CALLBACK (gtk_widget_destroy), window);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
/* Constraints/Interactive
|
||||
*
|
||||
* Demonstrate how constraints can be updates during
|
||||
* user interaction.
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_DECLARE_FINAL_TYPE (InteractiveGrid, interactive_grid, INTERACTIVE, GRID, GtkWidget)
|
||||
|
||||
struct _InteractiveGrid
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GtkWidget *button1, *button2;
|
||||
GtkWidget *button3;
|
||||
GtkConstraintGuide *guide;
|
||||
GtkConstraint *constraint;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (InteractiveGrid, interactive_grid, GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
interactive_grid_destroy (GtkWidget *widget)
|
||||
{
|
||||
InteractiveGrid *self = INTERACTIVE_GRID (widget);
|
||||
|
||||
g_clear_pointer (&self->button1, gtk_widget_destroy);
|
||||
g_clear_pointer (&self->button2, gtk_widget_destroy);
|
||||
g_clear_pointer (&self->button3, gtk_widget_destroy);
|
||||
|
||||
GTK_WIDGET_CLASS (interactive_grid_parent_class)->destroy (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
interactive_grid_class_init (InteractiveGridClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
widget_class->destroy = interactive_grid_destroy;
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
|
||||
}
|
||||
|
||||
static void
|
||||
build_constraints (InteractiveGrid *self,
|
||||
GtkConstraintLayout *manager)
|
||||
{
|
||||
self->guide = g_object_new (GTK_TYPE_CONSTRAINT_GUIDE, NULL);
|
||||
gtk_constraint_layout_add_guide (manager, self->guide);
|
||||
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new_constant (GTK_CONSTRAINT_TARGET (self->guide),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->button1),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button1),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->guide),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button2),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->guide),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button2),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->button3),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button3),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->guide),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->button1),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button2),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->button1),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button3),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->button2),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button3),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
}
|
||||
|
||||
static void
|
||||
drag_cb (GtkGestureDrag *drag,
|
||||
double offset_x,
|
||||
double offset_y,
|
||||
InteractiveGrid *self)
|
||||
{
|
||||
GtkConstraintLayout *layout = GTK_CONSTRAINT_LAYOUT (gtk_widget_get_layout_manager (GTK_WIDGET (self)));
|
||||
double x, y;
|
||||
|
||||
if (self->constraint)
|
||||
{
|
||||
gtk_constraint_layout_remove_constraint (layout, self->constraint);
|
||||
g_clear_object (&self->constraint);
|
||||
}
|
||||
|
||||
gtk_gesture_drag_get_start_point (drag, &x, &y);
|
||||
self->constraint = gtk_constraint_new_constant (GTK_CONSTRAINT_TARGET (self->guide),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_LEFT,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
x + offset_x,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
gtk_constraint_layout_add_constraint (layout, g_object_ref (self->constraint));
|
||||
gtk_widget_queue_allocate (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
static void
|
||||
interactive_grid_init (InteractiveGrid *self)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (self);
|
||||
GtkGesture *drag;
|
||||
|
||||
self->button1 = gtk_button_new_with_label ("Child 1");
|
||||
gtk_widget_set_parent (self->button1, widget);
|
||||
gtk_widget_set_name (self->button1, "button1");
|
||||
|
||||
self->button2 = gtk_button_new_with_label ("Child 2");
|
||||
gtk_widget_set_parent (self->button2, widget);
|
||||
gtk_widget_set_name (self->button2, "button2");
|
||||
|
||||
self->button3 = gtk_button_new_with_label ("Child 3");
|
||||
gtk_widget_set_parent (self->button3, widget);
|
||||
gtk_widget_set_name (self->button3, "button3");
|
||||
|
||||
GtkLayoutManager *manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
|
||||
build_constraints (self, GTK_CONSTRAINT_LAYOUT (manager));
|
||||
|
||||
drag = gtk_gesture_drag_new ();
|
||||
g_signal_connect (drag, "drag-update", G_CALLBACK (drag_cb), self);
|
||||
gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (drag));
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_constraints2 (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *header, *box, *grid, *button;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_title (GTK_HEADER_BAR (header), "Constraints");
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
||||
gtk_container_add (GTK_CONTAINER (window), box);
|
||||
|
||||
grid = g_object_new (interactive_grid_get_type (), NULL);
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
gtk_widget_set_vexpand (grid, TRUE);
|
||||
gtk_container_add (GTK_CONTAINER (box), grid);
|
||||
|
||||
button = gtk_button_new_with_label ("Close");
|
||||
gtk_container_add (GTK_CONTAINER (box), button);
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
g_signal_connect_swapped (button, "clicked",
|
||||
G_CALLBACK (gtk_widget_destroy), window);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/* Constraints/VFL
|
||||
*
|
||||
* GtkConstraintLayout allows defining constraints using a
|
||||
* compact syntax called Visual Format Language, or VFL.
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_DECLARE_FINAL_TYPE (VflGrid, vfl_grid, VFL, GRID, GtkWidget)
|
||||
|
||||
struct _VflGrid
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GtkWidget *button1, *button2;
|
||||
GtkWidget *button3;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (VflGrid, vfl_grid, GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
vfl_grid_destroy (GtkWidget *widget)
|
||||
{
|
||||
VflGrid *self = VFL_GRID (widget);
|
||||
|
||||
g_clear_pointer (&self->button1, gtk_widget_destroy);
|
||||
g_clear_pointer (&self->button2, gtk_widget_destroy);
|
||||
g_clear_pointer (&self->button3, gtk_widget_destroy);
|
||||
|
||||
GTK_WIDGET_CLASS (vfl_grid_parent_class)->destroy (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
vfl_grid_class_init (VflGridClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
widget_class->destroy = vfl_grid_destroy;
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
|
||||
}
|
||||
|
||||
/* Layout:
|
||||
*
|
||||
* +-----------------------------+
|
||||
* | +-----------+ +-----------+ |
|
||||
* | | Child 1 | | Child 2 | |
|
||||
* | +-----------+ +-----------+ |
|
||||
* | +-------------------------+ |
|
||||
* | | Child 3 | |
|
||||
* | +-------------------------+ |
|
||||
* +-----------------------------+
|
||||
*
|
||||
* Constraints:
|
||||
*
|
||||
* super.start = child1.start - 8
|
||||
* child1.width = child2.width
|
||||
* child1.end = child2.start - 12
|
||||
* child2.end = super.end - 8
|
||||
* super.start = child3.start - 8
|
||||
* child3.end = super.end - 8
|
||||
* super.top = child1.top - 8
|
||||
* super.top = child2.top - 8
|
||||
* child1.bottom = child3.top - 12
|
||||
* child2.bottom = child3.top - 12
|
||||
* child3.height = child1.height
|
||||
* child3.height = child2.height
|
||||
* child3.bottom = super.bottom - 8
|
||||
*
|
||||
* Visual format:
|
||||
*
|
||||
* H:|-8-[view1(==view2)-12-[view2]-8-|
|
||||
* H:|-8-[view3]-8-|
|
||||
* V:|-8-[view1]-12-[view3(==view1)]-8-|
|
||||
* V:|-8-[view2]-12-[view3(==view2)]-8-|
|
||||
*/
|
||||
static void
|
||||
build_constraints (VflGrid *self,
|
||||
GtkConstraintLayout *manager)
|
||||
{
|
||||
const char * const vfl[] = {
|
||||
"H:|-[button1(==button2)]-12-[button2]-|",
|
||||
"H:|-[button3]-|",
|
||||
"V:|-[button1]-12-[button3(==button1)]-|",
|
||||
"V:|-[button2]-12-[button3(==button2)]-|",
|
||||
};
|
||||
GError *error = NULL;
|
||||
|
||||
gtk_constraint_layout_add_constraints_from_description (manager, vfl, G_N_ELEMENTS (vfl),
|
||||
8, 8,
|
||||
&error,
|
||||
"button1", self->button1,
|
||||
"button2", self->button2,
|
||||
"button3", self->button3,
|
||||
NULL);
|
||||
if (error != NULL)
|
||||
{
|
||||
g_printerr ("VFL parsing error:\n%s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
vfl_grid_init (VflGrid *self)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (self);
|
||||
|
||||
self->button1 = gtk_button_new_with_label ("Child 1");
|
||||
gtk_widget_set_parent (self->button1, widget);
|
||||
gtk_widget_set_name (self->button1, "button1");
|
||||
|
||||
self->button2 = gtk_button_new_with_label ("Child 2");
|
||||
gtk_widget_set_parent (self->button2, widget);
|
||||
gtk_widget_set_name (self->button2, "button2");
|
||||
|
||||
self->button3 = gtk_button_new_with_label ("Child 3");
|
||||
gtk_widget_set_parent (self->button3, widget);
|
||||
gtk_widget_set_name (self->button3, "button3");
|
||||
|
||||
GtkLayoutManager *manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
|
||||
build_constraints (self, GTK_CONSTRAINT_LAYOUT (manager));
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_constraints3 (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *header, *box, *grid, *button;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_title (GTK_HEADER_BAR (header), "Constraints");
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
||||
gtk_container_add (GTK_CONTAINER (window), box);
|
||||
|
||||
grid = g_object_new (vfl_grid_get_type (), NULL);
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
gtk_widget_set_vexpand (grid, TRUE);
|
||||
gtk_container_add (GTK_CONTAINER (box), grid);
|
||||
|
||||
button = gtk_button_new_with_label ("Close");
|
||||
gtk_container_add (GTK_CONTAINER (box), button);
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
g_signal_connect_swapped (button, "clicked",
|
||||
G_CALLBACK (gtk_widget_destroy), window);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
||||
@@ -150,6 +150,9 @@
|
||||
<file>clipboard.c</file>
|
||||
<file>colorsel.c</file>
|
||||
<file>combobox.c</file>
|
||||
<file>constraints.c</file>
|
||||
<file>constraints2.c</file>
|
||||
<file>constraints3.c</file>
|
||||
<file>css_accordion.c</file>
|
||||
<file>css_basics.c</file>
|
||||
<file>css_blendmodes.c</file>
|
||||
|
||||
@@ -8,6 +8,9 @@ demos = files([
|
||||
'clipboard.c',
|
||||
'colorsel.c',
|
||||
'combobox.c',
|
||||
'constraints.c',
|
||||
'constraints2.c',
|
||||
'constraints3.c',
|
||||
'css_accordion.c',
|
||||
'css_basics.c',
|
||||
'css_blendmodes.c',
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
subdir('constraint-editor')
|
||||
subdir('gtk-demo')
|
||||
subdir('icon-browser')
|
||||
subdir('node-editor')
|
||||
|
||||
@@ -1707,7 +1707,7 @@ activate (GApplication *app)
|
||||
gtk_css_provider_load_from_resource (provider, "/org/gtk/WidgetFactory4/widget-factory.css");
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_USER);
|
||||
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
g_object_unref (provider);
|
||||
|
||||
builder = gtk_builder_new_from_resource ("/org/gtk/WidgetFactory4/widget-factory.ui");
|
||||
|
||||
@@ -99,7 +99,7 @@ if wayland_enabled
|
||||
src_dir += [ gdkwayland_inc ]
|
||||
endif
|
||||
|
||||
if get_option('documentation')
|
||||
if get_option('gtk_doc')
|
||||
configure_file(input: 'version.xml.in', output: 'version.xml', configuration: version_conf)
|
||||
|
||||
gnome.gtkdoc('gdk4',
|
||||
|
||||
@@ -34,7 +34,7 @@ private_headers = [
|
||||
images = [
|
||||
]
|
||||
|
||||
if get_option('documentation')
|
||||
if get_option('gtk_doc')
|
||||
configure_file(input: 'version.xml.in', output: 'version.xml', configuration: version_conf)
|
||||
|
||||
gnome.gtkdoc('gsk4',
|
||||
|
||||
@@ -355,8 +355,8 @@ How to compile GTK itself
|
||||
</group>
|
||||
<sbr/>
|
||||
<group>
|
||||
<arg choice="plain">-Ddocumentation=true</arg>
|
||||
<arg choice="plain">-Ddocumentation=false</arg>
|
||||
<arg choice="plain">-Dgtk_doc=true</arg>
|
||||
<arg choice="plain">-Dgtk_doc=false</arg>
|
||||
</group>
|
||||
<sbr/>
|
||||
<group>
|
||||
@@ -382,7 +382,7 @@ How to compile GTK itself
|
||||
</formalpara>
|
||||
|
||||
<formalpara>
|
||||
<title><systemitem>documentation</systemitem> and
|
||||
<title><systemitem>gtk_doc</systemitem> and
|
||||
<systemitem>man-pages</systemitem></title>
|
||||
|
||||
<para>
|
||||
@@ -394,7 +394,7 @@ How to compile GTK itself
|
||||
<application>gtk-doc</application> installed and
|
||||
are modifying GTK, you may want to enable
|
||||
<application>gtk-doc</application> support by passing
|
||||
in <systemitem>documentation</systemitem>.
|
||||
in <systemitem>gtk_doc</systemitem>.
|
||||
</para>
|
||||
<para>
|
||||
Additionally, some tools provided by GTK have their own
|
||||
|
||||
@@ -109,6 +109,9 @@
|
||||
<xi:include href="xml/gtkcustomlayout.xml" />
|
||||
<xi:include href="xml/gtkfixedlayout.xml" />
|
||||
<xi:include href="xml/gtkgridlayout.xml" />
|
||||
<xi:include href="xml/gtkconstraintlayout.xml" />
|
||||
<xi:include href="xml/gtkconstraint.xml" />
|
||||
<xi:include href="xml/gtkconstraintguide.xml" />
|
||||
</chapter>
|
||||
|
||||
<chapter id="DisplayWidgets">
|
||||
|
||||
@@ -7287,3 +7287,87 @@ gtk_grid_layout_get_type
|
||||
GTK_TYPE_GRID_LAYOUT_CHILD
|
||||
gtk_grid_layout_child_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkconstraint</FILE>
|
||||
GtkConstraint
|
||||
GtkConstraintTarget
|
||||
|
||||
gtk_constraint_new
|
||||
gtk_constraint_new_constant
|
||||
gtk_constraint_get_target
|
||||
GtkConstraintAttribute
|
||||
gtk_constraint_get_target_attribute
|
||||
GtkConstraintRelation
|
||||
gtk_constraint_get_relation
|
||||
gtk_constraint_get_source
|
||||
gtk_constraint_get_source_attribute
|
||||
gtk_constraint_get_multiplier
|
||||
gtk_constraint_get_constant
|
||||
GtkConstraintStrength
|
||||
gtk_constraint_get_strength
|
||||
gtk_constraint_is_required
|
||||
gtk_constraint_is_attached
|
||||
gtk_constraint_is_constant
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GTK_TYPE_CONSTRAINT
|
||||
gtk_constraint_get_type
|
||||
GTK_TYPE_CONSTRAINT_TARGET
|
||||
gtk_constraint_target_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkconstraintlayout</FILE>
|
||||
GtkConstraintLayout
|
||||
GtkConstraintLayoutChild
|
||||
GtkConstraintVflParserError
|
||||
|
||||
gtk_constraint_layout_new
|
||||
|
||||
<SUBSECTION Constraints>
|
||||
gtk_constraint_layout_add_constraint
|
||||
gtk_constraint_layout_remove_constraint
|
||||
gtk_constraint_layout_remove_all_constraints
|
||||
|
||||
<SUBSECTION Guides>
|
||||
gtk_constraint_layout_add_guide
|
||||
gtk_constraint_layout_remove_guide
|
||||
|
||||
<SUBSECTION VFL>
|
||||
gtk_constraint_layout_add_constraints_from_description
|
||||
gtk_constraint_layout_add_constraints_from_descriptionv
|
||||
|
||||
<SUBSECTION>
|
||||
gtk_constraint_layout_observe_constraints
|
||||
gtk_constraint_layout_observe_guides
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GTK_TYPE_CONSTRAINT_LAYOUT
|
||||
gtk_constraint_layout_get_type
|
||||
GTK_TYPE_CONSTRAINT_LAYOUT_CHILD
|
||||
gtk_constraint_layout_child_get_type
|
||||
GTK_CONSTRAINT_VFL_PARSER_ERROR
|
||||
gtk_constraint_vfl_parser_error_quark
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkconstraintguide</FILE>
|
||||
GtkConstraintGuide
|
||||
|
||||
gtk_constraint_guide_new
|
||||
gtk_constraint_guide_set_name
|
||||
gtk_constraint_guide_get_name
|
||||
gtk_constraint_guide_set_strength
|
||||
gtk_constraint_guide_get_strength
|
||||
gtk_constraint_guide_set_min_size
|
||||
gtk_constraint_guide_get_min_size
|
||||
gtk_constraint_guide_set_nat_size
|
||||
gtk_constraint_guide_get_nat_size
|
||||
gtk_constraint_guide_set_max_size
|
||||
gtk_constraint_guide_get_max_size
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GTK_TYPE_CONSTRAINT_GUIDE
|
||||
gtk_constraint_guide_get_tyoe
|
||||
</SECTION>
|
||||
|
||||
@@ -49,6 +49,10 @@ gtk_color_chooser_dialog_get_type
|
||||
gtk_color_chooser_widget_get_type
|
||||
gtk_combo_box_get_type
|
||||
gtk_combo_box_text_get_type
|
||||
gtk_constraint_get_type
|
||||
gtk_constraint_guide_get_type
|
||||
gtk_constraint_layout_get_type
|
||||
gtk_constraint_target_get_type
|
||||
gtk_container_get_type
|
||||
gtk_css_provider_get_type
|
||||
gtk_dialog_get_type
|
||||
|
||||
@@ -23,6 +23,13 @@ private_headers = [
|
||||
'gtkcolorswatchprivate.h',
|
||||
'gtkcomboboxprivate.h',
|
||||
'gtkcontainerprivate.h',
|
||||
'gtkconstraintexpressionprivate.h',
|
||||
'gtkconstraintguideprivate.h',
|
||||
'gtkconstraintlayoutprivate.h',
|
||||
'gtkconstraintprivate.h',
|
||||
'gtkconstraintsolverprivate.h',
|
||||
'gtkconstrainttypesprivate.h',
|
||||
'gtkconstraintvflparserprivate.h',
|
||||
'gtkcssanimatedstyleprivate.h',
|
||||
'gtkcssanimationprivate.h',
|
||||
'gtkcssarrayvalueprivate.h',
|
||||
@@ -394,7 +401,7 @@ else
|
||||
types_conf.set('DISABLE_ON_QUARTZ', '')
|
||||
endif
|
||||
|
||||
if get_option('documentation')
|
||||
if get_option('gtk_doc')
|
||||
configure_file(input: 'version.xml.in', output: 'version.xml', configuration: version_conf)
|
||||
configure_file(input: 'getting_started.xml.in', output: 'getting_started.xml', configuration: src_dir_conf)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
if get_option('documentation')
|
||||
if get_option('gtk_doc')
|
||||
glib_prefix = dependency('glib-2.0').get_pkgconfig_variable('prefix')
|
||||
glib_docpath = join_paths(glib_prefix, 'share', 'gtk-doc', 'html')
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
if x11_enabled and get_option('documentation')
|
||||
if x11_enabled and get_option('gtk_doc')
|
||||
doc_shooter_sources = [
|
||||
'shadow.c',
|
||||
'shooter.c',
|
||||
|
||||
@@ -808,7 +808,8 @@ upload_texture (GskGLRenderer *self,
|
||||
int texture_id;
|
||||
|
||||
if (texture->width <= 128 &&
|
||||
texture->height <= 128)
|
||||
texture->height <= 128 &&
|
||||
!GDK_IS_GL_TEXTURE (texture))
|
||||
{
|
||||
graphene_rect_t trect;
|
||||
|
||||
@@ -943,11 +944,9 @@ render_transform_node (GskGLRenderer *self,
|
||||
case GSK_TRANSFORM_CATEGORY_2D:
|
||||
default:
|
||||
{
|
||||
graphene_matrix_t mat;
|
||||
|
||||
if (node_supports_transform (child))
|
||||
{
|
||||
gsk_transform_to_matrix (node_transform, &mat);
|
||||
ops_push_modelview (builder, node_transform);
|
||||
gsk_gl_renderer_add_render_ops (self, child, builder);
|
||||
ops_pop_modelview (builder);
|
||||
@@ -972,7 +971,6 @@ render_transform_node (GskGLRenderer *self,
|
||||
®ion, &is_offscreen,
|
||||
RESET_CLIP | RESET_OPACITY);
|
||||
|
||||
gsk_transform_to_matrix (node_transform, &mat);
|
||||
ops_push_modelview (builder, node_transform);
|
||||
ops_set_texture (builder, region.texture_id);
|
||||
ops_set_program (builder, &self->blit_program);
|
||||
|
||||
@@ -339,9 +339,12 @@ ops_set_modelview_internal (RenderOpBuilder *builder,
|
||||
RenderOp op;
|
||||
graphene_matrix_t matrix;
|
||||
|
||||
#if 0
|
||||
XXX This is not possible if we want pop() to work.
|
||||
if (builder->current_program &&
|
||||
gsk_transform_equal (builder->current_program_state->modelview, transform))
|
||||
return;
|
||||
#endif
|
||||
|
||||
gsk_transform_to_matrix (transform, &matrix);
|
||||
|
||||
|
||||
+44
-4
@@ -1690,11 +1690,26 @@ gsk_transform_transform_bounds (GskTransform *self,
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_TRANSFORM_CATEGORY_2D_AFFINE:
|
||||
{
|
||||
float dx, dy, scale_x, scale_y;
|
||||
|
||||
gsk_transform_to_affine (self, &scale_x, &scale_y, &dx, &dy);
|
||||
|
||||
*out_rect = *rect;
|
||||
out_rect->origin.x *= scale_x;
|
||||
out_rect->origin.y *= scale_y;
|
||||
out_rect->size.width *= scale_x;
|
||||
out_rect->size.height *= scale_y;
|
||||
out_rect->origin.x += dx;
|
||||
out_rect->origin.y += dy;
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_TRANSFORM_CATEGORY_UNKNOWN:
|
||||
case GSK_TRANSFORM_CATEGORY_ANY:
|
||||
case GSK_TRANSFORM_CATEGORY_3D:
|
||||
case GSK_TRANSFORM_CATEGORY_2D:
|
||||
case GSK_TRANSFORM_CATEGORY_2D_AFFINE:
|
||||
default:
|
||||
{
|
||||
graphene_matrix_t mat;
|
||||
@@ -1886,18 +1901,43 @@ gsk_transform_parser_parse (GtkCssParser *parser,
|
||||
|
||||
transform = gsk_transform_translate_3d (transform, &GRAPHENE_POINT3D_INIT (0.f, 0.f, f[0]));
|
||||
}
|
||||
#if 0
|
||||
/* FIXME: add these */
|
||||
else if (gtk_css_token_is_function (token, "skew"))
|
||||
{
|
||||
graphene_matrix_t matrix;
|
||||
|
||||
if (!gtk_css_parser_consume_function (parser, 2, 2, gsk_transform_parse_float, f))
|
||||
goto fail;
|
||||
|
||||
f[0] = f[0] / 180.0 * G_PI;
|
||||
f[1] = f[1] / 180.0 * G_PI;
|
||||
|
||||
graphene_matrix_init_skew (&matrix, f[0], f[1]);
|
||||
transform = gsk_transform_matrix (transform, &matrix);
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "skewX"))
|
||||
{
|
||||
graphene_matrix_t matrix;
|
||||
|
||||
if (!gtk_css_parser_consume_function (parser, 1, 1, gsk_transform_parse_float, f))
|
||||
goto fail;
|
||||
|
||||
f[0] = f[0] / 180.0 * G_PI;
|
||||
|
||||
graphene_matrix_init_skew (&matrix, f[0], 0);
|
||||
transform = gsk_transform_matrix (transform, &matrix);
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "skewY"))
|
||||
{
|
||||
graphene_matrix_t matrix;
|
||||
|
||||
if (!gtk_css_parser_consume_function (parser, 1, 1, gsk_transform_parse_float, f))
|
||||
goto fail;
|
||||
|
||||
f[0] = f[0] / 180.0 * G_PI;
|
||||
|
||||
graphene_matrix_init_skew (&matrix, 0, f[0]);
|
||||
transform = gsk_transform_matrix (transform, &matrix);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
break;
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
#include <gtk/gtkcolorutils.h>
|
||||
#include <gtk/gtkcombobox.h>
|
||||
#include <gtk/gtkcomboboxtext.h>
|
||||
#include <gtk/gtkconstraintlayout.h>
|
||||
#include <gtk/gtkconstraint.h>
|
||||
#include <gtk/gtkcontainer.h>
|
||||
#include <gtk/gtkcssprovider.h>
|
||||
#include <gtk/gtkcustomlayout.h>
|
||||
|
||||
@@ -561,13 +561,6 @@ prop_actions_connect (GtkActionMuxer *muxer)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
prop_actions_disconnect (GtkActionMuxer *muxer)
|
||||
{
|
||||
if (muxer->widget)
|
||||
g_signal_handlers_disconnect_by_func (muxer->widget,
|
||||
prop_action_notify, muxer);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_action_muxer_query_action (GActionGroup *action_group,
|
||||
@@ -819,8 +812,6 @@ gtk_action_muxer_dispose (GObject *object)
|
||||
{
|
||||
GtkActionMuxer *muxer = GTK_ACTION_MUXER (object);
|
||||
|
||||
prop_actions_disconnect (muxer);
|
||||
|
||||
if (muxer->parent)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (muxer->parent, gtk_action_muxer_action_added_to_parent, muxer);
|
||||
|
||||
@@ -0,0 +1,614 @@
|
||||
/* gtkconstraint.c: Constraint between two widgets
|
||||
* Copyright 2019 GNOME Foundation
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author: Emmanuele Bassi
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:gtkconstraint
|
||||
* @Title: GtkConstraint
|
||||
* @Short_description: The description of a constraint
|
||||
*
|
||||
* #GtkConstraint describes a constraint between an attribute on a widget
|
||||
* and another attribute on another widget, expressed as a linear equation
|
||||
* like:
|
||||
*
|
||||
* |[
|
||||
* target.attr1 = source.attr2 × multiplier + constant
|
||||
* ]|
|
||||
*
|
||||
* Each #GtkConstraint is part of a system that will be solved by a
|
||||
* #GtkConstraintLayout in order to allocate and position each child widget.
|
||||
*
|
||||
* The source and target widgets, as well as their attributes, of a
|
||||
* #GtkConstraint instance are immutable after creation.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkconstraintprivate.h"
|
||||
#include "gtkconstraintsolverprivate.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtktypebuiltins.h"
|
||||
#include "gtkwidget.h"
|
||||
|
||||
enum {
|
||||
PROP_TARGET = 1,
|
||||
PROP_TARGET_ATTRIBUTE,
|
||||
PROP_RELATION,
|
||||
PROP_SOURCE,
|
||||
PROP_SOURCE_ATTRIBUTE,
|
||||
PROP_MULTIPLIER,
|
||||
PROP_CONSTANT,
|
||||
PROP_STRENGTH,
|
||||
|
||||
N_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[N_PROPERTIES];
|
||||
|
||||
G_DEFINE_TYPE (GtkConstraint, gtk_constraint, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gtk_constraint_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkConstraint *self = GTK_CONSTRAINT (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_TARGET:
|
||||
self->target = g_value_get_object (value);
|
||||
break;
|
||||
|
||||
case PROP_TARGET_ATTRIBUTE:
|
||||
self->target_attribute = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
case PROP_RELATION:
|
||||
self->relation = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
case PROP_SOURCE:
|
||||
self->source = g_value_get_object (value);
|
||||
break;
|
||||
|
||||
case PROP_SOURCE_ATTRIBUTE:
|
||||
self->source_attribute = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
case PROP_MULTIPLIER:
|
||||
self->multiplier = g_value_get_double (value);
|
||||
break;
|
||||
|
||||
case PROP_CONSTANT:
|
||||
self->constant = g_value_get_double (value);
|
||||
break;
|
||||
|
||||
case PROP_STRENGTH:
|
||||
self->strength = g_value_get_int (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_constraint_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkConstraint *self = GTK_CONSTRAINT (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_TARGET:
|
||||
g_value_set_object (value, self->target);
|
||||
break;
|
||||
|
||||
case PROP_TARGET_ATTRIBUTE:
|
||||
g_value_set_enum (value, self->target_attribute);
|
||||
break;
|
||||
|
||||
case PROP_RELATION:
|
||||
g_value_set_enum (value, self->relation);
|
||||
break;
|
||||
|
||||
case PROP_SOURCE:
|
||||
g_value_set_object (value, self->source);
|
||||
break;
|
||||
|
||||
case PROP_SOURCE_ATTRIBUTE:
|
||||
g_value_set_enum (value, self->source_attribute);
|
||||
break;
|
||||
|
||||
case PROP_MULTIPLIER:
|
||||
g_value_set_double (value, self->multiplier);
|
||||
break;
|
||||
|
||||
case PROP_CONSTANT:
|
||||
g_value_set_double (value, self->constant);
|
||||
break;
|
||||
|
||||
case PROP_STRENGTH:
|
||||
g_value_set_int (value, self->strength);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_constraint_finalize (GObject *gobject)
|
||||
{
|
||||
GtkConstraint *self = GTK_CONSTRAINT (gobject);
|
||||
|
||||
gtk_constraint_detach (self);
|
||||
|
||||
G_OBJECT_CLASS (gtk_constraint_parent_class)->finalize (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_constraint_class_init (GtkConstraintClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->set_property = gtk_constraint_set_property;
|
||||
gobject_class->get_property = gtk_constraint_get_property;
|
||||
gobject_class->finalize = gtk_constraint_finalize;
|
||||
|
||||
/**
|
||||
* GtkConstraint:target:
|
||||
*
|
||||
* The target of the constraint.
|
||||
*
|
||||
* The constraint will set the #GtkConstraint:target-attribute of the
|
||||
* target using the #GtkConstraint:source-attribute of the source
|
||||
* widget.
|
||||
*/
|
||||
obj_props[PROP_TARGET] =
|
||||
g_param_spec_object ("target",
|
||||
P_("Target"),
|
||||
P_("The target of the constraint"),
|
||||
GTK_TYPE_CONSTRAINT_TARGET,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
/**
|
||||
* GtkConstraint:target-attribute:
|
||||
*
|
||||
* The attribute of the #GtkConstraint:target set by the constraint.
|
||||
*/
|
||||
obj_props[PROP_TARGET_ATTRIBUTE] =
|
||||
g_param_spec_enum ("target-attribute",
|
||||
P_("Target Attribute"),
|
||||
P_("The attribute of the target set by the constraint"),
|
||||
GTK_TYPE_CONSTRAINT_ATTRIBUTE,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_NONE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
/**
|
||||
* GtkConstraint:relation:
|
||||
*
|
||||
* The order relation between the terms of the constraint.
|
||||
*/
|
||||
obj_props[PROP_RELATION] =
|
||||
g_param_spec_enum ("relation",
|
||||
P_("Relation"),
|
||||
P_("The relation between the source and target attributes"),
|
||||
GTK_TYPE_CONSTRAINT_RELATION,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
/**
|
||||
* GtkConstraint:source:
|
||||
*
|
||||
* The source of the constraint.
|
||||
*
|
||||
* The constraint will set the #GtkConstraint:target-attribute of the
|
||||
* target using the #GtkConstraint:source-attribute of the source.
|
||||
*/
|
||||
obj_props[PROP_SOURCE] =
|
||||
g_param_spec_object ("source",
|
||||
P_("Source"),
|
||||
P_("The source of the constraint"),
|
||||
GTK_TYPE_CONSTRAINT_TARGET,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
/**
|
||||
* GtkConstraint:source-attribute:
|
||||
*
|
||||
* The attribute of the #GtkConstraint:source read by the constraint.
|
||||
*/
|
||||
obj_props[PROP_SOURCE_ATTRIBUTE] =
|
||||
g_param_spec_enum ("source-attribute",
|
||||
P_("Source Attribute"),
|
||||
P_("The attribute of the source widget set by the constraint"),
|
||||
GTK_TYPE_CONSTRAINT_ATTRIBUTE,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_NONE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
/**
|
||||
* GtkConstraint:multiplier:
|
||||
*
|
||||
* The multiplication factor to be applied to the
|
||||
* #GtkConstraint:source-attribue.
|
||||
*/
|
||||
obj_props[PROP_MULTIPLIER] =
|
||||
g_param_spec_double ("multiplier",
|
||||
P_("Multiplier"),
|
||||
P_("The multiplication factor to be applied to the source attribute"),
|
||||
-G_MAXDOUBLE, G_MAXDOUBLE, 1.0,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
/**
|
||||
* GtkConstraint:constant:
|
||||
*
|
||||
* The constant value to be added to the #GtkConstraint:source-attribute.
|
||||
*/
|
||||
obj_props[PROP_CONSTANT] =
|
||||
g_param_spec_double ("constant",
|
||||
P_("Constant"),
|
||||
P_("The constant to be added to the source attribute"),
|
||||
-G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
/**
|
||||
* GtkConstraint:strength:
|
||||
*
|
||||
* The strength of the constraint.
|
||||
*
|
||||
* The strength can be expressed either using one of the symbolic values
|
||||
* of the #GtkConstraintStrength enumeration, or any positive integer
|
||||
* value.
|
||||
*/
|
||||
obj_props[PROP_STRENGTH] =
|
||||
g_param_spec_int ("strength",
|
||||
P_("Strength"),
|
||||
P_("The strength of the constraint"),
|
||||
0, GTK_CONSTRAINT_STRENGTH_REQUIRED,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPERTIES, obj_props);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_constraint_init (GtkConstraint *self)
|
||||
{
|
||||
self->multiplier = 1.0;
|
||||
self->constant = 0.0;
|
||||
|
||||
self->target_attribute = GTK_CONSTRAINT_ATTRIBUTE_NONE;
|
||||
self->source_attribute = GTK_CONSTRAINT_ATTRIBUTE_NONE;
|
||||
self->relation = GTK_CONSTRAINT_RELATION_EQ;
|
||||
self->strength = GTK_CONSTRAINT_STRENGTH_REQUIRED;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_new:
|
||||
* @target: (nullable) (type GtkConstraintTarget): a #GtkConstraintTarget
|
||||
* @target_attribute: the attribute of @target to be set
|
||||
* @relation: the relation equivalence between @target_attribute and @source_attribute
|
||||
* @source: (nullable) (type GtkConstraintTarget): a #GtkConstraintTarget
|
||||
* @source_attribute: the attribute of @source to be read
|
||||
* @multiplier: a multiplication factor to be applied to @source_attribute
|
||||
* @constant: a constant factor to be added to @source_attribute
|
||||
* @strength: the strength of the constraint
|
||||
*
|
||||
* Creates a new #GtkConstraint representing a relation between a layout
|
||||
* attribute on a source and a layout attribute on a target.
|
||||
*
|
||||
* Returns: the newly created #GtkConstraint
|
||||
*/
|
||||
GtkConstraint *
|
||||
gtk_constraint_new (gpointer target,
|
||||
GtkConstraintAttribute target_attribute,
|
||||
GtkConstraintRelation relation,
|
||||
gpointer source,
|
||||
GtkConstraintAttribute source_attribute,
|
||||
double multiplier,
|
||||
double constant,
|
||||
int strength)
|
||||
{
|
||||
g_return_val_if_fail (target == NULL || GTK_IS_CONSTRAINT_TARGET (target), NULL);
|
||||
g_return_val_if_fail (source == NULL || GTK_IS_CONSTRAINT_TARGET (source), NULL);
|
||||
|
||||
return g_object_new (GTK_TYPE_CONSTRAINT,
|
||||
"target", target,
|
||||
"target-attribute", target_attribute,
|
||||
"relation", relation,
|
||||
"source", source,
|
||||
"source-attribute", source_attribute,
|
||||
"multiplier", multiplier,
|
||||
"constant", constant,
|
||||
"strength", strength,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_new_constant:
|
||||
* @target: (nullable) (type GtkConstraintTarget): a #GtkConstraintTarget
|
||||
* @target_attribute: the attribute of @target to be set
|
||||
* @relation: the relation equivalence between @target_attribute and @constant
|
||||
* @constant: a constant factor to be set on @target_attribute
|
||||
* @strength: the strength of the constraint
|
||||
*
|
||||
* Creates a new #GtkConstraint representing a relation between a layout
|
||||
* attribute on a target and a constant value.
|
||||
*
|
||||
* Returns: the newly created #GtkConstraint
|
||||
*/
|
||||
GtkConstraint *
|
||||
gtk_constraint_new_constant (gpointer target,
|
||||
GtkConstraintAttribute target_attribute,
|
||||
GtkConstraintRelation relation,
|
||||
double constant,
|
||||
int strength)
|
||||
{
|
||||
g_return_val_if_fail (target == NULL || GTK_IS_CONSTRAINT_TARGET (target), NULL);
|
||||
|
||||
return g_object_new (GTK_TYPE_CONSTRAINT,
|
||||
"target", target,
|
||||
"target-attribute", target_attribute,
|
||||
"relation", relation,
|
||||
"source-attribute", GTK_CONSTRAINT_ATTRIBUTE_NONE,
|
||||
"constant", constant,
|
||||
"strength", strength,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_get_target:
|
||||
* @constraint: a #GtkConstraint
|
||||
*
|
||||
* Retrieves the #GtkConstraintTarget used as the target for @constraint.
|
||||
*
|
||||
* If the #GtkConstraint:target property is set to %NULL, the @constraint
|
||||
* will use the #GtkConstraintLayout's widget.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): a #GtkConstraintTarget
|
||||
*/
|
||||
GtkConstraintTarget *
|
||||
gtk_constraint_get_target (GtkConstraint *constraint)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CONSTRAINT (constraint), NULL);
|
||||
|
||||
return constraint->target;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_get_target_attribute:
|
||||
* @constraint: a #GtkConstraint
|
||||
*
|
||||
* Retrieves the attribute of the target to be set by the @constraint.
|
||||
*
|
||||
* Returns: the target's attribute
|
||||
*/
|
||||
GtkConstraintAttribute
|
||||
gtk_constraint_get_target_attribute (GtkConstraint *constraint)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CONSTRAINT (constraint), GTK_CONSTRAINT_ATTRIBUTE_NONE);
|
||||
|
||||
return constraint->target_attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_get_source:
|
||||
* @constraint: a #GtkConstraint
|
||||
*
|
||||
* Retrieves the #GtkConstraintTarget used as the source for @constraint.
|
||||
*
|
||||
* If the #GtkConstraint:source property is set to %NULL, the @constraint
|
||||
* will use the #GtkConstraintLayout's widget.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): a #GtkConstraintTarget
|
||||
*/
|
||||
GtkConstraintTarget *
|
||||
gtk_constraint_get_source (GtkConstraint *constraint)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CONSTRAINT (constraint), NULL);
|
||||
|
||||
return constraint->source;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_get_source_attribute:
|
||||
* @constraint: a #GtkConstraint
|
||||
*
|
||||
* Retrieves the attribute of the source to be read by the @constraint.
|
||||
*
|
||||
* Returns: the target's attribute
|
||||
*/
|
||||
GtkConstraintAttribute
|
||||
gtk_constraint_get_source_attribute (GtkConstraint *constraint)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CONSTRAINT (constraint), GTK_CONSTRAINT_ATTRIBUTE_NONE);
|
||||
|
||||
return constraint->source_attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_get_relation:
|
||||
* @constraint: a #GtkConstraint
|
||||
*
|
||||
* The order relation between the terms of the @constraint.
|
||||
*
|
||||
* Returns: a #GtkConstraintRelation value
|
||||
*/
|
||||
GtkConstraintRelation
|
||||
gtk_constraint_get_relation (GtkConstraint *constraint)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CONSTRAINT (constraint), GTK_CONSTRAINT_RELATION_EQ);
|
||||
|
||||
return constraint->relation;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_get_multiplier:
|
||||
* @constraint: a #GtkConstraint
|
||||
*
|
||||
* Retrieves the multiplication factor applied to the source
|
||||
* attribute's value.
|
||||
*
|
||||
* Returns: a multiplication factor
|
||||
*/
|
||||
double
|
||||
gtk_constraint_get_multiplier (GtkConstraint *constraint)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CONSTRAINT (constraint), 1.0);
|
||||
|
||||
return constraint->multiplier;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_get_constant:
|
||||
* @constraint: a #GtkConstraint
|
||||
*
|
||||
* Retrieves the constant factor added to the source attributes' value.
|
||||
*
|
||||
* Returns: a constant factor
|
||||
*/
|
||||
double
|
||||
gtk_constraint_get_constant (GtkConstraint *constraint)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CONSTRAINT (constraint), 0.0);
|
||||
|
||||
return constraint->constant;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_get_strength:
|
||||
* @constraint: a #GtkConstraint
|
||||
*
|
||||
* Retrieves the strength of the constraint.
|
||||
*
|
||||
* Returns: the strength of the constraint
|
||||
*/
|
||||
int
|
||||
gtk_constraint_get_strength (GtkConstraint *constraint)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CONSTRAINT (constraint), GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
|
||||
return constraint->strength;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_is_required:
|
||||
* @constraint: a #GtkConstraint
|
||||
*
|
||||
* Checks whether the @constraint is a required relation for solving the
|
||||
* constraint layout.
|
||||
*
|
||||
* Returns: %TRUE if the constraint is required
|
||||
*/
|
||||
gboolean
|
||||
gtk_constraint_is_required (GtkConstraint *constraint)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CONSTRAINT (constraint), FALSE);
|
||||
|
||||
return constraint->strength == GTK_CONSTRAINT_STRENGTH_REQUIRED;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_is_attached:
|
||||
* @constraint: a #GtkConstraint
|
||||
*
|
||||
* Checks whether the @constraint is attached to a #GtkConstraintLayout,
|
||||
* and it is contributing to the layout.
|
||||
*
|
||||
* Returns: %TRUE if the constraint is attached
|
||||
*/
|
||||
gboolean
|
||||
gtk_constraint_is_attached (GtkConstraint *constraint)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CONSTRAINT (constraint), FALSE);
|
||||
|
||||
return constraint->constraint_ref != NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_is_constant:
|
||||
* @constraint: a #GtkConstraint
|
||||
*
|
||||
* Checks whether the @constraint describes a relation between an attribute
|
||||
* on the #GtkConstraint:target-widget and a constant value.
|
||||
*
|
||||
* Returns: %TRUE if the constraint is a constant relation
|
||||
*/
|
||||
gboolean
|
||||
gtk_constraint_is_constant (GtkConstraint *constraint)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CONSTRAINT (constraint), FALSE);
|
||||
|
||||
return constraint->source == NULL &&
|
||||
constraint->source_attribute == GTK_CONSTRAINT_ATTRIBUTE_NONE;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_constraint_attach (GtkConstraint *constraint,
|
||||
GtkConstraintSolver *solver,
|
||||
GtkConstraintRef *ref)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_CONSTRAINT (constraint));
|
||||
g_return_if_fail (GTK_IS_CONSTRAINT_SOLVER (solver));
|
||||
g_return_if_fail (ref != NULL);
|
||||
|
||||
constraint->constraint_ref = ref;
|
||||
constraint->solver = solver;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_constraint_detach (GtkConstraint *constraint)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_CONSTRAINT (constraint));
|
||||
|
||||
if (constraint->constraint_ref == NULL)
|
||||
return;
|
||||
|
||||
gtk_constraint_solver_remove_constraint (constraint->solver, constraint->constraint_ref);
|
||||
constraint->constraint_ref = NULL;
|
||||
constraint->solver = NULL;
|
||||
}
|
||||
|
||||
typedef struct _GtkConstraintTargetInterface GtkConstraintTargetInterface;
|
||||
|
||||
struct _GtkConstraintTargetInterface
|
||||
{
|
||||
GTypeInterface g_iface;
|
||||
};
|
||||
|
||||
G_DEFINE_INTERFACE (GtkConstraintTarget, gtk_constraint_target, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gtk_constraint_target_default_init (GtkConstraintTargetInterface *iface)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/* gtkconstraint.h: Constraint between two widgets
|
||||
* Copyright 2019 GNOME Foundation
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author: Emmanuele Bassi
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtktypes.h>
|
||||
#include <gtk/gtkenums.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GtkConstraintTarget GtkConstraintTarget;
|
||||
|
||||
#define GTK_TYPE_CONSTRAINT_TARGET (gtk_constraint_target_get_type ())
|
||||
|
||||
/**
|
||||
* GtkConstraintTarget:
|
||||
*
|
||||
* The GtkConstraintTarget interface is implemented by objects that
|
||||
* can be used as source or target in #GtkConstraints. Besides
|
||||
* #GtkWidget, it is also implemented by #GtkConstraintGuide.
|
||||
*/
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_INTERFACE (GtkConstraintTarget, gtk_constraint_target, GTK, CONSTRAINT_TARGET, GObject)
|
||||
|
||||
#define GTK_TYPE_CONSTRAINT (gtk_constraint_get_type ())
|
||||
|
||||
/**
|
||||
* GtkConstraint:
|
||||
*
|
||||
* An object describing the relation between two widget attributes.
|
||||
*
|
||||
* All relations are in the form:
|
||||
*
|
||||
* |[<!-- language=plain -->
|
||||
* target.attr_name = source.attr_name × multiplier + constant
|
||||
* ]|
|
||||
*
|
||||
* A #GtkConstraint is immutable once it's created.
|
||||
*/
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (GtkConstraint, gtk_constraint, GTK, CONSTRAINT, GObject)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkConstraint * gtk_constraint_new (gpointer target,
|
||||
GtkConstraintAttribute target_attribute,
|
||||
GtkConstraintRelation relation,
|
||||
gpointer source,
|
||||
GtkConstraintAttribute source_attribute,
|
||||
double multiplier,
|
||||
double constant,
|
||||
int strength);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkConstraint * gtk_constraint_new_constant (gpointer target,
|
||||
GtkConstraintAttribute target_attribute,
|
||||
GtkConstraintRelation relation,
|
||||
double constant,
|
||||
int strength);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkConstraintTarget * gtk_constraint_get_target (GtkConstraint *constraint);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkConstraintAttribute gtk_constraint_get_target_attribute (GtkConstraint *constraint);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkConstraintTarget * gtk_constraint_get_source (GtkConstraint *constraint);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkConstraintAttribute gtk_constraint_get_source_attribute (GtkConstraint *constraint);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkConstraintRelation gtk_constraint_get_relation (GtkConstraint *constraint);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
double gtk_constraint_get_multiplier (GtkConstraint *constraint);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
double gtk_constraint_get_constant (GtkConstraint *constraint);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
int gtk_constraint_get_strength (GtkConstraint *constraint);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_constraint_is_required (GtkConstraint *constraint);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_constraint_is_attached (GtkConstraint *constraint);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_constraint_is_constant (GtkConstraint *constraint);
|
||||
|
||||
G_END_DECLS
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,279 @@
|
||||
/* gtkconstraintequationprivate.h: Constraint expressions and variables
|
||||
* Copyright 2019 GNOME Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author: Emmanuele Bassi
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gtkconstrainttypesprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GtkConstraintVariable *
|
||||
gtk_constraint_variable_new (const char *prefix,
|
||||
const char *name);
|
||||
|
||||
GtkConstraintVariable *
|
||||
gtk_constraint_variable_new_dummy (const char *name);
|
||||
|
||||
GtkConstraintVariable *
|
||||
gtk_constraint_variable_new_objective (const char *name);
|
||||
|
||||
GtkConstraintVariable *
|
||||
gtk_constraint_variable_new_slack (const char *name);
|
||||
|
||||
GtkConstraintVariable *
|
||||
gtk_constraint_variable_ref (GtkConstraintVariable *variable);
|
||||
|
||||
void
|
||||
gtk_constraint_variable_unref (GtkConstraintVariable *variable);
|
||||
|
||||
void
|
||||
gtk_constraint_variable_set_value (GtkConstraintVariable *variable,
|
||||
double value);
|
||||
|
||||
double
|
||||
gtk_constraint_variable_get_value (const GtkConstraintVariable *variable);
|
||||
|
||||
char *
|
||||
gtk_constraint_variable_to_string (const GtkConstraintVariable *variable);
|
||||
|
||||
gboolean
|
||||
gtk_constraint_variable_is_external (const GtkConstraintVariable *variable);
|
||||
|
||||
gboolean
|
||||
gtk_constraint_variable_is_pivotable (const GtkConstraintVariable *variable);
|
||||
|
||||
gboolean
|
||||
gtk_constraint_variable_is_restricted (const GtkConstraintVariable *variable);
|
||||
|
||||
gboolean
|
||||
gtk_constraint_variable_is_dummy (const GtkConstraintVariable *variable);
|
||||
|
||||
typedef struct {
|
||||
GtkConstraintVariable *first;
|
||||
GtkConstraintVariable *second;
|
||||
} GtkConstraintVariablePair;
|
||||
|
||||
GtkConstraintVariablePair *
|
||||
gtk_constraint_variable_pair_new (GtkConstraintVariable *first,
|
||||
GtkConstraintVariable *second);
|
||||
|
||||
void
|
||||
gtk_constraint_variable_pair_free (GtkConstraintVariablePair *pair);
|
||||
|
||||
typedef struct _GtkConstraintVariableSet GtkConstraintVariableSet;
|
||||
|
||||
GtkConstraintVariableSet *
|
||||
gtk_constraint_variable_set_new (void);
|
||||
|
||||
void
|
||||
gtk_constraint_variable_set_free (GtkConstraintVariableSet *set);
|
||||
|
||||
gboolean
|
||||
gtk_constraint_variable_set_add (GtkConstraintVariableSet *set,
|
||||
GtkConstraintVariable *variable);
|
||||
|
||||
gboolean
|
||||
gtk_constraint_variable_set_remove (GtkConstraintVariableSet *set,
|
||||
GtkConstraintVariable *variable);
|
||||
|
||||
gboolean
|
||||
gtk_constraint_variable_set_is_empty (GtkConstraintVariableSet *set);
|
||||
|
||||
gboolean
|
||||
gtk_constraint_variable_set_is_singleton (GtkConstraintVariableSet *set);
|
||||
|
||||
int
|
||||
gtk_constraint_variable_set_size (GtkConstraintVariableSet *set);
|
||||
|
||||
typedef struct {
|
||||
/*< private >*/
|
||||
gpointer dummy1;
|
||||
gpointer dummy2;
|
||||
gint64 dummy3;
|
||||
} GtkConstraintVariableSetIter;
|
||||
|
||||
void
|
||||
gtk_constraint_variable_set_iter_init (GtkConstraintVariableSetIter *iter,
|
||||
GtkConstraintVariableSet *set);
|
||||
|
||||
gboolean
|
||||
gtk_constraint_variable_set_iter_next (GtkConstraintVariableSetIter *iter,
|
||||
GtkConstraintVariable **variable_p);
|
||||
|
||||
GtkConstraintExpression *
|
||||
gtk_constraint_expression_new (double constant);
|
||||
|
||||
GtkConstraintExpression *
|
||||
gtk_constraint_expression_new_from_variable (GtkConstraintVariable *variable);
|
||||
|
||||
GtkConstraintExpression *
|
||||
gtk_constraint_expression_ref (GtkConstraintExpression *expression);
|
||||
|
||||
void
|
||||
gtk_constraint_expression_unref (GtkConstraintExpression *expression);
|
||||
|
||||
GtkConstraintExpression *
|
||||
gtk_constraint_expression_clone (GtkConstraintExpression *expression);
|
||||
|
||||
void
|
||||
gtk_constraint_expression_set_constant (GtkConstraintExpression *expression,
|
||||
double constant);
|
||||
double
|
||||
gtk_constraint_expression_get_constant (const GtkConstraintExpression *expression);
|
||||
|
||||
gboolean
|
||||
gtk_constraint_expression_is_constant (const GtkConstraintExpression *expression);
|
||||
|
||||
void
|
||||
gtk_constraint_expression_add_expression (GtkConstraintExpression *a_expr,
|
||||
GtkConstraintExpression *b_expr,
|
||||
double n,
|
||||
GtkConstraintVariable *subject,
|
||||
GtkConstraintSolver *solver);
|
||||
|
||||
void
|
||||
gtk_constraint_expression_add_variable (GtkConstraintExpression *expression,
|
||||
GtkConstraintVariable *variable,
|
||||
double coefficient,
|
||||
GtkConstraintVariable *subject,
|
||||
GtkConstraintSolver *solver);
|
||||
|
||||
void
|
||||
gtk_constraint_expression_remove_variable (GtkConstraintExpression *expression,
|
||||
GtkConstraintVariable *variable);
|
||||
|
||||
void
|
||||
gtk_constraint_expression_set_variable (GtkConstraintExpression *expression,
|
||||
GtkConstraintVariable *variable,
|
||||
double coefficient);
|
||||
|
||||
double
|
||||
gtk_constraint_expression_get_coefficient (GtkConstraintExpression *expression,
|
||||
GtkConstraintVariable *variable);
|
||||
|
||||
char *
|
||||
gtk_constraint_expression_to_string (const GtkConstraintExpression *expression);
|
||||
|
||||
double
|
||||
gtk_constraint_expression_new_subject (GtkConstraintExpression *expression,
|
||||
GtkConstraintVariable *subject);
|
||||
|
||||
void
|
||||
gtk_constraint_expression_change_subject (GtkConstraintExpression *expression,
|
||||
GtkConstraintVariable *old_subject,
|
||||
GtkConstraintVariable *new_subject);
|
||||
|
||||
void
|
||||
gtk_constraint_expression_substitute_out (GtkConstraintExpression *expression,
|
||||
GtkConstraintVariable *out_var,
|
||||
GtkConstraintExpression *expr,
|
||||
GtkConstraintVariable *subject,
|
||||
GtkConstraintSolver *solver);
|
||||
|
||||
GtkConstraintVariable *
|
||||
gtk_constraint_expression_get_pivotable_variable (GtkConstraintExpression *expression);
|
||||
|
||||
GtkConstraintExpression *
|
||||
gtk_constraint_expression_plus_constant (GtkConstraintExpression *expression,
|
||||
double constant);
|
||||
|
||||
GtkConstraintExpression *
|
||||
gtk_constraint_expression_minus_constant (GtkConstraintExpression *expression,
|
||||
double constant);
|
||||
|
||||
GtkConstraintExpression *
|
||||
gtk_constraint_expression_plus_variable (GtkConstraintExpression *expression,
|
||||
GtkConstraintVariable *variable);
|
||||
|
||||
GtkConstraintExpression *
|
||||
gtk_constraint_expression_minus_variable (GtkConstraintExpression *expression,
|
||||
GtkConstraintVariable *variable);
|
||||
|
||||
GtkConstraintExpression *
|
||||
gtk_constraint_expression_multiply_by (GtkConstraintExpression *expression,
|
||||
double factor);
|
||||
|
||||
GtkConstraintExpression *
|
||||
gtk_constraint_expression_divide_by (GtkConstraintExpression *expression,
|
||||
double factor);
|
||||
|
||||
struct _GtkConstraintExpressionBuilder
|
||||
{
|
||||
/*< private >*/
|
||||
gpointer dummy1;
|
||||
gpointer dummy2;
|
||||
int dummy3;
|
||||
};
|
||||
|
||||
void
|
||||
gtk_constraint_expression_builder_init (GtkConstraintExpressionBuilder *builder,
|
||||
GtkConstraintSolver *solver);
|
||||
|
||||
void
|
||||
gtk_constraint_expression_builder_term (GtkConstraintExpressionBuilder *builder,
|
||||
GtkConstraintVariable *term);
|
||||
|
||||
void
|
||||
gtk_constraint_expression_builder_plus (GtkConstraintExpressionBuilder *builder);
|
||||
|
||||
void
|
||||
gtk_constraint_expression_builder_minus (GtkConstraintExpressionBuilder *builder);
|
||||
|
||||
void
|
||||
gtk_constraint_expression_builder_divide_by (GtkConstraintExpressionBuilder *builder);
|
||||
|
||||
void
|
||||
gtk_constraint_expression_builder_multiply_by (GtkConstraintExpressionBuilder *builder);
|
||||
|
||||
void
|
||||
gtk_constraint_expression_builder_constant (GtkConstraintExpressionBuilder *builder,
|
||||
double value);
|
||||
|
||||
GtkConstraintExpression *
|
||||
gtk_constraint_expression_builder_finish (GtkConstraintExpressionBuilder *builder) G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
/*< private >
|
||||
* GtkConstraintExpressionIter:
|
||||
*
|
||||
* An iterator object for terms inside a #GtkConstraintExpression.
|
||||
*/
|
||||
typedef struct {
|
||||
/*< private >*/
|
||||
gpointer dummy1;
|
||||
gpointer dummy2;
|
||||
gint64 dummy3;
|
||||
} GtkConstraintExpressionIter;
|
||||
|
||||
void
|
||||
gtk_constraint_expression_iter_init (GtkConstraintExpressionIter *iter,
|
||||
GtkConstraintExpression *equation);
|
||||
|
||||
gboolean
|
||||
gtk_constraint_expression_iter_next (GtkConstraintExpressionIter *iter,
|
||||
GtkConstraintVariable **variable,
|
||||
double *coefficient);
|
||||
|
||||
gboolean
|
||||
gtk_constraint_expression_iter_prev (GtkConstraintExpressionIter *iter,
|
||||
GtkConstraintVariable **variable,
|
||||
double *coefficient);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -0,0 +1,694 @@
|
||||
/* gtkconstraintguide.c: Flexible space for constraints
|
||||
* 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/>.
|
||||
*
|
||||
* Author: Matthias Clasen
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:gtkconstraintguide
|
||||
* @Title: GtkConstraintGuide
|
||||
* @Short_description: An invisible constraint target
|
||||
*
|
||||
* A #GtkConstraintGuide is an invisible layout element that can be
|
||||
* used by widgets inside a #GtkConstraintLayout as a source or a target
|
||||
* of a #GtkConstraint. Guides can be used like guidelines or as
|
||||
* flexible space.
|
||||
*
|
||||
* Unlike a #GtkWidget, a #GtkConstraintGuide will not be drawn.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkconstraintguide.h"
|
||||
|
||||
#include "gtkconstraintguideprivate.h"
|
||||
#include "gtkconstraintlayoutprivate.h"
|
||||
#include "gtkconstraintexpressionprivate.h"
|
||||
#include "gtkconstraintsolverprivate.h"
|
||||
|
||||
#include "gtkdebug.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtkprivate.h"
|
||||
|
||||
|
||||
typedef enum {
|
||||
MIN_WIDTH,
|
||||
MIN_HEIGHT,
|
||||
NAT_WIDTH,
|
||||
NAT_HEIGHT,
|
||||
MAX_WIDTH,
|
||||
MAX_HEIGHT,
|
||||
LAST_VALUE
|
||||
} GuideValue;
|
||||
|
||||
struct _GtkConstraintGuide
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
char *name;
|
||||
|
||||
int strength;
|
||||
|
||||
int values[LAST_VALUE];
|
||||
|
||||
GtkConstraintLayout *layout;
|
||||
|
||||
/* HashTable<static string, Variable>; a hash table of variables,
|
||||
* one for each attribute; we use these to query and suggest the
|
||||
* values for the solver. The string is static and does not need
|
||||
* to be freed.
|
||||
*/
|
||||
GHashTable *bound_attributes;
|
||||
|
||||
GtkConstraintRef *constraints[LAST_VALUE];
|
||||
};
|
||||
|
||||
|
||||
struct _GtkConstraintGuideClass {
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_MIN_WIDTH = 1,
|
||||
PROP_MIN_HEIGHT,
|
||||
PROP_NAT_WIDTH,
|
||||
PROP_NAT_HEIGHT,
|
||||
PROP_MAX_WIDTH,
|
||||
PROP_MAX_HEIGHT,
|
||||
PROP_STRENGTH,
|
||||
PROP_NAME,
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
static GParamSpec *guide_props[LAST_PROP];
|
||||
|
||||
static void
|
||||
gtk_constraint_guide_constraint_target_iface_init (GtkConstraintTargetInterface *iface)
|
||||
{
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkConstraintGuide, gtk_constraint_guide, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_CONSTRAINT_TARGET,
|
||||
gtk_constraint_guide_constraint_target_iface_init))
|
||||
|
||||
static void
|
||||
gtk_constraint_guide_init (GtkConstraintGuide *guide)
|
||||
{
|
||||
guide->strength = GTK_CONSTRAINT_STRENGTH_MEDIUM;
|
||||
|
||||
guide->values[MIN_WIDTH] = 0;
|
||||
guide->values[MIN_HEIGHT] = 0;
|
||||
guide->values[NAT_WIDTH] = 0;
|
||||
guide->values[NAT_HEIGHT] = 0;
|
||||
guide->values[MAX_WIDTH] = G_MAXINT;
|
||||
guide->values[MAX_HEIGHT] = G_MAXINT;
|
||||
|
||||
guide->bound_attributes =
|
||||
g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
NULL,
|
||||
(GDestroyNotify) gtk_constraint_variable_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_constraint_guide_update_constraint (GtkConstraintGuide *guide,
|
||||
GuideValue index)
|
||||
{
|
||||
GtkConstraintSolver *solver;
|
||||
GtkConstraintVariable *var;
|
||||
|
||||
if (!guide->layout)
|
||||
return;
|
||||
|
||||
solver = gtk_constraint_layout_get_solver (guide->layout);
|
||||
if (!solver)
|
||||
return;
|
||||
|
||||
if (guide->constraints[index] != NULL)
|
||||
{
|
||||
gtk_constraint_solver_remove_constraint (solver, guide->constraints[index]);
|
||||
guide->constraints[index] = NULL;
|
||||
}
|
||||
|
||||
if (index == MIN_WIDTH || index == NAT_WIDTH || index == MAX_WIDTH)
|
||||
var = gtk_constraint_layout_get_attribute (guide->layout, GTK_CONSTRAINT_ATTRIBUTE_WIDTH, "guide", NULL, guide->bound_attributes);
|
||||
else
|
||||
var = gtk_constraint_layout_get_attribute (guide->layout, GTK_CONSTRAINT_ATTRIBUTE_HEIGHT, "guide", NULL, guide->bound_attributes);
|
||||
|
||||
/* We always install min-size constraints,
|
||||
* but we avoid nat-size constraints if min == max
|
||||
* and we avoid max-size constraints if max == G_MAXINT
|
||||
*/
|
||||
if (index == MIN_WIDTH || index == MIN_HEIGHT)
|
||||
{
|
||||
guide->constraints[index] =
|
||||
gtk_constraint_solver_add_constraint (solver,
|
||||
var,
|
||||
GTK_CONSTRAINT_RELATION_GE,
|
||||
gtk_constraint_expression_new (guide->values[index]),
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
}
|
||||
else if ((index == NAT_WIDTH && guide->values[MIN_WIDTH] != guide->values[MAX_WIDTH]) ||
|
||||
(index == NAT_HEIGHT && guide->values[MIN_HEIGHT] != guide->values[MAX_HEIGHT]))
|
||||
{
|
||||
gtk_constraint_variable_set_value (var, guide->values[index]);
|
||||
guide->constraints[index] =
|
||||
gtk_constraint_solver_add_stay_variable (solver,
|
||||
var,
|
||||
guide->strength);
|
||||
}
|
||||
else if ((index == MAX_WIDTH || index == MAX_HEIGHT) &&
|
||||
guide->values[index] < G_MAXINT)
|
||||
{
|
||||
guide->constraints[index] =
|
||||
gtk_constraint_solver_add_constraint (solver,
|
||||
var,
|
||||
GTK_CONSTRAINT_RELATION_LE,
|
||||
gtk_constraint_expression_new (guide->values[index]),
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
}
|
||||
|
||||
gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (guide->layout));
|
||||
}
|
||||
|
||||
void
|
||||
gtk_constraint_guide_update (GtkConstraintGuide *guide)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < LAST_VALUE; i++)
|
||||
gtk_constraint_guide_update_constraint (guide, i);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_constraint_guide_detach (GtkConstraintGuide *guide)
|
||||
{
|
||||
GtkConstraintSolver *solver;
|
||||
int i;
|
||||
|
||||
if (!guide->layout)
|
||||
return;
|
||||
|
||||
solver = gtk_constraint_layout_get_solver (guide->layout);
|
||||
if (!solver)
|
||||
return;
|
||||
|
||||
for (i = 0; i < LAST_VALUE; i++)
|
||||
{
|
||||
if (guide->constraints[i])
|
||||
{
|
||||
gtk_constraint_solver_remove_constraint (solver, guide->constraints[i]);
|
||||
guide->constraints[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
g_hash_table_remove_all (guide->bound_attributes);
|
||||
}
|
||||
|
||||
GtkConstraintVariable *
|
||||
gtk_constraint_guide_get_attribute (GtkConstraintGuide *guide,
|
||||
GtkConstraintAttribute attr)
|
||||
{
|
||||
GtkLayoutManager *manager = GTK_LAYOUT_MANAGER (guide->layout);
|
||||
GtkWidget *widget = gtk_layout_manager_get_widget (manager);
|
||||
|
||||
return gtk_constraint_layout_get_attribute (guide->layout, attr, "guide", widget, guide->bound_attributes);
|
||||
}
|
||||
|
||||
GtkConstraintLayout *
|
||||
gtk_constraint_guide_get_layout (GtkConstraintGuide *guide)
|
||||
{
|
||||
return guide->layout;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_constraint_guide_set_layout (GtkConstraintGuide *guide,
|
||||
GtkConstraintLayout *layout)
|
||||
{
|
||||
guide->layout = layout;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_constraint_guide_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkConstraintGuide *self = GTK_CONSTRAINT_GUIDE (gobject);
|
||||
int val;
|
||||
GuideValue index;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_MIN_WIDTH:
|
||||
case PROP_MIN_HEIGHT:
|
||||
case PROP_NAT_WIDTH:
|
||||
case PROP_NAT_HEIGHT:
|
||||
case PROP_MAX_WIDTH:
|
||||
case PROP_MAX_HEIGHT:
|
||||
val = g_value_get_int (value);
|
||||
index = prop_id - 1;
|
||||
if (self->values[index] != val)
|
||||
{
|
||||
self->values[index] = val;
|
||||
g_object_notify_by_pspec (gobject, pspec);
|
||||
|
||||
gtk_constraint_guide_update_constraint (self, index);
|
||||
if (index == MIN_WIDTH || index == MAX_WIDTH)
|
||||
gtk_constraint_guide_update_constraint (self, NAT_WIDTH);
|
||||
if (index == MIN_HEIGHT || index == MAX_HEIGHT)
|
||||
gtk_constraint_guide_update_constraint (self, NAT_HEIGHT);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_STRENGTH:
|
||||
gtk_constraint_guide_set_strength (self, g_value_get_enum (value));
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
gtk_constraint_guide_set_name (self, g_value_get_string (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_constraint_guide_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkConstraintGuide *self = GTK_CONSTRAINT_GUIDE (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_MIN_WIDTH:
|
||||
case PROP_MIN_HEIGHT:
|
||||
case PROP_NAT_WIDTH:
|
||||
case PROP_NAT_HEIGHT:
|
||||
case PROP_MAX_WIDTH:
|
||||
case PROP_MAX_HEIGHT:
|
||||
g_value_set_int (value, self->values[prop_id - 1]);
|
||||
break;
|
||||
|
||||
case PROP_STRENGTH:
|
||||
g_value_set_enum (value, self->strength);
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, self->name);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_constraint_guide_finalize (GObject *object)
|
||||
{
|
||||
GtkConstraintGuide *self = GTK_CONSTRAINT_GUIDE (object);
|
||||
|
||||
g_free (self->name);
|
||||
|
||||
g_clear_pointer (&self->bound_attributes, g_hash_table_unref);
|
||||
|
||||
G_OBJECT_CLASS (gtk_constraint_guide_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_constraint_guide_class_init (GtkConstraintGuideClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
object_class->finalize = gtk_constraint_guide_finalize;
|
||||
object_class->set_property = gtk_constraint_guide_set_property;
|
||||
object_class->get_property = gtk_constraint_guide_get_property;
|
||||
|
||||
/**
|
||||
* GtkConstraintGuide:min-width:
|
||||
*
|
||||
* The minimum width of the guide.
|
||||
*/
|
||||
guide_props[PROP_MIN_WIDTH] =
|
||||
g_param_spec_int ("min-width",
|
||||
"Minimum width",
|
||||
"Minimum width",
|
||||
0, G_MAXINT, 0,
|
||||
G_PARAM_READWRITE|
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
/**
|
||||
* GtkConstraintGuide:min-height:
|
||||
*
|
||||
* The minimum height of the guide.
|
||||
*/
|
||||
guide_props[PROP_MIN_HEIGHT] =
|
||||
g_param_spec_int ("min-height",
|
||||
"Minimum height",
|
||||
"Minimum height",
|
||||
0, G_MAXINT, 0,
|
||||
G_PARAM_READWRITE|
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
/**
|
||||
* GtkConstraintGuide:nat-width:
|
||||
*
|
||||
* The preferred, or natural, width of the guide.
|
||||
*/
|
||||
guide_props[PROP_NAT_WIDTH] =
|
||||
g_param_spec_int ("nat-width",
|
||||
"Natural width",
|
||||
"Natural width",
|
||||
0, G_MAXINT, 0,
|
||||
G_PARAM_READWRITE|
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
/**
|
||||
* GtkConstraintGuide:nat-height:
|
||||
*
|
||||
* The preferred, or natural, height of the guide.
|
||||
*/
|
||||
guide_props[PROP_NAT_HEIGHT] =
|
||||
g_param_spec_int ("nat-height",
|
||||
"Natural height",
|
||||
"Natural height",
|
||||
0, G_MAXINT, 0,
|
||||
G_PARAM_READWRITE|
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
/**
|
||||
* GtkConstraintGuide:max-width:
|
||||
*
|
||||
* The maximum width of the guide.
|
||||
*/
|
||||
guide_props[PROP_MAX_WIDTH] =
|
||||
g_param_spec_int ("max-width",
|
||||
"Maximum width",
|
||||
"Maximum width",
|
||||
0, G_MAXINT, G_MAXINT,
|
||||
G_PARAM_READWRITE|
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
/**
|
||||
* GtkConstraintGuide:max-height:
|
||||
*
|
||||
* The maximum height of the guide.
|
||||
*/
|
||||
guide_props[PROP_MAX_HEIGHT] =
|
||||
g_param_spec_int ("max-height",
|
||||
"Maximum height",
|
||||
"Maximum height",
|
||||
0, G_MAXINT, G_MAXINT,
|
||||
G_PARAM_READWRITE|
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
/**
|
||||
* GtkConstraintGuide:strength:
|
||||
*
|
||||
* The #GtkConstraintStrength to be used for the constraint on
|
||||
* the natural size of the guide.
|
||||
*/
|
||||
guide_props[PROP_STRENGTH] =
|
||||
g_param_spec_enum ("strength",
|
||||
"Strength",
|
||||
"The strength to use for natural size",
|
||||
GTK_TYPE_CONSTRAINT_STRENGTH,
|
||||
GTK_CONSTRAINT_STRENGTH_MEDIUM,
|
||||
G_PARAM_READWRITE|
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
/**
|
||||
* GtkConstraintGuide:name:
|
||||
*
|
||||
* A name that identifies the #GtkConstraintGuide, for debugging.
|
||||
*/
|
||||
guide_props[PROP_NAME] =
|
||||
g_param_spec_string ("name",
|
||||
"Name",
|
||||
"A name to use in debug message",
|
||||
NULL,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_properties (object_class, LAST_PROP, guide_props);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_guide_new:
|
||||
*
|
||||
* Creates a new #GtkConstraintGuide object.
|
||||
*
|
||||
* Return: a new #GtkConstraintGuide object.
|
||||
*/
|
||||
GtkConstraintGuide *
|
||||
gtk_constraint_guide_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_CONSTRAINT_GUIDE, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_guide_set_min_size:
|
||||
* @guide: a #GtkConstraintGuide object
|
||||
* @width: the new minimum width, or -1 to not change it
|
||||
* @height: the new minimum height, or -1 to not change it
|
||||
*
|
||||
* Sets the minimum size of @guide.
|
||||
*
|
||||
* If @guide is attached to a #GtkConstraintLayout,
|
||||
* the constraints will be updated to reflect the new size.
|
||||
*/
|
||||
void
|
||||
gtk_constraint_guide_set_min_size (GtkConstraintGuide *guide,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide));
|
||||
g_return_if_fail (width >= -1);
|
||||
g_return_if_fail (height >= -1);
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (guide));
|
||||
|
||||
if (width != -1)
|
||||
g_object_set (guide, "min-width", width, NULL);
|
||||
|
||||
if (height != -1)
|
||||
g_object_set (guide, "min-height", height, NULL);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (guide));
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_guide_get_min_size:
|
||||
* @guide: a #GtkContraintGuide object
|
||||
* @width: (allow-none): return location for the minimum width,
|
||||
* or %NULL
|
||||
* @height: (allow-none): return location for the minimum height,
|
||||
* or %NULL
|
||||
*
|
||||
* Gets the minimum size of @guide.
|
||||
*/
|
||||
void
|
||||
gtk_constraint_guide_get_min_size (GtkConstraintGuide *guide,
|
||||
int *width,
|
||||
int *height)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide));
|
||||
|
||||
if (width)
|
||||
*width = guide->values[MIN_WIDTH];
|
||||
if (height)
|
||||
*height = guide->values[MIN_HEIGHT];
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_guide_set_nat_size:
|
||||
* @guide: a #GtkConstraintGuide object
|
||||
* @width: the new natural width, or -1 to not change it
|
||||
* @height: the new natural height, or -1 to not change it
|
||||
*
|
||||
* Sets the natural size of @guide.
|
||||
*
|
||||
* If @guide is attached to a #GtkConstraintLayout,
|
||||
* the constraints will be updated to reflect the new size.
|
||||
*/
|
||||
void
|
||||
gtk_constraint_guide_set_nat_size (GtkConstraintGuide *guide,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide));
|
||||
g_return_if_fail (width >= -1);
|
||||
g_return_if_fail (height >= -1);
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (guide));
|
||||
|
||||
if (width != -1)
|
||||
g_object_set (guide, "nat-width", width, NULL);
|
||||
|
||||
if (height != -1)
|
||||
g_object_set (guide, "nat-height", height, NULL);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (guide));
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_guide_get_nat_size:
|
||||
* @guide: a #GtkContraintGuide object
|
||||
* @width: (allow-none): return location for the natural width,
|
||||
* or %NULL
|
||||
* @height: (allow-none): return location for the natural height,
|
||||
* or %NULL
|
||||
*
|
||||
* Gets the natural size of @guide.
|
||||
*/
|
||||
void
|
||||
gtk_constraint_guide_get_nat_size (GtkConstraintGuide *guide,
|
||||
int *width,
|
||||
int *height)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide));
|
||||
|
||||
if (width)
|
||||
*width = guide->values[NAT_WIDTH];
|
||||
if (height)
|
||||
*height = guide->values[NAT_HEIGHT];
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_guide_set_max_size:
|
||||
* @guide: a #GtkConstraintGuide object
|
||||
* @width: the new maximum width, or -1 to not change it
|
||||
* @height: the new maximum height, or -1 to not change it
|
||||
*
|
||||
* Sets the maximum size of @guide.
|
||||
*
|
||||
* If @guide is attached to a #GtkConstraintLayout,
|
||||
* the constraints will be updated to reflect the new size.
|
||||
*/
|
||||
void
|
||||
gtk_constraint_guide_set_max_size (GtkConstraintGuide *guide,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide));
|
||||
g_return_if_fail (width >= -1);
|
||||
g_return_if_fail (height >= -1);
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (guide));
|
||||
|
||||
if (width != -1)
|
||||
g_object_set (guide, "max-width", width, NULL);
|
||||
|
||||
if (height != -1)
|
||||
g_object_set (guide, "max-height", height, NULL);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (guide));
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_guide_get_max_size:
|
||||
* @guide: a #GtkContraintGuide object
|
||||
* @width: (allow-none): return location for the maximum width,
|
||||
* or %NULL
|
||||
* @height: (allow-none): return location for the maximum height,
|
||||
* or %NULL
|
||||
*
|
||||
* Gets the maximum size of @guide.
|
||||
*/
|
||||
void
|
||||
gtk_constraint_guide_get_max_size (GtkConstraintGuide *guide,
|
||||
int *width,
|
||||
int *height)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide));
|
||||
|
||||
if (width)
|
||||
*width = guide->values[MAX_WIDTH];
|
||||
if (height)
|
||||
*height = guide->values[MAX_HEIGHT];
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_guide_get_name:
|
||||
* @guide: a #GtkConstraintGuide
|
||||
*
|
||||
* Retrieves the name set using gtk_constraint_guide_set_name().
|
||||
*
|
||||
* Returns: (transfer none) (nullable): the name of the guide
|
||||
*/
|
||||
const char *
|
||||
gtk_constraint_guide_get_name (GtkConstraintGuide *guide)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide), NULL);
|
||||
|
||||
return guide->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_guide_set_name:
|
||||
* @guide: a #GtkConstraintGuide
|
||||
* @name: (nullable): a name for the @guide
|
||||
*
|
||||
* Sets a name for the given #GtkConstraintGuide.
|
||||
*
|
||||
* The name is useful for debugging purposes.
|
||||
*/
|
||||
void
|
||||
gtk_constraint_guide_set_name (GtkConstraintGuide *guide,
|
||||
const char *name)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide));
|
||||
|
||||
g_free (guide->name);
|
||||
guide->name = g_strdup (name);
|
||||
g_object_notify_by_pspec (G_OBJECT (guide), guide_props[PROP_NAME]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_guide_get_strength:
|
||||
* @guide: a #GtkConstraintGuide
|
||||
*
|
||||
* Retrieves the strength set using gtk_constraint_guide_set_strength().
|
||||
*
|
||||
* Returns: the strength of the constraint on the natural size
|
||||
*/
|
||||
GtkConstraintStrength
|
||||
gtk_constraint_guide_get_strength (GtkConstraintGuide *guide)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide),
|
||||
GTK_CONSTRAINT_STRENGTH_MEDIUM);
|
||||
|
||||
return guide->strength;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_constraint_guide_set_strength:
|
||||
* @guide: a #GtkConstraintGuide
|
||||
* @strength: the strength of the constraint
|
||||
*
|
||||
* Sets the strength of the constraint on the natural size of the
|
||||
* given #GtkConstraintGuide.
|
||||
*/
|
||||
void
|
||||
gtk_constraint_guide_set_strength (GtkConstraintGuide *guide,
|
||||
GtkConstraintStrength strength)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide));
|
||||
|
||||
if (guide->strength == strength)
|
||||
return;
|
||||
|
||||
guide->strength = strength;
|
||||
g_object_notify_by_pspec (G_OBJECT (guide), guide_props[PROP_STRENGTH]);
|
||||
gtk_constraint_guide_update_constraint (guide, NAT_WIDTH);
|
||||
gtk_constraint_guide_update_constraint (guide, NAT_HEIGHT);
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/* gtkconstraintguide.h: Flexible space for constraints
|
||||
* 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/>.
|
||||
*
|
||||
* Author: Matthias Clasen
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtktypes.h>
|
||||
#include <gtk/gtkenums.h>
|
||||
#include <gtk/gtktypebuiltins.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_CONSTRAINT_GUIDE (gtk_constraint_guide_get_type ())
|
||||
|
||||
/**
|
||||
* GtkConstraintGuide:
|
||||
*
|
||||
* An object that can be added to a #GtkConstraintLayout and be
|
||||
* used in constraints like a widget, without being drawn.
|
||||
*
|
||||
* Guides have a minimum, maximum and natural size. Depending
|
||||
* on the constraints that are applied, they can act like a
|
||||
* guideline that widgets can be aligned to, or like 'flexible space'.
|
||||
*/
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (GtkConstraintGuide, gtk_constraint_guide, GTK, CONSTRAINT_GUIDE, GObject)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkConstraintGuide * gtk_constraint_guide_new (void);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_constraint_guide_set_min_size (GtkConstraintGuide *guide,
|
||||
int width,
|
||||
int height);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_constraint_guide_get_min_size (GtkConstraintGuide *guide,
|
||||
int *width,
|
||||
int *height);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_constraint_guide_set_nat_size (GtkConstraintGuide *guide,
|
||||
int width,
|
||||
int height);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_constraint_guide_get_nat_size (GtkConstraintGuide *guide,
|
||||
int *width,
|
||||
int *height);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_constraint_guide_set_max_size (GtkConstraintGuide *guide,
|
||||
int width,
|
||||
int height);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_constraint_guide_get_max_size (GtkConstraintGuide *guide,
|
||||
int *width,
|
||||
int *height);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkConstraintStrength gtk_constraint_guide_get_strength (GtkConstraintGuide *guide);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_constraint_guide_set_strength (GtkConstraintGuide *guide,
|
||||
GtkConstraintStrength strength);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_constraint_guide_set_name (GtkConstraintGuide *guide,
|
||||
const char *name);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const char * gtk_constraint_guide_get_name (GtkConstraintGuide *guide);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -0,0 +1,38 @@
|
||||
/* gtkconstraintguideprivate.h: Constraint between two widgets
|
||||
* 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/>.
|
||||
*
|
||||
* Author: Matthias Clasen
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gtkconstraintguide.h"
|
||||
#include "gtkconstraintlayout.h"
|
||||
#include "gtkconstrainttypesprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void gtk_constraint_guide_update (GtkConstraintGuide *guide);
|
||||
void gtk_constraint_guide_detach (GtkConstraintGuide *guide);
|
||||
|
||||
GtkConstraintVariable *gtk_constraint_guide_get_attribute (GtkConstraintGuide *guide,
|
||||
GtkConstraintAttribute attr);
|
||||
|
||||
GtkConstraintLayout *gtk_constraint_guide_get_layout (GtkConstraintGuide *guide);
|
||||
void gtk_constraint_guide_set_layout (GtkConstraintGuide *guide,
|
||||
GtkConstraintLayout *layout);
|
||||
|
||||
G_END_DECLS
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,93 @@
|
||||
/* gtkconstraintlayout.h: Layout manager using constraints
|
||||
* Copyright 2019 GNOME Foundation
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author: Emmanuele Bassi
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtklayoutmanager.h>
|
||||
#include <gtk/gtkconstraint.h>
|
||||
#include <gtk/gtkconstraintguide.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_CONSTRAINT_LAYOUT (gtk_constraint_layout_get_type ())
|
||||
#define GTK_TYPE_CONSTRAINT_LAYOUT_CHILD (gtk_constraint_layout_child_get_type ())
|
||||
#define GTK_CONSTRAINT_VFL_PARSER_ERROR (gtk_constraint_vfl_parser_error_quark ())
|
||||
|
||||
/**
|
||||
* GtkConstraintLayoutChild:
|
||||
*
|
||||
* A #GtkLayoutChild in a #GtkConstraintLayout.
|
||||
*/
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (GtkConstraintLayoutChild, gtk_constraint_layout_child, GTK, CONSTRAINT_LAYOUT_CHILD, GtkLayoutChild)
|
||||
|
||||
/**
|
||||
* GtkConstraintLayout:
|
||||
*
|
||||
* A layout manager using #GtkConstraint to describe
|
||||
* relations between widgets.
|
||||
*/
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (GtkConstraintLayout, gtk_constraint_layout, GTK, CONSTRAINT_LAYOUT, GtkLayoutManager)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GQuark gtk_constraint_vfl_parser_error_quark (void);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkLayoutManager * gtk_constraint_layout_new (void);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_constraint_layout_add_constraint (GtkConstraintLayout *layout,
|
||||
GtkConstraint *constraint);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_constraint_layout_remove_constraint (GtkConstraintLayout *layout,
|
||||
GtkConstraint *constraint);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_constraint_layout_add_guide (GtkConstraintLayout *layout,
|
||||
GtkConstraintGuide *guide);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_constraint_layout_remove_guide (GtkConstraintLayout *layout,
|
||||
GtkConstraintGuide *guide);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_constraint_layout_remove_all_constraints (GtkConstraintLayout *layout);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GList * gtk_constraint_layout_add_constraints_from_description (GtkConstraintLayout *layout,
|
||||
const char * const lines[],
|
||||
gsize n_lines,
|
||||
int hspacing,
|
||||
int vspacing,
|
||||
GError **error,
|
||||
const char *first_view,
|
||||
...) G_GNUC_NULL_TERMINATED;
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GList * gtk_constraint_layout_add_constraints_from_descriptionv (GtkConstraintLayout *layout,
|
||||
const char * const lines[],
|
||||
gsize n_lines,
|
||||
int hspacing,
|
||||
int vspacing,
|
||||
GHashTable *views,
|
||||
GError **error);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GListModel * gtk_constraint_layout_observe_constraints (GtkConstraintLayout *layout);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GListModel * gtk_constraint_layout_observe_guides (GtkConstraintLayout *layout);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*
|
||||
* Author: Matthias Clasen
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gtkconstraintlayout.h"
|
||||
#include "gtkconstraintsolverprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GtkConstraintSolver *
|
||||
gtk_constraint_layout_get_solver (GtkConstraintLayout *layout);
|
||||
|
||||
GtkConstraintVariable *
|
||||
gtk_constraint_layout_get_attribute (GtkConstraintLayout *layout,
|
||||
GtkConstraintAttribute attr,
|
||||
const char *prefix,
|
||||
GtkWidget *widget,
|
||||
GHashTable *bound_attributes);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -0,0 +1,60 @@
|
||||
/* gtkconstraintprivate.h: Constraint between two widgets
|
||||
* Copyright 2019 GNOME Foundation
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author: Emmanuele Bassi
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gtkconstraint.h"
|
||||
#include "gtkconstrainttypesprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
struct _GtkConstraint
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GtkConstraintAttribute target_attribute;
|
||||
GtkConstraintAttribute source_attribute;
|
||||
|
||||
GtkConstraintTarget *target;
|
||||
GtkConstraintTarget *source;
|
||||
|
||||
GtkConstraintRelation relation;
|
||||
|
||||
double multiplier;
|
||||
double constant;
|
||||
|
||||
int strength;
|
||||
|
||||
/* A reference to the real constraint inside the
|
||||
* GtkConstraintSolver, so we can remove it when
|
||||
* finalizing the GtkConstraint instance
|
||||
*/
|
||||
GtkConstraintRef *constraint_ref;
|
||||
|
||||
GtkConstraintSolver *solver;
|
||||
|
||||
guint active : 1;
|
||||
};
|
||||
|
||||
void gtk_constraint_attach (GtkConstraint *constraint,
|
||||
GtkConstraintSolver *solver,
|
||||
GtkConstraintRef *ref);
|
||||
void gtk_constraint_detach (GtkConstraint *constraint);
|
||||
|
||||
G_END_DECLS
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,117 @@
|
||||
/* gtkconstraintsolverprivate.h: Constraint solver based on the Cassowary method
|
||||
* Copyright 2019 GNOME Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author: Emmanuele Bassi
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gtkconstrainttypesprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_CONSTRAINT_SOLVER (gtk_constraint_solver_get_type())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GtkConstraintSolver, gtk_constraint_solver, GTK, CONSTRAINT_SOLVER, GObject)
|
||||
|
||||
GtkConstraintSolver *
|
||||
gtk_constraint_solver_new (void);
|
||||
|
||||
void
|
||||
gtk_constraint_solver_freeze (GtkConstraintSolver *solver);
|
||||
|
||||
void
|
||||
gtk_constraint_solver_thaw (GtkConstraintSolver *solver);
|
||||
|
||||
void
|
||||
gtk_constraint_solver_resolve (GtkConstraintSolver *solver);
|
||||
|
||||
GtkConstraintVariable *
|
||||
gtk_constraint_solver_create_variable (GtkConstraintSolver *solver,
|
||||
const char *prefix,
|
||||
const char *name,
|
||||
double value);
|
||||
|
||||
GtkConstraintRef *
|
||||
gtk_constraint_solver_add_constraint (GtkConstraintSolver *solver,
|
||||
GtkConstraintVariable *variable,
|
||||
GtkConstraintRelation relation,
|
||||
GtkConstraintExpression *expression,
|
||||
int strength);
|
||||
|
||||
void
|
||||
gtk_constraint_solver_remove_constraint (GtkConstraintSolver *solver,
|
||||
GtkConstraintRef *reference);
|
||||
|
||||
GtkConstraintRef *
|
||||
gtk_constraint_solver_add_stay_variable (GtkConstraintSolver *solver,
|
||||
GtkConstraintVariable *variable,
|
||||
int strength);
|
||||
|
||||
void
|
||||
gtk_constraint_solver_remove_stay_variable (GtkConstraintSolver *solver,
|
||||
GtkConstraintVariable *variable);
|
||||
|
||||
gboolean
|
||||
gtk_constraint_solver_has_stay_variable (GtkConstraintSolver *solver,
|
||||
GtkConstraintVariable *variable);
|
||||
|
||||
GtkConstraintRef *
|
||||
gtk_constraint_solver_add_edit_variable (GtkConstraintSolver *solver,
|
||||
GtkConstraintVariable *variable,
|
||||
int strength);
|
||||
|
||||
void
|
||||
gtk_constraint_solver_remove_edit_variable (GtkConstraintSolver *solver,
|
||||
GtkConstraintVariable *variable);
|
||||
|
||||
gboolean
|
||||
gtk_constraint_solver_has_edit_variable (GtkConstraintSolver *solver,
|
||||
GtkConstraintVariable *variable);
|
||||
|
||||
void
|
||||
gtk_constraint_solver_suggest_value (GtkConstraintSolver *solver,
|
||||
GtkConstraintVariable *variable,
|
||||
double value);
|
||||
|
||||
void
|
||||
gtk_constraint_solver_begin_edit (GtkConstraintSolver *solver);
|
||||
|
||||
void
|
||||
gtk_constraint_solver_end_edit (GtkConstraintSolver *solver);
|
||||
|
||||
void
|
||||
gtk_constraint_solver_note_added_variable (GtkConstraintSolver *self,
|
||||
GtkConstraintVariable *variable,
|
||||
GtkConstraintVariable *subject);
|
||||
|
||||
void
|
||||
gtk_constraint_solver_note_removed_variable (GtkConstraintSolver *self,
|
||||
GtkConstraintVariable *variable,
|
||||
GtkConstraintVariable *subject);
|
||||
|
||||
void
|
||||
gtk_constraint_solver_clear (GtkConstraintSolver *solver);
|
||||
|
||||
char *
|
||||
gtk_constraint_solver_to_string (GtkConstraintSolver *solver);
|
||||
|
||||
char *
|
||||
gtk_constraint_solver_statistics (GtkConstraintSolver *solver);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -0,0 +1,50 @@
|
||||
/* gtkconstrainttypesprivate.h: Private types for the constraint solver
|
||||
* Copyright 2019 GNOME Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author: Emmanuele Bassi
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtktypes.h>
|
||||
#include <gtk/gtkenums.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GtkConstraintVariable GtkConstraintVariable;
|
||||
typedef struct _GtkConstraintExpression GtkConstraintExpression;
|
||||
typedef struct _GtkConstraintExpressionBuilder GtkConstraintExpressionBuilder;
|
||||
|
||||
/*< private >
|
||||
* GtkConstraintRef:
|
||||
*
|
||||
* A reference to a constraint stored inside the solver; while #GtkConstraint
|
||||
* represent the public API, a #GtkConstraintRef represents data stored inside
|
||||
* the solver. A #GtkConstraintRef is completely opaque, and should only be
|
||||
* used to remove a constraint from the solver.
|
||||
*/
|
||||
typedef struct _GtkConstraintRef GtkConstraintRef;
|
||||
|
||||
/*< private >
|
||||
* GtkConstraintSolver:
|
||||
*
|
||||
* A simplex solver using the Cassowary constraint solving algorithm.
|
||||
*/
|
||||
typedef struct _GtkConstraintSolver GtkConstraintSolver;
|
||||
|
||||
G_END_DECLS
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,76 @@
|
||||
/* gtkconstraintvflparserprivate.h: VFL constraint definition parser
|
||||
*
|
||||
* Copyright 2017 Endless
|
||||
* Copyright 2019 GNOME Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gtkconstrainttypesprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GtkConstraintVflParser GtkConstraintVflParser;
|
||||
|
||||
typedef struct {
|
||||
const char *view1;
|
||||
const char *attr1;
|
||||
GtkConstraintRelation relation;
|
||||
const char *view2;
|
||||
const char *attr2;
|
||||
double constant;
|
||||
double multiplier;
|
||||
double strength;
|
||||
} GtkConstraintVfl;
|
||||
|
||||
GtkConstraintVflParser *
|
||||
gtk_constraint_vfl_parser_new (void);
|
||||
|
||||
void
|
||||
gtk_constraint_vfl_parser_free (GtkConstraintVflParser *parser);
|
||||
|
||||
void
|
||||
gtk_constraint_vfl_parser_set_default_spacing (GtkConstraintVflParser *parser,
|
||||
int hspacing,
|
||||
int vspacing);
|
||||
|
||||
void
|
||||
gtk_constraint_vfl_parser_set_metrics (GtkConstraintVflParser *parser,
|
||||
GHashTable *metrics);
|
||||
|
||||
void
|
||||
gtk_constraint_vfl_parser_set_views (GtkConstraintVflParser *parser,
|
||||
GHashTable *views);
|
||||
|
||||
gboolean
|
||||
gtk_constraint_vfl_parser_parse_line (GtkConstraintVflParser *parser,
|
||||
const char *line,
|
||||
gssize len,
|
||||
GError **error);
|
||||
|
||||
int
|
||||
gtk_constraint_vfl_parser_get_error_offset (GtkConstraintVflParser *parser);
|
||||
|
||||
int
|
||||
gtk_constraint_vfl_parser_get_error_range (GtkConstraintVflParser *parser);
|
||||
|
||||
GtkConstraintVfl *
|
||||
gtk_constraint_vfl_parser_get_constraints (GtkConstraintVflParser *parser,
|
||||
int *n_constraints);
|
||||
|
||||
G_END_DECLS
|
||||
+2
-1
@@ -51,7 +51,8 @@ typedef enum {
|
||||
GTK_DEBUG_ACTIONS = 1 << 13,
|
||||
GTK_DEBUG_RESIZE = 1 << 14,
|
||||
GTK_DEBUG_LAYOUT = 1 << 15,
|
||||
GTK_DEBUG_SNAPSHOT = 1 << 16
|
||||
GTK_DEBUG_SNAPSHOT = 1 << 16,
|
||||
GTK_DEBUG_CONSTRAINTS = 1 << 17,
|
||||
} GtkDebugFlag;
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
|
||||
@@ -1053,4 +1053,98 @@ typedef enum {
|
||||
GTK_PICK_NON_TARGETABLE = 1 << 1
|
||||
} GtkPickFlags;
|
||||
|
||||
/**
|
||||
* GtkConstraintRelation:
|
||||
* @GTK_CONSTRAINT_RELATION_EQ: Equal
|
||||
* @GTK_CONSTRAINT_RELATION_LE: Less than, or equal
|
||||
* @GTK_CONSTRAINT_RELATION_GE: Greater than, or equal
|
||||
*
|
||||
* The relation between two terms of a constraint.
|
||||
*/
|
||||
typedef enum {
|
||||
GTK_CONSTRAINT_RELATION_LE = -1,
|
||||
GTK_CONSTRAINT_RELATION_EQ = 0,
|
||||
GTK_CONSTRAINT_RELATION_GE = 1
|
||||
} GtkConstraintRelation;
|
||||
|
||||
/**
|
||||
* GtkConstraintStrength:
|
||||
* @GTK_CONSTRAINT_STRENGTH_REQUIRED: The constraint is required towards solving the layout
|
||||
* @GTK_CONSTRAINT_STRENGTH_STRONG: A strong constraint
|
||||
* @GTK_CONSTRAINT_STRENGTH_MEDIUM: A medium constraint
|
||||
* @GTK_CONSTRAINT_STRENGTH_WEAK: A weak constraint
|
||||
*
|
||||
* The strength of a constraint, expressed as a symbolic constant.
|
||||
*
|
||||
* The strength of a #GtkConstraint can be expressed with any positive
|
||||
* integer; the values of this enumeration can be used for readability.
|
||||
*/
|
||||
typedef enum {
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED = 1001001000,
|
||||
GTK_CONSTRAINT_STRENGTH_STRONG = 1000000000,
|
||||
GTK_CONSTRAINT_STRENGTH_MEDIUM = 1000,
|
||||
GTK_CONSTRAINT_STRENGTH_WEAK = 1
|
||||
} GtkConstraintStrength;
|
||||
|
||||
/**
|
||||
* GtkConstraintAttribute:
|
||||
* @GTK_CONSTRAINT_ATTRIBUTE_NONE: No attribute, used for constant
|
||||
* relations
|
||||
* @GTK_CONSTRAINT_ATTRIBUTE_LEFT: The left edge of a widget, regardless of
|
||||
* text direction
|
||||
* @GTK_CONSTRAINT_ATTRIBUTE_RIGHT: The right edge of a widget, regardless
|
||||
* of text direction
|
||||
* @GTK_CONSTRAINT_ATTRIBUTE_TOP: The top edge of a widget
|
||||
* @GTK_CONSTRAINT_ATTRIBUTE_BOTTOM: The bottom edge of a widget
|
||||
* @GTK_CONSTRAINT_ATTRIBUTE_START: The leading edge of a widget, depending
|
||||
* on text direction; equivalent to %GTK_CONSTRAINT_ATTRIBUTE_LEFT for LTR
|
||||
* languages, and %GTK_CONSTRAINT_ATTRIBUTE_RIGHT for RTL ones
|
||||
* @GTK_CONSTRAINT_ATTRIBUTE_END: The trailing edge of a widget, depending
|
||||
* on text direction; equivalent to %GTK_CONSTRAINT_ATTRIBUTE_RIGHT for LTR
|
||||
* languages, and %GTK_CONSTRAINT_ATTRIBUTE_LEFT for RTL ones
|
||||
* @GTK_CONSTRAINT_ATTRIBUTE_WIDTH: The width of a widget
|
||||
* @GTK_CONSTRAINT_ATTRIBUTE_HEIGHT: The height of a widget
|
||||
* @GTK_CONSTRAINT_ATTRIBUTE_CENTER_X: The center of a widget, on the
|
||||
* horizontal axis
|
||||
* @GTK_CONSTRAINT_ATTRIBUTE_CENTER_Y: The center of a widget, on the
|
||||
* vertical axis
|
||||
* @GTK_CONSTRAINT_ATTRIBUTE_BASELINE: The baseline of a widget
|
||||
*
|
||||
* The widget attributes that can be used when creating a #GtkConstraint.
|
||||
*/
|
||||
typedef enum {
|
||||
GTK_CONSTRAINT_ATTRIBUTE_NONE,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_LEFT,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_RIGHT,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_CENTER_X,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_CENTER_Y,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BASELINE
|
||||
} GtkConstraintAttribute;
|
||||
|
||||
/**
|
||||
* GtkConstraintVflParserError:
|
||||
* @GTK_CONSTRAINT_VFL_PARSER_ERROR_INVALID_SYMBOL: Invalid or unknown symbol
|
||||
* @GTK_CONSTRAINT_VFL_PARSER_ERROR_INVALID_ATTRIBUTE: Invalid or unknown attribute
|
||||
* @GTK_CONSTRAINT_VFL_PARSER_ERROR_INVALID_VIEW: Invalid or unknown view
|
||||
* @GTK_CONSTRAINT_VFL_PARSER_ERROR_INVALID_METRIC: Invalid or unknown metric
|
||||
* @GTK_CONSTRAINT_VFL_PARSER_ERROR_INVALID_PRIORITY: Invalid or unknown priority
|
||||
* @GTK_CONSTRAINT_VFL_PARSER_ERROR_INVALID_RELATION: Invalid or unknown relation
|
||||
*
|
||||
* Domain for VFL parsing errors.
|
||||
*/
|
||||
typedef enum {
|
||||
GTK_CONSTRAINT_VFL_PARSER_ERROR_INVALID_SYMBOL,
|
||||
GTK_CONSTRAINT_VFL_PARSER_ERROR_INVALID_ATTRIBUTE,
|
||||
GTK_CONSTRAINT_VFL_PARSER_ERROR_INVALID_VIEW,
|
||||
GTK_CONSTRAINT_VFL_PARSER_ERROR_INVALID_METRIC,
|
||||
GTK_CONSTRAINT_VFL_PARSER_ERROR_INVALID_PRIORITY,
|
||||
GTK_CONSTRAINT_VFL_PARSER_ERROR_INVALID_RELATION
|
||||
} GtkConstraintVflParserError;
|
||||
|
||||
#endif /* __GTK_ENUMS_H__ */
|
||||
|
||||
@@ -216,17 +216,25 @@ gtk_flatten_list_model_items_changed_cb (GListModel *model,
|
||||
guint added,
|
||||
gpointer _node)
|
||||
{
|
||||
FlattenNode *node = _node, *parent;
|
||||
FlattenNode *node = _node, *parent, *left;
|
||||
GtkFlattenListModel *self = node->list;
|
||||
guint real_position;
|
||||
|
||||
gtk_rb_tree_node_mark_dirty (node);
|
||||
real_position = position;
|
||||
|
||||
for (real_position = position;
|
||||
left = gtk_rb_tree_node_get_left (node);
|
||||
if (left)
|
||||
{
|
||||
FlattenAugment *aug = gtk_rb_tree_get_augment (self->items, left);
|
||||
real_position += aug->n_items;
|
||||
}
|
||||
|
||||
for (;
|
||||
(parent = gtk_rb_tree_node_get_parent (node)) != NULL;
|
||||
node = parent)
|
||||
{
|
||||
FlattenNode *left = gtk_rb_tree_node_get_left (parent);
|
||||
left = gtk_rb_tree_node_get_left (parent);
|
||||
if (left != node)
|
||||
{
|
||||
if (left)
|
||||
|
||||
@@ -212,6 +212,8 @@ gtk_grid_layout_child_class_init (GtkGridLayoutChildClass *klass)
|
||||
static void
|
||||
gtk_grid_layout_child_init (GtkGridLayoutChild *self)
|
||||
{
|
||||
CHILD_ROW_SPAN (self) = 1;
|
||||
CHILD_COL_SPAN (self) = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -91,6 +91,7 @@
|
||||
|
||||
typedef struct {
|
||||
GtkWidget *widget;
|
||||
GtkRoot *root;
|
||||
|
||||
/* HashTable<Widget, LayoutChild> */
|
||||
GHashTable *layout_children;
|
||||
@@ -98,6 +99,16 @@ typedef struct {
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GtkLayoutManager, gtk_layout_manager, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gtk_layout_manager_real_root (GtkLayoutManager *manager)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_layout_manager_real_unroot (GtkLayoutManager *manager)
|
||||
{
|
||||
}
|
||||
|
||||
static GtkSizeRequestMode
|
||||
gtk_layout_manager_real_get_request_mode (GtkLayoutManager *manager,
|
||||
GtkWidget *widget)
|
||||
@@ -188,13 +199,30 @@ gtk_layout_manager_real_create_layout_child (GtkLayoutManager *manager,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_layout_manager_finalize (GObject *gobject)
|
||||
{
|
||||
GtkLayoutManager *self = GTK_LAYOUT_MANAGER (gobject);
|
||||
GtkLayoutManagerPrivate *priv = gtk_layout_manager_get_instance_private (self);
|
||||
|
||||
g_clear_pointer (&priv->layout_children, g_hash_table_unref);
|
||||
|
||||
G_OBJECT_CLASS (gtk_layout_manager_parent_class)->finalize (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_layout_manager_class_init (GtkLayoutManagerClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = gtk_layout_manager_finalize;
|
||||
|
||||
klass->get_request_mode = gtk_layout_manager_real_get_request_mode;
|
||||
klass->measure = gtk_layout_manager_real_measure;
|
||||
klass->allocate = gtk_layout_manager_real_allocate;
|
||||
klass->create_layout_child = gtk_layout_manager_real_create_layout_child;
|
||||
klass->root = gtk_layout_manager_real_root;
|
||||
klass->unroot = gtk_layout_manager_real_unroot;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -226,6 +254,38 @@ gtk_layout_manager_set_widget (GtkLayoutManager *layout_manager,
|
||||
}
|
||||
|
||||
priv->widget = widget;
|
||||
|
||||
if (widget != NULL)
|
||||
gtk_layout_manager_set_root (layout_manager, gtk_widget_get_root (widget));
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gtk_layout_manager_set_root:
|
||||
* @layout_manager: a #GtkLayoutManager
|
||||
* @root: (nullable): a #GtkWidget implementing #GtkRoot
|
||||
*
|
||||
* Sets a back pointer from @root to @layout_manager.
|
||||
*
|
||||
* This function is called by #GtkWidget when getting rooted and unrooted,
|
||||
* and will call #GtkLayoutManagerClass.root() or #GtkLayoutManagerClass.unroot()
|
||||
* depending on whether @root is a #GtkWidget or %NULL.
|
||||
*/
|
||||
void
|
||||
gtk_layout_manager_set_root (GtkLayoutManager *layout_manager,
|
||||
GtkRoot *root)
|
||||
{
|
||||
GtkLayoutManagerPrivate *priv = gtk_layout_manager_get_instance_private (layout_manager);
|
||||
GtkRoot *old_root = priv->root;
|
||||
|
||||
priv->root = root;
|
||||
|
||||
if (old_root != root)
|
||||
{
|
||||
if (priv->root != NULL)
|
||||
GTK_LAYOUT_MANAGER_GET_CLASS (layout_manager)->root (layout_manager);
|
||||
else
|
||||
GTK_LAYOUT_MANAGER_GET_CLASS (layout_manager)->unroot (layout_manager);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -42,6 +42,10 @@ G_DECLARE_DERIVABLE_TYPE (GtkLayoutManager, gtk_layout_manager, GTK, LAYOUT_MANA
|
||||
* @layout_child_type: the type of #GtkLayoutChild used by this layout manager
|
||||
* @create_layout_child: a virtual function, used to create a #GtkLayoutChild
|
||||
* meta object for the layout properties
|
||||
* @root: a virtual function, called when the widget using the layout
|
||||
* manager is attached to a #GtkRoot
|
||||
* @unroot: a virtual function, called when the widget using the layout
|
||||
* manager is detached from a #GtkRoot
|
||||
*
|
||||
* The `GtkLayoutManagerClass` structure contains only private data, and
|
||||
* should only be accessed through the provided API, or when subclassing
|
||||
@@ -77,6 +81,9 @@ struct _GtkLayoutManagerClass
|
||||
GtkWidget *widget,
|
||||
GtkWidget *for_child);
|
||||
|
||||
void (* root) (GtkLayoutManager *manager);
|
||||
void (* unroot) (GtkLayoutManager *manager);
|
||||
|
||||
/*< private >*/
|
||||
gpointer _padding[16];
|
||||
};
|
||||
|
||||
@@ -10,4 +10,7 @@ void gtk_layout_manager_set_widget (GtkLayoutManager *manager,
|
||||
void gtk_layout_manager_remove_layout_child (GtkLayoutManager *manager,
|
||||
GtkWidget *widget);
|
||||
|
||||
void gtk_layout_manager_set_root (GtkLayoutManager *manager,
|
||||
GtkRoot *root);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
+2
-1
@@ -179,7 +179,8 @@ static const GDebugKey gtk_debug_keys[] = {
|
||||
{ "actions", GTK_DEBUG_ACTIONS },
|
||||
{ "resize", GTK_DEBUG_RESIZE },
|
||||
{ "layout", GTK_DEBUG_LAYOUT },
|
||||
{ "snapshot", GTK_DEBUG_SNAPSHOT }
|
||||
{ "snapshot", GTK_DEBUG_SNAPSHOT },
|
||||
{ "constraints", GTK_DEBUG_CONSTRAINTS },
|
||||
};
|
||||
#endif /* G_ENABLE_DEBUG */
|
||||
|
||||
|
||||
@@ -50,10 +50,18 @@ gtk_root_default_get_display (GtkRoot *self)
|
||||
return gdk_display_get_default ();
|
||||
}
|
||||
|
||||
|
||||
static GtkConstraintSolver *
|
||||
gtk_root_default_get_constraint_solver (GtkRoot *self)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_root_default_init (GtkRootInterface *iface)
|
||||
{
|
||||
iface->get_display = gtk_root_default_get_display;
|
||||
iface->get_constraint_solver = gtk_root_default_get_constraint_solver;
|
||||
|
||||
g_object_interface_install_property (iface,
|
||||
g_param_spec_object ("focus-widget",
|
||||
@@ -82,6 +90,17 @@ gtk_root_get_display (GtkRoot *self)
|
||||
return iface->get_display (self);
|
||||
}
|
||||
|
||||
GtkConstraintSolver *
|
||||
gtk_root_get_constraint_solver (GtkRoot *self)
|
||||
{
|
||||
GtkRootInterface *iface;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_ROOT (self), NULL);
|
||||
|
||||
iface = GTK_ROOT_GET_IFACE (self);
|
||||
return iface->get_constraint_solver (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_root_set_focus:
|
||||
* @self: a #GtkRoot
|
||||
|
||||
@@ -34,20 +34,6 @@ G_BEGIN_DECLS
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_INTERFACE (GtkRoot, gtk_root, GTK, ROOT, GtkWidget)
|
||||
|
||||
/**
|
||||
* GtkRootIface:
|
||||
*
|
||||
* The list of functions that must be implemented for the #GtkRoot interface.
|
||||
*/
|
||||
struct _GtkRootInterface
|
||||
{
|
||||
/*< private >*/
|
||||
GTypeInterface g_iface;
|
||||
|
||||
/*< public >*/
|
||||
GdkDisplay * (* get_display) (GtkRoot *self);
|
||||
};
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDisplay * gtk_root_get_display (GtkRoot *self);
|
||||
|
||||
|
||||
@@ -3,8 +3,28 @@
|
||||
|
||||
#include "gtkroot.h"
|
||||
|
||||
#include "gtkconstraintsolverprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* GtkRootIface:
|
||||
*
|
||||
* The list of functions that must be implemented for the #GtkRoot interface.
|
||||
*/
|
||||
struct _GtkRootInterface
|
||||
{
|
||||
/*< private >*/
|
||||
GTypeInterface g_iface;
|
||||
|
||||
/*< public >*/
|
||||
GdkDisplay * (* get_display) (GtkRoot *self);
|
||||
|
||||
GtkConstraintSolver * (* get_constraint_solver) (GtkRoot *self);
|
||||
};
|
||||
|
||||
GtkConstraintSolver * gtk_root_get_constraint_solver (GtkRoot *self);
|
||||
|
||||
enum {
|
||||
GTK_ROOT_PROP_FOCUS_WIDGET,
|
||||
GTK_ROOT_NUM_PROPERTIES
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
#include "gtkwindowgroup.h"
|
||||
#include "gtkwindowprivate.h"
|
||||
#include "gtknativeprivate.h"
|
||||
#include "gtkconstraint.h"
|
||||
|
||||
#include "a11y/gtkwidgetaccessible.h"
|
||||
#include "inspector/window.h"
|
||||
@@ -770,6 +771,13 @@ gtk_widget_get_type (void)
|
||||
NULL /* interface data */
|
||||
};
|
||||
|
||||
const GInterfaceInfo constraint_target_info =
|
||||
{
|
||||
(GInterfaceInitFunc) NULL,
|
||||
(GInterfaceFinalizeFunc) NULL,
|
||||
NULL /* interface data */
|
||||
};
|
||||
|
||||
widget_type = g_type_register_static (G_TYPE_INITIALLY_UNOWNED, g_intern_static_string ("GtkWidget"),
|
||||
&widget_info, G_TYPE_FLAG_ABSTRACT);
|
||||
|
||||
@@ -782,6 +790,8 @@ gtk_widget_get_type (void)
|
||||
&accessibility_info) ;
|
||||
g_type_add_interface_static (widget_type, GTK_TYPE_BUILDABLE,
|
||||
&buildable_info) ;
|
||||
g_type_add_interface_static (widget_type, GTK_TYPE_CONSTRAINT_TARGET,
|
||||
&constraint_target_info) ;
|
||||
}
|
||||
|
||||
return widget_type;
|
||||
@@ -2893,6 +2903,9 @@ gtk_widget_root (GtkWidget *widget)
|
||||
|
||||
_gtk_widget_update_parent_muxer (widget);
|
||||
|
||||
if (priv->layout_manager)
|
||||
gtk_layout_manager_set_root (priv->layout_manager, priv->root);
|
||||
|
||||
GTK_WIDGET_GET_CLASS (widget)->root (widget);
|
||||
|
||||
if (!GTK_IS_ROOT (widget))
|
||||
@@ -2920,6 +2933,9 @@ gtk_widget_unroot (GtkWidget *widget)
|
||||
if (priv->context)
|
||||
gtk_style_context_set_display (priv->context, gdk_display_get_default ());
|
||||
|
||||
if (priv->layout_manager)
|
||||
gtk_layout_manager_set_root (priv->layout_manager, NULL);
|
||||
|
||||
if (g_object_get_qdata (G_OBJECT (widget), quark_pango_context))
|
||||
g_object_set_qdata (G_OBJECT (widget), quark_pango_context, NULL);
|
||||
|
||||
|
||||
@@ -281,6 +281,8 @@ typedef struct
|
||||
GskRenderer *renderer;
|
||||
|
||||
GList *foci;
|
||||
|
||||
GtkConstraintSolver *constraint_solver;
|
||||
} GtkWindowPrivate;
|
||||
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
@@ -1883,6 +1885,9 @@ gtk_window_init (GtkWindow *window)
|
||||
g_signal_connect_swapped (priv->key_controller, "key-released",
|
||||
G_CALLBACK (gtk_window_key_released), window);
|
||||
gtk_widget_add_controller (widget, priv->key_controller);
|
||||
|
||||
/* Shared constraint solver */
|
||||
priv->constraint_solver = gtk_constraint_solver_new ();
|
||||
}
|
||||
|
||||
static GtkGesture *
|
||||
@@ -2353,6 +2358,15 @@ gtk_window_native_get_renderer (GtkNative *native)
|
||||
return priv->renderer;
|
||||
}
|
||||
|
||||
static GtkConstraintSolver *
|
||||
gtk_window_root_get_constraint_solver (GtkRoot *root)
|
||||
{
|
||||
GtkWindow *self = GTK_WINDOW (root);
|
||||
GtkWindowPrivate *priv = gtk_window_get_instance_private (self);
|
||||
|
||||
return priv->constraint_solver;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_native_get_surface_transform (GtkNative *native,
|
||||
int *x,
|
||||
@@ -2381,6 +2395,7 @@ static void
|
||||
gtk_window_root_interface_init (GtkRootInterface *iface)
|
||||
{
|
||||
iface->get_display = gtk_window_root_get_display;
|
||||
iface->get_constraint_solver = gtk_window_root_get_constraint_solver;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -4723,6 +4738,7 @@ gtk_window_finalize (GObject *object)
|
||||
priv->mnemonics_display_timeout_id = 0;
|
||||
}
|
||||
|
||||
g_clear_object (&priv->constraint_solver);
|
||||
g_clear_object (&priv->renderer);
|
||||
|
||||
G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
|
||||
|
||||
@@ -37,6 +37,9 @@ gtk_private_sources = files([
|
||||
'gtkcolorpickershell.c',
|
||||
'gtkcolorscale.c',
|
||||
'gtkcolorswatch.c',
|
||||
'gtkconstraintexpression.c',
|
||||
'gtkconstraintsolver.c',
|
||||
'gtkconstraintvflparser.c',
|
||||
'gtkcssanimatedstyle.c',
|
||||
'gtkcssanimation.c',
|
||||
'gtkcssarrayvalue.c',
|
||||
@@ -200,6 +203,9 @@ gtk_public_sources = files([
|
||||
'gtkcombobox.c',
|
||||
'gtkcomboboxtext.c',
|
||||
'gtkcomposetable.c',
|
||||
'gtkconstraintguide.c',
|
||||
'gtkconstraintlayout.c',
|
||||
'gtkconstraint.c',
|
||||
'gtkcontainer.c',
|
||||
'gtkcssprovider.c',
|
||||
'gtkdialog.c',
|
||||
@@ -459,6 +465,9 @@ gtk_public_headers = files([
|
||||
'gtkcolorutils.h',
|
||||
'gtkcombobox.h',
|
||||
'gtkcomboboxtext.h',
|
||||
'gtkconstraintguide.h',
|
||||
'gtkconstraintlayout.h',
|
||||
'gtkconstraint.h',
|
||||
'gtkcontainer.h',
|
||||
'gtkcssprovider.h',
|
||||
'gtkcustomlayout.h',
|
||||
|
||||
@@ -2178,11 +2178,11 @@ popover>contents {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
popover>contents.background {
|
||||
popover.background>contents {
|
||||
|
||||
background-color: $popover_bg_color;
|
||||
box-shadow: 0 1px 2px transparentize(black, 0.7);
|
||||
.csd &, & {
|
||||
.csd &, & {
|
||||
border: 1px solid $borders_color;
|
||||
border-radius: $popover_radius;
|
||||
}
|
||||
@@ -4766,8 +4766,9 @@ popover.menu {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
arrow,
|
||||
&.background contents {
|
||||
background: white;
|
||||
background-color: $menu_color;
|
||||
}
|
||||
|
||||
&.background separator {
|
||||
|
||||
@@ -82,9 +82,9 @@ assistant .sidebar label { padding: 6px 12px; }
|
||||
|
||||
assistant .sidebar label.highlight { background-color: #5a5a59; }
|
||||
|
||||
.csd popover > contents.background.touch-selection, .csd popover > contents.background.magnifier, popover > contents.background.touch-selection, popover > contents.background.magnifier, .csd popover > contents.background.osd, popover > contents.background.osd, .app-notification, .app-notification.frame, .osd .scale-popup, .osd { color: #eeeeec; border: none; background-color: rgba(38, 38, 38, 0.7); background-clip: padding-box; text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; }
|
||||
.csd popover.background > contents.touch-selection, .csd popover.background > contents.magnifier, popover.background > contents.touch-selection, popover.background > contents.magnifier, .csd popover.background > contents.osd, popover.background > contents.osd, .app-notification, .app-notification.frame, .osd .scale-popup, .osd { color: #eeeeec; border: none; background-color: rgba(37, 37, 38, 0.7); background-clip: padding-box; text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; }
|
||||
|
||||
.csd popover > contents.background.touch-selection:backdrop, .csd popover > contents.background.magnifier:backdrop, popover > contents.background.touch-selection:backdrop, popover > contents.background.magnifier:backdrop, .csd popover > contents.background.osd:backdrop, popover > contents.background.osd:backdrop, .app-notification:backdrop, .osd .scale-popup:backdrop, .osd:backdrop { text-shadow: none; -gtk-icon-shadow: none; }
|
||||
.csd popover.background > contents.touch-selection:backdrop, .csd popover.background > contents.magnifier:backdrop, popover.background > contents.touch-selection:backdrop, popover.background > contents.magnifier:backdrop, .csd popover.background > contents.osd:backdrop, popover.background > contents.osd:backdrop, .app-notification:backdrop, .osd .scale-popup:backdrop, .osd:backdrop { text-shadow: none; -gtk-icon-shadow: none; }
|
||||
|
||||
/********************* Spinner Animation * */
|
||||
@keyframes spin { to { -gtk-icon-transform: rotate(1turn); } }
|
||||
@@ -265,7 +265,7 @@ row:selected button.sidebar-button:not(:active):not(:checked):not(:hover):not(di
|
||||
|
||||
row:selected button.sidebar-button:not(:active):not(:checked):not(:hover):not(disabled):backdrop, row:selected button.flat:not(:active):not(:checked):not(:hover):not(disabled):backdrop { color: #919190; }
|
||||
|
||||
button.osd { min-width: 26px; min-height: 32px; color: #eeeeec; border-radius: 5px; color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(38, 38, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); border: none; box-shadow: none; }
|
||||
button.osd { min-width: 26px; min-height: 32px; color: #eeeeec; border-radius: 5px; color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(37, 37, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); border: none; box-shadow: none; }
|
||||
|
||||
button.osd.image-button { min-width: 34px; }
|
||||
|
||||
@@ -275,27 +275,27 @@ button.osd:active, button.osd:checked { color: white; border-color: rgba(0, 0, 0
|
||||
|
||||
button.osd:disabled:backdrop, button.osd:disabled { color: #8a8a89; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(58, 58, 57, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; border: none; }
|
||||
|
||||
button.osd:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(38, 38, 38, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; border: none; }
|
||||
button.osd:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(37, 37, 38, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; border: none; }
|
||||
|
||||
.csd popover > contents.background.touch-selection button, .csd popover > contents.background.magnifier button, popover > contents.background.touch-selection button, popover > contents.background.magnifier button, .app-notification button, .app-notification.frame button, .osd button { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(38, 38, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
.csd popover.background > contents.touch-selection button, .csd popover.background > contents.magnifier button, popover.background > contents.touch-selection button, popover.background > contents.magnifier button, .app-notification button, .app-notification.frame button, .osd button { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(37, 37, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
|
||||
.csd popover > contents.background.touch-selection button:hover, .csd popover > contents.background.magnifier button:hover, popover > contents.background.touch-selection button:hover, popover > contents.background.magnifier button:hover, .app-notification button:hover, .osd button:hover { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(68, 68, 68, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
.csd popover.background > contents.touch-selection button:hover, .csd popover.background > contents.magnifier button:hover, popover.background > contents.touch-selection button:hover, popover.background > contents.magnifier button:hover, .app-notification button:hover, .osd button:hover { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(68, 68, 68, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
|
||||
.csd popover > contents.background.touch-selection button:active:backdrop, .csd popover > contents.background.magnifier button:active:backdrop, popover > contents.background.touch-selection button:active:backdrop, popover > contents.background.magnifier button:active:backdrop, .app-notification button:active:backdrop, .csd popover > contents.background.touch-selection button:active, .csd popover > contents.background.magnifier button:active, popover > contents.background.touch-selection button:active, popover > contents.background.magnifier button:active, .app-notification button:active, .csd popover > contents.background.touch-selection button:checked:backdrop, .csd popover > contents.background.magnifier button:checked:backdrop, popover > contents.background.touch-selection button:checked:backdrop, popover > contents.background.magnifier button:checked:backdrop, .app-notification button:checked:backdrop, .csd popover > contents.background.touch-selection button:checked, .csd popover > contents.background.magnifier button:checked, popover > contents.background.touch-selection button:checked, popover > contents.background.magnifier button:checked, .app-notification button:checked, .osd button:active:backdrop, .osd button:active, .osd button:checked:backdrop, .osd button:checked { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(0, 0, 0, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
.csd popover.background > contents.touch-selection button:active:backdrop, .csd popover.background > contents.magnifier button:active:backdrop, popover.background > contents.touch-selection button:active:backdrop, popover.background > contents.magnifier button:active:backdrop, .app-notification button:active:backdrop, .csd popover.background > contents.touch-selection button:active, .csd popover.background > contents.magnifier button:active, popover.background > contents.touch-selection button:active, popover.background > contents.magnifier button:active, .app-notification button:active, .csd popover.background > contents.touch-selection button:checked:backdrop, .csd popover.background > contents.magnifier button:checked:backdrop, popover.background > contents.touch-selection button:checked:backdrop, popover.background > contents.magnifier button:checked:backdrop, .app-notification button:checked:backdrop, .csd popover.background > contents.touch-selection button:checked, .csd popover.background > contents.magnifier button:checked, popover.background > contents.touch-selection button:checked, popover.background > contents.magnifier button:checked, .app-notification button:checked, .osd button:active:backdrop, .osd button:active, .osd button:checked:backdrop, .osd button:checked { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(0, 0, 0, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
|
||||
.csd popover > contents.background.touch-selection button:disabled:backdrop, .csd popover > contents.background.magnifier button:disabled:backdrop, popover > contents.background.touch-selection button:disabled:backdrop, popover > contents.background.magnifier button:disabled:backdrop, .app-notification button:disabled:backdrop, .csd popover > contents.background.touch-selection button:disabled, .csd popover > contents.background.magnifier button:disabled, popover > contents.background.touch-selection button:disabled, popover > contents.background.magnifier button:disabled, .app-notification button:disabled, .osd button:disabled:backdrop, .osd button:disabled { color: #8a8a89; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(58, 58, 57, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
|
||||
.csd popover.background > contents.touch-selection button:disabled:backdrop, .csd popover.background > contents.magnifier button:disabled:backdrop, popover.background > contents.touch-selection button:disabled:backdrop, popover.background > contents.magnifier button:disabled:backdrop, .app-notification button:disabled:backdrop, .csd popover.background > contents.touch-selection button:disabled, .csd popover.background > contents.magnifier button:disabled, popover.background > contents.touch-selection button:disabled, popover.background > contents.magnifier button:disabled, .app-notification button:disabled, .osd button:disabled:backdrop, .osd button:disabled { color: #8a8a89; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(58, 58, 57, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
|
||||
|
||||
.csd popover > contents.background.touch-selection button:backdrop, .csd popover > contents.background.magnifier button:backdrop, popover > contents.background.touch-selection button:backdrop, popover > contents.background.magnifier button:backdrop, .app-notification button:backdrop, .osd button:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(38, 38, 38, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
|
||||
.csd popover.background > contents.touch-selection button:backdrop, .csd popover.background > contents.magnifier button:backdrop, popover.background > contents.touch-selection button:backdrop, popover.background > contents.magnifier button:backdrop, .app-notification button:backdrop, .osd button:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(37, 37, 38, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
|
||||
|
||||
.csd popover > contents.background.touch-selection button.flat, .csd popover > contents.background.magnifier button.flat, popover > contents.background.touch-selection button.flat, popover > contents.background.magnifier button.flat, .app-notification button.flat, .osd button.flat { border-color: transparent; background-color: transparent; background-image: none; box-shadow: inset 0 1px rgba(255, 255, 255, 0); text-shadow: none; -gtk-icon-shadow: none; box-shadow: none; text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; }
|
||||
.csd popover.background > contents.touch-selection button.flat, .csd popover.background > contents.magnifier button.flat, popover.background > contents.touch-selection button.flat, popover.background > contents.magnifier button.flat, .app-notification button.flat, .osd button.flat { border-color: transparent; background-color: transparent; background-image: none; box-shadow: inset 0 1px rgba(255, 255, 255, 0); text-shadow: none; -gtk-icon-shadow: none; box-shadow: none; text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; }
|
||||
|
||||
.csd popover > contents.background.touch-selection button.flat:hover, .csd popover > contents.background.magnifier button.flat:hover, popover > contents.background.touch-selection button.flat:hover, popover > contents.background.magnifier button.flat:hover, .app-notification button.flat:hover, .osd button.flat:hover { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(68, 68, 68, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
.csd popover.background > contents.touch-selection button.flat:hover, .csd popover.background > contents.magnifier button.flat:hover, popover.background > contents.touch-selection button.flat:hover, popover.background > contents.magnifier button.flat:hover, .app-notification button.flat:hover, .osd button.flat:hover { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(68, 68, 68, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
|
||||
.csd popover > contents.background.touch-selection button.flat:disabled, .csd popover > contents.background.magnifier button.flat:disabled, popover > contents.background.touch-selection button.flat:disabled, popover > contents.background.magnifier button.flat:disabled, .app-notification button.flat:disabled, .osd button.flat:disabled { color: #8a8a89; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(58, 58, 57, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; background-image: none; border-color: transparent; box-shadow: none; }
|
||||
.csd popover.background > contents.touch-selection button.flat:disabled, .csd popover.background > contents.magnifier button.flat:disabled, popover.background > contents.touch-selection button.flat:disabled, popover.background > contents.magnifier button.flat:disabled, .app-notification button.flat:disabled, .osd button.flat:disabled { color: #8a8a89; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(58, 58, 57, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; background-image: none; border-color: transparent; box-shadow: none; }
|
||||
|
||||
.csd popover > contents.background.touch-selection button.flat:backdrop, .csd popover > contents.background.magnifier button.flat:backdrop, popover > contents.background.touch-selection button.flat:backdrop, popover > contents.background.magnifier button.flat:backdrop, .app-notification button.flat:backdrop, .osd button.flat:backdrop { border-color: transparent; background-color: transparent; background-image: none; box-shadow: inset 0 1px rgba(255, 255, 255, 0); text-shadow: none; -gtk-icon-shadow: none; }
|
||||
.csd popover.background > contents.touch-selection button.flat:backdrop, .csd popover.background > contents.magnifier button.flat:backdrop, popover.background > contents.touch-selection button.flat:backdrop, popover.background > contents.magnifier button.flat:backdrop, .app-notification button.flat:backdrop, .osd button.flat:backdrop { border-color: transparent; background-color: transparent; background-image: none; box-shadow: inset 0 1px rgba(255, 255, 255, 0); text-shadow: none; -gtk-icon-shadow: none; }
|
||||
|
||||
.csd popover > contents.background.touch-selection button.flat:active, .csd popover > contents.background.magnifier button.flat:active, popover > contents.background.touch-selection button.flat:active, popover > contents.background.magnifier button.flat:active, .app-notification button.flat:active, .csd popover > contents.background.touch-selection button.flat:checked, .csd popover > contents.background.magnifier button.flat:checked, popover > contents.background.touch-selection button.flat:checked, popover > contents.background.magnifier button.flat:checked, .app-notification button.flat:checked, .osd button.flat:active, .osd button.flat:checked { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(0, 0, 0, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
.csd popover.background > contents.touch-selection button.flat:active, .csd popover.background > contents.magnifier button.flat:active, popover.background > contents.touch-selection button.flat:active, popover.background > contents.magnifier button.flat:active, .app-notification button.flat:active, .csd popover.background > contents.touch-selection button.flat:checked, .csd popover.background > contents.magnifier button.flat:checked, popover.background > contents.touch-selection button.flat:checked, popover.background > contents.magnifier button.flat:checked, .app-notification button.flat:checked, .osd button.flat:active, .osd button.flat:checked { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(0, 0, 0, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
|
||||
button.suggested-action { color: white; outline-color: rgba(255, 255, 255, 0.3); border-color: #0f3b71; border-bottom-color: #092444; background-image: linear-gradient(to top, #155099 2px, #15539e); text-shadow: 0 -1px rgba(0, 0, 0, 0.719216); -gtk-icon-shadow: 0 -1px rgba(0, 0, 0, 0.719216); box-shadow: inset 0 1px rgba(255, 255, 255, 0.02), 0 1px 2px rgba(0, 0, 0, 0.07); }
|
||||
|
||||
@@ -497,7 +497,7 @@ button:link > label:active, button:visited > label:active, *:link:active, button
|
||||
|
||||
*:selected button:link > label:active, *:selected button:visited > label:active, *:selected *:link:active, *:selected button:active:link, *:selected button:active:visited { color: #d0ddec; }
|
||||
|
||||
button:link > label:disabled, button:visited > label:disabled, button:link > label:disabled:backdrop, button:visited > label:disabled:backdrop, *:link:disabled, button:disabled:link, button:disabled:visited, *:link:disabled:backdrop, button:disabled:backdrop:link, button:disabled:backdrop:visited { color: rgba(141, 141, 141, 0.8); }
|
||||
button:link > label:disabled, button:visited > label:disabled, button:link > label:disabled:backdrop, button:visited > label:disabled:backdrop, *:link:disabled, button:disabled:link, button:disabled:visited, *:link:disabled:backdrop, button:disabled:backdrop:link, button:disabled:backdrop:visited { color: rgba(140, 140, 141, 0.8); }
|
||||
|
||||
button:link > label:backdrop:backdrop:hover, button:visited > label:backdrop:backdrop:hover, button:link > label:backdrop:backdrop:hover:selected, button:visited > label:backdrop:backdrop:hover:selected, button:link > label:backdrop, button:visited > label:backdrop, *:link:backdrop:backdrop:hover, button:backdrop:backdrop:hover:link, button:backdrop:backdrop:hover:visited, *:link:backdrop:backdrop:hover:selected, button:backdrop:backdrop:hover:selected:link, button:backdrop:backdrop:hover:selected:visited, .selection-mode .titlebar:not(headerbar) .subtitle:backdrop:backdrop:hover:link, .selection-mode.titlebar:not(headerbar) .subtitle:backdrop:backdrop:hover:link, .selection-mode headerbar .subtitle:backdrop:backdrop:hover:link, headerbar.selection-mode .subtitle:backdrop:backdrop:hover:link, *:link:backdrop, button:backdrop:link, button:backdrop:visited { color: #15539e; }
|
||||
|
||||
@@ -564,7 +564,7 @@ spinbutton.vertical button.up { border-bottom-style: none; border-bottom-left-ra
|
||||
|
||||
spinbutton.vertical button.down { border-top-style: none; border-top-left-radius: 0; border-top-right-radius: 0; }
|
||||
|
||||
.osd spinbutton.vertical button:first-child { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(38, 38, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
.osd spinbutton.vertical button:first-child { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(37, 37, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
|
||||
.osd spinbutton.vertical button:first-child:hover { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(68, 68, 68, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
|
||||
@@ -572,7 +572,7 @@ spinbutton.vertical button.down { border-top-style: none; border-top-left-radius
|
||||
|
||||
.osd spinbutton.vertical button:first-child:disabled { color: #8a8a89; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(58, 58, 57, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
|
||||
|
||||
.osd spinbutton.vertical button:first-child:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(38, 38, 38, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
|
||||
.osd spinbutton.vertical button:first-child:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(37, 37, 38, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
|
||||
|
||||
treeview spinbutton:not(.vertical) { min-height: 0; border-style: none; border-radius: 0; }
|
||||
|
||||
@@ -590,7 +590,7 @@ toolbar { padding: 4px 3px 3px 4px; }
|
||||
|
||||
.osd toolbar { background-color: transparent; }
|
||||
|
||||
toolbar.osd { padding: 13px; border: none; border-radius: 5px; background-color: rgba(38, 38, 38, 0.7); }
|
||||
toolbar.osd { padding: 13px; border: none; border-radius: 5px; background-color: rgba(37, 37, 38, 0.7); }
|
||||
|
||||
toolbar.osd.left, toolbar.osd.right, toolbar.osd.top, toolbar.osd.bottom { border-radius: 0; }
|
||||
|
||||
@@ -613,7 +613,7 @@ searchbar > revealer > box { padding: 6px; border-width: 0 0 1px; }
|
||||
.inline-toolbar:backdrop, .location-bar:backdrop, searchbar > revealer > box:backdrop { border-color: #202020; background-color: #2e2e2e; box-shadow: none; transition: 200ms ease-out; }
|
||||
|
||||
/*************** Header bars * */
|
||||
.titlebar:not(headerbar), headerbar { padding: 0 6px; min-height: 46px; border-width: 0 0 1px; border-style: solid; border-color: #070707; border-radius: 0; background: #1b1b1b linear-gradient(to top, #262626, #2b2b2b); box-shadow: inset 0 1px rgba(238, 238, 236, 0.07); /* Darken switchbuttons for headerbars. issue #1588 */ /* hide the close button separator */ }
|
||||
.titlebar:not(headerbar), headerbar { padding: 0 6px; min-height: 46px; border-width: 0 0 1px; border-style: solid; border-color: #070707; border-radius: 0; background: #1b1b1b linear-gradient(to top, #252526, #2b2b2b); box-shadow: inset 0 1px rgba(238, 238, 236, 0.07); /* Darken switchbuttons for headerbars. issue #1588 */ /* hide the close button separator */ }
|
||||
|
||||
.titlebar:backdrop:not(headerbar), headerbar:backdrop { border-color: #202020; background-color: #353535; background-image: none; box-shadow: inset 0 1px rgba(238, 238, 236, 0.07); transition: 200ms ease-out; }
|
||||
|
||||
@@ -879,19 +879,19 @@ popover.menu > arrow, popover > arrow { background-color: #353535; border: 1px s
|
||||
|
||||
popover > contents { padding: 8px; background-color: #353535; border: 1px solid #1b1b1b; margin: 0px; }
|
||||
|
||||
popover > contents.background { background-color: #353535; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); }
|
||||
popover.background > contents { background-color: #353535; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); }
|
||||
|
||||
.csd popover > contents.background, popover > contents.background { border: 1px solid #1b1b1b; border-radius: 9px; }
|
||||
.csd popover.background > contents, popover.background > contents { border: 1px solid #1b1b1b; border-radius: 9px; }
|
||||
|
||||
popover > contents.background:backdrop { background-color: #353535; box-shadow: none; }
|
||||
popover.background > contents:backdrop { background-color: #353535; box-shadow: none; }
|
||||
|
||||
popover > contents.background > list, popover > contents.background > .view, popover > contents.background > iconview, popover > contents.background > toolbar { border-style: none; background-color: transparent; }
|
||||
popover.background > contents > list, popover.background > contents > .view, popover.background > contents > iconview, popover.background > contents > toolbar { border-style: none; background-color: transparent; }
|
||||
|
||||
.csd popover > contents.background.touch-selection, .csd popover > contents.background.magnifier, popover > contents.background.touch-selection, popover > contents.background.magnifier { border: 1px solid rgba(255, 255, 255, 0.1); }
|
||||
.csd popover.background > contents.touch-selection, .csd popover.background > contents.magnifier, popover.background > contents.touch-selection, popover.background > contents.magnifier { border: 1px solid rgba(255, 255, 255, 0.1); }
|
||||
|
||||
popover > contents.background separator { margin: 3px; }
|
||||
popover.background > contents separator { margin: 3px; }
|
||||
|
||||
popover > contents.background list separator { margin: 0px; }
|
||||
popover.background > contents list separator { margin: 0px; }
|
||||
|
||||
/************* Notebooks * */
|
||||
notebook box > header { padding: 1px; border-color: #1b1b1b; border-width: 1px; background-color: #282828; }
|
||||
@@ -1141,7 +1141,7 @@ switch:backdrop:disabled slider label, switch:backdrop:disabled slider { color:
|
||||
|
||||
.view.content-view.check:active:not(list), iconview.content-view.check:active:not(list), .content-view .tile check:active:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: transparent; background-color: rgba(21, 83, 158, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: none; -gtk-icon-shadow: none; }
|
||||
|
||||
.view.content-view.check:backdrop:not(list), iconview.content-view.check:backdrop:not(list), .content-view .tile check:backdrop:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: transparent; background-color: rgba(90, 90, 90, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: none; -gtk-icon-shadow: none; }
|
||||
.view.content-view.check:backdrop:not(list), iconview.content-view.check:backdrop:not(list), .content-view .tile check:backdrop:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: transparent; background-color: rgba(89, 89, 90, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: none; -gtk-icon-shadow: none; }
|
||||
|
||||
.view.content-view.check:checked:not(list), iconview.content-view.check:checked:not(list), .content-view .tile check:checked:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: #eeeeec; background-color: rgba(21, 83, 158, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: -gtk-icontheme('object-select-symbolic'); -gtk-icon-shadow: none; }
|
||||
|
||||
@@ -1149,7 +1149,7 @@ switch:backdrop:disabled slider label, switch:backdrop:disabled slider { color:
|
||||
|
||||
.view.content-view.check:checked:active:not(list), iconview.content-view.check:checked:active:not(list), .content-view .tile check:checked:active:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: #eeeeec; background-color: rgba(21, 83, 158, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: -gtk-icontheme('object-select-symbolic'); -gtk-icon-shadow: none; }
|
||||
|
||||
.view.content-view.check:backdrop:checked:not(list), iconview.content-view.check:backdrop:checked:not(list), .content-view .tile check:backdrop:checked:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: rgba(238, 238, 236, 0.8); background-color: rgba(90, 90, 90, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: -gtk-icontheme('object-select-symbolic'); -gtk-icon-shadow: none; }
|
||||
.view.content-view.check:backdrop:checked:not(list), iconview.content-view.check:backdrop:checked:not(list), .content-view .tile check:backdrop:checked:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: rgba(238, 238, 236, 0.8); background-color: rgba(89, 89, 90, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: -gtk-icontheme('object-select-symbolic'); -gtk-icon-shadow: none; }
|
||||
|
||||
checkbutton.text-button, radiobutton.text-button { padding: 2px 0; outline-offset: 0; }
|
||||
|
||||
@@ -1157,7 +1157,7 @@ checkbutton.text-button label:not(:only-child):first-child, radiobutton.text-but
|
||||
|
||||
checkbutton.text-button label:not(:only-child):last-child, radiobutton.text-button label:not(:only-child):last-child { margin-right: 4px; }
|
||||
|
||||
check, radio { margin: 0 4px; min-height: 14px; min-width: 14px; border: 1px solid; -gtk-icon-source: none; color: #eeeeec; outline-color: rgba(238, 238, 236, 0.3); border-color: #070707; text-shadow: 0 -1px rgba(0, 0, 0, 0.834353); -gtk-icon-shadow: 0 -1px rgba(0, 0, 0, 0.834353); background-image: linear-gradient(to bottom, #2d2d2d 20%, #262626 90%); box-shadow: inset 0 1px rgba(255, 255, 255, 0.02), 0 1px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.07); }
|
||||
check, radio { margin: 0 4px; min-height: 14px; min-width: 14px; border: 1px solid; -gtk-icon-source: none; color: #eeeeec; outline-color: rgba(238, 238, 236, 0.3); border-color: #070707; text-shadow: 0 -1px rgba(0, 0, 0, 0.834353); -gtk-icon-shadow: 0 -1px rgba(0, 0, 0, 0.834353); background-image: linear-gradient(to bottom, #2d2d2d 20%, #252526 90%); box-shadow: inset 0 1px rgba(255, 255, 255, 0.02), 0 1px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.07); }
|
||||
|
||||
check:only-child, radio:only-child { margin: 0; }
|
||||
|
||||
@@ -1181,13 +1181,13 @@ check:backdrop:disabled, radio:backdrop:disabled { border-color: #202020; backgr
|
||||
|
||||
check:backdrop:disabled label, check:backdrop:disabled, radio:backdrop:disabled label, radio:backdrop:disabled { color: #5b5b5b; }
|
||||
|
||||
.osd check, .osd radio { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(38, 38, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
.osd check, .osd radio { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(37, 37, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
|
||||
.osd check:hover, .osd radio:hover { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(38, 38, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
.osd check:hover, .osd radio:hover { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(37, 37, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
|
||||
.osd check:active, .osd radio:active { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(0, 0, 0, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
|
||||
.osd check:backdrop, .osd radio:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(38, 38, 38, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
|
||||
.osd check:backdrop, .osd radio:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(37, 37, 38, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
|
||||
|
||||
.osd check:disabled, .osd radio:disabled { color: #8a8a89; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(58, 58, 57, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
|
||||
|
||||
@@ -1280,7 +1280,7 @@ scale fill:disabled:backdrop, scale fill:disabled { border-color: transparent; b
|
||||
|
||||
.osd scale fill:disabled:backdrop, .osd scale fill:disabled { border-color: transparent; background-color: transparent; }
|
||||
|
||||
scale slider { color: #eeeeec; outline-color: rgba(238, 238, 236, 0.3); border-color: #070707; text-shadow: 0 -1px rgba(0, 0, 0, 0.834353); -gtk-icon-shadow: 0 -1px rgba(0, 0, 0, 0.834353); background-image: linear-gradient(to bottom, #2d2d2d 20%, #262626 90%); box-shadow: inset 0 1px rgba(255, 255, 255, 0.02), 0 1px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.07); border: 1px solid black; border-radius: 100%; transition: all 200ms cubic-bezier(0.25, 0.46, 0.45, 0.94); transition-property: background, border, box-shadow; }
|
||||
scale slider { color: #eeeeec; outline-color: rgba(238, 238, 236, 0.3); border-color: #070707; text-shadow: 0 -1px rgba(0, 0, 0, 0.834353); -gtk-icon-shadow: 0 -1px rgba(0, 0, 0, 0.834353); background-image: linear-gradient(to bottom, #2d2d2d 20%, #252526 90%); box-shadow: inset 0 1px rgba(255, 255, 255, 0.02), 0 1px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.07); border: 1px solid black; border-radius: 100%; transition: all 200ms cubic-bezier(0.25, 0.46, 0.45, 0.94); transition-property: background, border, box-shadow; }
|
||||
|
||||
scale slider:hover { color: #eeeeec; outline-color: rgba(238, 238, 236, 0.3); border-color: #070707; box-shadow: inset 0 1px rgba(255, 255, 255, 0.02), 0 1px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.07); background-image: linear-gradient(to bottom, #353535 20%, #2b2b2b 90%); }
|
||||
|
||||
@@ -1300,17 +1300,17 @@ scale slider:backdrop:disabled label, scale slider:backdrop:disabled { color: #5
|
||||
|
||||
row:selected scale slider:disabled, row:selected scale slider { border-color: #030c17; }
|
||||
|
||||
.osd scale slider { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(38, 38, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); border-color: rgba(0, 0, 0, 0.7); background-color: #262626; }
|
||||
.osd scale slider { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(37, 37, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); border-color: rgba(0, 0, 0, 0.7); background-color: #252526; }
|
||||
|
||||
.osd scale slider:hover { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(68, 68, 68, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); background-color: #262626; }
|
||||
.osd scale slider:hover { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(68, 68, 68, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); background-color: #252526; }
|
||||
|
||||
.osd scale slider:active { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(0, 0, 0, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; outline-color: rgba(238, 238, 236, 0.3); background-color: #262626; }
|
||||
.osd scale slider:active { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(0, 0, 0, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; outline-color: rgba(238, 238, 236, 0.3); background-color: #252526; }
|
||||
|
||||
.osd scale slider:disabled { color: #8a8a89; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(58, 58, 57, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; background-color: #262626; }
|
||||
.osd scale slider:disabled { color: #8a8a89; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(58, 58, 57, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; background-color: #252526; }
|
||||
|
||||
.osd scale slider:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(38, 38, 38, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; background-color: #262626; }
|
||||
.osd scale slider:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(37, 37, 38, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; background-color: #252526; }
|
||||
|
||||
.osd scale slider:backdrop:disabled { background-color: #262626; }
|
||||
.osd scale slider:backdrop:disabled { background-color: #252526; }
|
||||
|
||||
scale value { color: alpha(currentColor,0.55); }
|
||||
|
||||
@@ -1636,7 +1636,7 @@ row.activatable:selected.has-open-popup, row.activatable:selected:hover { backgr
|
||||
row.activatable:selected:backdrop { background-color: #15539e; }
|
||||
|
||||
/********************* App Notifications * */
|
||||
.app-notification, .app-notification.frame { padding: 10px; border-radius: 0 0 5px 5px; background-color: rgba(38, 38, 38, 0.7); background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.2), transparent 2px); background-clip: padding-box; }
|
||||
.app-notification, .app-notification.frame { padding: 10px; border-radius: 0 0 5px 5px; background-color: rgba(37, 37, 38, 0.7); background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.2), transparent 2px); background-clip: padding-box; }
|
||||
|
||||
.app-notification:backdrop, .app-notification.frame:backdrop { background-image: none; transition: 200ms ease-out; }
|
||||
|
||||
@@ -2063,7 +2063,7 @@ popover.menu box.inline-buttons { border-radius: 5px; border-style: none; border
|
||||
|
||||
popover.menu box.circular-buttons { padding-bottom: 5px; }
|
||||
|
||||
popover.menu.background contents { background: white; }
|
||||
popover.menu arrow, popover.menu.background contents { background-color: #2f2f2f; }
|
||||
|
||||
popover.menu.background separator { margin: 5px 0px; }
|
||||
|
||||
|
||||
@@ -82,9 +82,9 @@ assistant .sidebar label { padding: 6px 12px; }
|
||||
|
||||
assistant .sidebar label.highlight { background-color: #cecece; }
|
||||
|
||||
.csd popover > contents.background.touch-selection, .csd popover > contents.background.magnifier, popover > contents.background.touch-selection, popover > contents.background.magnifier, .csd popover > contents.background.osd, popover > contents.background.osd, .app-notification, .app-notification.frame, .osd .scale-popup, .osd { color: #eeeeec; border: none; background-color: rgba(53, 53, 53, 0.7); background-clip: padding-box; text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; }
|
||||
.csd popover.background > contents.touch-selection, .csd popover.background > contents.magnifier, popover.background > contents.touch-selection, popover.background > contents.magnifier, .csd popover.background > contents.osd, popover.background > contents.osd, .app-notification, .app-notification.frame, .osd .scale-popup, .osd { color: #eeeeec; border: none; background-color: rgba(53, 53, 53, 0.7); background-clip: padding-box; text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; }
|
||||
|
||||
.csd popover > contents.background.touch-selection:backdrop, .csd popover > contents.background.magnifier:backdrop, popover > contents.background.touch-selection:backdrop, popover > contents.background.magnifier:backdrop, .csd popover > contents.background.osd:backdrop, popover > contents.background.osd:backdrop, .app-notification:backdrop, .osd .scale-popup:backdrop, .osd:backdrop { text-shadow: none; -gtk-icon-shadow: none; }
|
||||
.csd popover.background > contents.touch-selection:backdrop, .csd popover.background > contents.magnifier:backdrop, popover.background > contents.touch-selection:backdrop, popover.background > contents.magnifier:backdrop, .csd popover.background > contents.osd:backdrop, popover.background > contents.osd:backdrop, .app-notification:backdrop, .osd .scale-popup:backdrop, .osd:backdrop { text-shadow: none; -gtk-icon-shadow: none; }
|
||||
|
||||
/********************* Spinner Animation * */
|
||||
@keyframes spin { to { -gtk-icon-transform: rotate(1turn); } }
|
||||
@@ -279,25 +279,25 @@ button.osd:disabled:backdrop, button.osd:disabled { color: #919190; border-color
|
||||
|
||||
button.osd:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(53, 53, 53, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; border: none; }
|
||||
|
||||
.csd popover > contents.background.touch-selection button, .csd popover > contents.background.magnifier button, popover > contents.background.touch-selection button, popover > contents.background.magnifier button, .app-notification button, .app-notification.frame button, .osd button { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(53, 53, 53, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
.csd popover.background > contents.touch-selection button, .csd popover.background > contents.magnifier button, popover.background > contents.touch-selection button, popover.background > contents.magnifier button, .app-notification button, .app-notification.frame button, .osd button { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(53, 53, 53, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
|
||||
.csd popover > contents.background.touch-selection button:hover, .csd popover > contents.background.magnifier button:hover, popover > contents.background.touch-selection button:hover, popover > contents.background.magnifier button:hover, .app-notification button:hover, .osd button:hover { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(83, 83, 83, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
.csd popover.background > contents.touch-selection button:hover, .csd popover.background > contents.magnifier button:hover, popover.background > contents.touch-selection button:hover, popover.background > contents.magnifier button:hover, .app-notification button:hover, .osd button:hover { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(83, 83, 83, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
|
||||
.csd popover > contents.background.touch-selection button:active:backdrop, .csd popover > contents.background.magnifier button:active:backdrop, popover > contents.background.touch-selection button:active:backdrop, popover > contents.background.magnifier button:active:backdrop, .app-notification button:active:backdrop, .csd popover > contents.background.touch-selection button:active, .csd popover > contents.background.magnifier button:active, popover > contents.background.touch-selection button:active, popover > contents.background.magnifier button:active, .app-notification button:active, .csd popover > contents.background.touch-selection button:checked:backdrop, .csd popover > contents.background.magnifier button:checked:backdrop, popover > contents.background.touch-selection button:checked:backdrop, popover > contents.background.magnifier button:checked:backdrop, .app-notification button:checked:backdrop, .csd popover > contents.background.touch-selection button:checked, .csd popover > contents.background.magnifier button:checked, popover > contents.background.touch-selection button:checked, popover > contents.background.magnifier button:checked, .app-notification button:checked, .osd button:active:backdrop, .osd button:active, .osd button:checked:backdrop, .osd button:checked { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(0, 0, 0, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
.csd popover.background > contents.touch-selection button:active:backdrop, .csd popover.background > contents.magnifier button:active:backdrop, popover.background > contents.touch-selection button:active:backdrop, popover.background > contents.magnifier button:active:backdrop, .app-notification button:active:backdrop, .csd popover.background > contents.touch-selection button:active, .csd popover.background > contents.magnifier button:active, popover.background > contents.touch-selection button:active, popover.background > contents.magnifier button:active, .app-notification button:active, .csd popover.background > contents.touch-selection button:checked:backdrop, .csd popover.background > contents.magnifier button:checked:backdrop, popover.background > contents.touch-selection button:checked:backdrop, popover.background > contents.magnifier button:checked:backdrop, .app-notification button:checked:backdrop, .csd popover.background > contents.touch-selection button:checked, .csd popover.background > contents.magnifier button:checked, popover.background > contents.touch-selection button:checked, popover.background > contents.magnifier button:checked, .app-notification button:checked, .osd button:active:backdrop, .osd button:active, .osd button:checked:backdrop, .osd button:checked { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(0, 0, 0, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
|
||||
.csd popover > contents.background.touch-selection button:disabled:backdrop, .csd popover > contents.background.magnifier button:disabled:backdrop, popover > contents.background.touch-selection button:disabled:backdrop, popover > contents.background.magnifier button:disabled:backdrop, .app-notification button:disabled:backdrop, .csd popover > contents.background.touch-selection button:disabled, .csd popover > contents.background.magnifier button:disabled, popover > contents.background.touch-selection button:disabled, popover > contents.background.magnifier button:disabled, .app-notification button:disabled, .osd button:disabled:backdrop, .osd button:disabled { color: #919190; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(71, 71, 71, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
|
||||
.csd popover.background > contents.touch-selection button:disabled:backdrop, .csd popover.background > contents.magnifier button:disabled:backdrop, popover.background > contents.touch-selection button:disabled:backdrop, popover.background > contents.magnifier button:disabled:backdrop, .app-notification button:disabled:backdrop, .csd popover.background > contents.touch-selection button:disabled, .csd popover.background > contents.magnifier button:disabled, popover.background > contents.touch-selection button:disabled, popover.background > contents.magnifier button:disabled, .app-notification button:disabled, .osd button:disabled:backdrop, .osd button:disabled { color: #919190; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(71, 71, 71, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
|
||||
|
||||
.csd popover > contents.background.touch-selection button:backdrop, .csd popover > contents.background.magnifier button:backdrop, popover > contents.background.touch-selection button:backdrop, popover > contents.background.magnifier button:backdrop, .app-notification button:backdrop, .osd button:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(53, 53, 53, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
|
||||
.csd popover.background > contents.touch-selection button:backdrop, .csd popover.background > contents.magnifier button:backdrop, popover.background > contents.touch-selection button:backdrop, popover.background > contents.magnifier button:backdrop, .app-notification button:backdrop, .osd button:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(53, 53, 53, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
|
||||
|
||||
.csd popover > contents.background.touch-selection button.flat, .csd popover > contents.background.magnifier button.flat, popover > contents.background.touch-selection button.flat, popover > contents.background.magnifier button.flat, .app-notification button.flat, .osd button.flat { border-color: transparent; background-color: transparent; background-image: none; box-shadow: inset 0 1px rgba(255, 255, 255, 0); text-shadow: none; -gtk-icon-shadow: none; box-shadow: none; text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; }
|
||||
.csd popover.background > contents.touch-selection button.flat, .csd popover.background > contents.magnifier button.flat, popover.background > contents.touch-selection button.flat, popover.background > contents.magnifier button.flat, .app-notification button.flat, .osd button.flat { border-color: transparent; background-color: transparent; background-image: none; box-shadow: inset 0 1px rgba(255, 255, 255, 0); text-shadow: none; -gtk-icon-shadow: none; box-shadow: none; text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; }
|
||||
|
||||
.csd popover > contents.background.touch-selection button.flat:hover, .csd popover > contents.background.magnifier button.flat:hover, popover > contents.background.touch-selection button.flat:hover, popover > contents.background.magnifier button.flat:hover, .app-notification button.flat:hover, .osd button.flat:hover { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(83, 83, 83, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
.csd popover.background > contents.touch-selection button.flat:hover, .csd popover.background > contents.magnifier button.flat:hover, popover.background > contents.touch-selection button.flat:hover, popover.background > contents.magnifier button.flat:hover, .app-notification button.flat:hover, .osd button.flat:hover { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(83, 83, 83, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
|
||||
.csd popover > contents.background.touch-selection button.flat:disabled, .csd popover > contents.background.magnifier button.flat:disabled, popover > contents.background.touch-selection button.flat:disabled, popover > contents.background.magnifier button.flat:disabled, .app-notification button.flat:disabled, .osd button.flat:disabled { color: #919190; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(71, 71, 71, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; background-image: none; border-color: transparent; box-shadow: none; }
|
||||
.csd popover.background > contents.touch-selection button.flat:disabled, .csd popover.background > contents.magnifier button.flat:disabled, popover.background > contents.touch-selection button.flat:disabled, popover.background > contents.magnifier button.flat:disabled, .app-notification button.flat:disabled, .osd button.flat:disabled { color: #919190; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(71, 71, 71, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; background-image: none; border-color: transparent; box-shadow: none; }
|
||||
|
||||
.csd popover > contents.background.touch-selection button.flat:backdrop, .csd popover > contents.background.magnifier button.flat:backdrop, popover > contents.background.touch-selection button.flat:backdrop, popover > contents.background.magnifier button.flat:backdrop, .app-notification button.flat:backdrop, .osd button.flat:backdrop { border-color: transparent; background-color: transparent; background-image: none; box-shadow: inset 0 1px rgba(255, 255, 255, 0); text-shadow: none; -gtk-icon-shadow: none; }
|
||||
.csd popover.background > contents.touch-selection button.flat:backdrop, .csd popover.background > contents.magnifier button.flat:backdrop, popover.background > contents.touch-selection button.flat:backdrop, popover.background > contents.magnifier button.flat:backdrop, .app-notification button.flat:backdrop, .osd button.flat:backdrop { border-color: transparent; background-color: transparent; background-image: none; box-shadow: inset 0 1px rgba(255, 255, 255, 0); text-shadow: none; -gtk-icon-shadow: none; }
|
||||
|
||||
.csd popover > contents.background.touch-selection button.flat:active, .csd popover > contents.background.magnifier button.flat:active, popover > contents.background.touch-selection button.flat:active, popover > contents.background.magnifier button.flat:active, .app-notification button.flat:active, .csd popover > contents.background.touch-selection button.flat:checked, .csd popover > contents.background.magnifier button.flat:checked, popover > contents.background.touch-selection button.flat:checked, popover > contents.background.magnifier button.flat:checked, .app-notification button.flat:checked, .osd button.flat:active, .osd button.flat:checked { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(0, 0, 0, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
.csd popover.background > contents.touch-selection button.flat:active, .csd popover.background > contents.magnifier button.flat:active, popover.background > contents.touch-selection button.flat:active, popover.background > contents.magnifier button.flat:active, .app-notification button.flat:active, .csd popover.background > contents.touch-selection button.flat:checked, .csd popover.background > contents.magnifier button.flat:checked, popover.background > contents.touch-selection button.flat:checked, popover.background > contents.magnifier button.flat:checked, .app-notification button.flat:checked, .osd button.flat:active, .osd button.flat:checked { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(0, 0, 0, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; outline-color: rgba(238, 238, 236, 0.3); }
|
||||
|
||||
button.suggested-action { color: white; outline-color: rgba(255, 255, 255, 0.3); border-color: #1b6acb; border-bottom-color: #15539e; background-image: linear-gradient(to top, #2379e2 2px, #3584e4); text-shadow: 0 -1px rgba(0, 0, 0, 0.559216); -gtk-icon-shadow: 0 -1px rgba(0, 0, 0, 0.559216); box-shadow: inset 0 1px rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.07); }
|
||||
|
||||
@@ -887,19 +887,19 @@ popover.menu > arrow, popover > arrow { background-color: #f6f5f4; border: 1px s
|
||||
|
||||
popover > contents { padding: 8px; background-color: #f6f5f4; border: 1px solid #cdc7c2; margin: 0px; }
|
||||
|
||||
popover > contents.background { background-color: #f6f5f4; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); }
|
||||
popover.background > contents { background-color: #f6f5f4; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); }
|
||||
|
||||
.csd popover > contents.background, popover > contents.background { border: 1px solid #cdc7c2; border-radius: 9px; }
|
||||
.csd popover.background > contents, popover.background > contents { border: 1px solid #cdc7c2; border-radius: 9px; }
|
||||
|
||||
popover > contents.background:backdrop { background-color: #f6f5f4; box-shadow: none; }
|
||||
popover.background > contents:backdrop { background-color: #f6f5f4; box-shadow: none; }
|
||||
|
||||
popover > contents.background > list, popover > contents.background > .view, popover > contents.background > iconview, popover > contents.background > toolbar { border-style: none; background-color: transparent; }
|
||||
popover.background > contents > list, popover.background > contents > .view, popover.background > contents > iconview, popover.background > contents > toolbar { border-style: none; background-color: transparent; }
|
||||
|
||||
.csd popover > contents.background.touch-selection, .csd popover > contents.background.magnifier, popover > contents.background.touch-selection, popover > contents.background.magnifier { border: 1px solid rgba(255, 255, 255, 0.1); }
|
||||
.csd popover.background > contents.touch-selection, .csd popover.background > contents.magnifier, popover.background > contents.touch-selection, popover.background > contents.magnifier { border: 1px solid rgba(255, 255, 255, 0.1); }
|
||||
|
||||
popover > contents.background separator { margin: 3px; }
|
||||
popover.background > contents separator { margin: 3px; }
|
||||
|
||||
popover > contents.background list separator { margin: 0px; }
|
||||
popover.background > contents list separator { margin: 0px; }
|
||||
|
||||
/************* Notebooks * */
|
||||
notebook box > header { padding: 1px; border-color: #cdc7c2; border-width: 1px; background-color: #e1dedb; }
|
||||
@@ -1155,7 +1155,7 @@ row:selected switch slider:checked, row:selected switch slider { border-color: #
|
||||
|
||||
.view.content-view.check:active:not(list), iconview.content-view.check:active:not(list), .content-view .tile check:active:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: transparent; background-color: rgba(53, 132, 228, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: none; -gtk-icon-shadow: none; }
|
||||
|
||||
.view.content-view.check:backdrop:not(list), iconview.content-view.check:backdrop:not(list), .content-view .tile check:backdrop:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: transparent; background-color: rgba(141, 141, 141, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: none; -gtk-icon-shadow: none; }
|
||||
.view.content-view.check:backdrop:not(list), iconview.content-view.check:backdrop:not(list), .content-view .tile check:backdrop:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: transparent; background-color: rgba(140, 140, 141, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: none; -gtk-icon-shadow: none; }
|
||||
|
||||
.view.content-view.check:checked:not(list), iconview.content-view.check:checked:not(list), .content-view .tile check:checked:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: #eeeeec; background-color: rgba(53, 132, 228, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: -gtk-icontheme('object-select-symbolic'); -gtk-icon-shadow: none; }
|
||||
|
||||
@@ -1163,7 +1163,7 @@ row:selected switch slider:checked, row:selected switch slider { border-color: #
|
||||
|
||||
.view.content-view.check:checked:active:not(list), iconview.content-view.check:checked:active:not(list), .content-view .tile check:checked:active:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: #eeeeec; background-color: rgba(53, 132, 228, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: -gtk-icontheme('object-select-symbolic'); -gtk-icon-shadow: none; }
|
||||
|
||||
.view.content-view.check:backdrop:checked:not(list), iconview.content-view.check:backdrop:checked:not(list), .content-view .tile check:backdrop:checked:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: rgba(238, 238, 236, 0.8); background-color: rgba(141, 141, 141, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: -gtk-icontheme('object-select-symbolic'); -gtk-icon-shadow: none; }
|
||||
.view.content-view.check:backdrop:checked:not(list), iconview.content-view.check:backdrop:checked:not(list), .content-view .tile check:backdrop:checked:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: rgba(238, 238, 236, 0.8); background-color: rgba(140, 140, 141, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: -gtk-icontheme('object-select-symbolic'); -gtk-icon-shadow: none; }
|
||||
|
||||
checkbutton.text-button, radiobutton.text-button { padding: 2px 0; outline-offset: 0; }
|
||||
|
||||
@@ -2079,7 +2079,7 @@ popover.menu box.inline-buttons { border-radius: 5px; border-style: none; border
|
||||
|
||||
popover.menu box.circular-buttons { padding-bottom: 5px; }
|
||||
|
||||
popover.menu.background contents { background: white; }
|
||||
popover.menu arrow, popover.menu.background contents { background-color: #ffffff; }
|
||||
|
||||
popover.menu.background separator { margin: 5px 0px; }
|
||||
|
||||
|
||||
+1
-1
@@ -827,7 +827,7 @@ summary = [
|
||||
' Colord support: @0@'.format(get_option('colord')),
|
||||
' Profiler: @0@'.format(get_option('profiler')),
|
||||
' Introspection: @0@'.format(get_option('introspection')),
|
||||
' Documentation: @0@'.format(get_option('documentation')),
|
||||
' Documentation: @0@'.format(get_option('gtk_doc')),
|
||||
' Man pages: @0@'.format(get_option('man-pages')),
|
||||
' Build tests: @0@'.format(get_option('build-tests')),
|
||||
' Install tests: @0@'.format(get_option('install-tests')),
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ option('colord', type: 'combo', choices : ['yes', 'no', 'auto'], value : 'auto',
|
||||
description : 'Build colord support for the CUPS printing backend')
|
||||
|
||||
# Documentation and introspection
|
||||
option('documentation', type: 'boolean', value: 'false',
|
||||
option('gtk_doc', type: 'boolean', value: 'false',
|
||||
description : 'Build API reference and tools documentation')
|
||||
option('man-pages', type: 'boolean', value: 'false',
|
||||
description : 'Build man pages for installed tools')
|
||||
|
||||
@@ -709,13 +709,7 @@ _post_send (GtkCupsRequest *request)
|
||||
httpClearFields (request->http);
|
||||
httpSetField (request->http, HTTP_FIELD_CONTENT_LENGTH, length);
|
||||
httpSetField (request->http, HTTP_FIELD_CONTENT_TYPE, "application/ipp");
|
||||
#ifdef HAVE_HTTPGETAUTHSTRING
|
||||
httpSetField (request->http, HTTP_FIELD_AUTHORIZATION, httpGetAuthString (request->http));
|
||||
#else
|
||||
#ifdef HAVE_HTTP_AUTHSTRING
|
||||
httpSetField (request->http, HTTP_FIELD_AUTHORIZATION, request->http->authstring);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (httpPost (request->http, request->resource))
|
||||
{
|
||||
@@ -1198,13 +1192,7 @@ _get_send (GtkCupsRequest *request)
|
||||
}
|
||||
|
||||
httpClearFields (request->http);
|
||||
#ifdef HAVE_HTTPGETAUTHSTRING
|
||||
httpSetField (request->http, HTTP_FIELD_AUTHORIZATION, httpGetAuthString (request->http));
|
||||
#else
|
||||
#ifdef HAVE_HTTP_AUTHSTRING
|
||||
httpSetField (request->http, HTTP_FIELD_AUTHORIZATION, request->http->authstring);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (httpGet (request->http, request->resource))
|
||||
{
|
||||
|
||||
@@ -17,32 +17,8 @@ print_backends = ['file']
|
||||
# Checks to see if we should compile with CUPS backend for GTK
|
||||
enable_cups = enabled_print_backends.contains('cups')
|
||||
if enable_cups
|
||||
#cups_config = find_program('cups-config', required : true)
|
||||
#if cups_config.found()
|
||||
# FIXME: eek, see configure.ac (we're just not going to support non-standar prefix for now)
|
||||
#endif
|
||||
if cc.has_header('cups/cups.h')
|
||||
# TODO: include_directories from cups-config
|
||||
cups_major_version = cc.compute_int('CUPS_VERSION_MAJOR', prefix : '#include <cups/cups.h>')
|
||||
cups_minor_version = cc.compute_int('CUPS_VERSION_MINOR', prefix : '#include <cups/cups.h>')
|
||||
message('Found CUPS version: @0@.@1@'.format(cups_major_version, cups_minor_version))
|
||||
if cups_major_version >= 2
|
||||
if cc.compiles('#include <cups/http.h> \n http_t http; char *s = http.authstring;')
|
||||
cdata.set('HAVE_HTTP_AUTHSTRING', 1,
|
||||
description :'Define if cups http_t authstring field is accessible')
|
||||
endif
|
||||
libcups = cc.find_library('cups', required : true)
|
||||
if libcups.found() and cc.has_function('httpGetAuthString', dependencies : libcups)
|
||||
cdata.set('HAVE_HTTPGETAUTHSTRING', 1)
|
||||
endif
|
||||
|
||||
print_backends += ['cups']
|
||||
else
|
||||
error('Need CUPS version >= 2.0')
|
||||
endif
|
||||
else
|
||||
error('Cannot find CUPS headers in default prefix.')
|
||||
endif
|
||||
cups_dep = dependency('cups', version : '>=2.0', required: true)
|
||||
print_backends += ['cups']
|
||||
endif
|
||||
|
||||
# Checks to see if we should compile with cloudprint backend for GTK
|
||||
@@ -101,7 +77,7 @@ if print_backends.contains('cups')
|
||||
'gtkcupsutils.c',
|
||||
'gtkcupssecretsutils.c',
|
||||
c_args: printbackends_args,
|
||||
dependencies: [libgtk_dep, libcups, colord_dep],
|
||||
dependencies: [libgtk_dep, cups_dep, colord_dep],
|
||||
install_dir: printbackends_install_dir,
|
||||
install : true)
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,380 @@
|
||||
#include <locale.h>
|
||||
|
||||
#include "../../gtk/gtkconstrainttypesprivate.h"
|
||||
#include "../../gtk/gtkconstraintsolverprivate.h"
|
||||
#include "../../gtk/gtkconstraintexpressionprivate.h"
|
||||
|
||||
static void
|
||||
constraint_solver_simple (void)
|
||||
{
|
||||
GtkConstraintSolver *solver = gtk_constraint_solver_new ();
|
||||
|
||||
GtkConstraintVariable *x = gtk_constraint_solver_create_variable (solver, NULL, "x", 167.0);
|
||||
GtkConstraintVariable *y = gtk_constraint_solver_create_variable (solver, NULL, "y", 2.0);
|
||||
|
||||
GtkConstraintExpression *e = gtk_constraint_expression_new_from_variable (y);
|
||||
|
||||
gtk_constraint_solver_add_constraint (solver,
|
||||
x, GTK_CONSTRAINT_RELATION_EQ, e,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
|
||||
double x_value = gtk_constraint_variable_get_value (x);
|
||||
double y_value = gtk_constraint_variable_get_value (y);
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (x_value, y_value, 0.001);
|
||||
g_assert_cmpfloat_with_epsilon (x_value, 0.0, 0.001);
|
||||
g_assert_cmpfloat_with_epsilon (y_value, 0.0, 0.001);
|
||||
|
||||
gtk_constraint_variable_unref (y);
|
||||
gtk_constraint_variable_unref (x);
|
||||
|
||||
g_object_unref (solver);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_solver_stay (void)
|
||||
{
|
||||
GtkConstraintSolver *solver = gtk_constraint_solver_new ();
|
||||
|
||||
GtkConstraintVariable *x = gtk_constraint_solver_create_variable (solver, NULL, "x", 5.0);
|
||||
GtkConstraintVariable *y = gtk_constraint_solver_create_variable (solver, NULL, "y", 10.0);
|
||||
|
||||
gtk_constraint_solver_add_stay_variable (solver, x, GTK_CONSTRAINT_STRENGTH_WEAK);
|
||||
gtk_constraint_solver_add_stay_variable (solver, y, GTK_CONSTRAINT_STRENGTH_WEAK);
|
||||
|
||||
double x_value = gtk_constraint_variable_get_value (x);
|
||||
double y_value = gtk_constraint_variable_get_value (y);
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (x_value, 5.0, 0.001);
|
||||
g_assert_cmpfloat_with_epsilon (y_value, 10.0, 0.001);
|
||||
|
||||
gtk_constraint_variable_unref (x);
|
||||
gtk_constraint_variable_unref (y);
|
||||
|
||||
g_object_unref (solver);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_solver_variable_geq_constant (void)
|
||||
{
|
||||
GtkConstraintSolver *solver = gtk_constraint_solver_new ();
|
||||
|
||||
GtkConstraintVariable *x = gtk_constraint_solver_create_variable (solver, NULL, "x", 10.0);
|
||||
GtkConstraintExpression *e = gtk_constraint_expression_new (100.0);
|
||||
|
||||
gtk_constraint_solver_add_constraint (solver,
|
||||
x, GTK_CONSTRAINT_RELATION_GE, e,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
|
||||
double x_value = gtk_constraint_variable_get_value (x);
|
||||
|
||||
g_assert_cmpfloat (x_value, >=, 100.0);
|
||||
|
||||
gtk_constraint_variable_unref (x);
|
||||
|
||||
g_object_unref (solver);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_solver_variable_leq_constant (void)
|
||||
{
|
||||
GtkConstraintSolver *solver = gtk_constraint_solver_new ();
|
||||
|
||||
GtkConstraintVariable *x = gtk_constraint_solver_create_variable (solver, NULL, "x", 100.0);
|
||||
GtkConstraintExpression *e = gtk_constraint_expression_new (10.0);
|
||||
|
||||
gtk_constraint_solver_add_constraint (solver,
|
||||
x, GTK_CONSTRAINT_RELATION_LE, e,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
|
||||
double x_value = gtk_constraint_variable_get_value (x);
|
||||
|
||||
g_assert_cmpfloat (x_value, <=, 10.0);
|
||||
|
||||
gtk_constraint_variable_unref (x);
|
||||
|
||||
g_object_unref (solver);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_solver_variable_eq_constant (void)
|
||||
{
|
||||
GtkConstraintSolver *solver = gtk_constraint_solver_new ();
|
||||
|
||||
GtkConstraintVariable *x = gtk_constraint_solver_create_variable (solver, NULL, "x", 10.0);
|
||||
GtkConstraintExpression *e = gtk_constraint_expression_new (100.0);
|
||||
|
||||
gtk_constraint_solver_add_constraint (solver,
|
||||
x, GTK_CONSTRAINT_RELATION_EQ, e,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
|
||||
double x_value = gtk_constraint_variable_get_value (x);
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (x_value, 100.0, 0.001);
|
||||
|
||||
gtk_constraint_variable_unref (x);
|
||||
|
||||
g_object_unref (solver);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_solver_eq_with_stay (void)
|
||||
{
|
||||
GtkConstraintSolver *solver = gtk_constraint_solver_new ();
|
||||
|
||||
GtkConstraintVariable *x = gtk_constraint_solver_create_variable (solver, NULL, "x", 10.0);
|
||||
GtkConstraintVariable *width = gtk_constraint_solver_create_variable (solver, NULL, "width", 10.0);
|
||||
GtkConstraintVariable *right_min = gtk_constraint_solver_create_variable (solver, NULL, "rightMin", 100.0);
|
||||
|
||||
GtkConstraintExpressionBuilder builder;
|
||||
gtk_constraint_expression_builder_init (&builder, solver);
|
||||
gtk_constraint_expression_builder_term (&builder, x);
|
||||
gtk_constraint_expression_builder_plus (&builder);
|
||||
gtk_constraint_expression_builder_term (&builder, width);
|
||||
GtkConstraintExpression *right = gtk_constraint_expression_builder_finish (&builder);
|
||||
|
||||
gtk_constraint_solver_add_stay_variable (solver, width, GTK_CONSTRAINT_STRENGTH_WEAK);
|
||||
gtk_constraint_solver_add_stay_variable (solver, right_min, GTK_CONSTRAINT_STRENGTH_WEAK);
|
||||
gtk_constraint_solver_add_constraint (solver,
|
||||
right_min, GTK_CONSTRAINT_RELATION_EQ, right,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
|
||||
double x_value = gtk_constraint_variable_get_value (x);
|
||||
double width_value = gtk_constraint_variable_get_value (width);
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (x_value, 90.0, 0.001);
|
||||
g_assert_cmpfloat_with_epsilon (width_value, 10.0, 0.001);
|
||||
|
||||
gtk_constraint_variable_unref (right_min);
|
||||
gtk_constraint_variable_unref (width);
|
||||
gtk_constraint_variable_unref (x);
|
||||
|
||||
g_object_unref (solver);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_solver_cassowary (void)
|
||||
{
|
||||
GtkConstraintSolver *solver = gtk_constraint_solver_new ();
|
||||
|
||||
GtkConstraintVariable *x = gtk_constraint_solver_create_variable (solver, NULL, "x", 0.0);
|
||||
GtkConstraintVariable *y = gtk_constraint_solver_create_variable (solver, NULL, "y", 0.0);
|
||||
|
||||
GtkConstraintExpression *e;
|
||||
|
||||
e = gtk_constraint_expression_new_from_variable (y);
|
||||
gtk_constraint_solver_add_constraint (solver,
|
||||
x, GTK_CONSTRAINT_RELATION_LE, e,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
|
||||
e = gtk_constraint_expression_plus_constant (gtk_constraint_expression_new_from_variable (x), 3.0);
|
||||
gtk_constraint_solver_add_constraint (solver,
|
||||
y, GTK_CONSTRAINT_RELATION_EQ, e,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
|
||||
e = gtk_constraint_expression_new (10.0);
|
||||
gtk_constraint_solver_add_constraint (solver,
|
||||
x, GTK_CONSTRAINT_RELATION_EQ, e,
|
||||
GTK_CONSTRAINT_STRENGTH_WEAK);
|
||||
|
||||
e = gtk_constraint_expression_new (10.0);
|
||||
gtk_constraint_solver_add_constraint (solver,
|
||||
y, GTK_CONSTRAINT_RELATION_EQ, e,
|
||||
GTK_CONSTRAINT_STRENGTH_WEAK);
|
||||
|
||||
double x_val = gtk_constraint_variable_get_value (x);
|
||||
double y_val = gtk_constraint_variable_get_value (y);
|
||||
|
||||
g_test_message ("x = %g, y = %g", x_val, y_val);
|
||||
|
||||
/* The system is unstable and has two possible solutions we need to test */
|
||||
g_assert_true ((G_APPROX_VALUE (x_val, 10.0, 1e-8) &&
|
||||
G_APPROX_VALUE (y_val, 13.0, 1e-8)) ||
|
||||
(G_APPROX_VALUE (x_val, 7.0, 1e-8) &&
|
||||
G_APPROX_VALUE (y_val, 10.0, 1e-8)));
|
||||
|
||||
gtk_constraint_variable_unref (x);
|
||||
gtk_constraint_variable_unref (y);
|
||||
|
||||
g_object_unref (solver);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_solver_edit_var_required (void)
|
||||
{
|
||||
GtkConstraintSolver *solver = gtk_constraint_solver_new ();
|
||||
|
||||
GtkConstraintVariable *a = gtk_constraint_solver_create_variable (solver, NULL, "a", 0.0);
|
||||
gtk_constraint_solver_add_stay_variable (solver, a, GTK_CONSTRAINT_STRENGTH_STRONG);
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (a), 0.0, 0.001);
|
||||
|
||||
gtk_constraint_solver_add_edit_variable (solver, a, GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
gtk_constraint_solver_begin_edit (solver);
|
||||
gtk_constraint_solver_suggest_value (solver, a, 2.0);
|
||||
gtk_constraint_solver_resolve (solver);
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (a), 2.0, 0.001);
|
||||
|
||||
gtk_constraint_solver_suggest_value (solver, a, 10.0);
|
||||
gtk_constraint_solver_resolve (solver);
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (a), 10.0, 0.001);
|
||||
|
||||
gtk_constraint_solver_end_edit (solver);
|
||||
|
||||
gtk_constraint_variable_unref (a);
|
||||
|
||||
g_object_unref (solver);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_solver_edit_var_suggest (void)
|
||||
{
|
||||
GtkConstraintSolver *solver = gtk_constraint_solver_new ();
|
||||
|
||||
GtkConstraintVariable *a = gtk_constraint_solver_create_variable (solver, NULL, "a", 0.0);
|
||||
GtkConstraintVariable *b = gtk_constraint_solver_create_variable (solver, NULL, "b", 0.0);
|
||||
|
||||
gtk_constraint_solver_add_stay_variable (solver, a, GTK_CONSTRAINT_STRENGTH_STRONG);
|
||||
|
||||
GtkConstraintExpression *e = gtk_constraint_expression_new_from_variable (b);
|
||||
gtk_constraint_solver_add_constraint (solver,
|
||||
a, GTK_CONSTRAINT_RELATION_EQ, e,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
|
||||
gtk_constraint_solver_resolve (solver);
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (a), 0.0, 0.001);
|
||||
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (b), 0.0, 0.001);
|
||||
|
||||
gtk_constraint_solver_add_edit_variable (solver, a, GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
gtk_constraint_solver_begin_edit (solver);
|
||||
|
||||
gtk_constraint_solver_suggest_value (solver, a, 2.0);
|
||||
gtk_constraint_solver_resolve (solver);
|
||||
|
||||
g_test_message ("Check values after first edit");
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (a), 2.0, 0.001);
|
||||
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (b), 2.0, 0.001);
|
||||
|
||||
gtk_constraint_solver_suggest_value (solver, a, 10.0);
|
||||
gtk_constraint_solver_resolve (solver);
|
||||
|
||||
g_test_message ("Check values after second edit");
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (a), 10.0, 0.001);
|
||||
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (b), 10.0, 0.001);
|
||||
|
||||
gtk_constraint_solver_suggest_value (solver, a, 12.0);
|
||||
gtk_constraint_solver_resolve (solver);
|
||||
|
||||
g_test_message ("Check values after third edit");
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (a), 12.0, 0.001);
|
||||
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (b), 12.0, 0.001);
|
||||
|
||||
gtk_constraint_variable_unref (a);
|
||||
gtk_constraint_variable_unref (b);
|
||||
|
||||
g_object_unref (solver);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_solver_paper (void)
|
||||
{
|
||||
GtkConstraintSolver *solver = gtk_constraint_solver_new ();
|
||||
|
||||
GtkConstraintVariable *left = gtk_constraint_solver_create_variable (solver, NULL, "left", 0.0);
|
||||
GtkConstraintVariable *middle = gtk_constraint_solver_create_variable (solver, NULL, "middle", 0.0);
|
||||
GtkConstraintVariable *right = gtk_constraint_solver_create_variable (solver, NULL, "right", 0.0);
|
||||
|
||||
GtkConstraintExpressionBuilder builder;
|
||||
GtkConstraintExpression *expr;
|
||||
|
||||
gtk_constraint_expression_builder_init (&builder, solver);
|
||||
gtk_constraint_expression_builder_term (&builder, left);
|
||||
gtk_constraint_expression_builder_plus (&builder);
|
||||
gtk_constraint_expression_builder_term (&builder, right);
|
||||
gtk_constraint_expression_builder_divide_by (&builder);
|
||||
gtk_constraint_expression_builder_constant (&builder, 2.0);
|
||||
expr = gtk_constraint_expression_builder_finish (&builder);
|
||||
gtk_constraint_solver_add_constraint (solver,
|
||||
middle, GTK_CONSTRAINT_RELATION_EQ, expr,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
|
||||
gtk_constraint_expression_builder_init (&builder, solver);
|
||||
gtk_constraint_expression_builder_term (&builder, left);
|
||||
gtk_constraint_expression_builder_plus (&builder);
|
||||
gtk_constraint_expression_builder_constant (&builder, 10.0);
|
||||
expr = gtk_constraint_expression_builder_finish (&builder);
|
||||
gtk_constraint_solver_add_constraint (solver,
|
||||
right, GTK_CONSTRAINT_RELATION_EQ, expr,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
|
||||
expr = gtk_constraint_expression_new (100.0);
|
||||
gtk_constraint_solver_add_constraint (solver,
|
||||
right, GTK_CONSTRAINT_RELATION_LE, expr,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
|
||||
expr = gtk_constraint_expression_new (0.0);
|
||||
gtk_constraint_solver_add_constraint (solver,
|
||||
left, GTK_CONSTRAINT_RELATION_GE, expr,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
|
||||
g_test_message ("Check constraints hold");
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (middle),
|
||||
(gtk_constraint_variable_get_value (left) + gtk_constraint_variable_get_value (right)) / 2.0,
|
||||
0.001);
|
||||
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (right),
|
||||
gtk_constraint_variable_get_value (left) + 10.0,
|
||||
0.001);
|
||||
g_assert_cmpfloat (gtk_constraint_variable_get_value (right), <=, 100.0);
|
||||
g_assert_cmpfloat (gtk_constraint_variable_get_value (left), >=, 0.0);
|
||||
|
||||
gtk_constraint_variable_set_value (middle, 45.0);
|
||||
gtk_constraint_solver_add_stay_variable (solver, middle, GTK_CONSTRAINT_STRENGTH_WEAK);
|
||||
|
||||
g_test_message ("Check constraints hold after setting middle");
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (middle),
|
||||
(gtk_constraint_variable_get_value (left) + gtk_constraint_variable_get_value (right)) / 2.0,
|
||||
0.001);
|
||||
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (right),
|
||||
gtk_constraint_variable_get_value (left) + 10.0,
|
||||
0.001);
|
||||
g_assert_cmpfloat (gtk_constraint_variable_get_value (right), <=, 100.0);
|
||||
g_assert_cmpfloat (gtk_constraint_variable_get_value (left), >=, 0.0);
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (left), 40.0, 0.001);
|
||||
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (middle), 45.0, 0.001);
|
||||
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (right), 50.0, 0.001);
|
||||
|
||||
gtk_constraint_variable_unref (left);
|
||||
gtk_constraint_variable_unref (middle);
|
||||
gtk_constraint_variable_unref (right);
|
||||
|
||||
g_object_unref (solver);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
setlocale (LC_ALL, "C");
|
||||
|
||||
g_test_add_func ("/constraint-solver/paper", constraint_solver_paper);
|
||||
g_test_add_func ("/constraint-solver/simple", constraint_solver_simple);
|
||||
g_test_add_func ("/constraint-solver/constant/eq", constraint_solver_variable_eq_constant);
|
||||
g_test_add_func ("/constraint-solver/constant/ge", constraint_solver_variable_geq_constant);
|
||||
g_test_add_func ("/constraint-solver/constant/le", constraint_solver_variable_leq_constant);
|
||||
g_test_add_func ("/constraint-solver/stay/simple", constraint_solver_stay);
|
||||
g_test_add_func ("/constraint-solver/stay/eq", constraint_solver_eq_with_stay);
|
||||
g_test_add_func ("/constraint-solver/cassowary", constraint_solver_cassowary);
|
||||
g_test_add_func ("/constraint-solver/edit/required", constraint_solver_edit_var_required);
|
||||
g_test_add_func ("/constraint-solver/edit/suggest", constraint_solver_edit_var_suggest);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
@@ -300,6 +300,44 @@ test_submodel_add (void)
|
||||
g_object_unref (flat);
|
||||
}
|
||||
|
||||
static void
|
||||
test_submodel_add2 (void)
|
||||
{
|
||||
GtkFlattenListModel *flat;
|
||||
GListStore *model, *store[2];
|
||||
|
||||
model = g_list_store_new (G_TYPE_LIST_MODEL);
|
||||
flat = new_model (model);
|
||||
assert_model (flat, "");
|
||||
assert_changes (flat, "");
|
||||
|
||||
store[0] = add_store (model, 1, 0, 0);
|
||||
store[1] = add_store (model, 1, 0, 0);
|
||||
store[2] = add_store (model, 1, 0, 0);
|
||||
|
||||
assert_model (flat, "");
|
||||
assert_changes (flat, "");
|
||||
|
||||
add (store[0], 1);
|
||||
assert_model (flat, "1");
|
||||
assert_changes (flat, "+0");
|
||||
|
||||
add (store[1], 3);
|
||||
assert_model (flat, "1 3");
|
||||
assert_changes (flat, "+1");
|
||||
|
||||
add (store[0], 2);
|
||||
assert_model (flat, "1 2 3");
|
||||
assert_changes (flat, "+1");
|
||||
|
||||
add (store[1], 4);
|
||||
assert_model (flat, "1 2 3 4");
|
||||
assert_changes (flat, "+3");
|
||||
|
||||
g_object_unref (model);
|
||||
g_object_unref (flat);
|
||||
}
|
||||
|
||||
static void
|
||||
test_model_remove (void)
|
||||
{
|
||||
@@ -365,6 +403,7 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/flattenlistmodel/model/add", test_model_add);
|
||||
#if GLIB_CHECK_VERSION (2, 58, 0) /* g_list_store_splice() is broken before 2.58 */
|
||||
g_test_add_func ("/flattenlistmodel/submodel/add", test_submodel_add);
|
||||
g_test_add_func ("/flattenlistmodel/submodel/add2", test_submodel_add2);
|
||||
g_test_add_func ("/flattenlistmodel/model/remove", test_model_remove);
|
||||
g_test_add_func ("/flattenlistmodel/submodel/remove", test_submodel_remove);
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,681 @@
|
||||
/* Copyright (C) 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 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 <gtk/gtk.h>
|
||||
|
||||
#define GTK_TYPE_GIZMO (gtk_gizmo_get_type ())
|
||||
#define GTK_GIZMO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_GIZMO, GtkGizmo))
|
||||
#define GTK_GIZMO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_GIZMO, GtkGizmoClass))
|
||||
#define GTK_IS_GIZMO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_GIZMO))
|
||||
#define GTK_IS_GIZMO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_GIZMO))
|
||||
#define GTK_GIZMO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_GIZMO, GtkGizmoClass))
|
||||
|
||||
typedef struct _GtkGizmo GtkGizmo;
|
||||
|
||||
struct _GtkGizmo {
|
||||
GtkWidget parent;
|
||||
|
||||
const char *name;
|
||||
int min_width;
|
||||
int min_height;
|
||||
int nat_width;
|
||||
int nat_height;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
typedef GtkWidgetClass GtkGizmoClass;
|
||||
|
||||
G_DEFINE_TYPE (GtkGizmo, gtk_gizmo, GTK_TYPE_WIDGET);
|
||||
|
||||
static void
|
||||
gtk_gizmo_measure (GtkWidget *widget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural,
|
||||
int *minimum_baseline,
|
||||
int *natural_baseline)
|
||||
{
|
||||
GtkGizmo *self = GTK_GIZMO (widget);
|
||||
|
||||
if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
{
|
||||
*minimum = self->min_width;
|
||||
*natural = self->nat_width;
|
||||
}
|
||||
else
|
||||
{
|
||||
*minimum = self->min_height;
|
||||
*natural = self->nat_height;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_gizmo_size_allocate (GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int baseline)
|
||||
{
|
||||
GtkGizmo *self = GTK_GIZMO (widget);
|
||||
|
||||
self->width = width;
|
||||
self->height = height;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_gizmo_class_init (GtkGizmoClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
widget_class->measure = gtk_gizmo_measure;
|
||||
widget_class->size_allocate = gtk_gizmo_size_allocate;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_gizmo_init (GtkGizmo *self)
|
||||
{
|
||||
}
|
||||
|
||||
/* Create a grid with three children in row
|
||||
*
|
||||
* +--------+--------+--------+
|
||||
* | child1 | child2 | child3 |
|
||||
* +--------+--------+--------+
|
||||
*
|
||||
* Verify that
|
||||
* - the layout has the expected min and nat sizes
|
||||
* - the children get their nat width when the layout does
|
||||
* - they all get the same height
|
||||
*/
|
||||
static void
|
||||
test_simple_row (void)
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *parent;
|
||||
GtkLayoutManager *layout;
|
||||
GtkGizmo *child1;
|
||||
GtkGizmo *child2;
|
||||
GtkGizmo *child3;
|
||||
GtkLayoutChild *lc;
|
||||
int minimum, natural;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
parent = g_object_new (GTK_TYPE_GIZMO, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), parent);
|
||||
|
||||
layout = gtk_grid_layout_new ();
|
||||
gtk_widget_set_layout_manager (parent, layout);
|
||||
|
||||
child1 = g_object_new (GTK_TYPE_GIZMO, NULL);
|
||||
child2 = g_object_new (GTK_TYPE_GIZMO, NULL);
|
||||
child3 = g_object_new (GTK_TYPE_GIZMO, NULL);
|
||||
|
||||
child1->name = "child1";
|
||||
child1->min_width = 10;
|
||||
child1->min_height = 10;
|
||||
child1->nat_width = 20;
|
||||
child1->nat_height = 20;
|
||||
child2->name = "child2";
|
||||
child2->min_width = 20;
|
||||
child2->min_height = 20;
|
||||
child2->nat_width = 30;
|
||||
child2->nat_height = 30;
|
||||
child3->name = "child3";
|
||||
child3->min_width = 30;
|
||||
child3->min_height = 30;
|
||||
child3->nat_width = 40;
|
||||
child3->nat_height = 40;
|
||||
|
||||
gtk_widget_set_parent (GTK_WIDGET (child1), parent);
|
||||
gtk_widget_set_parent (GTK_WIDGET (child2), parent);
|
||||
gtk_widget_set_parent (GTK_WIDGET (child3), parent);
|
||||
|
||||
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child1));
|
||||
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
|
||||
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child2));
|
||||
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 1);
|
||||
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child3));
|
||||
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 2);
|
||||
|
||||
#if 0
|
||||
gtk_widget_show (window);
|
||||
|
||||
g_timeout_add (1000, (GSourceFunc)gtk_main_quit, NULL);
|
||||
gtk_main ();
|
||||
#endif
|
||||
|
||||
gtk_layout_manager_measure (layout,
|
||||
parent,
|
||||
GTK_ORIENTATION_HORIZONTAL,
|
||||
-1,
|
||||
&minimum,
|
||||
&natural,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
g_assert_cmpint (minimum, ==, 10 + 20 + 30);
|
||||
g_assert_cmpint (natural, ==, 20 + 30 + 40);
|
||||
|
||||
gtk_layout_manager_measure (layout,
|
||||
parent,
|
||||
GTK_ORIENTATION_VERTICAL,
|
||||
-1,
|
||||
&minimum,
|
||||
&natural,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
g_assert_cmpint (minimum, ==, 30);
|
||||
g_assert_cmpint (natural, ==, 40);
|
||||
|
||||
gtk_layout_manager_allocate (layout, parent, 90, 40, 0);
|
||||
|
||||
g_assert_cmpint (child1->width, ==, 20);
|
||||
g_assert_cmpint (child2->width, ==, 30);
|
||||
g_assert_cmpint (child3->width, ==, 40);
|
||||
|
||||
g_assert_cmpint (child1->height, ==, 40);
|
||||
g_assert_cmpint (child2->height, ==, 40);
|
||||
g_assert_cmpint (child3->height, ==, 40);
|
||||
|
||||
gtk_widget_unparent (GTK_WIDGET (child1));
|
||||
gtk_widget_unparent (GTK_WIDGET (child2));
|
||||
gtk_widget_unparent (GTK_WIDGET (child3));
|
||||
|
||||
gtk_widget_destroy (parent);
|
||||
}
|
||||
|
||||
/* same as the previous test, with a column
|
||||
*/
|
||||
static void
|
||||
test_simple_column (void)
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *parent;
|
||||
GtkLayoutManager *layout;
|
||||
GtkGizmo *child1;
|
||||
GtkGizmo *child2;
|
||||
GtkGizmo *child3;
|
||||
GtkLayoutChild *lc;
|
||||
int minimum, natural;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
parent = g_object_new (GTK_TYPE_GIZMO, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), parent);
|
||||
|
||||
layout = gtk_grid_layout_new ();
|
||||
gtk_widget_set_layout_manager (parent, layout);
|
||||
|
||||
child1 = g_object_new (GTK_TYPE_GIZMO, NULL);
|
||||
child2 = g_object_new (GTK_TYPE_GIZMO, NULL);
|
||||
child3 = g_object_new (GTK_TYPE_GIZMO, NULL);
|
||||
|
||||
child1->name = "child1";
|
||||
child1->min_width = 10;
|
||||
child1->min_height = 10;
|
||||
child1->nat_width = 20;
|
||||
child1->nat_height = 20;
|
||||
child2->name = "child2";
|
||||
child2->min_width = 20;
|
||||
child2->min_height = 20;
|
||||
child2->nat_width = 30;
|
||||
child2->nat_height = 30;
|
||||
child3->name = "child3";
|
||||
child3->min_width = 30;
|
||||
child3->min_height = 30;
|
||||
child3->nat_width = 40;
|
||||
child3->nat_height = 40;
|
||||
|
||||
gtk_widget_set_parent (GTK_WIDGET (child1), parent);
|
||||
gtk_widget_set_parent (GTK_WIDGET (child2), parent);
|
||||
gtk_widget_set_parent (GTK_WIDGET (child3), parent);
|
||||
|
||||
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child1));
|
||||
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
|
||||
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child2));
|
||||
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 1);
|
||||
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child3));
|
||||
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 2);
|
||||
|
||||
#if 0
|
||||
gtk_widget_show (window);
|
||||
|
||||
g_timeout_add (1000, (GSourceFunc)gtk_main_quit, NULL);
|
||||
gtk_main ();
|
||||
#endif
|
||||
|
||||
gtk_layout_manager_measure (layout,
|
||||
parent,
|
||||
GTK_ORIENTATION_HORIZONTAL,
|
||||
-1,
|
||||
&minimum,
|
||||
&natural,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
g_assert_cmpint (minimum, ==, 30);
|
||||
g_assert_cmpint (natural, ==, 40);
|
||||
|
||||
gtk_layout_manager_measure (layout,
|
||||
parent,
|
||||
GTK_ORIENTATION_VERTICAL,
|
||||
-1,
|
||||
&minimum,
|
||||
&natural,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
g_assert_cmpint (minimum, ==, 10 + 20 + 30);
|
||||
g_assert_cmpint (natural, ==, 20 + 30 + 40);
|
||||
|
||||
gtk_layout_manager_allocate (layout, parent, 40, 90, 0);
|
||||
|
||||
g_assert_cmpint (child1->width, ==, 40);
|
||||
g_assert_cmpint (child2->width, ==, 40);
|
||||
g_assert_cmpint (child3->width, ==, 40);
|
||||
|
||||
g_assert_cmpint (child1->height, ==, 20);
|
||||
g_assert_cmpint (child2->height, ==, 30);
|
||||
g_assert_cmpint (child3->height, ==, 40);
|
||||
|
||||
gtk_widget_unparent (GTK_WIDGET (child1));
|
||||
gtk_widget_unparent (GTK_WIDGET (child2));
|
||||
gtk_widget_unparent (GTK_WIDGET (child3));
|
||||
|
||||
gtk_widget_destroy (parent);
|
||||
}
|
||||
|
||||
/* Create a grid with spanning children
|
||||
*
|
||||
* +--------+-----------------+
|
||||
* | child1 | child2 |
|
||||
* +--------+--------+--------+
|
||||
* | child3 | child4 |
|
||||
* +-----------------+--------+
|
||||
*
|
||||
* Verify that
|
||||
* - the layout has the expected min and nat sizes
|
||||
* - the children get their nat width when the layout does
|
||||
*/
|
||||
static void
|
||||
test_spans (void)
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *parent;
|
||||
GtkLayoutManager *layout;
|
||||
GtkGizmo *child1;
|
||||
GtkGizmo *child2;
|
||||
GtkGizmo *child3;
|
||||
GtkGizmo *child4;
|
||||
GtkLayoutChild *lc;
|
||||
int minimum, natural;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
parent = g_object_new (GTK_TYPE_GIZMO, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), parent);
|
||||
|
||||
layout = gtk_grid_layout_new ();
|
||||
gtk_widget_set_layout_manager (parent, layout);
|
||||
|
||||
child1 = g_object_new (GTK_TYPE_GIZMO, NULL);
|
||||
child2 = g_object_new (GTK_TYPE_GIZMO, NULL);
|
||||
child3 = g_object_new (GTK_TYPE_GIZMO, NULL);
|
||||
child4 = g_object_new (GTK_TYPE_GIZMO, NULL);
|
||||
|
||||
child1->name = "child1";
|
||||
child1->min_width = 10;
|
||||
child1->min_height = 10;
|
||||
child1->nat_width = 20;
|
||||
child1->nat_height = 20;
|
||||
child2->name = "child2";
|
||||
child2->min_width = 20;
|
||||
child2->min_height = 20;
|
||||
child2->nat_width = 30;
|
||||
child2->nat_height = 30;
|
||||
child3->name = "child3";
|
||||
child3->min_width = 30;
|
||||
child3->min_height = 30;
|
||||
child3->nat_width = 40;
|
||||
child3->nat_height = 40;
|
||||
child4->name = "child4";
|
||||
child4->min_width = 30;
|
||||
child4->min_height = 30;
|
||||
child4->nat_width = 40;
|
||||
child4->nat_height = 40;
|
||||
|
||||
gtk_widget_set_parent (GTK_WIDGET (child1), parent);
|
||||
gtk_widget_set_parent (GTK_WIDGET (child2), parent);
|
||||
gtk_widget_set_parent (GTK_WIDGET (child3), parent);
|
||||
gtk_widget_set_parent (GTK_WIDGET (child4), parent);
|
||||
|
||||
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child1));
|
||||
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
|
||||
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
|
||||
|
||||
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child2));
|
||||
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
|
||||
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 1);
|
||||
gtk_grid_layout_child_set_column_span (GTK_GRID_LAYOUT_CHILD (lc), 2);
|
||||
|
||||
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child3));
|
||||
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 1);
|
||||
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
|
||||
gtk_grid_layout_child_set_column_span (GTK_GRID_LAYOUT_CHILD (lc), 2);
|
||||
|
||||
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child4));
|
||||
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 1);
|
||||
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 2);
|
||||
|
||||
#if 0
|
||||
gtk_widget_show (window);
|
||||
|
||||
g_timeout_add (1000, (GSourceFunc)gtk_main_quit, NULL);
|
||||
gtk_main ();
|
||||
#endif
|
||||
|
||||
gtk_layout_manager_measure (layout,
|
||||
parent,
|
||||
GTK_ORIENTATION_HORIZONTAL,
|
||||
-1,
|
||||
&minimum,
|
||||
&natural,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
g_assert_cmpint (minimum, ==, 60);
|
||||
g_assert_cmpint (natural, ==, 80);
|
||||
|
||||
gtk_layout_manager_measure (layout,
|
||||
parent,
|
||||
GTK_ORIENTATION_VERTICAL,
|
||||
-1,
|
||||
&minimum,
|
||||
&natural,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
g_assert_cmpint (minimum, ==, 50);
|
||||
g_assert_cmpint (natural, ==, 70);
|
||||
|
||||
gtk_layout_manager_allocate (layout, parent, 80, 70, 0);
|
||||
|
||||
g_assert_cmpint (child1->width, ==, 30);
|
||||
g_assert_cmpint (child2->width, ==, 50);
|
||||
g_assert_cmpint (child3->width, ==, 40);
|
||||
g_assert_cmpint (child4->width, ==, 40);
|
||||
|
||||
g_assert_cmpint (child1->height, ==, 30);
|
||||
g_assert_cmpint (child2->height, ==, 30);
|
||||
g_assert_cmpint (child3->height, ==, 40);
|
||||
g_assert_cmpint (child4->height, ==, 40);
|
||||
|
||||
gtk_widget_unparent (GTK_WIDGET (child1));
|
||||
gtk_widget_unparent (GTK_WIDGET (child2));
|
||||
gtk_widget_unparent (GTK_WIDGET (child3));
|
||||
gtk_widget_unparent (GTK_WIDGET (child4));
|
||||
|
||||
gtk_widget_destroy (parent);
|
||||
}
|
||||
|
||||
/* Create a 2x2 homogeneous grid and verify
|
||||
* all children get the same size.
|
||||
*/
|
||||
static void
|
||||
test_homogeneous (void)
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *parent;
|
||||
GtkLayoutManager *layout;
|
||||
GtkGizmo *child1;
|
||||
GtkGizmo *child2;
|
||||
GtkGizmo *child3;
|
||||
GtkGizmo *child4;
|
||||
GtkLayoutChild *lc;
|
||||
int minimum, natural;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
parent = g_object_new (GTK_TYPE_GIZMO, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), parent);
|
||||
|
||||
layout = gtk_grid_layout_new ();
|
||||
gtk_grid_layout_set_row_homogeneous (GTK_GRID_LAYOUT (layout), TRUE);
|
||||
gtk_grid_layout_set_column_homogeneous (GTK_GRID_LAYOUT (layout), TRUE);
|
||||
gtk_widget_set_layout_manager (parent, layout);
|
||||
|
||||
child1 = g_object_new (GTK_TYPE_GIZMO, NULL);
|
||||
child2 = g_object_new (GTK_TYPE_GIZMO, NULL);
|
||||
child3 = g_object_new (GTK_TYPE_GIZMO, NULL);
|
||||
child4 = g_object_new (GTK_TYPE_GIZMO, NULL);
|
||||
|
||||
child1->name = "child1";
|
||||
child1->min_width = 10;
|
||||
child1->min_height = 10;
|
||||
child1->nat_width = 20;
|
||||
child1->nat_height = 20;
|
||||
child2->name = "child2";
|
||||
child2->min_width = 20;
|
||||
child2->min_height = 20;
|
||||
child2->nat_width = 30;
|
||||
child2->nat_height = 30;
|
||||
child3->name = "child3";
|
||||
child3->min_width = 30;
|
||||
child3->min_height = 30;
|
||||
child3->nat_width = 40;
|
||||
child3->nat_height = 40;
|
||||
child4->name = "child4";
|
||||
child4->min_width = 30;
|
||||
child4->min_height = 30;
|
||||
child4->nat_width = 40;
|
||||
child4->nat_height = 40;
|
||||
|
||||
gtk_widget_set_parent (GTK_WIDGET (child1), parent);
|
||||
gtk_widget_set_parent (GTK_WIDGET (child2), parent);
|
||||
gtk_widget_set_parent (GTK_WIDGET (child3), parent);
|
||||
gtk_widget_set_parent (GTK_WIDGET (child4), parent);
|
||||
|
||||
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child1));
|
||||
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
|
||||
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
|
||||
|
||||
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child2));
|
||||
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
|
||||
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 1);
|
||||
|
||||
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child3));
|
||||
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 1);
|
||||
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
|
||||
|
||||
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child4));
|
||||
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 1);
|
||||
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 1);
|
||||
|
||||
#if 0
|
||||
gtk_widget_show (window);
|
||||
|
||||
g_timeout_add (1000, (GSourceFunc)gtk_main_quit, NULL);
|
||||
gtk_main ();
|
||||
#endif
|
||||
|
||||
gtk_layout_manager_measure (layout,
|
||||
parent,
|
||||
GTK_ORIENTATION_HORIZONTAL,
|
||||
-1,
|
||||
&minimum,
|
||||
&natural,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
g_assert_cmpint (minimum, ==, 60);
|
||||
g_assert_cmpint (natural, ==, 80);
|
||||
|
||||
gtk_layout_manager_measure (layout,
|
||||
parent,
|
||||
GTK_ORIENTATION_VERTICAL,
|
||||
-1,
|
||||
&minimum,
|
||||
&natural,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
g_assert_cmpint (minimum, ==, 60);
|
||||
g_assert_cmpint (natural, ==, 80);
|
||||
|
||||
gtk_layout_manager_allocate (layout, parent, 80, 80, 0);
|
||||
|
||||
g_assert_cmpint (child1->width, ==, 40);
|
||||
g_assert_cmpint (child2->width, ==, 40);
|
||||
g_assert_cmpint (child3->width, ==, 40);
|
||||
g_assert_cmpint (child4->width, ==, 40);
|
||||
|
||||
g_assert_cmpint (child1->height, ==, 40);
|
||||
g_assert_cmpint (child2->height, ==, 40);
|
||||
g_assert_cmpint (child3->height, ==, 40);
|
||||
g_assert_cmpint (child4->height, ==, 40);
|
||||
|
||||
gtk_widget_unparent (GTK_WIDGET (child1));
|
||||
gtk_widget_unparent (GTK_WIDGET (child2));
|
||||
gtk_widget_unparent (GTK_WIDGET (child3));
|
||||
gtk_widget_unparent (GTK_WIDGET (child4));
|
||||
|
||||
gtk_widget_destroy (parent);
|
||||
}
|
||||
|
||||
/* Create a layout with three children
|
||||
*
|
||||
* +--------+--------+
|
||||
* | child1 | child2 |
|
||||
* +--------+--------+
|
||||
* | child3 |
|
||||
* +-----------------+
|
||||
*
|
||||
* This is a layout that we also reproduce with
|
||||
* constraints, for comparison. Among the contraints:
|
||||
* - child1.width == child2.width
|
||||
* - child1.height == child2.height == child3.height
|
||||
*/
|
||||
static void
|
||||
test_simple_layout (void)
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *parent;
|
||||
GtkLayoutManager *layout;
|
||||
GtkLayoutChild *lc;
|
||||
GtkGizmo *child1;
|
||||
GtkGizmo *child2;
|
||||
GtkGizmo *child3;
|
||||
int minimum, natural;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
parent = g_object_new (GTK_TYPE_GIZMO, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), parent);
|
||||
|
||||
layout = gtk_grid_layout_new ();
|
||||
gtk_grid_layout_set_row_homogeneous (GTK_GRID_LAYOUT (layout), TRUE);
|
||||
gtk_grid_layout_set_column_homogeneous (GTK_GRID_LAYOUT (layout), TRUE);
|
||||
gtk_widget_set_layout_manager (parent, layout);
|
||||
|
||||
child1 = g_object_new (GTK_TYPE_GIZMO, NULL);
|
||||
child2 = g_object_new (GTK_TYPE_GIZMO, NULL);
|
||||
child3 = g_object_new (GTK_TYPE_GIZMO, NULL);
|
||||
|
||||
child1->name = "child1";
|
||||
child1->min_width = 10;
|
||||
child1->min_height = 10;
|
||||
child1->nat_width = 50;
|
||||
child1->nat_height = 50;
|
||||
child2->name = "child2";
|
||||
child2->min_width = 20;
|
||||
child2->min_height = 20;
|
||||
child2->nat_width = 50;
|
||||
child2->nat_height = 50;
|
||||
child3->name = "child3";
|
||||
child3->min_width = 50;
|
||||
child3->min_height = 10;
|
||||
child3->nat_width = 50;
|
||||
child3->nat_height = 50;
|
||||
|
||||
gtk_widget_set_parent (GTK_WIDGET (child1), parent);
|
||||
gtk_widget_set_parent (GTK_WIDGET (child2), parent);
|
||||
gtk_widget_set_parent (GTK_WIDGET (child3), parent);
|
||||
|
||||
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child1));
|
||||
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
|
||||
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
|
||||
|
||||
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child2));
|
||||
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
|
||||
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 1);
|
||||
|
||||
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child3));
|
||||
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 1);
|
||||
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
|
||||
gtk_grid_layout_child_set_column_span (GTK_GRID_LAYOUT_CHILD (lc), 2);
|
||||
|
||||
gtk_layout_manager_measure (layout,
|
||||
parent,
|
||||
GTK_ORIENTATION_HORIZONTAL,
|
||||
-1,
|
||||
&minimum,
|
||||
&natural,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
g_assert_cmpint (minimum, ==, 50);
|
||||
g_assert_cmpint (natural, ==, 100);
|
||||
|
||||
gtk_layout_manager_measure (layout,
|
||||
parent,
|
||||
GTK_ORIENTATION_VERTICAL,
|
||||
-1,
|
||||
&minimum,
|
||||
&natural,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
g_assert_cmpint (minimum, ==, 40);
|
||||
g_assert_cmpint (natural, ==, 100);
|
||||
|
||||
gtk_layout_manager_allocate (layout, parent, 100, 100, 0);
|
||||
|
||||
g_assert_cmpint (child1->width, ==, 50);
|
||||
g_assert_cmpint (child2->width, ==, 50);
|
||||
g_assert_cmpint (child3->width, ==, 100);
|
||||
|
||||
g_assert_cmpint (child1->height, ==, 50);
|
||||
g_assert_cmpint (child2->height, ==, 50);
|
||||
g_assert_cmpint (child3->height, ==, 50);
|
||||
|
||||
gtk_widget_unparent (GTK_WIDGET (child1));
|
||||
gtk_widget_unparent (GTK_WIDGET (child2));
|
||||
gtk_widget_unparent (GTK_WIDGET (child3));
|
||||
|
||||
gtk_widget_destroy (parent);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
gtk_test_init (&argc, &argv);
|
||||
|
||||
g_test_add_func ("/grid-layout/row", test_simple_row);
|
||||
g_test_add_func ("/grid-layout/column", test_simple_column);
|
||||
g_test_add_func ("/grid-layout/span", test_spans);
|
||||
g_test_add_func ("/grid-layout/homogeneous", test_homogeneous);
|
||||
g_test_add_func ("/grid-layout/simple", test_simple_layout);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
@@ -17,6 +17,11 @@ tests = [
|
||||
['builderparser'],
|
||||
['cellarea'],
|
||||
['check-icon-names'],
|
||||
['constraint-solver', [
|
||||
'../../gtk/gtkconstraintsolver.c',
|
||||
'../../gtk/gtkconstraintexpression.c',
|
||||
], ['-DGTK_COMPILATION', '-UG_ENABLE_DEBUG']
|
||||
],
|
||||
['cssprovider'],
|
||||
['rbtree-crash', ['../../gtk/gtkrbtree.c'], ['-DGTK_COMPILATION', '-UG_ENABLE_DEBUG']],
|
||||
['defaultvalue'],
|
||||
@@ -28,6 +33,7 @@ tests = [
|
||||
['focus'],
|
||||
['gestures'],
|
||||
['grid'],
|
||||
['grid-layout'],
|
||||
['gtkmenu'],
|
||||
['icontheme'],
|
||||
['keyhash', ['../../gtk/gtkkeyhash.c', gtkresources, '../../gtk/gtkprivate.c'], gtk_cargs],
|
||||
|
||||
Reference in New Issue
Block a user