Compare commits
21 Commits
subsurface
...
path-point
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b533dfa0da | ||
|
|
1de378655e | ||
|
|
9cdc549bf9 | ||
|
|
9725d33196 | ||
|
|
2384c57051 | ||
|
|
0d178b6a4d | ||
|
|
bb98216951 | ||
|
|
c01f3d24ed | ||
|
|
068163939e | ||
|
|
cbee6ee382 | ||
|
|
c4c6d72375 | ||
|
|
a25484bb8c | ||
|
|
0582da02b3 | ||
|
|
1dd3986b03 | ||
|
|
44119a7a57 | ||
|
|
cc60d519f3 | ||
|
|
a592e52fab | ||
|
|
366abbb930 | ||
|
|
bac372d2a4 | ||
|
|
b48ec3ad8b | ||
|
|
471cbc8c41 |
@@ -30,16 +30,8 @@ variables:
|
|||||||
|
|
||||||
workflow:
|
workflow:
|
||||||
rules:
|
rules:
|
||||||
# run merge request pipelines
|
|
||||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
|
||||||
# do not run branch pipelines if corresponding merge requests exist...
|
|
||||||
# (this avoids duplicate pipelines)
|
|
||||||
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
|
|
||||||
when: never
|
|
||||||
# ...but otherwise run branch pipelines
|
|
||||||
- if: $CI_COMMIT_BRANCH
|
|
||||||
# run tag pipelines
|
|
||||||
- if: $CI_COMMIT_TAG
|
- if: $CI_COMMIT_TAG
|
||||||
|
- if: $CI_COMMIT_BRANCH
|
||||||
|
|
||||||
default:
|
default:
|
||||||
retry:
|
retry:
|
||||||
@@ -205,44 +197,28 @@ msys2-mingw64:
|
|||||||
paths:
|
paths:
|
||||||
- "${CI_PROJECT_DIR}/_build/gtkdll.tar.gz"
|
- "${CI_PROJECT_DIR}/_build/gtkdll.tar.gz"
|
||||||
|
|
||||||
macos-x86_64:
|
macos:
|
||||||
|
# Sadly, this fails regularly, and its failure is never enlightening
|
||||||
|
allow_failure: true
|
||||||
rules:
|
rules:
|
||||||
# Do not run in forks as the runner is not available there.
|
|
||||||
- if: $CI_PROJECT_NAMESPACE == "GNOME"
|
- if: $CI_PROJECT_NAMESPACE == "GNOME"
|
||||||
stage: build
|
stage: build
|
||||||
tags:
|
tags:
|
||||||
- macosintel
|
- macos
|
||||||
needs: []
|
needs: []
|
||||||
variables:
|
|
||||||
MESON_FORCE_BACKTRACKE: 1
|
|
||||||
TMPDIR: /Users/Shared/work/tmp
|
|
||||||
SDKROOT: /opt/sdks/MacOSX10.13.4.sdk
|
|
||||||
PIP_CACHE_DIR: /Users/Shared/build/cache
|
|
||||||
PIPENV_CACHE_DIR: $PIP_CACHE_DIR
|
|
||||||
PYTHONPYCACHEPREFIX: $PIP_CACHE_DIR
|
|
||||||
EXTRA_MESON_FLAGS: "-Dgobject-introspection:werror=false"
|
|
||||||
before_script:
|
before_script:
|
||||||
# Not using ccache on purpose as it accelerates the build so much that it
|
|
||||||
# can trigger race conditions in the gobject-introspection subproject.
|
|
||||||
- bash .gitlab-ci/show-info-osx.sh
|
- bash .gitlab-ci/show-info-osx.sh
|
||||||
- /opt/macports/bin/python3.10 -m venv .venv
|
- pip3 install --user meson~=1.0
|
||||||
- ln -s /opt/cmake/CMake.app/Contents/bin/cmake .venv/bin
|
- pip3 install --user ninja
|
||||||
- ln -s /opt/pkg-config/bin/pkg-config .venv/bin
|
- export PATH=/Users/gitlabrunner/Library/Python/3.7/bin:$PATH
|
||||||
- ln -s /opt/bison/bin/bison .venv/bin
|
- export MESON_FORCE_BACKTRACE=1
|
||||||
- source .venv/bin/activate
|
|
||||||
- pip3 install meson==1.2.0
|
|
||||||
- pip3 install ninja==1.11.1
|
|
||||||
- pip3 install /Users/Shared/build/pkgs/PyGObject-3.44.0-cp310-cp310-macosx_10_13_x86_64.whl
|
|
||||||
/Users/Shared/build/pkgs/pycairo-1.23.0-cp310-cp310-macosx_10_13_x86_64.whl
|
|
||||||
script:
|
script:
|
||||||
- meson setup
|
- meson setup ${COMMON_MESON_FLAGS}
|
||||||
${COMMON_MESON_FLAGS}
|
|
||||||
${EXTRA_MESON_FLAGS}
|
|
||||||
-Dx11-backend=false
|
-Dx11-backend=false
|
||||||
-Dbroadway-backend=true
|
-Dbroadway-backend=true
|
||||||
-Dmacos-backend=true
|
-Dmacos-backend=true
|
||||||
-Dmedia-gstreamer=disabled
|
-Dmedia-gstreamer=disabled
|
||||||
-Dintrospection=enabled
|
-Dintrospection=disabled
|
||||||
-Dcpp_std=c++11
|
-Dcpp_std=c++11
|
||||||
-Dpixman:tests=disabled
|
-Dpixman:tests=disabled
|
||||||
-Dlibjpeg-turbo:simd=disabled
|
-Dlibjpeg-turbo:simd=disabled
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ case "${backend}" in
|
|||||||
--suite=gtk \
|
--suite=gtk \
|
||||||
--no-suite=failing \
|
--no-suite=failing \
|
||||||
--no-suite=flaky \
|
--no-suite=flaky \
|
||||||
--no-suite=headless \
|
|
||||||
--no-suite=gsk-compare-broadway
|
--no-suite=gsk-compare-broadway
|
||||||
|
|
||||||
# Store the exit code for the CI run, but always
|
# Store the exit code for the CI run, but always
|
||||||
@@ -46,7 +45,6 @@ case "${backend}" in
|
|||||||
--suite=gtk \
|
--suite=gtk \
|
||||||
--no-suite=failing \
|
--no-suite=failing \
|
||||||
--no-suite=flaky \
|
--no-suite=flaky \
|
||||||
--no-suite=headless \
|
|
||||||
--no-suite=${backend}_failing \
|
--no-suite=${backend}_failing \
|
||||||
--no-suite=gsk-compare-broadway
|
--no-suite=gsk-compare-broadway
|
||||||
exit_code=$?
|
exit_code=$?
|
||||||
@@ -69,7 +67,6 @@ case "${backend}" in
|
|||||||
--suite=gtk \
|
--suite=gtk \
|
||||||
--no-suite=failing \
|
--no-suite=failing \
|
||||||
--no-suite=flaky \
|
--no-suite=flaky \
|
||||||
--no-suite=headless \
|
|
||||||
--no-suite=gsk-compare-opengl
|
--no-suite=gsk-compare-opengl
|
||||||
|
|
||||||
kill ${server}
|
kill ${server}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliar
|
|||||||
|
|
||||||
:: FIXME: make warnings fatal
|
:: FIXME: make warnings fatal
|
||||||
pip3 install --upgrade --user meson~=0.64 || goto :error
|
pip3 install --upgrade --user meson~=0.64 || goto :error
|
||||||
meson setup -Dbackend_max_links=1 -Ddebug=false -Dmedia-gstreamer=disabled _build || goto :error
|
meson -Ddebug=false -Dmedia-gstreamer=disabled _build || goto :error
|
||||||
ninja -C _build || goto :error
|
ninja -C _build || goto :error
|
||||||
|
|
||||||
goto :EOF
|
goto :EOF
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ The issue tracker is meant to be used for actionable issues only.
|
|||||||
|
|
||||||
You should not open a new issue for security related questions.
|
You should not open a new issue for security related questions.
|
||||||
|
|
||||||
When in doubt, follow [security](https://security.gnome.org/).
|
When in doubt, send an email to the [security](mailto:security@gnome.org)
|
||||||
|
mailing list.
|
||||||
|
|
||||||
### Bug reports
|
### Bug reports
|
||||||
|
|
||||||
@@ -243,11 +244,13 @@ people committing to GTK to follow a few rules:
|
|||||||
code, you should always ask. If your change is minor and you've been
|
code, you should always ask. If your change is minor and you've been
|
||||||
working on GTK for a while it probably isn't necessary to ask. But when
|
working on GTK for a while it probably isn't necessary to ask. But when
|
||||||
in doubt, ask. Even if your change is correct, somebody may know a
|
in doubt, ask. Even if your change is correct, somebody may know a
|
||||||
better way to do things.
|
better way to do things. If you are making changes to GTK, you should
|
||||||
The `gtk` [room on matrix](https://matrix.to/#/#gtk:gnome.org) is also a
|
be subscribed to the [gtk-devel](https://mail.gnome.org/mailman/listinfo/gtk-devel-list)
|
||||||
good place to find GTK developers to discuss changes, but if you live
|
mailing list; this is a good place to ask about intended changes.
|
||||||
outside of the EU/US time zones, the [gtk tag on the GNOME Discourse instance](https://discourse.gnome.org/tag/gtk)
|
The `#gtk` IRC channel on irc.gnome.org is also a good place to find GTK
|
||||||
is the most certain and preferred method.
|
developers to discuss changes, but if you live outside of the EU/US time
|
||||||
|
zones, an email to the gtk-devel mailing list is the most certain and
|
||||||
|
preferred method.
|
||||||
|
|
||||||
0. Ask _first_.
|
0. Ask _first_.
|
||||||
|
|
||||||
|
|||||||
194
NEWS
@@ -1,198 +1,6 @@
|
|||||||
Overview of Changes in 4.13.3, xx-xx-xxxx
|
Overview of Changes in 4.13.0, xx-xx-xxxx
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
Overview of Changes in 4.13.2, 22-10-2023
|
|
||||||
=========================================
|
|
||||||
|
|
||||||
* GtkPrintdialog:
|
|
||||||
- New async-style api to replace GtkPrintOperation
|
|
||||||
|
|
||||||
* GtkEmojiChooser:
|
|
||||||
- Add more languages: Bengali, Hindi, Japanese, Finnish,
|
|
||||||
Thai and Norwegian bokmål
|
|
||||||
|
|
||||||
* Accessibility:
|
|
||||||
- Fix some utf8 handling issues
|
|
||||||
|
|
||||||
* GDK:
|
|
||||||
- Add support for dmabuf textures, with GdkDmabufTextureBuilder
|
|
||||||
- Add a few more supported memory formats for textures
|
|
||||||
|
|
||||||
* GSK:
|
|
||||||
- Add a fast-path for masking color
|
|
||||||
- Add support for importing dmabuf textures
|
|
||||||
- Handle GLES better by using some extensions
|
|
||||||
|
|
||||||
* Translation updates:
|
|
||||||
Catalan
|
|
||||||
Russian
|
|
||||||
Turkish
|
|
||||||
|
|
||||||
|
|
||||||
Overview of Changes in 4.13.1, 28-09-2023
|
|
||||||
=========================================
|
|
||||||
|
|
||||||
* GtkTooltip:
|
|
||||||
- Don't cross native boundaries when looking for tooltips
|
|
||||||
|
|
||||||
* GtkCenterLayout, GtkEntry, GtkSearchEntry:
|
|
||||||
- Fix some issues with baseline handling
|
|
||||||
|
|
||||||
* GtkColorButton, GtkFontButton:
|
|
||||||
- Propagate focus-on-click
|
|
||||||
|
|
||||||
* GtkFileChooser:
|
|
||||||
- Make "Visit file" scroll to the file
|
|
||||||
|
|
||||||
* GtkSwitch:
|
|
||||||
- Respect text direction
|
|
||||||
|
|
||||||
* GtkWindow:
|
|
||||||
- Don't assume titlebars are GtkHeaderBars
|
|
||||||
|
|
||||||
* Printing:
|
|
||||||
- Fix some problems with the portal implementation
|
|
||||||
- Add a new simple print API: GtkPrintDialog
|
|
||||||
|
|
||||||
* Paths:
|
|
||||||
- GskPathMeasure performance has been improved
|
|
||||||
- Add custom contours for circles, rounded rectangles and rectangles
|
|
||||||
- Simplify GskPathPoint handling
|
|
||||||
- gsk_path_point_get_closest_point now returns the distance as well
|
|
||||||
- Make GskPathBuilder simplify curves
|
|
||||||
|
|
||||||
* Input:
|
|
||||||
- Handle (some) single-key compose sequences
|
|
||||||
- Fix active state tracking with sensitivity changes and grabs
|
|
||||||
|
|
||||||
* GSK:
|
|
||||||
- Make the repeated gradients match between GL and cairo
|
|
||||||
- Make rounded rect shrinking match between Vulkan, GL and cairo
|
|
||||||
- Fix parsing of text nodes with color glyphs
|
|
||||||
- Restrict an optimization to the cases where it is crrect
|
|
||||||
- Fix rendering of shadows with opacity
|
|
||||||
- The Vulkan renderer now requires Vulkan 1.2
|
|
||||||
- GL: Transition gradients unpremultiplied
|
|
||||||
- GL: Fix clipping of shadows
|
|
||||||
- GL: Some optimizations
|
|
||||||
- Broadway: Fix memory leaks in the renderer
|
|
||||||
|
|
||||||
* Wayland:
|
|
||||||
- Make activation more reliable
|
|
||||||
|
|
||||||
* macOS:
|
|
||||||
- Clamp damage regions to the surface size
|
|
||||||
|
|
||||||
* Tools:
|
|
||||||
- gtk4-path-tool gained restrict and reverse commands
|
|
||||||
- gtk4-path-tool show and render can show control points
|
|
||||||
|
|
||||||
* Demos:
|
|
||||||
- Add a demo for hit testing with paths
|
|
||||||
|
|
||||||
* Build:
|
|
||||||
- Fix build problems with C++ compilers
|
|
||||||
|
|
||||||
* Deprecations:
|
|
||||||
- gtk_window_present_with_time
|
|
||||||
|
|
||||||
* Translation updates
|
|
||||||
Brazilian Portuguese
|
|
||||||
British English
|
|
||||||
Catalan
|
|
||||||
Chinese (China)
|
|
||||||
Czech
|
|
||||||
Danish
|
|
||||||
Dutch
|
|
||||||
Esperanto
|
|
||||||
Galician
|
|
||||||
Georgian
|
|
||||||
Italian
|
|
||||||
Korean
|
|
||||||
Latvian
|
|
||||||
Lithuanian
|
|
||||||
Persian
|
|
||||||
Polish
|
|
||||||
Punjabi
|
|
||||||
Slovenian
|
|
||||||
Turkish
|
|
||||||
|
|
||||||
|
|
||||||
Overview of Changes in 4.13.0, 25-08-2023
|
|
||||||
=========================================
|
|
||||||
|
|
||||||
* GskPath, GskPathBuilder, GskPathMeasure:
|
|
||||||
Data types and APIs for path rendering. These APIs are still
|
|
||||||
considered experimental, and may change until 4.14. Please try
|
|
||||||
them out and give us feedback. Documentation can be found
|
|
||||||
here: https://docs.gtk.org/gsk4/paths.html
|
|
||||||
|
|
||||||
* GtkGridView:
|
|
||||||
- Fix a crash when scrolling
|
|
||||||
|
|
||||||
* GtkColumnView:
|
|
||||||
- Fix a refcounting issue in the new scroll_to api
|
|
||||||
|
|
||||||
* GtkTreeView
|
|
||||||
- Fix style classes for sort arrows
|
|
||||||
|
|
||||||
* GtkEntry:
|
|
||||||
- Improve tracking of user changes (for undo)
|
|
||||||
|
|
||||||
* GtkNotebook:
|
|
||||||
- Fix a critical when switching pages
|
|
||||||
|
|
||||||
* GtkColor/FontDialogButton:
|
|
||||||
- Make these widgets activatable
|
|
||||||
|
|
||||||
* GtkMenuButton:
|
|
||||||
- Fix problems with focus handling
|
|
||||||
- Fix problems with DND
|
|
||||||
- Make flags a settable property
|
|
||||||
|
|
||||||
* GtkShortcutsWindow:
|
|
||||||
- Add API to build shortcuts windows programmatically
|
|
||||||
|
|
||||||
* Printing
|
|
||||||
- Fix the cpdb backend build
|
|
||||||
|
|
||||||
* MacOS:
|
|
||||||
- Make file filters work again
|
|
||||||
|
|
||||||
* GSK:
|
|
||||||
- Fix issues with color matrix nodes
|
|
||||||
|
|
||||||
* Wayland:
|
|
||||||
- Fix a crash with compositors other than gnome-shell
|
|
||||||
|
|
||||||
* Deprecations:
|
|
||||||
- Remaining GtkTreeModel-related types
|
|
||||||
|
|
||||||
* Demos:
|
|
||||||
- Add a few path demos to gtk4-demo
|
|
||||||
|
|
||||||
* Tools:
|
|
||||||
- gtk4-path-tool provides a commandline interface for paths
|
|
||||||
|
|
||||||
* Translation updates:
|
|
||||||
Basque
|
|
||||||
Catalan
|
|
||||||
Finnish
|
|
||||||
Galician
|
|
||||||
Georgian
|
|
||||||
German
|
|
||||||
Greek
|
|
||||||
Indonesian
|
|
||||||
Kazakh
|
|
||||||
Persian
|
|
||||||
Polish
|
|
||||||
Romanian
|
|
||||||
Spanish
|
|
||||||
Swedish
|
|
||||||
Turkish
|
|
||||||
Ukrainian
|
|
||||||
|
|
||||||
|
|
||||||
Overview of Changes in 4.12.0, 05-08-2023
|
Overview of Changes in 4.12.0, 05-08-2023
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.7 KiB |
@@ -223,7 +223,7 @@ delete_messages (gpointer data)
|
|||||||
static void
|
static void
|
||||||
pop_message (GtkWidget *status)
|
pop_message (GtkWidget *status)
|
||||||
{
|
{
|
||||||
GList *messages = (GList *) g_object_steal_data (G_OBJECT (status), "messages");
|
GList *messages = (GList *) g_object_get_data (G_OBJECT (status), "messages");
|
||||||
|
|
||||||
if (messages)
|
if (messages)
|
||||||
{
|
{
|
||||||
@@ -241,7 +241,7 @@ static void
|
|||||||
push_message (GtkWidget *status,
|
push_message (GtkWidget *status,
|
||||||
const char *message)
|
const char *message)
|
||||||
{
|
{
|
||||||
GList *messages = (GList *) g_object_steal_data (G_OBJECT (status), "messages");
|
GList *messages = (GList *) g_object_get_data (G_OBJECT (status), "messages");
|
||||||
|
|
||||||
gtk_label_set_label (GTK_LABEL (status), message);
|
gtk_label_set_label (GTK_LABEL (status), message);
|
||||||
messages = g_list_prepend (messages, g_strdup (message));
|
messages = g_list_prepend (messages, g_strdup (message));
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1019 B After Width: | Height: | Size: 985 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -127,7 +127,6 @@
|
|||||||
<file>fishbowl.ui</file>
|
<file>fishbowl.ui</file>
|
||||||
<file>gtkfishbowl.c</file>
|
<file>gtkfishbowl.c</file>
|
||||||
<file>gtkfishbowl.h</file>
|
<file>gtkfishbowl.h</file>
|
||||||
<file>tiger.node</file>
|
|
||||||
</gresource>
|
</gresource>
|
||||||
<gresource prefix="/frames">
|
<gresource prefix="/frames">
|
||||||
<file>frames.ui</file>
|
<file>frames.ui</file>
|
||||||
@@ -338,8 +337,6 @@
|
|||||||
<file>password_entry.c</file>
|
<file>password_entry.c</file>
|
||||||
<file>path_fill.c</file>
|
<file>path_fill.c</file>
|
||||||
<file>path_maze.c</file>
|
<file>path_maze.c</file>
|
||||||
<file>path_spinner.c</file>
|
|
||||||
<file>path_walk.c</file>
|
|
||||||
<file>path_text.c</file>
|
<file>path_text.c</file>
|
||||||
<file>peg_solitaire.c</file>
|
<file>peg_solitaire.c</file>
|
||||||
<file>pickers.c</file>
|
<file>pickers.c</file>
|
||||||
@@ -426,10 +423,6 @@
|
|||||||
<gresource prefix="/fontrendering">
|
<gresource prefix="/fontrendering">
|
||||||
<file>fontrendering.ui</file>
|
<file>fontrendering.ui</file>
|
||||||
</gresource>
|
</gresource>
|
||||||
<gresource prefix="/path_walk">
|
|
||||||
<file>path_walk.ui</file>
|
|
||||||
<file compressed="true">path_world.txt</file>
|
|
||||||
</gresource>
|
|
||||||
<gresource prefix="/path_text">
|
<gresource prefix="/path_text">
|
||||||
<file>path_text.ui</file>
|
<file>path_text.ui</file>
|
||||||
</gresource>
|
</gresource>
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ transition (GtkWidget *widget,
|
|||||||
{
|
{
|
||||||
DemoWidget *self = DEMO_WIDGET (widget);
|
DemoWidget *self = DEMO_WIDGET (widget);
|
||||||
DemoLayout *demo_layout = DEMO_LAYOUT (gtk_widget_get_layout_manager (widget));
|
DemoLayout *demo_layout = DEMO_LAYOUT (gtk_widget_get_layout_manager (widget));
|
||||||
gint64 now = gdk_frame_clock_get_frame_time (frame_clock);
|
gint64 now = g_get_monotonic_time ();
|
||||||
|
|
||||||
gtk_widget_queue_allocate (widget);
|
gtk_widget_queue_allocate (widget);
|
||||||
|
|
||||||
@@ -66,13 +66,11 @@ clicked (GtkGestureClick *gesture,
|
|||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
DemoWidget *self = data;
|
DemoWidget *self = data;
|
||||||
GdkFrameClock *frame_clock;
|
|
||||||
|
|
||||||
if (self->tick_id != 0)
|
if (self->tick_id != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
frame_clock = gtk_widget_get_frame_clock (GTK_WIDGET (self));
|
self->start_time = g_get_monotonic_time ();
|
||||||
self->start_time = gdk_frame_clock_get_frame_time (frame_clock);
|
|
||||||
self->tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (self), transition, NULL, NULL);
|
self->tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (self), transition, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.4 KiB |
@@ -11,9 +11,6 @@
|
|||||||
#include "gtkgears.h"
|
#include "gtkgears.h"
|
||||||
#include "gskshaderpaintable.h"
|
#include "gskshaderpaintable.h"
|
||||||
|
|
||||||
#include "nodewidget.h"
|
|
||||||
#include "graphwidget.h"
|
|
||||||
|
|
||||||
const char *const css =
|
const char *const css =
|
||||||
".blurred-button {"
|
".blurred-button {"
|
||||||
" box-shadow: 0px 0px 5px 10px rgba(0, 0, 0, 0.5);"
|
" box-shadow: 0px 0px 5px 10px rgba(0, 0, 0, 0.5);"
|
||||||
@@ -74,7 +71,14 @@ create_blurred_button (void)
|
|||||||
static GtkWidget *
|
static GtkWidget *
|
||||||
create_font_button (void)
|
create_font_button (void)
|
||||||
{
|
{
|
||||||
return gtk_font_dialog_button_new (gtk_font_dialog_new ());
|
GtkFontDialog *dialog;
|
||||||
|
GtkWidget *button;
|
||||||
|
|
||||||
|
dialog = gtk_font_dialog_new ();
|
||||||
|
button = gtk_font_dialog_button_new (dialog);
|
||||||
|
g_object_unref (dialog);
|
||||||
|
|
||||||
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GtkWidget *
|
static GtkWidget *
|
||||||
@@ -204,18 +208,6 @@ create_menu_button (void)
|
|||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GtkWidget *
|
|
||||||
create_tiger (void)
|
|
||||||
{
|
|
||||||
return node_widget_new ("/fishbowl/tiger.node");
|
|
||||||
}
|
|
||||||
|
|
||||||
static GtkWidget *
|
|
||||||
create_graph (void)
|
|
||||||
{
|
|
||||||
return graph_widget_new ();
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
GtkWidget * (*create_func) (void);
|
GtkWidget * (*create_func) (void);
|
||||||
@@ -233,8 +225,6 @@ static const struct {
|
|||||||
{ "Switch", create_switch },
|
{ "Switch", create_switch },
|
||||||
{ "Menubutton", create_menu_button },
|
{ "Menubutton", create_menu_button },
|
||||||
{ "Shader", create_cogs },
|
{ "Shader", create_cogs },
|
||||||
{ "Tiger", create_tiger },
|
|
||||||
{ "Graph", create_graph },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int selected_widget_type = -1;
|
static int selected_widget_type = -1;
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -1,153 +0,0 @@
|
|||||||
#include "graphwidget.h"
|
|
||||||
|
|
||||||
struct _GraphWidget
|
|
||||||
{
|
|
||||||
GtkWidget parent_instance;
|
|
||||||
|
|
||||||
GskPath *path;
|
|
||||||
GskStroke *stroke;
|
|
||||||
GdkRGBA color;
|
|
||||||
|
|
||||||
guint tick_cb;
|
|
||||||
guint64 start_time;
|
|
||||||
|
|
||||||
double period;
|
|
||||||
double amplitude;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _GraphWidgetClass
|
|
||||||
{
|
|
||||||
GtkWidgetClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (GraphWidget, graph_widget, GTK_TYPE_WIDGET)
|
|
||||||
|
|
||||||
static void
|
|
||||||
update_path (GraphWidget *self,
|
|
||||||
float amplitude)
|
|
||||||
{
|
|
||||||
graphene_point_t p[20];
|
|
||||||
GskPathBuilder *builder;
|
|
||||||
|
|
||||||
g_clear_pointer (&self->path, gsk_path_unref);
|
|
||||||
|
|
||||||
for (int i = 0; i < 20; i++)
|
|
||||||
{
|
|
||||||
p[i].x = 10 * i;
|
|
||||||
p[i].y = 50;
|
|
||||||
|
|
||||||
if (i % 4 == 1 || i % 4 == 2)
|
|
||||||
{
|
|
||||||
if (i % 8 < 4)
|
|
||||||
p[i].y += amplitude;
|
|
||||||
else
|
|
||||||
p[i].y -= amplitude;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
builder = gsk_path_builder_new ();
|
|
||||||
gsk_path_builder_move_to (builder, p[0].x, p[0].y);
|
|
||||||
|
|
||||||
for (int i = 0; i < 20; i += 4)
|
|
||||||
gsk_path_builder_cubic_to (builder,
|
|
||||||
p[i+1].x, p[i+1].y,
|
|
||||||
p[i+2].x, p[i+2].y,
|
|
||||||
p[i+3].x, p[i+3].y);
|
|
||||||
|
|
||||||
self->path = gsk_path_builder_free_to_path (builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
tick_cb (GtkWidget *widget,
|
|
||||||
GdkFrameClock *frame_clock,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
GraphWidget *self = GRAPH_WIDGET (widget);
|
|
||||||
guint64 now;
|
|
||||||
double angle;
|
|
||||||
|
|
||||||
now = gdk_frame_clock_get_frame_time (frame_clock);
|
|
||||||
|
|
||||||
if (self->start_time == 0)
|
|
||||||
self->start_time = now;
|
|
||||||
|
|
||||||
angle = 360 * (now - self->start_time) / (double)(self->period * G_TIME_SPAN_MINUTE);
|
|
||||||
update_path (self, sin (angle) * self->amplitude);
|
|
||||||
|
|
||||||
gtk_widget_queue_draw (widget);
|
|
||||||
|
|
||||||
return G_SOURCE_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
graph_widget_init (GraphWidget *self)
|
|
||||||
{
|
|
||||||
self->color.red = g_random_double_range (0, 1);
|
|
||||||
self->color.green = g_random_double_range (0, 1);
|
|
||||||
self->color.blue = g_random_double_range (0, 1);
|
|
||||||
self->color.alpha = 1;
|
|
||||||
|
|
||||||
self->period = g_random_double_range (0.5, 1);
|
|
||||||
self->amplitude = g_random_double_range (10, 25);
|
|
||||||
|
|
||||||
self->stroke = gsk_stroke_new (2);
|
|
||||||
|
|
||||||
update_path (self, 0);
|
|
||||||
|
|
||||||
self->start_time = 0;
|
|
||||||
self->tick_cb = gtk_widget_add_tick_callback (GTK_WIDGET (self), tick_cb, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
graph_widget_dispose (GObject *object)
|
|
||||||
{
|
|
||||||
GraphWidget *self = GRAPH_WIDGET (object);
|
|
||||||
|
|
||||||
g_clear_pointer (&self->path, gsk_path_unref);
|
|
||||||
gsk_stroke_free (self->stroke);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (graph_widget_parent_class)->dispose (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
graph_widget_snapshot (GtkWidget *widget,
|
|
||||||
GtkSnapshot *snapshot)
|
|
||||||
{
|
|
||||||
GraphWidget *self = GRAPH_WIDGET (widget);
|
|
||||||
|
|
||||||
gtk_snapshot_append_stroke (snapshot, self->path, self->stroke, &self->color);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
graph_widget_measure (GtkWidget *widget,
|
|
||||||
GtkOrientation orientation,
|
|
||||||
int for_size,
|
|
||||||
int *minimum,
|
|
||||||
int *natural,
|
|
||||||
int *minimum_baseline,
|
|
||||||
int *natural_baseline)
|
|
||||||
{
|
|
||||||
if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
|
||||||
*minimum = *natural = 200;
|
|
||||||
else
|
|
||||||
*minimum = *natural = 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
graph_widget_class_init (GraphWidgetClass *class)
|
|
||||||
{
|
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
|
||||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
|
||||||
|
|
||||||
object_class->dispose = graph_widget_dispose;
|
|
||||||
|
|
||||||
widget_class->snapshot = graph_widget_snapshot;
|
|
||||||
widget_class->measure = graph_widget_measure;
|
|
||||||
}
|
|
||||||
|
|
||||||
GtkWidget *
|
|
||||||
graph_widget_new (void)
|
|
||||||
{
|
|
||||||
return g_object_new (GRAPH_TYPE_WIDGET, NULL);
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
|
||||||
|
|
||||||
#define GRAPH_TYPE_WIDGET (graph_widget_get_type ())
|
|
||||||
G_DECLARE_FINAL_TYPE (GraphWidget, graph_widget, GRAPH, WIDGET, GtkWidget)
|
|
||||||
|
|
||||||
GtkWidget * graph_widget_new (void);
|
|
||||||
@@ -840,24 +840,24 @@ gtk_gears_unrealize (GtkWidget *widget)
|
|||||||
GtkGearsPrivate *priv = gtk_gears_get_instance_private ((GtkGears *) widget);
|
GtkGearsPrivate *priv = gtk_gears_get_instance_private ((GtkGears *) widget);
|
||||||
|
|
||||||
gtk_gl_area_make_current (glarea);
|
gtk_gl_area_make_current (glarea);
|
||||||
if (gtk_gl_area_get_error (glarea) == NULL)
|
if (gtk_gl_area_get_error (glarea) != NULL)
|
||||||
{
|
return;
|
||||||
/* Release the resources associated with OpenGL */
|
|
||||||
if (priv->gear_vbo[0] != 0)
|
|
||||||
glDeleteBuffers (1, &(priv->gear_vbo[0]));
|
|
||||||
|
|
||||||
if (priv->gear_vbo[1] != 0)
|
/* Release the resources associated with OpenGL */
|
||||||
glDeleteBuffers (1, &(priv->gear_vbo[1]));
|
if (priv->gear_vbo[0] != 0)
|
||||||
|
glDeleteBuffers (1, &(priv->gear_vbo[0]));
|
||||||
|
|
||||||
if (priv->gear_vbo[2] != 0)
|
if (priv->gear_vbo[1] != 0)
|
||||||
glDeleteBuffers (1, &(priv->gear_vbo[2]));
|
glDeleteBuffers (1, &(priv->gear_vbo[1]));
|
||||||
|
|
||||||
if (priv->vao != 0)
|
if (priv->gear_vbo[2] != 0)
|
||||||
glDeleteVertexArrays (1, &priv->vao);
|
glDeleteBuffers (1, &(priv->gear_vbo[2]));
|
||||||
|
|
||||||
if (priv->program != 0)
|
if (priv->vao != 0)
|
||||||
glDeleteProgram (priv->program);
|
glDeleteVertexArrays (1, &priv->vao);
|
||||||
}
|
|
||||||
|
if (priv->program != 0)
|
||||||
|
glDeleteProgram (priv->program);
|
||||||
|
|
||||||
priv->ModelViewProjectionMatrix_location = 0;
|
priv->ModelViewProjectionMatrix_location = 0;
|
||||||
priv->NormalMatrix_location = 0;
|
priv->NormalMatrix_location = 0;
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -74,8 +74,6 @@ demos = files([
|
|||||||
'password_entry.c',
|
'password_entry.c',
|
||||||
'path_fill.c',
|
'path_fill.c',
|
||||||
'path_maze.c',
|
'path_maze.c',
|
||||||
'path_spinner.c',
|
|
||||||
'path_walk.c',
|
|
||||||
'path_text.c',
|
'path_text.c',
|
||||||
'peg_solitaire.c',
|
'peg_solitaire.c',
|
||||||
'pickers.c',
|
'pickers.c',
|
||||||
@@ -141,8 +139,6 @@ extra_demo_sources = files([
|
|||||||
'unicode-names.c',
|
'unicode-names.c',
|
||||||
'suggestionentry.c',
|
'suggestionentry.c',
|
||||||
'language-names.c',
|
'language-names.c',
|
||||||
'nodewidget.c',
|
|
||||||
'graphwidget.c',
|
|
||||||
])
|
])
|
||||||
|
|
||||||
if os_unix
|
if os_unix
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.3 KiB |
@@ -1,76 +0,0 @@
|
|||||||
#include "nodewidget.h"
|
|
||||||
|
|
||||||
struct _NodeWidget
|
|
||||||
{
|
|
||||||
GtkWidget parent_instance;
|
|
||||||
|
|
||||||
GskRenderNode *node;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _NodeWidgetClass
|
|
||||||
{
|
|
||||||
GtkWidgetClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (NodeWidget, node_widget, GTK_TYPE_WIDGET)
|
|
||||||
|
|
||||||
static void
|
|
||||||
node_widget_init (NodeWidget *self)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
node_widget_dispose (GObject *object)
|
|
||||||
{
|
|
||||||
NodeWidget *self = NODE_WIDGET (object);
|
|
||||||
|
|
||||||
gsk_render_node_unref (self->node);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (node_widget_parent_class)->dispose (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
node_widget_snapshot (GtkWidget *widget,
|
|
||||||
GtkSnapshot *snapshot)
|
|
||||||
{
|
|
||||||
NodeWidget *self = NODE_WIDGET (widget);
|
|
||||||
|
|
||||||
gtk_snapshot_append_node (snapshot, self->node);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
node_widget_class_init (NodeWidgetClass *class)
|
|
||||||
{
|
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
|
||||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
|
||||||
|
|
||||||
object_class->dispose = node_widget_dispose;
|
|
||||||
|
|
||||||
widget_class->snapshot = node_widget_snapshot;
|
|
||||||
}
|
|
||||||
|
|
||||||
GtkWidget *
|
|
||||||
node_widget_new (const char *resource)
|
|
||||||
{
|
|
||||||
NodeWidget *self;
|
|
||||||
GBytes *bytes;
|
|
||||||
GskRenderNode *node;
|
|
||||||
graphene_rect_t bounds;
|
|
||||||
float scale;
|
|
||||||
GskTransform *transform;
|
|
||||||
|
|
||||||
self = g_object_new (NODE_TYPE_WIDGET, NULL);
|
|
||||||
|
|
||||||
bytes = g_resources_lookup_data (resource, 0, NULL);
|
|
||||||
node = gsk_render_node_deserialize (bytes, NULL, NULL);
|
|
||||||
g_bytes_unref (bytes);
|
|
||||||
|
|
||||||
gsk_render_node_get_bounds (node, &bounds);
|
|
||||||
scale = MIN (100.0/bounds.size.width, 100.0/bounds.size.height);
|
|
||||||
transform = gsk_transform_scale (NULL, scale, scale);
|
|
||||||
self->node = gsk_transform_node_new (node, transform);
|
|
||||||
gsk_transform_unref (transform);
|
|
||||||
gsk_render_node_unref (node);
|
|
||||||
|
|
||||||
return GTK_WIDGET (self);
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
|
||||||
|
|
||||||
#define NODE_TYPE_WIDGET (node_widget_get_type ())
|
|
||||||
G_DECLARE_FINAL_TYPE (NodeWidget, node_widget, NODE, WIDGET, GtkWidget)
|
|
||||||
|
|
||||||
GtkWidget * node_widget_new (const char *file);
|
|
||||||
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -1,254 +1,311 @@
|
|||||||
/* Path/Fill and Stroke
|
/* Path/Fill
|
||||||
*
|
*
|
||||||
* This demo shows how to use GskPath to draw shapes that are (a bit)
|
* This demo shows how to use PangoCairo to draw text with more than
|
||||||
* more complex than a rounded rectangle.
|
* just a single color.
|
||||||
*
|
|
||||||
* It also demonstrates printing to a stream with GtkPrintDialog.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <glib/gi18n.h>
|
#include <glib/gi18n.h>
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include <cairo-pdf.h>
|
|
||||||
|
|
||||||
#include "paintable.h"
|
#include "paintable.h"
|
||||||
|
|
||||||
#define GTK_TYPE_LOGO_PAINTABLE (gtk_logo_paintable_get_type ())
|
#define GTK_TYPE_PATH_PAINTABLE (gtk_path_paintable_get_type ())
|
||||||
G_DECLARE_FINAL_TYPE (GtkLogoPaintable, gtk_logo_paintable, GTK, LOGO_PAINTABLE, GObject)
|
G_DECLARE_FINAL_TYPE (GtkPathPaintable, gtk_path_paintable, GTK, PATH_PAINTABLE, GObject)
|
||||||
|
|
||||||
struct _GtkLogoPaintable
|
struct _GtkPathPaintable
|
||||||
{
|
{
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
|
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
GskPath *path[3];
|
GskPath *path;
|
||||||
GdkRGBA color[3];
|
GdkPaintable *background;
|
||||||
|
|
||||||
GskPath *stroke_path;
|
|
||||||
GskStroke *stroke1;
|
|
||||||
GskStroke *stroke2;
|
|
||||||
GdkRGBA stroke_color;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GtkLogoPaintableClass
|
struct _GtkPathPaintableClass
|
||||||
{
|
{
|
||||||
GObjectClass parent_class;
|
GObjectClass parent_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gtk_logo_paintable_get_intrinsic_width (GdkPaintable *paintable)
|
gtk_path_paintable_get_intrinsic_width (GdkPaintable *paintable)
|
||||||
{
|
{
|
||||||
GtkLogoPaintable *self = GTK_LOGO_PAINTABLE (paintable);
|
GtkPathPaintable *self = GTK_PATH_PAINTABLE (paintable);
|
||||||
|
|
||||||
return self->width;
|
if (self->background)
|
||||||
|
return MAX (gdk_paintable_get_intrinsic_width (self->background), self->width);
|
||||||
|
else
|
||||||
|
return self->width;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gtk_logo_paintable_get_intrinsic_height (GdkPaintable *paintable)
|
gtk_path_paintable_get_intrinsic_height (GdkPaintable *paintable)
|
||||||
{
|
{
|
||||||
GtkLogoPaintable *self = GTK_LOGO_PAINTABLE (paintable);
|
GtkPathPaintable *self = GTK_PATH_PAINTABLE (paintable);
|
||||||
|
|
||||||
return self->height;
|
if (self->background)
|
||||||
|
return MAX (gdk_paintable_get_intrinsic_height (self->background), self->height);
|
||||||
|
else
|
||||||
|
return self->height;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_logo_paintable_snapshot (GdkPaintable *paintable,
|
gtk_path_paintable_snapshot (GdkPaintable *paintable,
|
||||||
GdkSnapshot *snapshot,
|
GdkSnapshot *snapshot,
|
||||||
double width,
|
double width,
|
||||||
double height)
|
double height)
|
||||||
{
|
{
|
||||||
GtkLogoPaintable *self = GTK_LOGO_PAINTABLE (paintable);
|
GtkPathPaintable *self = GTK_PATH_PAINTABLE (paintable);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < 3; i++)
|
#if 0
|
||||||
|
gtk_snapshot_push_fill (snapshot, self->path, GSK_FILL_RULE_WINDING);
|
||||||
|
#else
|
||||||
|
GskStroke *stroke = gsk_stroke_new (2.0);
|
||||||
|
gtk_snapshot_push_stroke (snapshot, self->path, stroke);
|
||||||
|
gsk_stroke_free (stroke);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (self->background)
|
||||||
{
|
{
|
||||||
gtk_snapshot_push_fill (snapshot, self->path[i], GSK_FILL_RULE_WINDING);
|
gdk_paintable_snapshot (self->background, snapshot, width, height);
|
||||||
gtk_snapshot_append_color (snapshot,
|
|
||||||
&self->color[i],
|
|
||||||
&GRAPHENE_RECT_INIT (0, 0, width, height));
|
|
||||||
gtk_snapshot_pop (snapshot);
|
|
||||||
}
|
}
|
||||||
for (unsigned int i = 0; i < 3; i++)
|
else
|
||||||
{
|
{
|
||||||
gtk_snapshot_push_stroke (snapshot, self->stroke_path, self->stroke1);
|
gtk_snapshot_append_linear_gradient (snapshot,
|
||||||
gtk_snapshot_append_color (snapshot,
|
&GRAPHENE_RECT_INIT (0, 0, width, height),
|
||||||
&self->stroke_color,
|
&GRAPHENE_POINT_INIT (0, 0),
|
||||||
&GRAPHENE_RECT_INIT (0, 0, width, height));
|
&GRAPHENE_POINT_INIT (width, height),
|
||||||
gtk_snapshot_pop (snapshot);
|
(GskColorStop[8]) {
|
||||||
|
{ 0.0, { 1.0, 0.0, 0.0, 1.0 } },
|
||||||
|
{ 0.2, { 1.0, 0.0, 0.0, 1.0 } },
|
||||||
|
{ 0.3, { 1.0, 1.0, 0.0, 1.0 } },
|
||||||
|
{ 0.4, { 0.0, 1.0, 0.0, 1.0 } },
|
||||||
|
{ 0.6, { 0.0, 1.0, 1.0, 1.0 } },
|
||||||
|
{ 0.7, { 0.0, 0.0, 1.0, 1.0 } },
|
||||||
|
{ 0.8, { 1.0, 0.0, 1.0, 1.0 } },
|
||||||
|
{ 1.0, { 1.0, 0.0, 1.0, 1.0 } }
|
||||||
|
},
|
||||||
|
8);
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_snapshot_push_stroke (snapshot, self->stroke_path, self->stroke2);
|
|
||||||
gtk_snapshot_append_color (snapshot,
|
|
||||||
&self->stroke_color,
|
|
||||||
&GRAPHENE_RECT_INIT (0, 0, width, height));
|
|
||||||
gtk_snapshot_pop (snapshot);
|
gtk_snapshot_pop (snapshot);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GdkPaintableFlags
|
static GdkPaintableFlags
|
||||||
gtk_logo_paintable_get_flags (GdkPaintable *paintable)
|
gtk_path_paintable_get_flags (GdkPaintable *paintable)
|
||||||
{
|
{
|
||||||
return GDK_PAINTABLE_STATIC_CONTENTS | GDK_PAINTABLE_STATIC_SIZE;
|
GtkPathPaintable *self = GTK_PATH_PAINTABLE (paintable);
|
||||||
|
|
||||||
|
if (self->background)
|
||||||
|
return gdk_paintable_get_flags (self->background);
|
||||||
|
else
|
||||||
|
return GDK_PAINTABLE_STATIC_CONTENTS | GDK_PAINTABLE_STATIC_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_logo_paintable_paintable_init (GdkPaintableInterface *iface)
|
gtk_path_paintable_paintable_init (GdkPaintableInterface *iface)
|
||||||
{
|
{
|
||||||
iface->get_intrinsic_width = gtk_logo_paintable_get_intrinsic_width;
|
iface->get_intrinsic_width = gtk_path_paintable_get_intrinsic_width;
|
||||||
iface->get_intrinsic_height = gtk_logo_paintable_get_intrinsic_height;
|
iface->get_intrinsic_height = gtk_path_paintable_get_intrinsic_height;
|
||||||
iface->snapshot = gtk_logo_paintable_snapshot;
|
iface->snapshot = gtk_path_paintable_snapshot;
|
||||||
iface->get_flags = gtk_logo_paintable_get_flags;
|
iface->get_flags = gtk_path_paintable_get_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When defining the GType, we need to implement the GdkPaintable interface */
|
/* When defining the GType, we need to implement the GdkPaintable interface */
|
||||||
G_DEFINE_TYPE_WITH_CODE (GtkLogoPaintable, gtk_logo_paintable, G_TYPE_OBJECT,
|
G_DEFINE_TYPE_WITH_CODE (GtkPathPaintable, gtk_path_paintable, G_TYPE_OBJECT,
|
||||||
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
|
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
|
||||||
gtk_logo_paintable_paintable_init))
|
gtk_path_paintable_paintable_init))
|
||||||
|
|
||||||
static void
|
/* Here's the boilerplate for the GObject declaration.
|
||||||
gtk_logo_paintable_dispose (GObject *object)
|
* We need to disconnect the signals here that we set up elsewhere
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
gtk_path_paintable_dispose (GObject *object)
|
||||||
{
|
{
|
||||||
GtkLogoPaintable *self = GTK_LOGO_PAINTABLE (object);
|
GtkPathPaintable *self = GTK_PATH_PAINTABLE (object);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < 3; i++)
|
if (self->background)
|
||||||
gsk_path_unref (self->path[i]);
|
{
|
||||||
|
g_signal_handlers_disconnect_by_func (self->background, gdk_paintable_invalidate_contents, self);
|
||||||
|
g_signal_handlers_disconnect_by_func (self->background, gdk_paintable_invalidate_size, self);
|
||||||
|
g_clear_object (&self->background);
|
||||||
|
}
|
||||||
|
|
||||||
gsk_path_unref (self->stroke_path);
|
G_OBJECT_CLASS (gtk_path_paintable_parent_class)->dispose (object);
|
||||||
|
|
||||||
gsk_stroke_free (self->stroke1);
|
|
||||||
gsk_stroke_free (self->stroke2);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (gtk_logo_paintable_parent_class)->dispose (object);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_logo_paintable_class_init (GtkLogoPaintableClass *klass)
|
gtk_path_paintable_class_init (GtkPathPaintableClass *klass)
|
||||||
{
|
{
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
object_class->dispose = gtk_logo_paintable_dispose;
|
object_class->dispose = gtk_path_paintable_dispose;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_logo_paintable_init (GtkLogoPaintable *self)
|
gtk_path_paintable_init (GtkPathPaintable *self)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static GdkPaintable *
|
/* And finally, we add a simple constructor.
|
||||||
gtk_logo_paintable_new (void)
|
* It is declared in the header so that the other examples
|
||||||
|
* can use it.
|
||||||
|
*/
|
||||||
|
GdkPaintable *
|
||||||
|
gtk_path_paintable_new (GskPath *path,
|
||||||
|
GdkPaintable *background,
|
||||||
|
int width,
|
||||||
|
int height)
|
||||||
{
|
{
|
||||||
GtkLogoPaintable *self;
|
GtkPathPaintable *self;
|
||||||
graphene_rect_t bounds, bounds2;
|
|
||||||
|
|
||||||
self = g_object_new (GTK_TYPE_LOGO_PAINTABLE, NULL);
|
self = g_object_new (GTK_TYPE_PATH_PAINTABLE, NULL);
|
||||||
|
self->path = path;
|
||||||
/* Paths and colors extracted from gtk-logo.svg */
|
self->background = background;
|
||||||
self->path[0] = gsk_path_parse ("m3.12,66.17 -2.06,-51.46 32.93,24.7 v55.58 l-30.87,-28.82 z");
|
if (self->background)
|
||||||
self->path[1] = gsk_path_parse ("m34,95 49.4,-20.58 4.12,-51.46 -53.52,16.47 v55.58 z");
|
{
|
||||||
self->path[2] = gsk_path_parse ("m1.06,14.71 32.93,24.7 53.52,-16.47 -36.75,-21.88 -49.7,13.65 z");
|
g_object_ref (self->background);
|
||||||
|
g_signal_connect_swapped (self->background, "invalidate-contents", G_CALLBACK (gdk_paintable_invalidate_contents), self);
|
||||||
gdk_rgba_parse (&self->color[0], "#e40000");
|
g_signal_connect_swapped (self->background, "invalidate-size", G_CALLBACK (gdk_paintable_invalidate_size), self);
|
||||||
gdk_rgba_parse (&self->color[1], "#7fe719");
|
}
|
||||||
gdk_rgba_parse (&self->color[2], "#729fcf");
|
self->width = width;
|
||||||
|
self->height = height;
|
||||||
self->stroke_path = gsk_path_parse ("m50.6,51.3 -47.3,14 z l33,23 z v-50");
|
|
||||||
self->stroke1 = gsk_stroke_new (2.12);
|
|
||||||
self->stroke2 = gsk_stroke_new (1.25);
|
|
||||||
gdk_rgba_parse (&self->stroke_color, "#ffffff");
|
|
||||||
|
|
||||||
gsk_path_get_stroke_bounds (self->path[0], self->stroke1, &bounds);
|
|
||||||
gsk_path_get_stroke_bounds (self->path[1], self->stroke1, &bounds2);
|
|
||||||
graphene_rect_union (&bounds, &bounds2, &bounds);
|
|
||||||
gsk_path_get_stroke_bounds (self->path[2], self->stroke1, &bounds2);
|
|
||||||
graphene_rect_union (&bounds, &bounds2, &bounds);
|
|
||||||
gsk_path_get_stroke_bounds (self->stroke_path, self->stroke2, &bounds2);
|
|
||||||
graphene_rect_union (&bounds, &bounds2, &bounds);
|
|
||||||
|
|
||||||
self->width = bounds.origin.x + bounds.size.width;
|
|
||||||
self->height = bounds.origin.y + bounds.size.height;
|
|
||||||
|
|
||||||
return GDK_PAINTABLE (self);
|
return GDK_PAINTABLE (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static cairo_status_t
|
void
|
||||||
write_cairo (void *closure,
|
gtk_path_paintable_set_path (GtkPathPaintable *self,
|
||||||
const unsigned char *data,
|
GskPath *path)
|
||||||
unsigned int length)
|
|
||||||
{
|
{
|
||||||
GOutputStream *stream = closure;
|
g_clear_pointer (&self->path, gsk_path_unref);
|
||||||
gsize written;
|
self->path = gsk_path_ref (path);
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
if (!g_output_stream_write_all (stream, data, length, &written, NULL, &error))
|
gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
|
||||||
{
|
|
||||||
g_print ("Error writing pdf stream: %s\n", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
return CAIRO_STATUS_WRITE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static GskPath *
|
||||||
print_ready (GObject *source,
|
create_hexagon (GtkWidget *widget)
|
||||||
GAsyncResult *result,
|
|
||||||
gpointer data)
|
|
||||||
{
|
{
|
||||||
GtkPrintDialog *dialog = GTK_PRINT_DIALOG (source);
|
GskPathBuilder *builder;
|
||||||
GError *error = NULL;
|
|
||||||
GOutputStream *stream;
|
|
||||||
GtkSnapshot *snapshot;
|
|
||||||
GdkPaintable *paintable;
|
|
||||||
GskRenderNode *node;
|
|
||||||
cairo_surface_t *surface;
|
|
||||||
cairo_t *cr;
|
|
||||||
|
|
||||||
stream = gtk_print_dialog_print_finish (dialog, result, &error);
|
builder = gsk_path_builder_new ();
|
||||||
if (stream == NULL)
|
|
||||||
{
|
|
||||||
g_print ("Failed to get output stream: %s\n", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
snapshot = gtk_snapshot_new ();
|
gsk_path_builder_move_to (builder, 120, 0);
|
||||||
paintable = gtk_picture_get_paintable (GTK_PICTURE (data));
|
gsk_path_builder_line_to (builder, 360, 0);
|
||||||
gdk_paintable_snapshot (paintable, snapshot, 100, 100);
|
gsk_path_builder_line_to (builder, 480, 208);
|
||||||
node = gtk_snapshot_free_to_node (snapshot);
|
gsk_path_builder_line_to (builder, 360, 416);
|
||||||
|
gsk_path_builder_line_to (builder, 120, 416);
|
||||||
|
gsk_path_builder_line_to (builder, 0, 208);
|
||||||
|
gsk_path_builder_close (builder);
|
||||||
|
|
||||||
surface = cairo_pdf_surface_create_for_stream (write_cairo, stream, 100, 100);
|
return gsk_path_builder_free_to_path (builder);
|
||||||
cr = cairo_create (surface);
|
|
||||||
|
|
||||||
gsk_render_node_draw (node, cr);
|
|
||||||
|
|
||||||
cairo_destroy (cr);
|
|
||||||
cairo_surface_destroy (surface);
|
|
||||||
gsk_render_node_unref (node);
|
|
||||||
|
|
||||||
if (!g_output_stream_close (stream, NULL, &error))
|
|
||||||
{
|
|
||||||
g_print ("Error from close: %s\n", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_object_unref (stream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static GskPath *
|
||||||
print (GtkButton *button,
|
create_path_from_text (GtkWidget *widget)
|
||||||
gpointer data)
|
|
||||||
{
|
{
|
||||||
GtkWidget *picture = data;
|
PangoLayout *layout;
|
||||||
GtkPrintDialog *dialog;
|
PangoFontDescription *desc;
|
||||||
|
GskPathBuilder *builder;
|
||||||
|
|
||||||
dialog = gtk_print_dialog_new ();
|
layout = gtk_widget_create_pango_layout (widget, "Pango power!\nPango power!\nPango power!");
|
||||||
|
desc = pango_font_description_from_string ("sans bold 36");
|
||||||
|
pango_layout_set_font_description (layout, desc);
|
||||||
|
pango_font_description_free (desc);
|
||||||
|
|
||||||
gtk_print_dialog_print (dialog,
|
builder = gsk_path_builder_new ();
|
||||||
GTK_WINDOW (gtk_widget_get_root (picture)),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
print_ready,
|
|
||||||
picture);
|
|
||||||
|
|
||||||
g_object_unref (dialog);
|
gsk_path_builder_add_layout (builder, layout);
|
||||||
|
|
||||||
|
return gsk_path_builder_free_to_path (builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
build_path (GskPathOperation op,
|
||||||
|
const graphene_point_t *pts,
|
||||||
|
gsize n_pts,
|
||||||
|
float weight,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GskPathBuilder *builder = user_data;
|
||||||
|
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case GSK_PATH_MOVE:
|
||||||
|
gsk_path_builder_move_to (builder, pts[0].x, pts[0].y);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GSK_PATH_CLOSE:
|
||||||
|
gsk_path_builder_close (builder);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GSK_PATH_LINE:
|
||||||
|
gsk_path_builder_line_to (builder, pts[1].x, pts[1].y);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GSK_PATH_QUAD:
|
||||||
|
gsk_path_builder_quad_to (builder, pts[1].x, pts[1].y, pts[2].x, pts[2].y);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GSK_PATH_CUBIC:
|
||||||
|
gsk_path_builder_cubic_to (builder, pts[1].x, pts[1].y, pts[2].x, pts[2].y, pts[3].x, pts[3].y);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GSK_PATH_CONIC:
|
||||||
|
gsk_path_builder_conic_to (builder, pts[1].x, pts[1].y, pts[2].x, pts[2].y, weight);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
update_path (GtkWidget *widget,
|
||||||
|
GdkFrameClock *frame_clock,
|
||||||
|
gpointer measure)
|
||||||
|
{
|
||||||
|
float progress = gdk_frame_clock_get_frame_time (frame_clock) % (60 * G_USEC_PER_SEC) / (float) (30 * G_USEC_PER_SEC);
|
||||||
|
GskPathBuilder *builder;
|
||||||
|
GskPath *path;
|
||||||
|
GskPathPoint point;
|
||||||
|
graphene_point_t pos;
|
||||||
|
graphene_vec2_t tangent;
|
||||||
|
GskStroke *stroke;
|
||||||
|
|
||||||
|
path = gsk_path_measure_get_path (measure);
|
||||||
|
|
||||||
|
stroke = gsk_stroke_new (1);
|
||||||
|
gsk_stroke_set_dash (stroke, (float[2]) { 10, 5 }, 2);
|
||||||
|
gsk_stroke_set_dash_offset (stroke, - (gdk_frame_clock_get_frame_time (frame_clock) % G_USEC_PER_SEC) * 15. / G_USEC_PER_SEC);
|
||||||
|
builder = gsk_path_builder_new ();
|
||||||
|
gsk_path_dash (path, stroke, 0.2, build_path, builder);
|
||||||
|
|
||||||
|
if (gsk_path_measure_get_point (measure,
|
||||||
|
(progress > 1 ? (progress - 1) : progress) * gsk_path_measure_get_length (measure), &point))
|
||||||
|
{
|
||||||
|
gsk_path_point_get_position (&point, &pos);
|
||||||
|
gsk_path_point_get_tangent (&point, GSK_PATH_END, &tangent);
|
||||||
|
|
||||||
|
gsk_path_builder_move_to (builder, pos.x + 5 * graphene_vec2_get_x (&tangent), pos.y + 5 * graphene_vec2_get_y (&tangent));
|
||||||
|
gsk_path_builder_line_to (builder, pos.x + 3 * graphene_vec2_get_y (&tangent), pos.y + 3 * graphene_vec2_get_x (&tangent));
|
||||||
|
gsk_path_builder_line_to (builder, pos.x - 3 * graphene_vec2_get_y (&tangent), pos.y - 3 * graphene_vec2_get_x (&tangent));
|
||||||
|
gsk_path_builder_close (builder);
|
||||||
|
|
||||||
|
path = gsk_path_builder_free_to_path (builder);
|
||||||
|
|
||||||
|
gtk_path_paintable_set_path (GTK_PATH_PAINTABLE (gtk_picture_get_paintable (GTK_PICTURE (widget))),
|
||||||
|
path);
|
||||||
|
gsk_path_unref (path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget *
|
GtkWidget *
|
||||||
@@ -258,31 +315,41 @@ do_path_fill (GtkWidget *do_widget)
|
|||||||
|
|
||||||
if (!window)
|
if (!window)
|
||||||
{
|
{
|
||||||
GtkWidget *header, *button, *label;
|
|
||||||
GtkWidget *picture;
|
GtkWidget *picture;
|
||||||
GdkPaintable *paintable;
|
GdkPaintable *paintable;
|
||||||
|
GtkMediaStream *stream;
|
||||||
|
GskPath *path;
|
||||||
|
graphene_rect_t bounds;
|
||||||
|
GskPathMeasure *measure;
|
||||||
|
|
||||||
window = gtk_window_new ();
|
window = gtk_window_new ();
|
||||||
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
|
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
|
||||||
gtk_window_set_default_size (GTK_WINDOW (window), 100, 100);
|
gtk_window_set_title (GTK_WINDOW (window), "Path Fill");
|
||||||
gtk_window_set_title (GTK_WINDOW (window), "Fill and Stroke");
|
|
||||||
header = gtk_header_bar_new ();
|
|
||||||
button = gtk_button_new_from_icon_name ("printer-symbolic");
|
|
||||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), button);
|
|
||||||
label = gtk_label_new ("Fill and Stroke");
|
|
||||||
gtk_widget_add_css_class (label, "title");
|
|
||||||
gtk_header_bar_set_title_widget (GTK_HEADER_BAR (header), label);
|
|
||||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
|
||||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||||
|
|
||||||
paintable = gtk_logo_paintable_new ();
|
#if 0
|
||||||
|
stream = gtk_media_file_new_for_resource ("/images/gtk-logo.webm");
|
||||||
|
#else
|
||||||
|
stream = gtk_nuclear_media_stream_new ();
|
||||||
|
#endif
|
||||||
|
gtk_media_stream_play (stream);
|
||||||
|
gtk_media_stream_set_loop (stream, TRUE);
|
||||||
|
|
||||||
|
path = create_hexagon (window);
|
||||||
|
path = create_path_from_text (window);
|
||||||
|
gsk_path_get_bounds (path, &bounds);
|
||||||
|
|
||||||
|
paintable = gtk_path_paintable_new (path,
|
||||||
|
GDK_PAINTABLE (stream),
|
||||||
|
bounds.origin.x + bounds.size.width,
|
||||||
|
bounds.origin.y + bounds.size.height);
|
||||||
picture = gtk_picture_new_for_paintable (paintable);
|
picture = gtk_picture_new_for_paintable (paintable);
|
||||||
|
measure = gsk_path_measure_new (path);
|
||||||
|
gtk_widget_add_tick_callback (picture, update_path, measure, (GDestroyNotify) gsk_path_measure_unref);
|
||||||
gtk_picture_set_content_fit (GTK_PICTURE (picture), GTK_CONTENT_FIT_CONTAIN);
|
gtk_picture_set_content_fit (GTK_PICTURE (picture), GTK_CONTENT_FIT_CONTAIN);
|
||||||
gtk_picture_set_can_shrink (GTK_PICTURE (picture), FALSE);
|
gtk_picture_set_can_shrink (GTK_PICTURE (picture), FALSE);
|
||||||
g_object_unref (paintable);
|
g_object_unref (paintable);
|
||||||
|
|
||||||
g_signal_connect (button, "clicked", G_CALLBACK (print), picture);
|
|
||||||
|
|
||||||
gtk_window_set_child (GTK_WINDOW (window), picture);
|
gtk_window_set_child (GTK_WINDOW (window), picture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
/* Path/Maze
|
/* Path/Maze
|
||||||
*
|
*
|
||||||
* This demo shows how to use a GskPath to create a maze and use
|
* This demo shows how to use a GskPath to create a maze and use
|
||||||
* gsk_path_get_closest_point() to check the mouse stays
|
* gsk_path_measure_get_closest_point() to check the mouse stays
|
||||||
* on the path.
|
* on the path.
|
||||||
*
|
*
|
||||||
* It also shows off the performance of GskPath (or not) as this
|
* It also shows off the performance of GskPath (or not) as this
|
||||||
* is a rather complex path.
|
* is a rather complex path.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include <glib/gi18n.h>
|
#include <glib/gi18n.h>
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
@@ -132,24 +131,6 @@ gtk_maze_class_init (GtkMazeClass *klass)
|
|||||||
widget_class->snapshot = gtk_maze_snapshot;
|
widget_class->snapshot = gtk_maze_snapshot;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
celebrate (gboolean win)
|
|
||||||
{
|
|
||||||
char *path;
|
|
||||||
GtkMediaStream *stream;
|
|
||||||
|
|
||||||
if (win)
|
|
||||||
path = g_build_filename (GTK_DATADIR, "sounds", "freedesktop", "stereo", "complete.oga", NULL);
|
|
||||||
else
|
|
||||||
path = g_build_filename (GTK_DATADIR, "sounds", "freedesktop", "stereo", "suspend-error.oga", NULL);
|
|
||||||
stream = gtk_media_file_new_for_filename (path);
|
|
||||||
gtk_media_stream_set_volume (stream, 1.0);
|
|
||||||
gtk_media_stream_play (stream);
|
|
||||||
|
|
||||||
g_signal_connect (stream, "notify::ended", G_CALLBACK (g_object_unref), NULL);
|
|
||||||
g_free (path);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pointer_motion (GtkEventControllerMotion *controller,
|
pointer_motion (GtkEventControllerMotion *controller,
|
||||||
double x,
|
double x,
|
||||||
@@ -157,25 +138,21 @@ pointer_motion (GtkEventControllerMotion *controller,
|
|||||||
GtkMaze *self)
|
GtkMaze *self)
|
||||||
{
|
{
|
||||||
GskPathPoint point;
|
GskPathPoint point;
|
||||||
float distance;
|
graphene_point_t pos;
|
||||||
|
|
||||||
if (!self->active)
|
if (!self->active)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (gsk_path_get_closest_point (self->path,
|
if (gsk_path_get_closest_point (self->path, &GRAPHENE_POINT_INIT (x, y), INFINITY, &point))
|
||||||
&GRAPHENE_POINT_INIT (x, y),
|
|
||||||
INFINITY,
|
|
||||||
&point,
|
|
||||||
&distance))
|
|
||||||
{
|
{
|
||||||
if (distance < MAZE_STROKE_SIZE_ACTIVE / 2.f)
|
gsk_path_point_get_position (&point, &pos);
|
||||||
|
|
||||||
|
if (graphene_point_distance (&pos, &GRAPHENE_POINT_INIT (x, y), NULL, NULL) <= MAZE_STROKE_SIZE_ACTIVE / 2.0f)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
self->active = FALSE;
|
||||||
|
gtk_widget_queue_draw (GTK_WIDGET (self));
|
||||||
}
|
}
|
||||||
|
|
||||||
celebrate (FALSE);
|
|
||||||
|
|
||||||
self->active = FALSE;
|
|
||||||
gtk_widget_queue_draw (GTK_WIDGET (self));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -1,323 +0,0 @@
|
|||||||
/* Path/Spinner
|
|
||||||
*
|
|
||||||
* This demo shows how to use GskPath to draw a simple animation
|
|
||||||
* that could be used as a spinner.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <glib/gi18n.h>
|
|
||||||
#include <gtk/gtk.h>
|
|
||||||
|
|
||||||
#include "paintable.h"
|
|
||||||
|
|
||||||
#undef SHOW_CONTROLS
|
|
||||||
|
|
||||||
#define GTK_TYPE_SPINNER_PAINTABLE (gtk_spinner_paintable_get_type ())
|
|
||||||
G_DECLARE_FINAL_TYPE (GtkSpinnerPaintable, gtk_spinner_paintable, GTK, SPINNER_PAINTABLE, GObject)
|
|
||||||
|
|
||||||
struct _GtkSpinnerPaintable
|
|
||||||
{
|
|
||||||
GObject parent_instance;
|
|
||||||
|
|
||||||
gint64 start_time;
|
|
||||||
|
|
||||||
int width;
|
|
||||||
double angle;
|
|
||||||
double completion;
|
|
||||||
|
|
||||||
GskPath *circle;
|
|
||||||
GskPath *path;
|
|
||||||
GskStroke *stroke;
|
|
||||||
GdkRGBA color;
|
|
||||||
GdkRGBA circle_color;
|
|
||||||
#ifdef SHOW_CONTROLS
|
|
||||||
GskPath *controls;
|
|
||||||
GdkRGBA control_color;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _GtkSpinnerPaintableClass
|
|
||||||
{
|
|
||||||
GObjectClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
gtk_spinner_paintable_get_intrinsic_width (GdkPaintable *paintable)
|
|
||||||
{
|
|
||||||
GtkSpinnerPaintable *self = GTK_SPINNER_PAINTABLE (paintable);
|
|
||||||
|
|
||||||
return self->width;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
gtk_spinner_paintable_get_intrinsic_height (GdkPaintable *paintable)
|
|
||||||
{
|
|
||||||
GtkSpinnerPaintable *self = GTK_SPINNER_PAINTABLE (paintable);
|
|
||||||
|
|
||||||
return self->width;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gtk_spinner_paintable_snapshot (GdkPaintable *paintable,
|
|
||||||
GdkSnapshot *snapshot,
|
|
||||||
double width,
|
|
||||||
double height)
|
|
||||||
{
|
|
||||||
GtkSpinnerPaintable *self = GTK_SPINNER_PAINTABLE (paintable);
|
|
||||||
|
|
||||||
gtk_snapshot_append_stroke (snapshot, self->circle, self->stroke, &self->circle_color);
|
|
||||||
gtk_snapshot_append_stroke (snapshot, self->path, self->stroke, &self->color);
|
|
||||||
#ifdef SHOW_CONTROLS
|
|
||||||
GskStroke *stroke = gsk_stroke_new (1);
|
|
||||||
gtk_snapshot_append_stroke (snapshot, self->controls, stroke, &self->control_color);
|
|
||||||
gsk_stroke_free (stroke);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static GdkPaintableFlags
|
|
||||||
gtk_spinner_paintable_get_flags (GdkPaintable *paintable)
|
|
||||||
{
|
|
||||||
return GDK_PAINTABLE_STATIC_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gtk_spinner_paintable_paintable_init (GdkPaintableInterface *iface)
|
|
||||||
{
|
|
||||||
iface->get_intrinsic_width = gtk_spinner_paintable_get_intrinsic_width;
|
|
||||||
iface->get_intrinsic_height = gtk_spinner_paintable_get_intrinsic_height;
|
|
||||||
iface->snapshot = gtk_spinner_paintable_snapshot;
|
|
||||||
iface->get_flags = gtk_spinner_paintable_get_flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* When defining the GType, we need to implement the GdkPaintable interface */
|
|
||||||
G_DEFINE_TYPE_WITH_CODE (GtkSpinnerPaintable, gtk_spinner_paintable, G_TYPE_OBJECT,
|
|
||||||
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
|
|
||||||
gtk_spinner_paintable_paintable_init))
|
|
||||||
|
|
||||||
static void
|
|
||||||
gtk_spinner_paintable_dispose (GObject *object)
|
|
||||||
{
|
|
||||||
GtkSpinnerPaintable *self = GTK_SPINNER_PAINTABLE (object);
|
|
||||||
|
|
||||||
gsk_path_unref (self->circle);
|
|
||||||
gsk_path_unref (self->path);
|
|
||||||
#ifdef SHOW_CONTROLS
|
|
||||||
gsk_path_unref (self->controls);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
gsk_stroke_free (self->stroke);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (gtk_spinner_paintable_parent_class)->dispose (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gtk_spinner_paintable_class_init (GtkSpinnerPaintableClass *klass)
|
|
||||||
{
|
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
||||||
|
|
||||||
object_class->dispose = gtk_spinner_paintable_dispose;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gtk_spinner_paintable_init (GtkSpinnerPaintable *self)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static GdkPaintable *
|
|
||||||
gtk_spinner_paintable_new (void)
|
|
||||||
{
|
|
||||||
GtkSpinnerPaintable *self;
|
|
||||||
GskPathBuilder *builder;
|
|
||||||
|
|
||||||
self = g_object_new (GTK_TYPE_SPINNER_PAINTABLE, NULL);
|
|
||||||
|
|
||||||
builder = gsk_path_builder_new ();
|
|
||||||
gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (50, 50), 40);
|
|
||||||
self->circle = gsk_path_builder_free_to_path (builder);
|
|
||||||
|
|
||||||
self->width = 100;
|
|
||||||
self->angle = 0;
|
|
||||||
self->completion = 1;
|
|
||||||
gdk_rgba_parse (&self->color, "green");
|
|
||||||
gdk_rgba_parse (&self->circle_color, "lightgray");
|
|
||||||
#ifdef SHOW_CONTROLS
|
|
||||||
gdk_rgba_parse (&self->control_color, "black");
|
|
||||||
#endif
|
|
||||||
self->stroke = gsk_stroke_new (5);
|
|
||||||
|
|
||||||
return GDK_PAINTABLE (self);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SHOW_CONTROLS
|
|
||||||
static gboolean
|
|
||||||
add_controls (GskPathOperation op,
|
|
||||||
const graphene_point_t *pts,
|
|
||||||
gsize n_pts,
|
|
||||||
float weight,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
GskPathBuilder *builder = data;
|
|
||||||
|
|
||||||
switch (op)
|
|
||||||
{
|
|
||||||
case GSK_PATH_MOVE:
|
|
||||||
gsk_path_builder_move_to (builder, pts[0].x, pts[0].y);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GSK_PATH_CLOSE:
|
|
||||||
case GSK_PATH_LINE:
|
|
||||||
gsk_path_builder_line_to (builder, pts[1].x, pts[1].y);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GSK_PATH_QUAD:
|
|
||||||
case GSK_PATH_CONIC:
|
|
||||||
gsk_path_builder_line_to (builder, pts[1].x, pts[1].y);
|
|
||||||
gsk_path_builder_line_to (builder, pts[2].x, pts[2].y);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GSK_PATH_CUBIC:
|
|
||||||
gsk_path_builder_line_to (builder, pts[1].x, pts[1].y);
|
|
||||||
gsk_path_builder_line_to (builder, pts[2].x, pts[2].y);
|
|
||||||
gsk_path_builder_line_to (builder, pts[3].x, pts[3].y);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
g_assert_not_reached ();
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
|
||||||
update_path (GtkSpinnerPaintable *self)
|
|
||||||
{
|
|
||||||
GskPathBuilder *builder;
|
|
||||||
GskPathPoint start, end;
|
|
||||||
graphene_point_t p0, p1;
|
|
||||||
float start_angle, end_angle;
|
|
||||||
|
|
||||||
start_angle = self->angle;
|
|
||||||
end_angle = fmod (self->angle + 360 * self->completion / 100, 360);
|
|
||||||
|
|
||||||
p0 = GRAPHENE_POINT_INIT (50 + 40 * cos (M_PI * start_angle / 180),
|
|
||||||
50 + 40 * sin (M_PI * start_angle / 180));
|
|
||||||
p1 = GRAPHENE_POINT_INIT (50 + 40 * cos (M_PI * end_angle / 180),
|
|
||||||
50 + 40 * sin (M_PI * end_angle / 180));
|
|
||||||
|
|
||||||
g_clear_pointer (&self->path, gsk_path_unref);
|
|
||||||
|
|
||||||
gsk_path_get_closest_point (self->circle, &p0, INFINITY, &start, NULL);
|
|
||||||
gsk_path_get_closest_point (self->circle, &p1, INFINITY, &end, NULL);
|
|
||||||
|
|
||||||
builder = gsk_path_builder_new ();
|
|
||||||
gsk_path_builder_add_segment (builder, self->circle, &start, &end);
|
|
||||||
self->path = gsk_path_builder_free_to_path (builder);
|
|
||||||
|
|
||||||
#ifdef SHOW_CONTROLS
|
|
||||||
g_clear_pointer (&self->controls, gsk_path_unref);
|
|
||||||
builder = gsk_path_builder_new ();
|
|
||||||
gsk_path_foreach (self->path, -1, add_controls, builder);
|
|
||||||
self->controls = gsk_path_builder_free_to_path (builder);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gtk_spinner_paintable_set_completion (GtkSpinnerPaintable *self,
|
|
||||||
float completion)
|
|
||||||
{
|
|
||||||
self->completion = CLAMP (completion, 0, 100);
|
|
||||||
update_path (self);
|
|
||||||
}
|
|
||||||
|
|
||||||
static float
|
|
||||||
gtk_spinner_paintable_get_completion (GtkSpinnerPaintable *self)
|
|
||||||
{
|
|
||||||
return self->completion;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gtk_spinner_paintable_set_frame_time (GtkSpinnerPaintable *self,
|
|
||||||
gint64 time)
|
|
||||||
{
|
|
||||||
double delta;
|
|
||||||
|
|
||||||
if (self->start_time == 0)
|
|
||||||
self->start_time = time;
|
|
||||||
|
|
||||||
delta = (time - self->start_time) / (double) G_TIME_SPAN_SECOND;
|
|
||||||
self->angle = fmod (60 * delta, 360);
|
|
||||||
update_path (self);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
tick_cb (GtkWidget *widget,
|
|
||||||
GdkFrameClock *clock,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
GtkSpinnerPaintable *self = data;
|
|
||||||
|
|
||||||
gtk_spinner_paintable_set_frame_time (self, gdk_frame_clock_get_frame_time (clock));
|
|
||||||
return G_SOURCE_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
progress_timeout (gpointer data)
|
|
||||||
{
|
|
||||||
GtkSpinnerPaintable *self = data;
|
|
||||||
static float progress_delta = 0.5;
|
|
||||||
float progress;
|
|
||||||
|
|
||||||
progress = gtk_spinner_paintable_get_completion (self);
|
|
||||||
if (progress >= 100 || progress <= 0)
|
|
||||||
progress_delta = -progress_delta;
|
|
||||||
|
|
||||||
gtk_spinner_paintable_set_completion (self, progress + progress_delta);
|
|
||||||
|
|
||||||
return G_SOURCE_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
unset_timeout (gpointer data)
|
|
||||||
{
|
|
||||||
g_source_remove (GPOINTER_TO_UINT (data));
|
|
||||||
}
|
|
||||||
|
|
||||||
GtkWidget *
|
|
||||||
do_path_spinner (GtkWidget *do_widget)
|
|
||||||
{
|
|
||||||
static GtkWidget *window = NULL;
|
|
||||||
|
|
||||||
if (!window)
|
|
||||||
{
|
|
||||||
GtkWidget *picture;
|
|
||||||
GdkPaintable *paintable;
|
|
||||||
guint timeout_id;
|
|
||||||
|
|
||||||
window = gtk_window_new ();
|
|
||||||
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
|
|
||||||
gtk_window_set_title (GTK_WINDOW (window), "Spinner");
|
|
||||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
|
||||||
|
|
||||||
paintable = gtk_spinner_paintable_new ();
|
|
||||||
picture = gtk_picture_new_for_paintable (paintable);
|
|
||||||
gtk_picture_set_content_fit (GTK_PICTURE (picture), GTK_CONTENT_FIT_CONTAIN);
|
|
||||||
gtk_picture_set_can_shrink (GTK_PICTURE (picture), FALSE);
|
|
||||||
g_object_unref (paintable);
|
|
||||||
|
|
||||||
gtk_widget_add_tick_callback (picture, tick_cb, paintable, NULL);
|
|
||||||
timeout_id = g_timeout_add (100, progress_timeout, paintable);
|
|
||||||
|
|
||||||
g_object_set_data_full (G_OBJECT (picture), "timeout", GUINT_TO_POINTER (timeout_id), unset_timeout);
|
|
||||||
|
|
||||||
gtk_window_set_child (GTK_WINDOW (window), picture);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gtk_widget_get_visible (window))
|
|
||||||
gtk_window_present (GTK_WINDOW (window));
|
|
||||||
else
|
|
||||||
gtk_window_destroy (GTK_WINDOW (window));
|
|
||||||
|
|
||||||
return window;
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
/* Path/Text
|
/* Path/Text
|
||||||
*
|
*
|
||||||
* This demo shows how to use GskPath to transform a path along another path.
|
* This demo shows how to use GskPath to animate a path along another path.
|
||||||
*
|
|
||||||
* It also demonstrates that paths can be filled with more interesting
|
|
||||||
* content than just plain colors.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <glib/gi18n.h>
|
#include <glib/gi18n.h>
|
||||||
@@ -31,8 +28,10 @@ struct _GtkPathWidget
|
|||||||
graphene_point_t points[4];
|
graphene_point_t points[4];
|
||||||
|
|
||||||
guint active_point;
|
guint active_point;
|
||||||
|
float line_closest;
|
||||||
|
|
||||||
GskPath *line_path;
|
GskPath *line_path;
|
||||||
|
GskPathMeasure *line_measure;
|
||||||
GskPath *text_path;
|
GskPath *text_path;
|
||||||
|
|
||||||
GdkPaintable *background;
|
GdkPaintable *background;
|
||||||
@@ -93,10 +92,8 @@ gtk_path_transform_point (GskPathMeasure *measure,
|
|||||||
|
|
||||||
if (gsk_path_measure_get_point (measure, (pt->x + offset->x) * scale, &point))
|
if (gsk_path_measure_get_point (measure, (pt->x + offset->x) * scale, &point))
|
||||||
{
|
{
|
||||||
GskPath *path = gsk_path_measure_get_path (measure);
|
gsk_path_point_get_position (&point, res);
|
||||||
|
gsk_path_point_get_tangent (&point, GSK_PATH_END, &tangent);
|
||||||
gsk_path_point_get_position (&point, path, res);
|
|
||||||
gsk_path_point_get_tangent (&point, path, GSK_PATH_TO_END, &tangent);
|
|
||||||
|
|
||||||
res->x -= (pt->y + offset->y) * scale * graphene_vec2_get_y (&tangent);
|
res->x -= (pt->y + offset->y) * scale * graphene_vec2_get_y (&tangent);
|
||||||
res->y += (pt->y + offset->y) * scale * graphene_vec2_get_x (&tangent);
|
res->y += (pt->y + offset->y) * scale * graphene_vec2_get_x (&tangent);
|
||||||
@@ -153,7 +150,7 @@ gtk_path_transform_op (GskPathOperation op,
|
|||||||
{
|
{
|
||||||
graphene_point_t res[2];
|
graphene_point_t res[2];
|
||||||
gtk_path_transform_point (transform->measure, &pts[1], &transform->offset, transform->scale, &res[0]);
|
gtk_path_transform_point (transform->measure, &pts[1], &transform->offset, transform->scale, &res[0]);
|
||||||
gtk_path_transform_point (transform->measure, &pts[3], &transform->offset, transform->scale, &res[1]);
|
gtk_path_transform_point (transform->measure, &pts[2], &transform->offset, transform->scale, &res[1]);
|
||||||
gsk_path_builder_conic_to (transform->builder, res[0].x, res[0].y, res[1].x, res[1].y, weight);
|
gsk_path_builder_conic_to (transform->builder, res[0].x, res[0].y, res[1].x, res[1].y, weight);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -171,11 +168,10 @@ gtk_path_transform_op (GskPathOperation op,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static GskPath *
|
static GskPath *
|
||||||
gtk_path_transform (GskPath *line_path,
|
gtk_path_transform (GskPathMeasure *measure,
|
||||||
GskPath *path,
|
GskPath *path,
|
||||||
const graphene_point_t *offset)
|
const graphene_point_t *offset)
|
||||||
{
|
{
|
||||||
GskPathMeasure *measure = gsk_path_measure_new (line_path);
|
|
||||||
GtkPathTransform transform = { measure, gsk_path_builder_new (), *offset };
|
GtkPathTransform transform = { measure, gsk_path_builder_new (), *offset };
|
||||||
graphene_rect_t bounds;
|
graphene_rect_t bounds;
|
||||||
|
|
||||||
@@ -187,8 +183,6 @@ gtk_path_transform (GskPath *line_path,
|
|||||||
|
|
||||||
gsk_path_foreach (path, -1, gtk_path_transform_op, &transform);
|
gsk_path_foreach (path, -1, gtk_path_transform_op, &transform);
|
||||||
|
|
||||||
gsk_path_measure_unref (measure);
|
|
||||||
|
|
||||||
return gsk_path_builder_free_to_path (transform.builder);
|
return gsk_path_builder_free_to_path (transform.builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,6 +198,7 @@ gtk_path_widget_clear_paths (GtkPathWidget *self)
|
|||||||
gtk_path_widget_clear_text_path (self);
|
gtk_path_widget_clear_text_path (self);
|
||||||
|
|
||||||
g_clear_pointer (&self->line_path, gsk_path_unref);
|
g_clear_pointer (&self->line_path, gsk_path_unref);
|
||||||
|
g_clear_pointer (&self->line_measure, gsk_path_measure_unref);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -214,8 +209,11 @@ gtk_path_widget_create_text_path (GtkPathWidget *self)
|
|||||||
|
|
||||||
gtk_path_widget_clear_text_path (self);
|
gtk_path_widget_clear_text_path (self);
|
||||||
|
|
||||||
|
if (self->line_measure == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
path = create_path_from_text (GTK_WIDGET (self), self->text, &offset);
|
path = create_path_from_text (GTK_WIDGET (self), self->text, &offset);
|
||||||
self->text_path = gtk_path_transform (self->line_path, path, &offset);
|
self->text_path = gtk_path_transform (self->line_measure, path, &offset);
|
||||||
|
|
||||||
gsk_path_unref (path);
|
gsk_path_unref (path);
|
||||||
}
|
}
|
||||||
@@ -241,6 +239,8 @@ gtk_path_widget_create_paths (GtkPathWidget *self)
|
|||||||
self->points[3].x * width, self->points[3].y * height);
|
self->points[3].x * width, self->points[3].y * height);
|
||||||
self->line_path = gsk_path_builder_free_to_path (builder);
|
self->line_path = gsk_path_builder_free_to_path (builder);
|
||||||
|
|
||||||
|
self->line_measure = gsk_path_measure_new (self->line_path);
|
||||||
|
|
||||||
gtk_path_widget_create_text_path (self);
|
gtk_path_widget_create_text_path (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,6 +322,27 @@ gtk_path_widget_snapshot (GtkWidget *widget,
|
|||||||
|
|
||||||
gsk_path_unref (path);
|
gsk_path_unref (path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self->line_closest >= 0)
|
||||||
|
{
|
||||||
|
GskPathBuilder *builder;
|
||||||
|
GskPathPoint point;
|
||||||
|
graphene_point_t closest;
|
||||||
|
|
||||||
|
builder = gsk_path_builder_new ();
|
||||||
|
if (gsk_path_measure_get_point (self->line_measure, self->line_closest, &point))
|
||||||
|
{
|
||||||
|
gsk_path_point_get_position (&point, &closest);
|
||||||
|
gsk_path_builder_add_circle (builder, &closest, POINT_SIZE);
|
||||||
|
path = gsk_path_builder_free_to_path (builder);
|
||||||
|
|
||||||
|
gtk_snapshot_push_fill (snapshot, path, GSK_FILL_RULE_WINDING);
|
||||||
|
gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 0, 0, 1, 1 }, &GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||||
|
gtk_snapshot_pop (snapshot);
|
||||||
|
|
||||||
|
gsk_path_unref (path);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -501,13 +522,16 @@ pointer_motion (GtkEventControllerMotion *controller,
|
|||||||
GtkPathWidget *self)
|
GtkPathWidget *self)
|
||||||
{
|
{
|
||||||
GskPathPoint point;
|
GskPathPoint point;
|
||||||
|
graphene_point_t pos;
|
||||||
|
|
||||||
if (gsk_path_get_closest_point (self->line_path,
|
if (gsk_path_get_closest_point (gsk_path_measure_get_path (self->line_measure),
|
||||||
&GRAPHENE_POINT_INIT (x, y),
|
&GRAPHENE_POINT_INIT (x, y),
|
||||||
INFINITY,
|
INFINITY,
|
||||||
&point,
|
&point))
|
||||||
NULL))
|
|
||||||
{
|
{
|
||||||
|
gsk_path_point_get_position (&point, &pos);
|
||||||
|
self->line_closest = graphene_point_distance (&pos, &GRAPHENE_POINT_INIT (x, y), NULL, NULL);
|
||||||
|
|
||||||
gtk_widget_queue_draw (GTK_WIDGET (self));
|
gtk_widget_queue_draw (GTK_WIDGET (self));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -516,6 +540,8 @@ static void
|
|||||||
pointer_leave (GtkEventControllerMotion *controller,
|
pointer_leave (GtkEventControllerMotion *controller,
|
||||||
GtkPathWidget *self)
|
GtkPathWidget *self)
|
||||||
{
|
{
|
||||||
|
self->line_closest = -1;
|
||||||
|
|
||||||
gtk_widget_queue_draw (GTK_WIDGET (self));
|
gtk_widget_queue_draw (GTK_WIDGET (self));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -536,6 +562,8 @@ gtk_path_widget_init (GtkPathWidget *self)
|
|||||||
g_signal_connect (controller, "leave", G_CALLBACK (pointer_leave), self);
|
g_signal_connect (controller, "leave", G_CALLBACK (pointer_leave), self);
|
||||||
gtk_widget_add_controller (GTK_WIDGET (self), controller);
|
gtk_widget_add_controller (GTK_WIDGET (self), controller);
|
||||||
|
|
||||||
|
self->line_closest = -1;
|
||||||
|
|
||||||
self->points[0] = GRAPHENE_POINT_INIT (0.1, 0.9);
|
self->points[0] = GRAPHENE_POINT_INIT (0.1, 0.9);
|
||||||
self->points[1] = GRAPHENE_POINT_INIT (0.3, 0.1);
|
self->points[1] = GRAPHENE_POINT_INIT (0.3, 0.1);
|
||||||
self->points[2] = GRAPHENE_POINT_INIT (0.7, 0.1);
|
self->points[2] = GRAPHENE_POINT_INIT (0.7, 0.1);
|
||||||
|
|||||||
@@ -1,373 +0,0 @@
|
|||||||
/* Path/Walk
|
|
||||||
*
|
|
||||||
* This demo draws a world map and shows how to animate objects along a GskPath.
|
|
||||||
*
|
|
||||||
* The world map that is used here is a path with 211 lines and 1569 cubic
|
|
||||||
* Bėzier segments in 121 contours.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <glib/gi18n.h>
|
|
||||||
#include <gtk/gtk.h>
|
|
||||||
|
|
||||||
#define GTK_TYPE_PATH_WALK (gtk_path_walk_get_type ())
|
|
||||||
G_DECLARE_FINAL_TYPE (GtkPathWalk, gtk_path_walk, GTK, PATH_WALK, GtkWidget)
|
|
||||||
|
|
||||||
#define POINT_SIZE 8
|
|
||||||
|
|
||||||
enum {
|
|
||||||
PROP_0,
|
|
||||||
PROP_N_POINTS,
|
|
||||||
PROP_PATH,
|
|
||||||
N_PROPS
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _GtkPathWalk
|
|
||||||
{
|
|
||||||
GtkWidget parent_instance;
|
|
||||||
|
|
||||||
GskPath *path;
|
|
||||||
GskPathMeasure *measure;
|
|
||||||
graphene_rect_t bounds;
|
|
||||||
GskPath *arrow_path;
|
|
||||||
guint n_points;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _GtkPathWalkClass
|
|
||||||
{
|
|
||||||
GtkWidgetClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (GtkPathWalk, gtk_path_walk, GTK_TYPE_WIDGET)
|
|
||||||
|
|
||||||
static void
|
|
||||||
rgba_init_from_hsla (GdkRGBA *rgba,
|
|
||||||
float hue,
|
|
||||||
float saturation,
|
|
||||||
float lightness,
|
|
||||||
float alpha)
|
|
||||||
{
|
|
||||||
float m1, m2;
|
|
||||||
|
|
||||||
if (lightness <= 0.5)
|
|
||||||
m2 = lightness * (1 + saturation);
|
|
||||||
else
|
|
||||||
m2 = lightness + saturation - lightness * saturation;
|
|
||||||
m1 = 2 * lightness - m2;
|
|
||||||
|
|
||||||
rgba->alpha = alpha;
|
|
||||||
|
|
||||||
if (saturation == 0)
|
|
||||||
{
|
|
||||||
rgba->red = lightness;
|
|
||||||
rgba->green = lightness;
|
|
||||||
rgba->blue = lightness;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hue = hue + 120;
|
|
||||||
while (hue > 360)
|
|
||||||
hue -= 360;
|
|
||||||
while (hue < 0)
|
|
||||||
hue += 360;
|
|
||||||
|
|
||||||
if (hue < 60)
|
|
||||||
rgba->red = m1 + (m2 - m1) * hue / 60;
|
|
||||||
else if (hue < 180)
|
|
||||||
rgba->red = m2;
|
|
||||||
else if (hue < 240)
|
|
||||||
rgba->red = m1 + (m2 - m1) * (240 - hue) / 60;
|
|
||||||
else
|
|
||||||
rgba->red = m1;
|
|
||||||
|
|
||||||
hue -= 120;
|
|
||||||
if (hue < 0)
|
|
||||||
hue += 360;
|
|
||||||
|
|
||||||
if (hue < 60)
|
|
||||||
rgba->green = m1 + (m2 - m1) * hue / 60;
|
|
||||||
else if (hue < 180)
|
|
||||||
rgba->green = m2;
|
|
||||||
else if (hue < 240)
|
|
||||||
rgba->green = m1 + (m2 - m1) * (240 - hue) / 60;
|
|
||||||
else
|
|
||||||
rgba->green = m1;
|
|
||||||
|
|
||||||
hue -= 120;
|
|
||||||
if (hue < 0)
|
|
||||||
hue += 360;
|
|
||||||
|
|
||||||
if (hue < 60)
|
|
||||||
rgba->blue = m1 + (m2 - m1) * hue / 60;
|
|
||||||
else if (hue < 180)
|
|
||||||
rgba->blue = m2;
|
|
||||||
else if (hue < 240)
|
|
||||||
rgba->blue = m1 + (m2 - m1) * (240 - hue) / 60;
|
|
||||||
else
|
|
||||||
rgba->blue = m1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gtk_path_walk_snapshot (GtkWidget *widget,
|
|
||||||
GtkSnapshot *snapshot)
|
|
||||||
{
|
|
||||||
GtkPathWalk *self = GTK_PATH_WALK (widget);
|
|
||||||
double width = gtk_widget_get_width (widget);
|
|
||||||
double height = gtk_widget_get_height (widget);
|
|
||||||
float length, progress;
|
|
||||||
GskStroke *stroke;
|
|
||||||
guint i;
|
|
||||||
|
|
||||||
if (self->path == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
gtk_snapshot_save (snapshot);
|
|
||||||
|
|
||||||
stroke = gsk_stroke_new (2.0);
|
|
||||||
gtk_snapshot_push_stroke (snapshot, self->path, stroke);
|
|
||||||
gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 0, 0, 0, 1 }, &GRAPHENE_RECT_INIT (0, 0, width, height));
|
|
||||||
gtk_snapshot_pop (snapshot);
|
|
||||||
gsk_stroke_free (stroke);
|
|
||||||
|
|
||||||
length = gsk_path_measure_get_length (self->measure);
|
|
||||||
progress = 25.f * gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (widget)) / G_USEC_PER_SEC;
|
|
||||||
|
|
||||||
stroke = gsk_stroke_new (1.0);
|
|
||||||
for (i = 0; i < self->n_points; i++)
|
|
||||||
{
|
|
||||||
GskPathPoint point;
|
|
||||||
graphene_point_t position;
|
|
||||||
float angle;
|
|
||||||
GdkRGBA color;
|
|
||||||
float distance;
|
|
||||||
|
|
||||||
distance = i * length / self->n_points;
|
|
||||||
distance = fmod (distance + progress, length);
|
|
||||||
|
|
||||||
gsk_path_measure_get_point (self->measure, distance, &point);
|
|
||||||
gsk_path_point_get_position (&point, self->path, &position);
|
|
||||||
angle = gsk_path_point_get_rotation (&point, self->path, GSK_PATH_FROM_START);
|
|
||||||
rgba_init_from_hsla (&color, 360.f * i / self->n_points, 1, 0.5, 1);
|
|
||||||
|
|
||||||
gtk_snapshot_save (snapshot);
|
|
||||||
gtk_snapshot_translate (snapshot, &position);
|
|
||||||
gtk_snapshot_rotate (snapshot, angle);
|
|
||||||
gtk_snapshot_append_fill (snapshot, self->arrow_path, GSK_FILL_RULE_EVEN_ODD, &color);
|
|
||||||
gtk_snapshot_append_stroke (snapshot, self->arrow_path, stroke, &(GdkRGBA) { 0, 0, 0, 1 });
|
|
||||||
gtk_snapshot_restore (snapshot);
|
|
||||||
}
|
|
||||||
|
|
||||||
gsk_stroke_free (stroke);
|
|
||||||
gtk_snapshot_restore (snapshot);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gtk_path_walk_measure (GtkWidget *widget,
|
|
||||||
GtkOrientation orientation,
|
|
||||||
int for_size,
|
|
||||||
int *minimum,
|
|
||||||
int *natural,
|
|
||||||
int *minimum_baseline,
|
|
||||||
int *natural_baseline)
|
|
||||||
{
|
|
||||||
GtkPathWalk *self = GTK_PATH_WALK (widget);
|
|
||||||
|
|
||||||
if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
|
||||||
*minimum = *natural = (int) ceilf (self->bounds.size.width);
|
|
||||||
else
|
|
||||||
*minimum = *natural = (int) ceilf (self->bounds.size.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gtk_path_walk_set_n_points (GtkPathWalk *self,
|
|
||||||
gsize n_points)
|
|
||||||
{
|
|
||||||
if (self->n_points == n_points)
|
|
||||||
return;
|
|
||||||
|
|
||||||
self->n_points = n_points;
|
|
||||||
|
|
||||||
gtk_widget_queue_draw (GTK_WIDGET (self));
|
|
||||||
|
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_POINTS]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gtk_path_walk_set_path (GtkPathWalk *self,
|
|
||||||
GskPath *path)
|
|
||||||
{
|
|
||||||
if (self->path == path)
|
|
||||||
return;
|
|
||||||
|
|
||||||
g_clear_pointer (&self->path, gsk_path_unref);
|
|
||||||
graphene_rect_init (&self->bounds, 0, 0, 0, 0);
|
|
||||||
if (path)
|
|
||||||
{
|
|
||||||
GskStroke *stroke;
|
|
||||||
|
|
||||||
self->path = gsk_path_ref (path);
|
|
||||||
stroke = gsk_stroke_new (2.0);
|
|
||||||
gsk_path_get_stroke_bounds (path, stroke, &self->bounds);
|
|
||||||
gsk_stroke_free (stroke);
|
|
||||||
self->measure = gsk_path_measure_new (self->path);
|
|
||||||
}
|
|
||||||
|
|
||||||
gtk_widget_queue_resize (GTK_WIDGET (self));
|
|
||||||
|
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PATH]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gtk_path_walk_set_property (GObject *object,
|
|
||||||
guint prop_id,
|
|
||||||
const GValue *value,
|
|
||||||
GParamSpec *pspec)
|
|
||||||
|
|
||||||
{
|
|
||||||
GtkPathWalk *self = GTK_PATH_WALK (object);
|
|
||||||
|
|
||||||
switch (prop_id)
|
|
||||||
{
|
|
||||||
case PROP_N_POINTS:
|
|
||||||
gtk_path_walk_set_n_points (self, g_value_get_uint (value));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_PATH:
|
|
||||||
gtk_path_walk_set_path (self, g_value_get_boxed (value));
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gtk_path_walk_get_property (GObject *object,
|
|
||||||
guint prop_id,
|
|
||||||
GValue *value,
|
|
||||||
GParamSpec *pspec)
|
|
||||||
{
|
|
||||||
GtkPathWalk *self = GTK_PATH_WALK (object);
|
|
||||||
|
|
||||||
switch (prop_id)
|
|
||||||
{
|
|
||||||
case PROP_N_POINTS:
|
|
||||||
g_value_set_uint (value, self->n_points);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_PATH:
|
|
||||||
g_value_set_boxed (value, self->path);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gtk_path_walk_dispose (GObject *object)
|
|
||||||
{
|
|
||||||
GtkPathWalk *self = GTK_PATH_WALK (object);
|
|
||||||
|
|
||||||
g_clear_pointer (&self->path, gsk_path_unref);
|
|
||||||
g_clear_pointer (&self->measure, gsk_path_measure_unref);
|
|
||||||
g_clear_pointer (&self->arrow_path, gsk_path_unref);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (gtk_path_walk_parent_class)->dispose (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gtk_path_walk_class_init (GtkPathWalkClass *klass)
|
|
||||||
{
|
|
||||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
||||||
|
|
||||||
object_class->dispose = gtk_path_walk_dispose;
|
|
||||||
object_class->set_property = gtk_path_walk_set_property;
|
|
||||||
object_class->get_property = gtk_path_walk_get_property;
|
|
||||||
|
|
||||||
widget_class->snapshot = gtk_path_walk_snapshot;
|
|
||||||
widget_class->measure = gtk_path_walk_measure;
|
|
||||||
|
|
||||||
properties[PROP_N_POINTS] =
|
|
||||||
g_param_spec_uint ("n-points",
|
|
||||||
NULL, NULL,
|
|
||||||
1, G_MAXUINT,
|
|
||||||
500,
|
|
||||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
|
||||||
|
|
||||||
properties[PROP_PATH] =
|
|
||||||
g_param_spec_boxed ("path",
|
|
||||||
NULL, NULL,
|
|
||||||
GSK_TYPE_PATH,
|
|
||||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
|
||||||
|
|
||||||
g_object_class_install_properties (object_class, N_PROPS, properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
tick_tick_tick (GtkWidget *self,
|
|
||||||
GdkFrameClock *frame_clock,
|
|
||||||
gpointer unused)
|
|
||||||
{
|
|
||||||
gtk_widget_queue_draw (GTK_WIDGET (self));
|
|
||||||
|
|
||||||
return G_SOURCE_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gtk_path_walk_init (GtkPathWalk *self)
|
|
||||||
{
|
|
||||||
/* Data taken from
|
|
||||||
* https://commons.wikimedia.org/wiki/Maps_of_the_world#/media/File:Simplified_blank_world_map_without_Antartica_(no_borders).svg
|
|
||||||
*/
|
|
||||||
GBytes *data = g_resources_lookup_data ("/path_walk/path_world.txt", 0, NULL);
|
|
||||||
GskPath *path = gsk_path_parse (g_bytes_get_data (data, NULL));
|
|
||||||
g_bytes_unref (data);
|
|
||||||
gtk_path_walk_set_path (self, path);
|
|
||||||
gsk_path_unref (path);
|
|
||||||
self->arrow_path = gsk_path_parse ("M 5 0 L 0 -5. 0 -2, -5 -2, -5 2, 0 2, 0 5 Z");
|
|
||||||
self->n_points = 500;
|
|
||||||
gtk_widget_add_tick_callback (GTK_WIDGET (self), tick_tick_tick, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
GtkWidget *
|
|
||||||
gtk_path_walk_new (void)
|
|
||||||
{
|
|
||||||
GtkPathWalk *self;
|
|
||||||
|
|
||||||
self = g_object_new (GTK_TYPE_PATH_WALK, NULL);
|
|
||||||
|
|
||||||
return GTK_WIDGET (self);
|
|
||||||
}
|
|
||||||
|
|
||||||
GtkWidget *
|
|
||||||
do_path_walk (GtkWidget *do_widget)
|
|
||||||
{
|
|
||||||
static GtkWidget *window = NULL;
|
|
||||||
|
|
||||||
if (!window)
|
|
||||||
{
|
|
||||||
GtkBuilder *builder;
|
|
||||||
|
|
||||||
g_type_ensure (GTK_TYPE_PATH_WALK);
|
|
||||||
|
|
||||||
builder = gtk_builder_new_from_resource ("/path_walk/path_walk.ui");
|
|
||||||
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
|
|
||||||
gtk_window_set_display (GTK_WINDOW (window),
|
|
||||||
gtk_widget_get_display (do_widget));
|
|
||||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *) &window);
|
|
||||||
g_object_unref (builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gtk_widget_get_visible (window))
|
|
||||||
gtk_window_present (GTK_WINDOW (window));
|
|
||||||
else
|
|
||||||
gtk_window_destroy (GTK_WINDOW (window));
|
|
||||||
|
|
||||||
return window;
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<interface>
|
|
||||||
<object class="GtkWindow" id="window">
|
|
||||||
<property name="title" translatable="yes">World Map</property>
|
|
||||||
<property name="titlebar">
|
|
||||||
<object class="GtkHeaderBar">
|
|
||||||
<child type="end">
|
|
||||||
<object class="GtkSpinButton">
|
|
||||||
<property name="adjustment">
|
|
||||||
<object class="GtkAdjustment" id="adjustment">
|
|
||||||
<property name="lower">0</property>
|
|
||||||
<property name="upper">5000</property>
|
|
||||||
<property name="value">500</property>
|
|
||||||
<property name="step-increment">1</property>
|
|
||||||
<property name="page-increment">10</property>
|
|
||||||
</object>
|
|
||||||
</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</property>
|
|
||||||
<property name="child">
|
|
||||||
<object class="GtkBox">
|
|
||||||
<property name="orientation">vertical</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkPathWalk" id="view">
|
|
||||||
<property name="n-points" bind-source="adjustment" bind-property="value"/>
|
|
||||||
<property name="hexpand">true</property>
|
|
||||||
<property name="vexpand">true</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</property>
|
|
||||||
</object>
|
|
||||||
</interface>
|
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
/* Pickers and Launchers
|
/* Pickers and Launchers
|
||||||
* #Keywords: GtkColorDialog, GtkFontDialog, GtkFileDialog, GtkPrintDialog, GtkFileLauncher, GtkUriLauncher
|
* #Keywords: GtkColorDialog, GtkFontDialog, GtkFileDialog, GtkFileLauncher, GtkUriLauncher
|
||||||
*
|
*
|
||||||
* The dialogs are mainly intended for use in preference dialogs.
|
* The dialogs are mainly intended for use in preference dialogs.
|
||||||
* They allow to select colors, fonts and files. There is also a
|
* They allow to select colors, fonts and applications.
|
||||||
* print dialog.
|
|
||||||
*
|
*
|
||||||
* The launchers let you open files or URIs in applications that
|
* The launchers let you open files or URIs in applications that
|
||||||
* can handle them.
|
* can handle them.
|
||||||
@@ -12,13 +11,11 @@
|
|||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
static GtkWidget *app_picker;
|
static GtkWidget *app_picker;
|
||||||
static GtkWidget *print_button;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_file (GFile *file,
|
set_file (GFile *file,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
GFileInfo *info;
|
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
if (!file)
|
if (!file)
|
||||||
@@ -34,13 +31,6 @@ set_file (GFile *file,
|
|||||||
|
|
||||||
gtk_widget_set_sensitive (app_picker, TRUE);
|
gtk_widget_set_sensitive (app_picker, TRUE);
|
||||||
g_object_set_data_full (G_OBJECT (app_picker), "file", g_object_ref (file), g_object_unref);
|
g_object_set_data_full (G_OBJECT (app_picker), "file", g_object_ref (file), g_object_unref);
|
||||||
|
|
||||||
info = g_file_query_info (file, "standard::content-type", 0, NULL, NULL);
|
|
||||||
if (strcmp (g_file_info_get_content_type (info), "application/pdf") == 0)
|
|
||||||
{
|
|
||||||
gtk_widget_set_sensitive (print_button, TRUE);
|
|
||||||
g_object_set_data_full (G_OBJECT (print_button), "file", g_object_ref (file), g_object_unref);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -57,10 +47,6 @@ file_opened (GObject *source,
|
|||||||
{
|
{
|
||||||
g_print ("%s\n", error->message);
|
g_print ("%s\n", error->message);
|
||||||
g_error_free (error);
|
g_error_free (error);
|
||||||
gtk_widget_set_sensitive (app_picker, FALSE);
|
|
||||||
g_object_set_data (G_OBJECT (app_picker), "file", NULL);
|
|
||||||
gtk_widget_set_sensitive (print_button, FALSE);
|
|
||||||
g_object_set_data (G_OBJECT (print_button), "file", NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set_file (file, data);
|
set_file (file, data);
|
||||||
@@ -128,53 +114,6 @@ open_app (GtkButton *picker)
|
|||||||
g_object_unref (launcher);
|
g_object_unref (launcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
print_file_done (GObject *source,
|
|
||||||
GAsyncResult *result,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
GtkPrintDialog *dialog = GTK_PRINT_DIALOG (source);
|
|
||||||
GError *error = NULL;
|
|
||||||
GCancellable *cancellable;
|
|
||||||
unsigned int id;
|
|
||||||
|
|
||||||
cancellable = g_task_get_cancellable (G_TASK (result));
|
|
||||||
id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (cancellable), "timeout"));
|
|
||||||
if (id)
|
|
||||||
g_source_remove (id);
|
|
||||||
|
|
||||||
if (!gtk_print_dialog_print_file_finish (dialog, result, &error))
|
|
||||||
{
|
|
||||||
g_print ("%s\n", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
print_file (GtkButton *picker)
|
|
||||||
{
|
|
||||||
GtkWindow *parent = GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (picker)));
|
|
||||||
GtkPrintDialog *dialog;
|
|
||||||
GCancellable *cancellable;
|
|
||||||
GFile *file;
|
|
||||||
unsigned int id;
|
|
||||||
|
|
||||||
file = G_FILE (g_object_get_data (G_OBJECT (picker), "file"));
|
|
||||||
dialog = gtk_print_dialog_new ();
|
|
||||||
|
|
||||||
cancellable = g_cancellable_new ();
|
|
||||||
|
|
||||||
id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT,
|
|
||||||
20,
|
|
||||||
abort_mission, g_object_ref (cancellable), g_object_unref);
|
|
||||||
g_object_set_data (G_OBJECT (cancellable), "timeout", GUINT_TO_POINTER (id));
|
|
||||||
|
|
||||||
gtk_print_dialog_print_file (dialog, parent, NULL, file, cancellable, print_file_done, NULL);
|
|
||||||
|
|
||||||
g_object_unref (cancellable);
|
|
||||||
g_object_unref (dialog);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
open_uri_done (GObject *source,
|
open_uri_done (GObject *source,
|
||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
@@ -295,15 +234,9 @@ do_pickers (GtkWidget *do_widget)
|
|||||||
gtk_widget_set_sensitive (app_picker, FALSE);
|
gtk_widget_set_sensitive (app_picker, FALSE);
|
||||||
g_signal_connect (app_picker, "clicked", G_CALLBACK (open_app), NULL);
|
g_signal_connect (app_picker, "clicked", G_CALLBACK (open_app), NULL);
|
||||||
gtk_box_append (GTK_BOX (picker), app_picker);
|
gtk_box_append (GTK_BOX (picker), app_picker);
|
||||||
|
|
||||||
print_button = gtk_button_new_from_icon_name ("printer-symbolic");
|
|
||||||
gtk_widget_set_tooltip_text (print_button, "Print file");
|
|
||||||
gtk_widget_set_sensitive (print_button, FALSE);
|
|
||||||
g_signal_connect (print_button, "clicked", G_CALLBACK (print_file), NULL);
|
|
||||||
gtk_box_append (GTK_BOX (picker), print_button);
|
|
||||||
|
|
||||||
gtk_grid_attach (GTK_GRID (table), picker, 1, 2, 1, 1);
|
gtk_grid_attach (GTK_GRID (table), picker, 1, 2, 1, 1);
|
||||||
|
|
||||||
|
|
||||||
label = gtk_label_new ("URI:");
|
label = gtk_label_new ("URI:");
|
||||||
gtk_widget_set_halign (label, GTK_ALIGN_START);
|
gtk_widget_set_halign (label, GTK_ALIGN_START);
|
||||||
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
|
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 844 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 823 B |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
@@ -147,19 +147,6 @@ Creates a node like `gsk_cross_fade_node_new()` with the given properties.
|
|||||||
|
|
||||||
Creates a node like `gsk_debug_node_new()` with the given properties.
|
Creates a node like `gsk_debug_node_new()` with the given properties.
|
||||||
|
|
||||||
### fill
|
|
||||||
|
|
||||||
| property | syntax | default | printed |
|
|
||||||
| --------- | --------------- | ---------------------- | ----------- |
|
|
||||||
| child | `<node>` | *see below* | always |
|
|
||||||
| path | `<string>` | "" | always |
|
|
||||||
| fill-rule | `<fill-rule>` | winding | always |
|
|
||||||
|
|
||||||
Creates a node like `gsk_fill_node_new()` with the given properties.
|
|
||||||
|
|
||||||
The default child node is the default color node, but created with the
|
|
||||||
bounds of the path.
|
|
||||||
|
|
||||||
### glshader
|
### glshader
|
||||||
|
|
||||||
| property | syntax | default | printed |
|
| property | syntax | default | printed |
|
||||||
@@ -302,24 +289,6 @@ Creates a node like `gsk_rounded_clip_node_new()` with the given properties.
|
|||||||
|
|
||||||
Creates a node like `gsk_shadow_node_new()` with the given properties.
|
Creates a node like `gsk_shadow_node_new()` with the given properties.
|
||||||
|
|
||||||
### stroke
|
|
||||||
|
|
||||||
| property | syntax | default | printed |
|
|
||||||
| ----------- | ------------------ | ----------------- | ----------- |
|
|
||||||
| child | `<node>` | *see below* | always |
|
|
||||||
| path | `<string>` | "" | always |
|
|
||||||
| line-width | `<number>` | 0 | non-default |
|
|
||||||
| line-cap | `<line-cap>` | butt | always |
|
|
||||||
| line-join | `<line-join>` | miter | always |
|
|
||||||
| miter-limit | `<number>` | 4 | non-default |
|
|
||||||
| dash | `<number>{+}|none` | none | non-default |
|
|
||||||
| dash-offset | `<number>` | 0 | non-default |
|
|
||||||
|
|
||||||
Creates a node like `gsk_stroke_node_new()` with the given properties.
|
|
||||||
|
|
||||||
The default child node is the default color node, but created with the
|
|
||||||
stroke bounds of the path.
|
|
||||||
|
|
||||||
### text
|
### text
|
||||||
|
|
||||||
| property | syntax | default | printed |
|
| property | syntax | default | printed |
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1019 B After Width: | Height: | Size: 985 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 844 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 823 B |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
@@ -32,34 +32,7 @@ show_class_hierarchy = true
|
|||||||
base_url = "https://gitlab.gnome.org/GNOME/gtk/-/blob/main/"
|
base_url = "https://gitlab.gnome.org/GNOME/gtk/-/blob/main/"
|
||||||
|
|
||||||
[extra]
|
[extra]
|
||||||
content_files = [
|
|
||||||
"paths.md",
|
|
||||||
]
|
|
||||||
content_images = [
|
content_images = [
|
||||||
"gtk-logo.svg",
|
"gtk-logo.svg",
|
||||||
"images/arc-dark.png",
|
|
||||||
"images/arc-light.png",
|
|
||||||
"images/caps-dark.png",
|
|
||||||
"images/caps-light.png",
|
|
||||||
"images/conic-light.png",
|
|
||||||
"images/conic-dark.png",
|
|
||||||
"images/cubic-dark.png",
|
|
||||||
"images/cubic-light.png",
|
|
||||||
"images/curvature-dark.png",
|
|
||||||
"images/curvature-light.png",
|
|
||||||
"images/directions-dark.png",
|
|
||||||
"images/directions-light.png",
|
|
||||||
"images/fill-even-odd.png",
|
|
||||||
"images/fill-winding.png",
|
|
||||||
"images/join-dark.png",
|
|
||||||
"images/join-light.png",
|
|
||||||
"images/line-dark.png",
|
|
||||||
"images/line-light.png",
|
|
||||||
"images/path-dark.png",
|
|
||||||
"images/path-light.png",
|
|
||||||
"images/quad-dark.png",
|
|
||||||
"images/quad-light.png",
|
|
||||||
"images/stroke-miter.png",
|
|
||||||
"images/stroke-round.png",
|
|
||||||
]
|
]
|
||||||
urlmap_file = "urlmap.js"
|
urlmap_file = "urlmap.js"
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 8.4 KiB |
@@ -1,92 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
width="210mm"
|
|
||||||
height="297mm"
|
|
||||||
viewBox="0 0 210 297"
|
|
||||||
version="1.1"
|
|
||||||
id="svg1"
|
|
||||||
inkscape:version="1.3 (0e150ed6c4, 2023-07-21)"
|
|
||||||
sodipodi:docname="arcto.svg"
|
|
||||||
inkscape:export-filename="cubic-light.png"
|
|
||||||
inkscape:export-xdpi="96"
|
|
||||||
inkscape:export-ydpi="96"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg">
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="namedview1"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#000000"
|
|
||||||
borderopacity="0.25"
|
|
||||||
inkscape:showpageshadow="2"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pagecheckerboard="0"
|
|
||||||
inkscape:deskcolor="#d1d1d1"
|
|
||||||
inkscape:document-units="mm"
|
|
||||||
inkscape:zoom="0.75989759"
|
|
||||||
inkscape:cx="399.39592"
|
|
||||||
inkscape:cy="466.51023"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1123"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="0"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="false" />
|
|
||||||
<defs
|
|
||||||
id="defs1" />
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1">
|
|
||||||
<path
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
|
|
||||||
d="M 58.033485,123.96862 C 75.231194,113.95411 92.489919,103.26728 107.81401,113.89786"
|
|
||||||
id="path3"
|
|
||||||
sodipodi:nodetypes="cc" />
|
|
||||||
<ellipse
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:0.20061772;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
|
|
||||||
id="path2"
|
|
||||||
cx="-16.837238"
|
|
||||||
cy="154.55043"
|
|
||||||
rx="35.832706"
|
|
||||||
ry="17.920988"
|
|
||||||
transform="matrix(0.86643544,-0.49928912,0.59215321,0.8058254,0,0)" />
|
|
||||||
<path
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
|
|
||||||
d="M 57.432798,124.38759 86.59638,102.1496 107.25717,113.71009"
|
|
||||||
id="path1"
|
|
||||||
sodipodi:nodetypes="ccc" />
|
|
||||||
<circle
|
|
||||||
style="fill:#ff0404;fill-opacity:1;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
|
|
||||||
id="path2-8-7-9"
|
|
||||||
cx="86.580566"
|
|
||||||
cy="102.81618"
|
|
||||||
r="1.5" />
|
|
||||||
<path
|
|
||||||
style="fill:#f90048;stroke:#a2a2a2;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
|
|
||||||
d="m 45.061871,134.70541 12.60825,-10.20893"
|
|
||||||
id="path4-4"
|
|
||||||
sodipodi:nodetypes="cc" />
|
|
||||||
<path
|
|
||||||
style="fill:#f90048;stroke:#a2a2a2;stroke-width:1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:1, 3;stroke-dashoffset:0;stroke-opacity:1"
|
|
||||||
d="m 35.405008,142.35717 8.95641,-7.26298"
|
|
||||||
id="path4-8-8"
|
|
||||||
sodipodi:nodetypes="cc" />
|
|
||||||
<circle
|
|
||||||
style="fill:#818181;fill-opacity:1;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
|
|
||||||
id="path2-8-7-61-1"
|
|
||||||
cx="57.597607"
|
|
||||||
cy="124.23325"
|
|
||||||
r="1.5" />
|
|
||||||
<circle
|
|
||||||
style="fill:#ff0404;fill-opacity:1;stroke:#000064;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:10;stroke-dasharray:none"
|
|
||||||
id="path2-8-7-6-5"
|
|
||||||
cx="108.01463"
|
|
||||||
cy="114.17829"
|
|
||||||
r="1.5" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 12 KiB |