Compare commits

..

107 Commits

Author SHA1 Message Date
Matthias Clasen 4eb28908b8 Make grid constraint dynamic
Handle dynamic changes:
- adding/removing children
- changing homogeneity
- attaching/detaching from a layout
2019-07-02 20:28:11 +00:00
Matthias Clasen 138195998d Add two grid constraints demos 2019-07-02 12:55:25 -04:00
Matthias Clasen 0468238871 Add a grid constraint implementation
This is a convenience class that can create
all the constraints to set up a grid.
2019-07-02 12:51:44 -04:00
Matthias Clasen b5aee936a9 Merge branch 'constraint-list-model' into 'master'
Constraint list models

See merge request GNOME/gtk!975
2019-07-02 14:18:42 +00:00
Matthias Clasen aa8687316f constraint editor: Implement loading
Allow to reread the ui builder files we write out.
Just barely.
2019-07-02 10:03:48 -04:00
Matthias Clasen 5a3cf5a194 constraints editor: Stop naming constraints
We don't have a field for the name in ui files,
so stop naming constraints.
2019-07-02 10:03:48 -04:00
Matthias Clasen c5e1b00994 constraint editor: Implement saving
Save to a ui file.
2019-07-02 10:03:48 -04:00
Matthias Clasen 377f0c1a0a constraint editor: Use name properties 2019-07-02 10:03:48 -04:00
Matthias Clasen a442e6e8de constraint editor: Use the list models
Instead of handrolling our own list models,
use the ones provided by GtkConstraintLayout.
2019-07-02 10:03:48 -04:00
Matthias Clasen 274c47e5ba constraint layout: Provide list models
Provide list models for the constraints and guides,
so we can show them in the inspector, and use them
in e.g. the constraints editor.
2019-07-02 10:03:48 -04:00
Matthias Clasen b2f15a622d Merge branch 'wip/ebassi/constraint-layout' into 'master'
Add constraint-based layout manager

Closes #1090

See merge request GNOME/gtk!973
2019-07-02 14:01:01 +00:00
Emmanuele Bassi 04aaf02881 docs: Add more private headers to the list
The various GtkConstraint private API should not be scanned for
documentation.
2019-07-02 09:48:17 +01:00
Emmanuele Bassi d5f8e1bf29 docs: Fix typo in function name 2019-07-02 09:44:48 +01:00
Daniel Boles 33bd7051f2 widget-factory: Use correct StyleProvider priority
We are an application, not a user.

cherry-pick of !974
2019-07-02 09:09:47 +01:00
Matthias Clasen 61345b3216 Merge branch 'option-names' into 'master'
meson: Rename documentation option to gtk_doc

See merge request GNOME/gtk!972
2019-07-02 01:28:43 +00:00
Benjamin Otte 129691f3a6 flattenlistmodeL: Compute items-changed position properly
The code previously forgot to include the left child of the model's
node. Which of course only happened if that child wasn't NULL, which is
a common case.

Found and test provided by Matthias Clasen.
2019-07-02 02:53:00 +02:00
Matthias Clasen 4eaf860e86 meson: Rename documentation option to gtk_doc
This name is what most of the stack is using.
Lets follow along, even though it is (imo)
uglier.
2019-07-01 20:16:37 -04:00
Christoph Reiter 72814c54a8 meson: cups: use cups-config for looking up cups
We were looking for the cups headers and the cups lib in the default locations
which for example breaks with OpenBSD where the cups headers are under /usr/local/include/

Instead just use the "cups" dependency type from meson which internally uses cups-config.

See #1967

Ported to master from !963
2019-07-01 21:52:06 +02:00
Christoph Reiter 4d4e02c9d0 build/cups: remove checks for httpGetAuthString and http_t.authstring
httpGetAuthString() was added with cups 1.3 and we depend on a newer version
now. The direct field access was a fallback in case httpGetAuthString()
was missing, so this can also be dropped.

Ported to master from !938
2019-07-01 21:34:44 +02:00
Emmanuele Bassi 8ab609e4e7 Add custom parser for guides defined in GtkBuilder UI files
Like we describe constraints, we can also define guides.
2019-07-01 19:22:48 +01:00
Emmanuele Bassi 6bc156c237 Implement GtkBuildable for GtkConstraintLayout
Using GtkBuildable we can provide a custom parser for reading
constraints defined in a GtkBuilder UI file.
2019-07-01 18:03:20 +01:00
Emmanuele Bassi b435dc4366 Use the right GValue getter for GtkConstraintGuide:strength
The property is defined as an enum.

This fixes the defaultvalue and notify tests.
2019-07-01 18:02:19 +01:00
Emmanuele Bassi 4dd1de4129 Use explicit values for constraint strength
Instead of playing games with mapping negative symbolic values to
positive ones, let's use the appropriate constants everywhere. This
allows us to use:

        GTK_CONSTRAINT_STRENGTH_WEAK * 2

Or

        GTK_CONSTRAINT_STRENGTH_STRONG + 1

In code using the public API.

We also store the strength values as integers, so we can compare them
properly, and only turn them into doubles when they are inserted into
the solver, just like every other variable.
2019-07-01 12:39:24 +01:00
Matthias Clasen 48e6cd4255 constraint editor: Allow dragging children
We add a weak constraint for the position
and update it as the widget is dragged.
2019-07-01 04:24:26 +00:00
Matthias Clasen 658397fad0 Documentation fixes
Make sure all types show up in the docs,
and misc other improvements.
2019-07-01 03:17:58 +00:00
Matthias Clasen 670fc5bb94 constraint editor: Enable max size for guide
Also, use the apis we have now, and make the
spin buttons display 'unset' values as such.
2019-07-01 02:23:39 +00:00
Matthias Clasen b224df8109 constraint layout: go back to keeping constraints
We want to minimize changes to the solver, so
keep the size constraints around and only update
them when the size changes.
2019-07-01 01:54:57 +00:00
Matthias Clasen c88e7c180d constraint layout: Use stronger force for min size
We want our edit constraint to be strong enough to
overpower nat. size constraint, therefore use STRONG * 2.
2019-07-01 01:49:20 +00:00
Emmanuele Bassi 2aabd64f1a Fix warnings from the introspection scanner
The name of the arguments of the functions must match the name of the
arguments in the documentation stanza.
2019-07-01 01:13:00 +01:00
Emmanuele Bassi 7990b24287 Add gtkconstraintguide.h to the public headers
It needs to be introspected and installed.
2019-07-01 01:12:25 +01:00
Emmanuele Bassi c76c1a46e4 Remove specialised API from GtkConstraint
Thet widget-based API for constraint target and source properties is
unused, and not really necessary.
2019-07-01 01:05:04 +01:00
Emmanuele Bassi 68fed63eac Add missing documentation for GtkConstraint 2019-07-01 01:02:56 +01:00
Emmanuele Bassi 46403bac12 docs: Add GtkConstraint and friends to the API reference 2019-07-01 00:49:20 +01:00
Emmanuele Bassi 74c626f835 Document GtkConstraintGuide 2019-07-01 00:48:59 +01:00
Emmanuele Bassi d45a662679 Move the VFL error domain to a public header
Since the public API will use it to fill out GErrors, it needs to be
publicly available.
2019-07-01 00:48:48 +01:00
Matthias Clasen f6019f1a16 Merge branch 'gbsneto/fix-popover-dark-theme' into 'master'
Fix GtkPopoverMenu in dark theme

See merge request GNOME/gtk!970
2019-06-30 23:17:40 +00:00
Matthias Clasen 514de0b91a Add a constraint editor demo
This is an initial cut at providing a tool
for interactive exploration of constraints.
2019-07-01 00:10:11 +01:00
Emmanuele Bassi 9a463056d0 constraint layout: Notice when guides change
We need to queue a resize here.
2019-07-01 00:10:11 +01:00
Matthias Clasen 035baa092c Mark the layout as changed
We should mark the layout as changed when
constraints are added or removed.
2019-07-01 00:10:11 +01:00
Matthias Clasen 499738c903 constraint guide: Avoid redundant constraints
There is no point in creating a stay for nat
size when min == max. And no point in a constraint
for <= G_MAXINT either.
2019-07-01 00:10:11 +01:00
Matthias Clasen f2d7433bf6 constraint guide: Fix initial property values
This was overlooked when the max-width/max-height/
strength properties were added.
2019-07-01 00:10:11 +01:00
Matthias Clasen 405121bccc constraint solver: Use GTK_NOTE
Allow using GTK_DEBUG=constraints to get debug
output from the constraints solver.
2019-07-01 00:10:11 +01:00
Matthias Clasen cb96b34315 solver: Add private statistics api
No point in keeping these counters without
a way to show them.
2019-07-01 00:10:11 +01:00
Matthias Clasen 9edf6fb6cb constraint layout: Dont reset constraints in allocate
If trust our allocation algorithm, this can never
trigger (and in fact, it never does).
2019-07-01 00:10:11 +01:00
Matthias Clasen e3c4fb67ca constraints: Add some internal apis
Checking if a set is empty or a singleton can
be done more efficiently than determining its size.
2019-07-01 00:10:11 +01:00
Matthias Clasen a9dfca04e4 constraint guide: Make strength tweakable
The strength for the natural width can be used
as a tie-breaker to make instable systems behave
in a more predictable way. This can be seen
in the simple constraints demo in gtk-demo.
2019-07-01 00:10:11 +01:00
Matthias Clasen 71b52f485e constraints demo: Update comments 2019-07-01 00:10:11 +01:00
Matthias Clasen f62fc4e2f2 constraint layout: freeze/thaw on mass ops
In measure and allocate we are potentially
changing quite a few constraints. Don't
optimize at every step.
2019-07-01 00:10:11 +01:00
Matthias Clasen 511e2b435e constraints: Use better data structures
Use a GSequence for GtkVariableSet, to avoid
quadratic behavior.
2019-07-01 00:10:11 +01:00
Matthias Clasen 3f36340921 constraint layout: Measure min/nat size separately
Only constraint the opposite direction if we
actually have a for_size, and measure natural
size after removing the edit constraints. With
these changes, the test that compares constraint
layout to grid layout passes.
2019-07-01 00:10:11 +01:00
Matthias Clasen b1f0f4478e constraint layout: Use stays for natural size
It makes more sense to treat the natural size
of both children and guides as stays, since
we want to meet these values as closely as we
can, under the circumstances.
2019-07-01 00:10:11 +01:00
Matthias Clasen 90f8dcc5e1 constraint layout: Add debug output for guides
Print out the allocation we end up giving to
guides. This helps in making sense of the
allocations of the child widgets that these
guides relate to.
2019-07-01 00:10:11 +01:00
Matthias Clasen 5a019bfccd constraints demo: Give space a name
Lets call it 'space'.
2019-07-01 00:10:11 +01:00
Matthias Clasen b39a5fe5dc constraint guide: Add a name property
We need to be able to print meaningful debug messages
regarding these objects, and eventually present them
in the inspector too.
2019-07-01 00:10:11 +01:00
Matthias Clasen c7ef8411bd constraint guide: Shorten names
Now that this is its own source file,
no need for these prefixes anymore.
2019-07-01 00:10:11 +01:00
Matthias Clasen dab8a8b5c5 constraint layout: Measure more correctly
Set up all constraints for minimum + natural
width + height when measuring, regardless
of the orientation we're measuring. Anything
else will lead to incorrect answers when
there are constraints that cut across
dimensions.
2019-07-01 00:10:11 +01:00
Matthias Clasen 8b9c5e3a04 solver: Fix a copy/paste error 2019-07-01 00:10:11 +01:00
Matthias Clasen 3d3a672deb constraint solver: Fix repeat suggestions
We were not storing the previous value, causing
the first two suggestions to work, but not later
ones.

Fixes the test added in the previous commit.
2019-07-01 00:10:11 +01:00
Matthias Clasen 2f97134a08 Amend a constraint solver test
Make the 'repeat edit' test make more than to
suggestions in a single edit phase. It turns out
that this does not work, whereas just doing
two in a row does.
2019-07-01 00:10:11 +01:00
Matthias Clasen 47237d32eb demo: Use constraint guide api
Use proper api to create and set up
the guide, and also try max-width.
2019-07-01 00:10:11 +01:00
Matthias Clasen 139a59cae3 Flesh out GtkConstraintGuide
This commit moves GtkConstraintGuide into its own
source files to avoid gtkconstraintlayout.c turning
too messy, adds max size properties and implements
getters and setters.
2019-07-01 00:10:11 +01:00
Matthias Clasen 60fb9092fe Drop an indirection
This struct is not really useful for just
a single hash table, and it gets in the way
of moving the guide code to its own file.
2019-07-01 00:10:11 +01:00
Matthias Clasen 61b4febbaf Detach guides on unroot
We don't want to leave constraints behind.
2019-07-01 00:10:11 +01:00
Matthias Clasen 4f4ba8c4f6 Simplify the guide implementation
Store the values and constraints in
arrays, to facilitate treating them
uniformly.
2019-07-01 00:10:11 +01:00
Emmanuele Bassi 651adbfb39 Return the list of constraints added via VFL description
Otherwise it's impossible to remove them.
2019-07-01 00:10:11 +01:00
Emmanuele Bassi 3204347bb0 Add method to remove all constraints from a layout 2019-07-01 00:10:11 +01:00
Georges Basile Stavracas Neto b929846cc1 Adwaita: Also apply $color_menu to popover arrows
So that popovers and arrows are always in agreement of
the background color.
2019-06-30 19:51:51 -03:00
Georges Basile Stavracas Neto fe65da05be Adwaita: Use $menu_color background in popover.menu
GtkPopoverMenus should mimic menus. Commit d936967b7a introduced
some CSS related to menu popovers, however, it hardcodes 'white'
as the background color. That is problematic for the dark theme.

Use '$menu_color' instead of 'white', since $menu_color both
guarantees menu popovers and menus match, and already handles
different colors for dark and light theme variants.
2019-06-30 19:47:32 -03:00
Emmanuele Bassi 06c825df90 Add a C convenience function for VFL constraints
The dictionary-based function is convenient for language bindings, but C
developers will feel more at home with a variadic arguments list.
2019-06-30 23:42:45 +01:00
Emmanuele Bassi 46430ea85b Add Constraints/VFL demo
Shows how to describe constraints using VFL instead of constructing
objects manually.
2019-06-30 23:42:45 +01:00
Emmanuele Bassi 859c95b435 Allow adding constraints described through VFL 2019-06-30 23:42:45 +01:00
Emmanuele Bassi 5ea8167802 Add VFL parser for constraints
Constraints can be expressed with a compact syntax, called VFL (visual
format language).
2019-06-30 23:42:45 +01:00
Emmanuele Bassi 92d3d55164 Remove GtkConstraintVariable.set_prefix()
The prefix and name are set at construction time.
2019-06-30 23:42:45 +01:00
Matthias Clasen ba2125d8e1 Add an interactive constraints demo 2019-06-30 23:42:44 +01:00
Matthias Clasen 7c96326c18 Make the constraints demo more interesting
Add a max size to the buttons, to force the
space to open up.
2019-06-30 23:42:44 +01:00
Matthias Clasen 38d353dc1a Add GtkConstraintGuide
This is meant to be a flexible space.
2019-06-30 23:42:44 +01:00
Emmanuele Bassi 7ae04ba36b Use generic pointers for constraint targets
Since GtkWidget implements GtkConstraintTarget, we can omit the explicit
cast, and validate the type at run time.
2019-06-30 23:42:44 +01:00
Matthias Clasen 39c284c490 Redefine constraints with GtkConstraintTarget
This is in preparation for allowing non-widgets
to act as constraint targets.
2019-06-30 23:42:44 +01:00
Matthias Clasen 895e8e25a8 widget: Implement GtkConstraintTarget 2019-06-30 23:42:44 +01:00
Matthias Clasen 04562a76e3 Add GtkConstraintTarget
This is an marker interface that we will
use to accept other things that widgets
in constraints.
2019-06-30 23:42:44 +01:00
Emmanuele Bassi b6781e06c1 Notify a layout change when adding and removing constraints
Changing the set of constraints should cause a relayout.
2019-06-30 23:42:44 +01:00
Emmanuele Bassi 54104b6676 Fix the opposite size measurement in GtkConstraintLayout
We cannot use the given "for size" when querying our children, because
the constraint layout has no idea about the opposite size of its
children until the layout is complete.

Additionally, we should only suggest an opposite size for the layout if
we have one, instead of suggesting a weak zero size.
2019-06-30 23:42:44 +01:00
Emmanuele Bassi 21450d5f23 Remove size constraints from ConstraintLayoutChild
The size constraints are transient to measurement and allocation, so
they don't really need to be stored inside the GtkLayoutChild subclass
created by a GtkConstraintLayout.
2019-06-30 23:42:44 +01:00
Matthias Clasen a39bbb2041 constraints: Make internal consistency required
The relations between left, right, width
and top, bottom, height are required for
internal consistency. It doesn't make sense
to ever drop these.

Changing the strength of these relations makes
my systems behave much more stable.
2019-06-30 23:42:44 +01:00
Matthias Clasen 176d9c6baf Add gtk_constraint_layout_remove_constraint
Otherwise, you can't do many interesting things.
2019-06-30 23:42:44 +01:00
Emmanuele Bassi 64afa765c8 Do not release reference on the subject of an expression
We don't own the reference in the first place.
2019-06-30 23:42:44 +01:00
Matthias Clasen a246d8c926 constraints solver: Avoid critials
When the solver is finalized with existing
constraints, we end up with criticals when
the constraints ref finalize code calls
back into the hash table. Avoid that by
emptying the hash table beforehand.
2019-06-30 23:42:44 +01:00
Matthias Clasen 0531e663ee constraint solver: Fix thawing
There was an obviously wrong precondition here.
2019-06-30 23:42:44 +01:00
Emmanuele Bassi bd2349c0a0 Do not leak LayoutChild instances
Since the LayoutManager owns the LayoutChild it creates, it's also
responsible for mopping them up.
2019-06-30 23:42:44 +01:00
Emmanuele Bassi 636fbc0f1a Add GtkConstraintLayout demo 2019-06-30 23:42:44 +01:00
Emmanuele Bassi cdf80f1d65 Add GtkConstraintLayout
A layout manager using GtkConstraintSolver to measure and allocate
children.
2019-06-30 23:42:44 +01:00
Emmanuele Bassi e7b2c530c5 Propagate rooting and unrooting widgets to layout managers
Layout managers may need to get access to data attached to the root of a
scene graph.
2019-06-30 23:42:44 +01:00
Emmanuele Bassi e07098da03 window: Create a GtkConstraintSolver
Implement the GtkRoot getter for GtkConstraintSolver.
2019-06-30 23:42:44 +01:00
Emmanuele Bassi 98a21bf498 Assign a GtkConstraintSolver to each GtkRoot
Constraints need to work across different parents, so it's better to
have a single constraint solver per top level.
2019-06-30 23:42:44 +01:00
Emmanuele Bassi c694dd6049 Move the Root interface to a private header
We don't expect out of tree implementations of GtkRoot, and having the
interface structure private to the GTK code allows us to add virtual
functions involving private types.
2019-06-30 23:42:44 +01:00
Emmanuele Bassi 6b308cd71e Add constraint solver
GtkConstraintSolver is an implementation of the Cassowary constraint
solving algorithm:

  http://constraints.cs.washington.edu/cassowary/

The Cassowary method allows to incrementally solve a tableau of linear
equations, in the form of:

  x = y × coefficient + constant

with different weights, or strengths, applied to each one.

These equations can be used to describe constraints applied to a layout
of UI elements, which allows layout managers using the Cassowary method
to quickly, and efficiently, lay out widgets in complex relations
between themselves and their parent container.
2019-06-30 23:42:44 +01:00
Matthias Clasen 3b6ee32f83 Fix a crash in action muxer destruction
I've seen a crash when the action muxer gets
disposed during widget destroy, and tries to
disconnect from widget signals too late.

