Compare commits

..

171 Commits

Author SHA1 Message Date
Emmanuele Bassi 74ee566fbd tests/notify: Always print the diagnostic messages
We're using the TAP mode of GTest, so we can always emit diagnostic
messages using g_test_message(), without necessarily caring about
verbosity.
2019-07-17 16:23:51 +01:00
Matthias Clasen e816d5afb7 Don't leak layout parser data
Reported in https://gitlab.gnome.org/GNOME/gtk/issues/2022
2019-07-17 15:46:53 +01:00
Timm Bäder 24a4063645 scrollbar: Use a box layout
Makes a lot more sense than the intermediate box just for its layout.
2019-07-15 07:52:42 +02:00
Timm Bäder 4f11bbc59b text: Don't leak emoji chooser 2019-07-15 06:56:19 +02:00
Timm Bäder 9ceb41f9a4 menu: Fix an uninitialized value
If the menu does not have any children, we'd otherwise end up calling
g_object_ref() on an uninitialized value.
2019-07-15 06:43:25 +02:00
Timm Bäder 831309eed2 progressbar: Use box layout
Instead of the custom layouting we did before.
2019-07-15 06:38:51 +02:00
Timm Bäder 4bb4a98493 text: Move some locals into the closest scope 2019-07-15 05:38:25 +02:00
Timm Bäder 70b0f712ad text: Remove some useless casts 2019-07-15 05:19:02 +02:00
Timm Bäder c6e9372ba3 text: Move some locals into the closest scope 2019-07-15 05:17:46 +02:00
Jordi Mas 13b055ab2d Update Catalan translation 2019-07-14 11:25:12 +02:00
Timm Bäder 38f4a7708e Remove some dead assignments 2019-07-14 10:08:04 +02:00
Timm Bäder 6abcd8d013 Adwaita: Add fontbutton spacing back 2019-07-14 10:08:04 +02:00
Timm Bäder 37906a2200 adwaita: Remove a dead rule
GtkFileChooserButtons are called "filechooserbutton" these days, not
button.file
2019-07-14 10:08:04 +02:00
Timm Bäder b9b5072668 gl renderer: Fix opacity nodes with overlapping child nodes 2019-07-14 10:08:04 +02:00
Aurimas Černius 459edfa77b Updated Lithuanian translation 2019-07-13 18:28:21 +03:00
Timm Bäder 92a79d3f96 popover: Fix a broken cast
The widget passed here is priv->relative_to, not the popover.
2019-07-13 17:06:22 +02:00
Timm Bäder 984dff54ab rendernodeparser: fix typo 2019-07-13 11:12:47 +02:00
Timm Bäder 1866aa93e3 fishbowl: Plug a small leak 2019-07-13 10:10:17 +02:00
Timm Bäder 2884691740 picture: Unref previous paintable
We were leaking all of them.
2019-07-13 09:38:28 +02:00
Timm Bäder b8549a142e suppression file: Add glReadPixels mesa exception 2019-07-13 09:38:14 +02:00
Timm Bäder 0f3ca349e7 node editor: Manually unrealize all created renderers
This has not been a problem before since we were leaking them.
2019-07-13 09:37:47 +02:00
Timm Bäder a13d6bbbdf Merge branch 'fix-issue-2014-gtk4' into 'master'
Fix a string leak in gtkemojicompletion.c [gtk4]

Closes #2014

See merge request GNOME/gtk!993
2019-07-12 09:59:38 +00:00
Luca Bacci d15dc6f90b Fix a string leak
Fixes #2014
2019-07-12 08:43:44 +00:00
Timm Bäder 58e6c277b0 fpsoverlay: Fix fps overlay position 2019-07-10 18:34:16 +02:00
Matthias Clasen 1d29d44ddb Merge branch 'wip/baedert/accelmap' into 'master'
AccelMap: Sort accels before iterating over them in foreach()

See merge request GNOME/gtk!980
2019-07-09 19:39:58 +00:00
Matthias Clasen bda3c6c084 Merge branch 'wip/baedert/for-master' into 'master'
Improve the valgrind experience

See merge request GNOME/gtk!984
2019-07-09 19:39:13 +00:00
Kukuh Syafaat 159913be2f Update Indonesian translation 2019-07-09 07:56:21 +00:00
Asier Sarasua Garmendia b05d1676d3 Update Basque translation 2019-07-08 20:19:10 +00:00
Asier Sarasua Garmendia 0b21ed0c7a Update Basque translation 2019-07-08 20:14:08 +00:00
Asier Sarasua Garmendia 564a92830b Update Basque translation 2019-07-08 19:18:08 +00:00
Chun-wei Fan a20fd5e14e demos/constraint-editor: Fix linking on MSVC builds
We must apply the /entry:mainCRTStartup linker flag in order to link GTK
apps in pure GUI form.  This follows what is done in demos/gtk-demo,
etc.
2019-07-08 18:37:27 +08:00
Timm Bäder 138986f064 Merge branch 'ui-enum-values' into 'master'
Change the few examples that use a full GTK_ enum value in .ui files.

See merge request GNOME/gtk!987
2019-07-08 07:14:48 +00:00
Timm Bäder f286c99338 Merge branch 'gltexsubimage2d' into 'master'
use glTexSubImage2D instead of glTextureSubImage2D

Closes #2005

See merge request GNOME/gtk!986
2019-07-08 07:14:13 +00:00
Timm Bäder ea48d1de5e Merge branch 'glsl-float-literals' into 'master'
glsl: use float literals

See merge request GNOME/gtk!985
2019-07-08 07:10:41 +00:00
Robert Ancell dbd2a81501 Change the few examples that use a full GTK_ enum value in .ui files.
Lowercase versions work just as well and are much more readable.
2019-07-08 15:52:28 +12:00
Piotr Drąg be6ec8f50b Update Polish translation 2019-07-07 13:22:10 +02:00
Timm Bäder 264d4bada6 widget: Remove queue_resize_no_redraw
We always invalidate the widget in size_allocate() anyway.
2019-07-07 07:43:08 +02:00
Timm Bäder 633172fd66 widget: Make queue_compute_expand() private
Nobody needs to call this anymore.
2019-07-07 07:36:29 +02:00
Timm Bäder 042f7d117f compare-render: Don't unref an invalid GFile
We already unref it when the g_file_make_directory_with_parents fails.
2019-07-07 07:24:00 +02:00
Timm Bäder b062594ae6 gl renderer: Properly clean up program state transforms 2019-07-07 07:24:00 +02:00
Timm Bäder 95f30fee87 iconhelper: Try to avoid some save/restore calls
GtkImage already does something similar so we often end up with 0/0
here. Avoid the save()/restore() calls in GtkSnapshot in that case.
2019-07-07 07:24:00 +02:00
Timm Bäder dbc49e7742 transform: Fix identity transform fast paths
Returning an extra ref will cause leaks later.
2019-07-07 07:24:00 +02:00
Timm Bäder 449c96ffb3 widget: Unref previous transform 2019-07-07 07:24:00 +02:00
Timm Bäder 1459ca2c26 widget factory: Plug a memory leak 2019-07-07 07:24:00 +02:00
Timm Bäder 4123c85021 actionmuxer: Plug a memory leak 2019-07-07 07:24:00 +02:00
Timm Bäder d1c37c41d9 Add a gtk valgrind suppression file
Not ideal but otherwise I get 30k line output from valgrind when just
running the widget factory. It's mostly mesa but still.
2019-07-07 07:23:57 +02:00
Elias Aebi ea6d3f589f use glTexSubImage2D instead of glTextureSubImage2D 2019-07-06 16:23:21 +02:00
Elias Aebi 1e6120e776 glsl: use float literals 2019-07-06 14:42:08 +02:00
Timm Bäder a77f8e886b cssprovider: Fix a memory leak in load_internal
We create a new GBytes but never unref it.
2019-07-06 09:50:07 +02:00
Benjamin Otte 96b782c026 x11: Make sure stream stays alive long enough
When unreffing the stream from a different thread, the close function
will schedule its cleanup asynchornously in the main thread.
We need to make sure the stream object stays alive for as long as
that hasn't happened, so ref() it.

Fixes #2003
2019-07-05 21:17:00 +02:00
Timm Bäder 6455a54f6c Merge branch 'header-custom-title-valign' into 'master'
headerbar: Don't change the custom title's valign

See merge request GNOME/gtk!981
2019-07-04 12:45:13 +00:00
Adrien Plazas 3bae6fa1c7 headerbar: Don't change the custom title's valign
This allows custom titles to use the vertical alignment of their choice
without having to set it manually after it has been added to the header
bar, hence allowing them to define their preferred alignment from a UI
template.

This is useful for widgets like the view switcher which requires filling
the header bar's whole height.
2019-07-04 13:03:37 +02:00
Timm Bäder 68f19a8e6a accelmap: Sort accels before interating over them in foreach() 2019-07-04 08:35:42 +02:00
Timm Bäder 12ebbd1b24 accelmap: Avoid a confusing goto 2019-07-04 08:35:34 +02:00
Emmanuele Bassi 9b7bda6137 ci: Comment job, not just the stage
GitLab doesn't like it when we keep a job but disable the stage.
2019-07-03 17:57:27 +01:00
Emmanuele Bassi 1b4ed58331 ci: Disable deploy jobs
The version of gtk-doc in our CI image is not new enough to cope with
the fact that GTK lost container properties.
2019-07-03 17:54:32 +01:00
Benjamin Otte b2868d7218 Merge branch 'wip/frame-clock-consumers' into 'master'
Frame clock consumers

See merge request GNOME/gtk!971
2019-07-03 16:21:32 +00:00
Emmanuele Bassi bdc8f9dccf Merge branch 'layout-manager-ref' into 'master'
widget: Don't lose a layout manager ref

See merge request GNOME/gtk!977
2019-07-03 13:25:44 +00:00
Matthias Clasen 9768f35931 widget: Don't lose a layout manager ref
gtk_widget_set_layout_manager is transfer-full,
so we must give it a new reference from set_property
to implement object property semantics properly.
2019-07-03 09:18:41 -04:00
Daniel Mustieles 19a4ee031d Updated Spanish translation 2019-07-03 11:45:12 +02:00
Jonas Ådahl a7ee1b4e85 gdksurface: Make all surfaces listen to the frame clock signals
Instead of the toplevel driving popups, have the popups listen to the
frame clock themselves. Otherwise, if the toplevel for some reason isn't
drawn by the compositor and stops drawing new frames, popups wouldn't
get painted either.
2019-07-03 11:42:28 +02:00
Jonas Ådahl 5db079b052 gdk/frameclock: Make surfaces inhibit freeze
To make a frame clock tick as long as any of the associated surfaces
expect to receive ticks, make the surfaces inhibit freezing the clock,
instead of directly tell the frame clock to freeze itself.

This makes it so that as long as any surface using a certain frame clock
is not frozen (e.g. just received a frame event from the display
server), the frame clock will not be frozen.

With this, the frame clock is initiated as frozen, and won't be thawed
until any surface inhibits freeze. It will be frozen again, when every
surface has that previously inhibited freeze uninhibited freeze.
2019-07-03 11:42:28 +02:00
Jonas Ådahl a2ff6af4b3 tests: Add back testpopupat
It's still useful for testing menus. Fixed the .ui file by removing a
property that no longer exists.

