Compare commits
218 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8eded0ba62 | |||
| b25214aa26 | |||
| 70013161b3 | |||
| 8999bb0b78 | |||
| 7a81b7c7be | |||
| e475d4bdc5 | |||
| 980a6a20b1 | |||
| 064ad42432 | |||
| 4ff9163c47 | |||
| 45ebe47d94 | |||
| 2803bd93ce | |||
| 51161fb0d6 | |||
| 63fd97749c | |||
| f2d736d2cc | |||
| 9b9a656e54 | |||
| 8f734b01b2 | |||
| 69250371b0 | |||
| 731613d70b | |||
| 5f21c45f75 | |||
| 8beea4d958 | |||
| 1583200e24 | |||
| 03fa8ed259 | |||
| 0bd939624e | |||
| b658a1a8e3 | |||
| 7eae9d115c | |||
| 2ca56d4c4c | |||
| f6d7967e96 | |||
| 9bddc0ff85 | |||
| 6e47ebe030 | |||
| 9728dabf12 | |||
| e904c49e8a | |||
| 27ddd39d69 | |||
| 86e907b088 | |||
| 8b46538af9 | |||
| 5910a28aa5 | |||
| 3935027880 | |||
| 8665828d7f | |||
| a8b559e99f | |||
| 5674a3db46 | |||
| dd3acc9014 | |||
| a9364bc053 | |||
| 59313e1459 | |||
| 3e54d374de | |||
| 9856218073 | |||
| d8f91e7df9 | |||
| 91d4e2b3e3 | |||
| e5cccbf5a0 | |||
| 5cfe9ab603 | |||
| 01a6bbdc73 | |||
| 24a4063645 | |||
| 4f11bbc59b | |||
| 9ceb41f9a4 | |||
| 831309eed2 | |||
| 4bb4a98493 | |||
| 70b0f712ad | |||
| c6e9372ba3 | |||
| 13b055ab2d | |||
| 38f4a7708e | |||
| 6abcd8d013 | |||
| 37906a2200 | |||
| b9b5072668 | |||
| 459edfa77b | |||
| 92a79d3f96 | |||
| 984dff54ab | |||
| 1866aa93e3 | |||
| 2884691740 | |||
| b8549a142e | |||
| 0f3ca349e7 | |||
| a13d6bbbdf | |||
| d15dc6f90b | |||
| 58e6c277b0 | |||
| 1d29d44ddb | |||
| bda3c6c084 | |||
| 159913be2f | |||
| b05d1676d3 | |||
| 0b21ed0c7a | |||
| 564a92830b | |||
| a20fd5e14e | |||
| 138986f064 | |||
| f286c99338 | |||
| ea48d1de5e | |||
| dbd2a81501 | |||
| be6ec8f50b | |||
| 264d4bada6 | |||
| 633172fd66 | |||
| 042f7d117f | |||
| b062594ae6 | |||
| 95f30fee87 | |||
| dbc49e7742 | |||
| 449c96ffb3 | |||
| 1459ca2c26 | |||
| 4123c85021 | |||
| d1c37c41d9 | |||
| ea6d3f589f | |||
| 1e6120e776 | |||
| a77f8e886b | |||
| 96b782c026 | |||
| 6455a54f6c | |||
| 3bae6fa1c7 | |||
| 68f19a8e6a | |||
| 12ebbd1b24 | |||
| 9b7bda6137 | |||
| 1b4ed58331 | |||
| b2868d7218 | |||
| bdc8f9dccf | |||
| 9768f35931 | |||
| 19a4ee031d | |||
| a7ee1b4e85 | |||
| 5db079b052 | |||
| a2ff6af4b3 | |||
| f66e764855 | |||
| a8c23d06ac | |||
| 36b4cd4bfc | |||
| 46c59e3c3d | |||
| 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 |
+17
-18
@@ -1,7 +1,7 @@
|
||||
stages:
|
||||
- build
|
||||
- flatpak
|
||||
- deploy
|
||||
# - deploy
|
||||
|
||||
.cache-paths: &cache-paths
|
||||
paths:
|
||||
@@ -101,20 +101,19 @@ flatpak-master:icon-browser:
|
||||
APPID: org.gtk.IconBrowser4
|
||||
<<: *flatpak-master
|
||||
|
||||
pages:
|
||||
image: registry.gitlab.gnome.org/gnome/gtk/master:v6
|
||||
stage: deploy
|
||||
script:
|
||||
- meson -Ddocumentation=true _build .
|
||||
- ninja -C _build
|
||||
- ninja -C _build gdk4-doc gsk4-doc gtk4-doc
|
||||
|
||||
- mkdir -p public/
|
||||
- mv _build/docs/reference/gtk/html/ public/gtk/
|
||||
- mv _build/docs/reference/gdk/html/ public/gdk/
|
||||
- mv _build/docs/reference/gsk/html/ public/gsk/
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
only:
|
||||
- master
|
||||
#pages:
|
||||
# image: registry.gitlab.gnome.org/gnome/gtk/master:v6
|
||||
# stage: deploy
|
||||
# script:
|
||||
# - meson -Dgtk_doc=true _build .
|
||||
# - ninja -C _build
|
||||
# - ninja -C _build gdk4-doc gsk4-doc gtk4-doc
|
||||
# - mkdir -p public/
|
||||
# - mv _build/docs/reference/gtk/html/ public/gtk/
|
||||
# - mv _build/docs/reference/gdk/html/ public/gdk/
|
||||
# - mv _build/docs/reference/gsk/html/ public/gsk/
|
||||
# artifacts:
|
||||
# paths:
|
||||
# - public
|
||||
# only:
|
||||
# - master
|
||||
|
||||
@@ -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,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,639 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
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);
|
||||
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
|
||||
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));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (GTK_IS_CONSTRAINT (item) || GTK_IS_CONSTRAINT_GUIDE (item))
|
||||
{
|
||||
button = gtk_button_new_from_icon_name ("document-edit-symbolic");
|
||||
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (row_edit), win);
|
||||
g_object_set_data (G_OBJECT (row), "edit", button);
|
||||
gtk_container_add (GTK_CONTAINER (box), button);
|
||||
button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
|
||||
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (row_delete), win);
|
||||
gtk_container_add (GTK_CONTAINER (box), button);
|
||||
}
|
||||
else if (GTK_IS_WIDGET (item))
|
||||
{
|
||||
button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
|
||||
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (row_delete), win);
|
||||
gtk_container_add (GTK_CONTAINER (box), button);
|
||||
}
|
||||
|
||||
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,656 @@
|
||||
/*
|
||||
* 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 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));
|
||||
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);
|
||||
|
||||
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_nick (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));
|
||||
c = g_ascii_strtod (constant, NULL);
|
||||
|
||||
attr = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source_attr));
|
||||
if (strcmp (attr, "none") != 0)
|
||||
{
|
||||
name = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source));
|
||||
multiplier = gtk_editable_get_text (GTK_EDITABLE (editor->multiplier));
|
||||
m = g_ascii_strtod (multiplier, NULL);
|
||||
|
||||
if (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_combo_box_get_active_id (GTK_COMBO_BOX (editor->source)) != 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,12 @@
|
||||
constraintview {
|
||||
background: black;
|
||||
color: white;
|
||||
}
|
||||
|
||||
constraintview .child {
|
||||
background: red;
|
||||
}
|
||||
|
||||
constraintview .guide {
|
||||
background: blue;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?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>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,343 @@
|
||||
/* 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"
|
||||
|
||||
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;
|
||||
|
||||
widget = gtk_widget_pick (GTK_WIDGET (self), start_x, start_y, GTK_PICK_DEFAULT);
|
||||
|
||||
if (GTK_IS_LABEL (widget))
|
||||
{
|
||||
widget = gtk_widget_get_ancestor (widget, GTK_TYPE_FRAME);
|
||||
if (widget &&
|
||||
gtk_widget_get_parent (widget) == (GtkWidget *)self)
|
||||
{
|
||||
self->drag_widget = widget;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
label = gtk_label_new (name);
|
||||
frame = gtk_frame_new (NULL);
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (frame), "child");
|
||||
gtk_widget_set_name (frame, name);
|
||||
gtk_container_add (GTK_CONTAINER (frame), label);
|
||||
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 *frame;
|
||||
GtkWidget *label;
|
||||
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);
|
||||
label = gtk_label_new (name);
|
||||
g_object_bind_property (guide, "name",
|
||||
label, "label",
|
||||
G_BINDING_DEFAULT);
|
||||
|
||||
frame = gtk_frame_new (NULL);
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (frame), "guide");
|
||||
g_object_set_data (G_OBJECT (frame), "internal", "yes");
|
||||
gtk_container_add (GTK_CONTAINER (frame), label);
|
||||
gtk_widget_insert_after (frame, GTK_WIDGET (view), NULL);
|
||||
|
||||
g_object_set_data (G_OBJECT (guide), "frame", frame);
|
||||
|
||||
layout = GTK_CONSTRAINT_LAYOUT (gtk_widget_get_layout_manager (GTK_WIDGET (view)));
|
||||
gtk_constraint_layout_add_guide (layout, g_object_ref (guide));
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (names); i++)
|
||||
{
|
||||
constraint = gtk_constraint_new (frame,
|
||||
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, frame, 150, 150);
|
||||
}
|
||||
|
||||
void
|
||||
constraint_view_remove_guide (ConstraintView *view,
|
||||
GtkConstraintGuide *guide)
|
||||
{
|
||||
GtkConstraintLayout *layout;
|
||||
GtkWidget *frame;
|
||||
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);
|
||||
}
|
||||
|
||||
frame = (GtkWidget *)g_object_get_data (G_OBJECT (guide), "frame");
|
||||
update_weak_position (view, frame, -100, -100);
|
||||
gtk_widget_unparent (frame);
|
||||
|
||||
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,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,20 @@
|
||||
constraint_editor_sources = [
|
||||
'main.c',
|
||||
'constraint-editor-application.c',
|
||||
'constraint-editor-window.c',
|
||||
'constraint-view.c',
|
||||
'constraint-editor.c',
|
||||
'guide-editor.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,
|
||||
link_args: extra_demo_ldflags,
|
||||
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>
|
||||
|
||||
@@ -306,6 +306,7 @@ do_fishbowl (GtkWidget *do_widget)
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
gtk_widget_realize (window);
|
||||
g_object_unref (builder);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -707,6 +707,14 @@ static void
|
||||
node_editor_window_unrealize (GtkWidget *widget)
|
||||
{
|
||||
NodeEditorWindow *self = NODE_EDITOR_WINDOW (widget);
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (self->renderers)); i ++)
|
||||
{
|
||||
gpointer item = g_list_model_get_item (G_LIST_MODEL (self->renderers), i);
|
||||
gsk_renderer_unrealize (gtk_renderer_paintable_get_renderer (item));
|
||||
g_object_unref (item);
|
||||
}
|
||||
|
||||
g_list_store_remove_all (self->renderers);
|
||||
|
||||
|
||||
@@ -1405,8 +1405,10 @@ text_view_add_to_context_menu (GtkTextView *text_view)
|
||||
item = g_menu_item_new (_("Underline"), "format.underline");
|
||||
g_menu_item_set_attribute (item, "touch-icon", "s", "format-text-underline-symbolic");
|
||||
g_menu_append_item (G_MENU (menu), item);
|
||||
g_object_unref (item);
|
||||
|
||||
gtk_text_view_set_extra_menu (text_view, G_MENU_MODEL (menu));
|
||||
g_object_unref (menu);
|
||||
|
||||
g_signal_connect (gtk_text_view_get_buffer (text_view), "changed", G_CALLBACK (text_changed), NULL);
|
||||
g_signal_connect (gtk_text_view_get_buffer (text_view), "mark-set", G_CALLBACK (text_changed), NULL);
|
||||
@@ -1707,7 +1709,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">
|
||||
|
||||
@@ -4432,7 +4432,6 @@ gtk_widget_realize
|
||||
gtk_widget_unrealize
|
||||
gtk_widget_queue_draw
|
||||
gtk_widget_queue_resize
|
||||
gtk_widget_queue_resize_no_redraw
|
||||
gtk_widget_queue_allocate
|
||||
gtk_widget_get_frame_clock
|
||||
gtk_widget_get_scale_factor
|
||||
@@ -4604,7 +4603,6 @@ gtk_widget_get_vexpand
|
||||
gtk_widget_set_vexpand
|
||||
gtk_widget_get_vexpand_set
|
||||
gtk_widget_set_vexpand_set
|
||||
gtk_widget_queue_compute_expand
|
||||
gtk_widget_compute_expand
|
||||
|
||||
<SUBSECTION Templates>
|
||||
@@ -7287,3 +7285,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',
|
||||
|
||||
@@ -88,10 +88,10 @@ gdk_broadway_surface_finalize (GObject *object)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
thaw_clock_cb (GdkFrameClock *clock)
|
||||
thaw_updates_cb (GdkSurface *surface)
|
||||
{
|
||||
_gdk_frame_clock_thaw (clock);
|
||||
g_object_unref (clock);
|
||||
gdk_surface_thaw_updates (surface);
|
||||
g_object_unref (surface);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
@@ -109,9 +109,9 @@ _gdk_broadway_roundtrip_notify (GdkSurface *surface,
|
||||
|
||||
/* If there is no remote web client, rate limit update to once a second */
|
||||
if (local_reply)
|
||||
g_timeout_add_seconds (1, (GSourceFunc)thaw_clock_cb, g_object_ref (clock));
|
||||
g_timeout_add_seconds (1, (GSourceFunc)thaw_updates_cb, g_object_ref (surface));
|
||||
else
|
||||
_gdk_frame_clock_thaw (clock);
|
||||
gdk_surface_thaw_updates (surface);
|
||||
|
||||
if (timings)
|
||||
{
|
||||
@@ -140,7 +140,7 @@ on_frame_clock_after_paint (GdkFrameClock *clock,
|
||||
GdkBroadwayDisplay *broadway_display;
|
||||
|
||||
impl->pending_frame_counter = gdk_frame_clock_get_frame_counter (clock);
|
||||
_gdk_frame_clock_freeze (gdk_surface_get_frame_clock (surface));
|
||||
gdk_surface_freeze_updates (surface);
|
||||
|
||||
broadway_display = GDK_BROADWAY_DISPLAY (display);
|
||||
|
||||
|
||||
+44
-2
@@ -97,10 +97,14 @@ struct _GdkFrameClockPrivate
|
||||
gint n_timings;
|
||||
gint current;
|
||||
GdkFrameTimings *timings[FRAME_HISTORY_MAX_LENGTH];
|
||||
gint n_freeze_inhibitors;
|
||||
};
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GdkFrameClock, gdk_frame_clock, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
_gdk_frame_clock_freeze (GdkFrameClock *clock);
|
||||
|
||||
static void
|
||||
gdk_frame_clock_finalize (GObject *object)
|
||||
{
|
||||
@@ -114,12 +118,21 @@ gdk_frame_clock_finalize (GObject *object)
|
||||
G_OBJECT_CLASS (gdk_frame_clock_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_frame_clock_constructed (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (gdk_frame_clock_parent_class)->constructed (object);
|
||||
|
||||
_gdk_frame_clock_freeze (GDK_FRAME_CLOCK (object));
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_frame_clock_class_init (GdkFrameClockClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass*) klass;
|
||||
|
||||
gobject_class->finalize = gdk_frame_clock_finalize;
|
||||
gobject_class->constructed = gdk_frame_clock_constructed;
|
||||
|
||||
/**
|
||||
* GdkFrameClock::flush-events:
|
||||
@@ -335,7 +348,7 @@ gdk_frame_clock_end_updating (GdkFrameClock *frame_clock)
|
||||
GDK_FRAME_CLOCK_GET_CLASS (frame_clock)->end_updating (frame_clock);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
_gdk_frame_clock_freeze (GdkFrameClock *clock)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_FRAME_CLOCK (clock));
|
||||
@@ -344,7 +357,7 @@ _gdk_frame_clock_freeze (GdkFrameClock *clock)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
static void
|
||||
_gdk_frame_clock_thaw (GdkFrameClock *clock)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_FRAME_CLOCK (clock));
|
||||
@@ -352,6 +365,35 @@ _gdk_frame_clock_thaw (GdkFrameClock *clock)
|
||||
GDK_FRAME_CLOCK_GET_CLASS (clock)->thaw (clock);
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_frame_clock_inhibit_freeze (GdkFrameClock *clock)
|
||||
{
|
||||
GdkFrameClockPrivate *priv;
|
||||
|
||||
g_return_if_fail (GDK_IS_FRAME_CLOCK (clock));
|
||||
|
||||
priv = clock->priv;
|
||||
|
||||
priv->n_freeze_inhibitors++;
|
||||
if (priv->n_freeze_inhibitors == 1)
|
||||
_gdk_frame_clock_thaw (clock);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_gdk_frame_clock_uninhibit_freeze (GdkFrameClock *clock)
|
||||
{
|
||||
GdkFrameClockPrivate *priv;
|
||||
|
||||
g_return_if_fail (GDK_IS_FRAME_CLOCK (clock));
|
||||
|
||||
priv = clock->priv;
|
||||
|
||||
priv->n_freeze_inhibitors--;
|
||||
if (priv->n_freeze_inhibitors == 0)
|
||||
_gdk_frame_clock_freeze (clock);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_frame_clock_get_frame_counter:
|
||||
* @frame_clock: a #GdkFrameClock
|
||||
|
||||
@@ -105,8 +105,8 @@ struct _GdkFrameTimings
|
||||
guint slept_before : 1;
|
||||
};
|
||||
|
||||
void _gdk_frame_clock_freeze (GdkFrameClock *clock);
|
||||
void _gdk_frame_clock_thaw (GdkFrameClock *clock);
|
||||
void _gdk_frame_clock_inhibit_freeze (GdkFrameClock *clock);
|
||||
void _gdk_frame_clock_uninhibit_freeze (GdkFrameClock *clock);
|
||||
|
||||
void _gdk_frame_clock_begin_frame (GdkFrameClock *clock);
|
||||
void _gdk_frame_clock_debug_print_timings (GdkFrameClock *clock,
|
||||
|
||||
+56
-42
@@ -1341,10 +1341,14 @@ gdk_surface_schedule_update (GdkSurface *surface)
|
||||
{
|
||||
GdkFrameClock *frame_clock;
|
||||
|
||||
if (surface &&
|
||||
(surface->update_freeze_count ||
|
||||
gdk_surface_is_toplevel_frozen (surface)))
|
||||
return;
|
||||
g_return_if_fail (surface);
|
||||
|
||||
if (surface->update_freeze_count ||
|
||||
gdk_surface_is_toplevel_frozen (surface))
|
||||
{
|
||||
surface->pending_schedule_update = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If there's no frame clock (a foreign surface), then the invalid
|
||||
* region will just stick around unless gdk_surface_process_updates()
|
||||
@@ -1400,7 +1404,6 @@ gdk_surface_paint_on_clock (GdkFrameClock *clock,
|
||||
void *data)
|
||||
{
|
||||
GdkSurface *surface = GDK_SURFACE (data);
|
||||
GList *l;
|
||||
|
||||
g_return_if_fail (GDK_IS_SURFACE (surface));
|
||||
|
||||
@@ -1421,9 +1424,6 @@ gdk_surface_paint_on_clock (GdkFrameClock *clock,
|
||||
gdk_surface_remove_update_surface (surface);
|
||||
}
|
||||
|
||||
for (l = surface->children; l; l = l->next)
|
||||
gdk_surface_paint_on_clock (clock, l->data);
|
||||
|
||||
g_object_unref (surface);
|
||||
}
|
||||
|
||||
@@ -1581,13 +1581,17 @@ gdk_surface_freeze_updates (GdkSurface *surface)
|
||||
g_return_if_fail (GDK_IS_SURFACE (surface));
|
||||
|
||||
surface->update_freeze_count++;
|
||||
if (surface->update_freeze_count == 1)
|
||||
_gdk_frame_clock_uninhibit_freeze (surface->frame_clock);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_surface_thaw_updates:
|
||||
* @surface: a #GdkSurface
|
||||
*
|
||||
* Thaws a surface frozen with gdk_surface_freeze_updates().
|
||||
* Thaws a surface frozen with gdk_surface_freeze_updates(). Note that this
|
||||
* will not necessarily schedule updates if the surface freeze count reaches
|
||||
* zero.
|
||||
**/
|
||||
void
|
||||
gdk_surface_thaw_updates (GdkSurface *surface)
|
||||
@@ -1597,7 +1601,15 @@ gdk_surface_thaw_updates (GdkSurface *surface)
|
||||
g_return_if_fail (surface->update_freeze_count > 0);
|
||||
|
||||
if (--surface->update_freeze_count == 0)
|
||||
gdk_surface_schedule_update (surface);
|
||||
{
|
||||
_gdk_frame_clock_inhibit_freeze (surface->frame_clock);
|
||||
|
||||
if (surface->pending_schedule_update)
|
||||
{
|
||||
surface->pending_schedule_update = FALSE;
|
||||
gdk_surface_schedule_update (surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1606,7 +1618,7 @@ gdk_surface_freeze_toplevel_updates (GdkSurface *surface)
|
||||
g_return_if_fail (GDK_IS_SURFACE (surface));
|
||||
|
||||
surface->update_and_descendants_freeze_count++;
|
||||
_gdk_frame_clock_freeze (gdk_surface_get_frame_clock (surface));
|
||||
gdk_surface_freeze_updates (surface);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1616,9 +1628,9 @@ gdk_surface_thaw_toplevel_updates (GdkSurface *surface)
|
||||
g_return_if_fail (surface->update_and_descendants_freeze_count > 0);
|
||||
|
||||
surface->update_and_descendants_freeze_count--;
|
||||
_gdk_frame_clock_thaw (gdk_surface_get_frame_clock (surface));
|
||||
|
||||
gdk_surface_schedule_update (surface);
|
||||
gdk_surface_thaw_updates (surface);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3703,40 +3715,42 @@ gdk_surface_set_frame_clock (GdkSurface *surface,
|
||||
if (clock)
|
||||
{
|
||||
g_object_ref (clock);
|
||||
if (surface->parent == NULL)
|
||||
{
|
||||
g_signal_connect (G_OBJECT (clock),
|
||||
"flush-events",
|
||||
G_CALLBACK (gdk_surface_flush_events),
|
||||
surface);
|
||||
g_signal_connect (G_OBJECT (clock),
|
||||
"resume-events",
|
||||
G_CALLBACK (gdk_surface_resume_events),
|
||||
surface);
|
||||
g_signal_connect (G_OBJECT (clock),
|
||||
"paint",
|
||||
G_CALLBACK (gdk_surface_paint_on_clock),
|
||||
surface);
|
||||
}
|
||||
|
||||
g_signal_connect (G_OBJECT (clock),
|
||||
"flush-events",
|
||||
G_CALLBACK (gdk_surface_flush_events),
|
||||
surface);
|
||||
g_signal_connect (G_OBJECT (clock),
|
||||
"resume-events",
|
||||
G_CALLBACK (gdk_surface_resume_events),
|
||||
surface);
|
||||
g_signal_connect (G_OBJECT (clock),
|
||||
"paint",
|
||||
G_CALLBACK (gdk_surface_paint_on_clock),
|
||||
surface);
|
||||
|
||||
if (surface->update_freeze_count == 0)
|
||||
_gdk_frame_clock_inhibit_freeze (clock);
|
||||
}
|
||||
|
||||
if (surface->frame_clock)
|
||||
{
|
||||
if (surface->parent == NULL)
|
||||
{
|
||||
if (surface->frame_clock_events_paused)
|
||||
gdk_surface_resume_events (surface->frame_clock, G_OBJECT (surface));
|
||||
if (surface->frame_clock_events_paused)
|
||||
gdk_surface_resume_events (surface->frame_clock, G_OBJECT (surface));
|
||||
|
||||
g_signal_handlers_disconnect_by_func (G_OBJECT (surface->frame_clock),
|
||||
G_CALLBACK (gdk_surface_flush_events),
|
||||
surface);
|
||||
g_signal_handlers_disconnect_by_func (G_OBJECT (surface->frame_clock),
|
||||
G_CALLBACK (gdk_surface_resume_events),
|
||||
surface);
|
||||
g_signal_handlers_disconnect_by_func (G_OBJECT (surface->frame_clock),
|
||||
G_CALLBACK (gdk_surface_paint_on_clock),
|
||||
surface);
|
||||
|
||||
if (surface->update_freeze_count == 0)
|
||||
_gdk_frame_clock_uninhibit_freeze (surface->frame_clock);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (G_OBJECT (surface->frame_clock),
|
||||
G_CALLBACK (gdk_surface_flush_events),
|
||||
surface);
|
||||
g_signal_handlers_disconnect_by_func (G_OBJECT (surface->frame_clock),
|
||||
G_CALLBACK (gdk_surface_resume_events),
|
||||
surface);
|
||||
g_signal_handlers_disconnect_by_func (G_OBJECT (surface->frame_clock),
|
||||
G_CALLBACK (gdk_surface_paint_on_clock),
|
||||
surface);
|
||||
}
|
||||
g_object_unref (surface->frame_clock);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ struct _GdkSurface
|
||||
|
||||
cairo_region_t *update_area;
|
||||
guint update_freeze_count;
|
||||
gboolean pending_schedule_update;
|
||||
/* This is the update_area that was in effect when the current expose
|
||||
started. It may be smaller than the expose area if we'e painting
|
||||
more than we have to, but it represents the "true" damage. */
|
||||
|
||||
@@ -349,7 +349,7 @@ frame_callback (void *data,
|
||||
return;
|
||||
|
||||
impl->awaiting_frame = FALSE;
|
||||
_gdk_frame_clock_thaw (clock);
|
||||
gdk_surface_thaw_updates (surface);
|
||||
|
||||
timings = gdk_frame_clock_get_timings (clock, impl->pending_frame_counter);
|
||||
impl->pending_frame_counter = 0;
|
||||
@@ -465,8 +465,9 @@ on_frame_clock_after_paint (GdkFrameClock *clock,
|
||||
g_signal_emit (impl, signals[COMMITTED], 0);
|
||||
}
|
||||
|
||||
if (impl->awaiting_frame)
|
||||
_gdk_frame_clock_freeze (clock);
|
||||
if (impl->awaiting_frame &&
|
||||
impl->pending_frame_counter == gdk_frame_clock_get_frame_counter (clock))
|
||||
gdk_surface_freeze_updates (surface);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2577,12 +2578,8 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface)
|
||||
|
||||
if (impl->awaiting_frame)
|
||||
{
|
||||
GdkFrameClock *frame_clock;
|
||||
|
||||
impl->awaiting_frame = FALSE;
|
||||
frame_clock = gdk_surface_get_frame_clock (surface);
|
||||
if (frame_clock)
|
||||
_gdk_frame_clock_thaw (frame_clock);
|
||||
gdk_surface_thaw_updates (surface);
|
||||
}
|
||||
|
||||
if (impl->display_server.gtk_surface)
|
||||
|
||||
@@ -874,7 +874,7 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
|
||||
surface_impl->toplevel->frame_pending)
|
||||
{
|
||||
surface_impl->toplevel->frame_pending = FALSE;
|
||||
_gdk_frame_clock_thaw (gdk_surface_get_frame_clock (event->any.surface));
|
||||
gdk_surface_thaw_updates (event->any.surface);
|
||||
}
|
||||
|
||||
if (toplevel)
|
||||
@@ -1238,7 +1238,7 @@ _gdk_wm_protocols_filter (const XEvent *xevent,
|
||||
if (surface_impl->toplevel->frame_pending)
|
||||
{
|
||||
surface_impl->toplevel->frame_pending = FALSE;
|
||||
_gdk_frame_clock_thaw (clock);
|
||||
gdk_surface_thaw_updates (event->any.surface);
|
||||
}
|
||||
|
||||
gdk_frame_clock_get_refresh_info (clock,
|
||||
|
||||
@@ -503,6 +503,7 @@ gdk_x11_selection_output_stream_invoke_close (gpointer stream)
|
||||
g_signal_handlers_disconnect_by_func (priv->display,
|
||||
gdk_x11_selection_output_stream_xevent,
|
||||
stream);
|
||||
g_object_unref (stream);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
@@ -512,7 +513,7 @@ gdk_x11_selection_output_stream_close (GOutputStream *stream,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_main_context_invoke (NULL, gdk_x11_selection_output_stream_invoke_close, stream);
|
||||
g_main_context_invoke (NULL, gdk_x11_selection_output_stream_invoke_close, g_object_ref (stream));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -397,7 +397,7 @@ gdk_x11_surface_end_frame (GdkSurface *surface)
|
||||
g_intern_static_string ("_NET_WM_FRAME_DRAWN")))
|
||||
{
|
||||
impl->toplevel->frame_pending = TRUE;
|
||||
_gdk_frame_clock_freeze (gdk_surface_get_frame_clock (surface));
|
||||
gdk_surface_freeze_updates (surface);
|
||||
timings->cookie = impl->toplevel->current_counter_value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,10 +193,10 @@ upload_glyph (GlyphCacheKey *key,
|
||||
if (render_glyph (key, value, &r))
|
||||
{
|
||||
glBindTexture (GL_TEXTURE_2D, value->texture_id);
|
||||
glTextureSubImage2D (value->texture_id, 0,
|
||||
r.x, r.y, r.width, r.height,
|
||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
r.data);
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0,
|
||||
r.x, r.y, r.width, r.height,
|
||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
r.data);
|
||||
g_free (r.data);
|
||||
}
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ upload_region_or_else (GskGLIconCache *self,
|
||||
GskImageRegion *region)
|
||||
{
|
||||
glBindTexture (GL_TEXTURE_2D, texture_id);
|
||||
glTextureSubImage2D (texture_id, 0, region->x, region->y, region->width, region->height,
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0, region->x, region->y, region->width, region->height,
|
||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, region->data);
|
||||
}
|
||||
|
||||
|
||||
+56
-21
@@ -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);
|
||||
@@ -1017,12 +1015,49 @@ render_opacity_node (GskGLRenderer *self,
|
||||
GskRenderNode *node,
|
||||
RenderOpBuilder *builder)
|
||||
{
|
||||
GskRenderNode *child = gsk_opacity_node_get_child (node);
|
||||
const float opacity = gsk_opacity_node_get_opacity (node);
|
||||
float prev_opacity;
|
||||
|
||||
prev_opacity = ops_set_opacity (builder,
|
||||
builder->current_opacity * gsk_opacity_node_get_opacity (node));
|
||||
if (gsk_render_node_get_node_type (child) == GSK_CONTAINER_NODE)
|
||||
{
|
||||
const float min_x = builder->dx + node->bounds.origin.x;
|
||||
const float min_y = builder->dy + node->bounds.origin.y;
|
||||
const float max_x = min_x + node->bounds.size.width;
|
||||
const float max_y = min_y + node->bounds.size.height;
|
||||
gboolean is_offscreen;
|
||||
TextureRegion region;
|
||||
|
||||
gsk_gl_renderer_add_render_ops (self, gsk_opacity_node_get_child (node), builder);
|
||||
/* The semantics of an opacity node mandate that when, e.g., two color nodes overlap,
|
||||
* there may not be any blending between them */
|
||||
add_offscreen_ops (self, builder, &child->bounds,
|
||||
child,
|
||||
®ion, &is_offscreen,
|
||||
FORCE_OFFSCREEN | RESET_OPACITY | RESET_CLIP);
|
||||
|
||||
prev_opacity = ops_set_opacity (builder,
|
||||
builder->current_opacity * opacity);
|
||||
|
||||
ops_set_program (builder, &self->blit_program);
|
||||
ops_set_texture (builder, region.texture_id);
|
||||
|
||||
ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
|
||||
{ { min_x, min_y }, { region.x, region.y2 }, },
|
||||
{ { min_x, max_y }, { region.x, region.y }, },
|
||||
{ { max_x, min_y }, { region.x2, region.y2 }, },
|
||||
|
||||
{ { max_x, max_y }, { region.x2, region.y }, },
|
||||
{ { min_x, max_y }, { region.x, region.y }, },
|
||||
{ { max_x, min_y }, { region.x2, region.y2 }, },
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
prev_opacity = ops_set_opacity (builder,
|
||||
builder->current_opacity * opacity);
|
||||
|
||||
gsk_gl_renderer_add_render_ops (self, child, builder);
|
||||
}
|
||||
|
||||
ops_set_opacity (builder, prev_opacity);
|
||||
}
|
||||
@@ -1292,7 +1327,7 @@ render_rounded_clip_node (GskGLRenderer *self,
|
||||
{ { min_x, min_y }, { 0, 1 }, },
|
||||
{ { min_x, max_y }, { 0, 0 }, },
|
||||
{ { max_x, min_y }, { 1, 1 }, },
|
||||
|
||||
|
||||
{ { max_x, max_y }, { 1, 0 }, },
|
||||
{ { min_x, max_y }, { 0, 0 }, },
|
||||
{ { max_x, min_y }, { 1, 1 }, },
|
||||
@@ -1393,7 +1428,7 @@ render_blur_node (GskGLRenderer *self,
|
||||
ops_set_program (builder, &self->blur_program);
|
||||
op.op = OP_CHANGE_BLUR;
|
||||
graphene_size_init_from_size (&op.blur.size, &node->bounds.size);
|
||||
op.blur.radius = gsk_blur_node_get_radius (node);
|
||||
op.blur.radius = blur_radius;
|
||||
ops_add (builder, &op);
|
||||
|
||||
ops_set_texture (builder, region.texture_id);
|
||||
@@ -1404,7 +1439,7 @@ render_blur_node (GskGLRenderer *self,
|
||||
{ { min_x, min_y }, { 0, 1 }, },
|
||||
{ { min_x, max_y }, { 0, 0 }, },
|
||||
{ { max_x, min_y }, { 1, 1 }, },
|
||||
|
||||
|
||||
{ { max_x, max_y }, { 1, 0 }, },
|
||||
{ { min_x, max_y }, { 0, 0 }, },
|
||||
{ { max_x, min_y }, { 1, 1 }, },
|
||||
@@ -1855,10 +1890,10 @@ render_shadow_node (GskGLRenderer *self,
|
||||
RenderOpBuilder *builder,
|
||||
const GskQuadVertex *vertex_data)
|
||||
{
|
||||
float min_x = node->bounds.origin.x;
|
||||
float min_y = node->bounds.origin.y;
|
||||
float max_x = min_x + node->bounds.size.width;
|
||||
float max_y = min_y + node->bounds.size.height;
|
||||
float min_x;
|
||||
float min_y;
|
||||
float max_x;
|
||||
float max_y;
|
||||
GskRenderNode *original_child = gsk_shadow_node_get_child (node);
|
||||
GskRenderNode *shadow_child = original_child;
|
||||
gsize n_shadows = gsk_shadow_node_get_n_shadows (node);
|
||||
@@ -1884,6 +1919,11 @@ render_shadow_node (GskGLRenderer *self,
|
||||
shadow_child = gsk_color_matrix_node_get_child (shadow_child);
|
||||
}
|
||||
|
||||
min_x = builder->dx + shadow_child->bounds.origin.x;
|
||||
min_y = builder->dy + shadow_child->bounds.origin.y;
|
||||
max_x = min_x + shadow_child->bounds.size.width;
|
||||
max_y = min_y + shadow_child->bounds.size.height;
|
||||
|
||||
for (i = 0; i < n_shadows; i ++)
|
||||
{
|
||||
const GskShadow *shadow = gsk_shadow_node_peek_shadow (node, i);
|
||||
@@ -1905,11 +1945,6 @@ render_shadow_node (GskGLRenderer *self,
|
||||
if (gdk_rgba_is_clear (&shadow->color))
|
||||
continue;
|
||||
|
||||
min_x = builder->dx + shadow_child->bounds.origin.x;
|
||||
min_y = builder->dy + shadow_child->bounds.origin.y;
|
||||
max_x = min_x + shadow_child->bounds.size.width;
|
||||
max_y = min_y + shadow_child->bounds.size.height;
|
||||
|
||||
/* Draw the child offscreen, without the offset. */
|
||||
add_offscreen_ops (self, builder,
|
||||
&shadow_child->bounds,
|
||||
@@ -2344,6 +2379,7 @@ gsk_gl_renderer_dispose (GObject *gobject)
|
||||
GskGLRenderer *self = GSK_GL_RENDERER (gobject);
|
||||
|
||||
g_clear_pointer (&self->render_ops, g_array_unref);
|
||||
ops_free (&self->op_builder);
|
||||
|
||||
G_OBJECT_CLASS (gsk_gl_renderer_parent_class)->dispose (gobject);
|
||||
}
|
||||
@@ -3160,7 +3196,7 @@ gsk_gl_renderer_do_render (GskRenderer *renderer,
|
||||
int scale_factor)
|
||||
{
|
||||
GskGLRenderer *self = GSK_GL_RENDERER (renderer);
|
||||
graphene_matrix_t modelview, projection;
|
||||
graphene_matrix_t projection;
|
||||
gsize buffer_size;
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
GskProfiler *profiler;
|
||||
@@ -3180,7 +3216,6 @@ gsk_gl_renderer_do_render (GskRenderer *renderer,
|
||||
g_assert (gsk_gl_driver_in_frame (self->gl_driver));
|
||||
|
||||
/* Set up the modelview and projection matrices to fit our viewport */
|
||||
graphene_matrix_init_scale (&modelview, scale_factor, scale_factor, 1.0);
|
||||
graphene_matrix_init_ortho (&projection,
|
||||
viewport->origin.x,
|
||||
viewport->origin.x + viewport->size.width,
|
||||
|
||||
@@ -187,6 +187,17 @@ ops_init (RenderOpBuilder *builder)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ops_free (RenderOpBuilder *builder)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < GL_N_PROGRAMS; i ++)
|
||||
{
|
||||
gsk_transform_unref (builder->program_state[i].modelview);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ops_set_program (RenderOpBuilder *builder,
|
||||
const Program *program)
|
||||
@@ -225,6 +236,7 @@ ops_set_program (RenderOpBuilder *builder,
|
||||
op.op = OP_CHANGE_MODELVIEW;
|
||||
gsk_transform_to_matrix (builder->current_modelview, &op.modelview);
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
gsk_transform_unref (program_state->modelview);
|
||||
program_state->modelview = gsk_transform_ref (builder->current_modelview);
|
||||
}
|
||||
|
||||
@@ -339,9 +351,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);
|
||||
|
||||
|
||||
@@ -290,6 +290,7 @@ void ops_dump_framebuffer (RenderOpBuilder *builder,
|
||||
int width,
|
||||
int height);
|
||||
void ops_init (RenderOpBuilder *builder);
|
||||
void ops_free (RenderOpBuilder *builder);
|
||||
void ops_push_debug_group (RenderOpBuilder *builder,
|
||||
const char *text);
|
||||
void ops_pop_debug_group (RenderOpBuilder *builder);
|
||||
|
||||
@@ -1966,14 +1966,14 @@ gsk_transform_node_diff (GskRenderNode *node1,
|
||||
cairo_region_t *tmp = cairo_region_copy (sub);
|
||||
cairo_region_translate (tmp, 1, 0);
|
||||
cairo_region_union (sub, tmp);
|
||||
cairo_region_destroy (sub);
|
||||
cairo_region_destroy (tmp);
|
||||
}
|
||||
if (floor (dy) != dy)
|
||||
{
|
||||
cairo_region_t *tmp = cairo_region_copy (sub);
|
||||
cairo_region_translate (tmp, 0, 1);
|
||||
cairo_region_union (sub, tmp);
|
||||
cairo_region_destroy (sub);
|
||||
cairo_region_destroy (tmp);
|
||||
}
|
||||
cairo_region_union (region, sub);
|
||||
cairo_region_destroy (sub);
|
||||
|
||||
@@ -94,6 +94,7 @@ parse_texture (GtkCssParser *parser,
|
||||
if (bytes)
|
||||
{
|
||||
stream = g_memory_input_stream_new_from_bytes (bytes);
|
||||
g_bytes_unref (bytes);
|
||||
pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, &error);
|
||||
g_object_unref (stream);
|
||||
if (pixbuf != NULL)
|
||||
@@ -748,6 +749,8 @@ parse_glyphs (GtkCssParser *parser,
|
||||
pango_glyph_string_set_size (glyph_string, glyph_string->num_glyphs + 1);
|
||||
glyph_string->glyphs[glyph_string->num_glyphs - 1] = gi;
|
||||
}
|
||||
|
||||
g_free (s);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -817,7 +820,7 @@ parse_container_node (GtkCssParser *parser)
|
||||
token = gtk_css_parser_get_token (parser))
|
||||
{
|
||||
node = NULL;
|
||||
/* We don't wand a semicolon here, but the parse_node function will figure
|
||||
/* We don't want a semicolon here, but the parse_node function will figure
|
||||
* that out itself and return an error if we encounter one.
|
||||
*/
|
||||
gtk_css_parser_start_semicolon_block (parser, GTK_CSS_TOKEN_OPEN_CURLY);
|
||||
|
||||
+49
-9
@@ -646,7 +646,7 @@ gsk_transform_translate_3d (GskTransform *next,
|
||||
GskTranslateTransform *result;
|
||||
|
||||
if (graphene_point3d_equal (point, graphene_point3d_zero ()))
|
||||
return gsk_transform_ref (next);
|
||||
return next;
|
||||
|
||||
if (gsk_transform_has_class (next, &GSK_TRANSLATE_TRANSFORM_CLASS))
|
||||
{
|
||||
@@ -801,7 +801,7 @@ gsk_transform_rotate (GskTransform *next,
|
||||
GskRotateTransform *result;
|
||||
|
||||
if (angle == 0.0f)
|
||||
return gsk_transform_ref (next);
|
||||
return next;
|
||||
|
||||
if (gsk_transform_has_class (next, &GSK_ROTATE_TRANSFORM_CLASS))
|
||||
{
|
||||
@@ -932,7 +932,7 @@ gsk_transform_rotate_3d (GskTransform *next,
|
||||
return gsk_transform_rotate (next, angle);
|
||||
|
||||
if (angle == 0.0f)
|
||||
return gsk_transform_ref (next);
|
||||
return next;
|
||||
|
||||
result = gsk_transform_alloc (&GSK_ROTATE3D_TRANSFORM_CLASS,
|
||||
GSK_TRANSFORM_CATEGORY_3D,
|
||||
@@ -1121,7 +1121,7 @@ gsk_transform_scale_3d (GskTransform *next,
|
||||
GskScaleTransform *result;
|
||||
|
||||
if (factor_x == 1 && factor_y == 1 && factor_z == 1)
|
||||
return gsk_transform_ref (next);
|
||||
return next;
|
||||
|
||||
if (gsk_transform_has_class (next, &GSK_SCALE_TRANSFORM_CLASS))
|
||||
{
|
||||
@@ -1250,7 +1250,7 @@ gsk_transform_perspective (GskTransform *next,
|
||||
float depth)
|
||||
{
|
||||
GskPerspectiveTransform *result;
|
||||
|
||||
|
||||
if (gsk_transform_has_class (next, &GSK_PERSPECTIVE_TRANSFORM_CLASS))
|
||||
{
|
||||
GskTransform *r = gsk_transform_perspective (gsk_transform_ref (next->next),
|
||||
@@ -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;
|
||||
|
||||
@@ -4,14 +4,14 @@ uniform sampler2D u_source2;
|
||||
float
|
||||
combine (float source, float backdrop)
|
||||
{
|
||||
return source + backdrop * (1 - source);
|
||||
return source + backdrop * (1.0 - source);
|
||||
}
|
||||
|
||||
vec4
|
||||
composite (vec4 Cs, vec4 Cb, vec3 B)
|
||||
{
|
||||
float ao = Cs.a + Cb.a * (1 - Cs.a);
|
||||
vec3 Co = (Cs.a*(1 - Cb.a)*Cs.rgb + Cs.a*Cb.a*B + (1 - Cs.a)*Cb.a*Cb.rgb) / ao;
|
||||
float ao = Cs.a + Cb.a * (1.0 - Cs.a);
|
||||
vec3 Co = (Cs.a*(1.0 - Cb.a)*Cs.rgb + Cs.a*Cb.a*B + (1.0 - Cs.a)*Cb.a*Cb.rgb) / ao;
|
||||
return vec4(Co, ao);
|
||||
}
|
||||
|
||||
@@ -43,9 +43,9 @@ float
|
||||
hard_light (float source, float backdrop)
|
||||
{
|
||||
if (source <= 0.5)
|
||||
return 2 * backdrop * source;
|
||||
return 2.0 * backdrop * source;
|
||||
else
|
||||
return 2 * (backdrop + source - backdrop * source) - 1;
|
||||
return 2.0 * (backdrop + source - backdrop * source) - 1.0;
|
||||
}
|
||||
|
||||
vec4
|
||||
@@ -63,14 +63,14 @@ soft_light (float source, float backdrop)
|
||||
float db;
|
||||
|
||||
if (backdrop <= 0.25)
|
||||
db = ((16 * backdrop - 12) * backdrop + 4) * backdrop;
|
||||
db = ((16.0 * backdrop - 12.0) * backdrop + 4.0) * backdrop;
|
||||
else
|
||||
db = sqrt (backdrop);
|
||||
|
||||
if (source <= 0.5)
|
||||
return backdrop - (1 - 2 * source) * backdrop * (1 - backdrop);
|
||||
return backdrop - (1.0 - 2.0 * source) * backdrop * (1.0 - backdrop);
|
||||
else
|
||||
return backdrop + (2 * source - 1) * (db - backdrop);
|
||||
return backdrop + (2.0 * source - 1.0) * (db - backdrop);
|
||||
}
|
||||
|
||||
vec4
|
||||
@@ -155,8 +155,8 @@ clip_color (vec3 c)
|
||||
float l = lum (c);
|
||||
float n = min (c.r, min (c.g, c.b));
|
||||
float x = max (c.r, max (c.g, c.b));
|
||||
if (n < 0) c = l + (((c - l) * l) / (l - n));
|
||||
if (x > 1) c = l + (((c - l) * (1 - l)) / (x - l));
|
||||
if (n < 0.0) c = l + (((c - l) * l) / (l - n));
|
||||
if (x > 1.0) c = l + (((c - l) * (1.0 - l)) / (x - l));
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -189,12 +189,12 @@ set_sat (vec3 c, float s)
|
||||
if (c.g == cmin)
|
||||
{
|
||||
res.b = ((c.b - cmin) * s) / (cmax - cmin);
|
||||
res.g = 0;
|
||||
res.g = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
res.g = ((c.g - cmin) * s) / (cmax - cmin);
|
||||
res.b = 0;
|
||||
res.b = 0.0;
|
||||
}
|
||||
res.r = s;
|
||||
}
|
||||
@@ -203,12 +203,12 @@ set_sat (vec3 c, float s)
|
||||
if (c.r == cmin)
|
||||
{
|
||||
res.b = ((c.b - cmin) * s) / (cmax - cmin);
|
||||
res.r = 0;
|
||||
res.r = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
res.r = ((c.r - cmin) * s) / (cmax - cmin);
|
||||
res.b = 0;
|
||||
res.b = 0.0;
|
||||
}
|
||||
res.g = s;
|
||||
}
|
||||
@@ -217,12 +217,12 @@ set_sat (vec3 c, float s)
|
||||
if (c.r == cmin)
|
||||
{
|
||||
res.g = ((c.g - cmin) * s) / (cmax - cmin);
|
||||
res.r = 0;
|
||||
res.r = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
res.r = ((c.r - cmin) * s) / (cmax - cmin);
|
||||
res.g = 0;
|
||||
res.g = 0.0;
|
||||
}
|
||||
res.b = s;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
# Actual GTK things
|
||||
{
|
||||
GtkWidgetClass action GPtrArray
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
fun:g_malloc
|
||||
fun:g_slice_alloc
|
||||
fun:g_ptr_array_sized_new
|
||||
fun:g_ptr_array_new
|
||||
fun:gtk_widget_class_add_action
|
||||
}
|
||||
|
||||
{
|
||||
GTK media extension gio modules
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:malloc
|
||||
fun:g_malloc
|
||||
fun:g_slice_alloc
|
||||
fun:g_slice_alloc0
|
||||
fun:g_type_create_instance
|
||||
fun:g_object_new_internal
|
||||
fun:g_object_new_with_properties
|
||||
fun:g_object_new
|
||||
fun:g_io_module_new
|
||||
fun:g_io_modules_scan_all_in_directory_with_scope
|
||||
fun:gtk_media_file_extension_init
|
||||
}
|
||||
|
||||
# mesa driver stuff
|
||||
{
|
||||
i965 addr4
|
||||
Memcheck:Addr4
|
||||
obj:/usr/lib/dri/i965_dri.so*
|
||||
}
|
||||
|
||||
{
|
||||
i965 addr8
|
||||
Memcheck:Addr8
|
||||
obj:/usr/lib/dri/i965_dri.so*
|
||||
}
|
||||
|
||||
{
|
||||
i965 memcpy
|
||||
Memcheck:Addr8
|
||||
fun:memcpy*
|
||||
obj:/usr/lib/dri/i965_dri.so*
|
||||
}
|
||||
|
||||
{
|
||||
i965 memcpy
|
||||
Memcheck:Addr2
|
||||
fun:memcpy*
|
||||
obj:/usr/lib/dri/i965_dri.so*
|
||||
}
|
||||
|
||||
{
|
||||
mesa memcmp 8
|
||||
Memcheck:Addr8
|
||||
fun:*memcmp*
|
||||
obj:/usr/lib/dri/i965_dri.so*
|
||||
}
|
||||
|
||||
{
|
||||
mesa memcmp 1
|
||||
Memcheck:Addr1
|
||||
fun:*memcmp*
|
||||
obj:/usr/lib/dri/i965_dri.so*
|
||||
}
|
||||
|
||||
{
|
||||
mesa memset 8
|
||||
Memcheck:Addr8
|
||||
fun:*memset*
|
||||
obj:/usr/lib/dri/i965_dri.so
|
||||
}
|
||||
|
||||
{
|
||||
mesa realpath
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:malloc
|
||||
fun:realpath@@GLIBC_2.3
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
fun:epoxy_eglInitialize_global_rewrite_ptr
|
||||
}
|
||||
|
||||
{
|
||||
mesa calloc
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:calloc
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
fun:epoxy_eglInitialize_global_rewrite_ptr
|
||||
}
|
||||
|
||||
{
|
||||
mesa malloc
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:malloc
|
||||
obj:/usr/lib/dri/i965_dri.so*
|
||||
}
|
||||
|
||||
{
|
||||
mesa glReadPixels
|
||||
Memcheck:Addr16
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
fun:epoxy_glReadPixels_global_rewrite_ptr
|
||||
}
|
||||
|
||||
{
|
||||
epoxy glxQueryServerString 1
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
fun:XextAddDisplay
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
fun:epoxy_glXQueryServerString_global_rewrite_ptr
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
epoxy glxQueryServerString 2
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:malloc
|
||||
fun:realpath*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
fun:epoxy_glXQueryServerString_global_rewrite_ptr
|
||||
}
|
||||
|
||||
|
||||
# Fontconfig
|
||||
{
|
||||
FcFontSetList
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:malloc
|
||||
obj:/usr/lib/libfontconfig.so*
|
||||
obj:/usr/lib/libfontconfig.so*
|
||||
fun:FcFontSetList
|
||||
}
|
||||
|
||||
{
|
||||
FcFontRenderPrepare
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:realloc
|
||||
obj:/usr/lib/libfontconfig.so*
|
||||
obj:/usr/lib/libfontconfig.so*
|
||||
fun:FcFontRenderPrepare
|
||||
}
|
||||
|
||||
{
|
||||
FcDefaultSubstitute
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:realloc
|
||||
obj:/usr/lib/libfontconfig.so*
|
||||
obj:/usr/lib/libfontconfig.so*
|
||||
fun:FcDefaultSubstitute
|
||||
}
|
||||
|
||||
# Pixman
|
||||
{
|
||||
pixman_image_composite32
|
||||
Memcheck:Cond
|
||||
obj:/usr/lib/libpixman-1.so*
|
||||
obj:/usr/lib/libpixman-1.so*
|
||||
fun:pixman_image_composite32
|
||||
}
|
||||
|
||||
# Pango
|
||||
{
|
||||
pango 1
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:realloc
|
||||
obj:/usr/lib/libfontconfig.so*
|
||||
obj:/usr/lib/libfontconfig.so*
|
||||
obj:/usr/lib/libcairo.so*
|
||||
fun:pango_cairo_fc_font_map_fontset_key_substitute
|
||||
}
|
||||
|
||||
+150
-40
@@ -23,41 +23,26 @@
|
||||
#include "gsk/gskrendernodeprivate.h"
|
||||
#include "gskpango.h"
|
||||
#include "gtksnapshotprivate.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtktextlayoutprivate.h"
|
||||
#include "gtktextviewprivate.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <pango/pango.h>
|
||||
#include <cairo.h>
|
||||
|
||||
#define GSK_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_PANGO_RENDERER, GskPangoRendererClass))
|
||||
#define GSK_IS_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_PANGO_RENDERER))
|
||||
#define GSK_PANGO_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_PANGO_RENDERER, GskPangoRendererClass))
|
||||
|
||||
/*
|
||||
* This is a PangoRenderer implementation that translates all the draw calls to
|
||||
* gsk render nodes, using the GtkSnapshot helper class. Glyphs are translated
|
||||
* to text nodes, all other draw calls fall back to cairo nodes.
|
||||
*/
|
||||
|
||||
struct _GskPangoRenderer
|
||||
{
|
||||
PangoRenderer parent_instance;
|
||||
|
||||
GtkSnapshot *snapshot;
|
||||
GdkRGBA fg_color;
|
||||
graphene_rect_t bounds;
|
||||
|
||||
/* house-keeping options */
|
||||
gboolean is_cached_renderer;
|
||||
};
|
||||
|
||||
struct _GskPangoRendererClass
|
||||
{
|
||||
PangoRendererClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GskPangoRenderer, gsk_pango_renderer, PANGO_TYPE_RENDERER)
|
||||
|
||||
void
|
||||
gsk_pango_renderer_set_state (GskPangoRenderer *crenderer,
|
||||
GskPangoRendererState state)
|
||||
{
|
||||
g_return_if_fail (GSK_IS_PANGO_RENDERER (crenderer));
|
||||
|
||||
crenderer->state = state;
|
||||
}
|
||||
|
||||
static void
|
||||
get_color (GskPangoRenderer *crenderer,
|
||||
PangoRenderPart part,
|
||||
@@ -158,15 +143,14 @@ gsk_pango_renderer_draw_rectangle (PangoRenderer *renderer,
|
||||
{
|
||||
GskPangoRenderer *crenderer = (GskPangoRenderer *) (renderer);
|
||||
GdkRGBA rgba;
|
||||
graphene_rect_t bounds;
|
||||
|
||||
get_color (crenderer, part, &rgba);
|
||||
|
||||
graphene_rect_init (&bounds,
|
||||
(double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
|
||||
(double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
|
||||
|
||||
gtk_snapshot_append_color (crenderer->snapshot, &rgba, &bounds);
|
||||
gtk_snapshot_append_color (crenderer->snapshot,
|
||||
&rgba,
|
||||
&GRAPHENE_RECT_INIT ((double)x / PANGO_SCALE,
|
||||
(double)y / PANGO_SCALE,
|
||||
(double)width / PANGO_SCALE,
|
||||
(double)height / PANGO_SCALE));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -336,6 +320,124 @@ gsk_pango_renderer_draw_shape (PangoRenderer *renderer,
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
|
||||
static void
|
||||
text_renderer_set_rgba (GskPangoRenderer *crenderer,
|
||||
PangoRenderPart part,
|
||||
const GdkRGBA *rgba)
|
||||
{
|
||||
PangoRenderer *renderer = PANGO_RENDERER (crenderer);
|
||||
PangoColor color = { 0, };
|
||||
guint16 alpha;
|
||||
|
||||
if (rgba)
|
||||
{
|
||||
color.red = (guint16)(rgba->red * 65535);
|
||||
color.green = (guint16)(rgba->green * 65535);
|
||||
color.blue = (guint16)(rgba->blue * 65535);
|
||||
alpha = (guint16)(rgba->alpha * 65535);
|
||||
pango_renderer_set_color (renderer, part, &color);
|
||||
pango_renderer_set_alpha (renderer, part, alpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
pango_renderer_set_color (renderer, part, NULL);
|
||||
pango_renderer_set_alpha (renderer, part, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static GtkTextAppearance *
|
||||
get_item_appearance (PangoItem *item)
|
||||
{
|
||||
GSList *tmp_list = item->analysis.extra_attrs;
|
||||
|
||||
while (tmp_list)
|
||||
{
|
||||
PangoAttribute *attr = tmp_list->data;
|
||||
|
||||
if (attr->klass->type == gtk_text_attr_appearance_type)
|
||||
return &((GtkTextAttrAppearance *)attr)->appearance;
|
||||
|
||||
tmp_list = tmp_list->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_pango_renderer_prepare_run (PangoRenderer *renderer,
|
||||
PangoLayoutRun *run)
|
||||
{
|
||||
GtkStyleContext *context;
|
||||
GskPangoRenderer *crenderer = GSK_PANGO_RENDERER (renderer);
|
||||
GdkRGBA *bg_rgba = NULL;
|
||||
GdkRGBA *fg_rgba = NULL;
|
||||
GtkTextAppearance *appearance;
|
||||
|
||||
PANGO_RENDERER_CLASS (gsk_pango_renderer_parent_class)->prepare_run (renderer, run);
|
||||
|
||||
appearance = get_item_appearance (run->item);
|
||||
|
||||
if (appearance == NULL)
|
||||
return;
|
||||
|
||||
context = gtk_widget_get_style_context (crenderer->widget);
|
||||
|
||||
if (appearance->draw_bg && crenderer->state == GSK_PANGO_RENDERER_NORMAL)
|
||||
bg_rgba = appearance->bg_rgba;
|
||||
else
|
||||
bg_rgba = NULL;
|
||||
|
||||
text_renderer_set_rgba (crenderer, PANGO_RENDER_PART_BACKGROUND, bg_rgba);
|
||||
|
||||
if (crenderer->state == GSK_PANGO_RENDERER_SELECTED &&
|
||||
GTK_IS_TEXT_VIEW (crenderer->widget))
|
||||
{
|
||||
GtkCssNode *selection_node;
|
||||
|
||||
selection_node = gtk_text_view_get_selection_node ((GtkTextView *)crenderer->widget);
|
||||
gtk_style_context_save_to_node (context, selection_node);
|
||||
|
||||
gtk_style_context_get (context,
|
||||
"color", &fg_rgba,
|
||||
NULL);
|
||||
|
||||
gtk_style_context_restore (context);
|
||||
}
|
||||
else if (crenderer->state == GSK_PANGO_RENDERER_CURSOR && gtk_widget_has_focus (crenderer->widget))
|
||||
{
|
||||
gtk_style_context_get (context,
|
||||
"background-color", &fg_rgba,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
fg_rgba = appearance->fg_rgba;
|
||||
|
||||
text_renderer_set_rgba (crenderer, PANGO_RENDER_PART_FOREGROUND, fg_rgba);
|
||||
|
||||
if (appearance->strikethrough_rgba)
|
||||
text_renderer_set_rgba (crenderer, PANGO_RENDER_PART_STRIKETHROUGH, appearance->strikethrough_rgba);
|
||||
else
|
||||
text_renderer_set_rgba (crenderer, PANGO_RENDER_PART_STRIKETHROUGH, fg_rgba);
|
||||
|
||||
if (appearance->underline_rgba)
|
||||
text_renderer_set_rgba (crenderer, PANGO_RENDER_PART_UNDERLINE, appearance->underline_rgba);
|
||||
else if (appearance->underline == PANGO_UNDERLINE_ERROR)
|
||||
{
|
||||
if (!crenderer->error_color)
|
||||
{
|
||||
static const GdkRGBA red = { 1, 0, 0, 1 };
|
||||
crenderer->error_color = gdk_rgba_copy (&red);
|
||||
}
|
||||
|
||||
text_renderer_set_rgba (crenderer, PANGO_RENDER_PART_UNDERLINE, crenderer->error_color);
|
||||
}
|
||||
else
|
||||
text_renderer_set_rgba (crenderer, PANGO_RENDER_PART_UNDERLINE, fg_rgba);
|
||||
|
||||
if (fg_rgba != appearance->fg_rgba)
|
||||
gdk_rgba_free (fg_rgba);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_pango_renderer_init (GskPangoRenderer *renderer G_GNUC_UNUSED)
|
||||
{
|
||||
@@ -352,13 +454,14 @@ gsk_pango_renderer_class_init (GskPangoRendererClass *klass)
|
||||
renderer_class->draw_trapezoid = gsk_pango_renderer_draw_trapezoid;
|
||||
renderer_class->draw_error_underline = gsk_pango_renderer_draw_error_underline;
|
||||
renderer_class->draw_shape = gsk_pango_renderer_draw_shape;
|
||||
renderer_class->prepare_run = gsk_pango_renderer_prepare_run;
|
||||
}
|
||||
|
||||
static GskPangoRenderer *cached_renderer = NULL; /* MT-safe */
|
||||
G_LOCK_DEFINE_STATIC (cached_renderer);
|
||||
|
||||
static GskPangoRenderer *
|
||||
acquire_renderer (void)
|
||||
GskPangoRenderer *
|
||||
gsk_pango_renderer_acquire (void)
|
||||
{
|
||||
GskPangoRenderer *renderer;
|
||||
|
||||
@@ -380,13 +483,20 @@ acquire_renderer (void)
|
||||
return renderer;
|
||||
}
|
||||
|
||||
static void
|
||||
release_renderer (GskPangoRenderer *renderer)
|
||||
void
|
||||
gsk_pango_renderer_release (GskPangoRenderer *renderer)
|
||||
{
|
||||
if (G_LIKELY (renderer->is_cached_renderer))
|
||||
{
|
||||
renderer->widget = NULL;
|
||||
renderer->snapshot = NULL;
|
||||
|
||||
if (renderer->error_color)
|
||||
{
|
||||
gdk_rgba_free (renderer->error_color);
|
||||
renderer->error_color = NULL;
|
||||
}
|
||||
|
||||
G_UNLOCK (cached_renderer);
|
||||
}
|
||||
else
|
||||
@@ -414,7 +524,7 @@ gtk_snapshot_append_layout (GtkSnapshot *snapshot,
|
||||
g_return_if_fail (snapshot != NULL);
|
||||
g_return_if_fail (PANGO_IS_LAYOUT (layout));
|
||||
|
||||
crenderer = acquire_renderer ();
|
||||
crenderer = gsk_pango_renderer_acquire ();
|
||||
|
||||
crenderer->snapshot = snapshot;
|
||||
crenderer->fg_color = *color;
|
||||
@@ -424,5 +534,5 @@ gtk_snapshot_append_layout (GtkSnapshot *snapshot,
|
||||
|
||||
pango_renderer_draw_layout (PANGO_RENDERER (crenderer), layout, 0, 0);
|
||||
|
||||
release_renderer (crenderer);
|
||||
gsk_pango_renderer_release (crenderer);
|
||||
}
|
||||
|
||||
+48
-6
@@ -24,15 +24,57 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_PANGO_RENDERER (gsk_pango_renderer_get_type ())
|
||||
#define GSK_TYPE_PANGO_RENDERER (gsk_pango_renderer_get_type ())
|
||||
#define GSK_PANGO_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_PANGO_RENDERER, GskPangoRenderer))
|
||||
#define GSK_IS_PANGO_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_PANGO_RENDERER))
|
||||
#define GSK_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_PANGO_RENDERER, GskPangoRendererClass))
|
||||
#define GSK_IS_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_PANGO_RENDERER))
|
||||
#define GSK_PANGO_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_PANGO_RENDERER, GskPangoRendererClass))
|
||||
|
||||
#define GSK_PANGO_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_PANGO_RENDERER, GskPangoRenderer))
|
||||
#define GSK_IS_PANGO_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_PANGO_RENDERER))
|
||||
typedef struct _GskPangoRenderer GskPangoRenderer;
|
||||
typedef struct _GskPangoRendererClass GskPangoRendererClass;
|
||||
|
||||
typedef struct _GskPangoRenderer GskPangoRenderer;
|
||||
typedef struct _GskPangoRendererClass GskPangoRendererClass;
|
||||
typedef enum
|
||||
{
|
||||
GSK_PANGO_RENDERER_NORMAL,
|
||||
GSK_PANGO_RENDERER_SELECTED,
|
||||
GSK_PANGO_RENDERER_CURSOR
|
||||
} GskPangoRendererState;
|
||||
|
||||
GType gsk_pango_renderer_get_type (void) G_GNUC_CONST;
|
||||
/*
|
||||
* This is a PangoRenderer implementation that translates all the draw calls to
|
||||
* gsk render nodes, using the GtkSnapshot helper class. Glyphs are translated
|
||||
* to text nodes, all other draw calls fall back to cairo nodes.
|
||||
*/
|
||||
|
||||
struct _GskPangoRenderer
|
||||
{
|
||||
PangoRenderer parent_instance;
|
||||
|
||||
GtkWidget *widget;
|
||||
GtkSnapshot *snapshot;
|
||||
GdkRGBA fg_color;
|
||||
graphene_rect_t bounds;
|
||||
|
||||
/* Error underline color for this widget */
|
||||
GdkRGBA *error_color;
|
||||
|
||||
GskPangoRendererState state;
|
||||
|
||||
/* house-keeping options */
|
||||
guint is_cached_renderer : 1;
|
||||
};
|
||||
|
||||
struct _GskPangoRendererClass
|
||||
{
|
||||
PangoRendererClass parent_class;
|
||||
};
|
||||
|
||||
GType gsk_pango_renderer_get_type (void) G_GNUC_CONST;
|
||||
void gsk_pango_renderer_set_state (GskPangoRenderer *crenderer,
|
||||
GskPangoRendererState state);
|
||||
GskPangoRenderer *gsk_pango_renderer_acquire (void);
|
||||
void gsk_pango_renderer_release (GskPangoRenderer *crenderer);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
+21
-5
@@ -155,6 +155,16 @@ accel_entry_equal (gconstpointer key1,
|
||||
return g_str_equal (entry1->accel_path, entry2->accel_path);
|
||||
}
|
||||
|
||||
static int
|
||||
accel_entry_compare (gconstpointer a,
|
||||
gconstpointer b)
|
||||
{
|
||||
const AccelEntry *entry1 = a;
|
||||
const AccelEntry *entry2 = b;
|
||||
|
||||
return strcmp (entry1->accel_path, entry2->accel_path);
|
||||
}
|
||||
|
||||
static inline AccelEntry*
|
||||
accel_path_lookup (const gchar *accel_path)
|
||||
{
|
||||
@@ -817,17 +827,23 @@ gtk_accel_map_foreach (gpointer data,
|
||||
g_return_if_fail (foreach_func != NULL);
|
||||
|
||||
entries = g_hash_table_slist_values (accel_entry_ht);
|
||||
entries = g_slist_sort (entries, accel_entry_compare);
|
||||
|
||||
for (slist = entries; slist; slist = slist->next)
|
||||
{
|
||||
AccelEntry *entry = slist->data;
|
||||
gboolean changed = entry->accel_key != entry->std_accel_key || entry->accel_mods != entry->std_accel_mods;
|
||||
gboolean skip = FALSE;
|
||||
|
||||
for (node = accel_filters; node; node = node->next)
|
||||
if (g_pattern_match_string (node->data, entry->accel_path))
|
||||
goto skip_accel;
|
||||
foreach_func (data, entry->accel_path, entry->accel_key, entry->accel_mods, changed);
|
||||
skip_accel:
|
||||
/* noop */;
|
||||
if (g_pattern_match_string (node->data, entry->accel_path))
|
||||
{
|
||||
skip = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!skip)
|
||||
foreach_func (data, entry->accel_path, entry->accel_key, entry->accel_mods, changed);
|
||||
}
|
||||
g_slist_free (entries);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
@@ -810,6 +803,8 @@ gtk_action_muxer_finalize (GObject *object)
|
||||
if (muxer->primary_accels)
|
||||
g_hash_table_unref (muxer->primary_accels);
|
||||
|
||||
g_free (muxer->widget_actions_enabled);
|
||||
|
||||
G_OBJECT_CLASS (gtk_action_muxer_parent_class)
|
||||
->finalize (object);
|
||||
}
|
||||
@@ -819,8 +814,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);
|
||||
|
||||
@@ -289,7 +289,6 @@ gtk_builder_init (GtkBuilder *builder)
|
||||
{
|
||||
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (builder);
|
||||
|
||||
priv = gtk_builder_get_instance_private (builder);
|
||||
priv->domain = NULL;
|
||||
priv->objects = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, g_object_unref);
|
||||
|
||||
+2
-2
@@ -3474,7 +3474,7 @@ gtk_calendar_set_detail_width_chars (GtkCalendar *calendar,
|
||||
{
|
||||
priv->detail_width_chars = chars;
|
||||
g_object_notify (G_OBJECT (calendar), "detail-width-chars");
|
||||
gtk_widget_queue_resize_no_redraw (GTK_WIDGET (calendar));
|
||||
gtk_widget_queue_resize (GTK_WIDGET (calendar));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3498,7 +3498,7 @@ gtk_calendar_set_detail_height_rows (GtkCalendar *calendar,
|
||||
{
|
||||
priv->detail_height_rows = rows;
|
||||
g_object_notify (G_OBJECT (calendar), "detail-height-rows");
|
||||
gtk_widget_queue_resize_no_redraw (GTK_WIDGET (calendar));
|
||||
gtk_widget_queue_resize (GTK_WIDGET (calendar));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-36
@@ -1604,8 +1604,9 @@ get_size (GtkCellRenderer *cell,
|
||||
GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (cell);
|
||||
GtkCellRendererTextPrivate *priv = gtk_cell_renderer_text_get_instance_private (celltext);
|
||||
PangoRectangle rect;
|
||||
gint xpad, ypad;
|
||||
gint cell_width, cell_height;
|
||||
int xpad, ypad;
|
||||
int cell_width, cell_height;
|
||||
float xalign, yalign;
|
||||
|
||||
gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
|
||||
|
||||
@@ -1652,52 +1653,30 @@ get_size (GtkCellRenderer *cell,
|
||||
if (width == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
if (layout)
|
||||
g_object_ref (layout);
|
||||
else
|
||||
layout = get_layout (celltext, widget, NULL, 0);
|
||||
|
||||
pango_layout_get_pixel_extents (layout, NULL, &rect);
|
||||
|
||||
if (cell_area)
|
||||
{
|
||||
gfloat xalign, yalign;
|
||||
gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);
|
||||
|
||||
gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);
|
||||
rect.height = MIN (rect.height, cell_area->height - 2 * ypad);
|
||||
rect.width = MIN (rect.width, cell_area->width - 2 * xpad);
|
||||
|
||||
rect.height = MIN (rect.height, cell_area->height - 2 * ypad);
|
||||
rect.width = MIN (rect.width, cell_area->width - 2 * xpad);
|
||||
|
||||
if (x_offset)
|
||||
{
|
||||
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
|
||||
*x_offset = (1.0 - xalign) * (cell_area->width - (rect.width + (2 * xpad)));
|
||||
else
|
||||
*x_offset = xalign * (cell_area->width - (rect.width + (2 * xpad)));
|
||||
|
||||
if ((priv->ellipsize_set && priv->ellipsize != PANGO_ELLIPSIZE_NONE) || priv->wrap_width != -1)
|
||||
*x_offset = MAX(*x_offset, 0);
|
||||
}
|
||||
if (y_offset)
|
||||
{
|
||||
*y_offset = yalign * (cell_area->height - (rect.height + (2 * ypad)));
|
||||
*y_offset = MAX (*y_offset, 0);
|
||||
}
|
||||
}
|
||||
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
|
||||
*x_offset = (1.0 - xalign) * (cell_area->width - (rect.width + (2 * xpad)));
|
||||
else
|
||||
{
|
||||
if (x_offset) *x_offset = 0;
|
||||
if (y_offset) *y_offset = 0;
|
||||
}
|
||||
*x_offset = xalign * (cell_area->width - (rect.width + (2 * xpad)));
|
||||
|
||||
if ((priv->ellipsize_set && priv->ellipsize != PANGO_ELLIPSIZE_NONE) || priv->wrap_width != -1)
|
||||
*x_offset = MAX(*x_offset, 0);
|
||||
|
||||
*y_offset = yalign * (cell_area->height - (rect.height + (2 * ypad)));
|
||||
*y_offset = MAX (*y_offset, 0);
|
||||
|
||||
if (height)
|
||||
*height = ypad * 2 + rect.height;
|
||||
|
||||
if (width)
|
||||
*width = xpad * 2 + rect.width;
|
||||
|
||||
g_object_unref (layout);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -408,7 +408,6 @@ gtk_cell_renderer_toggle_snapshot (GtkCellRenderer *cell,
|
||||
GtkBorder padding, border;
|
||||
GtkCssImageBuiltinType image_type;
|
||||
|
||||
context = gtk_widget_get_style_context (widget);
|
||||
gtk_cell_renderer_toggle_get_size (cell, widget, cell_area,
|
||||
&x_offset, &y_offset,
|
||||
&width, &height);
|
||||
|
||||
@@ -537,8 +537,6 @@ gtk_color_chooser_widget_init (GtkColorChooserWidget *cc)
|
||||
AtkObject *atk_obj;
|
||||
gchar *text, *name;
|
||||
|
||||
priv = gtk_color_chooser_widget_get_instance_private (cc);
|
||||
|
||||
priv->use_alpha = TRUE;
|
||||
|
||||
gtk_orientable_set_orientation (GTK_ORIENTABLE (cc), GTK_ORIENTATION_VERTICAL);
|
||||
|
||||
@@ -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-attribute.
|
||||
*/
|
||||
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
|
||||
@@ -1118,6 +1118,8 @@ gtk_css_provider_load_internal (GtkCssProvider *self,
|
||||
|
||||
if (parent == NULL)
|
||||
gtk_css_provider_postprocess (self);
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1149,8 +1151,8 @@ gtk_css_provider_load_from_data (GtkCssProvider *css_provider,
|
||||
|
||||
gtk_css_provider_reset (css_provider);
|
||||
|
||||
g_bytes_ref (bytes);
|
||||
gtk_css_provider_load_internal (css_provider, NULL, NULL, bytes);
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
gtk_style_provider_changed (GTK_STYLE_PROVIDER (css_provider));
|
||||
|
||||
+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
|
||||
|
||||
@@ -566,7 +566,6 @@ populate_completion (GtkEmojiCompletion *completion,
|
||||
GVariantIter iter;
|
||||
GVariant *item;
|
||||
|
||||
text = g_strdup (text);
|
||||
g_free (completion->text);
|
||||
completion->text = g_strdup (text);
|
||||
completion->length = g_utf8_strlen (text, -1);
|
||||
|
||||
@@ -1529,6 +1529,7 @@ gtk_entry_measure (GtkWidget *widget,
|
||||
{
|
||||
GtkEntry *entry = GTK_ENTRY (widget);
|
||||
GtkEntryPrivate *priv = gtk_entry_get_instance_private (entry);
|
||||
int i;
|
||||
|
||||
gtk_widget_measure (priv->text,
|
||||
orientation,
|
||||
@@ -1536,6 +1537,30 @@ gtk_entry_measure (GtkWidget *widget,
|
||||
minimum, natural,
|
||||
minimum_baseline, natural_baseline);
|
||||
|
||||
for (i = 0; i < MAX_ICONS; i++)
|
||||
{
|
||||
EntryIconInfo *icon_info = priv->icons[i];
|
||||
int icon_min, icon_nat;
|
||||
|
||||
if (!icon_info)
|
||||
continue;
|
||||
|
||||
gtk_widget_measure (icon_info->widget,
|
||||
GTK_ORIENTATION_HORIZONTAL,
|
||||
-1, &icon_min, &icon_nat, NULL, NULL);
|
||||
|
||||
if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
{
|
||||
*minimum += icon_min;
|
||||
*natural += icon_nat;
|
||||
}
|
||||
else
|
||||
{
|
||||
*minimum = MAX (*minimum, icon_min);
|
||||
*natural = MAX (*natural, icon_nat);
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->progress_widget && gtk_widget_get_visible (priv->progress_widget))
|
||||
{
|
||||
int prog_min, prog_nat;
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -577,9 +577,34 @@ gtk_file_chooser_dialog_map (GtkWidget *widget)
|
||||
GTK_WIDGET_CLASS (gtk_file_chooser_dialog_parent_class)->map (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
save_dialog_geometry (GtkFileChooserDialog *dialog)
|
||||
{
|
||||
GtkWindow *window;
|
||||
GSettings *settings;
|
||||
int old_width, old_height;
|
||||
int width, height;
|
||||
|
||||
settings = _gtk_file_chooser_get_settings_for_widget (GTK_WIDGET (dialog));
|
||||
|
||||
window = GTK_WINDOW (dialog);
|
||||
|
||||
gtk_window_get_size (window, &width, &height);
|
||||
|
||||
g_settings_get (settings, SETTINGS_KEY_WINDOW_SIZE, "(ii)", &old_width, &old_height);
|
||||
if (old_width != width || old_height != height)
|
||||
g_settings_set (settings, SETTINGS_KEY_WINDOW_SIZE, "(ii)", width, height);
|
||||
|
||||
g_settings_apply (settings);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_chooser_dialog_unmap (GtkWidget *widget)
|
||||
{
|
||||
GtkFileChooserDialog *dialog = GTK_FILE_CHOOSER_DIALOG (widget);
|
||||
|
||||
save_dialog_geometry (dialog);
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_file_chooser_dialog_parent_class)->unmap (widget);
|
||||
}
|
||||
|
||||
@@ -593,6 +618,8 @@ gtk_file_chooser_dialog_size_allocate (GtkWidget *widget,
|
||||
width,
|
||||
height,
|
||||
baseline);
|
||||
if (gtk_widget_is_drawable (widget))
|
||||
save_dialog_geometry (GTK_FILE_CHOOSER_DIALOG (widget));
|
||||
}
|
||||
|
||||
/* We do a signal connection here rather than overriding the method in
|
||||
|
||||
+27
-15
@@ -2460,19 +2460,6 @@ location_changed_timeout_cb (gpointer user_data)
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
reset_location_timeout (GtkFileChooserWidget *impl)
|
||||
{
|
||||
GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
|
||||
|
||||
if (priv->location_changed_id > 0)
|
||||
g_source_remove (priv->location_changed_id);
|
||||
priv->location_changed_id = g_timeout_add (LOCATION_CHANGED_TIMEOUT,
|
||||
location_changed_timeout_cb,
|
||||
impl);
|
||||
g_source_set_name_by_id (priv->location_changed_id, "[gtk] location_changed_timeout_cb");
|
||||
}
|
||||
|
||||
static void
|
||||
location_entry_changed_cb (GtkEditable *editable,
|
||||
GtkFileChooserWidget *impl)
|
||||
@@ -2489,7 +2476,16 @@ location_entry_changed_cb (GtkEditable *editable,
|
||||
}
|
||||
|
||||
if (priv->action != GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
|
||||
reset_location_timeout (impl);
|
||||
{
|
||||
/* Reset location timeout */
|
||||
if (priv->location_changed_id > 0)
|
||||
g_source_remove (priv->location_changed_id);
|
||||
|
||||
priv->location_changed_id = g_timeout_add (LOCATION_CHANGED_TIMEOUT,
|
||||
location_changed_timeout_cb,
|
||||
impl);
|
||||
g_source_set_name_by_id (priv->location_changed_id, "[gtk] location_changed_timeout_cb");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -3051,12 +3047,20 @@ static void
|
||||
operation_mode_set_browse (GtkFileChooserWidget *impl)
|
||||
{
|
||||
GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
|
||||
GtkRevealerTransitionType old_revealer_transition_type;
|
||||
|
||||
gtk_places_sidebar_set_location (GTK_PLACES_SIDEBAR (priv->places_sidebar), priv->current_folder);
|
||||
gtk_stack_set_visible_child_name (GTK_STACK (priv->browse_files_stack), "list");
|
||||
location_mode_set (impl, LOCATION_MODE_PATH_BAR);
|
||||
gtk_stack_set_visible_child_name (GTK_STACK (priv->browse_header_stack), "pathbar");
|
||||
|
||||
old_revealer_transition_type = gtk_revealer_get_transition_type (GTK_REVEALER (priv->browse_header_revealer));
|
||||
gtk_revealer_set_transition_type (GTK_REVEALER (priv->browse_header_revealer),
|
||||
GTK_REVEALER_TRANSITION_TYPE_NONE);
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (priv->browse_header_revealer), TRUE);
|
||||
gtk_revealer_set_transition_type (GTK_REVEALER (priv->browse_header_revealer),
|
||||
old_revealer_transition_type);
|
||||
|
||||
gtk_widget_set_sensitive (priv->filter_combo, TRUE);
|
||||
g_object_notify (G_OBJECT (impl), "subtitle");
|
||||
}
|
||||
@@ -3090,10 +3094,19 @@ operation_mode_set_recent (GtkFileChooserWidget *impl)
|
||||
{
|
||||
GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
|
||||
GFile *file;
|
||||
GtkRevealerTransitionType old_revealer_transition_type;
|
||||
|
||||
gtk_stack_set_visible_child_name (GTK_STACK (priv->browse_files_stack), "list");
|
||||
gtk_stack_set_visible_child_name (GTK_STACK (priv->browse_header_stack), "pathbar");
|
||||
|
||||
/* Hide browse_header without a transition */
|
||||
old_revealer_transition_type = gtk_revealer_get_transition_type (GTK_REVEALER (priv->browse_header_revealer));
|
||||
gtk_revealer_set_transition_type (GTK_REVEALER (priv->browse_header_revealer),
|
||||
GTK_REVEALER_TRANSITION_TYPE_NONE);
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (priv->browse_header_revealer), FALSE);
|
||||
gtk_revealer_set_transition_type (GTK_REVEALER (priv->browse_header_revealer),
|
||||
old_revealer_transition_type);
|
||||
|
||||
location_bar_update (impl);
|
||||
recent_start_loading (impl);
|
||||
file = g_file_new_for_uri ("recent:///");
|
||||
@@ -3584,7 +3597,6 @@ gtk_file_chooser_widget_unroot (GtkWidget *widget)
|
||||
|
||||
remove_settings_signal (impl, gtk_widget_get_display (widget));
|
||||
check_icon_theme (impl);
|
||||
emit_default_size_changed (impl);
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_file_chooser_widget_parent_class)->unroot (widget);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1356,7 +1356,6 @@ gtk_header_bar_set_custom_title (GtkHeaderBar *bar,
|
||||
|
||||
gtk_header_bar_reorder_css_node (bar, GTK_PACK_START, priv->custom_title);
|
||||
gtk_widget_set_parent (priv->custom_title, GTK_WIDGET (bar));
|
||||
gtk_widget_set_valign (priv->custom_title, GTK_ALIGN_CENTER);
|
||||
|
||||
if (priv->label_box != NULL)
|
||||
{
|
||||
|
||||
+44
-17
@@ -227,19 +227,35 @@ gtk_icon_helper_paintable_snapshot (GdkPaintable *paintable,
|
||||
h = MIN (h, height);
|
||||
x = (width - w) / 2;
|
||||
y = (height - h) / 2;
|
||||
gtk_snapshot_save (snapshot);
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
|
||||
gtk_css_style_snapshot_icon_paintable (style,
|
||||
snapshot,
|
||||
self->paintable,
|
||||
w, h,
|
||||
self->texture_is_symbolic);
|
||||
gtk_snapshot_restore (snapshot);
|
||||
|
||||
if (x != 0 || y != 0)
|
||||
{
|
||||
gtk_snapshot_save (snapshot);
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
|
||||
gtk_css_style_snapshot_icon_paintable (style,
|
||||
snapshot,
|
||||
self->paintable,
|
||||
w, h,
|
||||
self->texture_is_symbolic);
|
||||
gtk_snapshot_restore (snapshot);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_style_snapshot_icon_paintable (style,
|
||||
snapshot,
|
||||
self->paintable,
|
||||
w, h,
|
||||
self->texture_is_symbolic);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case GTK_IMAGE_PAINTABLE:
|
||||
case GTK_IMAGE_EMPTY:
|
||||
break;
|
||||
|
||||
case GTK_IMAGE_PAINTABLE:
|
||||
default:
|
||||
{
|
||||
double image_ratio = (double) width / height;
|
||||
@@ -269,14 +285,25 @@ gtk_icon_helper_paintable_snapshot (GdkPaintable *paintable,
|
||||
x = floor (width - ceil (w)) / 2;
|
||||
y = floor (height - ceil (h)) / 2;
|
||||
|
||||
gtk_snapshot_save (snapshot);
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
|
||||
gtk_css_style_snapshot_icon_paintable (style,
|
||||
snapshot,
|
||||
self->paintable,
|
||||
w, h,
|
||||
self->texture_is_symbolic);
|
||||
gtk_snapshot_restore (snapshot);
|
||||
if (x != 0 || y != 0)
|
||||
{
|
||||
gtk_snapshot_save (snapshot);
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
|
||||
gtk_css_style_snapshot_icon_paintable (style,
|
||||
snapshot,
|
||||
self->paintable,
|
||||
w, h,
|
||||
self->texture_is_symbolic);
|
||||
gtk_snapshot_restore (snapshot);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_style_snapshot_icon_paintable (style,
|
||||
snapshot,
|
||||
self->paintable,
|
||||
w, h,
|
||||
self->texture_is_symbolic);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
+3
-6
@@ -1757,7 +1757,7 @@ GtkWidget*
|
||||
gtk_menu_get_active (GtkMenu *menu)
|
||||
{
|
||||
GtkMenuPrivate *priv;
|
||||
GtkWidget *child;
|
||||
GtkWidget *child = NULL;
|
||||
GList *children, *l;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_MENU (menu), NULL);
|
||||
@@ -2414,7 +2414,6 @@ gtk_menu_position (GtkMenu *menu)
|
||||
GdkAnchorHints anchor_hints;
|
||||
gint rect_anchor_dx, rect_anchor_dy;
|
||||
GdkSurface *toplevel;
|
||||
gboolean emulated_move_to_rect = FALSE;
|
||||
|
||||
rect_anchor = priv->rect_anchor;
|
||||
menu_anchor = priv->menu_anchor;
|
||||
@@ -2461,10 +2460,8 @@ gtk_menu_position (GtkMenu *menu)
|
||||
|
||||
g_signal_handlers_disconnect_by_func (toplevel, moved_to_rect_cb, menu);
|
||||
|
||||
if (!emulated_move_to_rect)
|
||||
g_signal_connect (toplevel, "moved-to-rect", G_CALLBACK (moved_to_rect_cb),
|
||||
menu);
|
||||
|
||||
g_signal_connect (toplevel, "moved-to-rect", G_CALLBACK (moved_to_rect_cb),
|
||||
menu);
|
||||
|
||||
gdk_surface_move_to_rect (toplevel,
|
||||
&rect,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user