There is no real need to disconnect, since the
only time an action muxer is going away is when
its widget is destroyed, so just don't do it.
2019-06-30 18:37:32 +00:00
Timm Bäder 3bc3e140dd transform: Add transform_bounds fast path for 2D_AFFINE transforms
E.g. anything involving a scale. This is important when e.g. scrolling
in the node list in the recorder, which scales every recorded node down
to fit in the list.
2019-06-29 09:49:38 +02:00
Timm Bäder a6a9853676 Adwaita: Fix popover style
We add the .background class to the popover node now.
2019-06-29 09:06:32 +02:00
Timm Bäder 6b42e5b433 gl renderer: Fix push/pop modelview behavior 2019-06-29 08:57:27 +02:00
Timm Bäder 99c01607f1 gl renderer: Remove some dead code 2019-06-29 08:53:36 +02:00
Timm Bäder 071748592d gl renderer: Don't upload GL textures into the icon cache 2019-06-29 07:15:43 +02:00
Timm Bäder 8dd74eac2e transform: Add skew parsing 2019-06-29 07:15:43 +02:00
Matthias Clasen f6a2678486 Add another grid layout test
This one will be used for comparison
with constraint layouts.
2019-06-28 19:21:21 +00:00
Matthias Clasen e28ec2a3eb Some more grid layout tests
Add testcases for spanning children and homogeneity.
2019-06-28 18:07:23 +00:00
Matthias Clasen c4fd786866 Add a test for the grid layout manager
Test some obvious conditions. This is mainly
to test the waters for more intesting tests
with other layout managers later.
2019-06-28 13:30:16 +00:00
Matthias Clasen 8fa7de5563 grid layout: Fix initial property values
Too bad that we don't cover layout children
in the default value test - it would have
caught this.
2019-06-28 12:42:06 +00:00
75 changed files with 7578 additions and 3040 deletions
+1 -1
View File
@@ -105,7 +105,7 @@ pages:
image: registry.gitlab.gnome.org/gnome/gtk/master:v6
stage: deploy
script:
- meson -Ddocumentation=true _build .
- meson -Dgtk_doc=true _build .
- ninja -C _build
- ninja -C _build gdk4-doc gsk4-doc gtk4-doc
-6
View File
@@ -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>
+656
View File
@@ -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>
@@ -1,5 +1,5 @@
/*
* Copyright 2019 Red Hat, inc.
/*
* 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
@@ -14,34 +14,21 @@
* 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
* Authors: Matthias Clasen
*/
#include "gtkgridconstraint.h"
#include "gtkconstraintsolverprivate.h"
#pragma once
typedef struct {
GtkWidget *child;
int left;
int right;
int top;
int bottom;
} GtkGridConstraintChild;
#include <gtk/gtk.h>
struct _GtkGridConstraint {
GObject parent;
#define CONSTRAINT_EDITOR_TYPE (constraint_editor_get_type ())
gboolean row_homogeneous;
gboolean column_homogeneous;
G_DECLARE_FINAL_TYPE (ConstraintEditor, constraint_editor, CONSTRAINT, EDITOR, GtkWidget)
GPtrArray *children;
ConstraintEditor * constraint_editor_new (GListModel *model,
GtkConstraint *constraint);
GtkConstraintSolver *solver;
GPtrArray *refs;
};
gboolean gtk_grid_constraint_is_attached (GtkGridConstraint *constraint);
void gtk_grid_constraint_attach (GtkGridConstraint *constraint,
GtkConstraintSolver *solver,
GPtrArray *refs);
void gtk_grid_constraint_detach (GtkGridConstraint *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);
+343
View File
@@ -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;
}
+44
View File
@@ -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);
+411
View File
@@ -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);
}
+32
View File
@@ -0,0 +1,32 @@
/*
* Copyright © 2019 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#pragma once
#include <gtk/gtk.h>
#define 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);
+188
View File
@@ -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>
+28
View File
@@ -0,0 +1,28 @@
/*
* Copyright © 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen <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);
}
+19
View File
@@ -0,0 +1,19 @@
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,
install: false)
+66 -91
View File
@@ -1,128 +1,110 @@
/* Constraints/Grid
/* Constraints/VFL
*
* GtkConstraintLayout lets you define complex layouts
* like grids.
* 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 (ComplexGrid, complex_grid, COMPLEX, GRID, GtkWidget)
G_DECLARE_FINAL_TYPE (VflGrid, vfl_grid, VFL, GRID, GtkWidget)
struct _ComplexGrid
struct _VflGrid
{
GtkWidget parent_instance;
GtkWidget *button1, *button2, *button3;
GtkWidget *button4, *button5;
GtkWidget *button1, *button2;
GtkWidget *button3;
};
G_DEFINE_TYPE (ComplexGrid, complex_grid, GTK_TYPE_WIDGET)
G_DEFINE_TYPE (VflGrid, vfl_grid, GTK_TYPE_WIDGET)
static void
complex_grid_destroy (GtkWidget *widget)
vfl_grid_destroy (GtkWidget *widget)
{
ComplexGrid *self = COMPLEX_GRID (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);
g_clear_pointer (&self->button4, gtk_widget_destroy);
g_clear_pointer (&self->button5, gtk_widget_destroy);
GTK_WIDGET_CLASS (complex_grid_parent_class)->destroy (widget);
GTK_WIDGET_CLASS (vfl_grid_parent_class)->destroy (widget);
}
static void
complex_grid_class_init (ComplexGridClass *klass)
vfl_grid_class_init (VflGridClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
widget_class->destroy = complex_grid_destroy;
widget_class->destroy = vfl_grid_destroy;
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
}
/* Layout:
*
* +--------------------------------------+
* | +-----------+ |
* | | Child 4 | |
* | +-----------+-----------+----------+ |
* | | Child 1 | Child 2 | Child 3 | |
* | +-----------+-----------+----------+ |
* | | Child 5 | |
* | +-----------+ |
* +--------------------------------------+
* +-----------------------------+
* | +-----------+ +-----------+ |
* | | 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 (ComplexGrid *self,
build_constraints (VflGrid *self,
GtkConstraintLayout *manager)
{
GtkGridConstraint *constraint;
GtkConstraint *s;
const char * const vfl[] = {
"H:|-[button1(==button2)]-12-[button2]-|",
"H:|-[button3]-|",
"V:|-[button1]-12-[button3(==button1)]-|",
"V:|-[button2]-12-[button3(==button2)]-|",
};
GError *error = NULL;
s = gtk_constraint_new (NULL, GTK_CONSTRAINT_ATTRIBUTE_LEFT,
GTK_CONSTRAINT_RELATION_EQ,
self->button1, GTK_CONSTRAINT_ATTRIBUTE_LEFT,
1.0, 0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (manager, s);
s = gtk_constraint_new (self->button3, GTK_CONSTRAINT_ATTRIBUTE_RIGHT,
GTK_CONSTRAINT_RELATION_EQ,
NULL, GTK_CONSTRAINT_ATTRIBUTE_RIGHT,
1.0, 0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (manager, s);
s = gtk_constraint_new (NULL, GTK_CONSTRAINT_ATTRIBUTE_TOP,
GTK_CONSTRAINT_RELATION_EQ,
self->button4, GTK_CONSTRAINT_ATTRIBUTE_TOP,
1.0, 0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (manager, s);
s = gtk_constraint_new (NULL, GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
GTK_CONSTRAINT_RELATION_EQ,
self->button5, GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
1.0, 0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (manager, s);
constraint = gtk_grid_constraint_new ();
g_object_set (constraint, "column-homogeneous", TRUE, NULL);
gtk_grid_constraint_add (constraint,
self->button1,
0, 1, 0, 1);
gtk_grid_constraint_add (constraint,
self->button2,
1, 2, 0, 1);
gtk_grid_constraint_add (constraint,
self->button3,
2, 3, 0, 1);
gtk_constraint_layout_add_grid_constraint (manager, constraint);
constraint = gtk_grid_constraint_new ();
g_object_set (constraint, "row-homogeneous", TRUE, NULL);
gtk_grid_constraint_add (constraint,
self->button4,
0, 1, 0, 1);
gtk_grid_constraint_add (constraint,
self->button2,
0, 1, 1, 2);
gtk_grid_constraint_add (constraint,
self->button5,
0, 1, 2, 3);
gtk_constraint_layout_add_grid_constraint (manager, constraint);
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
complex_grid_init (ComplexGrid *self)
vfl_grid_init (VflGrid *self)
{
GtkWidget *widget = GTK_WIDGET (self);
GtkLayoutManager *manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
self->button1 = gtk_button_new_with_label ("Child 1");
gtk_widget_set_parent (self->button1, widget);
@@ -136,14 +118,7 @@ complex_grid_init (ComplexGrid *self)
gtk_widget_set_parent (self->button3, widget);
gtk_widget_set_name (self->button3, "button3");
self->button4 = gtk_button_new_with_label ("Child 4");
gtk_widget_set_parent (self->button4, widget);
gtk_widget_set_name (self->button4, "button4");
self->button5 = gtk_button_new_with_label ("Child 5");
gtk_widget_set_parent (self->button5, widget);
gtk_widget_set_name (self->button5, "button5");
GtkLayoutManager *manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
build_constraints (self, GTK_CONSTRAINT_LAYOUT (manager));
}
@@ -169,7 +144,7 @@ do_constraints3 (GtkWidget *do_widget)
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
gtk_container_add (GTK_CONTAINER (window), box);
grid = g_object_new (complex_grid_get_type (), NULL);
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);
+112 -289
View File
@@ -1,296 +1,138 @@
/* Constraints/Words
/* Constraints/Grid
*
* GtkConstraintLayout lets you define big grids.
* GtkConstraintLayout lets you define complex layouts
* like grids.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#define WORDS_TYPE_BASE (words_base_get_type ())
#define WORDS_TYPE_GRID (words_grid_get_type ())
#define WORDS_TYPE_CONSTRAINT (words_constraint_get_type ())
G_DECLARE_FINAL_TYPE (ComplexGrid, complex_grid, COMPLEX, GRID, GtkWidget)
typedef struct
struct _ComplexGrid
{
GtkWidget parent_instance;
} WordsBase;
typedef WordsBase WordsGrid;
typedef WordsBase WordsConstraint;
GtkWidget *button1, *button2, *button3;
GtkWidget *button4, *button5;
};
typedef GtkWidgetClass WordsBaseClass;
typedef GtkWidgetClass WordsGridClass;
typedef GtkWidgetClass WordsConstraintClass;
G_DEFINE_TYPE (WordsBase, words_base, GTK_TYPE_WIDGET)
G_DEFINE_TYPE (WordsGrid, words_grid, WORDS_TYPE_BASE)
G_DEFINE_TYPE (WordsConstraint, words_constraint, WORDS_TYPE_BASE)
G_DEFINE_TYPE (ComplexGrid, complex_grid, GTK_TYPE_WIDGET)
static void
words_grid_init (WordsGrid *words)
complex_grid_destroy (GtkWidget *widget)
{
ComplexGrid *self = COMPLEX_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);
g_clear_pointer (&self->button4, gtk_widget_destroy);
g_clear_pointer (&self->button5, gtk_widget_destroy);
GTK_WIDGET_CLASS (complex_grid_parent_class)->destroy (widget);
}
static void
words_grid_class_init (WordsGridClass *class)
complex_grid_class_init (ComplexGridClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_GRID_LAYOUT);
}
static void
words_constraint_init (WordsGrid *words)
{
}
static void
words_constraint_class_init (WordsConstraintClass *class)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
widget_class->destroy = complex_grid_destroy;
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
}
/* Layout:
*
* +--------------------------------------+
* | +-----------+ |
* | | Child 4 | |
* | +-----------+-----------+----------+ |
* | | Child 1 | Child 2 | Child 3 | |
* | +-----------+-----------+----------+ |
* | | Child 5 | |
* | +-----------+ |
* +--------------------------------------+
*
*/
static void
word_base_dispose (GObject *object)
build_constraints (ComplexGrid *self,
GtkConstraintLayout *manager)
{
GtkWidget *self = GTK_WIDGET (object);
GtkWidget *child;
GtkGridConstraint *constraint;
GtkConstraint *s;
while ((child = gtk_widget_get_first_child (self)) != NULL)
gtk_widget_unparent (child);
s = gtk_constraint_new (NULL, GTK_CONSTRAINT_ATTRIBUTE_LEFT,
GTK_CONSTRAINT_RELATION_EQ,
self->button1, GTK_CONSTRAINT_ATTRIBUTE_LEFT,
1.0, 0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (manager, s);
G_OBJECT_CLASS (words_base_parent_class)->dispose (object);
s = gtk_constraint_new (self->button3, GTK_CONSTRAINT_ATTRIBUTE_RIGHT,
GTK_CONSTRAINT_RELATION_EQ,
NULL, GTK_CONSTRAINT_ATTRIBUTE_RIGHT,
1.0, 0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (manager, s);
s = gtk_constraint_new (NULL, GTK_CONSTRAINT_ATTRIBUTE_TOP,
GTK_CONSTRAINT_RELATION_EQ,
self->button4, GTK_CONSTRAINT_ATTRIBUTE_TOP,
1.0, 0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (manager, s);
s = gtk_constraint_new (NULL, GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
GTK_CONSTRAINT_RELATION_EQ,
self->button5, GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
1.0, 0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (manager, s);
constraint = gtk_grid_constraint_new ();
g_object_set (constraint, "column-homogeneous", TRUE, NULL);
gtk_grid_constraint_add (constraint, self->button1, 0, 1, 0, 1);
gtk_grid_constraint_add (constraint, self->button2, 1, 2, 0, 1);
gtk_grid_constraint_add (constraint, self->button3, 2, 3, 0, 1);
gtk_grid_constraint_attach (constraint, manager);
constraint = gtk_grid_constraint_new ();
g_object_set (constraint, "row-homogeneous", TRUE, NULL);
gtk_grid_constraint_add (constraint, self->button4, 0, 1, 0, 1);
gtk_grid_constraint_add (constraint, self->button2, 0, 1, 1, 2);
gtk_grid_constraint_add (constraint, self->button5, 0, 1, 2, 3);
gtk_grid_constraint_attach (constraint, manager);
}
static void
words_base_class_init (WordsBaseClass *klass)
complex_grid_init (ComplexGrid *self)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidget *widget = GTK_WIDGET (self);
GtkLayoutManager *manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
object_class->dispose = word_base_dispose;
}
self->button1 = gtk_button_new_with_label ("Child 1");
gtk_widget_set_parent (self->button1, widget);
gtk_widget_set_name (self->button1, "button1");
static int num_words = 100;
static gboolean use_constraints = FALSE;
self->button2 = gtk_button_new_with_label ("Child 2");
gtk_widget_set_parent (self->button2, widget);
gtk_widget_set_name (self->button2, "button2");
static void
read_words (WordsBase *self)
{
GBytes *data;
const char *words;
int left, top;
GtkWidget *child = NULL;
GtkLayoutManager *layout = gtk_widget_get_layout_manager (GTK_WIDGET (self));
GtkGridConstraint *grid;
GtkConstraint *constraint;
int count;
int rightmost;
GtkWidget *right_child = NULL;
gboolean use_constraint = GTK_IS_CONSTRAINT_LAYOUT (layout);
self->button3 = gtk_button_new_with_label ("Child 3");
gtk_widget_set_parent (self->button3, widget);
gtk_widget_set_name (self->button3, "button3");
if (use_constraint)
{
grid = gtk_grid_constraint_new ();
g_object_set (grid,
"row-homogeneous", TRUE,
"column-homogeneous", FALSE,
NULL);
}
else
{
gtk_grid_layout_set_row_homogeneous (GTK_GRID_LAYOUT (layout), TRUE);
gtk_grid_layout_set_column_homogeneous (GTK_GRID_LAYOUT (layout), FALSE);
}
self->button4 = gtk_button_new_with_label ("Child 4");
gtk_widget_set_parent (self->button4, widget);
gtk_widget_set_name (self->button4, "button4");
data = g_resources_lookup_data ("/constraints4/words", 0, NULL);
words = g_bytes_get_data (data, NULL);
count = 0;
self->button5 = gtk_button_new_with_label ("Child 5");
gtk_widget_set_parent (self->button5, widget);
gtk_widget_set_name (self->button5, "button5");
rightmost = 0;
left = 0;
top = 0;
while (words && words[0])
{
char *p = strchr (words, '\n');
char *word;
int len;
if (p)
{
word = strndup (words, p - words);
words = p + 1;
}
else
{
word = strdup (words);
words = NULL;
}
len = strlen (word);
child = gtk_button_new_with_label (word);
if (left + len > 50)
{
top++;
left = 0;
}
gtk_widget_set_parent (child, GTK_WIDGET (self));
if (left + len > rightmost)
{
rightmost = left + len;
right_child = child;
}
if (use_constraint)
{
gtk_grid_constraint_add (grid, child,
left, left + len,
top, top + 1);
if (left == 0 && top == 0)
{
constraint = gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_TOP,
GTK_CONSTRAINT_RELATION_EQ,
child,
GTK_CONSTRAINT_ATTRIBUTE_TOP,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (layout),
constraint);
constraint = gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_LEFT,
GTK_CONSTRAINT_RELATION_EQ,
child,
GTK_CONSTRAINT_ATTRIBUTE_LEFT,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (layout),
constraint);
}
}
else
{
GtkGridLayoutChild *grid_child = GTK_GRID_LAYOUT_CHILD (gtk_layout_manager_get_layout_child (layout, child));
g_object_set (grid_child,
"left-attach", left,
"top-attach", top,
"column-span", len,
"row-span", 1,
NULL);
}
left = left + len;
count++;
if (count >= num_words)
break;
}
if (use_constraint)
{
constraint = gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_RIGHT,
GTK_CONSTRAINT_RELATION_EQ,
right_child,
GTK_CONSTRAINT_ATTRIBUTE_RIGHT,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (layout),
constraint);
constraint = gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
GTK_CONSTRAINT_RELATION_EQ,
child,
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (layout),
constraint);
gtk_constraint_layout_add_grid_constraint (GTK_CONSTRAINT_LAYOUT (layout),
grid);
}
g_bytes_unref (data);
}
static void
words_base_init (WordsBase *self)
{
read_words (self);
}
static void
show_words (GtkWidget *parent)
{
GtkWidget *window;
GtkWidget *header, *box, *grid, *button;
GtkWidget *swin;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_transient_for (GTK_WINDOW (window),
GTK_WINDOW (gtk_widget_get_root (parent)));
gtk_window_set_modal (GTK_WINDOW (window), TRUE);
header = gtk_header_bar_new ();
gtk_header_bar_set_title (GTK_HEADER_BAR (header), use_constraints ? "Constraints" : "Grid");
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
gtk_window_set_titlebar (GTK_WINDOW (window), header);
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add (GTK_CONTAINER (window), box);
swin = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_propagate_natural_width (GTK_SCROLLED_WINDOW (swin), TRUE);
gtk_scrolled_window_set_propagate_natural_height (GTK_SCROLLED_WINDOW (swin), TRUE);
gtk_widget_set_hexpand (swin, TRUE);
gtk_widget_set_vexpand (swin, TRUE);
gtk_widget_set_halign (swin, GTK_ALIGN_FILL);
gtk_widget_set_valign (swin, GTK_ALIGN_FILL);
gtk_container_add (GTK_CONTAINER (box), swin);
if (use_constraints)
grid = g_object_new (WORDS_TYPE_CONSTRAINT, NULL);
else
grid = g_object_new (WORDS_TYPE_GRID, NULL);
gtk_widget_set_halign (swin, GTK_ALIGN_START);
gtk_widget_set_valign (swin, GTK_ALIGN_START);
gtk_container_add (GTK_CONTAINER (swin), grid);
button = gtk_button_new_with_label ("Close");
gtk_container_add (GTK_CONTAINER (box), button);
g_signal_connect_swapped (button, "clicked",
G_CALLBACK (gtk_widget_destroy), window);
gtk_widget_show (window);
}
static void
use_constraints_cb (GtkButton *button)
{
use_constraints = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
}
static void
word_count_cb (GtkSpinButton *button)
{
num_words = gtk_spin_button_get_value_as_int (button);
build_constraints (self, GTK_CONSTRAINT_LAYOUT (manager));
}
GtkWidget *
@@ -300,50 +142,31 @@ do_constraints4 (GtkWidget *do_widget)
if (!window)
{
GtkWidget *header, *grid, *button, *label;
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), "Words");
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
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);
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
grid = gtk_grid_new ();
g_object_set (grid,
"margin", 12,
"row-spacing", 12,
"column-spacing", 6,
"halign", GTK_ALIGN_FILL,
"valign", GTK_ALIGN_FILL,
"hexpand", TRUE,
"vexpand", TRUE,
NULL);
gtk_container_add (GTK_CONTAINER (window), grid);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
gtk_container_add (GTK_CONTAINER (window), box);
label = gtk_label_new ("Constraints:");
gtk_label_set_xalign (GTK_LABEL (label), 1.0);
gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
button = gtk_check_button_new ();
g_signal_connect (button, "clicked", G_CALLBACK (use_constraints_cb), NULL);
gtk_grid_attach (GTK_GRID (grid), button, 1, 0, 1, 1);
label = gtk_label_new ("Words:");
gtk_label_set_xalign (GTK_LABEL (label), 1.0);
gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
button = gtk_spin_button_new_with_range (0, 1300, 1);
g_signal_connect (button, "value-changed", G_CALLBACK (word_count_cb), NULL);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (button), 10);
gtk_grid_attach (GTK_GRID (grid), button, 1, 1, 1, 1);
grid = g_object_new (complex_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 ("Show");
gtk_widget_set_halign (button, GTK_ALIGN_END);
gtk_widget_set_valign (button, GTK_ALIGN_END);
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 (show_words), window);
gtk_grid_attach (GTK_GRID (grid), button, 0, 2, 2, 1);
G_CALLBACK (gtk_widget_destroy), window);
}
if (!gtk_widget_get_visible (window))
+354
View File
@@ -0,0 +1,354 @@
/* Constraints/Words
*
* GtkConstraintLayout lets you define big grids.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#define WORDS_TYPE_BASE (words_base_get_type ())
#define WORDS_TYPE_GRID (words_grid_get_type ())
#define WORDS_TYPE_CONSTRAINT (words_constraint_get_type ())
typedef struct
{
GtkWidget parent_instance;
} WordsBase;
typedef WordsBase WordsGrid;
typedef WordsBase WordsConstraint;
typedef GtkWidgetClass WordsBaseClass;
typedef GtkWidgetClass WordsGridClass;
typedef GtkWidgetClass WordsConstraintClass;
G_DEFINE_TYPE (WordsBase, words_base, GTK_TYPE_WIDGET)
G_DEFINE_TYPE (WordsGrid, words_grid, WORDS_TYPE_BASE)
G_DEFINE_TYPE (WordsConstraint, words_constraint, WORDS_TYPE_BASE)
static void
words_grid_init (WordsGrid *words)
{
}
static void
words_grid_class_init (WordsGridClass *class)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_GRID_LAYOUT);
}
static void
words_constraint_init (WordsGrid *words)
{
}
static void
words_constraint_class_init (WordsConstraintClass *class)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
}
static void
word_base_dispose (GObject *object)
{
GtkWidget *self = GTK_WIDGET (object);
GtkWidget *child;
while ((child = gtk_widget_get_first_child (self)) != NULL)
gtk_widget_unparent (child);
G_OBJECT_CLASS (words_base_parent_class)->dispose (object);
}
static void
words_base_class_init (WordsBaseClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = word_base_dispose;
}
static int num_words = 100;
static gboolean use_constraints = FALSE;
static void
read_words (WordsBase *self)
{
GBytes *data;
const char *words;
int left, top;
GtkWidget *child = NULL;
GtkLayoutManager *layout = gtk_widget_get_layout_manager (GTK_WIDGET (self));
GtkGridConstraint *grid;
GtkConstraint *constraint;
int count;
int rightmost;
GtkWidget *right_child = NULL;
gboolean use_constraint = GTK_IS_CONSTRAINT_LAYOUT (layout);
if (use_constraint)
{
grid = gtk_grid_constraint_new ();
g_object_set (grid,
"row-homogeneous", TRUE,
"column-homogeneous", FALSE,
NULL);
}
else
{
gtk_grid_layout_set_row_homogeneous (GTK_GRID_LAYOUT (layout), TRUE);
gtk_grid_layout_set_column_homogeneous (GTK_GRID_LAYOUT (layout), FALSE);
}
data = g_resources_lookup_data ("/constraints5/words", 0, NULL);
words = g_bytes_get_data (data, NULL);
count = 0;
rightmost = 0;
left = 0;
top = 0;
while (words && words[0])
{
char *p = strchr (words, '\n');
char *word;
int len;
if (p)
{
word = strndup (words, p - words);
words = p + 1;
}
else
{
word = strdup (words);
words = NULL;
}
len = strlen (word);
child = gtk_button_new_with_label (word);
if (left + len > 50)
{
top++;
left = 0;
}
gtk_widget_set_parent (child, GTK_WIDGET (self));
if (left + len > rightmost)
{
rightmost = left + len;
right_child = child;
}
if (use_constraint)
{
gtk_grid_constraint_add (grid, child,
left, left + len,
top, top + 1);
if (left == 0 && top == 0)
{
constraint = gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_TOP,
GTK_CONSTRAINT_RELATION_EQ,
child,
GTK_CONSTRAINT_ATTRIBUTE_TOP,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (layout),
constraint);
constraint = gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_LEFT,
GTK_CONSTRAINT_RELATION_EQ,
child,
GTK_CONSTRAINT_ATTRIBUTE_LEFT,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (layout),
constraint);
}
}
else
{
GtkGridLayoutChild *grid_child = GTK_GRID_LAYOUT_CHILD (gtk_layout_manager_get_layout_child (layout, child));
g_object_set (grid_child,
"left-attach", left,
"top-attach", top,
"column-span", len,
"row-span", 1,
NULL);
}
left = left + len;
count++;
if (count >= num_words)
break;
}
if (use_constraint)
{
constraint = gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_RIGHT,
GTK_CONSTRAINT_RELATION_EQ,
right_child,
GTK_CONSTRAINT_ATTRIBUTE_RIGHT,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (layout),
constraint);
constraint = gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
GTK_CONSTRAINT_RELATION_EQ,
child,
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (layout),
constraint);
gtk_grid_constraint_attach (grid, GTK_CONSTRAINT_LAYOUT (layout));
}
g_bytes_unref (data);
}
static void
words_base_init (WordsBase *self)
{
read_words (self);
}
static void
show_words (GtkWidget *parent)
{
GtkWidget *window;
GtkWidget *header, *box, *grid, *button;
GtkWidget *swin;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_transient_for (GTK_WINDOW (window),
GTK_WINDOW (gtk_widget_get_root (parent)));
gtk_window_set_modal (GTK_WINDOW (window), TRUE);
header = gtk_header_bar_new ();
gtk_header_bar_set_title (GTK_HEADER_BAR (header), use_constraints ? "Constraints" : "Grid");
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
gtk_window_set_titlebar (GTK_WINDOW (window), header);
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add (GTK_CONTAINER (window), box);
swin = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_propagate_natural_width (GTK_SCROLLED_WINDOW (swin), TRUE);
gtk_scrolled_window_set_propagate_natural_height (GTK_SCROLLED_WINDOW (swin), TRUE);
gtk_widget_set_hexpand (swin, TRUE);
gtk_widget_set_vexpand (swin, TRUE);
gtk_widget_set_halign (swin, GTK_ALIGN_FILL);
gtk_widget_set_valign (swin, GTK_ALIGN_FILL);
gtk_container_add (GTK_CONTAINER (box), swin);
if (use_constraints)
grid = g_object_new (WORDS_TYPE_CONSTRAINT, NULL);
else
grid = g_object_new (WORDS_TYPE_GRID, NULL);
gtk_widget_set_halign (swin, GTK_ALIGN_START);
gtk_widget_set_valign (swin, GTK_ALIGN_START);
gtk_container_add (GTK_CONTAINER (swin), grid);
button = gtk_button_new_with_label ("Close");
gtk_container_add (GTK_CONTAINER (box), button);
g_signal_connect_swapped (button, "clicked",
G_CALLBACK (gtk_widget_destroy), window);
gtk_widget_show (window);
}
static void
use_constraints_cb (GtkButton *button)
{
use_constraints = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
}
static void
word_count_cb (GtkSpinButton *button)
{
num_words = gtk_spin_button_get_value_as_int (button);
}
GtkWidget *
do_constraints5 (GtkWidget *do_widget)
{
static GtkWidget *window;
if (!window)
{
GtkWidget *header, *grid, *button, *label;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
header = gtk_header_bar_new ();
gtk_header_bar_set_title (GTK_HEADER_BAR (header), "Words");
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
gtk_window_set_titlebar (GTK_WINDOW (window), header);
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
grid = gtk_grid_new ();
g_object_set (grid,
"margin", 12,
"row-spacing", 12,
"column-spacing", 6,
"halign", GTK_ALIGN_FILL,
"valign", GTK_ALIGN_FILL,
"hexpand", TRUE,
"vexpand", TRUE,
NULL);
gtk_container_add (GTK_CONTAINER (window), grid);
label = gtk_label_new ("Constraints:");
gtk_label_set_xalign (GTK_LABEL (label), 1.0);
gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
button = gtk_check_button_new ();
g_signal_connect (button, "clicked", G_CALLBACK (use_constraints_cb), NULL);
gtk_grid_attach (GTK_GRID (grid), button, 1, 0, 1, 1);
label = gtk_label_new ("Words:");
gtk_label_set_xalign (GTK_LABEL (label), 1.0);
gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
button = gtk_spin_button_new_with_range (0, 1300, 1);
g_signal_connect (button, "value-changed", G_CALLBACK (word_count_cb), NULL);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (button), 10);
gtk_grid_attach (GTK_GRID (grid), button, 1, 1, 1, 1);
button = gtk_button_new_with_label ("Show");
gtk_widget_set_halign (button, GTK_ALIGN_END);
gtk_widget_set_valign (button, GTK_ALIGN_END);
g_signal_connect_swapped (button, "clicked",
G_CALLBACK (show_words), window);
gtk_grid_attach (GTK_GRID (grid), button, 0, 2, 2, 1);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_widget_destroy (window);
return window;
}
+4 -3
View File
@@ -12,9 +12,6 @@
<gresource prefix="/builder">
<file>demo.ui</file>
</gresource>
<gresource prefix="/constraints4">
<file>words</file>
</gresource>
<gresource prefix="/css_accordion">
<file>css_accordion.css</file>
<file>reset.css</file>
@@ -62,6 +59,9 @@
<file>cssview.css</file>
<file>reset.css</file>
</gresource>
<gresource prefix="/constraints5">
<file>words</file>
</gresource>
<gresource prefix="/cursors">
<file>cursors.ui</file>
<file>alias_cursor.png</file>
@@ -157,6 +157,7 @@
<file>constraints2.c</file>
<file>constraints3.c</file>
<file>constraints4.c</file>
<file>constraints5.c</file>
<file>css_accordion.c</file>
<file>css_basics.c</file>
<file>css_blendmodes.c</file>
+1
View File
@@ -12,6 +12,7 @@ demos = files([
'constraints2.c',
'constraints3.c',
'constraints4.c',
'constraints5.c',
'css_accordion.c',
'css_basics.c',
'css_blendmodes.c',
-1315
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -1,3 +1,4 @@
subdir('constraint-editor')
subdir('gtk-demo')
subdir('icon-browser')
subdir('node-editor')
+1 -1
View File
@@ -1707,7 +1707,7 @@ activate (GApplication *app)
gtk_css_provider_load_from_resource (provider, "/org/gtk/WidgetFactory4/widget-factory.css");
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_USER);
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
g_object_unref (provider);
builder = gtk_builder_new_from_resource ("/org/gtk/WidgetFactory4/widget-factory.ui");
+1 -1
View File
@@ -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',
+1 -1
View File
@@ -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',
+4 -4
View File
@@ -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
+3
View File
@@ -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">
+84
View File
@@ -7287,3 +7287,87 @@ gtk_grid_layout_get_type
GTK_TYPE_GRID_LAYOUT_CHILD
gtk_grid_layout_child_get_type
</SECTION>
<SECTION>
<FILE>gtkconstraint</FILE>
GtkConstraint
GtkConstraintTarget
gtk_constraint_new
gtk_constraint_new_constant
gtk_constraint_get_target
GtkConstraintAttribute
gtk_constraint_get_target_attribute
GtkConstraintRelation
gtk_constraint_get_relation
gtk_constraint_get_source
gtk_constraint_get_source_attribute
gtk_constraint_get_multiplier
gtk_constraint_get_constant
GtkConstraintStrength
gtk_constraint_get_strength
gtk_constraint_is_required
gtk_constraint_is_attached
gtk_constraint_is_constant
<SUBSECTION Standard>
GTK_TYPE_CONSTRAINT
gtk_constraint_get_type
GTK_TYPE_CONSTRAINT_TARGET
gtk_constraint_target_get_type
</SECTION>
<SECTION>
<FILE>gtkconstraintlayout</FILE>
GtkConstraintLayout
GtkConstraintLayoutChild
GtkConstraintVflParserError
gtk_constraint_layout_new
<SUBSECTION Constraints>
gtk_constraint_layout_add_constraint
gtk_constraint_layout_remove_constraint
gtk_constraint_layout_remove_all_constraints
<SUBSECTION Guides>
gtk_constraint_layout_add_guide
gtk_constraint_layout_remove_guide
<SUBSECTION VFL>
gtk_constraint_layout_add_constraints_from_description
gtk_constraint_layout_add_constraints_from_descriptionv
<SUBSECTION>
gtk_constraint_layout_observe_constraints
gtk_constraint_layout_observe_guides
<SUBSECTION Standard>
GTK_TYPE_CONSTRAINT_LAYOUT
gtk_constraint_layout_get_type
GTK_TYPE_CONSTRAINT_LAYOUT_CHILD
gtk_constraint_layout_child_get_type
GTK_CONSTRAINT_VFL_PARSER_ERROR
gtk_constraint_vfl_parser_error_quark
</SECTION>
<SECTION>
<FILE>gtkconstraintguide</FILE>
GtkConstraintGuide
gtk_constraint_guide_new
gtk_constraint_guide_set_name
gtk_constraint_guide_get_name
gtk_constraint_guide_set_strength
gtk_constraint_guide_get_strength
gtk_constraint_guide_set_min_size
gtk_constraint_guide_get_min_size
gtk_constraint_guide_set_nat_size
gtk_constraint_guide_get_nat_size
gtk_constraint_guide_set_max_size
gtk_constraint_guide_get_max_size
<SUBSECTION Standard>
GTK_TYPE_CONSTRAINT_GUIDE
gtk_constraint_guide_get_tyoe
</SECTION>
+4
View File
@@ -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
+8 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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',
+2 -4
View File
@@ -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,
&region, &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);
+3
View File
@@ -339,9 +339,12 @@ ops_set_modelview_internal (RenderOpBuilder *builder,
RenderOp op;
graphene_matrix_t matrix;
#if 0
XXX This is not possible if we want pop() to work.
if (builder->current_program &&
gsk_transform_equal (builder->current_program_state->modelview, transform))
return;
#endif
gsk_transform_to_matrix (transform, &matrix);
+44 -4
View File
@@ -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;
-9
View File
@@ -561,13 +561,6 @@ prop_actions_connect (GtkActionMuxer *muxer)
}
}
static void
prop_actions_disconnect (GtkActionMuxer *muxer)
{
if (muxer->widget)
g_signal_handlers_disconnect_by_func (muxer->widget,
prop_action_notify, muxer);
}
static gboolean
gtk_action_muxer_query_action (GActionGroup *action_group,
@@ -819,8 +812,6 @@ gtk_action_muxer_dispose (GObject *object)
{
GtkActionMuxer *muxer = GTK_ACTION_MUXER (object);
prop_actions_disconnect (muxer);
if (muxer->parent)
{
g_signal_handlers_disconnect_by_func (muxer->parent, gtk_action_muxer_action_added_to_parent, muxer);
+63 -66
View File
@@ -211,7 +211,7 @@ gtk_constraint_class_init (GtkConstraintClass *klass)
/**
* GtkConstraint:relation:
*
* The relation order between the terms of the constraint.
* The order relation between the terms of the constraint.
*/
obj_props[PROP_RELATION] =
g_param_spec_enum ("relation",
@@ -292,7 +292,7 @@ gtk_constraint_class_init (GtkConstraintClass *klass)
g_param_spec_int ("strength",
P_("Strength"),
P_("The strength of the constraint"),
GTK_CONSTRAINT_STRENGTH_WEAK, G_MAXINT,
0, GTK_CONSTRAINT_STRENGTH_REQUIRED,
GTK_CONSTRAINT_STRENGTH_REQUIRED,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS |
@@ -387,24 +387,16 @@ gtk_constraint_new_constant (gpointer target,
}
/**
* gtk_constraint_get_target_widget:
* gtk_constraint_get_target:
* @constraint: a #GtkConstraint
*
* Retrieves the target widget for the @constraint.
* Retrieves the #GtkConstraintTarget used as the target for @constraint.
*
* Returns: (transfer none) (nullable): a #GtkWidget
* If the #GtkConstraint:target property is set to %NULL, the @constraint
* will use the #GtkConstraintLayout's widget.
*
* Returns: (transfer none) (nullable): a #GtkConstraintTarget
*/
GtkWidget *
gtk_constraint_get_target_widget (GtkConstraint *constraint)
{
g_return_val_if_fail (GTK_IS_CONSTRAINT (constraint), NULL);
if (GTK_IS_WIDGET (constraint->target))
return GTK_WIDGET (constraint->target);
return NULL;
}
GtkConstraintTarget *
gtk_constraint_get_target (GtkConstraint *constraint)
{
@@ -413,6 +405,14 @@ gtk_constraint_get_target (GtkConstraint *constraint)
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)
{
@@ -422,24 +422,16 @@ gtk_constraint_get_target_attribute (GtkConstraint *constraint)
}
/**
* gtk_constraint_get_source_widget:
* gtk_constraint_get_source:
* @constraint: a #GtkConstraint
*
* Retrieves the source widget for the @constraint.
* Retrieves the #GtkConstraintTarget used as the source for @constraint.
*
* Returns: (transfer none) (nullable): a #GtkWidget
* If the #GtkConstraint:source property is set to %NULL, the @constraint
* will use the #GtkConstraintLayout's widget.
*
* Returns: (transfer none) (nullable): a #GtkConstraintTarget
*/
GtkWidget *
gtk_constraint_get_source_widget (GtkConstraint *constraint)
{
g_return_val_if_fail (GTK_IS_CONSTRAINT (constraint), NULL);
if (GTK_IS_WIDGET (constraint->source))
return GTK_WIDGET (constraint->source);
return NULL;
}
GtkConstraintTarget *
gtk_constraint_get_source (GtkConstraint *constraint)
{
@@ -448,6 +440,14 @@ gtk_constraint_get_source (GtkConstraint *constraint)
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)
{
@@ -456,6 +456,14 @@ gtk_constraint_get_source_attribute (GtkConstraint *constraint)
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)
{
@@ -464,6 +472,15 @@ gtk_constraint_get_relation (GtkConstraint *constraint)
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)
{
@@ -472,6 +489,14 @@ gtk_constraint_get_multiplier (GtkConstraint *constraint)
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)
{
@@ -480,6 +505,14 @@ gtk_constraint_get_constant (GtkConstraint *constraint)
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)
{
@@ -488,42 +521,6 @@ gtk_constraint_get_strength (GtkConstraint *constraint)
return constraint->strength;
}
/*< private >
* gtk_constraint_get_weight:
* @constraint: a #GtkConstraint
*
* Computes the weight of the @constraint to be used with
* #GtkConstraintSolver.
*
* Returns: the weight of the constraint
*/
double
gtk_constraint_get_weight (GtkConstraint *constraint)
{
if (constraint->strength > 0)
return constraint->strength;
switch (constraint->strength)
{
case GTK_CONSTRAINT_STRENGTH_REQUIRED:
return GTK_CONSTRAINT_WEIGHT_REQUIRED;
case GTK_CONSTRAINT_STRENGTH_STRONG:
return GTK_CONSTRAINT_WEIGHT_STRONG;
case GTK_CONSTRAINT_STRENGTH_MEDIUM:
return GTK_CONSTRAINT_WEIGHT_MEDIUM;
case GTK_CONSTRAINT_STRENGTH_WEAK:
return GTK_CONSTRAINT_WEIGHT_WEAK;
default:
g_assert_not_reached ();
}
return 0;
}
/**
* gtk_constraint_is_required:
* @constraint: a #GtkConstraint
-4
View File
@@ -73,15 +73,11 @@ GtkConstraint * gtk_constraint_new_constant (gpointer
double constant,
int strength);
GDK_AVAILABLE_IN_ALL
GtkWidget * gtk_constraint_get_target_widget (GtkConstraint *constraint);
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
GtkWidget * gtk_constraint_get_source_widget (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);
+11 -24
View File
@@ -55,9 +55,12 @@ static guint64 gtk_constraint_variable_next_id;
static void
gtk_constraint_variable_init (GtkConstraintVariable *variable,
const char *prefix,
const char *name)
{
variable->_id = gtk_constraint_variable_next_id++;
variable->prefix = g_intern_string (prefix);
variable->name = g_intern_string (name);
variable->prefix = NULL;
variable->value = 0.0;
@@ -81,7 +84,7 @@ gtk_constraint_variable_new_dummy (const char *name)
{
GtkConstraintVariable *res = g_rc_box_new (GtkConstraintVariable);
gtk_constraint_variable_init (res, name);
gtk_constraint_variable_init (res, NULL, name);
res->_type = GTK_CONSTRAINT_SYMBOL_DUMMY;
res->is_external = FALSE;
@@ -108,7 +111,7 @@ gtk_constraint_variable_new_objective (const char *name)
{
GtkConstraintVariable *res = g_rc_box_new (GtkConstraintVariable);
gtk_constraint_variable_init (res, name);
gtk_constraint_variable_init (res, NULL, name);
res->_type = GTK_CONSTRAINT_SYMBOL_OBJECTIVE;
res->is_external = FALSE;
@@ -145,7 +148,7 @@ gtk_constraint_variable_new_slack (const char *name)
{
GtkConstraintVariable *res = g_rc_box_new (GtkConstraintVariable);
gtk_constraint_variable_init (res, name);
gtk_constraint_variable_init (res, NULL, name);
res->_type = GTK_CONSTRAINT_SYMBOL_SLACK;
res->is_external = FALSE;
@@ -157,7 +160,8 @@ gtk_constraint_variable_new_slack (const char *name)
/*< private >
* gtk_constraint_variable_new:
* @name: the name of the variable
* @prefix: (nullable): an optional prefix string for @name
* @name: (nullable): an optional name for the variable
*
* Allocates and initializes a new #GtkConstraintVariable for a regular
* symbol. All variables introduced by constraints are regular variables.
@@ -170,11 +174,12 @@ gtk_constraint_variable_new_slack (const char *name)
* Returns: a newly allocated #GtkConstraintVariable
*/
GtkConstraintVariable *
gtk_constraint_variable_new (const char *name)
gtk_constraint_variable_new (const char *prefix,
const char *name)
{
GtkConstraintVariable *res = g_rc_box_new (GtkConstraintVariable);
gtk_constraint_variable_init (res, name);
gtk_constraint_variable_init (res, prefix, name);
res->_type = GTK_CONSTRAINT_SYMBOL_REGULAR;
res->is_external = TRUE;
@@ -184,24 +189,6 @@ gtk_constraint_variable_new (const char *name)
return res;
}
/*< private >
* gtk_constraint_variable_set_prefix:
* @variable: a #GtkConstraintVariable
* @prefix: a prefix string
*
* Sets the prefix to the @variable's name.
*
* This function is useful when debugging the variable contents.
*/
void
gtk_constraint_variable_set_prefix (GtkConstraintVariable *variable,
const char *prefix)
{
g_return_if_fail (variable != NULL);
variable->prefix = g_intern_string (prefix);
}
/*< private >
* gtk_constraint_variable_ref:
* @variable: a #GtkConstraintVariable
+2 -5
View File
@@ -26,7 +26,8 @@
G_BEGIN_DECLS
GtkConstraintVariable *
gtk_constraint_variable_new (const char *name);
gtk_constraint_variable_new (const char *prefix,
const char *name);
GtkConstraintVariable *
gtk_constraint_variable_new_dummy (const char *name);
@@ -50,10 +51,6 @@ gtk_constraint_variable_set_value (GtkConstraintVariable *variable,
double
gtk_constraint_variable_get_value (const GtkConstraintVariable *variable);
void
gtk_constraint_variable_set_prefix (GtkConstraintVariable *variable,
const char *prefix);
char *
gtk_constraint_variable_to_string (const GtkConstraintVariable *variable);
+92 -5
View File
@@ -17,6 +17,19 @@
* 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"
@@ -145,7 +158,7 @@ gtk_constraint_guide_update_constraint (GtkConstraintGuide *guide,
var,
GTK_CONSTRAINT_RELATION_GE,
gtk_constraint_expression_new (guide->values[index]),
GTK_CONSTRAINT_WEIGHT_REQUIRED);
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]))
@@ -164,8 +177,10 @@ gtk_constraint_guide_update_constraint (GtkConstraintGuide *guide,
var,
GTK_CONSTRAINT_RELATION_LE,
gtk_constraint_expression_new (guide->values[index]),
GTK_CONSTRAINT_WEIGHT_REQUIRED);
GTK_CONSTRAINT_STRENGTH_REQUIRED);
}
gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (guide->layout));
}
void
@@ -292,7 +307,7 @@ gtk_constraint_guide_get_property (GObject *gobject,
break;
case PROP_STRENGTH:
g_value_set_int (value, self->strength);
g_value_set_enum (value, self->strength);
break;
case PROP_NAME:
@@ -326,6 +341,11 @@ gtk_constraint_guide_class_init (GtkConstraintGuideClass *class)
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",
@@ -333,6 +353,11 @@ gtk_constraint_guide_class_init (GtkConstraintGuideClass *class)
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",
@@ -340,6 +365,11 @@ gtk_constraint_guide_class_init (GtkConstraintGuideClass *class)
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",
@@ -347,6 +377,11 @@ gtk_constraint_guide_class_init (GtkConstraintGuideClass *class)
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",
@@ -354,6 +389,11 @@ gtk_constraint_guide_class_init (GtkConstraintGuideClass *class)
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",
@@ -361,6 +401,11 @@ gtk_constraint_guide_class_init (GtkConstraintGuideClass *class)
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",
@@ -368,7 +413,12 @@ gtk_constraint_guide_class_init (GtkConstraintGuideClass *class)
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",
@@ -377,7 +427,11 @@ gtk_constraint_guide_class_init (GtkConstraintGuideClass *class)
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",
@@ -563,6 +617,14 @@ gtk_constraint_guide_get_max_size (GtkConstraintGuide *guide,
*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)
{
@@ -571,6 +633,15 @@ gtk_constraint_guide_get_name (GtkConstraintGuide *guide)
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)
@@ -582,6 +653,14 @@ gtk_constraint_guide_set_name (GtkConstraintGuide *guide,
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)
{
@@ -591,6 +670,14 @@ gtk_constraint_guide_get_strength (GtkConstraintGuide *guide)
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)
-1
View File
@@ -25,7 +25,6 @@
G_BEGIN_DECLS
#define GTK_TYPE_CONSTRAINT_GUIDE (gtk_constraint_guide_get_type ())
/**
+1056 -190
View File
File diff suppressed because it is too large Load Diff
+33 -9
View File
@@ -21,12 +21,12 @@
#include <gtk/gtklayoutmanager.h>
#include <gtk/gtkconstraint.h>
#include <gtk/gtkconstraintguide.h>
#include <gtk/gtkgridconstraint.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:
@@ -45,25 +45,49 @@ G_DECLARE_FINAL_TYPE (GtkConstraintLayoutChild, gtk_constraint_layout_child, GTK
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 *manager,
void gtk_constraint_layout_add_constraint (GtkConstraintLayout *layout,
GtkConstraint *constraint);
GDK_AVAILABLE_IN_ALL
void gtk_constraint_layout_remove_constraint (GtkConstraintLayout *manager,
void gtk_constraint_layout_remove_constraint (GtkConstraintLayout *layout,
GtkConstraint *constraint);
GDK_AVAILABLE_IN_ALL
void gtk_constraint_layout_add_grid_constraint (GtkConstraintLayout *manager,
GtkGridConstraint *constraint);
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
void gtk_constraint_layout_add_guide (GtkConstraintLayout *manager,
GtkConstraintGuide *guide);
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
void gtk_constraint_layout_remove_guide (GtkConstraintLayout *manager,
GtkConstraintGuide *guide);
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
-2
View File
@@ -52,8 +52,6 @@ struct _GtkConstraint
guint active : 1;
};
double gtk_constraint_get_weight (GtkConstraint *constraint);
void gtk_constraint_attach (GtkConstraint *constraint,
GtkConstraintSolver *solver,
GtkConstraintRef *ref);
+40 -39
View File
@@ -73,14 +73,14 @@
* e = gtk_constraint_expression_builder_finish (&builder);
* gtk_constraint_solver_add_constraint (solver,
* right, GTK_CONSTRAINT_RELATION_EQ, e,
* GTK_CONSTRAINT_WEIGHT_REQUIRED);
* GTK_CONSTRAINT_STRENGTH_REQUIRED);
*
* // right ≤ 100
* gtk_constraint_expression_builder_constant (&builder, 100.0);
* e = gtk_constraint_expression_builder_finish (&builder);
* gtk_constraint_solver_add_constraint (solver,
* right, GTK_CONSTRAINT_RELATION_LE, e,
* GTK_CONSTRAINT_WEIGHT_REQUIRED);
* GTK_CONSTRAINT_STRENGTH_REQUIRED);
*
* // middle = (left + right) / 2
* gtk_constraint_expression_builder_term (&builder, left);
@@ -91,14 +91,14 @@
* e = gtk_constraint_expression_builder_finish (&builder);
* gtk_constraint_solver_add_constraint (solver
* middle, GTK_CONSTRAINT_RELATION_EQ, e,
* GTK_CONSTRAINT_WEIGHT_REQUIRED);
* GTK_CONSTRAINT_STRENGTH_REQUIRED);
*
* // left ≥ 0
* gtk_constraint_expression_builder_constant (&builder, 0.0);
* e = gtk_constraint_expression_builder_finish (&builder);
* gtk_constraint_solver_add_constraint (solver,
* left, GTK_CONSTRAINT_RELATION_GE, e,
* GTK_CONSTRAINT_WEIGHT_REQUIRED);
* GTK_CONSTRAINT_STRENGTH_REQUIRED);
* ]|
*
* Now that we have all our constraints in place, suppose we wish to find
@@ -110,8 +110,8 @@
* |[
* // Set the value first
* gtk_constraint_variable_set_value (middle, 45.0);
* // and then add the stay constraint, with a weak weight
* gtk_constraint_solver_add_stay_variable (solver, middle, GTK_CONSTRAINT_WEIGHT_WEAK);
* // and then add the stay constraint, with a weak strength
* gtk_constraint_solver_add_stay_variable (solver, middle, GTK_CONSTRAINT_STRENGTH_WEAK);
* ]|
*
* GtkConstraintSolver incrementally solves the system every time a constraint
@@ -185,8 +185,11 @@ struct _GtkConstraintRef
/* The original relation used when creating the constraint */
GtkConstraintRelation relation;
/* The weight, or strength, of the constraint */
double weight;
/* The strength of the constraint; this value is used to strengthen
* or weaken a constraint weight in the tableau when coming to a
* solution
*/
int strength;
GtkConstraintSolver *solver;
@@ -374,7 +377,7 @@ gtk_constraint_ref_is_inequality (const GtkConstraintRef *self)
static gboolean
gtk_constraint_ref_is_required (const GtkConstraintRef *self)
{
return self->weight >= GTK_CONSTRAINT_WEIGHT_REQUIRED;
return self->strength == GTK_CONSTRAINT_STRENGTH_REQUIRED;
}
static const char *relations[] = {
@@ -390,15 +393,12 @@ relation_to_string (GtkConstraintRelation r)
}
static const char *
weight_to_string (double s)
strength_to_string (int s)
{
if (s >= GTK_CONSTRAINT_WEIGHT_REQUIRED)
return "required";
if (s >= GTK_CONSTRAINT_WEIGHT_STRONG)
if (s >= GTK_CONSTRAINT_STRENGTH_STRONG)
return "strong";
if (s >= GTK_CONSTRAINT_WEIGHT_MEDIUM)
if (s >= GTK_CONSTRAINT_STRENGTH_MEDIUM)
return "medium";
return "weak";
@@ -423,9 +423,12 @@ gtk_constraint_ref_to_string (const GtkConstraintRef *self)
g_string_append (buf, relation_to_string (self->relation));
g_string_append (buf, " 0.0");
g_string_append_printf (buf, " [weight:%s (%g)]",
weight_to_string (self->weight),
self->weight);
if (gtk_constraint_ref_is_required (self))
g_string_append (buf, " [strength:required]");
else
g_string_append_printf (buf, " [strength:%d (%s)]",
self->strength,
strength_to_string (self->strength));
return g_string_free (buf, FALSE);
}
@@ -909,7 +912,7 @@ gtk_constraint_solver_new_expression (GtkConstraintSolver *self,
gtk_constraint_variable_unref (eminus);
z_row = g_hash_table_lookup (self->rows, self->objective);
gtk_constraint_expression_set_variable (z_row, eminus, constraint->weight);
gtk_constraint_expression_set_variable (z_row, eminus, constraint->strength);
gtk_constraint_solver_insert_error_variable (self, constraint, eminus);
gtk_constraint_solver_note_added_variable (self, eminus, self->objective);
@@ -939,6 +942,8 @@ gtk_constraint_solver_new_expression (GtkConstraintSolver *self,
gtk_constraint_expression_set_variable (expr, dummy_var, 1.0);
g_hash_table_insert (self->marker_vars, constraint, dummy_var);
gtk_constraint_variable_unref (dummy_var);
}
else
{
@@ -966,8 +971,8 @@ gtk_constraint_solver_new_expression (GtkConstraintSolver *self,
z_row = g_hash_table_lookup (self->rows, self->objective);
gtk_constraint_expression_set_variable (z_row, eplus, constraint->weight);
gtk_constraint_expression_set_variable (z_row, eminus, constraint->weight);
gtk_constraint_expression_set_variable (z_row, eplus, constraint->strength);
gtk_constraint_expression_set_variable (z_row, eminus, constraint->strength);
gtk_constraint_solver_note_added_variable (self, eplus, self->objective);
gtk_constraint_solver_note_added_variable (self, eminus, self->objective);
@@ -1049,10 +1054,7 @@ gtk_constraint_solver_dual_optimize (GtkConstraintSolver *self)
}
if (ratio == DBL_MAX)
{
g_critical ("INTERNAL: ratio == DBL_MAX in dual_optimize");
break;
}
g_critical ("INTERNAL: ratio == DBL_MAX in dual_optimize");
gtk_constraint_solver_pivot (self, entry_var, exit_var);
}
@@ -1480,12 +1482,11 @@ gtk_constraint_solver_create_variable (GtkConstraintSolver *self,
{
GtkConstraintVariable *res;
self->var_counter++;
res = gtk_constraint_variable_new (name);
gtk_constraint_variable_set_prefix (res, prefix);
res = gtk_constraint_variable_new (prefix, name);
gtk_constraint_variable_set_value (res, value);
self->var_counter++;
return res;
}
@@ -1524,7 +1525,7 @@ gtk_constraint_solver_resolve (GtkConstraintSolver *solver)
* @variable: the subject of the constraint
* @relation: the relation of the constraint
* @expression: the expression of the constraint
* @strength: the weight of the constraint
* @strength: the strength of the constraint
*
* Adds a new constraint in the form of:
*
@@ -1543,12 +1544,12 @@ gtk_constraint_solver_add_constraint (GtkConstraintSolver *self,
GtkConstraintVariable *variable,
GtkConstraintRelation relation,
GtkConstraintExpression *expression,
double strength)
int strength)
{
GtkConstraintRef *res = g_new0 (GtkConstraintRef, 1);
res->solver = self;
res->weight = strength;
res->strength = strength;
res->is_edit = FALSE;
res->is_stay = FALSE;
res->relation = relation;
@@ -1600,7 +1601,7 @@ gtk_constraint_solver_add_constraint (GtkConstraintSolver *self,
* gtk_constraint_solver_add_stay_variable:
* @self: a #GtkConstraintSolver
* @variable: a stay #GtkConstraintVariable
* @strength: the weight of the constraint
* @strength: the strength of the constraint
*
* Adds a constraint on a stay @variable with the given @strength.
*
@@ -1614,14 +1615,14 @@ gtk_constraint_solver_add_constraint (GtkConstraintSolver *self,
GtkConstraintRef *
gtk_constraint_solver_add_stay_variable (GtkConstraintSolver *self,
GtkConstraintVariable *variable,
double strength)
int strength)
{
GtkConstraintRef *res = g_new0 (GtkConstraintRef, 1);
res->solver = self;
res->variable = gtk_constraint_variable_ref (variable);
res->relation = GTK_CONSTRAINT_RELATION_EQ;
res->weight = strength;
res->strength = strength;
res->is_stay = TRUE;
res->is_edit = FALSE;
@@ -1694,14 +1695,14 @@ gtk_constraint_solver_remove_stay_variable (GtkConstraintSolver *self,
GtkConstraintRef *
gtk_constraint_solver_add_edit_variable (GtkConstraintSolver *self,
GtkConstraintVariable *variable,
double strength)
int strength)
{
GtkConstraintRef *res = g_new0 (GtkConstraintRef, 1);
res->solver = self;
res->variable = gtk_constraint_variable_ref (variable);
res->relation = GTK_CONSTRAINT_RELATION_EQ;
res->weight = strength;
res->strength = strength;
res->is_stay = FALSE;
res->is_edit = TRUE;
@@ -1784,7 +1785,7 @@ gtk_constraint_solver_remove_constraint (GtkConstraintSolver *self,
{
gtk_constraint_expression_add_variable (z_row,
v,
constraint->weight,
constraint->strength,
self->objective,
self);
}
@@ -1792,7 +1793,7 @@ gtk_constraint_solver_remove_constraint (GtkConstraintSolver *self,
{
gtk_constraint_expression_add_expression (z_row,
e,
constraint->weight,
constraint->strength,
self->objective,
self);
}
+3 -54
View File
@@ -25,61 +25,10 @@
G_BEGIN_DECLS
#ifdef GTK_TEST_EXTERNAL
#define GTK_TYPE_CONSTRAINT_SOLVER (g_type_from_name ("GtkConstraintSolver"))
#define GTK_CONSTRAINT_SOLVER(solver) (G_TYPE_CHECK_INSTANCE_CAST ((solver), GTK_TYPE_CONSTRAINT_SOLVER, GtkConstraintSolver))
#define GTK_CONSTRAINT_SOLVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_CONSTRAINT_SOLVER, GtkConstraintSolverClass))
#define GTK_IS_CONSTRAINT_SOLVER(solver) (G_TYPE_CHECK_INSTANCE_TYPE ((solver), GTK_TYPE_CONSTRAINT_SOLVER))
#define GTK_IS_CONSTRAINT_SOLVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_CONSTRAINT_SOLVER))
#define GTK_CONSTRAINT_SOLVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CONSTRAINT_SOLVER, GtkConstraintSolverClass))
typedef struct _GtkConstraintSolver GtkConstraintSolver;
typedef struct _GtkConstraintSolverClass GtkConstraintSolverClass;
struct _GtkConstraintSolverClass {
GObjectClass parent_class;
};
#else
#define GTK_TYPE_CONSTRAINT_SOLVER (gtk_constraint_solver_get_type())
G_DECLARE_FINAL_TYPE (GtkConstraintSolver, gtk_constraint_solver, GTK, CONSTRAINT_SOLVER, GObject)
#endif
/* Symbolic weight thresholds
*
* Constraint weights live on a continuum, but we use thresholds for simplicity's
* sake, so we don't have to necessarily reason in terms of numeric values.
*
* The public API has a similar approach, where the symbolic constants are negative
* values, and positive values are explicit weights. We map those values into
* numeric values that the GtkConstraintSolver can plug into the linear equations
* tableau.
*/
#define GTK_CONSTRAINT_WEIGHT_REQUIRED (make_weight (1000, 1000, 1000, 1))
#define GTK_CONSTRAINT_WEIGHT_STRONG (make_weight ( 1, 0, 0, 1))
#define GTK_CONSTRAINT_WEIGHT_MEDIUM (make_weight ( 0, 1, 0, 1))
#define GTK_CONSTRAINT_WEIGHT_WEAK (make_weight ( 0, 0, 1, 1))
G_GNUC_PURE
static inline double
make_weight (double a,
double b,
double c,
double w)
{
double res = 0;
res += CLAMP (a * w, 0, 1000) * 1000000;
res += CLAMP (b * w, 0, 1000) * 1000;
res += CLAMP (c * w, 0, 1000);
return res;
}
GtkConstraintSolver *
gtk_constraint_solver_new (void);
@@ -103,7 +52,7 @@ gtk_constraint_solver_add_constraint (GtkConstraintSolver *solver,
GtkConstraintVariable *variable,
GtkConstraintRelation relation,
GtkConstraintExpression *expression,
double strength);
int strength);
void
gtk_constraint_solver_remove_constraint (GtkConstraintSolver *solver,
@@ -112,7 +61,7 @@ gtk_constraint_solver_remove_constraint (GtkConstraintSolver *solver,
GtkConstraintRef *
gtk_constraint_solver_add_stay_variable (GtkConstraintSolver *solver,
GtkConstraintVariable *variable,
double strength);
int strength);
void
gtk_constraint_solver_remove_stay_variable (GtkConstraintSolver *solver,
@@ -125,7 +74,7 @@ gtk_constraint_solver_has_stay_variable (GtkConstraintSolver *solver,
GtkConstraintRef *
gtk_constraint_solver_add_edit_variable (GtkConstraintSolver *solver,
GtkConstraintVariable *variable,
double strength);
int strength);
void
gtk_constraint_solver_remove_edit_variable (GtkConstraintSolver *solver,
File diff suppressed because it is too large Load Diff
+76
View File
@@ -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
+24 -4
View File
@@ -1080,10 +1080,10 @@ typedef enum {
* integer; the values of this enumeration can be used for readability.
*/
typedef enum {
GTK_CONSTRAINT_STRENGTH_REQUIRED = 0,
GTK_CONSTRAINT_STRENGTH_STRONG = -1,
GTK_CONSTRAINT_STRENGTH_MEDIUM = -2,
GTK_CONSTRAINT_STRENGTH_WEAK = -3
GTK_CONSTRAINT_STRENGTH_REQUIRED = 1001001000,
GTK_CONSTRAINT_STRENGTH_STRONG = 1000000000,
GTK_CONSTRAINT_STRENGTH_MEDIUM = 1000,
GTK_CONSTRAINT_STRENGTH_WEAK = 1
} GtkConstraintStrength;
/**
@@ -1127,4 +1127,24 @@ typedef enum {
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__ */
+11 -3
View File
@@ -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)
+457 -28
View File
@@ -20,11 +20,81 @@
#include "config.h"
#include "gtkgridconstraint.h"
#include "gtkgridconstraintprivate.h"
#include "gtkintl.h"
#include "gtktypebuiltins.h"
enum {
POS_LEFT,
POS_RIGHT,
POS_TOP,
POS_BOTTOM,
LAST_POS,
SIZE_WIDTH = LAST_POS,
SIZE_HEIGHT,
LAST_CONSTRAINT
};
/* We maintain constraints of the form:
*
* child.top = row_x
* child.bottom = row_y
*
* (and similar for columns). We avoid introducing
* extra variables for rows and columns by keeping
* track of the first child we encounter that ends
* at a given position, and using that instead:
*
* child.top = first.bottom
*
* (assuming that @first is the first child we saw
* that ends at row x (and has its bottom edge there).
*
* For homogeneous grids, we additionally maintain
* constraints of the form:
*
* a.width / a.colspan = b.width / b.colspan
*
* (and similar for heights). We only maintain
* these relations between a child and its
* predecessor in the list of children.
*/
typedef struct {
GtkConstraintTarget *child;
int left;
int right;
int top;
int bottom;
/* We hold a ref on these */
GtkConstraint *constraints[LAST_CONSTRAINT];
} GtkGridConstraintChild;
typedef struct {
GtkConstraintTarget *target;
GtkConstraintAttribute attr;
} Attach;
struct _GtkGridConstraint {
GObject parent;
GtkConstraintLayout *layout;
gboolean row_homogeneous;
gboolean column_homogeneous;
/* List<GtkGridConstraintChild>, owned */
GPtrArray *children;
/* List<GtkConstaint>, not owned */
GPtrArray *constraints;
/* Array<Attach>, not owning Attach.target */
GArray *rows;
GArray *cols;
};
enum {
PROP_ROW_HOMOGENEOUS = 1,
PROP_COLUMN_HOMOGENEOUS,
@@ -35,6 +105,11 @@ static GParamSpec *obj_props[N_PROPERTIES];
G_DEFINE_TYPE (GtkGridConstraint, gtk_grid_constraint, G_TYPE_OBJECT)
static void set_row_homogeneous (GtkGridConstraint *self,
gboolean homogeneous);
static void set_column_homogeneous (GtkGridConstraint *self,
gboolean homogeneous);
static void
gtk_constraint_set_property (GObject *gobject,
guint prop_id,
@@ -46,11 +121,11 @@ gtk_constraint_set_property (GObject *gobject,
switch (prop_id)
{
case PROP_ROW_HOMOGENEOUS:
self->row_homogeneous = g_value_get_boolean (value);
set_row_homogeneous (self, g_value_get_boolean (value));
break;
case PROP_COLUMN_HOMOGENEOUS:
self->column_homogeneous = g_value_get_boolean (value);
set_column_homogeneous (self, g_value_get_boolean (value));
break;
default:
@@ -83,12 +158,29 @@ gtk_constraint_get_property (GObject *gobject,
}
}
static void
gtk_grid_constraint_init (GtkGridConstraint *self)
{
self->children = g_ptr_array_new_with_free_func (g_free);
self->constraints = g_ptr_array_new ();
self->rows = g_array_new (FALSE, TRUE, sizeof (Attach));
self->cols = g_array_new (FALSE, TRUE, sizeof (Attach));
}
static void
gtk_constraint_finalize (GObject *gobject)
{
GtkGridConstraint *self = GTK_GRID_CONSTRAINT (gobject);
gtk_grid_constraint_detach (self);
g_array_free (self->rows, TRUE);
g_array_free (self->cols, TRUE);
if (self->layout)
gtk_grid_constraint_detach (self);
g_assert (self->constraints->len == 0);
g_ptr_array_free (self->constraints, TRUE);
g_ptr_array_free (self->children, TRUE);
@@ -134,9 +226,257 @@ gtk_grid_constraint_class_init (GtkGridConstraintClass *klass)
}
static void
gtk_grid_constraint_init (GtkGridConstraint *self)
remove_child_constraint (GtkGridConstraint *self,
GtkGridConstraintChild *child,
int pos)
{
self->children = g_ptr_array_new_with_free_func (g_free);
if (child->constraints[pos] == NULL)
return;
if (self->layout)
gtk_constraint_layout_remove_constraint (self->layout,
child->constraints[pos]);
g_object_unref (child->constraints[pos]);
child->constraints[pos] = NULL;
}
/* Ensure that the child variable @var is placed
* at the grid edge @pos. If we already have a variable
* that needs to end up there, we use it to assert
* var = vars[top], otherwise we put @var in the
* the list of variables.
*
* @attr may be one of LEFT/RIGHT/TOP/BOTTOM here.
*/
static void
add_child_constraint (GtkGridConstraint *self,
GtkGridConstraintChild *child,
GtkConstraintAttribute attr,
int pos)
{
Attach *attach;
GArray *vars;
int cpos;
switch ((int)attr)
{
case GTK_CONSTRAINT_ATTRIBUTE_LEFT:
vars = self->cols;
cpos = POS_LEFT;
break;
case GTK_CONSTRAINT_ATTRIBUTE_RIGHT:
vars = self->cols;
cpos = POS_RIGHT;
break;
case GTK_CONSTRAINT_ATTRIBUTE_TOP:
vars = self->rows;
cpos = POS_TOP;
break;
case GTK_CONSTRAINT_ATTRIBUTE_BOTTOM:
vars = self->rows;
cpos = POS_BOTTOM;
break;
default:
g_assert_not_reached ();
}
if (vars->len <= pos)
g_array_set_size (vars, pos + 1);
attach = &g_array_index (vars, Attach, pos);
if (attach->target == NULL)
{
attach->target = child->child;
attach->attr = attr;
}
else
{
g_assert (child->constraints[cpos] == NULL);
child->constraints[cpos] = gtk_constraint_new (child->child, attr,
GTK_CONSTRAINT_RELATION_EQ,
attach->target, attach->attr,
1.0, 0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
if (self->layout)
gtk_constraint_layout_add_constraint (self->layout,
child->constraints[cpos]);
}
}
/* Create the contraint:
*
* child1.width/child1.colspan = child2.width/child2.colspan
*
* @attr can be WIDTH or HEIGHT here.
*/
static void
add_homogeneous_constraint (GtkGridConstraint *self,
GtkGridConstraintChild *child1,
GtkGridConstraintChild *child2,
GtkConstraintAttribute attr)
{
int span1, span2;
int pos;
if (attr == GTK_CONSTRAINT_ATTRIBUTE_WIDTH)
{
pos = SIZE_WIDTH;
span1 = child1->right - child1->left;
span2 = child2->right - child2->left;
}
else
{
pos = SIZE_HEIGHT;
span1 = child1->bottom - child1->top;
span2 = child2->bottom - child2->top;
}
g_assert (child1->constraints[pos] == NULL);
child1->constraints[pos] = gtk_constraint_new (child1->child, attr,
GTK_CONSTRAINT_RELATION_EQ,
child2->child, attr,
(double) span1 / (double) span2,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
if (self->layout)
gtk_constraint_layout_add_constraint (self->layout,
child1->constraints[pos]);
}
static void
set_row_homogeneous (GtkGridConstraint *self,
gboolean homogeneous)
{
GtkGridConstraintChild *child1;
GtkGridConstraintChild *child2;
int i;
if (self->row_homogeneous == homogeneous)
return;
self->row_homogeneous = homogeneous;
for (i = 1; i < self->children->len; i++)
{
child1 = g_ptr_array_index (self->children, i);
child2 = g_ptr_array_index (self->children, i - 1);
if (homogeneous)
add_homogeneous_constraint (self, child1, child2, GTK_CONSTRAINT_ATTRIBUTE_HEIGHT);
else
remove_child_constraint (self, child1, SIZE_HEIGHT);
}
g_object_notify (G_OBJECT (self), "row-homogeneous");
}
static void
set_column_homogeneous (GtkGridConstraint *self,
gboolean homogeneous)
{
GtkGridConstraintChild *child1;
GtkGridConstraintChild *child2;
int i;
if (self->column_homogeneous == homogeneous)
return;
self->column_homogeneous = homogeneous;
for (i = 1; i < self->children->len; i++)
{
child1 = g_ptr_array_index (self->children, i);
child2 = g_ptr_array_index (self->children, i - 1);
if (homogeneous)
add_homogeneous_constraint (self, child1, child2, GTK_CONSTRAINT_ATTRIBUTE_WIDTH);
else
remove_child_constraint (self, child1, SIZE_WIDTH);
}
g_object_notify (G_OBJECT (self), "column-homogeneous");
}
/* Fix up attachment constraints for the removal of @target.
* We are fixing up the attachment at row/col @rows and
* position @pos. If @target was not the representative
* for this position, there is nothing to do (all of @targets
* constraints are already removed). Otherwise, look over
* all children that are attached to @target for this position,
* pick a new representative, and fix up the constraints
* for all others to attach to the new representative.
*/
static void
fix_up_attach (GtkGridConstraint *self,
GtkConstraintTarget *target,
gboolean rows,
int pos)
{
int i;
Attach *attach;
if (rows)
attach = &g_array_index (self->rows, Attach, pos);
else
attach = &g_array_index (self->cols, Attach, pos);
if (attach->target != target)
return;
attach->target = NULL;
for (i = 0; i < self->children->len; i++)
{
int cpos;
GtkGridConstraintChild *child;
GtkConstraintAttribute attr;
child = g_ptr_array_index (self->children, i);
if (rows && child->top == pos)
{
cpos = POS_TOP;
attr = GTK_CONSTRAINT_ATTRIBUTE_TOP;
}
else if (rows && child->bottom == pos)
{
cpos = POS_BOTTOM;
attr = GTK_CONSTRAINT_ATTRIBUTE_BOTTOM;
}
else if (!rows && child->left == pos)
{
cpos = POS_LEFT;
attr = GTK_CONSTRAINT_ATTRIBUTE_LEFT;
}
else if (!rows && child->right == pos)
{
cpos = POS_LEFT;
attr = GTK_CONSTRAINT_ATTRIBUTE_LEFT;
}
else
continue;
remove_child_constraint (self, child, cpos);
if (attach->target == NULL)
{
attach->target = child->child;
attach->attr = attr;
}
else
{
child->constraints[cpos] =
gtk_constraint_new (child->child, attr,
GTK_CONSTRAINT_RELATION_EQ,
attach->target, attach->attr,
1.0, 0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
if (self->layout)
gtk_constraint_layout_add_constraint (self->layout,
g_object_ref (child->constraints[cpos]));
}
}
}
GtkGridConstraint *
@@ -153,54 +493,143 @@ gtk_grid_constraint_add (GtkGridConstraint *self,
int top,
int bottom)
{
GtkGridConstraintChild *data;
GtkGridConstraintChild *child1;
GtkGridConstraintChild *child2;
g_return_if_fail (GTK_IS_GRID_CONSTRAINT (self));
g_return_if_fail (GTK_IS_WIDGET (child));
g_return_if_fail (left < right);
g_return_if_fail (top < bottom);
g_return_if_fail (self->refs == NULL);
g_return_if_fail (self->layout == NULL);
data = g_new0 (GtkGridConstraintChild, 1);
child1 = g_new0 (GtkGridConstraintChild, 1);
data->child = child;
data->left = left;
data->right = right;
data->top = top;
data->bottom = bottom;
child1->child = GTK_CONSTRAINT_TARGET (child);
child1->left = left;
child1->right = right;
child1->top = top;
child1->bottom = bottom;
g_ptr_array_add (self->children, data);
if (self->children->len > 0)
child2 = g_ptr_array_index (self->children, self->children->len - 1);
else
child2 = NULL;
add_child_constraint (self, child1, GTK_CONSTRAINT_ATTRIBUTE_TOP, top);
add_child_constraint (self, child1, GTK_CONSTRAINT_ATTRIBUTE_BOTTOM, bottom);
add_child_constraint (self, child1, GTK_CONSTRAINT_ATTRIBUTE_LEFT, left);
add_child_constraint (self, child1, GTK_CONSTRAINT_ATTRIBUTE_RIGHT, right);
if (self->row_homogeneous && child2)
add_homogeneous_constraint (self, child1, child2, GTK_CONSTRAINT_ATTRIBUTE_HEIGHT);
if (self->column_homogeneous && child2)
add_homogeneous_constraint (self, child1, child2, GTK_CONSTRAINT_ATTRIBUTE_WIDTH);
g_ptr_array_add (self->children, child1);
}
void
gtk_grid_constraint_remove (GtkGridConstraint *self,
GtkWidget *child)
{
GtkGridConstraintChild *child1 = NULL;
GtkGridConstraintChild *next = NULL;
GtkGridConstraintChild *prev = NULL;
GtkConstraintTarget *target = (GtkConstraintTarget *)child;
int i;
int left, right, top, bottom;
for (i = 0; i < self->children->len; i++)
{
child1 = g_ptr_array_index (self->children, i);
if (child1->child == target)
break;
child1 = NULL;
}
if (child1 == NULL)
return;
if (i > 0)
prev = g_ptr_array_index (self->children, i - 1);
if (i + 1 < self->children->len)
next = g_ptr_array_index (self->children, i + 1);
for (i = 0; i < LAST_CONSTRAINT; i++)
remove_child_constraint (self, child1, i);
top = child1->top;
bottom = child1->bottom;
left = child1->left;
right = child1->right;
g_ptr_array_remove (self->children, child1);
fix_up_attach (self, target, TRUE, top);
fix_up_attach (self, target, TRUE, bottom);
fix_up_attach (self, target, FALSE, right);
fix_up_attach (self, target, FALSE, left);
if (self->column_homogeneous && next)
{
remove_child_constraint (self, next, SIZE_WIDTH);
if (prev)
add_homogeneous_constraint (self, next, prev, GTK_CONSTRAINT_ATTRIBUTE_WIDTH);
}
if (self->row_homogeneous && next)
{
remove_child_constraint (self, next, SIZE_HEIGHT);
if (prev)
add_homogeneous_constraint (self, next, prev, GTK_CONSTRAINT_ATTRIBUTE_HEIGHT);
}
}
gboolean
gtk_grid_constraint_is_attached (GtkGridConstraint *self)
{
return self->refs != NULL;
return self->layout != NULL;
}
void
gtk_grid_constraint_attach (GtkGridConstraint *self,
GtkConstraintSolver *solver,
GPtrArray *refs)
GtkConstraintLayout *layout)
{
g_return_if_fail (self->refs == NULL);
int i, j;
self->solver = solver;
self->refs = g_ptr_array_ref (refs);
g_return_if_fail (self->layout == NULL);
self->layout = layout;
for (i = 0; i < self->children->len; i++)
{
GtkGridConstraintChild *child = g_ptr_array_index (self->children, i);
for (j = 0; j < LAST_CONSTRAINT; j++)
{
if (child->constraints[j] != NULL)
gtk_constraint_layout_add_constraint (self->layout,
g_object_ref (child->constraints[j]));
}
}
}
void gtk_grid_constraint_detach (GtkGridConstraint *self)
void
gtk_grid_constraint_detach (GtkGridConstraint *self)
{
int i;
int i, j;
if (self->refs == NULL)
if (self->layout == NULL)
return;
for (i = 0; i < self->refs->len; i++)
for (i = 0; i < self->children->len; i++)
{
GtkConstraintRef *ref = g_ptr_array_index (self->refs, i);
gtk_constraint_solver_remove_constraint (self->solver, ref);
GtkGridConstraintChild *child = g_ptr_array_index (self->children, i);
for (j = 0; j < LAST_CONSTRAINT; j++)
{
if (child->constraints[j] != NULL)
gtk_constraint_layout_remove_constraint (self->layout,
child->constraints[j]);
}
}
g_clear_pointer (&self->refs, g_ptr_array_unref);
self->layout = NULL;
}
+13
View File
@@ -19,6 +19,7 @@
#define __GTK_GRID_CONSTRAINT_H__
#include <gtk/gtkwidget.h>
#include <gtk/gtkconstraintlayout.h>
G_BEGIN_DECLS
@@ -44,6 +45,18 @@ void gtk_grid_constraint_add (GtkGridConstraint *self,
int top,
int bottom);
GDK_AVAILABLE_IN_ALL
void gtk_grid_constraint_remove (GtkGridConstraint *self,
GtkWidget *child);
GDK_AVAILABLE_IN_ALL
void gtk_grid_constraint_attach (GtkGridConstraint *self,
GtkConstraintLayout *layout);
GDK_AVAILABLE_IN_ALL
void gtk_grid_constraint_detach (GtkGridConstraint *self);
GDK_AVAILABLE_IN_ALL
gboolean gtk_grid_constraint_is_attached (GtkGridConstraint *self);
G_END_DECLS
#endif /* __GTK_GRID_CONSTRAINT_H__ */
+2
View File
@@ -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;
}
/**
+2
View File
@@ -39,6 +39,7 @@ gtk_private_sources = files([
'gtkcolorswatch.c',
'gtkconstraintexpression.c',
'gtkconstraintsolver.c',
'gtkconstraintvflparser.c',
'gtkcssanimatedstyle.c',
'gtkcssanimation.c',
'gtkcssarrayvalue.c',
@@ -465,6 +466,7 @@ gtk_public_headers = files([
'gtkcolorutils.h',
'gtkcombobox.h',
'gtkcomboboxtext.h',
'gtkconstraintguide.h',
'gtkconstraintlayout.h',
'gtkconstraint.h',
'gtkcontainer.h',
+4 -3
View File
@@ -2178,11 +2178,11 @@ popover>contents {
margin: 0px;
}
popover>contents.background {
popover.background>contents {
background-color: $popover_bg_color;
box-shadow: 0 1px 2px transparentize(black, 0.7);
.csd &, & {
.csd &, & {
border: 1px solid $borders_color;
border-radius: $popover_radius;
}
@@ -4766,8 +4766,9 @@ popover.menu {
padding-bottom: 5px;
}
arrow,
&.background contents {
background: white;
background-color: $menu_color;
}
&.background separator {
+41 -41
View File
@@ -82,9 +82,9 @@ assistant .sidebar label { padding: 6px 12px; }
assistant .sidebar label.highlight { background-color: #5a5a59; }
.csd popover > contents.background.touch-selection, .csd popover > contents.background.magnifier, popover > contents.background.touch-selection, popover > contents.background.magnifier, .csd popover > contents.background.osd, popover > contents.background.osd, .app-notification, .app-notification.frame, .osd .scale-popup, .osd { color: #eeeeec; border: none; background-color: rgba(38, 38, 38, 0.7); background-clip: padding-box; text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; }
.csd popover.background > contents.touch-selection, .csd popover.background > contents.magnifier, popover.background > contents.touch-selection, popover.background > contents.magnifier, .csd popover.background > contents.osd, popover.background > contents.osd, .app-notification, .app-notification.frame, .osd .scale-popup, .osd { color: #eeeeec; border: none; background-color: rgba(37, 37, 38, 0.7); background-clip: padding-box; text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; }
.csd popover > contents.background.touch-selection:backdrop, .csd popover > contents.background.magnifier:backdrop, popover > contents.background.touch-selection:backdrop, popover > contents.background.magnifier:backdrop, .csd popover > contents.background.osd:backdrop, popover > contents.background.osd:backdrop, .app-notification:backdrop, .osd .scale-popup:backdrop, .osd:backdrop { text-shadow: none; -gtk-icon-shadow: none; }
.csd popover.background > contents.touch-selection:backdrop, .csd popover.background > contents.magnifier:backdrop, popover.background > contents.touch-selection:backdrop, popover.background > contents.magnifier:backdrop, .csd popover.background > contents.osd:backdrop, popover.background > contents.osd:backdrop, .app-notification:backdrop, .osd .scale-popup:backdrop, .osd:backdrop { text-shadow: none; -gtk-icon-shadow: none; }
/********************* Spinner Animation * */
@keyframes spin { to { -gtk-icon-transform: rotate(1turn); } }
@@ -265,7 +265,7 @@ row:selected button.sidebar-button:not(:active):not(:checked):not(:hover):not(di
row:selected button.sidebar-button:not(:active):not(:checked):not(:hover):not(disabled):backdrop, row:selected button.flat:not(:active):not(:checked):not(:hover):not(disabled):backdrop { color: #919190; }
button.osd { min-width: 26px; min-height: 32px; color: #eeeeec; border-radius: 5px; color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(38, 38, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); border: none; box-shadow: none; }
button.osd { min-width: 26px; min-height: 32px; color: #eeeeec; border-radius: 5px; color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(37, 37, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); border: none; box-shadow: none; }
button.osd.image-button { min-width: 34px; }
@@ -275,27 +275,27 @@ button.osd:active, button.osd:checked { color: white; border-color: rgba(0, 0, 0
button.osd:disabled:backdrop, button.osd:disabled { color: #8a8a89; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(58, 58, 57, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; border: none; }
button.osd:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(38, 38, 38, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; border: none; }
button.osd:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(37, 37, 38, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; border: none; }
.csd popover > contents.background.touch-selection button, .csd popover > contents.background.magnifier button, popover > contents.background.touch-selection button, popover > contents.background.magnifier button, .app-notification button, .app-notification.frame button, .osd button { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(38, 38, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
.csd popover.background > contents.touch-selection button, .csd popover.background > contents.magnifier button, popover.background > contents.touch-selection button, popover.background > contents.magnifier button, .app-notification button, .app-notification.frame button, .osd button { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(37, 37, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
.csd popover > contents.background.touch-selection button:hover, .csd popover > contents.background.magnifier button:hover, popover > contents.background.touch-selection button:hover, popover > contents.background.magnifier button:hover, .app-notification button:hover, .osd button:hover { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(68, 68, 68, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
.csd popover.background > contents.touch-selection button:hover, .csd popover.background > contents.magnifier button:hover, popover.background > contents.touch-selection button:hover, popover.background > contents.magnifier button:hover, .app-notification button:hover, .osd button:hover { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(68, 68, 68, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
.csd popover > contents.background.touch-selection button:active:backdrop, .csd popover > contents.background.magnifier button:active:backdrop, popover > contents.background.touch-selection button:active:backdrop, popover > contents.background.magnifier button:active:backdrop, .app-notification button:active:backdrop, .csd popover > contents.background.touch-selection button:active, .csd popover > contents.background.magnifier button:active, popover > contents.background.touch-selection button:active, popover > contents.background.magnifier button:active, .app-notification button:active, .csd popover > contents.background.touch-selection button:checked:backdrop, .csd popover > contents.background.magnifier button:checked:backdrop, popover > contents.background.touch-selection button:checked:backdrop, popover > contents.background.magnifier button:checked:backdrop, .app-notification button:checked:backdrop, .csd popover > contents.background.touch-selection button:checked, .csd popover > contents.background.magnifier button:checked, popover > contents.background.touch-selection button:checked, popover > contents.background.magnifier button:checked, .app-notification button:checked, .osd button:active:backdrop, .osd button:active, .osd button:checked:backdrop, .osd button:checked { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(0, 0, 0, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; outline-color: rgba(238, 238, 236, 0.3); }
.csd popover.background > contents.touch-selection button:active:backdrop, .csd popover.background > contents.magnifier button:active:backdrop, popover.background > contents.touch-selection button:active:backdrop, popover.background > contents.magnifier button:active:backdrop, .app-notification button:active:backdrop, .csd popover.background > contents.touch-selection button:active, .csd popover.background > contents.magnifier button:active, popover.background > contents.touch-selection button:active, popover.background > contents.magnifier button:active, .app-notification button:active, .csd popover.background > contents.touch-selection button:checked:backdrop, .csd popover.background > contents.magnifier button:checked:backdrop, popover.background > contents.touch-selection button:checked:backdrop, popover.background > contents.magnifier button:checked:backdrop, .app-notification button:checked:backdrop, .csd popover.background > contents.touch-selection button:checked, .csd popover.background > contents.magnifier button:checked, popover.background > contents.touch-selection button:checked, popover.background > contents.magnifier button:checked, .app-notification button:checked, .osd button:active:backdrop, .osd button:active, .osd button:checked:backdrop, .osd button:checked { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(0, 0, 0, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; outline-color: rgba(238, 238, 236, 0.3); }
.csd popover > contents.background.touch-selection button:disabled:backdrop, .csd popover > contents.background.magnifier button:disabled:backdrop, popover > contents.background.touch-selection button:disabled:backdrop, popover > contents.background.magnifier button:disabled:backdrop, .app-notification button:disabled:backdrop, .csd popover > contents.background.touch-selection button:disabled, .csd popover > contents.background.magnifier button:disabled, popover > contents.background.touch-selection button:disabled, popover > contents.background.magnifier button:disabled, .app-notification button:disabled, .osd button:disabled:backdrop, .osd button:disabled { color: #8a8a89; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(58, 58, 57, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
.csd popover.background > contents.touch-selection button:disabled:backdrop, .csd popover.background > contents.magnifier button:disabled:backdrop, popover.background > contents.touch-selection button:disabled:backdrop, popover.background > contents.magnifier button:disabled:backdrop, .app-notification button:disabled:backdrop, .csd popover.background > contents.touch-selection button:disabled, .csd popover.background > contents.magnifier button:disabled, popover.background > contents.touch-selection button:disabled, popover.background > contents.magnifier button:disabled, .app-notification button:disabled, .osd button:disabled:backdrop, .osd button:disabled { color: #8a8a89; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(58, 58, 57, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
.csd popover > contents.background.touch-selection button:backdrop, .csd popover > contents.background.magnifier button:backdrop, popover > contents.background.touch-selection button:backdrop, popover > contents.background.magnifier button:backdrop, .app-notification button:backdrop, .osd button:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(38, 38, 38, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
.csd popover.background > contents.touch-selection button:backdrop, .csd popover.background > contents.magnifier button:backdrop, popover.background > contents.touch-selection button:backdrop, popover.background > contents.magnifier button:backdrop, .app-notification button:backdrop, .osd button:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(37, 37, 38, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
.csd popover > contents.background.touch-selection button.flat, .csd popover > contents.background.magnifier button.flat, popover > contents.background.touch-selection button.flat, popover > contents.background.magnifier button.flat, .app-notification button.flat, .osd button.flat { border-color: transparent; background-color: transparent; background-image: none; box-shadow: inset 0 1px rgba(255, 255, 255, 0); text-shadow: none; -gtk-icon-shadow: none; box-shadow: none; text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; }
.csd popover.background > contents.touch-selection button.flat, .csd popover.background > contents.magnifier button.flat, popover.background > contents.touch-selection button.flat, popover.background > contents.magnifier button.flat, .app-notification button.flat, .osd button.flat { border-color: transparent; background-color: transparent; background-image: none; box-shadow: inset 0 1px rgba(255, 255, 255, 0); text-shadow: none; -gtk-icon-shadow: none; box-shadow: none; text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; }
.csd popover > contents.background.touch-selection button.flat:hover, .csd popover > contents.background.magnifier button.flat:hover, popover > contents.background.touch-selection button.flat:hover, popover > contents.background.magnifier button.flat:hover, .app-notification button.flat:hover, .osd button.flat:hover { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(68, 68, 68, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
.csd popover.background > contents.touch-selection button.flat:hover, .csd popover.background > contents.magnifier button.flat:hover, popover.background > contents.touch-selection button.flat:hover, popover.background > contents.magnifier button.flat:hover, .app-notification button.flat:hover, .osd button.flat:hover { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(68, 68, 68, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
.csd popover > contents.background.touch-selection button.flat:disabled, .csd popover > contents.background.magnifier button.flat:disabled, popover > contents.background.touch-selection button.flat:disabled, popover > contents.background.magnifier button.flat:disabled, .app-notification button.flat:disabled, .osd button.flat:disabled { color: #8a8a89; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(58, 58, 57, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; background-image: none; border-color: transparent; box-shadow: none; }
.csd popover.background > contents.touch-selection button.flat:disabled, .csd popover.background > contents.magnifier button.flat:disabled, popover.background > contents.touch-selection button.flat:disabled, popover.background > contents.magnifier button.flat:disabled, .app-notification button.flat:disabled, .osd button.flat:disabled { color: #8a8a89; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(58, 58, 57, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; background-image: none; border-color: transparent; box-shadow: none; }
.csd popover > contents.background.touch-selection button.flat:backdrop, .csd popover > contents.background.magnifier button.flat:backdrop, popover > contents.background.touch-selection button.flat:backdrop, popover > contents.background.magnifier button.flat:backdrop, .app-notification button.flat:backdrop, .osd button.flat:backdrop { border-color: transparent; background-color: transparent; background-image: none; box-shadow: inset 0 1px rgba(255, 255, 255, 0); text-shadow: none; -gtk-icon-shadow: none; }
.csd popover.background > contents.touch-selection button.flat:backdrop, .csd popover.background > contents.magnifier button.flat:backdrop, popover.background > contents.touch-selection button.flat:backdrop, popover.background > contents.magnifier button.flat:backdrop, .app-notification button.flat:backdrop, .osd button.flat:backdrop { border-color: transparent; background-color: transparent; background-image: none; box-shadow: inset 0 1px rgba(255, 255, 255, 0); text-shadow: none; -gtk-icon-shadow: none; }
.csd popover > contents.background.touch-selection button.flat:active, .csd popover > contents.background.magnifier button.flat:active, popover > contents.background.touch-selection button.flat:active, popover > contents.background.magnifier button.flat:active, .app-notification button.flat:active, .csd popover > contents.background.touch-selection button.flat:checked, .csd popover > contents.background.magnifier button.flat:checked, popover > contents.background.touch-selection button.flat:checked, popover > contents.background.magnifier button.flat:checked, .app-notification button.flat:checked, .osd button.flat:active, .osd button.flat:checked { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(0, 0, 0, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; outline-color: rgba(238, 238, 236, 0.3); }
.csd popover.background > contents.touch-selection button.flat:active, .csd popover.background > contents.magnifier button.flat:active, popover.background > contents.touch-selection button.flat:active, popover.background > contents.magnifier button.flat:active, .app-notification button.flat:active, .csd popover.background > contents.touch-selection button.flat:checked, .csd popover.background > contents.magnifier button.flat:checked, popover.background > contents.touch-selection button.flat:checked, popover.background > contents.magnifier button.flat:checked, .app-notification button.flat:checked, .osd button.flat:active, .osd button.flat:checked { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(0, 0, 0, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; outline-color: rgba(238, 238, 236, 0.3); }
button.suggested-action { color: white; outline-color: rgba(255, 255, 255, 0.3); border-color: #0f3b71; border-bottom-color: #092444; background-image: linear-gradient(to top, #155099 2px, #15539e); text-shadow: 0 -1px rgba(0, 0, 0, 0.719216); -gtk-icon-shadow: 0 -1px rgba(0, 0, 0, 0.719216); box-shadow: inset 0 1px rgba(255, 255, 255, 0.02), 0 1px 2px rgba(0, 0, 0, 0.07); }
@@ -497,7 +497,7 @@ button:link > label:active, button:visited > label:active, *:link:active, button
*:selected button:link > label:active, *:selected button:visited > label:active, *:selected *:link:active, *:selected button:active:link, *:selected button:active:visited { color: #d0ddec; }
button:link > label:disabled, button:visited > label:disabled, button:link > label:disabled:backdrop, button:visited > label:disabled:backdrop, *:link:disabled, button:disabled:link, button:disabled:visited, *:link:disabled:backdrop, button:disabled:backdrop:link, button:disabled:backdrop:visited { color: rgba(141, 141, 141, 0.8); }
button:link > label:disabled, button:visited > label:disabled, button:link > label:disabled:backdrop, button:visited > label:disabled:backdrop, *:link:disabled, button:disabled:link, button:disabled:visited, *:link:disabled:backdrop, button:disabled:backdrop:link, button:disabled:backdrop:visited { color: rgba(140, 140, 141, 0.8); }
button:link > label:backdrop:backdrop:hover, button:visited > label:backdrop:backdrop:hover, button:link > label:backdrop:backdrop:hover:selected, button:visited > label:backdrop:backdrop:hover:selected, button:link > label:backdrop, button:visited > label:backdrop, *:link:backdrop:backdrop:hover, button:backdrop:backdrop:hover:link, button:backdrop:backdrop:hover:visited, *:link:backdrop:backdrop:hover:selected, button:backdrop:backdrop:hover:selected:link, button:backdrop:backdrop:hover:selected:visited, .selection-mode .titlebar:not(headerbar) .subtitle:backdrop:backdrop:hover:link, .selection-mode.titlebar:not(headerbar) .subtitle:backdrop:backdrop:hover:link, .selection-mode headerbar .subtitle:backdrop:backdrop:hover:link, headerbar.selection-mode .subtitle:backdrop:backdrop:hover:link, *:link:backdrop, button:backdrop:link, button:backdrop:visited { color: #15539e; }
@@ -564,7 +564,7 @@ spinbutton.vertical button.up { border-bottom-style: none; border-bottom-left-ra
spinbutton.vertical button.down { border-top-style: none; border-top-left-radius: 0; border-top-right-radius: 0; }
.osd spinbutton.vertical button:first-child { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(38, 38, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
.osd spinbutton.vertical button:first-child { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(37, 37, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
.osd spinbutton.vertical button:first-child:hover { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(68, 68, 68, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
@@ -572,7 +572,7 @@ spinbutton.vertical button.down { border-top-style: none; border-top-left-radius
.osd spinbutton.vertical button:first-child:disabled { color: #8a8a89; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(58, 58, 57, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
.osd spinbutton.vertical button:first-child:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(38, 38, 38, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
.osd spinbutton.vertical button:first-child:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(37, 37, 38, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
treeview spinbutton:not(.vertical) { min-height: 0; border-style: none; border-radius: 0; }
@@ -590,7 +590,7 @@ toolbar { padding: 4px 3px 3px 4px; }
.osd toolbar { background-color: transparent; }
toolbar.osd { padding: 13px; border: none; border-radius: 5px; background-color: rgba(38, 38, 38, 0.7); }
toolbar.osd { padding: 13px; border: none; border-radius: 5px; background-color: rgba(37, 37, 38, 0.7); }
toolbar.osd.left, toolbar.osd.right, toolbar.osd.top, toolbar.osd.bottom { border-radius: 0; }
@@ -613,7 +613,7 @@ searchbar > revealer > box { padding: 6px; border-width: 0 0 1px; }
.inline-toolbar:backdrop, .location-bar:backdrop, searchbar > revealer > box:backdrop { border-color: #202020; background-color: #2e2e2e; box-shadow: none; transition: 200ms ease-out; }
/*************** Header bars * */
.titlebar:not(headerbar), headerbar { padding: 0 6px; min-height: 46px; border-width: 0 0 1px; border-style: solid; border-color: #070707; border-radius: 0; background: #1b1b1b linear-gradient(to top, #262626, #2b2b2b); box-shadow: inset 0 1px rgba(238, 238, 236, 0.07); /* Darken switchbuttons for headerbars. issue #1588 */ /* hide the close button separator */ }
.titlebar:not(headerbar), headerbar { padding: 0 6px; min-height: 46px; border-width: 0 0 1px; border-style: solid; border-color: #070707; border-radius: 0; background: #1b1b1b linear-gradient(to top, #252526, #2b2b2b); box-shadow: inset 0 1px rgba(238, 238, 236, 0.07); /* Darken switchbuttons for headerbars. issue #1588 */ /* hide the close button separator */ }
.titlebar:backdrop:not(headerbar), headerbar:backdrop { border-color: #202020; background-color: #353535; background-image: none; box-shadow: inset 0 1px rgba(238, 238, 236, 0.07); transition: 200ms ease-out; }
@@ -879,19 +879,19 @@ popover.menu > arrow, popover > arrow { background-color: #353535; border: 1px s
popover > contents { padding: 8px; background-color: #353535; border: 1px solid #1b1b1b; margin: 0px; }
popover > contents.background { background-color: #353535; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); }
popover.background > contents { background-color: #353535; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); }
.csd popover > contents.background, popover > contents.background { border: 1px solid #1b1b1b; border-radius: 9px; }
.csd popover.background > contents, popover.background > contents { border: 1px solid #1b1b1b; border-radius: 9px; }
popover > contents.background:backdrop { background-color: #353535; box-shadow: none; }
popover.background > contents:backdrop { background-color: #353535; box-shadow: none; }
popover > contents.background > list, popover > contents.background > .view, popover > contents.background > iconview, popover > contents.background > toolbar { border-style: none; background-color: transparent; }
popover.background > contents > list, popover.background > contents > .view, popover.background > contents > iconview, popover.background > contents > toolbar { border-style: none; background-color: transparent; }
.csd popover > contents.background.touch-selection, .csd popover > contents.background.magnifier, popover > contents.background.touch-selection, popover > contents.background.magnifier { border: 1px solid rgba(255, 255, 255, 0.1); }
.csd popover.background > contents.touch-selection, .csd popover.background > contents.magnifier, popover.background > contents.touch-selection, popover.background > contents.magnifier { border: 1px solid rgba(255, 255, 255, 0.1); }
popover > contents.background separator { margin: 3px; }
popover.background > contents separator { margin: 3px; }
popover > contents.background list separator { margin: 0px; }
popover.background > contents list separator { margin: 0px; }
/************* Notebooks * */
notebook box > header { padding: 1px; border-color: #1b1b1b; border-width: 1px; background-color: #282828; }
@@ -1141,7 +1141,7 @@ switch:backdrop:disabled slider label, switch:backdrop:disabled slider { color:
.view.content-view.check:active:not(list), iconview.content-view.check:active:not(list), .content-view .tile check:active:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: transparent; background-color: rgba(21, 83, 158, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: none; -gtk-icon-shadow: none; }
.view.content-view.check:backdrop:not(list), iconview.content-view.check:backdrop:not(list), .content-view .tile check:backdrop:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: transparent; background-color: rgba(90, 90, 90, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: none; -gtk-icon-shadow: none; }
.view.content-view.check:backdrop:not(list), iconview.content-view.check:backdrop:not(list), .content-view .tile check:backdrop:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: transparent; background-color: rgba(89, 89, 90, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: none; -gtk-icon-shadow: none; }
.view.content-view.check:checked:not(list), iconview.content-view.check:checked:not(list), .content-view .tile check:checked:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: #eeeeec; background-color: rgba(21, 83, 158, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: -gtk-icontheme('object-select-symbolic'); -gtk-icon-shadow: none; }
@@ -1149,7 +1149,7 @@ switch:backdrop:disabled slider label, switch:backdrop:disabled slider { color:
.view.content-view.check:checked:active:not(list), iconview.content-view.check:checked:active:not(list), .content-view .tile check:checked:active:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: #eeeeec; background-color: rgba(21, 83, 158, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: -gtk-icontheme('object-select-symbolic'); -gtk-icon-shadow: none; }
.view.content-view.check:backdrop:checked:not(list), iconview.content-view.check:backdrop:checked:not(list), .content-view .tile check:backdrop:checked:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: rgba(238, 238, 236, 0.8); background-color: rgba(90, 90, 90, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: -gtk-icontheme('object-select-symbolic'); -gtk-icon-shadow: none; }
.view.content-view.check:backdrop:checked:not(list), iconview.content-view.check:backdrop:checked:not(list), .content-view .tile check:backdrop:checked:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: rgba(238, 238, 236, 0.8); background-color: rgba(89, 89, 90, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: -gtk-icontheme('object-select-symbolic'); -gtk-icon-shadow: none; }
checkbutton.text-button, radiobutton.text-button { padding: 2px 0; outline-offset: 0; }
@@ -1157,7 +1157,7 @@ checkbutton.text-button label:not(:only-child):first-child, radiobutton.text-but
checkbutton.text-button label:not(:only-child):last-child, radiobutton.text-button label:not(:only-child):last-child { margin-right: 4px; }
check, radio { margin: 0 4px; min-height: 14px; min-width: 14px; border: 1px solid; -gtk-icon-source: none; color: #eeeeec; outline-color: rgba(238, 238, 236, 0.3); border-color: #070707; text-shadow: 0 -1px rgba(0, 0, 0, 0.834353); -gtk-icon-shadow: 0 -1px rgba(0, 0, 0, 0.834353); background-image: linear-gradient(to bottom, #2d2d2d 20%, #262626 90%); box-shadow: inset 0 1px rgba(255, 255, 255, 0.02), 0 1px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.07); }
check, radio { margin: 0 4px; min-height: 14px; min-width: 14px; border: 1px solid; -gtk-icon-source: none; color: #eeeeec; outline-color: rgba(238, 238, 236, 0.3); border-color: #070707; text-shadow: 0 -1px rgba(0, 0, 0, 0.834353); -gtk-icon-shadow: 0 -1px rgba(0, 0, 0, 0.834353); background-image: linear-gradient(to bottom, #2d2d2d 20%, #252526 90%); box-shadow: inset 0 1px rgba(255, 255, 255, 0.02), 0 1px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.07); }
check:only-child, radio:only-child { margin: 0; }
@@ -1181,13 +1181,13 @@ check:backdrop:disabled, radio:backdrop:disabled { border-color: #202020; backgr
check:backdrop:disabled label, check:backdrop:disabled, radio:backdrop:disabled label, radio:backdrop:disabled { color: #5b5b5b; }
.osd check, .osd radio { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(38, 38, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
.osd check, .osd radio { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(37, 37, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
.osd check:hover, .osd radio:hover { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(38, 38, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
.osd check:hover, .osd radio:hover { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(37, 37, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
.osd check:active, .osd radio:active { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(0, 0, 0, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; outline-color: rgba(238, 238, 236, 0.3); }
.osd check:backdrop, .osd radio:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(38, 38, 38, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
.osd check:backdrop, .osd radio:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(37, 37, 38, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
.osd check:disabled, .osd radio:disabled { color: #8a8a89; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(58, 58, 57, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
@@ -1280,7 +1280,7 @@ scale fill:disabled:backdrop, scale fill:disabled { border-color: transparent; b
.osd scale fill:disabled:backdrop, .osd scale fill:disabled { border-color: transparent; background-color: transparent; }
scale slider { color: #eeeeec; outline-color: rgba(238, 238, 236, 0.3); border-color: #070707; text-shadow: 0 -1px rgba(0, 0, 0, 0.834353); -gtk-icon-shadow: 0 -1px rgba(0, 0, 0, 0.834353); background-image: linear-gradient(to bottom, #2d2d2d 20%, #262626 90%); box-shadow: inset 0 1px rgba(255, 255, 255, 0.02), 0 1px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.07); border: 1px solid black; border-radius: 100%; transition: all 200ms cubic-bezier(0.25, 0.46, 0.45, 0.94); transition-property: background, border, box-shadow; }
scale slider { color: #eeeeec; outline-color: rgba(238, 238, 236, 0.3); border-color: #070707; text-shadow: 0 -1px rgba(0, 0, 0, 0.834353); -gtk-icon-shadow: 0 -1px rgba(0, 0, 0, 0.834353); background-image: linear-gradient(to bottom, #2d2d2d 20%, #252526 90%); box-shadow: inset 0 1px rgba(255, 255, 255, 0.02), 0 1px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.07); border: 1px solid black; border-radius: 100%; transition: all 200ms cubic-bezier(0.25, 0.46, 0.45, 0.94); transition-property: background, border, box-shadow; }
scale slider:hover { color: #eeeeec; outline-color: rgba(238, 238, 236, 0.3); border-color: #070707; box-shadow: inset 0 1px rgba(255, 255, 255, 0.02), 0 1px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.07); background-image: linear-gradient(to bottom, #353535 20%, #2b2b2b 90%); }
@@ -1300,17 +1300,17 @@ scale slider:backdrop:disabled label, scale slider:backdrop:disabled { color: #5
row:selected scale slider:disabled, row:selected scale slider { border-color: #030c17; }
.osd scale slider { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(38, 38, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); border-color: rgba(0, 0, 0, 0.7); background-color: #262626; }
.osd scale slider { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(37, 37, 38, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); border-color: rgba(0, 0, 0, 0.7); background-color: #252526; }
.osd scale slider:hover { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(68, 68, 68, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); background-color: #262626; }
.osd scale slider:hover { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(68, 68, 68, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); background-color: #252526; }
.osd scale slider:active { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(0, 0, 0, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; outline-color: rgba(238, 238, 236, 0.3); background-color: #262626; }
.osd scale slider:active { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(0, 0, 0, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; outline-color: rgba(238, 238, 236, 0.3); background-color: #252526; }
.osd scale slider:disabled { color: #8a8a89; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(58, 58, 57, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; background-color: #262626; }
.osd scale slider:disabled { color: #8a8a89; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(58, 58, 57, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; background-color: #252526; }
.osd scale slider:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(38, 38, 38, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; background-color: #262626; }
.osd scale slider:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(37, 37, 38, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; background-color: #252526; }
.osd scale slider:backdrop:disabled { background-color: #262626; }
.osd scale slider:backdrop:disabled { background-color: #252526; }
scale value { color: alpha(currentColor,0.55); }
@@ -1636,7 +1636,7 @@ row.activatable:selected.has-open-popup, row.activatable:selected:hover { backgr
row.activatable:selected:backdrop { background-color: #15539e; }
/********************* App Notifications * */
.app-notification, .app-notification.frame { padding: 10px; border-radius: 0 0 5px 5px; background-color: rgba(38, 38, 38, 0.7); background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.2), transparent 2px); background-clip: padding-box; }
.app-notification, .app-notification.frame { padding: 10px; border-radius: 0 0 5px 5px; background-color: rgba(37, 37, 38, 0.7); background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.2), transparent 2px); background-clip: padding-box; }
.app-notification:backdrop, .app-notification.frame:backdrop { background-image: none; transition: 200ms ease-out; }
@@ -2063,7 +2063,7 @@ popover.menu box.inline-buttons { border-radius: 5px; border-style: none; border
popover.menu box.circular-buttons { padding-bottom: 5px; }
popover.menu.background contents { background: white; }
popover.menu arrow, popover.menu.background contents { background-color: #2f2f2f; }
popover.menu.background separator { margin: 5px 0px; }
+22 -22
View File
@@ -82,9 +82,9 @@ assistant .sidebar label { padding: 6px 12px; }
assistant .sidebar label.highlight { background-color: #cecece; }
.csd popover > contents.background.touch-selection, .csd popover > contents.background.magnifier, popover > contents.background.touch-selection, popover > contents.background.magnifier, .csd popover > contents.background.osd, popover > contents.background.osd, .app-notification, .app-notification.frame, .osd .scale-popup, .osd { color: #eeeeec; border: none; background-color: rgba(53, 53, 53, 0.7); background-clip: padding-box; text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; }
.csd popover.background > contents.touch-selection, .csd popover.background > contents.magnifier, popover.background > contents.touch-selection, popover.background > contents.magnifier, .csd popover.background > contents.osd, popover.background > contents.osd, .app-notification, .app-notification.frame, .osd .scale-popup, .osd { color: #eeeeec; border: none; background-color: rgba(53, 53, 53, 0.7); background-clip: padding-box; text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; }
.csd popover > contents.background.touch-selection:backdrop, .csd popover > contents.background.magnifier:backdrop, popover > contents.background.touch-selection:backdrop, popover > contents.background.magnifier:backdrop, .csd popover > contents.background.osd:backdrop, popover > contents.background.osd:backdrop, .app-notification:backdrop, .osd .scale-popup:backdrop, .osd:backdrop { text-shadow: none; -gtk-icon-shadow: none; }
.csd popover.background > contents.touch-selection:backdrop, .csd popover.background > contents.magnifier:backdrop, popover.background > contents.touch-selection:backdrop, popover.background > contents.magnifier:backdrop, .csd popover.background > contents.osd:backdrop, popover.background > contents.osd:backdrop, .app-notification:backdrop, .osd .scale-popup:backdrop, .osd:backdrop { text-shadow: none; -gtk-icon-shadow: none; }
/********************* Spinner Animation * */
@keyframes spin { to { -gtk-icon-transform: rotate(1turn); } }
@@ -279,25 +279,25 @@ button.osd:disabled:backdrop, button.osd:disabled { color: #919190; border-color
button.osd:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(53, 53, 53, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; border: none; }
.csd popover > contents.background.touch-selection button, .csd popover > contents.background.magnifier button, popover > contents.background.touch-selection button, popover > contents.background.magnifier button, .app-notification button, .app-notification.frame button, .osd button { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(53, 53, 53, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
.csd popover.background > contents.touch-selection button, .csd popover.background > contents.magnifier button, popover.background > contents.touch-selection button, popover.background > contents.magnifier button, .app-notification button, .app-notification.frame button, .osd button { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(53, 53, 53, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
.csd popover > contents.background.touch-selection button:hover, .csd popover > contents.background.magnifier button:hover, popover > contents.background.touch-selection button:hover, popover > contents.background.magnifier button:hover, .app-notification button:hover, .osd button:hover { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(83, 83, 83, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
.csd popover.background > contents.touch-selection button:hover, .csd popover.background > contents.magnifier button:hover, popover.background > contents.touch-selection button:hover, popover.background > contents.magnifier button:hover, .app-notification button:hover, .osd button:hover { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(83, 83, 83, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
.csd popover > contents.background.touch-selection button:active:backdrop, .csd popover > contents.background.magnifier button:active:backdrop, popover > contents.background.touch-selection button:active:backdrop, popover > contents.background.magnifier button:active:backdrop, .app-notification button:active:backdrop, .csd popover > contents.background.touch-selection button:active, .csd popover > contents.background.magnifier button:active, popover > contents.background.touch-selection button:active, popover > contents.background.magnifier button:active, .app-notification button:active, .csd popover > contents.background.touch-selection button:checked:backdrop, .csd popover > contents.background.magnifier button:checked:backdrop, popover > contents.background.touch-selection button:checked:backdrop, popover > contents.background.magnifier button:checked:backdrop, .app-notification button:checked:backdrop, .csd popover > contents.background.touch-selection button:checked, .csd popover > contents.background.magnifier button:checked, popover > contents.background.touch-selection button:checked, popover > contents.background.magnifier button:checked, .app-notification button:checked, .osd button:active:backdrop, .osd button:active, .osd button:checked:backdrop, .osd button:checked { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(0, 0, 0, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; outline-color: rgba(238, 238, 236, 0.3); }
.csd popover.background > contents.touch-selection button:active:backdrop, .csd popover.background > contents.magnifier button:active:backdrop, popover.background > contents.touch-selection button:active:backdrop, popover.background > contents.magnifier button:active:backdrop, .app-notification button:active:backdrop, .csd popover.background > contents.touch-selection button:active, .csd popover.background > contents.magnifier button:active, popover.background > contents.touch-selection button:active, popover.background > contents.magnifier button:active, .app-notification button:active, .csd popover.background > contents.touch-selection button:checked:backdrop, .csd popover.background > contents.magnifier button:checked:backdrop, popover.background > contents.touch-selection button:checked:backdrop, popover.background > contents.magnifier button:checked:backdrop, .app-notification button:checked:backdrop, .csd popover.background > contents.touch-selection button:checked, .csd popover.background > contents.magnifier button:checked, popover.background > contents.touch-selection button:checked, popover.background > contents.magnifier button:checked, .app-notification button:checked, .osd button:active:backdrop, .osd button:active, .osd button:checked:backdrop, .osd button:checked { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(0, 0, 0, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; outline-color: rgba(238, 238, 236, 0.3); }
.csd popover > contents.background.touch-selection button:disabled:backdrop, .csd popover > contents.background.magnifier button:disabled:backdrop, popover > contents.background.touch-selection button:disabled:backdrop, popover > contents.background.magnifier button:disabled:backdrop, .app-notification button:disabled:backdrop, .csd popover > contents.background.touch-selection button:disabled, .csd popover > contents.background.magnifier button:disabled, popover > contents.background.touch-selection button:disabled, popover > contents.background.magnifier button:disabled, .app-notification button:disabled, .osd button:disabled:backdrop, .osd button:disabled { color: #919190; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(71, 71, 71, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
.csd popover.background > contents.touch-selection button:disabled:backdrop, .csd popover.background > contents.magnifier button:disabled:backdrop, popover.background > contents.touch-selection button:disabled:backdrop, popover.background > contents.magnifier button:disabled:backdrop, .app-notification button:disabled:backdrop, .csd popover.background > contents.touch-selection button:disabled, .csd popover.background > contents.magnifier button:disabled, popover.background > contents.touch-selection button:disabled, popover.background > contents.magnifier button:disabled, .app-notification button:disabled, .osd button:disabled:backdrop, .osd button:disabled { color: #919190; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(71, 71, 71, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
.csd popover > contents.background.touch-selection button:backdrop, .csd popover > contents.background.magnifier button:backdrop, popover > contents.background.touch-selection button:backdrop, popover > contents.background.magnifier button:backdrop, .app-notification button:backdrop, .osd button:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(53, 53, 53, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
.csd popover.background > contents.touch-selection button:backdrop, .csd popover.background > contents.magnifier button:backdrop, popover.background > contents.touch-selection button:backdrop, popover.background > contents.magnifier button:backdrop, .app-notification button:backdrop, .osd button:backdrop { color: #eeeeec; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(53, 53, 53, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; }
.csd popover > contents.background.touch-selection button.flat, .csd popover > contents.background.magnifier button.flat, popover > contents.background.touch-selection button.flat, popover > contents.background.magnifier button.flat, .app-notification button.flat, .osd button.flat { border-color: transparent; background-color: transparent; background-image: none; box-shadow: inset 0 1px rgba(255, 255, 255, 0); text-shadow: none; -gtk-icon-shadow: none; box-shadow: none; text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; }
.csd popover.background > contents.touch-selection button.flat, .csd popover.background > contents.magnifier button.flat, popover.background > contents.touch-selection button.flat, popover.background > contents.magnifier button.flat, .app-notification button.flat, .osd button.flat { border-color: transparent; background-color: transparent; background-image: none; box-shadow: inset 0 1px rgba(255, 255, 255, 0); text-shadow: none; -gtk-icon-shadow: none; box-shadow: none; text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; }
.csd popover > contents.background.touch-selection button.flat:hover, .csd popover > contents.background.magnifier button.flat:hover, popover > contents.background.touch-selection button.flat:hover, popover > contents.background.magnifier button.flat:hover, .app-notification button.flat:hover, .osd button.flat:hover { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(83, 83, 83, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
.csd popover.background > contents.touch-selection button.flat:hover, .csd popover.background > contents.magnifier button.flat:hover, popover.background > contents.touch-selection button.flat:hover, popover.background > contents.magnifier button.flat:hover, .app-notification button.flat:hover, .osd button.flat:hover { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(83, 83, 83, 0.7)); background-clip: padding-box; box-shadow: inset 0 1px rgba(255, 255, 255, 0.1); text-shadow: 0 1px black; -gtk-icon-shadow: 0 1px black; outline-color: rgba(238, 238, 236, 0.3); }
.csd popover > contents.background.touch-selection button.flat:disabled, .csd popover > contents.background.magnifier button.flat:disabled, popover > contents.background.touch-selection button.flat:disabled, popover > contents.background.magnifier button.flat:disabled, .app-notification button.flat:disabled, .osd button.flat:disabled { color: #919190; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(71, 71, 71, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; background-image: none; border-color: transparent; box-shadow: none; }
.csd popover.background > contents.touch-selection button.flat:disabled, .csd popover.background > contents.magnifier button.flat:disabled, popover.background > contents.touch-selection button.flat:disabled, popover.background > contents.magnifier button.flat:disabled, .app-notification button.flat:disabled, .osd button.flat:disabled { color: #919190; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(71, 71, 71, 0.5)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; background-image: none; border-color: transparent; box-shadow: none; }
.csd popover > contents.background.touch-selection button.flat:backdrop, .csd popover > contents.background.magnifier button.flat:backdrop, popover > contents.background.touch-selection button.flat:backdrop, popover > contents.background.magnifier button.flat:backdrop, .app-notification button.flat:backdrop, .osd button.flat:backdrop { border-color: transparent; background-color: transparent; background-image: none; box-shadow: inset 0 1px rgba(255, 255, 255, 0); text-shadow: none; -gtk-icon-shadow: none; }
.csd popover.background > contents.touch-selection button.flat:backdrop, .csd popover.background > contents.magnifier button.flat:backdrop, popover.background > contents.touch-selection button.flat:backdrop, popover.background > contents.magnifier button.flat:backdrop, .app-notification button.flat:backdrop, .osd button.flat:backdrop { border-color: transparent; background-color: transparent; background-image: none; box-shadow: inset 0 1px rgba(255, 255, 255, 0); text-shadow: none; -gtk-icon-shadow: none; }
.csd popover > contents.background.touch-selection button.flat:active, .csd popover > contents.background.magnifier button.flat:active, popover > contents.background.touch-selection button.flat:active, popover > contents.background.magnifier button.flat:active, .app-notification button.flat:active, .csd popover > contents.background.touch-selection button.flat:checked, .csd popover > contents.background.magnifier button.flat:checked, popover > contents.background.touch-selection button.flat:checked, popover > contents.background.magnifier button.flat:checked, .app-notification button.flat:checked, .osd button.flat:active, .osd button.flat:checked { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(0, 0, 0, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; outline-color: rgba(238, 238, 236, 0.3); }
.csd popover.background > contents.touch-selection button.flat:active, .csd popover.background > contents.magnifier button.flat:active, popover.background > contents.touch-selection button.flat:active, popover.background > contents.magnifier button.flat:active, .app-notification button.flat:active, .csd popover.background > contents.touch-selection button.flat:checked, .csd popover.background > contents.magnifier button.flat:checked, popover.background > contents.touch-selection button.flat:checked, popover.background > contents.magnifier button.flat:checked, .app-notification button.flat:checked, .osd button.flat:active, .osd button.flat:checked { color: white; border-color: rgba(0, 0, 0, 0.7); background-color: transparent; background-image: image(rgba(0, 0, 0, 0.7)); background-clip: padding-box; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; outline-color: rgba(238, 238, 236, 0.3); }
button.suggested-action { color: white; outline-color: rgba(255, 255, 255, 0.3); border-color: #1b6acb; border-bottom-color: #15539e; background-image: linear-gradient(to top, #2379e2 2px, #3584e4); text-shadow: 0 -1px rgba(0, 0, 0, 0.559216); -gtk-icon-shadow: 0 -1px rgba(0, 0, 0, 0.559216); box-shadow: inset 0 1px rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.07); }
@@ -887,19 +887,19 @@ popover.menu > arrow, popover > arrow { background-color: #f6f5f4; border: 1px s
popover > contents { padding: 8px; background-color: #f6f5f4; border: 1px solid #cdc7c2; margin: 0px; }
popover > contents.background { background-color: #f6f5f4; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); }
popover.background > contents { background-color: #f6f5f4; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); }
.csd popover > contents.background, popover > contents.background { border: 1px solid #cdc7c2; border-radius: 9px; }
.csd popover.background > contents, popover.background > contents { border: 1px solid #cdc7c2; border-radius: 9px; }
popover > contents.background:backdrop { background-color: #f6f5f4; box-shadow: none; }
popover.background > contents:backdrop { background-color: #f6f5f4; box-shadow: none; }
popover > contents.background > list, popover > contents.background > .view, popover > contents.background > iconview, popover > contents.background > toolbar { border-style: none; background-color: transparent; }
popover.background > contents > list, popover.background > contents > .view, popover.background > contents > iconview, popover.background > contents > toolbar { border-style: none; background-color: transparent; }
.csd popover > contents.background.touch-selection, .csd popover > contents.background.magnifier, popover > contents.background.touch-selection, popover > contents.background.magnifier { border: 1px solid rgba(255, 255, 255, 0.1); }
.csd popover.background > contents.touch-selection, .csd popover.background > contents.magnifier, popover.background > contents.touch-selection, popover.background > contents.magnifier { border: 1px solid rgba(255, 255, 255, 0.1); }
popover > contents.background separator { margin: 3px; }
popover.background > contents separator { margin: 3px; }
popover > contents.background list separator { margin: 0px; }
popover.background > contents list separator { margin: 0px; }
/************* Notebooks * */
notebook box > header { padding: 1px; border-color: #cdc7c2; border-width: 1px; background-color: #e1dedb; }
@@ -1155,7 +1155,7 @@ row:selected switch slider:checked, row:selected switch slider { border-color: #
.view.content-view.check:active:not(list), iconview.content-view.check:active:not(list), .content-view .tile check:active:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: transparent; background-color: rgba(53, 132, 228, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: none; -gtk-icon-shadow: none; }
.view.content-view.check:backdrop:not(list), iconview.content-view.check:backdrop:not(list), .content-view .tile check:backdrop:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: transparent; background-color: rgba(141, 141, 141, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: none; -gtk-icon-shadow: none; }
.view.content-view.check:backdrop:not(list), iconview.content-view.check:backdrop:not(list), .content-view .tile check:backdrop:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: transparent; background-color: rgba(140, 140, 141, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: none; -gtk-icon-shadow: none; }
.view.content-view.check:checked:not(list), iconview.content-view.check:checked:not(list), .content-view .tile check:checked:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: #eeeeec; background-color: rgba(53, 132, 228, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: -gtk-icontheme('object-select-symbolic'); -gtk-icon-shadow: none; }
@@ -1163,7 +1163,7 @@ row:selected switch slider:checked, row:selected switch slider { border-color: #
.view.content-view.check:checked:active:not(list), iconview.content-view.check:checked:active:not(list), .content-view .tile check:checked:active:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: #eeeeec; background-color: rgba(53, 132, 228, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: -gtk-icontheme('object-select-symbolic'); -gtk-icon-shadow: none; }
.view.content-view.check:backdrop:checked:not(list), iconview.content-view.check:backdrop:checked:not(list), .content-view .tile check:backdrop:checked:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: rgba(238, 238, 236, 0.8); background-color: rgba(141, 141, 141, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: -gtk-icontheme('object-select-symbolic'); -gtk-icon-shadow: none; }
.view.content-view.check:backdrop:checked:not(list), iconview.content-view.check:backdrop:checked:not(list), .content-view .tile check:backdrop:checked:not(list) { margin: 4px; min-width: 32px; min-height: 32px; color: rgba(238, 238, 236, 0.8); background-color: rgba(140, 140, 141, 0.95); border-radius: 5px; background-image: none; transition: 200ms; box-shadow: none; border-width: 0; -gtk-icon-source: -gtk-icontheme('object-select-symbolic'); -gtk-icon-shadow: none; }
checkbutton.text-button, radiobutton.text-button { padding: 2px 0; outline-offset: 0; }
@@ -2079,7 +2079,7 @@ popover.menu box.inline-buttons { border-radius: 5px; border-style: none; border
popover.menu box.circular-buttons { padding-bottom: 5px; }
popover.menu.background contents { background: white; }
popover.menu arrow, popover.menu.background contents { background-color: #ffffff; }
popover.menu.background separator { margin: 5px 0px; }
+1 -1
View File
@@ -827,7 +827,7 @@ summary = [
' Colord support: @0@'.format(get_option('colord')),
' Profiler: @0@'.format(get_option('profiler')),
' Introspection: @0@'.format(get_option('introspection')),
' Documentation: @0@'.format(get_option('documentation')),
' Documentation: @0@'.format(get_option('gtk_doc')),
' Man pages: @0@'.format(get_option('man-pages')),
' Build tests: @0@'.format(get_option('build-tests')),
' Install tests: @0@'.format(get_option('install-tests')),
+1 -1
View File
@@ -31,7 +31,7 @@ option('colord', type: 'combo', choices : ['yes', 'no', 'auto'], value : 'auto',
description : 'Build colord support for the CUPS printing backend')
# Documentation and introspection
option('documentation', type: 'boolean', value: 'false',
option('gtk_doc', type: 'boolean', value: 'false',
description : 'Build API reference and tools documentation')
option('man-pages', type: 'boolean', value: 'false',
description : 'Build man pages for installed tools')
-12
View File
@@ -709,13 +709,7 @@ _post_send (GtkCupsRequest *request)
httpClearFields (request->http);
httpSetField (request->http, HTTP_FIELD_CONTENT_LENGTH, length);
httpSetField (request->http, HTTP_FIELD_CONTENT_TYPE, "application/ipp");
#ifdef HAVE_HTTPGETAUTHSTRING
httpSetField (request->http, HTTP_FIELD_AUTHORIZATION, httpGetAuthString (request->http));
#else
#ifdef HAVE_HTTP_AUTHSTRING
httpSetField (request->http, HTTP_FIELD_AUTHORIZATION, request->http->authstring);
#endif
#endif
if (httpPost (request->http, request->resource))
{
@@ -1198,13 +1192,7 @@ _get_send (GtkCupsRequest *request)
}
httpClearFields (request->http);
#ifdef HAVE_HTTPGETAUTHSTRING
httpSetField (request->http, HTTP_FIELD_AUTHORIZATION, httpGetAuthString (request->http));
#else
#ifdef HAVE_HTTP_AUTHSTRING
httpSetField (request->http, HTTP_FIELD_AUTHORIZATION, request->http->authstring);
#endif
#endif
if (httpGet (request->http, request->resource))
{
+3 -27
View File
@@ -17,32 +17,8 @@ print_backends = ['file']
# Checks to see if we should compile with CUPS backend for GTK
enable_cups = enabled_print_backends.contains('cups')
if enable_cups
#cups_config = find_program('cups-config', required : true)
#if cups_config.found()
# FIXME: eek, see configure.ac (we're just not going to support non-standar prefix for now)
#endif
if cc.has_header('cups/cups.h')
# TODO: include_directories from cups-config
cups_major_version = cc.compute_int('CUPS_VERSION_MAJOR', prefix : '#include <cups/cups.h>')
cups_minor_version = cc.compute_int('CUPS_VERSION_MINOR', prefix : '#include <cups/cups.h>')
message('Found CUPS version: @0@.@1@'.format(cups_major_version, cups_minor_version))
if cups_major_version >= 2
if cc.compiles('#include <cups/http.h> \n http_t http; char *s = http.authstring;')
cdata.set('HAVE_HTTP_AUTHSTRING', 1,
description :'Define if cups http_t authstring field is accessible')
endif
libcups = cc.find_library('cups', required : true)
if libcups.found() and cc.has_function('httpGetAuthString', dependencies : libcups)
cdata.set('HAVE_HTTPGETAUTHSTRING', 1)
endif
print_backends += ['cups']
else
error('Need CUPS version >= 2.0')
endif
else
error('Cannot find CUPS headers in default prefix.')
endif
cups_dep = dependency('cups', version : '>=2.0', required: true)
print_backends += ['cups']
endif
# Checks to see if we should compile with cloudprint backend for GTK
@@ -101,7 +77,7 @@ if print_backends.contains('cups')
'gtkcupsutils.c',
'gtkcupssecretsutils.c',
c_args: printbackends_args,
dependencies: [libgtk_dep, libcups, colord_dep],
dependencies: [libgtk_dep, cups_dep, colord_dep],
install_dir: printbackends_install_dir,
install : true)
endif
-382
View File
@@ -1,382 +0,0 @@
#include <gtk/gtk.h>
#include "../../gtk/gtkconstrainttypesprivate.h"
#include "../../gtk/gtkconstraintsolverprivate.h"
#include "../../gtk/gtkconstraintexpressionprivate.h"
typedef struct _Node Node;
static GtkConstraintSolver *solver;
static Node *tree;
static Node *drag_node;
static double drag_start_x;
static double drag_start_y;
static GtkConstraintVariable *width_var;
static GtkConstraintVariable *height_var;
struct _Node {
double x;
double y;
Node *parent;
Node *left;
Node *right;
GtkConstraintVariable *x_var;
GtkConstraintVariable *y_var;
};
static Node *
make_tree (Node *parent,
int depth,
int x,
int y,
int dx,
int dy)
{
Node *node;
node = g_new0 (Node, 1);
node->parent = parent;
if (depth > 0)
{
node->left = make_tree (node, depth - 1, x - dx, y + dy, dx / 2, dy);
node->right = make_tree (node, depth - 1, x + dx, y + dy, dx / 2, dy);
}
node->x = x;
node->y = y;
node->x_var = gtk_constraint_solver_create_variable (solver, NULL, "x", x);
node->y_var = gtk_constraint_solver_create_variable (solver, NULL, "y", y);
/* weak stay for the current position */
gtk_constraint_solver_add_stay_variable (solver, node->x_var, GTK_CONSTRAINT_WEIGHT_WEAK);
gtk_constraint_solver_add_stay_variable (solver, node->y_var, GTK_CONSTRAINT_WEIGHT_WEAK);
/* require to stay in area */
gtk_constraint_solver_add_constraint (solver,
node->x_var,
GTK_CONSTRAINT_RELATION_GE,
gtk_constraint_expression_new (0.0),
GTK_CONSTRAINT_WEIGHT_REQUIRED);
gtk_constraint_solver_add_constraint (solver,
node->x_var,
GTK_CONSTRAINT_RELATION_LE,
gtk_constraint_expression_new (1600.0),
//gtk_constraint_expression_new_from_variable (width_var),
GTK_CONSTRAINT_WEIGHT_REQUIRED);
gtk_constraint_solver_add_constraint (solver,
node->y_var,
GTK_CONSTRAINT_RELATION_GE,
gtk_constraint_expression_new (0.0),
GTK_CONSTRAINT_WEIGHT_REQUIRED);
gtk_constraint_solver_add_constraint (solver,
node->y_var,
GTK_CONSTRAINT_RELATION_LE,
gtk_constraint_expression_new (600.0),
//gtk_constraint_expression_new_from_variable (height_var),
GTK_CONSTRAINT_WEIGHT_REQUIRED);
if (node->left)
{
GtkConstraintExpressionBuilder builder;
/* left.y = right.y */
gtk_constraint_solver_add_constraint (solver,
node->left->y_var,
GTK_CONSTRAINT_RELATION_EQ,
gtk_constraint_expression_new_from_variable (node->right->y_var),
GTK_CONSTRAINT_WEIGHT_REQUIRED);
/* left.y >= parent.y + 10 */
gtk_constraint_expression_builder_init (&builder, solver);
gtk_constraint_expression_builder_term (&builder, node->y_var);
gtk_constraint_expression_builder_plus (&builder);
gtk_constraint_expression_builder_constant (&builder, 10.0);
gtk_constraint_solver_add_constraint (solver,
node->left->y_var,
GTK_CONSTRAINT_RELATION_GE,
gtk_constraint_expression_builder_finish (&builder),
GTK_CONSTRAINT_WEIGHT_REQUIRED);
/* right.y >= parent.y + 10 */
gtk_constraint_expression_builder_init (&builder, solver);
gtk_constraint_expression_builder_term (&builder, node->y_var);
gtk_constraint_expression_builder_plus (&builder);
gtk_constraint_expression_builder_constant (&builder, 10.0);
gtk_constraint_solver_add_constraint (solver,
node->right->y_var,
GTK_CONSTRAINT_RELATION_GE,
gtk_constraint_expression_builder_finish (&builder),
GTK_CONSTRAINT_WEIGHT_REQUIRED);
/* parent.x = (left.x + right.x) / 2 */
gtk_constraint_expression_builder_init (&builder, solver);
gtk_constraint_expression_builder_term (&builder, node->left->x_var);
gtk_constraint_expression_builder_plus (&builder);
gtk_constraint_expression_builder_term (&builder, node->right->x_var);
gtk_constraint_expression_builder_divide_by (&builder);
gtk_constraint_expression_builder_constant (&builder, 2.0);
gtk_constraint_solver_add_constraint (solver,
node->x_var,
GTK_CONSTRAINT_RELATION_EQ,
gtk_constraint_expression_builder_finish (&builder),
GTK_CONSTRAINT_WEIGHT_REQUIRED);
}
return node;
}
static void
draw_node (Node *node, cairo_t *cr)
{
if (node->left)
draw_node (node->left, cr);
if (node->right)
draw_node (node->right, cr);
if (node->parent)
{
cairo_set_source_rgb (cr, 0, 0, 0);
cairo_move_to (cr, node->parent->x, node->parent->y);
cairo_line_to (cr, node->x, node->y);
cairo_stroke (cr);
}
if (node == drag_node)
cairo_set_source_rgb (cr, 1, 0, 0);
else
cairo_set_source_rgb (cr, 0, 0, 0);
cairo_move_to (cr, node->x, node->y);
cairo_arc (cr, node->x, node->y, 5, 0, 2*M_PI);
cairo_close_path (cr);
cairo_fill (cr);
}
static void
draw_func (GtkDrawingArea *da,
cairo_t *cr,
int width,
int height,
gpointer data)
{
cairo_set_line_width (cr, 1);
cairo_set_source_rgb (cr, 1, 1, 1);
cairo_paint (cr);
draw_node (tree, cr);
}
static Node *
find_node (Node *node,
double x,
double y)
{
Node *ret;
double dx = x - node->x;
double dy = y - node->y;
if (dx*dx + dy*dy < 10*10)
return node;
if (node->left)
{
ret = find_node (node->left, x, y);
if (ret)
return ret;
}
if (node->right)
{
ret = find_node (node->right, x, y);
if (ret)
return ret;
}
return NULL;
}
static void
drag_begin (GtkGestureDrag *drag,
double start_x,
double start_y,
gpointer data)
{
drag_node = find_node (tree, start_x, start_y);
if (!drag_node)
return;
drag_start_x = start_x;
drag_start_y = start_y;
gtk_widget_queue_draw (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (drag)));
gtk_constraint_solver_add_edit_variable (solver,
drag_node->x_var,
GTK_CONSTRAINT_WEIGHT_STRONG);
gtk_constraint_solver_add_edit_variable (solver,
drag_node->y_var,
GTK_CONSTRAINT_WEIGHT_STRONG);
gtk_constraint_solver_begin_edit (solver);
}
static void
update_tree (Node *node)
{
if (!node)
return;
node->x = gtk_constraint_variable_get_value (node->x_var);
node->y = gtk_constraint_variable_get_value (node->y_var);
update_tree (node->left);
update_tree (node->right);
}
static void
drag_update (GtkGestureDrag *drag,
double offset_x,
double offset_y,
gpointer data)
{
if (!drag_node)
return;
gtk_constraint_solver_suggest_value (solver,
drag_node->x_var,
drag_start_x + offset_x);
gtk_constraint_solver_suggest_value (solver,
drag_node->y_var,
drag_start_y + offset_y);
gtk_constraint_solver_resolve (solver);
update_tree (tree);
gtk_widget_queue_draw (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (drag)));
}
static void
drag_end (GtkGestureDrag *drag,
double offset_x,
double offset_y,
gpointer data)
{
if (!drag_node)
return;
gtk_constraint_solver_remove_edit_variable (solver, drag_node->x_var);
gtk_constraint_solver_remove_edit_variable (solver, drag_node->y_var);
gtk_constraint_solver_end_edit (solver);
drag_node = NULL;
gtk_widget_queue_draw (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (drag)));
}
static void
size_change (GtkWidget *da,
int width,
int height,
int baseline,
gpointer data)
{
gtk_constraint_variable_set_value (width_var, width);
gtk_constraint_variable_set_value (height_var, height);
gtk_constraint_solver_resolve (solver);
}
static void
reset_tree (Node *node,
int x,
int y,
int dx,
int dy)
{
node->x = x;
node->y = y;
gtk_constraint_solver_remove_stay_variable (solver, node->x_var);
gtk_constraint_solver_remove_stay_variable (solver, node->y_var);
gtk_constraint_variable_set_value (node->x_var, x);
gtk_constraint_variable_set_value (node->y_var, y);
gtk_constraint_solver_add_stay_variable (solver, node->x_var, GTK_CONSTRAINT_WEIGHT_WEAK);
gtk_constraint_solver_add_stay_variable (solver, node->y_var, GTK_CONSTRAINT_WEIGHT_WEAK);
if (node->left)
reset_tree (node->left, x - dx, y + dy, dx / 2, dy);
if (node->right)
reset_tree (node->right, x + dx, y + dy, dx / 2, dy);
}
static void
reset (GtkButton *button,
GtkWidget *da)
{
int width, height;
width = gtk_widget_get_allocated_width (da);
height = gtk_widget_get_allocated_height (da);
gtk_constraint_solver_freeze (solver);
reset_tree (tree, width / 2, 20, width / 4 - 40, (height - 40) / 7);
gtk_constraint_solver_thaw (solver);
gtk_widget_queue_draw (da);
}
int
main (int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *header;
GtkWidget *button;
GtkWidget *da;
GtkGesture *drag;
int width = 1600;
int height = 600;
gtk_init ();
da = gtk_drawing_area_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
header = gtk_header_bar_new ();
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
button = gtk_button_new_with_label ("Reset");
g_signal_connect (button, "clicked", G_CALLBACK (reset), da);
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), button);
gtk_window_set_titlebar (GTK_WINDOW (window), header);
gtk_drawing_area_set_content_width (GTK_DRAWING_AREA (da), width);
gtk_drawing_area_set_content_height (GTK_DRAWING_AREA (da), height);
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (da), draw_func, NULL, NULL);
gtk_container_add (GTK_CONTAINER (window), da);
drag = gtk_gesture_drag_new ();
g_signal_connect (drag, "drag-begin", G_CALLBACK (drag_begin), NULL);
g_signal_connect (drag, "drag-update", G_CALLBACK (drag_update), NULL);
g_signal_connect (drag, "drag-end", G_CALLBACK (drag_end), NULL);
gtk_widget_add_controller (da, GTK_EVENT_CONTROLLER (drag));
solver = g_object_new (g_type_from_name ("GtkConstraintSolver"), NULL);
gtk_constraint_solver_freeze (solver);
width_var = gtk_constraint_solver_create_variable (solver, NULL, "width", width);
height_var = gtk_constraint_solver_create_variable (solver, NULL, "height", height);
gtk_constraint_solver_add_stay_variable (solver, width_var, GTK_CONSTRAINT_WEIGHT_REQUIRED);
gtk_constraint_solver_add_stay_variable (solver, height_var, GTK_CONSTRAINT_WEIGHT_REQUIRED);
g_signal_connect (da, "size-allocate", G_CALLBACK (size_change), NULL);
tree = make_tree (NULL, 7, width / 2, 20, width / 4 - 40, (height - 40) / 7);
gtk_constraint_solver_thaw (solver);
gtk_widget_show (window);
gtk_main ();
return 0;
}
+1 -9
View File
@@ -1,10 +1,5 @@
gtk_tests = [
# testname, optional extra sources
['constrainttree', [
'../gtk/gtkconstraintsolver.c',
'../gtk/gtkconstraintexpression.c',
], ['-DGTK_COMPILATION', '-UG_ENABLE_DEBUG', '-DGTK_TEST_EXTERNAL']
],
['rendernode'],
['rendernode-create-tests'],
['overlayscroll'],
@@ -147,12 +142,9 @@ test_args = ['-DGTK_SRCDIR="@0@"'.format(meson.current_source_dir())]
foreach t: gtk_tests
test_name = t.get(0)
test_srcs = ['@0@.c'.format(test_name), t.get(1, [])]
test_extra_cargs = t.get(2, [])
test_extra_ldflags = t.get(3, [])
executable(test_name, test_srcs,
include_directories: [confinc, gdkinc],
c_args: test_args + test_extra_cargs,
link_args : test_extra_ldflags,
c_args: test_args,
dependencies: [libgtk_dep, libm])
endforeach
-326
View File
@@ -1,326 +0,0 @@
/* Copyright (C) 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <gtk/gtk.h>
#define GTK_TYPE_GIZMO (gtk_gizmo_get_type ())
#define GTK_GIZMO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_GIZMO, GtkGizmo))
#define GTK_GIZMO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_GIZMO, GtkGizmoClass))
#define GTK_IS_GIZMO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_GIZMO))
#define GTK_IS_GIZMO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_GIZMO))
#define GTK_GIZMO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_GIZMO, GtkGizmoClass))
typedef struct _GtkGizmo GtkGizmo;
struct _GtkGizmo {
GtkWidget parent;
int min_width;
int min_height;
int nat_width;
int nat_height;
int width;
int height;
};
typedef GtkWidgetClass GtkGizmoClass;
G_DEFINE_TYPE (GtkGizmo, gtk_gizmo, GTK_TYPE_WIDGET);
static void
gtk_gizmo_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
GtkGizmo *self = GTK_GIZMO (widget);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
*minimum = self->min_width;
*natural = self->nat_width;
}
else
{
*minimum = self->min_height;
*natural = self->nat_height;
}
}
static void
gtk_gizmo_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
GtkGizmo *self = GTK_GIZMO (widget);
self->width = width;
self->height = height;
}
static void
gtk_gizmo_class_init (GtkGizmoClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
widget_class->measure = gtk_gizmo_measure;
widget_class->size_allocate = gtk_gizmo_size_allocate;
}
static void
gtk_gizmo_init (GtkGizmo *self)
{
}
/* Create a layout with three children
*
* +--------+--------+
* | child1 | child2 |
* +--------+--------+
* | child3 |
* +-----------------+
*
* Verify that
* - the layout has the expected min and nat sizes
* - the children get their >=nat width when the layout does
* - test that allocating the layout larger keeps
* child1 and child2 at the same size
*/
static void
test_simple_layout (void)
{
GtkWidget *window;
GtkWidget *parent;
GtkLayoutManager *layout;
GtkConstraintLayout *manager;
GtkGizmo *child1;
GtkGizmo *child2;
GtkGizmo *child3;
int minimum, natural;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
parent = g_object_new (GTK_TYPE_GIZMO, NULL);
gtk_widget_set_name (parent, "parent");
gtk_container_add (GTK_CONTAINER (window), parent);
layout = gtk_constraint_layout_new ();
gtk_widget_set_layout_manager (parent, layout);
manager = GTK_CONSTRAINT_LAYOUT (layout);
child1 = g_object_new (GTK_TYPE_GIZMO, NULL);
child2 = g_object_new (GTK_TYPE_GIZMO, NULL);
child3 = g_object_new (GTK_TYPE_GIZMO, NULL);
gtk_widget_set_name (GTK_WIDGET (child1), "child1");
child1->min_width = 10;
child1->min_height = 10;
child1->nat_width = 50;
child1->nat_height = 50;
gtk_widget_set_name (GTK_WIDGET (child2), "child2");
child2->min_width = 20;
child2->min_height = 20;
child2->nat_width = 50;
child2->nat_height = 50;
gtk_widget_set_name (GTK_WIDGET (child3), "child3");
child3->min_width = 50;
child3->min_height = 10;
child3->nat_width = 50;
child3->nat_height = 50;
gtk_widget_set_parent (GTK_WIDGET (child1), parent);
gtk_widget_set_parent (GTK_WIDGET (child2), parent);
gtk_widget_set_parent (GTK_WIDGET (child3), parent);
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_START,
GTK_CONSTRAINT_RELATION_EQ,
child1,
GTK_CONSTRAINT_ATTRIBUTE_START,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (child1,
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
GTK_CONSTRAINT_RELATION_EQ,
child2,
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (child1,
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
GTK_CONSTRAINT_RELATION_EQ,
child2,
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (child1,
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
GTK_CONSTRAINT_RELATION_EQ,
child3,
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (child1,
GTK_CONSTRAINT_ATTRIBUTE_END,
GTK_CONSTRAINT_RELATION_EQ,
child2,
GTK_CONSTRAINT_ATTRIBUTE_START,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (child2,
GTK_CONSTRAINT_ATTRIBUTE_END,
GTK_CONSTRAINT_RELATION_EQ,
NULL,
GTK_CONSTRAINT_ATTRIBUTE_END,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_START,
GTK_CONSTRAINT_RELATION_EQ,
child3,
GTK_CONSTRAINT_ATTRIBUTE_START,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (child3,
GTK_CONSTRAINT_ATTRIBUTE_END,
GTK_CONSTRAINT_RELATION_EQ,
NULL,
GTK_CONSTRAINT_ATTRIBUTE_END,
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,
child1,
GTK_CONSTRAINT_ATTRIBUTE_TOP,
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,
child2,
GTK_CONSTRAINT_ATTRIBUTE_TOP,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (child1,
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
GTK_CONSTRAINT_RELATION_EQ,
child3,
GTK_CONSTRAINT_ATTRIBUTE_TOP,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (child2,
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
GTK_CONSTRAINT_RELATION_EQ,
child3,
GTK_CONSTRAINT_ATTRIBUTE_TOP,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (child3,
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
GTK_CONSTRAINT_RELATION_EQ,
NULL,
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
#if 0
gtk_widget_show (window);
g_timeout_add (1000, (GSourceFunc)gtk_main_quit, NULL);
gtk_main ();
#endif
gtk_layout_manager_measure (layout,
parent,
GTK_ORIENTATION_HORIZONTAL,
-1,
&minimum,
&natural,
NULL,
NULL);
g_assert_cmpint (minimum, ==, 50);
g_assert_cmpint (natural, ==, 100);
gtk_layout_manager_measure (layout,
parent,
GTK_ORIENTATION_VERTICAL,
-1,
&minimum,
&natural,
NULL,
NULL);
g_assert_cmpint (minimum, ==, 40);
g_assert_cmpint (natural, ==, 100);
gtk_layout_manager_allocate (layout, parent, 100, 100, 0);
g_assert_cmpint (child1->width, ==, 50);
g_assert_cmpint (child2->width, ==, 50);
g_assert_cmpint (child3->width, ==, 100);
g_assert_cmpint (child1->height, ==, 50);
g_assert_cmpint (child2->height, ==, 50);
g_assert_cmpint (child3->height, ==, 50);
gtk_widget_unparent (GTK_WIDGET (child1));
gtk_widget_unparent (GTK_WIDGET (child2));
gtk_widget_unparent (GTK_WIDGET (child3));
gtk_widget_destroy (parent);
}
int
main (int argc,
char *argv[])
{
gtk_test_init (&argc, &argv);
g_test_add_func ("/constraint-layout/simple", test_simple_layout);
return g_test_run();
}
+23 -23
View File
@@ -16,7 +16,7 @@ constraint_solver_simple (void)
gtk_constraint_solver_add_constraint (solver,
x, GTK_CONSTRAINT_RELATION_EQ, e,
GTK_CONSTRAINT_WEIGHT_REQUIRED);
GTK_CONSTRAINT_STRENGTH_REQUIRED);
double x_value = gtk_constraint_variable_get_value (x);
double y_value = gtk_constraint_variable_get_value (y);
@@ -39,8 +39,8 @@ constraint_solver_stay (void)
GtkConstraintVariable *x = gtk_constraint_solver_create_variable (solver, NULL, "x", 5.0);
GtkConstraintVariable *y = gtk_constraint_solver_create_variable (solver, NULL, "y", 10.0);
gtk_constraint_solver_add_stay_variable (solver, x, GTK_CONSTRAINT_WEIGHT_WEAK);
gtk_constraint_solver_add_stay_variable (solver, y, GTK_CONSTRAINT_WEIGHT_WEAK);
gtk_constraint_solver_add_stay_variable (solver, x, GTK_CONSTRAINT_STRENGTH_WEAK);
gtk_constraint_solver_add_stay_variable (solver, y, GTK_CONSTRAINT_STRENGTH_WEAK);
double x_value = gtk_constraint_variable_get_value (x);
double y_value = gtk_constraint_variable_get_value (y);
@@ -64,7 +64,7 @@ constraint_solver_variable_geq_constant (void)
gtk_constraint_solver_add_constraint (solver,
x, GTK_CONSTRAINT_RELATION_GE, e,
GTK_CONSTRAINT_WEIGHT_REQUIRED);
GTK_CONSTRAINT_STRENGTH_REQUIRED);
double x_value = gtk_constraint_variable_get_value (x);
@@ -85,7 +85,7 @@ constraint_solver_variable_leq_constant (void)
gtk_constraint_solver_add_constraint (solver,
x, GTK_CONSTRAINT_RELATION_LE, e,
GTK_CONSTRAINT_WEIGHT_REQUIRED);
GTK_CONSTRAINT_STRENGTH_REQUIRED);
double x_value = gtk_constraint_variable_get_value (x);
@@ -106,7 +106,7 @@ constraint_solver_variable_eq_constant (void)
gtk_constraint_solver_add_constraint (solver,
x, GTK_CONSTRAINT_RELATION_EQ, e,
GTK_CONSTRAINT_WEIGHT_REQUIRED);
GTK_CONSTRAINT_STRENGTH_REQUIRED);
double x_value = gtk_constraint_variable_get_value (x);
@@ -133,11 +133,11 @@ constraint_solver_eq_with_stay (void)
gtk_constraint_expression_builder_term (&builder, width);
GtkConstraintExpression *right = gtk_constraint_expression_builder_finish (&builder);
gtk_constraint_solver_add_stay_variable (solver, width, GTK_CONSTRAINT_WEIGHT_WEAK);
gtk_constraint_solver_add_stay_variable (solver, right_min, GTK_CONSTRAINT_WEIGHT_WEAK);
gtk_constraint_solver_add_stay_variable (solver, width, GTK_CONSTRAINT_STRENGTH_WEAK);
gtk_constraint_solver_add_stay_variable (solver, right_min, GTK_CONSTRAINT_STRENGTH_WEAK);
gtk_constraint_solver_add_constraint (solver,
right_min, GTK_CONSTRAINT_RELATION_EQ, right,
GTK_CONSTRAINT_WEIGHT_REQUIRED);
GTK_CONSTRAINT_STRENGTH_REQUIRED);
double x_value = gtk_constraint_variable_get_value (x);
double width_value = gtk_constraint_variable_get_value (width);
@@ -165,22 +165,22 @@ constraint_solver_cassowary (void)
e = gtk_constraint_expression_new_from_variable (y);
gtk_constraint_solver_add_constraint (solver,
x, GTK_CONSTRAINT_RELATION_LE, e,
GTK_CONSTRAINT_WEIGHT_REQUIRED);
GTK_CONSTRAINT_STRENGTH_REQUIRED);
e = gtk_constraint_expression_plus_constant (gtk_constraint_expression_new_from_variable (x), 3.0);
gtk_constraint_solver_add_constraint (solver,
y, GTK_CONSTRAINT_RELATION_EQ, e,
GTK_CONSTRAINT_WEIGHT_REQUIRED);
GTK_CONSTRAINT_STRENGTH_REQUIRED);
e = gtk_constraint_expression_new (10.0);
gtk_constraint_solver_add_constraint (solver,
x, GTK_CONSTRAINT_RELATION_EQ, e,
GTK_CONSTRAINT_WEIGHT_WEAK);
GTK_CONSTRAINT_STRENGTH_WEAK);
e = gtk_constraint_expression_new (10.0);
gtk_constraint_solver_add_constraint (solver,
y, GTK_CONSTRAINT_RELATION_EQ, e,
GTK_CONSTRAINT_WEIGHT_WEAK);
GTK_CONSTRAINT_STRENGTH_WEAK);
double x_val = gtk_constraint_variable_get_value (x);
double y_val = gtk_constraint_variable_get_value (y);
@@ -205,11 +205,11 @@ constraint_solver_edit_var_required (void)
GtkConstraintSolver *solver = gtk_constraint_solver_new ();
GtkConstraintVariable *a = gtk_constraint_solver_create_variable (solver, NULL, "a", 0.0);
gtk_constraint_solver_add_stay_variable (solver, a, GTK_CONSTRAINT_WEIGHT_STRONG);
gtk_constraint_solver_add_stay_variable (solver, a, GTK_CONSTRAINT_STRENGTH_STRONG);
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (a), 0.0, 0.001);
gtk_constraint_solver_add_edit_variable (solver, a, GTK_CONSTRAINT_WEIGHT_REQUIRED);
gtk_constraint_solver_add_edit_variable (solver, a, GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_solver_begin_edit (solver);
gtk_constraint_solver_suggest_value (solver, a, 2.0);
gtk_constraint_solver_resolve (solver);
@@ -236,19 +236,19 @@ constraint_solver_edit_var_suggest (void)
GtkConstraintVariable *a = gtk_constraint_solver_create_variable (solver, NULL, "a", 0.0);
GtkConstraintVariable *b = gtk_constraint_solver_create_variable (solver, NULL, "b", 0.0);
gtk_constraint_solver_add_stay_variable (solver, a, GTK_CONSTRAINT_WEIGHT_STRONG);
gtk_constraint_solver_add_stay_variable (solver, a, GTK_CONSTRAINT_STRENGTH_STRONG);
GtkConstraintExpression *e = gtk_constraint_expression_new_from_variable (b);
gtk_constraint_solver_add_constraint (solver,
a, GTK_CONSTRAINT_RELATION_EQ, e,
GTK_CONSTRAINT_WEIGHT_REQUIRED);
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_solver_resolve (solver);
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (a), 0.0, 0.001);
g_assert_cmpfloat_with_epsilon (gtk_constraint_variable_get_value (b), 0.0, 0.001);
gtk_constraint_solver_add_edit_variable (solver, a, GTK_CONSTRAINT_WEIGHT_REQUIRED);
gtk_constraint_solver_add_edit_variable (solver, a, GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_solver_begin_edit (solver);
gtk_constraint_solver_suggest_value (solver, a, 2.0);
@@ -302,7 +302,7 @@ constraint_solver_paper (void)
expr = gtk_constraint_expression_builder_finish (&builder);
gtk_constraint_solver_add_constraint (solver,
middle, GTK_CONSTRAINT_RELATION_EQ, expr,
GTK_CONSTRAINT_WEIGHT_REQUIRED);
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_expression_builder_init (&builder, solver);
gtk_constraint_expression_builder_term (&builder, left);
@@ -311,17 +311,17 @@ constraint_solver_paper (void)
expr = gtk_constraint_expression_builder_finish (&builder);
gtk_constraint_solver_add_constraint (solver,
right, GTK_CONSTRAINT_RELATION_EQ, expr,
GTK_CONSTRAINT_WEIGHT_REQUIRED);
GTK_CONSTRAINT_STRENGTH_REQUIRED);
expr = gtk_constraint_expression_new (100.0);
gtk_constraint_solver_add_constraint (solver,
right, GTK_CONSTRAINT_RELATION_LE, expr,
GTK_CONSTRAINT_WEIGHT_REQUIRED);
GTK_CONSTRAINT_STRENGTH_REQUIRED);
expr = gtk_constraint_expression_new (0.0);
gtk_constraint_solver_add_constraint (solver,
left, GTK_CONSTRAINT_RELATION_GE, expr,
GTK_CONSTRAINT_WEIGHT_REQUIRED);
GTK_CONSTRAINT_STRENGTH_REQUIRED);
g_test_message ("Check constraints hold");
@@ -335,7 +335,7 @@ constraint_solver_paper (void)
g_assert_cmpfloat (gtk_constraint_variable_get_value (left), >=, 0.0);
gtk_constraint_variable_set_value (middle, 45.0);
gtk_constraint_solver_add_stay_variable (solver, middle, GTK_CONSTRAINT_WEIGHT_WEAK);
gtk_constraint_solver_add_stay_variable (solver, middle, GTK_CONSTRAINT_STRENGTH_WEAK);
g_test_message ("Check constraints hold after setting middle");
+39
View File
@@ -300,6 +300,44 @@ test_submodel_add (void)
g_object_unref (flat);
}
static void
test_submodel_add2 (void)
{
GtkFlattenListModel *flat;
GListStore *model, *store[2];
model = g_list_store_new (G_TYPE_LIST_MODEL);
flat = new_model (model);
assert_model (flat, "");
assert_changes (flat, "");
store[0] = add_store (model, 1, 0, 0);
store[1] = add_store (model, 1, 0, 0);
store[2] = add_store (model, 1, 0, 0);
assert_model (flat, "");
assert_changes (flat, "");
add (store[0], 1);
assert_model (flat, "1");
assert_changes (flat, "+0");
add (store[1], 3);
assert_model (flat, "1 3");
assert_changes (flat, "+1");
add (store[0], 2);
assert_model (flat, "1 2 3");
assert_changes (flat, "+1");
add (store[1], 4);
assert_model (flat, "1 2 3 4");
assert_changes (flat, "+3");
g_object_unref (model);
g_object_unref (flat);
}
static void
test_model_remove (void)
{
@@ -365,6 +403,7 @@ main (int argc, char *argv[])
g_test_add_func ("/flattenlistmodel/model/add", test_model_add);
#if GLIB_CHECK_VERSION (2, 58, 0) /* g_list_store_splice() is broken before 2.58 */
g_test_add_func ("/flattenlistmodel/submodel/add", test_submodel_add);
g_test_add_func ("/flattenlistmodel/submodel/add2", test_submodel_add2);
g_test_add_func ("/flattenlistmodel/model/remove", test_model_remove);
g_test_add_func ("/flattenlistmodel/submodel/remove", test_submodel_remove);
#endif
+681
View File
@@ -0,0 +1,681 @@
/* Copyright (C) 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <gtk/gtk.h>
#define GTK_TYPE_GIZMO (gtk_gizmo_get_type ())
#define GTK_GIZMO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_GIZMO, GtkGizmo))
#define GTK_GIZMO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_GIZMO, GtkGizmoClass))
#define GTK_IS_GIZMO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_GIZMO))
#define GTK_IS_GIZMO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_GIZMO))
#define GTK_GIZMO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_GIZMO, GtkGizmoClass))
typedef struct _GtkGizmo GtkGizmo;
struct _GtkGizmo {
GtkWidget parent;
const char *name;
int min_width;
int min_height;
int nat_width;
int nat_height;
int width;
int height;
};
typedef GtkWidgetClass GtkGizmoClass;
G_DEFINE_TYPE (GtkGizmo, gtk_gizmo, GTK_TYPE_WIDGET);
static void
gtk_gizmo_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
GtkGizmo *self = GTK_GIZMO (widget);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
*minimum = self->min_width;
*natural = self->nat_width;
}
else
{
*minimum = self->min_height;
*natural = self->nat_height;
}
}
static void
gtk_gizmo_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
GtkGizmo *self = GTK_GIZMO (widget);
self->width = width;
self->height = height;
}
static void
gtk_gizmo_class_init (GtkGizmoClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
widget_class->measure = gtk_gizmo_measure;
widget_class->size_allocate = gtk_gizmo_size_allocate;
}
static void
gtk_gizmo_init (GtkGizmo *self)
{
}
/* Create a grid with three children in row
*
* +--------+--------+--------+
* | child1 | child2 | child3 |
* +--------+--------+--------+
*
* Verify that
* - the layout has the expected min and nat sizes
* - the children get their nat width when the layout does
* - they all get the same height
*/
static void
test_simple_row (void)
{
GtkWidget *window;
GtkWidget *parent;
GtkLayoutManager *layout;
GtkGizmo *child1;
GtkGizmo *child2;
GtkGizmo *child3;
GtkLayoutChild *lc;
int minimum, natural;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
parent = g_object_new (GTK_TYPE_GIZMO, NULL);
gtk_container_add (GTK_CONTAINER (window), parent);
layout = gtk_grid_layout_new ();
gtk_widget_set_layout_manager (parent, layout);
child1 = g_object_new (GTK_TYPE_GIZMO, NULL);
child2 = g_object_new (GTK_TYPE_GIZMO, NULL);
child3 = g_object_new (GTK_TYPE_GIZMO, NULL);
child1->name = "child1";
child1->min_width = 10;
child1->min_height = 10;
child1->nat_width = 20;
child1->nat_height = 20;
child2->name = "child2";
child2->min_width = 20;
child2->min_height = 20;
child2->nat_width = 30;
child2->nat_height = 30;
child3->name = "child3";
child3->min_width = 30;
child3->min_height = 30;
child3->nat_width = 40;
child3->nat_height = 40;
gtk_widget_set_parent (GTK_WIDGET (child1), parent);
gtk_widget_set_parent (GTK_WIDGET (child2), parent);
gtk_widget_set_parent (GTK_WIDGET (child3), parent);
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child1));
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child2));
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 1);
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child3));
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 2);
#if 0
gtk_widget_show (window);
g_timeout_add (1000, (GSourceFunc)gtk_main_quit, NULL);
gtk_main ();
#endif
gtk_layout_manager_measure (layout,
parent,
GTK_ORIENTATION_HORIZONTAL,
-1,
&minimum,
&natural,
NULL,
NULL);
g_assert_cmpint (minimum, ==, 10 + 20 + 30);
g_assert_cmpint (natural, ==, 20 + 30 + 40);
gtk_layout_manager_measure (layout,
parent,
GTK_ORIENTATION_VERTICAL,
-1,
&minimum,
&natural,
NULL,
NULL);
g_assert_cmpint (minimum, ==, 30);
g_assert_cmpint (natural, ==, 40);
gtk_layout_manager_allocate (layout, parent, 90, 40, 0);
g_assert_cmpint (child1->width, ==, 20);
g_assert_cmpint (child2->width, ==, 30);
g_assert_cmpint (child3->width, ==, 40);
g_assert_cmpint (child1->height, ==, 40);
g_assert_cmpint (child2->height, ==, 40);
g_assert_cmpint (child3->height, ==, 40);
gtk_widget_unparent (GTK_WIDGET (child1));
gtk_widget_unparent (GTK_WIDGET (child2));
gtk_widget_unparent (GTK_WIDGET (child3));
gtk_widget_destroy (parent);
}
/* same as the previous test, with a column
*/
static void
test_simple_column (void)
{
GtkWidget *window;
GtkWidget *parent;
GtkLayoutManager *layout;
GtkGizmo *child1;
GtkGizmo *child2;
GtkGizmo *child3;
GtkLayoutChild *lc;
int minimum, natural;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
parent = g_object_new (GTK_TYPE_GIZMO, NULL);
gtk_container_add (GTK_CONTAINER (window), parent);
layout = gtk_grid_layout_new ();
gtk_widget_set_layout_manager (parent, layout);
child1 = g_object_new (GTK_TYPE_GIZMO, NULL);
child2 = g_object_new (GTK_TYPE_GIZMO, NULL);
child3 = g_object_new (GTK_TYPE_GIZMO, NULL);
child1->name = "child1";
child1->min_width = 10;
child1->min_height = 10;
child1->nat_width = 20;
child1->nat_height = 20;
child2->name = "child2";
child2->min_width = 20;
child2->min_height = 20;
child2->nat_width = 30;
child2->nat_height = 30;
child3->name = "child3";
child3->min_width = 30;
child3->min_height = 30;
child3->nat_width = 40;
child3->nat_height = 40;
gtk_widget_set_parent (GTK_WIDGET (child1), parent);
gtk_widget_set_parent (GTK_WIDGET (child2), parent);
gtk_widget_set_parent (GTK_WIDGET (child3), parent);
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child1));
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child2));
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 1);
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child3));
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 2);
#if 0
gtk_widget_show (window);
g_timeout_add (1000, (GSourceFunc)gtk_main_quit, NULL);
gtk_main ();
#endif
gtk_layout_manager_measure (layout,
parent,
GTK_ORIENTATION_HORIZONTAL,
-1,
&minimum,
&natural,
NULL,
NULL);
g_assert_cmpint (minimum, ==, 30);
g_assert_cmpint (natural, ==, 40);
gtk_layout_manager_measure (layout,
parent,
GTK_ORIENTATION_VERTICAL,
-1,
&minimum,
&natural,
NULL,
NULL);
g_assert_cmpint (minimum, ==, 10 + 20 + 30);
g_assert_cmpint (natural, ==, 20 + 30 + 40);
gtk_layout_manager_allocate (layout, parent, 40, 90, 0);
g_assert_cmpint (child1->width, ==, 40);
g_assert_cmpint (child2->width, ==, 40);
g_assert_cmpint (child3->width, ==, 40);
g_assert_cmpint (child1->height, ==, 20);
g_assert_cmpint (child2->height, ==, 30);
g_assert_cmpint (child3->height, ==, 40);
gtk_widget_unparent (GTK_WIDGET (child1));
gtk_widget_unparent (GTK_WIDGET (child2));
gtk_widget_unparent (GTK_WIDGET (child3));
gtk_widget_destroy (parent);
}
/* Create a grid with spanning children
*
* +--------+-----------------+
* | child1 | child2 |
* +--------+--------+--------+
* | child3 | child4 |
* +-----------------+--------+
*
* Verify that
* - the layout has the expected min and nat sizes
* - the children get their nat width when the layout does
*/
static void
test_spans (void)
{
GtkWidget *window;
GtkWidget *parent;
GtkLayoutManager *layout;
GtkGizmo *child1;
GtkGizmo *child2;
GtkGizmo *child3;
GtkGizmo *child4;
GtkLayoutChild *lc;
int minimum, natural;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
parent = g_object_new (GTK_TYPE_GIZMO, NULL);
gtk_container_add (GTK_CONTAINER (window), parent);
layout = gtk_grid_layout_new ();
gtk_widget_set_layout_manager (parent, layout);
child1 = g_object_new (GTK_TYPE_GIZMO, NULL);
child2 = g_object_new (GTK_TYPE_GIZMO, NULL);
child3 = g_object_new (GTK_TYPE_GIZMO, NULL);
child4 = g_object_new (GTK_TYPE_GIZMO, NULL);
child1->name = "child1";
child1->min_width = 10;
child1->min_height = 10;
child1->nat_width = 20;
child1->nat_height = 20;
child2->name = "child2";
child2->min_width = 20;
child2->min_height = 20;
child2->nat_width = 30;
child2->nat_height = 30;
child3->name = "child3";
child3->min_width = 30;
child3->min_height = 30;
child3->nat_width = 40;
child3->nat_height = 40;
child4->name = "child4";
child4->min_width = 30;
child4->min_height = 30;
child4->nat_width = 40;
child4->nat_height = 40;
gtk_widget_set_parent (GTK_WIDGET (child1), parent);
gtk_widget_set_parent (GTK_WIDGET (child2), parent);
gtk_widget_set_parent (GTK_WIDGET (child3), parent);
gtk_widget_set_parent (GTK_WIDGET (child4), parent);
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child1));
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child2));
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 1);
gtk_grid_layout_child_set_column_span (GTK_GRID_LAYOUT_CHILD (lc), 2);
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child3));
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 1);
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
gtk_grid_layout_child_set_column_span (GTK_GRID_LAYOUT_CHILD (lc), 2);
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child4));
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 1);
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 2);
#if 0
gtk_widget_show (window);
g_timeout_add (1000, (GSourceFunc)gtk_main_quit, NULL);
gtk_main ();
#endif
gtk_layout_manager_measure (layout,
parent,
GTK_ORIENTATION_HORIZONTAL,
-1,
&minimum,
&natural,
NULL,
NULL);
g_assert_cmpint (minimum, ==, 60);
g_assert_cmpint (natural, ==, 80);
gtk_layout_manager_measure (layout,
parent,
GTK_ORIENTATION_VERTICAL,
-1,
&minimum,
&natural,
NULL,
NULL);
g_assert_cmpint (minimum, ==, 50);
g_assert_cmpint (natural, ==, 70);
gtk_layout_manager_allocate (layout, parent, 80, 70, 0);
g_assert_cmpint (child1->width, ==, 30);
g_assert_cmpint (child2->width, ==, 50);
g_assert_cmpint (child3->width, ==, 40);
g_assert_cmpint (child4->width, ==, 40);
g_assert_cmpint (child1->height, ==, 30);
g_assert_cmpint (child2->height, ==, 30);
g_assert_cmpint (child3->height, ==, 40);
g_assert_cmpint (child4->height, ==, 40);
gtk_widget_unparent (GTK_WIDGET (child1));
gtk_widget_unparent (GTK_WIDGET (child2));
gtk_widget_unparent (GTK_WIDGET (child3));
gtk_widget_unparent (GTK_WIDGET (child4));
gtk_widget_destroy (parent);
}
/* Create a 2x2 homogeneous grid and verify
* all children get the same size.
*/
static void
test_homogeneous (void)
{
GtkWidget *window;
GtkWidget *parent;
GtkLayoutManager *layout;
GtkGizmo *child1;
GtkGizmo *child2;
GtkGizmo *child3;
GtkGizmo *child4;
GtkLayoutChild *lc;
int minimum, natural;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
parent = g_object_new (GTK_TYPE_GIZMO, NULL);
gtk_container_add (GTK_CONTAINER (window), parent);
layout = gtk_grid_layout_new ();
gtk_grid_layout_set_row_homogeneous (GTK_GRID_LAYOUT (layout), TRUE);
gtk_grid_layout_set_column_homogeneous (GTK_GRID_LAYOUT (layout), TRUE);
gtk_widget_set_layout_manager (parent, layout);
child1 = g_object_new (GTK_TYPE_GIZMO, NULL);
child2 = g_object_new (GTK_TYPE_GIZMO, NULL);
child3 = g_object_new (GTK_TYPE_GIZMO, NULL);
child4 = g_object_new (GTK_TYPE_GIZMO, NULL);
child1->name = "child1";
child1->min_width = 10;
child1->min_height = 10;
child1->nat_width = 20;
child1->nat_height = 20;
child2->name = "child2";
child2->min_width = 20;
child2->min_height = 20;
child2->nat_width = 30;
child2->nat_height = 30;
child3->name = "child3";
child3->min_width = 30;
child3->min_height = 30;
child3->nat_width = 40;
child3->nat_height = 40;
child4->name = "child4";
child4->min_width = 30;
child4->min_height = 30;
child4->nat_width = 40;
child4->nat_height = 40;
gtk_widget_set_parent (GTK_WIDGET (child1), parent);
gtk_widget_set_parent (GTK_WIDGET (child2), parent);
gtk_widget_set_parent (GTK_WIDGET (child3), parent);
gtk_widget_set_parent (GTK_WIDGET (child4), parent);
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child1));
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child2));
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 1);
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child3));
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 1);
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child4));
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 1);
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 1);
#if 0
gtk_widget_show (window);
g_timeout_add (1000, (GSourceFunc)gtk_main_quit, NULL);
gtk_main ();
#endif
gtk_layout_manager_measure (layout,
parent,
GTK_ORIENTATION_HORIZONTAL,
-1,
&minimum,
&natural,
NULL,
NULL);
g_assert_cmpint (minimum, ==, 60);
g_assert_cmpint (natural, ==, 80);
gtk_layout_manager_measure (layout,
parent,
GTK_ORIENTATION_VERTICAL,
-1,
&minimum,
&natural,
NULL,
NULL);
g_assert_cmpint (minimum, ==, 60);
g_assert_cmpint (natural, ==, 80);
gtk_layout_manager_allocate (layout, parent, 80, 80, 0);
g_assert_cmpint (child1->width, ==, 40);
g_assert_cmpint (child2->width, ==, 40);
g_assert_cmpint (child3->width, ==, 40);
g_assert_cmpint (child4->width, ==, 40);
g_assert_cmpint (child1->height, ==, 40);
g_assert_cmpint (child2->height, ==, 40);
g_assert_cmpint (child3->height, ==, 40);
g_assert_cmpint (child4->height, ==, 40);
gtk_widget_unparent (GTK_WIDGET (child1));
gtk_widget_unparent (GTK_WIDGET (child2));
gtk_widget_unparent (GTK_WIDGET (child3));
gtk_widget_unparent (GTK_WIDGET (child4));
gtk_widget_destroy (parent);
}
/* Create a layout with three children
*
* +--------+--------+
* | child1 | child2 |
* +--------+--------+
* | child3 |
* +-----------------+
*
* This is a layout that we also reproduce with
* constraints, for comparison. Among the contraints:
* - child1.width == child2.width
* - child1.height == child2.height == child3.height
*/
static void
test_simple_layout (void)
{
GtkWidget *window;
GtkWidget *parent;
GtkLayoutManager *layout;
GtkLayoutChild *lc;
GtkGizmo *child1;
GtkGizmo *child2;
GtkGizmo *child3;
int minimum, natural;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
parent = g_object_new (GTK_TYPE_GIZMO, NULL);
gtk_container_add (GTK_CONTAINER (window), parent);
layout = gtk_grid_layout_new ();
gtk_grid_layout_set_row_homogeneous (GTK_GRID_LAYOUT (layout), TRUE);
gtk_grid_layout_set_column_homogeneous (GTK_GRID_LAYOUT (layout), TRUE);
gtk_widget_set_layout_manager (parent, layout);
child1 = g_object_new (GTK_TYPE_GIZMO, NULL);
child2 = g_object_new (GTK_TYPE_GIZMO, NULL);
child3 = g_object_new (GTK_TYPE_GIZMO, NULL);
child1->name = "child1";
child1->min_width = 10;
child1->min_height = 10;
child1->nat_width = 50;
child1->nat_height = 50;
child2->name = "child2";
child2->min_width = 20;
child2->min_height = 20;
child2->nat_width = 50;
child2->nat_height = 50;
child3->name = "child3";
child3->min_width = 50;
child3->min_height = 10;
child3->nat_width = 50;
child3->nat_height = 50;
gtk_widget_set_parent (GTK_WIDGET (child1), parent);
gtk_widget_set_parent (GTK_WIDGET (child2), parent);
gtk_widget_set_parent (GTK_WIDGET (child3), parent);
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child1));
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child2));
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 1);
lc = gtk_layout_manager_get_layout_child (layout, GTK_WIDGET (child3));
gtk_grid_layout_child_set_top_attach (GTK_GRID_LAYOUT_CHILD (lc), 1);
gtk_grid_layout_child_set_left_attach (GTK_GRID_LAYOUT_CHILD (lc), 0);
gtk_grid_layout_child_set_column_span (GTK_GRID_LAYOUT_CHILD (lc), 2);
gtk_layout_manager_measure (layout,
parent,
GTK_ORIENTATION_HORIZONTAL,
-1,
&minimum,
&natural,
NULL,
NULL);
g_assert_cmpint (minimum, ==, 50);
g_assert_cmpint (natural, ==, 100);
gtk_layout_manager_measure (layout,
parent,
GTK_ORIENTATION_VERTICAL,
-1,
&minimum,
&natural,
NULL,
NULL);
g_assert_cmpint (minimum, ==, 40);
g_assert_cmpint (natural, ==, 100);
gtk_layout_manager_allocate (layout, parent, 100, 100, 0);
g_assert_cmpint (child1->width, ==, 50);
g_assert_cmpint (child2->width, ==, 50);
g_assert_cmpint (child3->width, ==, 100);
g_assert_cmpint (child1->height, ==, 50);
g_assert_cmpint (child2->height, ==, 50);
g_assert_cmpint (child3->height, ==, 50);
gtk_widget_unparent (GTK_WIDGET (child1));
gtk_widget_unparent (GTK_WIDGET (child2));
gtk_widget_unparent (GTK_WIDGET (child3));
gtk_widget_destroy (parent);
}
int
main (int argc,
char *argv[])
{
gtk_test_init (&argc, &argv);
g_test_add_func ("/grid-layout/row", test_simple_row);
g_test_add_func ("/grid-layout/column", test_simple_column);
g_test_add_func ("/grid-layout/span", test_spans);
g_test_add_func ("/grid-layout/homogeneous", test_homogeneous);
g_test_add_func ("/grid-layout/simple", test_simple_layout);
return g_test_run();
}
+1 -1
View File
@@ -17,7 +17,6 @@ tests = [
['builderparser'],
['cellarea'],
['check-icon-names'],
['constraint-layout'],
['constraint-solver', [
'../../gtk/gtkconstraintsolver.c',
'../../gtk/gtkconstraintexpression.c',
@@ -34,6 +33,7 @@ tests = [
['focus'],
['gestures'],
['grid'],
['grid-layout'],
['gtkmenu'],
['icontheme'],
['keyhash', ['../../gtk/gtkkeyhash.c', gtkresources, '../../gtk/gtkprivate.c'], gtk_cargs],