This effectively reverts commit
84d2150077.
2019-07-03 11:42:28 +02:00
Jonas Ådahl f66e764855 menu: Remove unused variable 2019-07-03 11:42:28 +02:00
Mohammed Sadiq a8c23d06ac constraint: Fix property name typo in doc 2019-07-03 09:31:39 +05:30
Piotr Drąg 36b4cd4bfc Update POTFILES.in and POTFILES.skip 2019-07-02 19:02:36 +02:00
Matej Urbančič 46c59e3c3d Updated Slovenian translation 2019-07-02 18:51:55 +02: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
137 changed files with 23845 additions and 11810 deletions
+17 -18
View File
@@ -1,7 +1,7 @@
stages:
- build
- flatpak
- deploy
# - deploy
.cache-paths: &cache-paths
paths:
@@ -101,20 +101,19 @@ flatpak-master:icon-browser:
APPID: org.gtk.IconBrowser4
<<: *flatpak-master
pages:
image: registry.gitlab.gnome.org/gnome/gtk/master:v6
stage: deploy
script:
- meson -Ddocumentation=true _build .
- ninja -C _build
- ninja -C _build gdk4-doc gsk4-doc gtk4-doc
- mkdir -p public/
- mv _build/docs/reference/gtk/html/ public/gtk/
- mv _build/docs/reference/gdk/html/ public/gdk/
- mv _build/docs/reference/gsk/html/ public/gsk/
artifacts:
paths:
- public
only:
- master
#pages:
# image: registry.gitlab.gnome.org/gnome/gtk/master:v6
# stage: deploy
# script:
# - meson -Dgtk_doc=true _build .
# - ninja -C _build
# - ninja -C _build gdk4-doc gsk4-doc gtk4-doc
# - mkdir -p public/
# - mv _build/docs/reference/gtk/html/ public/gtk/
# - mv _build/docs/reference/gdk/html/ public/gdk/
# - mv _build/docs/reference/gsk/html/ public/gsk/
# artifacts:
# paths:
# - public
# only:
# - master
-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>
@@ -0,0 +1,34 @@
/*
* Copyright © 2019 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#pragma once
#include <gtk/gtk.h>
#define CONSTRAINT_EDITOR_TYPE (constraint_editor_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintEditor, constraint_editor, CONSTRAINT, EDITOR, GtkWidget)
ConstraintEditor * constraint_editor_new (GListModel *model,
GtkConstraint *constraint);
void constraint_editor_serialize_constraint (GString *str,
int indent,
GtkConstraint *constraint);
char *constraint_editor_constraint_to_string (GtkConstraint *constraint);
@@ -0,0 +1,163 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ConstraintEditor" parent="GtkWidget">
<child>
<object class="GtkGrid" id="grid">
<property name="margin">20</property>
<property name="row-spacing">10</property>
<property name="column-spacing">10</property>
<child>
<object class="GtkLabel">
<property name="label">Target</property>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkComboBoxText" id="target">
<signal name="changed" handler="update_preview" swapped="yes"/>
<signal name="changed" handler="update_button" swapped="yes"/>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkComboBoxText" id="target_attr">
<signal name="changed" handler="update_preview" swapped="yes"/>
<layout>
<property name="left-attach">2</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Relation</property>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkComboBoxText" id="relation">
<signal name="changed" handler="update_preview" swapped="yes"/>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Source</property>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkComboBoxText" id="source">
<signal name="changed" handler="update_preview" swapped="yes"/>
<signal name="changed" handler="update_button" swapped="yes"/>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkComboBoxText" id="source_attr">
<signal name="changed" handler="update_preview" swapped="yes"/>
<signal name="changed" handler="source_attr_changed" swapped="yes"/>
<layout>
<property name="left-attach">2</property>
<property name="top-attach">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Multiplier</property>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">4</property>
</layout>
</object>
</child>
<child>
<object class="GtkEntry" id="multiplier">
<signal name="changed" handler="update_preview" swapped="yes"/>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">4</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Constant</property>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">5</property>
</layout>
</object>
</child>
<child>
<object class="GtkEntry" id="constant">
<signal name="changed" handler="update_preview" swapped="yes"/>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">5</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Strength</property>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">6</property>
</layout>
</object>
</child>
<child>
<object class="GtkComboBoxText" id="strength">
<layout>
<property name="left-attach">1</property>
<property name="top-attach">6</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel" id="preview">
<property name="xalign">0</property>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">7</property>
<property name="column-span">2</property>
</layout>
<attributes>
<attribute name="scale" value="1.44"/>
</attributes>
</object>
</child>
<child>
<object class="GtkButton" id="button">
<property name="label">Create</property>
<signal name="clicked" handler="create_constraint"/>
<layout>
<property name="left-attach">2</property>
<property name="top-attach">8</property>
</layout>
</object>
</child>
</object>
</child>
</template>
</interface>
@@ -0,0 +1,93 @@
/*
* Copyright © 2019 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#include "constraint-view-child.h"
struct _ConstraintViewChild
{
GObject parent_instance;
char *name;
};
enum {
PROP_NAME = 1,
LAST_PROP
};
static GParamSpec props[LAST_PROP];
G_DEFINE_TYPE (ConstraintViewChild, constraint_view_child, G_TYPE_OBJECT)
static void
constraint_view_child_init (ConstraintViewChild *child)
{
}
static void
constraint_view_child_finalize (GObject *object)
{
ConstraintViewChild *child = CONSTRAINT_VIEW_CHILD (object);
g_free (child->name);
G_OBJECT_CLASS (constraint_view_child_parent_class)->finalize (object);
}
static void
constraint_view_child_set_property (GObject *object,
static void
constraint_view_child_class_init (ConstraintViewChildClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->finalize = constraint_view_child_finalize;
object_class->get_property = constraint_view_child_get_property;
object_class->set_property = constraint_view_child_set_property;
props[PROP_NAME] =
g_param_spec_string ("name", "name", "name",
NULL,
G_PARAM_READWRITE);
g_object_class_install_properties (object_class, LAST_PROP, props);
}
#define CONSTRAINT_VIEW_CHILD_TYPE (constraint_view_get_type ())
G_DECLARE_TYPE (ConstraintViewChild, constraint_view_child, CONSTRAINT, VIEW_CHILD, GObject)
#define CONSTRAINT_VIEW_WIDGET_TYPE (constraint_view_widget_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewWidget, constraint_view_widget, CONSTRAINT, VIEW_WIDGET, ConstraintViewChild)
ConstraintViewWidget * constraint_view_widget_new (void);
#define CONSTRAINT_VIEW_GUIDE_TYPE (constraint_view_guide_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewGuide, constraint_view_guide, CONSTRAINT, VIEW_GUIDE, ConstraintViewChild)
ConstraintViewGuide * constraint_view_guide_new (void);
#define CONSTRAINT_VIEW_CONSTRAINT_TYPE (constraint_view_constraint_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewConstraint, constraint_view_constraint, CONSTRAINT, VIEW_CONSTRAINT, ConstraintViewChild)
ConstraintViewGuide * constraint_view_constraint_new (void);
@@ -0,0 +1,44 @@
/*
* Copyright © 2019 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#pragma once
#include <gtk/gtk.h>
#define CONSTRAINT_VIEW_CHILD_TYPE (constraint_view_get_type ())
G_DECLARE_TYPE (ConstraintViewChild, constraint_view_child, CONSTRAINT, VIEW_CHILD, GObject)
#define CONSTRAINT_VIEW_WIDGET_TYPE (constraint_view_widget_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewWidget, constraint_view_widget, CONSTRAINT, VIEW_WIDGET, ConstraintViewChild)
ConstraintViewWidget * constraint_view_widget_new (void);
#define CONSTRAINT_VIEW_GUIDE_TYPE (constraint_view_guide_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewGuide, constraint_view_guide, CONSTRAINT, VIEW_GUIDE, ConstraintViewChild)
ConstraintViewGuide * constraint_view_guide_new (void);
#define CONSTRAINT_VIEW_CONSTRAINT_TYPE (constraint_view_constraint_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewConstraint, constraint_view_constraint, CONSTRAINT, VIEW_CONSTRAINT, ConstraintViewChild)
ConstraintViewGuide * constraint_view_constraint_new (void);
+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);
}
+20
View File
@@ -0,0 +1,20 @@
constraint_editor_sources = [
'main.c',
'constraint-editor-application.c',
'constraint-editor-window.c',
'constraint-view.c',
'constraint-editor.c',
'guide-editor.c',
]
constraint_editor_resources = gnome.compile_resources('constraint_editor_resources',
'constraint-editor.gresource.xml',
source_dir: '.')
executable('gtk4-constraint-editor',
constraint_editor_sources, constraint_editor_resources,
dependencies: libgtk_dep,
include_directories: confinc,
gui_app: true,
link_args: extra_demo_ldflags,
install: false)
+22 -15
View File
@@ -44,20 +44,21 @@ simple_grid_class_init (SimpleGridClass *klass)
/* Layout:
*
* +-----------------------------+
* | +-----------+ +-----------+ |
* | | Child 1 | | Child 2 | |
* | +-----------+ +-----------+ |
* | +-------------------------+ |
* | | Child 3 | |
* | +-------------------------+ |
* +-----------------------------+
* +-------------------------------------+
* | +-----------++-------++-----------+ |
* | | Child 1 || Space || Child 2 | |
* | +-----------++-------++-----------+ |
* | +---------------------------------+ |
* | | Child 3 | |
* | +---------------------------------+ |
* +-------------------------------------+
*
* Constraints:
*
* super.start = child1.start - 8
* child1.width = child2.width
* child1.end = child2.start - 12
* child1.end = space.start
* space.end = child2.start
* child2.end = super.end - 8
* super.start = child3.start - 8
* child3.end = super.end - 8
@@ -69,6 +70,12 @@ simple_grid_class_init (SimpleGridClass *klass)
* child3.height = child2.height
* child3.bottom = super.bottom - 8
*
* To add some flexibility, we make the space
* stretchable:
*
* space.width >= 10
* space.width = 100
* space.width <= 200
*/
static void
build_constraints (SimpleGrid *self,
@@ -76,12 +83,12 @@ build_constraints (SimpleGrid *self,
{
GtkConstraintGuide *guide;
guide = g_object_new (GTK_TYPE_CONSTRAINT_GUIDE,
"min-width", 10,
"min-height", 10,
"nat-width", 100,
"nat-height", 10,
NULL);
guide = gtk_constraint_guide_new ();
gtk_constraint_guide_set_name (guide, "space");
gtk_constraint_guide_set_min_size (guide, 10, 10);
gtk_constraint_guide_set_nat_size (guide, 100, 10);
gtk_constraint_guide_set_max_size (guide, 200, 20);
gtk_constraint_guide_set_strength (guide, GTK_CONSTRAINT_STRENGTH_STRONG);
gtk_constraint_layout_add_guide (manager, guide);
gtk_constraint_layout_add_constraint (manager,
+165
View File
@@ -0,0 +1,165 @@
/* Constraints/VFL
*
* GtkConstraintLayout allows defining constraints using a
* compact syntax called Visual Format Language, or VFL.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
G_DECLARE_FINAL_TYPE (VflGrid, vfl_grid, VFL, GRID, GtkWidget)
struct _VflGrid
{
GtkWidget parent_instance;
GtkWidget *button1, *button2;
GtkWidget *button3;
};
G_DEFINE_TYPE (VflGrid, vfl_grid, GTK_TYPE_WIDGET)
static void
vfl_grid_destroy (GtkWidget *widget)
{
VflGrid *self = VFL_GRID (widget);
g_clear_pointer (&self->button1, gtk_widget_destroy);
g_clear_pointer (&self->button2, gtk_widget_destroy);
g_clear_pointer (&self->button3, gtk_widget_destroy);
GTK_WIDGET_CLASS (vfl_grid_parent_class)->destroy (widget);
}
static void
vfl_grid_class_init (VflGridClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
widget_class->destroy = vfl_grid_destroy;
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
}
/* Layout:
*
* +-----------------------------+
* | +-----------+ +-----------+ |
* | | Child 1 | | Child 2 | |
* | +-----------+ +-----------+ |
* | +-------------------------+ |
* | | Child 3 | |
* | +-------------------------+ |
* +-----------------------------+
*
* Constraints:
*
* super.start = child1.start - 8
* child1.width = child2.width
* child1.end = child2.start - 12
* child2.end = super.end - 8
* super.start = child3.start - 8
* child3.end = super.end - 8
* super.top = child1.top - 8
* super.top = child2.top - 8
* child1.bottom = child3.top - 12
* child2.bottom = child3.top - 12
* child3.height = child1.height
* child3.height = child2.height
* child3.bottom = super.bottom - 8
*
* Visual format:
*
* H:|-8-[view1(==view2)-12-[view2]-8-|
* H:|-8-[view3]-8-|
* V:|-8-[view1]-12-[view3(==view1)]-8-|
* V:|-8-[view2]-12-[view3(==view2)]-8-|
*/
static void
build_constraints (VflGrid *self,
GtkConstraintLayout *manager)
{
const char * const vfl[] = {
"H:|-[button1(==button2)]-12-[button2]-|",
"H:|-[button3]-|",
"V:|-[button1]-12-[button3(==button1)]-|",
"V:|-[button2]-12-[button3(==button2)]-|",
};
GError *error = NULL;
gtk_constraint_layout_add_constraints_from_description (manager, vfl, G_N_ELEMENTS (vfl),
8, 8,
&error,
"button1", self->button1,
"button2", self->button2,
"button3", self->button3,
NULL);
if (error != NULL)
{
g_printerr ("VFL parsing error:\n%s", error->message);
g_error_free (error);
}
}
static void
vfl_grid_init (VflGrid *self)
{
GtkWidget *widget = GTK_WIDGET (self);
self->button1 = gtk_button_new_with_label ("Child 1");
gtk_widget_set_parent (self->button1, widget);
gtk_widget_set_name (self->button1, "button1");
self->button2 = gtk_button_new_with_label ("Child 2");
gtk_widget_set_parent (self->button2, widget);
gtk_widget_set_name (self->button2, "button2");
self->button3 = gtk_button_new_with_label ("Child 3");
gtk_widget_set_parent (self->button3, widget);
gtk_widget_set_name (self->button3, "button3");
GtkLayoutManager *manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
build_constraints (self, GTK_CONSTRAINT_LAYOUT (manager));
}
GtkWidget *
do_constraints3 (GtkWidget *do_widget)
{
static GtkWidget *window;
if (!window)
{
GtkWidget *header, *box, *grid, *button;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
header = gtk_header_bar_new ();
gtk_header_bar_set_title (GTK_HEADER_BAR (header), "Constraints");
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
gtk_window_set_titlebar (GTK_WINDOW (window), header);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
gtk_container_add (GTK_CONTAINER (window), box);
grid = g_object_new (vfl_grid_get_type (), NULL);
gtk_widget_set_hexpand (grid, TRUE);
gtk_widget_set_vexpand (grid, TRUE);
gtk_container_add (GTK_CONTAINER (box), grid);
button = gtk_button_new_with_label ("Close");
gtk_container_add (GTK_CONTAINER (box), button);
gtk_widget_set_hexpand (grid, TRUE);
g_signal_connect_swapped (button, "clicked",
G_CALLBACK (gtk_widget_destroy), window);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_widget_destroy (window);
return window;
}
+1
View File
@@ -152,6 +152,7 @@
<file>combobox.c</file>
<file>constraints.c</file>
<file>constraints2.c</file>
<file>constraints3.c</file>
<file>css_accordion.c</file>
<file>css_basics.c</file>
<file>css_blendmodes.c</file>
+1
View File
@@ -306,6 +306,7 @@ do_fishbowl (GtkWidget *do_widget)
G_CALLBACK (gtk_widget_destroyed), &window);
gtk_widget_realize (window);
g_object_unref (builder);
}
if (!gtk_widget_get_visible (window))
+1
View File
@@ -10,6 +10,7 @@ demos = files([
'combobox.c',
'constraints.c',
'constraints2.c',
'constraints3.c',
'css_accordion.c',
'css_basics.c',
'css_blendmodes.c',
+1
View File
@@ -1,3 +1,4 @@
subdir('constraint-editor')
subdir('gtk-demo')
subdir('icon-browser')
subdir('node-editor')
+8
View File
@@ -707,6 +707,14 @@ static void
node_editor_window_unrealize (GtkWidget *widget)
{
NodeEditorWindow *self = NODE_EDITOR_WINDOW (widget);
guint i;
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (self->renderers)); i ++)
{
gpointer item = g_list_model_get_item (G_LIST_MODEL (self->renderers), i);
gsk_renderer_unrealize (gtk_renderer_paintable_get_renderer (item));
g_object_unref (item);
}
g_list_store_remove_all (self->renderers);
+3 -1
View File
@@ -1405,8 +1405,10 @@ text_view_add_to_context_menu (GtkTextView *text_view)
item = g_menu_item_new (_("Underline"), "format.underline");
g_menu_item_set_attribute (item, "touch-icon", "s", "format-text-underline-symbolic");
g_menu_append_item (G_MENU (menu), item);
g_object_unref (item);
gtk_text_view_set_extra_menu (text_view, G_MENU_MODEL (menu));
g_object_unref (menu);
g_signal_connect (gtk_text_view_get_buffer (text_view), "changed", G_CALLBACK (text_changed), NULL);
g_signal_connect (gtk_text_view_get_buffer (text_view), "mark-set", G_CALLBACK (text_changed), NULL);
@@ -1707,7 +1709,7 @@ activate (GApplication *app)
gtk_css_provider_load_from_resource (provider, "/org/gtk/WidgetFactory4/widget-factory.css");
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_USER);
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
g_object_unref (provider);
builder = gtk_builder_new_from_resource ("/org/gtk/WidgetFactory4/widget-factory.ui");
+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 -2
View File
@@ -4432,7 +4432,6 @@ gtk_widget_realize
gtk_widget_unrealize
gtk_widget_queue_draw
gtk_widget_queue_resize
gtk_widget_queue_resize_no_redraw
gtk_widget_queue_allocate
gtk_widget_get_frame_clock
gtk_widget_get_scale_factor
@@ -4604,7 +4603,6 @@ gtk_widget_get_vexpand
gtk_widget_set_vexpand
gtk_widget_get_vexpand_set
gtk_widget_set_vexpand_set
gtk_widget_queue_compute_expand
gtk_widget_compute_expand
<SUBSECTION Templates>
@@ -7287,3 +7285,87 @@ gtk_grid_layout_get_type
GTK_TYPE_GRID_LAYOUT_CHILD
gtk_grid_layout_child_get_type
</SECTION>
<SECTION>
<FILE>gtkconstraint</FILE>
GtkConstraint
GtkConstraintTarget
gtk_constraint_new
gtk_constraint_new_constant
gtk_constraint_get_target
GtkConstraintAttribute
gtk_constraint_get_target_attribute
GtkConstraintRelation
gtk_constraint_get_relation
gtk_constraint_get_source
gtk_constraint_get_source_attribute
gtk_constraint_get_multiplier
gtk_constraint_get_constant
GtkConstraintStrength
gtk_constraint_get_strength
gtk_constraint_is_required
gtk_constraint_is_attached
gtk_constraint_is_constant
<SUBSECTION Standard>
GTK_TYPE_CONSTRAINT
gtk_constraint_get_type
GTK_TYPE_CONSTRAINT_TARGET
gtk_constraint_target_get_type
</SECTION>
<SECTION>
<FILE>gtkconstraintlayout</FILE>
GtkConstraintLayout
GtkConstraintLayoutChild
GtkConstraintVflParserError
gtk_constraint_layout_new
<SUBSECTION Constraints>
gtk_constraint_layout_add_constraint
gtk_constraint_layout_remove_constraint
gtk_constraint_layout_remove_all_constraints
<SUBSECTION Guides>
gtk_constraint_layout_add_guide
gtk_constraint_layout_remove_guide
<SUBSECTION VFL>
gtk_constraint_layout_add_constraints_from_description
gtk_constraint_layout_add_constraints_from_descriptionv
<SUBSECTION>
gtk_constraint_layout_observe_constraints
gtk_constraint_layout_observe_guides
<SUBSECTION Standard>
GTK_TYPE_CONSTRAINT_LAYOUT
gtk_constraint_layout_get_type
GTK_TYPE_CONSTRAINT_LAYOUT_CHILD
gtk_constraint_layout_child_get_type
GTK_CONSTRAINT_VFL_PARSER_ERROR
gtk_constraint_vfl_parser_error_quark
</SECTION>
<SECTION>
<FILE>gtkconstraintguide</FILE>
GtkConstraintGuide
gtk_constraint_guide_new
gtk_constraint_guide_set_name
gtk_constraint_guide_get_name
gtk_constraint_guide_set_strength
gtk_constraint_guide_get_strength
gtk_constraint_guide_set_min_size
gtk_constraint_guide_get_min_size
gtk_constraint_guide_set_nat_size
gtk_constraint_guide_get_nat_size
gtk_constraint_guide_set_max_size
gtk_constraint_guide_get_max_size
<SUBSECTION Standard>
GTK_TYPE_CONSTRAINT_GUIDE
gtk_constraint_guide_get_tyoe
</SECTION>
+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',
+6 -6
View File
@@ -88,10 +88,10 @@ gdk_broadway_surface_finalize (GObject *object)
}
static gboolean
thaw_clock_cb (GdkFrameClock *clock)
thaw_updates_cb (GdkSurface *surface)
{
_gdk_frame_clock_thaw (clock);
g_object_unref (clock);
gdk_surface_thaw_updates (surface);
g_object_unref (surface);
return G_SOURCE_REMOVE;
}
@@ -109,9 +109,9 @@ _gdk_broadway_roundtrip_notify (GdkSurface *surface,
/* If there is no remote web client, rate limit update to once a second */
if (local_reply)
g_timeout_add_seconds (1, (GSourceFunc)thaw_clock_cb, g_object_ref (clock));
g_timeout_add_seconds (1, (GSourceFunc)thaw_updates_cb, g_object_ref (surface));
else
_gdk_frame_clock_thaw (clock);
gdk_surface_thaw_updates (surface);
if (timings)
{
@@ -140,7 +140,7 @@ on_frame_clock_after_paint (GdkFrameClock *clock,
GdkBroadwayDisplay *broadway_display;
impl->pending_frame_counter = gdk_frame_clock_get_frame_counter (clock);
_gdk_frame_clock_freeze (gdk_surface_get_frame_clock (surface));
gdk_surface_freeze_updates (surface);
broadway_display = GDK_BROADWAY_DISPLAY (display);
+44 -2
View File
@@ -97,10 +97,14 @@ struct _GdkFrameClockPrivate
gint n_timings;
gint current;
GdkFrameTimings *timings[FRAME_HISTORY_MAX_LENGTH];
gint n_freeze_inhibitors;
};
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GdkFrameClock, gdk_frame_clock, G_TYPE_OBJECT)
static void
_gdk_frame_clock_freeze (GdkFrameClock *clock);
static void
gdk_frame_clock_finalize (GObject *object)
{
@@ -114,12 +118,21 @@ gdk_frame_clock_finalize (GObject *object)
G_OBJECT_CLASS (gdk_frame_clock_parent_class)->finalize (object);
}
static void
gdk_frame_clock_constructed (GObject *object)
{
G_OBJECT_CLASS (gdk_frame_clock_parent_class)->constructed (object);
_gdk_frame_clock_freeze (GDK_FRAME_CLOCK (object));
}
static void
gdk_frame_clock_class_init (GdkFrameClockClass *klass)
{
GObjectClass *gobject_class = (GObjectClass*) klass;
gobject_class->finalize = gdk_frame_clock_finalize;
gobject_class->constructed = gdk_frame_clock_constructed;
/**
* GdkFrameClock::flush-events:
@@ -335,7 +348,7 @@ gdk_frame_clock_end_updating (GdkFrameClock *frame_clock)
GDK_FRAME_CLOCK_GET_CLASS (frame_clock)->end_updating (frame_clock);
}
void
static void
_gdk_frame_clock_freeze (GdkFrameClock *clock)
{
g_return_if_fail (GDK_IS_FRAME_CLOCK (clock));
@@ -344,7 +357,7 @@ _gdk_frame_clock_freeze (GdkFrameClock *clock)
}
void
static void
_gdk_frame_clock_thaw (GdkFrameClock *clock)
{
g_return_if_fail (GDK_IS_FRAME_CLOCK (clock));
@@ -352,6 +365,35 @@ _gdk_frame_clock_thaw (GdkFrameClock *clock)
GDK_FRAME_CLOCK_GET_CLASS (clock)->thaw (clock);
}
void
_gdk_frame_clock_inhibit_freeze (GdkFrameClock *clock)
{
GdkFrameClockPrivate *priv;
g_return_if_fail (GDK_IS_FRAME_CLOCK (clock));
priv = clock->priv;
priv->n_freeze_inhibitors++;
if (priv->n_freeze_inhibitors == 1)
_gdk_frame_clock_thaw (clock);
}
void
_gdk_frame_clock_uninhibit_freeze (GdkFrameClock *clock)
{
GdkFrameClockPrivate *priv;
g_return_if_fail (GDK_IS_FRAME_CLOCK (clock));
priv = clock->priv;
priv->n_freeze_inhibitors--;
if (priv->n_freeze_inhibitors == 0)
_gdk_frame_clock_freeze (clock);
}
/**
* gdk_frame_clock_get_frame_counter:
* @frame_clock: a #GdkFrameClock
+2 -2
View File
@@ -105,8 +105,8 @@ struct _GdkFrameTimings
guint slept_before : 1;
};
void _gdk_frame_clock_freeze (GdkFrameClock *clock);
void _gdk_frame_clock_thaw (GdkFrameClock *clock);
void _gdk_frame_clock_inhibit_freeze (GdkFrameClock *clock);
void _gdk_frame_clock_uninhibit_freeze (GdkFrameClock *clock);
void _gdk_frame_clock_begin_frame (GdkFrameClock *clock);
void _gdk_frame_clock_debug_print_timings (GdkFrameClock *clock,
+56 -42
View File
@@ -1341,10 +1341,14 @@ gdk_surface_schedule_update (GdkSurface *surface)
{
GdkFrameClock *frame_clock;
if (surface &&
(surface->update_freeze_count ||
gdk_surface_is_toplevel_frozen (surface)))
return;
g_return_if_fail (surface);
if (surface->update_freeze_count ||
gdk_surface_is_toplevel_frozen (surface))
{
surface->pending_schedule_update = TRUE;
return;
}
/* If there's no frame clock (a foreign surface), then the invalid
* region will just stick around unless gdk_surface_process_updates()
@@ -1400,7 +1404,6 @@ gdk_surface_paint_on_clock (GdkFrameClock *clock,
void *data)
{
GdkSurface *surface = GDK_SURFACE (data);
GList *l;
g_return_if_fail (GDK_IS_SURFACE (surface));
@@ -1421,9 +1424,6 @@ gdk_surface_paint_on_clock (GdkFrameClock *clock,
gdk_surface_remove_update_surface (surface);
}
for (l = surface->children; l; l = l->next)
gdk_surface_paint_on_clock (clock, l->data);
g_object_unref (surface);
}
@@ -1581,13 +1581,17 @@ gdk_surface_freeze_updates (GdkSurface *surface)
g_return_if_fail (GDK_IS_SURFACE (surface));
surface->update_freeze_count++;
if (surface->update_freeze_count == 1)
_gdk_frame_clock_uninhibit_freeze (surface->frame_clock);
}
/**
* gdk_surface_thaw_updates:
* @surface: a #GdkSurface
*
* Thaws a surface frozen with gdk_surface_freeze_updates().
* Thaws a surface frozen with gdk_surface_freeze_updates(). Note that this
* will not necessarily schedule updates if the surface freeze count reaches
* zero.
**/
void
gdk_surface_thaw_updates (GdkSurface *surface)
@@ -1597,7 +1601,15 @@ gdk_surface_thaw_updates (GdkSurface *surface)
g_return_if_fail (surface->update_freeze_count > 0);
if (--surface->update_freeze_count == 0)
gdk_surface_schedule_update (surface);
{
_gdk_frame_clock_inhibit_freeze (surface->frame_clock);
if (surface->pending_schedule_update)
{
surface->pending_schedule_update = FALSE;
gdk_surface_schedule_update (surface);
}
}
}
void
@@ -1606,7 +1618,7 @@ gdk_surface_freeze_toplevel_updates (GdkSurface *surface)
g_return_if_fail (GDK_IS_SURFACE (surface));
surface->update_and_descendants_freeze_count++;
_gdk_frame_clock_freeze (gdk_surface_get_frame_clock (surface));
gdk_surface_freeze_updates (surface);
}
void
@@ -1616,9 +1628,9 @@ gdk_surface_thaw_toplevel_updates (GdkSurface *surface)
g_return_if_fail (surface->update_and_descendants_freeze_count > 0);
surface->update_and_descendants_freeze_count--;
_gdk_frame_clock_thaw (gdk_surface_get_frame_clock (surface));
gdk_surface_schedule_update (surface);
gdk_surface_thaw_updates (surface);
}
/**
@@ -3703,40 +3715,42 @@ gdk_surface_set_frame_clock (GdkSurface *surface,
if (clock)
{
g_object_ref (clock);
if (surface->parent == NULL)
{
g_signal_connect (G_OBJECT (clock),
"flush-events",
G_CALLBACK (gdk_surface_flush_events),
surface);
g_signal_connect (G_OBJECT (clock),
"resume-events",
G_CALLBACK (gdk_surface_resume_events),
surface);
g_signal_connect (G_OBJECT (clock),
"paint",
G_CALLBACK (gdk_surface_paint_on_clock),
surface);
}
g_signal_connect (G_OBJECT (clock),
"flush-events",
G_CALLBACK (gdk_surface_flush_events),
surface);
g_signal_connect (G_OBJECT (clock),
"resume-events",
G_CALLBACK (gdk_surface_resume_events),
surface);
g_signal_connect (G_OBJECT (clock),
"paint",
G_CALLBACK (gdk_surface_paint_on_clock),
surface);
if (surface->update_freeze_count == 0)
_gdk_frame_clock_inhibit_freeze (clock);
}
if (surface->frame_clock)
{
if (surface->parent == NULL)
{
if (surface->frame_clock_events_paused)
gdk_surface_resume_events (surface->frame_clock, G_OBJECT (surface));
if (surface->frame_clock_events_paused)
gdk_surface_resume_events (surface->frame_clock, G_OBJECT (surface));
g_signal_handlers_disconnect_by_func (G_OBJECT (surface->frame_clock),
G_CALLBACK (gdk_surface_flush_events),
surface);
g_signal_handlers_disconnect_by_func (G_OBJECT (surface->frame_clock),
G_CALLBACK (gdk_surface_resume_events),
surface);
g_signal_handlers_disconnect_by_func (G_OBJECT (surface->frame_clock),
G_CALLBACK (gdk_surface_paint_on_clock),
surface);
if (surface->update_freeze_count == 0)
_gdk_frame_clock_uninhibit_freeze (surface->frame_clock);
g_signal_handlers_disconnect_by_func (G_OBJECT (surface->frame_clock),
G_CALLBACK (gdk_surface_flush_events),
surface);
g_signal_handlers_disconnect_by_func (G_OBJECT (surface->frame_clock),
G_CALLBACK (gdk_surface_resume_events),
surface);
g_signal_handlers_disconnect_by_func (G_OBJECT (surface->frame_clock),
G_CALLBACK (gdk_surface_paint_on_clock),
surface);
}
g_object_unref (surface->frame_clock);
}
+1
View File
@@ -49,6 +49,7 @@ struct _GdkSurface
cairo_region_t *update_area;
guint update_freeze_count;
gboolean pending_schedule_update;
/* This is the update_area that was in effect when the current expose
started. It may be smaller than the expose area if we'e painting
more than we have to, but it represents the "true" damage. */
+5 -8
View File
@@ -349,7 +349,7 @@ frame_callback (void *data,
return;
impl->awaiting_frame = FALSE;
_gdk_frame_clock_thaw (clock);
gdk_surface_thaw_updates (surface);
timings = gdk_frame_clock_get_timings (clock, impl->pending_frame_counter);
impl->pending_frame_counter = 0;
@@ -465,8 +465,9 @@ on_frame_clock_after_paint (GdkFrameClock *clock,
g_signal_emit (impl, signals[COMMITTED], 0);
}
if (impl->awaiting_frame)
_gdk_frame_clock_freeze (clock);
if (impl->awaiting_frame &&
impl->pending_frame_counter == gdk_frame_clock_get_frame_counter (clock))
gdk_surface_freeze_updates (surface);
}
void
@@ -2577,12 +2578,8 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface)
if (impl->awaiting_frame)
{
GdkFrameClock *frame_clock;
impl->awaiting_frame = FALSE;
frame_clock = gdk_surface_get_frame_clock (surface);
if (frame_clock)
_gdk_frame_clock_thaw (frame_clock);
gdk_surface_thaw_updates (surface);
}
if (impl->display_server.gtk_surface)
+2 -2
View File
@@ -874,7 +874,7 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
surface_impl->toplevel->frame_pending)
{
surface_impl->toplevel->frame_pending = FALSE;
_gdk_frame_clock_thaw (gdk_surface_get_frame_clock (event->any.surface));
gdk_surface_thaw_updates (event->any.surface);
}
if (toplevel)
@@ -1238,7 +1238,7 @@ _gdk_wm_protocols_filter (const XEvent *xevent,
if (surface_impl->toplevel->frame_pending)
{
surface_impl->toplevel->frame_pending = FALSE;
_gdk_frame_clock_thaw (clock);
gdk_surface_thaw_updates (event->any.surface);
}
gdk_frame_clock_get_refresh_info (clock,
+2 -1
View File
@@ -503,6 +503,7 @@ gdk_x11_selection_output_stream_invoke_close (gpointer stream)
g_signal_handlers_disconnect_by_func (priv->display,
gdk_x11_selection_output_stream_xevent,
stream);
g_object_unref (stream);
return G_SOURCE_REMOVE;
}
@@ -512,7 +513,7 @@ gdk_x11_selection_output_stream_close (GOutputStream *stream,
GCancellable *cancellable,
GError **error)
{
g_main_context_invoke (NULL, gdk_x11_selection_output_stream_invoke_close, stream);
g_main_context_invoke (NULL, gdk_x11_selection_output_stream_invoke_close, g_object_ref (stream));
return TRUE;
}
+1 -1
View File
@@ -397,7 +397,7 @@ gdk_x11_surface_end_frame (GdkSurface *surface)
g_intern_static_string ("_NET_WM_FRAME_DRAWN")))
{
impl->toplevel->frame_pending = TRUE;
_gdk_frame_clock_freeze (gdk_surface_get_frame_clock (surface));
gdk_surface_freeze_updates (surface);
timings->cookie = impl->toplevel->current_counter_value;
}
}
+4 -4
View File
@@ -193,10 +193,10 @@ upload_glyph (GlyphCacheKey *key,
if (render_glyph (key, value, &r))
{
glBindTexture (GL_TEXTURE_2D, value->texture_id);
glTextureSubImage2D (value->texture_id, 0,
r.x, r.y, r.width, r.height,
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
r.data);
glTexSubImage2D (GL_TEXTURE_2D, 0,
r.x, r.y, r.width, r.height,
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
r.data);
g_free (r.data);
}
+1 -1
View File
@@ -136,7 +136,7 @@ upload_region_or_else (GskGLIconCache *self,
GskImageRegion *region)
{
glBindTexture (GL_TEXTURE_2D, texture_id);
glTextureSubImage2D (texture_id, 0, region->x, region->y, region->width, region->height,
glTexSubImage2D (GL_TEXTURE_2D, 0, region->x, region->y, region->width, region->height,
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, region->data);
}
+44 -8
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);
@@ -1017,12 +1015,49 @@ render_opacity_node (GskGLRenderer *self,
GskRenderNode *node,
RenderOpBuilder *builder)
{
GskRenderNode *child = gsk_opacity_node_get_child (node);
const float opacity = gsk_opacity_node_get_opacity (node);
float prev_opacity;
prev_opacity = ops_set_opacity (builder,
builder->current_opacity * gsk_opacity_node_get_opacity (node));
if (gsk_render_node_get_node_type (child) == GSK_CONTAINER_NODE)
{
const float min_x = builder->dx + node->bounds.origin.x;
const float min_y = builder->dy + node->bounds.origin.y;
const float max_x = min_x + node->bounds.size.width;
const float max_y = min_y + node->bounds.size.height;
gboolean is_offscreen;
TextureRegion region;
gsk_gl_renderer_add_render_ops (self, gsk_opacity_node_get_child (node), builder);
/* The semantics of an opacity node mandate that when, e.g., two color nodes overlap,
* there may not be any blending between them */
add_offscreen_ops (self, builder, &child->bounds,
child,
&region, &is_offscreen,
FORCE_OFFSCREEN | RESET_OPACITY | RESET_CLIP);
prev_opacity = ops_set_opacity (builder,
builder->current_opacity * opacity);
ops_set_program (builder, &self->blit_program);
ops_set_texture (builder, region.texture_id);
ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
{ { min_x, min_y }, { region.x, region.y2 }, },
{ { min_x, max_y }, { region.x, region.y }, },
{ { max_x, min_y }, { region.x2, region.y2 }, },
{ { max_x, max_y }, { region.x2, region.y }, },
{ { min_x, max_y }, { region.x, region.y }, },
{ { max_x, min_y }, { region.x2, region.y2 }, },
});
}
else
{
prev_opacity = ops_set_opacity (builder,
builder->current_opacity * opacity);
gsk_gl_renderer_add_render_ops (self, child, builder);
}
ops_set_opacity (builder, prev_opacity);
}
@@ -1292,7 +1327,7 @@ render_rounded_clip_node (GskGLRenderer *self,
{ { min_x, min_y }, { 0, 1 }, },
{ { min_x, max_y }, { 0, 0 }, },
{ { max_x, min_y }, { 1, 1 }, },
{ { max_x, max_y }, { 1, 0 }, },
{ { min_x, max_y }, { 0, 0 }, },
{ { max_x, min_y }, { 1, 1 }, },
@@ -2344,6 +2379,7 @@ gsk_gl_renderer_dispose (GObject *gobject)
GskGLRenderer *self = GSK_GL_RENDERER (gobject);
g_clear_pointer (&self->render_ops, g_array_unref);
ops_free (&self->op_builder);
G_OBJECT_CLASS (gsk_gl_renderer_parent_class)->dispose (gobject);
}
+15
View File
@@ -187,6 +187,17 @@ ops_init (RenderOpBuilder *builder)
}
}
void
ops_free (RenderOpBuilder *builder)
{
int i;
for (i = 0; i < GL_N_PROGRAMS; i ++)
{
gsk_transform_unref (builder->program_state[i].modelview);
}
}
void
ops_set_program (RenderOpBuilder *builder,
const Program *program)
@@ -225,6 +236,7 @@ ops_set_program (RenderOpBuilder *builder,
op.op = OP_CHANGE_MODELVIEW;
gsk_transform_to_matrix (builder->current_modelview, &op.modelview);
g_array_append_val (builder->render_ops, op);
gsk_transform_unref (program_state->modelview);
program_state->modelview = gsk_transform_ref (builder->current_modelview);
}
@@ -339,9 +351,12 @@ ops_set_modelview_internal (RenderOpBuilder *builder,
RenderOp op;
graphene_matrix_t matrix;
#if 0
XXX This is not possible if we want pop() to work.
if (builder->current_program &&
gsk_transform_equal (builder->current_program_state->modelview, transform))
return;
#endif
gsk_transform_to_matrix (transform, &matrix);
+1
View File
@@ -290,6 +290,7 @@ void ops_dump_framebuffer (RenderOpBuilder *builder,
int width,
int height);
void ops_init (RenderOpBuilder *builder);
void ops_free (RenderOpBuilder *builder);
void ops_push_debug_group (RenderOpBuilder *builder,
const char *text);
void ops_pop_debug_group (RenderOpBuilder *builder);
+1 -1
View File
@@ -817,7 +817,7 @@ parse_container_node (GtkCssParser *parser)
token = gtk_css_parser_get_token (parser))
{
node = NULL;
/* We don't wand a semicolon here, but the parse_node function will figure
/* We don't want a semicolon here, but the parse_node function will figure
* that out itself and return an error if we encounter one.
*/
gtk_css_parser_start_semicolon_block (parser, GTK_CSS_TOKEN_OPEN_CURLY);
+49 -9
View File
@@ -646,7 +646,7 @@ gsk_transform_translate_3d (GskTransform *next,
GskTranslateTransform *result;
if (graphene_point3d_equal (point, graphene_point3d_zero ()))
return gsk_transform_ref (next);
return next;
if (gsk_transform_has_class (next, &GSK_TRANSLATE_TRANSFORM_CLASS))
{
@@ -801,7 +801,7 @@ gsk_transform_rotate (GskTransform *next,
GskRotateTransform *result;
if (angle == 0.0f)
return gsk_transform_ref (next);
return next;
if (gsk_transform_has_class (next, &GSK_ROTATE_TRANSFORM_CLASS))
{
@@ -932,7 +932,7 @@ gsk_transform_rotate_3d (GskTransform *next,
return gsk_transform_rotate (next, angle);
if (angle == 0.0f)
return gsk_transform_ref (next);
return next;
result = gsk_transform_alloc (&GSK_ROTATE3D_TRANSFORM_CLASS,
GSK_TRANSFORM_CATEGORY_3D,
@@ -1121,7 +1121,7 @@ gsk_transform_scale_3d (GskTransform *next,
GskScaleTransform *result;
if (factor_x == 1 && factor_y == 1 && factor_z == 1)
return gsk_transform_ref (next);
return next;
if (gsk_transform_has_class (next, &GSK_SCALE_TRANSFORM_CLASS))
{
@@ -1250,7 +1250,7 @@ gsk_transform_perspective (GskTransform *next,
float depth)
{
GskPerspectiveTransform *result;
if (gsk_transform_has_class (next, &GSK_PERSPECTIVE_TRANSFORM_CLASS))
{
GskTransform *r = gsk_transform_perspective (gsk_transform_ref (next->next),
@@ -1690,11 +1690,26 @@ gsk_transform_transform_bounds (GskTransform *self,
}
break;
case GSK_TRANSFORM_CATEGORY_2D_AFFINE:
{
float dx, dy, scale_x, scale_y;
gsk_transform_to_affine (self, &scale_x, &scale_y, &dx, &dy);
*out_rect = *rect;
out_rect->origin.x *= scale_x;
out_rect->origin.y *= scale_y;
out_rect->size.width *= scale_x;
out_rect->size.height *= scale_y;
out_rect->origin.x += dx;
out_rect->origin.y += dy;
}
break;
case GSK_TRANSFORM_CATEGORY_UNKNOWN:
case GSK_TRANSFORM_CATEGORY_ANY:
case GSK_TRANSFORM_CATEGORY_3D:
case GSK_TRANSFORM_CATEGORY_2D:
case GSK_TRANSFORM_CATEGORY_2D_AFFINE:
default:
{
graphene_matrix_t mat;
@@ -1886,18 +1901,43 @@ gsk_transform_parser_parse (GtkCssParser *parser,
transform = gsk_transform_translate_3d (transform, &GRAPHENE_POINT3D_INIT (0.f, 0.f, f[0]));
}
#if 0
/* FIXME: add these */
else if (gtk_css_token_is_function (token, "skew"))
{
graphene_matrix_t matrix;
if (!gtk_css_parser_consume_function (parser, 2, 2, gsk_transform_parse_float, f))
goto fail;
f[0] = f[0] / 180.0 * G_PI;
f[1] = f[1] / 180.0 * G_PI;
graphene_matrix_init_skew (&matrix, f[0], f[1]);
transform = gsk_transform_matrix (transform, &matrix);
}
else if (gtk_css_token_is_function (token, "skewX"))
{
graphene_matrix_t matrix;
if (!gtk_css_parser_consume_function (parser, 1, 1, gsk_transform_parse_float, f))
goto fail;
f[0] = f[0] / 180.0 * G_PI;
graphene_matrix_init_skew (&matrix, f[0], 0);
transform = gsk_transform_matrix (transform, &matrix);
}
else if (gtk_css_token_is_function (token, "skewY"))
{
graphene_matrix_t matrix;
if (!gtk_css_parser_consume_function (parser, 1, 1, gsk_transform_parse_float, f))
goto fail;
f[0] = f[0] / 180.0 * G_PI;
graphene_matrix_init_skew (&matrix, 0, f[0]);
transform = gsk_transform_matrix (transform, &matrix);
}
#endif
else
{
break;
+16 -16
View File
@@ -4,14 +4,14 @@ uniform sampler2D u_source2;
float
combine (float source, float backdrop)
{
return source + backdrop * (1 - source);
return source + backdrop * (1.0 - source);
}
vec4
composite (vec4 Cs, vec4 Cb, vec3 B)
{
float ao = Cs.a + Cb.a * (1 - Cs.a);
vec3 Co = (Cs.a*(1 - Cb.a)*Cs.rgb + Cs.a*Cb.a*B + (1 - Cs.a)*Cb.a*Cb.rgb) / ao;
float ao = Cs.a + Cb.a * (1.0 - Cs.a);
vec3 Co = (Cs.a*(1.0 - Cb.a)*Cs.rgb + Cs.a*Cb.a*B + (1.0 - Cs.a)*Cb.a*Cb.rgb) / ao;
return vec4(Co, ao);
}
@@ -43,9 +43,9 @@ float
hard_light (float source, float backdrop)
{
if (source <= 0.5)
return 2 * backdrop * source;
return 2.0 * backdrop * source;
else
return 2 * (backdrop + source - backdrop * source) - 1;
return 2.0 * (backdrop + source - backdrop * source) - 1.0;
}
vec4
@@ -63,14 +63,14 @@ soft_light (float source, float backdrop)
float db;
if (backdrop <= 0.25)
db = ((16 * backdrop - 12) * backdrop + 4) * backdrop;
db = ((16.0 * backdrop - 12.0) * backdrop + 4.0) * backdrop;
else
db = sqrt (backdrop);
if (source <= 0.5)
return backdrop - (1 - 2 * source) * backdrop * (1 - backdrop);
return backdrop - (1.0 - 2.0 * source) * backdrop * (1.0 - backdrop);
else
return backdrop + (2 * source - 1) * (db - backdrop);
return backdrop + (2.0 * source - 1.0) * (db - backdrop);
}
vec4
@@ -155,8 +155,8 @@ clip_color (vec3 c)
float l = lum (c);
float n = min (c.r, min (c.g, c.b));
float x = max (c.r, max (c.g, c.b));
if (n < 0) c = l + (((c - l) * l) / (l - n));
if (x > 1) c = l + (((c - l) * (1 - l)) / (x - l));
if (n < 0.0) c = l + (((c - l) * l) / (l - n));
if (x > 1.0) c = l + (((c - l) * (1.0 - l)) / (x - l));
return c;
}
@@ -189,12 +189,12 @@ set_sat (vec3 c, float s)
if (c.g == cmin)
{
res.b = ((c.b - cmin) * s) / (cmax - cmin);
res.g = 0;
res.g = 0.0;
}
else
{
res.g = ((c.g - cmin) * s) / (cmax - cmin);
res.b = 0;
res.b = 0.0;
}
res.r = s;
}
@@ -203,12 +203,12 @@ set_sat (vec3 c, float s)
if (c.r == cmin)
{
res.b = ((c.b - cmin) * s) / (cmax - cmin);
res.r = 0;
res.r = 0.0;
}
else
{
res.r = ((c.r - cmin) * s) / (cmax - cmin);
res.b = 0;
res.b = 0.0;
}
res.g = s;
}
@@ -217,12 +217,12 @@ set_sat (vec3 c, float s)
if (c.r == cmin)
{
res.g = ((c.g - cmin) * s) / (cmax - cmin);
res.r = 0;
res.r = 0.0;
}
else
{
res.r = ((c.r - cmin) * s) / (cmax - cmin);
res.g = 0;
res.g = 0.0;
}
res.b = s;
}
+163
View File
@@ -0,0 +1,163 @@
# Actual GTK things
{
GtkWidgetClass action GPtrArray
Memcheck:Leak
fun:malloc
fun:g_malloc
fun:g_slice_alloc
fun:g_ptr_array_sized_new
fun:g_ptr_array_new
fun:gtk_widget_class_add_action
}
{
GTK media extension gio modules
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
fun:g_malloc
fun:g_slice_alloc
fun:g_slice_alloc0
fun:g_type_create_instance
fun:g_object_new_internal
fun:g_object_new_with_properties
fun:g_object_new
fun:g_io_module_new
fun:g_io_modules_scan_all_in_directory_with_scope
fun:gtk_media_file_extension_init
}
# mesa driver stuff
{
i965 addr4
Memcheck:Addr4
obj:/usr/lib/dri/i965_dri.so*
}
{
i965 addr8
Memcheck:Addr8
obj:/usr/lib/dri/i965_dri.so*
}
{
i965 memcpy
Memcheck:Addr8
fun:memcpy*
obj:/usr/lib/dri/i965_dri.so*
}
{
i965 memcpy
Memcheck:Addr2
fun:memcpy*
obj:/usr/lib/dri/i965_dri.so*
}
{
mesa memcmp 8
Memcheck:Addr8
fun:*memcmp*
obj:/usr/lib/dri/i965_dri.so*
}
{
mesa memcmp 1
Memcheck:Addr1
fun:*memcmp*
obj:/usr/lib/dri/i965_dri.so*
}
{
mesa memset 8
Memcheck:Addr8
fun:*memset*
obj:/usr/lib/dri/i965_dri.so
}
{
mesa realpath
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
fun:realpath@@GLIBC_2.3
obj:*
obj:*
obj:*
obj:*
obj:*
obj:*
obj:*
obj:*
fun:epoxy_eglInitialize_global_rewrite_ptr
}
{
mesa calloc
Memcheck:Leak
match-leak-kinds: definite
fun:calloc
obj:*
obj:*
obj:*
obj:*
obj:*
obj:*
obj:*
obj:*
obj:*
fun:epoxy_eglInitialize_global_rewrite_ptr
}
{
mesa malloc
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
obj:/usr/lib/dri/i965_dri.so*
}
{
mesa glReadPixels
Memcheck:Addr16
obj:*
obj:*
obj:*
obj:*
obj:*
fun:epoxy_glReadPixels_global_rewrite_ptr
}
# Fontconfig
{
FcFontSetList
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
obj:/usr/lib/libfontconfig.so*
obj:/usr/lib/libfontconfig.so*
fun:FcFontSetList
}
{
FcFontRenderPrepare
Memcheck:Leak
match-leak-kinds: definite
fun:realloc
obj:/usr/lib/libfontconfig.so*
obj:/usr/lib/libfontconfig.so*
fun:FcFontRenderPrepare
}
# Pango
{
pango 1
Memcheck:Leak
match-leak-kinds: definite
fun:realloc
obj:/usr/lib/libfontconfig.so*
obj:/usr/lib/libfontconfig.so*
obj:/usr/lib/libcairo.so*
fun:pango_cairo_fc_font_map_fontset_key_substitute
}
+21 -5
View File
@@ -155,6 +155,16 @@ accel_entry_equal (gconstpointer key1,
return g_str_equal (entry1->accel_path, entry2->accel_path);
}
static int
accel_entry_compare (gconstpointer a,
gconstpointer b)
{
const AccelEntry *entry1 = a;
const AccelEntry *entry2 = b;
return strcmp (entry1->accel_path, entry2->accel_path);
}
static inline AccelEntry*
accel_path_lookup (const gchar *accel_path)
{
@@ -817,17 +827,23 @@ gtk_accel_map_foreach (gpointer data,
g_return_if_fail (foreach_func != NULL);
entries = g_hash_table_slist_values (accel_entry_ht);
entries = g_slist_sort (entries, accel_entry_compare);
for (slist = entries; slist; slist = slist->next)
{
AccelEntry *entry = slist->data;
gboolean changed = entry->accel_key != entry->std_accel_key || entry->accel_mods != entry->std_accel_mods;
gboolean skip = FALSE;
for (node = accel_filters; node; node = node->next)
if (g_pattern_match_string (node->data, entry->accel_path))
goto skip_accel;
foreach_func (data, entry->accel_path, entry->accel_key, entry->accel_mods, changed);
skip_accel:
/* noop */;
if (g_pattern_match_string (node->data, entry->accel_path))
{
skip = TRUE;
break;
}
if (!skip)
foreach_func (data, entry->accel_path, entry->accel_key, entry->accel_mods, changed);
}
g_slist_free (entries);
}
+2 -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,
@@ -810,6 +803,8 @@ gtk_action_muxer_finalize (GObject *object)
if (muxer->primary_accels)
g_hash_table_unref (muxer->primary_accels);
g_free (muxer->widget_actions_enabled);
G_OBJECT_CLASS (gtk_action_muxer_parent_class)
->finalize (object);
}
@@ -819,8 +814,6 @@ gtk_action_muxer_dispose (GObject *object)
{
GtkActionMuxer *muxer = GTK_ACTION_MUXER (object);
prop_actions_disconnect (muxer);
if (muxer->parent)
{
g_signal_handlers_disconnect_by_func (muxer->parent, gtk_action_muxer_action_added_to_parent, muxer);
-1
View File
@@ -289,7 +289,6 @@ gtk_builder_init (GtkBuilder *builder)
{
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (builder);
priv = gtk_builder_get_instance_private (builder);
priv->domain = NULL;
priv->objects = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_object_unref);
+2 -2
View File
@@ -3474,7 +3474,7 @@ gtk_calendar_set_detail_width_chars (GtkCalendar *calendar,
{
priv->detail_width_chars = chars;
g_object_notify (G_OBJECT (calendar), "detail-width-chars");
gtk_widget_queue_resize_no_redraw (GTK_WIDGET (calendar));
gtk_widget_queue_resize (GTK_WIDGET (calendar));
}
}
@@ -3498,7 +3498,7 @@ gtk_calendar_set_detail_height_rows (GtkCalendar *calendar,
{
priv->detail_height_rows = rows;
g_object_notify (G_OBJECT (calendar), "detail-height-rows");
gtk_widget_queue_resize_no_redraw (GTK_WIDGET (calendar));
gtk_widget_queue_resize (GTK_WIDGET (calendar));
}
}
-1
View File
@@ -408,7 +408,6 @@ gtk_cell_renderer_toggle_snapshot (GtkCellRenderer *cell,
GtkBorder padding, border;
GtkCssImageBuiltinType image_type;
context = gtk_widget_get_style_context (widget);
gtk_cell_renderer_toggle_get_size (cell, widget, cell_area,
&x_offset, &y_offset,
&width, &height);
-2
View File
@@ -537,8 +537,6 @@ gtk_color_chooser_widget_init (GtkColorChooserWidget *cc)
AtkObject *atk_obj;
gchar *text, *name;
priv = gtk_color_chooser_widget_get_instance_private (cc);
priv->use_alpha = TRUE;
gtk_orientable_set_orientation (GTK_ORIENTABLE (cc), GTK_ORIENTATION_VERTICAL);
+64 -67
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",
@@ -256,7 +256,7 @@ gtk_constraint_class_init (GtkConstraintClass *klass)
* GtkConstraint:multiplier:
*
* The multiplication factor to be applied to the
* #GtkConstraint:source-attribue.
* #GtkConstraint:source-attribute.
*/
obj_props[PROP_MULTIPLIER] =
g_param_spec_double ("multiplier",
@@ -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);
+51 -57
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
@@ -384,11 +371,8 @@ gtk_constraint_variable_is_dummy (const GtkConstraintVariable *variable)
* A set of variables.
*/
struct _GtkConstraintVariableSet {
/* HashSet<Variable>, owns a reference */
GHashTable *set;
/* List<Variable>, used for iterating */
GList *ordered_set;
/* List<Variable>, owns a reference */
GSequence *set;
/* Age of the set, to guard against mutations while iterating */
gint64 age;
@@ -405,8 +389,7 @@ gtk_constraint_variable_set_free (GtkConstraintVariableSet *set)
{
g_return_if_fail (set != NULL);
g_list_free (set->ordered_set);
g_hash_table_unref (set->set);
g_sequence_free (set->set);
g_free (set);
}
@@ -423,10 +406,7 @@ gtk_constraint_variable_set_new (void)
{
GtkConstraintVariableSet *res = g_new (GtkConstraintVariableSet, 1);
res->set = g_hash_table_new_full (NULL, NULL,
(GDestroyNotify) gtk_constraint_variable_unref,
NULL);
res->ordered_set = NULL;
res->set = g_sequence_new ((GDestroyNotify) gtk_constraint_variable_unref);
res->age = 0;
@@ -435,7 +415,8 @@ gtk_constraint_variable_set_new (void)
static int
sort_by_variable_id (gconstpointer a,
gconstpointer b)
gconstpointer b,
gpointer data)
{
const GtkConstraintVariable *va = a, *vb = b;
@@ -463,16 +444,17 @@ gboolean
gtk_constraint_variable_set_add (GtkConstraintVariableSet *set,
GtkConstraintVariable *variable)
{
if (g_hash_table_contains (set->set, variable))
return FALSE;
GSequenceIter *iter;
g_hash_table_add (set->set, gtk_constraint_variable_ref (variable));
iter = g_sequence_search (set->set, variable, sort_by_variable_id, NULL);
if (!g_sequence_iter_is_end (iter))
{
GtkConstraintVariable *v = g_sequence_get (iter);
if (v->_id == variable->_id)
return FALSE;
}
/* This is a tricky bit; the variables in the set must be ordered
* not by insertion, but by the incremental id of each variable,
* as that's the expected iteration order
*/
set->ordered_set = g_list_insert_sorted (set->ordered_set, variable, sort_by_variable_id);
g_sequence_insert_before (iter, gtk_constraint_variable_ref (variable));
set->age += 1;
@@ -495,10 +477,12 @@ gboolean
gtk_constraint_variable_set_remove (GtkConstraintVariableSet *set,
GtkConstraintVariable *variable)
{
if (g_hash_table_contains (set->set, variable))
GSequenceIter *iter;
iter = g_sequence_lookup (set->set, variable, sort_by_variable_id, NULL);
if (iter != NULL)
{
set->ordered_set = g_list_remove (set->ordered_set, variable);
g_hash_table_remove (set->set, variable);
g_sequence_remove (iter);
set->age += 1;
return TRUE;
@@ -518,7 +502,19 @@ gtk_constraint_variable_set_remove (GtkConstraintVariableSet *set,
int
gtk_constraint_variable_set_size (GtkConstraintVariableSet *set)
{
return g_hash_table_size (set->set);
return g_sequence_get_length (set->set);
}
gboolean
gtk_constraint_variable_set_is_empty (GtkConstraintVariableSet *set)
{
return g_sequence_is_empty (set->set);
}
gboolean
gtk_constraint_variable_set_is_singleton (GtkConstraintVariableSet *set)
{
return g_sequence_iter_next (g_sequence_get_begin_iter (set->set)) == g_sequence_get_end_iter (set->set);
}
/*< private >
@@ -529,7 +525,7 @@ gtk_constraint_variable_set_size (GtkConstraintVariableSet *set)
/* Keep in sync with GtkConstraintVariableSetIter */
typedef struct {
GtkConstraintVariableSet *set;
GList *current;
GSequenceIter *iter;
gint64 age;
} RealVariableSetIter;
@@ -552,7 +548,7 @@ gtk_constraint_variable_set_iter_init (GtkConstraintVariableSetIter *iter,
g_return_if_fail (set != NULL);
riter->set = set;
riter->current = NULL;
riter->iter = g_sequence_get_begin_iter (set->set);
riter->age = set->age;
}
@@ -576,15 +572,13 @@ gtk_constraint_variable_set_iter_next (GtkConstraintVariableSetIter *iter,
g_assert (riter->age == riter->set->age);
if (riter->current == NULL)
riter->current = riter->set->ordered_set;
else
riter->current = riter->current->next;
if (g_sequence_iter_is_end (riter->iter))
return FALSE;
if (riter->current != NULL)
*variable_p = riter->current->data;
*variable_p = g_sequence_get (riter->iter);
riter->iter = g_sequence_iter_next (riter->iter);
return riter->current != NULL;
return TRUE;
}
/*< private >
+8 -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);
@@ -97,6 +94,12 @@ gboolean
gtk_constraint_variable_set_remove (GtkConstraintVariableSet *set,
GtkConstraintVariable *variable);
gboolean
gtk_constraint_variable_set_is_empty (GtkConstraintVariableSet *set);
gboolean
gtk_constraint_variable_set_is_singleton (GtkConstraintVariableSet *set);
int
gtk_constraint_variable_set_size (GtkConstraintVariableSet *set);
+694
View File
@@ -0,0 +1,694 @@
/* gtkconstraintguide.c: Flexible space for constraints
* Copyright 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Matthias Clasen
*/
/**
* SECTION:gtkconstraintguide
* @Title: GtkConstraintGuide
* @Short_description: An invisible constraint target
*
* A #GtkConstraintGuide is an invisible layout element that can be
* used by widgets inside a #GtkConstraintLayout as a source or a target
* of a #GtkConstraint. Guides can be used like guidelines or as
* flexible space.
*
* Unlike a #GtkWidget, a #GtkConstraintGuide will not be drawn.
*/
#include "config.h"
#include "gtkconstraintguide.h"
#include "gtkconstraintguideprivate.h"
#include "gtkconstraintlayoutprivate.h"
#include "gtkconstraintexpressionprivate.h"
#include "gtkconstraintsolverprivate.h"
#include "gtkdebug.h"
#include "gtkintl.h"
#include "gtkprivate.h"
typedef enum {
MIN_WIDTH,
MIN_HEIGHT,
NAT_WIDTH,
NAT_HEIGHT,
MAX_WIDTH,
MAX_HEIGHT,
LAST_VALUE
} GuideValue;
struct _GtkConstraintGuide
{
GObject parent_instance;
char *name;
int strength;
int values[LAST_VALUE];
GtkConstraintLayout *layout;
/* HashTable<static string, Variable>; a hash table of variables,
* one for each attribute; we use these to query and suggest the
* values for the solver. The string is static and does not need
* to be freed.
*/
GHashTable *bound_attributes;
GtkConstraintRef *constraints[LAST_VALUE];
};
struct _GtkConstraintGuideClass {
GObjectClass parent_class;
};
enum {
PROP_MIN_WIDTH = 1,
PROP_MIN_HEIGHT,
PROP_NAT_WIDTH,
PROP_NAT_HEIGHT,
PROP_MAX_WIDTH,
PROP_MAX_HEIGHT,
PROP_STRENGTH,
PROP_NAME,
LAST_PROP
};
static GParamSpec *guide_props[LAST_PROP];
static void
gtk_constraint_guide_constraint_target_iface_init (GtkConstraintTargetInterface *iface)
{
}
G_DEFINE_TYPE_WITH_CODE (GtkConstraintGuide, gtk_constraint_guide, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GTK_TYPE_CONSTRAINT_TARGET,
gtk_constraint_guide_constraint_target_iface_init))
static void
gtk_constraint_guide_init (GtkConstraintGuide *guide)
{
guide->strength = GTK_CONSTRAINT_STRENGTH_MEDIUM;
guide->values[MIN_WIDTH] = 0;
guide->values[MIN_HEIGHT] = 0;
guide->values[NAT_WIDTH] = 0;
guide->values[NAT_HEIGHT] = 0;
guide->values[MAX_WIDTH] = G_MAXINT;
guide->values[MAX_HEIGHT] = G_MAXINT;
guide->bound_attributes =
g_hash_table_new_full (g_str_hash, g_str_equal,
NULL,
(GDestroyNotify) gtk_constraint_variable_unref);
}
static void
gtk_constraint_guide_update_constraint (GtkConstraintGuide *guide,
GuideValue index)
{
GtkConstraintSolver *solver;
GtkConstraintVariable *var;
if (!guide->layout)
return;
solver = gtk_constraint_layout_get_solver (guide->layout);
if (!solver)
return;
if (guide->constraints[index] != NULL)
{
gtk_constraint_solver_remove_constraint (solver, guide->constraints[index]);
guide->constraints[index] = NULL;
}
if (index == MIN_WIDTH || index == NAT_WIDTH || index == MAX_WIDTH)
var = gtk_constraint_layout_get_attribute (guide->layout, GTK_CONSTRAINT_ATTRIBUTE_WIDTH, "guide", NULL, guide->bound_attributes);
else
var = gtk_constraint_layout_get_attribute (guide->layout, GTK_CONSTRAINT_ATTRIBUTE_HEIGHT, "guide", NULL, guide->bound_attributes);
/* We always install min-size constraints,
* but we avoid nat-size constraints if min == max
* and we avoid max-size constraints if max == G_MAXINT
*/
if (index == MIN_WIDTH || index == MIN_HEIGHT)
{
guide->constraints[index] =
gtk_constraint_solver_add_constraint (solver,
var,
GTK_CONSTRAINT_RELATION_GE,
gtk_constraint_expression_new (guide->values[index]),
GTK_CONSTRAINT_STRENGTH_REQUIRED);
}
else if ((index == NAT_WIDTH && guide->values[MIN_WIDTH] != guide->values[MAX_WIDTH]) ||
(index == NAT_HEIGHT && guide->values[MIN_HEIGHT] != guide->values[MAX_HEIGHT]))
{
gtk_constraint_variable_set_value (var, guide->values[index]);
guide->constraints[index] =
gtk_constraint_solver_add_stay_variable (solver,
var,
guide->strength);
}
else if ((index == MAX_WIDTH || index == MAX_HEIGHT) &&
guide->values[index] < G_MAXINT)
{
guide->constraints[index] =
gtk_constraint_solver_add_constraint (solver,
var,
GTK_CONSTRAINT_RELATION_LE,
gtk_constraint_expression_new (guide->values[index]),
GTK_CONSTRAINT_STRENGTH_REQUIRED);
}
gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (guide->layout));
}
void
gtk_constraint_guide_update (GtkConstraintGuide *guide)
{
int i;
for (i = 0; i < LAST_VALUE; i++)
gtk_constraint_guide_update_constraint (guide, i);
}
void
gtk_constraint_guide_detach (GtkConstraintGuide *guide)
{
GtkConstraintSolver *solver;
int i;
if (!guide->layout)
return;
solver = gtk_constraint_layout_get_solver (guide->layout);
if (!solver)
return;
for (i = 0; i < LAST_VALUE; i++)
{
if (guide->constraints[i])
{
gtk_constraint_solver_remove_constraint (solver, guide->constraints[i]);
guide->constraints[i] = NULL;
}
}
g_hash_table_remove_all (guide->bound_attributes);
}
GtkConstraintVariable *
gtk_constraint_guide_get_attribute (GtkConstraintGuide *guide,
GtkConstraintAttribute attr)
{
GtkLayoutManager *manager = GTK_LAYOUT_MANAGER (guide->layout);
GtkWidget *widget = gtk_layout_manager_get_widget (manager);
return gtk_constraint_layout_get_attribute (guide->layout, attr, "guide", widget, guide->bound_attributes);
}
GtkConstraintLayout *
gtk_constraint_guide_get_layout (GtkConstraintGuide *guide)
{
return guide->layout;
}
void
gtk_constraint_guide_set_layout (GtkConstraintGuide *guide,
GtkConstraintLayout *layout)
{
guide->layout = layout;
}
static void
gtk_constraint_guide_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkConstraintGuide *self = GTK_CONSTRAINT_GUIDE (gobject);
int val;
GuideValue index;
switch (prop_id)
{
case PROP_MIN_WIDTH:
case PROP_MIN_HEIGHT:
case PROP_NAT_WIDTH:
case PROP_NAT_HEIGHT:
case PROP_MAX_WIDTH:
case PROP_MAX_HEIGHT:
val = g_value_get_int (value);
index = prop_id - 1;
if (self->values[index] != val)
{
self->values[index] = val;
g_object_notify_by_pspec (gobject, pspec);
gtk_constraint_guide_update_constraint (self, index);
if (index == MIN_WIDTH || index == MAX_WIDTH)
gtk_constraint_guide_update_constraint (self, NAT_WIDTH);
if (index == MIN_HEIGHT || index == MAX_HEIGHT)
gtk_constraint_guide_update_constraint (self, NAT_HEIGHT);
}
break;
case PROP_STRENGTH:
gtk_constraint_guide_set_strength (self, g_value_get_enum (value));
break;
case PROP_NAME:
gtk_constraint_guide_set_name (self, g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
gtk_constraint_guide_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkConstraintGuide *self = GTK_CONSTRAINT_GUIDE (gobject);
switch (prop_id)
{
case PROP_MIN_WIDTH:
case PROP_MIN_HEIGHT:
case PROP_NAT_WIDTH:
case PROP_NAT_HEIGHT:
case PROP_MAX_WIDTH:
case PROP_MAX_HEIGHT:
g_value_set_int (value, self->values[prop_id - 1]);
break;
case PROP_STRENGTH:
g_value_set_enum (value, self->strength);
break;
case PROP_NAME:
g_value_set_string (value, self->name);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
gtk_constraint_guide_finalize (GObject *object)
{
GtkConstraintGuide *self = GTK_CONSTRAINT_GUIDE (object);
g_free (self->name);
g_clear_pointer (&self->bound_attributes, g_hash_table_unref);
G_OBJECT_CLASS (gtk_constraint_guide_parent_class)->finalize (object);
}
static void
gtk_constraint_guide_class_init (GtkConstraintGuideClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->finalize = gtk_constraint_guide_finalize;
object_class->set_property = gtk_constraint_guide_set_property;
object_class->get_property = gtk_constraint_guide_get_property;
/**
* GtkConstraintGuide:min-width:
*
* The minimum width of the guide.
*/
guide_props[PROP_MIN_WIDTH] =
g_param_spec_int ("min-width",
"Minimum width",
"Minimum width",
0, G_MAXINT, 0,
G_PARAM_READWRITE|
G_PARAM_EXPLICIT_NOTIFY);
/**
* GtkConstraintGuide:min-height:
*
* The minimum height of the guide.
*/
guide_props[PROP_MIN_HEIGHT] =
g_param_spec_int ("min-height",
"Minimum height",
"Minimum height",
0, G_MAXINT, 0,
G_PARAM_READWRITE|
G_PARAM_EXPLICIT_NOTIFY);
/**
* GtkConstraintGuide:nat-width:
*
* The preferred, or natural, width of the guide.
*/
guide_props[PROP_NAT_WIDTH] =
g_param_spec_int ("nat-width",
"Natural width",
"Natural width",
0, G_MAXINT, 0,
G_PARAM_READWRITE|
G_PARAM_EXPLICIT_NOTIFY);
/**
* GtkConstraintGuide:nat-height:
*
* The preferred, or natural, height of the guide.
*/
guide_props[PROP_NAT_HEIGHT] =
g_param_spec_int ("nat-height",
"Natural height",
"Natural height",
0, G_MAXINT, 0,
G_PARAM_READWRITE|
G_PARAM_EXPLICIT_NOTIFY);
/**
* GtkConstraintGuide:max-width:
*
* The maximum width of the guide.
*/
guide_props[PROP_MAX_WIDTH] =
g_param_spec_int ("max-width",
"Maximum width",
"Maximum width",
0, G_MAXINT, G_MAXINT,
G_PARAM_READWRITE|
G_PARAM_EXPLICIT_NOTIFY);
/**
* GtkConstraintGuide:max-height:
*
* The maximum height of the guide.
*/
guide_props[PROP_MAX_HEIGHT] =
g_param_spec_int ("max-height",
"Maximum height",
"Maximum height",
0, G_MAXINT, G_MAXINT,
G_PARAM_READWRITE|
G_PARAM_EXPLICIT_NOTIFY);
/**
* GtkConstraintGuide:strength:
*
* The #GtkConstraintStrength to be used for the constraint on
* the natural size of the guide.
*/
guide_props[PROP_STRENGTH] =
g_param_spec_enum ("strength",
"Strength",
"The strength to use for natural size",
GTK_TYPE_CONSTRAINT_STRENGTH,
GTK_CONSTRAINT_STRENGTH_MEDIUM,
G_PARAM_READWRITE|
G_PARAM_EXPLICIT_NOTIFY);
/**
* GtkConstraintGuide:name:
*
* A name that identifies the #GtkConstraintGuide, for debugging.
*/
guide_props[PROP_NAME] =
g_param_spec_string ("name",
"Name",
"A name to use in debug message",
NULL,
G_PARAM_READWRITE);
g_object_class_install_properties (object_class, LAST_PROP, guide_props);
}
/**
* gtk_constraint_guide_new:
*
* Creates a new #GtkConstraintGuide object.
*
* Return: a new #GtkConstraintGuide object.
*/
GtkConstraintGuide *
gtk_constraint_guide_new (void)
{
return g_object_new (GTK_TYPE_CONSTRAINT_GUIDE, NULL);
}
/**
* gtk_constraint_guide_set_min_size:
* @guide: a #GtkConstraintGuide object
* @width: the new minimum width, or -1 to not change it
* @height: the new minimum height, or -1 to not change it
*
* Sets the minimum size of @guide.
*
* If @guide is attached to a #GtkConstraintLayout,
* the constraints will be updated to reflect the new size.
*/
void
gtk_constraint_guide_set_min_size (GtkConstraintGuide *guide,
int width,
int height)
{
g_return_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide));
g_return_if_fail (width >= -1);
g_return_if_fail (height >= -1);
g_object_freeze_notify (G_OBJECT (guide));
if (width != -1)
g_object_set (guide, "min-width", width, NULL);
if (height != -1)
g_object_set (guide, "min-height", height, NULL);
g_object_thaw_notify (G_OBJECT (guide));
}
/**
* gtk_constraint_guide_get_min_size:
* @guide: a #GtkContraintGuide object
* @width: (allow-none): return location for the minimum width,
* or %NULL
* @height: (allow-none): return location for the minimum height,
* or %NULL
*
* Gets the minimum size of @guide.
*/
void
gtk_constraint_guide_get_min_size (GtkConstraintGuide *guide,
int *width,
int *height)
{
g_return_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide));
if (width)
*width = guide->values[MIN_WIDTH];
if (height)
*height = guide->values[MIN_HEIGHT];
}
/**
* gtk_constraint_guide_set_nat_size:
* @guide: a #GtkConstraintGuide object
* @width: the new natural width, or -1 to not change it
* @height: the new natural height, or -1 to not change it
*
* Sets the natural size of @guide.
*
* If @guide is attached to a #GtkConstraintLayout,
* the constraints will be updated to reflect the new size.
*/
void
gtk_constraint_guide_set_nat_size (GtkConstraintGuide *guide,
int width,
int height)
{
g_return_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide));
g_return_if_fail (width >= -1);
g_return_if_fail (height >= -1);
g_object_freeze_notify (G_OBJECT (guide));
if (width != -1)
g_object_set (guide, "nat-width", width, NULL);
if (height != -1)
g_object_set (guide, "nat-height", height, NULL);
g_object_thaw_notify (G_OBJECT (guide));
}
/**
* gtk_constraint_guide_get_nat_size:
* @guide: a #GtkContraintGuide object
* @width: (allow-none): return location for the natural width,
* or %NULL
* @height: (allow-none): return location for the natural height,
* or %NULL
*
* Gets the natural size of @guide.
*/
void
gtk_constraint_guide_get_nat_size (GtkConstraintGuide *guide,
int *width,
int *height)
{
g_return_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide));
if (width)
*width = guide->values[NAT_WIDTH];
if (height)
*height = guide->values[NAT_HEIGHT];
}
/**
* gtk_constraint_guide_set_max_size:
* @guide: a #GtkConstraintGuide object
* @width: the new maximum width, or -1 to not change it
* @height: the new maximum height, or -1 to not change it
*
* Sets the maximum size of @guide.
*
* If @guide is attached to a #GtkConstraintLayout,
* the constraints will be updated to reflect the new size.
*/
void
gtk_constraint_guide_set_max_size (GtkConstraintGuide *guide,
int width,
int height)
{
g_return_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide));
g_return_if_fail (width >= -1);
g_return_if_fail (height >= -1);
g_object_freeze_notify (G_OBJECT (guide));
if (width != -1)
g_object_set (guide, "max-width", width, NULL);
if (height != -1)
g_object_set (guide, "max-height", height, NULL);
g_object_thaw_notify (G_OBJECT (guide));
}
/**
* gtk_constraint_guide_get_max_size:
* @guide: a #GtkContraintGuide object
* @width: (allow-none): return location for the maximum width,
* or %NULL
* @height: (allow-none): return location for the maximum height,
* or %NULL
*
* Gets the maximum size of @guide.
*/
void
gtk_constraint_guide_get_max_size (GtkConstraintGuide *guide,
int *width,
int *height)
{
g_return_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide));
if (width)
*width = guide->values[MAX_WIDTH];
if (height)
*height = guide->values[MAX_HEIGHT];
}
/**
* gtk_constraint_guide_get_name:
* @guide: a #GtkConstraintGuide
*
* Retrieves the name set using gtk_constraint_guide_set_name().
*
* Returns: (transfer none) (nullable): the name of the guide
*/
const char *
gtk_constraint_guide_get_name (GtkConstraintGuide *guide)
{
g_return_val_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide), NULL);
return guide->name;
}
/**
* gtk_constraint_guide_set_name:
* @guide: a #GtkConstraintGuide
* @name: (nullable): a name for the @guide
*
* Sets a name for the given #GtkConstraintGuide.
*
* The name is useful for debugging purposes.
*/
void
gtk_constraint_guide_set_name (GtkConstraintGuide *guide,
const char *name)
{
g_return_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide));
g_free (guide->name);
guide->name = g_strdup (name);
g_object_notify_by_pspec (G_OBJECT (guide), guide_props[PROP_NAME]);
}
/**
* gtk_constraint_guide_get_strength:
* @guide: a #GtkConstraintGuide
*
* Retrieves the strength set using gtk_constraint_guide_set_strength().
*
* Returns: the strength of the constraint on the natural size
*/
GtkConstraintStrength
gtk_constraint_guide_get_strength (GtkConstraintGuide *guide)
{
g_return_val_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide),
GTK_CONSTRAINT_STRENGTH_MEDIUM);
return guide->strength;
}
/**
* gtk_constraint_guide_set_strength:
* @guide: a #GtkConstraintGuide
* @strength: the strength of the constraint
*
* Sets the strength of the constraint on the natural size of the
* given #GtkConstraintGuide.
*/
void
gtk_constraint_guide_set_strength (GtkConstraintGuide *guide,
GtkConstraintStrength strength)
{
g_return_if_fail (GTK_IS_CONSTRAINT_GUIDE (guide));
if (guide->strength == strength)
return;
guide->strength = strength;
g_object_notify_by_pspec (G_OBJECT (guide), guide_props[PROP_STRENGTH]);
gtk_constraint_guide_update_constraint (guide, NAT_WIDTH);
gtk_constraint_guide_update_constraint (guide, NAT_HEIGHT);
}
+83
View File
@@ -0,0 +1,83 @@
/* gtkconstraintguide.h: Flexible space for constraints
* Copyright 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Matthias Clasen
*/
#pragma once
#include <gtk/gtktypes.h>
#include <gtk/gtkenums.h>
#include <gtk/gtktypebuiltins.h>
G_BEGIN_DECLS
#define GTK_TYPE_CONSTRAINT_GUIDE (gtk_constraint_guide_get_type ())
/**
* GtkConstraintGuide:
*
* An object that can be added to a #GtkConstraintLayout and be
* used in constraints like a widget, without being drawn.
*
* Guides have a minimum, maximum and natural size. Depending
* on the constraints that are applied, they can act like a
* guideline that widgets can be aligned to, or like 'flexible space'.
*/
GDK_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (GtkConstraintGuide, gtk_constraint_guide, GTK, CONSTRAINT_GUIDE, GObject)
GDK_AVAILABLE_IN_ALL
GtkConstraintGuide * gtk_constraint_guide_new (void);
GDK_AVAILABLE_IN_ALL
void gtk_constraint_guide_set_min_size (GtkConstraintGuide *guide,
int width,
int height);
GDK_AVAILABLE_IN_ALL
void gtk_constraint_guide_get_min_size (GtkConstraintGuide *guide,
int *width,
int *height);
GDK_AVAILABLE_IN_ALL
void gtk_constraint_guide_set_nat_size (GtkConstraintGuide *guide,
int width,
int height);
GDK_AVAILABLE_IN_ALL
void gtk_constraint_guide_get_nat_size (GtkConstraintGuide *guide,
int *width,
int *height);
GDK_AVAILABLE_IN_ALL
void gtk_constraint_guide_set_max_size (GtkConstraintGuide *guide,
int width,
int height);
GDK_AVAILABLE_IN_ALL
void gtk_constraint_guide_get_max_size (GtkConstraintGuide *guide,
int *width,
int *height);
GDK_AVAILABLE_IN_ALL
GtkConstraintStrength gtk_constraint_guide_get_strength (GtkConstraintGuide *guide);
GDK_AVAILABLE_IN_ALL
void gtk_constraint_guide_set_strength (GtkConstraintGuide *guide,
GtkConstraintStrength strength);
GDK_AVAILABLE_IN_ALL
void gtk_constraint_guide_set_name (GtkConstraintGuide *guide,
const char *name);
GDK_AVAILABLE_IN_ALL
const char * gtk_constraint_guide_get_name (GtkConstraintGuide *guide);
G_END_DECLS
+38
View File
@@ -0,0 +1,38 @@
/* gtkconstraintguideprivate.h: Constraint between two widgets
* Copyright 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Matthias Clasen
*/
#pragma once
#include "gtkconstraintguide.h"
#include "gtkconstraintlayout.h"
#include "gtkconstrainttypesprivate.h"
G_BEGIN_DECLS
void gtk_constraint_guide_update (GtkConstraintGuide *guide);
void gtk_constraint_guide_detach (GtkConstraintGuide *guide);
GtkConstraintVariable *gtk_constraint_guide_get_attribute (GtkConstraintGuide *guide,
GtkConstraintAttribute attr);
GtkConstraintLayout *gtk_constraint_guide_get_layout (GtkConstraintGuide *guide);
void gtk_constraint_guide_set_layout (GtkConstraintGuide *guide,
GtkConstraintLayout *layout);
G_END_DECLS
+1375 -716
View File
File diff suppressed because it is too large Load Diff
+34 -20
View File
@@ -20,12 +20,13 @@
#include <gtk/gtklayoutmanager.h>
#include <gtk/gtkconstraint.h>
#include <gtk/gtkconstraintguide.h>
G_BEGIN_DECLS
#define GTK_TYPE_CONSTRAINT_LAYOUT (gtk_constraint_layout_get_type ())
#define GTK_TYPE_CONSTRAINT_LAYOUT_CHILD (gtk_constraint_layout_child_get_type ())
#define GTK_TYPE_CONSTRAINT_GUIDE (gtk_constraint_guide_get_type ())
#define GTK_CONSTRAINT_VFL_PARSER_ERROR (gtk_constraint_vfl_parser_error_quark ())
/**
* GtkConstraintLayoutChild:
@@ -35,21 +36,6 @@ G_BEGIN_DECLS
GDK_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (GtkConstraintLayoutChild, gtk_constraint_layout_child, GTK, CONSTRAINT_LAYOUT_CHILD, GtkLayoutChild)
/**
* GtkConstraintGuide:
*
* An object that can be added to a #GtkConstraintLayout and be
* used in constraints like a widget, without being drawn. Guides
* have a minimal and natural size. Depending on the constraints
* that are applied, they can act like a guideline that widgets
* can be aligned to, or like 'flexible space'.
*/
GDK_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (GtkConstraintGuide, gtk_constraint_guide, GTK, CONSTRAINT_GUIDE, GObject)
GDK_AVAILABLE_IN_ALL
GtkConstraintGuide * gtk_constraint_guide_new (void);
/**
* GtkConstraintLayout:
*
@@ -59,21 +45,49 @@ GtkConstraintGuide * gtk_constraint_guide_new (void);
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_guide (GtkConstraintLayout *manager,
void gtk_constraint_layout_add_guide (GtkConstraintLayout *layout,
GtkConstraintGuide *guide);
GDK_AVAILABLE_IN_ALL
void gtk_constraint_layout_remove_guide (GtkConstraintLayout *manager,
void gtk_constraint_layout_remove_guide (GtkConstraintLayout *layout,
GtkConstraintGuide *guide);
GDK_AVAILABLE_IN_ALL
void gtk_constraint_layout_remove_all_constraints (GtkConstraintLayout *layout);
GDK_AVAILABLE_IN_ALL
GList * gtk_constraint_layout_add_constraints_from_description (GtkConstraintLayout *layout,
const char * const lines[],
gsize n_lines,
int hspacing,
int vspacing,
GError **error,
const char *first_view,
...) G_GNUC_NULL_TERMINATED;
GDK_AVAILABLE_IN_ALL
GList * gtk_constraint_layout_add_constraints_from_descriptionv (GtkConstraintLayout *layout,
const char * const lines[],
gsize n_lines,
int hspacing,
int vspacing,
GHashTable *views,
GError **error);
GDK_AVAILABLE_IN_ALL
GListModel * gtk_constraint_layout_observe_constraints (GtkConstraintLayout *layout);
GDK_AVAILABLE_IN_ALL
GListModel * gtk_constraint_layout_observe_guides (GtkConstraintLayout *layout);
G_END_DECLS
+37
View File
@@ -0,0 +1,37 @@
/*
* Copyright 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Matthias Clasen
*/
#pragma once
#include "gtkconstraintlayout.h"
#include "gtkconstraintsolverprivate.h"
G_BEGIN_DECLS
GtkConstraintSolver *
gtk_constraint_layout_get_solver (GtkConstraintLayout *layout);
GtkConstraintVariable *
gtk_constraint_layout_get_attribute (GtkConstraintLayout *layout,
GtkConstraintAttribute attr,
const char *prefix,
GtkWidget *widget,
GHashTable *bound_attributes);
G_END_DECLS
-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);
+125 -88
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);
}
@@ -736,17 +739,12 @@ gtk_constraint_solver_optimize (GtkConstraintSolver *self,
self->optimize_count += 1;
#ifdef G_ENABLE_DEBUG
{
char *str;
str = gtk_constraint_variable_to_string (z);
g_debug ("optimize: %s\n", str);
g_free (str);
str = gtk_constraint_solver_to_string (self);
g_debug ("%s\n", str);
g_free (str);
}
if (GTK_DEBUG_CHECK (CONSTRAINTS))
{
char *str = gtk_constraint_variable_to_string (z);
g_message ("optimize: %s", str);
g_free (str);
}
#endif
while (TRUE)
@@ -802,28 +800,28 @@ gtk_constraint_solver_optimize (GtkConstraintSolver *self,
if (min_ratio == DBL_MAX)
{
g_debug ("Unbounded objective variable during optimization");
GTK_NOTE (CONSTRAINTS, g_message ("Unbounded objective variable during optimization"));
break;
}
#ifdef G_ENABLE_DEBUG
{
char *entry_s = gtk_constraint_variable_to_string (entry);
char *exit_s = gtk_constraint_variable_to_string (exit);
g_debug ("pivot(entry: %s, exit: %s)", entry_s, exit_s);
g_free (entry_s);
g_free (exit_s);
}
if (GTK_DEBUG_CHECK (CONSTRAINTS))
{
char *entry_s = gtk_constraint_variable_to_string (entry);
char *exit_s = gtk_constraint_variable_to_string (exit);
g_message ("pivot(entry: %s, exit: %s)", entry_s, exit_s);
g_free (entry_s);
g_free (exit_s);
}
#endif
gtk_constraint_solver_pivot (self, entry, exit);
}
#ifdef G_ENABLE_DEBUG
g_debug ("solver.optimize.time := %.3f ms (pass: %d)",
(float) (g_get_monotonic_time () - start_time) / 1000.f,
self->optimize_count);
#endif
GTK_NOTE (CONSTRAINTS,
g_message ("solver.optimize.time := %.3f ms (pass: %d)",
(float) (g_get_monotonic_time () - start_time) / 1000.f,
self->optimize_count));
}
/*< private >
@@ -914,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);
@@ -973,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);
@@ -1061,10 +1059,9 @@ gtk_constraint_solver_dual_optimize (GtkConstraintSolver *self)
gtk_constraint_solver_pivot (self, entry_var, exit_var);
}
#ifdef G_ENABLE_DEBUG
g_debug ("dual_optimize.time := %.3f ms",
(float) (g_get_monotonic_time () - start_time) / 1000.f);
#endif
GTK_NOTE (CONSTRAINTS,
g_message ("dual_optimize.time := %.3f ms",
(float) (g_get_monotonic_time () - start_time) / 1000.f));
}
static void
@@ -1168,7 +1165,7 @@ gtk_constraint_solver_choose_subject (GtkConstraintSolver *self,
GtkConstraintVariableSet *cset = g_hash_table_lookup (self->columns, t_v);
if (cset == NULL ||
(gtk_constraint_variable_set_size (cset) == 1 &&
(gtk_constraint_variable_set_is_singleton (cset) &&
g_hash_table_contains (self->columns, self->objective)))
{
subject = t_v;
@@ -1205,7 +1202,8 @@ gtk_constraint_solver_choose_subject (GtkConstraintSolver *self,
if (!G_APPROX_VALUE (gtk_constraint_expression_get_constant (expression), 0.0, 0.001))
{
g_debug ("Unable to satisfy required constraint (choose_subject)");
GTK_NOTE (CONSTRAINTS,
g_message ("Unable to satisfy required constraint (choose_subject)"));
return NULL;
}
@@ -1266,14 +1264,17 @@ gtk_constraint_solver_add_with_artificial_variable (GtkConstraintSolver *self,
az_tableau_row = g_hash_table_lookup (self->rows, az);
if (!G_APPROX_VALUE (gtk_constraint_expression_get_constant (az_tableau_row), 0.0, 0.001))
{
char *str = gtk_constraint_expression_to_string (expression);
gtk_constraint_solver_remove_column (self, av);
gtk_constraint_solver_remove_row (self, az, TRUE);
g_debug ("Unable to satisfy a required constraint (add): %s", str);
g_free (str);
#ifdef G_ENABLE_DEBUG
if (GTK_DEBUG_CHECK (CONSTRAINTS))
{
char *str = gtk_constraint_expression_to_string (expression);
g_message ("Unable to satisfy a required constraint (add): %s", str);
g_free (str);
}
#endif
return;
}
@@ -1318,15 +1319,14 @@ gtk_constraint_solver_add_constraint_internal (GtkConstraintSolver *self,
&prev_constant);
#ifdef G_ENABLE_DEBUG
{
char *expr_s = gtk_constraint_expression_to_string (expr);
char *ref_s = gtk_constraint_ref_to_string (constraint);
g_debug ("Adding constraint '%s' (normalized expression: '%s')\n", ref_s, expr_s);
g_free (ref_s);
g_free (expr_s);
}
if (GTK_DEBUG_CHECK (CONSTRAINTS))
{
char *expr_s = gtk_constraint_expression_to_string (expr);
char *ref_s = gtk_constraint_ref_to_string (constraint);
g_message ("Adding constraint '%s' (normalized expression: '%s')", ref_s, expr_s);
g_free (ref_s);
g_free (expr_s);
}
#endif
if (constraint->is_stay)
@@ -1482,10 +1482,11 @@ gtk_constraint_solver_create_variable (GtkConstraintSolver *self,
{
GtkConstraintVariable *res;
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;
}
@@ -1511,10 +1512,9 @@ gtk_constraint_solver_resolve (GtkConstraintSolver *solver)
gtk_constraint_solver_reset_stay_constants (solver);
#ifdef G_ENABLE_DEBUG
g_debug ("resolve.time := %.3f ms",
(float) (g_get_monotonic_time () - start_time) / 1000.f);
#endif
GTK_NOTE (CONSTRAINTS,
g_message ("resolve.time := %.3f ms",
(float) (g_get_monotonic_time () - start_time) / 1000.f));
solver->needs_solving = FALSE;
}
@@ -1525,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:
*
@@ -1544,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;
@@ -1601,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.
*
@@ -1615,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;
@@ -1633,11 +1633,12 @@ gtk_constraint_solver_add_stay_variable (GtkConstraintSolver *self,
self);
#ifdef G_ENABLE_DEBUG
{
char *str = gtk_constraint_expression_to_string (res->expression);
g_debug ("Adding stay variable: %s", str);
g_free (str);
}
if (GTK_DEBUG_CHECK (CONSTRAINTS))
{
char *str = gtk_constraint_expression_to_string (res->expression);
g_message ("Adding stay variable: %s", str);
g_free (str);
}
#endif
gtk_constraint_solver_add_constraint_internal (self, res);
@@ -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;
@@ -1735,7 +1736,7 @@ gtk_constraint_solver_remove_edit_variable (GtkConstraintSolver *self,
{
char *str = gtk_constraint_variable_to_string (variable);
g_critical ("Unknown stay variable '%s'", str);
g_critical ("Unknown edit variable '%s'", str);
g_free (str);
@@ -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);
}
@@ -1866,7 +1867,7 @@ gtk_constraint_solver_remove_constraint (GtkConstraintSolver *self,
if (exit_var == NULL)
{
if (gtk_constraint_variable_set_size (set) == 0)
if (gtk_constraint_variable_set_is_empty (set))
gtk_constraint_solver_remove_column (self, marker);
else
{
@@ -2208,3 +2209,39 @@ gtk_constraint_solver_to_string (GtkConstraintSolver *solver)
return g_string_free (buf, FALSE);
}
char *
gtk_constraint_solver_statistics (GtkConstraintSolver *solver)
{
GString *buf = g_string_new (NULL);
g_string_append_printf (buf, "Variables: %d\n", solver->var_counter);
g_string_append_printf (buf, "Slack vars: %d\n", solver->slack_counter);
g_string_append_printf (buf, "Artificial vars: %d\n", solver->artificial_counter);
g_string_append_printf (buf, "Dummy vars: %d\n", solver->dummy_counter);
g_string_append_printf (buf, "Stay vars: %d\n", g_hash_table_size (solver->stay_var_map));
g_string_append_printf (buf, "Optimize count: %d\n", solver->optimize_count);
g_string_append_printf (buf, "Rows: %d\n", g_hash_table_size (solver->rows));
g_string_append_printf (buf, "Columns: %d\n", g_hash_table_size (solver->columns));
if (g_hash_table_size (solver->columns) > 0)
{
GHashTableIter iter;
gpointer val;
double sum = 0;
g_hash_table_iter_init (&iter, solver->columns);
while (g_hash_table_iter_next (&iter, NULL, &val))
{
GtkConstraintVariableSet *set = val;
sum += gtk_constraint_variable_set_size (set);
}
g_string_append_printf (buf, "Avg column size: %g\n", sum / g_hash_table_size (solver->columns));
}
g_string_append_printf (buf, "Infeasible rows: %d\n", solver->infeasible_rows->len);
g_string_append_printf (buf, "External basic variables: %d\n", g_hash_table_size (solver->external_rows));
g_string_append_printf (buf, "External parametric variables: %d\n", g_hash_table_size (solver->external_parametric_vars));
return g_string_free (buf, FALSE);
}
+6 -34
View File
@@ -29,37 +29,6 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (GtkConstraintSolver, gtk_constraint_solver, GTK, CONSTRAINT_SOLVER, GObject)
/* 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);
@@ -83,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,
@@ -92,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,
@@ -105,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,
@@ -142,4 +111,7 @@ gtk_constraint_solver_clear (GtkConstraintSolver *solver);
char *
gtk_constraint_solver_to_string (GtkConstraintSolver *solver);
char *
gtk_constraint_solver_statistics (GtkConstraintSolver *solver);
G_END_DECLS
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
+3 -1
View File
@@ -1118,6 +1118,8 @@ gtk_css_provider_load_internal (GtkCssProvider *self,
if (parent == NULL)
gtk_css_provider_postprocess (self);
g_bytes_unref (bytes);
}
}
@@ -1149,8 +1151,8 @@ gtk_css_provider_load_from_data (GtkCssProvider *css_provider,
gtk_css_provider_reset (css_provider);
g_bytes_ref (bytes);
gtk_css_provider_load_internal (css_provider, NULL, NULL, bytes);
g_bytes_unref (bytes);
gtk_style_provider_changed (GTK_STYLE_PROVIDER (css_provider));
+2 -1
View File
@@ -51,7 +51,8 @@ typedef enum {
GTK_DEBUG_ACTIONS = 1 << 13,
GTK_DEBUG_RESIZE = 1 << 14,
GTK_DEBUG_LAYOUT = 1 << 15,
GTK_DEBUG_SNAPSHOT = 1 << 16
GTK_DEBUG_SNAPSHOT = 1 << 16,
GTK_DEBUG_CONSTRAINTS = 1 << 17,
} GtkDebugFlag;
#ifdef G_ENABLE_DEBUG
-1
View File
@@ -566,7 +566,6 @@ populate_completion (GtkEmojiCompletion *completion,
GVariantIter iter;
GVariant *item;
text = g_strdup (text);
g_free (completion->text);
completion->text = g_strdup (text);
completion->length = g_utf8_strlen (text, -1);
+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)
+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;
}
/**
-1
View File
@@ -1356,7 +1356,6 @@ gtk_header_bar_set_custom_title (GtkHeaderBar *bar,
gtk_header_bar_reorder_css_node (bar, GTK_PACK_START, priv->custom_title);
gtk_widget_set_parent (priv->custom_title, GTK_WIDGET (bar));
gtk_widget_set_valign (priv->custom_title, GTK_ALIGN_CENTER);
if (priv->label_box != NULL)
{
+44 -17
View File
@@ -227,19 +227,35 @@ gtk_icon_helper_paintable_snapshot (GdkPaintable *paintable,
h = MIN (h, height);
x = (width - w) / 2;
y = (height - h) / 2;
gtk_snapshot_save (snapshot);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
gtk_css_style_snapshot_icon_paintable (style,
snapshot,
self->paintable,
w, h,
self->texture_is_symbolic);
gtk_snapshot_restore (snapshot);
if (x != 0 || y != 0)
{
gtk_snapshot_save (snapshot);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
gtk_css_style_snapshot_icon_paintable (style,
snapshot,
self->paintable,
w, h,
self->texture_is_symbolic);
gtk_snapshot_restore (snapshot);
}
else
{
gtk_css_style_snapshot_icon_paintable (style,
snapshot,
self->paintable,
w, h,
self->texture_is_symbolic);
}
}
break;
case GTK_IMAGE_PAINTABLE:
case GTK_IMAGE_EMPTY:
break;
case GTK_IMAGE_PAINTABLE:
default:
{
double image_ratio = (double) width / height;
@@ -269,14 +285,25 @@ gtk_icon_helper_paintable_snapshot (GdkPaintable *paintable,
x = floor (width - ceil (w)) / 2;
y = floor (height - ceil (h)) / 2;
gtk_snapshot_save (snapshot);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
gtk_css_style_snapshot_icon_paintable (style,
snapshot,
self->paintable,
w, h,
self->texture_is_symbolic);
gtk_snapshot_restore (snapshot);
if (x != 0 || y != 0)
{
gtk_snapshot_save (snapshot);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
gtk_css_style_snapshot_icon_paintable (style,
snapshot,
self->paintable,
w, h,
self->texture_is_symbolic);
gtk_snapshot_restore (snapshot);
}
else
{
gtk_css_style_snapshot_icon_paintable (style,
snapshot,
self->paintable,
w, h,
self->texture_is_symbolic);
}
}
break;
}
+2 -1
View File
@@ -179,7 +179,8 @@ static const GDebugKey gtk_debug_keys[] = {
{ "actions", GTK_DEBUG_ACTIONS },
{ "resize", GTK_DEBUG_RESIZE },
{ "layout", GTK_DEBUG_LAYOUT },
{ "snapshot", GTK_DEBUG_SNAPSHOT }
{ "snapshot", GTK_DEBUG_SNAPSHOT },
{ "constraints", GTK_DEBUG_CONSTRAINTS },
};
#endif /* G_ENABLE_DEBUG */
+3 -6
View File
@@ -1757,7 +1757,7 @@ GtkWidget*
gtk_menu_get_active (GtkMenu *menu)
{
GtkMenuPrivate *priv;
GtkWidget *child;
GtkWidget *child = NULL;
GList *children, *l;
g_return_val_if_fail (GTK_IS_MENU (menu), NULL);
@@ -2414,7 +2414,6 @@ gtk_menu_position (GtkMenu *menu)
GdkAnchorHints anchor_hints;
gint rect_anchor_dx, rect_anchor_dy;
GdkSurface *toplevel;
gboolean emulated_move_to_rect = FALSE;
rect_anchor = priv->rect_anchor;
menu_anchor = priv->menu_anchor;
@@ -2461,10 +2460,8 @@ gtk_menu_position (GtkMenu *menu)
g_signal_handlers_disconnect_by_func (toplevel, moved_to_rect_cb, menu);
if (!emulated_move_to_rect)
g_signal_connect (toplevel, "moved-to-rect", G_CALLBACK (moved_to_rect_cb),
menu);
g_signal_connect (toplevel, "moved-to-rect", G_CALLBACK (moved_to_rect_cb),
menu);
gdk_surface_move_to_rect (toplevel,
&rect,
+2
View File
@@ -809,6 +809,8 @@ gtk_picture_set_paintable (GtkPicture *self,
g_signal_handlers_disconnect_by_func (self->paintable,
gtk_picture_paintable_invalidate_size,
self);
g_object_unref (self->paintable);
}
self->paintable = paintable;
+1 -1
View File
@@ -683,7 +683,7 @@ surface_transform_changed_cb (GtkWidget *widget,
const graphene_matrix_t *transform,
gpointer user_data)
{
GtkPopover *popover = GTK_POPOVER (widget);
GtkPopover *popover = user_data;
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
move_to_rect (popover);
+25 -135
View File
@@ -38,6 +38,7 @@
#include "gtkprivate.h"
#include "gtkstylecontextprivate.h"
#include "gtkwidgetprivate.h"
#include "gtkboxlayout.h"
#include "a11y/gtkprogressbaraccessible.h"
@@ -155,11 +156,6 @@ static void gtk_progress_bar_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void gtk_progress_bar_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline);
static void gtk_progress_bar_act_mode_enter (GtkProgressBar *progress);
static void gtk_progress_bar_act_mode_leave (GtkProgressBar *progress);
static void gtk_progress_bar_finalize (GObject *object);
@@ -168,14 +164,6 @@ static void gtk_progress_bar_set_orientation (GtkProgressBar *progress,
static void gtk_progress_bar_direction_changed (GtkWidget *widget,
GtkTextDirection previous_dir);
static void gtk_progress_bar_measure (GtkWidget *widget,
GtkOrientation orientation,
gint for_size,
gint *minimum,
gint *natural,
gint *minimum_baseline,
gint *natural_baseline);
G_DEFINE_TYPE_WITH_CODE (GtkProgressBar, gtk_progress_bar, GTK_TYPE_WIDGET,
G_ADD_PRIVATE (GtkProgressBar)
G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL))
@@ -193,8 +181,6 @@ gtk_progress_bar_class_init (GtkProgressBarClass *class)
gobject_class->get_property = gtk_progress_bar_get_property;
gobject_class->finalize = gtk_progress_bar_finalize;
widget_class->measure = gtk_progress_bar_measure;
widget_class->size_allocate = gtk_progress_bar_size_allocate;
widget_class->direction_changed = gtk_progress_bar_direction_changed;
g_object_class_override_property (gobject_class, PROP_ORIENTATION, "orientation");
@@ -274,6 +260,7 @@ gtk_progress_bar_class_init (GtkProgressBarClass *class)
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_PROGRESS_BAR_ACCESSIBLE);
gtk_widget_class_set_css_name (widget_class, I_("progressbar"));
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
}
static void
@@ -475,7 +462,6 @@ gtk_progress_bar_init (GtkProgressBar *pbar)
{
GtkProgressBarPrivate *priv = gtk_progress_bar_get_instance_private (pbar);
priv->orientation = GTK_ORIENTATION_HORIZONTAL;
priv->inverted = FALSE;
priv->pulse_fraction = 0.1;
priv->activity_pos = 0;
@@ -487,8 +473,6 @@ gtk_progress_bar_init (GtkProgressBar *pbar)
priv->text = NULL;
priv->fraction = 0.0;
_gtk_orientable_set_style_classes (GTK_ORIENTABLE (pbar));
priv->trough_widget = gtk_gizmo_new ("trough",
NULL,
allocate_trough,
@@ -499,7 +483,10 @@ gtk_progress_bar_init (GtkProgressBar *pbar)
priv->progress_widget = gtk_gizmo_new ("progress", NULL, NULL, NULL, NULL);
gtk_widget_set_parent (priv->progress_widget, priv->trough_widget);
update_node_classes (pbar);
/* horizontal is default */
priv->orientation = GTK_ORIENTATION_VERTICAL; /* Just to force an update... */
gtk_progress_bar_set_orientation (pbar, GTK_ORIENTATION_HORIZONTAL);
_gtk_orientable_set_style_classes (GTK_ORIENTABLE (pbar));
}
static void
@@ -626,122 +613,6 @@ get_current_text (GtkProgressBar *pbar)
return g_strdup_printf (C_("progress bar label", "%.0f%%"), priv->fraction * 100.0);
}
static void
gtk_progress_bar_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
GtkProgressBarPrivate *priv = gtk_progress_bar_get_instance_private (GTK_PROGRESS_BAR (widget));
gint bar_width, bar_height;
gint text_width, text_height, text_min, text_nat;
GtkAllocation alloc;
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
{
gtk_widget_measure (priv->trough_widget, GTK_ORIENTATION_VERTICAL, -1,
&bar_height, NULL,
NULL, NULL);
bar_width = width;
}
else
{
gtk_widget_measure (priv->trough_widget, GTK_ORIENTATION_HORIZONTAL, -1,
&bar_width, NULL,
NULL, NULL);
bar_height = height;
}
alloc.x = width - bar_width;
alloc.y = height - bar_height;
alloc.width = bar_width;
alloc.height = bar_height;
gtk_widget_size_allocate (priv->trough_widget, &alloc, -1);
if (!priv->show_text)
return;
gtk_widget_measure (priv->label, GTK_ORIENTATION_HORIZONTAL, -1,
&text_min, &text_nat,
NULL, NULL);
gtk_widget_measure (priv->label, GTK_ORIENTATION_VERTICAL, -1,
&text_height, NULL,
NULL, NULL);
text_width = CLAMP (text_nat, text_min, width);
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
{
alloc.x = (width - text_width) / 2;
alloc.y = 0;
alloc.width = text_width;
alloc.height = text_height;
}
else
{
alloc.x = width - text_width;
alloc.y = (height - text_height) / 2;
alloc.width = text_width;
alloc.height = text_height;
}
gtk_widget_size_allocate (priv->label, &alloc, -1);
}
static void
gtk_progress_bar_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
GtkProgressBar *pbar = GTK_PROGRESS_BAR (widget);
GtkProgressBarPrivate *priv = gtk_progress_bar_get_instance_private (pbar);
gint text_minimum, text_natural;
gint trough_minimum, trough_natural;
if (priv->show_text)
gtk_widget_measure (priv->label, orientation, -1,
&text_minimum, &text_natural,
NULL, NULL);
else
text_minimum = text_natural = 0;
gtk_widget_measure (priv->trough_widget, orientation, -1,
&trough_minimum, &trough_natural,
NULL, NULL);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
{
*minimum = MAX (text_minimum, trough_minimum);
*natural = MAX (text_natural, trough_natural);
}
else
{
*minimum = text_minimum + trough_minimum;
*natural = text_natural + trough_natural;
}
}
else
{
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
{
*minimum = text_minimum + trough_minimum;
*natural = text_natural + trough_natural;
}
else
{
*minimum = MAX (text_minimum, trough_minimum);
*natural = MAX (text_natural, trough_natural);
}
}
}
static gboolean
tick_cb (GtkWidget *widget,
GdkFrameClock *frame_clock,
@@ -1087,16 +958,35 @@ gtk_progress_bar_set_orientation (GtkProgressBar *pbar,
GtkOrientation orientation)
{
GtkProgressBarPrivate *priv = gtk_progress_bar_get_instance_private (pbar);
GtkBoxLayout *layout;
if (priv->orientation == orientation)
return;
priv->orientation = orientation;
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
gtk_widget_set_vexpand (priv->trough_widget, FALSE);
gtk_widget_set_hexpand (priv->trough_widget, TRUE);
gtk_widget_set_halign (priv->trough_widget, GTK_ALIGN_FILL);
gtk_widget_set_valign (priv->trough_widget, GTK_ALIGN_CENTER);
}
else
{
gtk_widget_set_vexpand (priv->trough_widget, TRUE);
gtk_widget_set_hexpand (priv->trough_widget, FALSE);
gtk_widget_set_halign (priv->trough_widget, GTK_ALIGN_CENTER);
gtk_widget_set_valign (priv->trough_widget, GTK_ALIGN_FILL);
}
_gtk_orientable_set_style_classes (GTK_ORIENTABLE (pbar));
update_node_classes (pbar);
gtk_widget_queue_resize (GTK_WIDGET (pbar));
layout = GTK_BOX_LAYOUT (gtk_widget_get_layout_manager (GTK_WIDGET (pbar)));
gtk_orientable_set_orientation (GTK_ORIENTABLE (layout), GTK_ORIENTATION_VERTICAL);
g_object_notify (G_OBJECT (pbar), "orientation");
}
-3
View File
@@ -40,9 +40,6 @@ finalize (GObject *object)
GtkQuery *query = GTK_QUERY (object);
GtkQueryPrivate *priv = gtk_query_get_instance_private (query);
query = GTK_QUERY (object);
g_clear_object (&priv->location);
g_free (priv->text);
g_strfreev (priv->words);
+10 -48
View File
@@ -33,7 +33,7 @@
#include "gtkorientable.h"
#include "gtkorientableprivate.h"
#include "gtkprivate.h"
#include "gtkbox.h"
#include "gtkboxlayout.h"
/**
@@ -59,14 +59,13 @@
*
* |[<!-- language="plain" -->
* scrollbar
* box
* range[.fine-tune]
* trough
* slider
* range[.fine-tune]
* trough
* slider
* ]|
*
* GtkScrollbar has a main CSS node with name scrollbar and a subnode for its
* contents. Both the main node and the box subnode get the .horizontal or .vertical
* contents. The main node gets the .horizontal or .vertical
* style classes applied, depending on the scrollbar's orientation.
*
* The range node gets the style class .fine-tune added when the scrollbar is
@@ -95,7 +94,6 @@ struct _GtkScrollbarClass
typedef struct {
GtkOrientation orientation;
GtkWidget *box;
GtkWidget *range;
} GtkScrollbarPrivate;
@@ -114,39 +112,6 @@ G_DEFINE_TYPE_WITH_CODE (GtkScrollbar, gtk_scrollbar, GTK_TYPE_WIDGET,
static GParamSpec *props[LAST_PROP] = { NULL, };
static void
gtk_scrollbar_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
GtkScrollbar *self = GTK_SCROLLBAR (widget);
GtkScrollbarPrivate *priv = gtk_scrollbar_get_instance_private (self);
gtk_widget_measure (priv->box, orientation, for_size,
minimum, natural, minimum_baseline, natural_baseline);
}
static void
gtk_scrollbar_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
GtkScrollbar *self = GTK_SCROLLBAR (widget);
GtkScrollbarPrivate *priv = gtk_scrollbar_get_instance_private (self);
gtk_widget_size_allocate (priv->box,
&(GtkAllocation) {
0, 0,
width, height
}, -1);
}
static void
gtk_scrollbar_get_property (GObject *object,
guint property_id,
@@ -190,7 +155,8 @@ gtk_scrollbar_set_property (GObject *object,
if (orientation != priv->orientation)
{
gtk_orientable_set_orientation (GTK_ORIENTABLE (priv->box), orientation);
GtkLayoutManager *layout = gtk_widget_get_layout_manager (GTK_WIDGET (self));
gtk_orientable_set_orientation (GTK_ORIENTABLE (layout), orientation);
gtk_orientable_set_orientation (GTK_ORIENTABLE (priv->range), orientation);
priv->orientation = orientation;
_gtk_orientable_set_style_classes (GTK_ORIENTABLE (self));
@@ -212,7 +178,7 @@ gtk_scrollbar_dispose (GObject *object)
GtkScrollbar *self = GTK_SCROLLBAR (object);
GtkScrollbarPrivate *priv = gtk_scrollbar_get_instance_private (self);
g_clear_pointer (&priv->box, gtk_widget_unparent);
g_clear_pointer (&priv->range, gtk_widget_unparent);
G_OBJECT_CLASS (gtk_scrollbar_parent_class)->dispose (object);
}
@@ -227,9 +193,6 @@ gtk_scrollbar_class_init (GtkScrollbarClass *class)
object_class->set_property = gtk_scrollbar_set_property;
object_class->dispose = gtk_scrollbar_dispose;
widget_class->measure = gtk_scrollbar_measure;
widget_class->size_allocate = gtk_scrollbar_size_allocate;
props[PROP_ADJUSTMENT] =
g_param_spec_object ("adjustment",
P_("Adjustment"),
@@ -243,6 +206,7 @@ gtk_scrollbar_class_init (GtkScrollbarClass *class)
gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_SCROLL_BAR);
gtk_widget_class_set_css_name (widget_class, I_("scrollbar"));
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
}
static gboolean
@@ -262,13 +226,11 @@ gtk_scrollbar_init (GtkScrollbar *self)
priv->orientation = GTK_ORIENTATION_HORIZONTAL;
priv->box = gtk_box_new (priv->orientation, 0);
gtk_widget_set_parent (priv->box, GTK_WIDGET (self));
priv->range = g_object_new (GTK_TYPE_RANGE, NULL);
g_signal_connect_swapped (priv->range, "popup-menu", G_CALLBACK (emit_popup_menu), self);
gtk_widget_set_hexpand (priv->range, TRUE);
gtk_widget_set_vexpand (priv->range, TRUE);
gtk_container_add (GTK_CONTAINER (priv->box), priv->range);
gtk_widget_set_parent (priv->range, GTK_WIDGET (self));
_gtk_orientable_set_style_classes (GTK_ORIENTABLE (self));
}
+1 -1
View File
@@ -93,7 +93,7 @@
* An example of a UI definition fragment with GtkSizeGroup:
* |[
* <object class="GtkSizeGroup">
* <property name="mode">GTK_SIZE_GROUP_HORIZONTAL</property>
* <property name="mode">horizontal</property>
* <widgets>
* <widget name="radio1"/>
* <widget name="radio2"/>
+13 -9
View File
@@ -1783,6 +1783,7 @@ gtk_text_dispose (GObject *object)
GtkText *self = GTK_TEXT (object);
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
GdkKeymap *keymap;
GtkWidget *chooser;
priv->current_pos = 0;
@@ -1794,6 +1795,9 @@ gtk_text_dispose (GObject *object)
}
g_clear_pointer (&priv->emoji_completion, gtk_widget_unparent);
chooser = g_object_get_data (object, "gtk-emoji-chooser");
if (chooser)
gtk_widget_unparent (chooser);
keymap = gdk_display_get_keymap (gtk_widget_get_display (GTK_WIDGET (object)));
g_signal_handlers_disconnect_by_func (keymap, keymap_direction_changed, self);
@@ -2253,18 +2257,18 @@ gtk_text_snapshot (GtkWidget *widget,
/* Draw text and cursor */
if (priv->dnd_position != -1)
gtk_text_draw_cursor (GTK_TEXT (widget), snapshot, CURSOR_DND);
gtk_text_draw_cursor (self, snapshot, CURSOR_DND);
if (priv->placeholder)
gtk_widget_snapshot_child (widget, priv->placeholder, snapshot);
gtk_text_draw_text (GTK_TEXT (widget), snapshot);
gtk_text_draw_text (self, snapshot);
/* When no text is being displayed at all, don't show the cursor */
if (gtk_text_get_display_mode (self) != DISPLAY_BLANK &&
gtk_widget_has_focus (widget) &&
priv->selection_bound == priv->current_pos && priv->cursor_visible)
gtk_text_draw_cursor (GTK_TEXT (widget), snapshot, CURSOR_STANDARD);
gtk_text_draw_cursor (self, snapshot, CURSOR_STANDARD);
gtk_text_draw_undershoot (self, snapshot);
}
@@ -4323,7 +4327,6 @@ gtk_text_draw_text (GtkText *self,
GtkStyleContext *context;
PangoLayout *layout;
int x, y;
int width, height;
/* Nothing to display at all */
if (gtk_text_get_display_mode (self) == DISPLAY_BLANK)
@@ -4331,8 +4334,6 @@ gtk_text_draw_text (GtkText *self,
context = gtk_widget_get_style_context (widget);
layout = gtk_text_ensure_layout (self, TRUE);
width = gtk_widget_get_width (widget);
height = gtk_widget_get_height (widget);
gtk_text_get_layout_offsets (self, &x, &y);
@@ -4346,6 +4347,10 @@ gtk_text_draw_text (GtkText *self,
cairo_region_t *clip;
cairo_rectangle_int_t clip_extents;
int range[2];
int width, height;
width = gtk_widget_get_width (widget);
height = gtk_widget_get_height (widget);
range[0] = MIN (start_index, end_index);
range[1] = MAX (start_index, end_index);
@@ -4381,15 +4386,12 @@ gtk_text_draw_cursor (GtkText *self,
PangoLayout *layout;
const char *text;
int x, y;
int width, height;
context = gtk_widget_get_style_context (widget);
layout = gtk_text_ensure_layout (self, TRUE);
text = pango_layout_get_text (layout);
gtk_text_get_layout_offsets (self, &x, &y);
width = gtk_widget_get_width (widget);
height = gtk_widget_get_height (widget);
if (type == CURSOR_DND)
cursor_index = g_utf8_offset_to_pointer (text, priv->dnd_position) - text;
@@ -4409,6 +4411,8 @@ gtk_text_draw_cursor (GtkText *self,
}
else /* overwrite_mode */
{
int width = gtk_widget_get_width (widget);
int height = gtk_widget_get_height (widget);
graphene_rect_t bounds;
bounds.origin.x = PANGO_PIXELS (cursor_rect.x) + x;
+1 -1
View File
@@ -4449,7 +4449,7 @@ changed_handler (GtkTextLayout *layout,
tmp_list = tmp_list->next;
}
gtk_widget_queue_resize_no_redraw(widget);
gtk_widget_queue_resize(widget);
}
}
+4 -4
View File
@@ -933,13 +933,13 @@ slide_idle_handler (gpointer data)
if (cont)
{
gtk_widget_queue_resize_no_redraw (GTK_WIDGET (toolbar));
gtk_widget_queue_resize (GTK_WIDGET (toolbar));
return TRUE;
}
}
gtk_widget_queue_resize_no_redraw (GTK_WIDGET (toolbar));
gtk_widget_queue_resize (GTK_WIDGET (toolbar));
priv->is_sliding = FALSE;
priv->idle_id = 0;
@@ -1052,7 +1052,7 @@ gtk_toolbar_begin_sliding (GtkToolbar *toolbar)
* so that the idle handler will not immediately return
* FALSE
*/
gtk_widget_queue_resize_no_redraw (GTK_WIDGET (toolbar));
gtk_widget_queue_resize (GTK_WIDGET (toolbar));
g_timer_reset (priv->timer);
}
@@ -1086,7 +1086,7 @@ gtk_toolbar_stop_sliding (GtkToolbar *toolbar)
}
}
gtk_widget_queue_resize_no_redraw (GTK_WIDGET (toolbar));
gtk_widget_queue_resize (GTK_WIDGET (toolbar));
}
}
+2 -2
View File
@@ -6311,7 +6311,7 @@ do_validate_rows (GtkTreeView *tree_view, gboolean queue_resize)
MAX (gtk_adjustment_get_upper (tree_view->priv->vadjustment), requisition.height));
if (queue_resize)
gtk_widget_queue_resize_no_redraw (GTK_WIDGET (tree_view));
gtk_widget_queue_resize (GTK_WIDGET (tree_view));
}
if (path) gtk_tree_path_free (path);
@@ -8319,7 +8319,7 @@ gtk_tree_view_row_inserted (GtkTreeModel *model,
if (node_visible && node_is_visible (tree_view, tree, tmpnode))
gtk_widget_queue_resize (GTK_WIDGET (tree_view));
else
gtk_widget_queue_resize_no_redraw (GTK_WIDGET (tree_view));
gtk_widget_queue_resize (GTK_WIDGET (tree_view));
}
else
install_presize_handler (tree_view);
+7 -18
View File
@@ -365,7 +365,7 @@
* |[
* <interface>
* <template class="FooWidget" parent="GtkBox">
* <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
* <property name="orientation">horizontal</property>
* <property name="spacing">4</property>
* <child>
* <object class="GtkButton" id="hello_button">
@@ -713,6 +713,8 @@ static gboolean gtk_widget_class_get_visible_by_default (GtkWidgetClass *widget_
static void remove_parent_surface_transform_changed_listener (GtkWidget *widget);
static void add_parent_surface_transform_changed_listener (GtkWidget *widget);
static void gtk_widget_queue_compute_expand (GtkWidget *widget);
/* --- variables --- */
@@ -2303,7 +2305,7 @@ gtk_widget_set_property (GObject *object,
gtk_css_node_set_name (priv->cssnode, GTK_WIDGET_GET_CLASS (widget)->priv->css_name);
break;
case PROP_LAYOUT_MANAGER:
gtk_widget_set_layout_manager (widget, g_value_get_object (value));
gtk_widget_set_layout_manager (widget, g_value_dup_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -4159,21 +4161,6 @@ gtk_widget_queue_resize (GtkWidget *widget)
gtk_widget_queue_resize_internal (widget);
}
/**
* gtk_widget_queue_resize_no_redraw:
* @widget: a #GtkWidget
*
* This function works like gtk_widget_queue_resize(),
* except that the widget is not invalidated.
**/
void
gtk_widget_queue_resize_no_redraw (GtkWidget *widget)
{
g_return_if_fail (GTK_IS_WIDGET (widget));
gtk_widget_queue_resize_internal (widget);
}
/**
* gtk_widget_get_frame_clock:
* @widget: a #GtkWidget
@@ -4468,6 +4455,7 @@ gtk_widget_allocate (GtkWidget *widget,
if (adjusted.x || adjusted.y)
transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (adjusted.x, adjusted.y));
gsk_transform_unref (priv->transform);
priv->transform = transform;
if (priv->surface_transform_data)
@@ -8954,7 +8942,7 @@ gtk_widget_update_computed_expand (GtkWidget *widget)
*
* See gtk_widget_compute_expand().
*/
void
static void
gtk_widget_queue_compute_expand (GtkWidget *widget)
{
GtkWidget *parent;
@@ -10119,6 +10107,7 @@ gtk_widget_buildable_finish_layout_properties (GtkWidget *widget,
}
g_slist_free_full (layout_properties, layout_property_info_free);
g_slice_free (LayoutParserData, layout_data);
}
static void
-4
View File
@@ -375,8 +375,6 @@ void gtk_widget_queue_draw (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_widget_queue_resize (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_widget_queue_resize_no_redraw (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_widget_queue_allocate (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
GdkFrameClock* gtk_widget_get_frame_clock (GtkWidget *widget);
@@ -645,8 +643,6 @@ GDK_AVAILABLE_IN_ALL
void gtk_widget_set_vexpand_set (GtkWidget *widget,
gboolean set);
GDK_AVAILABLE_IN_ALL
void gtk_widget_queue_compute_expand (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
gboolean gtk_widget_compute_expand (GtkWidget *widget,
GtkOrientation orientation);
+4 -4
View File
@@ -4367,7 +4367,7 @@ gtk_window_set_default_size_internal (GtkWindow *window,
g_object_thaw_notify (G_OBJECT (window));
gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
gtk_widget_queue_resize (GTK_WIDGET (window));
}
/**
@@ -4498,7 +4498,7 @@ gtk_window_resize (GtkWindow *window,
info->resize_width = width;
info->resize_height = height;
gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
gtk_widget_queue_resize (GTK_WIDGET (window));
}
/**
@@ -7129,7 +7129,7 @@ gtk_window_move_resize (GtkWindow *window)
* to postpone our configure request until later.
*/
info->last = saved_last_info;
gtk_widget_queue_resize_no_redraw (widget); /* might recurse for GTK_RESIZE_IMMEDIATE */
gtk_widget_queue_resize (widget); /* might recurse for GTK_RESIZE_IMMEDIATE */
}
return; /* Bail out, we didn't really process the move/resize */
@@ -7963,7 +7963,7 @@ gtk_window_set_resizable (GtkWindow *window,
update_window_buttons (window);
gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
gtk_widget_queue_resize (GTK_WIDGET (window));
g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_RESIZABLE]);
}

Some files were not shown because too many files have changed in this diff Show More