Compare commits
12 Commits
fix-7147
...
wip/matthi
Author | SHA1 | Date | |
---|---|---|---|
|
4c5fc2db89 | ||
|
9faeea801e | ||
|
26aecbb006 | ||
|
17ccb849b3 | ||
|
4a3894e820 | ||
|
156a7450be | ||
|
b7988d133d | ||
|
1baaeeb048 | ||
|
63f489dc64 | ||
|
3323f08c75 | ||
|
35060aae8d | ||
|
c6c13ded6a |
2
.gitignore
vendored
@@ -1,4 +1,2 @@
|
||||
/subprojects/*/
|
||||
.flatpak-builder/
|
||||
.vscode/
|
||||
subprojects/*.wrap
|
||||
|
@@ -22,12 +22,11 @@ stages:
|
||||
|
||||
# Common variables
|
||||
variables:
|
||||
COMMON_MESON_FLAGS: "-Dwerror=true -Dcairo:werror=false -Dgi-docgen:werror=false -Dgraphene:werror=false -Dlibepoxy:werror=false -Dlibsass:werror=false -Dpango:werror=false -Dsassc:werror=false -Dgdk-pixbuf:werror=false -Dglib:werror=false -Dlibcloudproviders:werror=false -Dlibpng:werror=false -Dlibtiff:werror=false -Dsysprof:werror=false -Dwayland-protocols:werror=false -Dharfbuzz:werror=false -Dfreetype2:werror=false -Dfontconfig:werror=false -Dfribidi:werror=false -Dlibffi:werror=false -Dlibjpeg-turbo:werror=false -Dmutest:werror=false -Dpcre2:werror=false -Dpixman:werror=false -Dproxy-libintl:werror=false"
|
||||
COMMON_MESON_FLAGS: "-Dwerror=true -Dcairo:werror=false -Dgi-docgen:werror=false -Dgraphene:werror=false -Dlibepoxy:werror=false -Dlibsass:werror=false -Dpango:werror=false -Dsassc:werror=false -Dgdk-pixbuf:werror=false -Dglib:werror=false -Dlibcloudproviders:werror=false -Dlibpng:werror=false -Dlibtiff:werror=false -Dsysprof:werror=false -Dwayland-protocols:werror=false -Dharfbuzz:werror=false -Dfreetype2:werror=false -Dfontconfig:werror=false -Dfribidi:werror=false -Dlibffi:werror=false -Dlibjpeg-turbo:werror=false -Dmutest:werror=false -Dpixman:werror=false -Dproxy-libintl:werror=false"
|
||||
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true"
|
||||
FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled -Dbuild-testsuite=true -Dintrospection=enabled"
|
||||
MESON_TEST_TIMEOUT_MULTIPLIER: 3
|
||||
MESON_TEST_MAX_PROCESSES: 8
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v52"
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v49"
|
||||
|
||||
workflow:
|
||||
rules:
|
||||
@@ -62,16 +61,19 @@ style-check-diff:
|
||||
.build-fedora-default:
|
||||
image: $FEDORA_IMAGE
|
||||
artifacts:
|
||||
name: "gtk-${CI_COMMIT_REF_NAME}"
|
||||
when: always
|
||||
reports:
|
||||
junit:
|
||||
- "${CI_PROJECT_DIR}/_build/meson-logs/testlog-x11.junit.xml"
|
||||
- "${CI_PROJECT_DIR}/_build/meson-logs/testlog-wayland.junit.xml"
|
||||
- "${CI_PROJECT_DIR}/_build/meson-logs/testlog-wayland_gl.junit.xml"
|
||||
- "${CI_PROJECT_DIR}/_build/meson-logs/testlog-broadway.junit.xml"
|
||||
- "${CI_PROJECT_DIR}/_build/report-x11.xml"
|
||||
- "${CI_PROJECT_DIR}/_build/report-wayland.xml"
|
||||
- "${CI_PROJECT_DIR}/_build/report-wayland_gl.xml"
|
||||
- "${CI_PROJECT_DIR}/_build/report-wayland_gles2.xml"
|
||||
- "${CI_PROJECT_DIR}/_build/report-broadway.xml"
|
||||
name: "gtk-${CI_COMMIT_REF_NAME}"
|
||||
paths:
|
||||
- "${CI_PROJECT_DIR}/_build/meson-logs"
|
||||
- "${CI_PROJECT_DIR}/_build/report*.xml"
|
||||
- "${CI_PROJECT_DIR}/_build/report*.html"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/reftests/output/*/*.png"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/reftests/output/*/*.node"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/tools/output/*/*"
|
||||
@@ -115,12 +117,10 @@ release-build:
|
||||
EXTRA_MESON_FLAGS: "--buildtype=release"
|
||||
script:
|
||||
- .gitlab-ci/show-info-linux.sh
|
||||
- mkdir _install
|
||||
# don't use catch by default, since it causes sporadic test failures
|
||||
# - export PATH="$HOME/.local/bin:${CI_PROJECT_DIR}/_install/bin:$PATH"
|
||||
# - .gitlab-ci/install-meson-project.sh --prefix ${CI_PROJECT_DIR}/_install https://gitlab.gnome.org/jadahl/catch.git main
|
||||
- export PATH="$HOME/.local/bin:$PATH"
|
||||
- meson subprojects download
|
||||
- meson subprojects update --reset
|
||||
- mkdir _install
|
||||
- meson setup
|
||||
--prefix=${CI_PROJECT_DIR}/_install
|
||||
${COMMON_MESON_FLAGS}
|
||||
@@ -133,6 +133,8 @@ release-build:
|
||||
- PKG_CONFIG_PATH=${CI_PROJECT_DIR}/_install/lib64/pkgconfig:${CI_PROJECT_DIR}/_install/share/pkgconfig meson setup _build_hello examples/hello
|
||||
- LD_LIBRARY_PATH=${CI_PROJECT_DIR}/_install/lib64 meson compile -C _build_hello
|
||||
- .gitlab-ci/run-tests.sh _build wayland gtk
|
||||
# only repeat test runs that are likely affected by test setups
|
||||
- .gitlab-ci/run-tests.sh _build wayland_gles2 gtk:gdk,gtk:gsk-gl
|
||||
|
||||
fedora-clang:
|
||||
extends: .build-fedora-default
|
||||
@@ -196,11 +198,11 @@ fedora-mingw64:
|
||||
- subprojects/libepoxy/
|
||||
- subprojects/pango/
|
||||
|
||||
msys2-ucrt64:
|
||||
msys2-mingw64:
|
||||
extends: .mingw-defaults
|
||||
needs: []
|
||||
variables:
|
||||
MSYSTEM: "UCRT64"
|
||||
MSYSTEM: "MINGW64"
|
||||
CHERE_INVOKING: "yes"
|
||||
artifacts:
|
||||
when: always
|
||||
@@ -216,7 +218,7 @@ macos:
|
||||
when: never
|
||||
- if: $RUNNER == "macosintel"
|
||||
variables:
|
||||
SDKROOT: /opt/sdks/MacOSX10.15.6.sdk
|
||||
SDKROOT: /opt/sdks/MacOSX10.13.4.sdk
|
||||
NINJA_PKG: $CI_API_V4_URL/projects/30745/packages/generic/ninja_macos/v1.11.1.1+9/ninja-1.11.1.1-cp38-cp38-macosx_11_0_x86_64.whl
|
||||
when: manual
|
||||
allow_failure: true
|
||||
@@ -240,7 +242,6 @@ macos:
|
||||
PIPENV_CACHE_DIR: $PIP_CACHE_DIR
|
||||
PYTHONPYCACHEPREFIX: $PIP_CACHE_DIR
|
||||
before_script:
|
||||
- ls /opt/sdks/
|
||||
- .gitlab-ci/show-info-macos.sh
|
||||
- python3 -m venv .venv
|
||||
# Building the introspection feature requires pkg-config and bison.
|
||||
@@ -264,7 +265,7 @@ macos:
|
||||
paths:
|
||||
- "${CI_PROJECT_DIR}/_build/meson-logs"
|
||||
|
||||
vs2019-x64:
|
||||
vs2017-x64:
|
||||
# TODO: Uncomment this when ready to merge.
|
||||
# rules:
|
||||
# - if: $CI_PROJECT_NAMESPACE == "GNOME"
|
||||
@@ -273,7 +274,7 @@ vs2019-x64:
|
||||
- win32-ps
|
||||
needs: []
|
||||
script:
|
||||
- .gitlab-ci/test-msvc.bat ${COMMON_MESON_FLAGS}
|
||||
- .gitlab-ci/test-msvc.bat
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
@@ -326,6 +327,20 @@ flatpak:widget-factory:aarch64:
|
||||
variables:
|
||||
APPID: org.gtk.WidgetFactory4
|
||||
|
||||
flatpak:icon-browser:
|
||||
extends: '.flatpak-defaults'
|
||||
needs: []
|
||||
variables:
|
||||
APPID: org.gtk.IconBrowser4
|
||||
|
||||
flatpak:icon-browser:aarch64:
|
||||
extends: '.flatpak-defaults'
|
||||
needs: []
|
||||
tags:
|
||||
- flatpak-aarch64
|
||||
variables:
|
||||
APPID: org.gtk.IconBrowser4
|
||||
|
||||
flatpak:node-editor:
|
||||
extends: '.flatpak-defaults'
|
||||
needs: []
|
||||
@@ -359,6 +374,14 @@ nightly factory aarch64:
|
||||
extends: '.publish_nightly'
|
||||
needs: ['flatpak:widget-factory:aarch64']
|
||||
|
||||
nightly icon-browser:
|
||||
extends: '.publish_nightly'
|
||||
needs: ['flatpak:icon-browser']
|
||||
|
||||
nightly icon-browser aarch64:
|
||||
extends: '.publish_nightly'
|
||||
needs: ['flatpak:icon-browser:aarch64']
|
||||
|
||||
nightly node-editor:
|
||||
extends: '.publish_nightly'
|
||||
needs: ['flatpak:node-editor']
|
||||
@@ -390,12 +413,11 @@ static-scan:
|
||||
# Run tests with the address sanitizer. We need to turn off introspection
|
||||
# and f16c, since they are incompatible with asan
|
||||
asan-build:
|
||||
extends: .build-fedora-default
|
||||
image: $FEDORA_IMAGE
|
||||
tags: [ asan ]
|
||||
stage: analysis
|
||||
needs: []
|
||||
variables:
|
||||
MESON_TEST_MAX_PROCESSES: 4
|
||||
script:
|
||||
- export PATH="$HOME/.local/bin:$PATH"
|
||||
- CC=clang meson setup
|
||||
@@ -423,10 +445,10 @@ reference:
|
||||
--force-fallback-for=gdk-pixbuf,pango
|
||||
-Dintrospection=enabled
|
||||
-Ddocumentation=true
|
||||
-Dman-pages=true
|
||||
-Dgtk_doc=true
|
||||
-Dgdk-pixbuf:gtk_doc=true
|
||||
-Dpango:documentation=true
|
||||
-Dbuild-demos=true
|
||||
-Dpango:gtk_doc=true
|
||||
-Dbuild-demos=false
|
||||
-Dbuild-examples=false
|
||||
-Dbuild-tests=false
|
||||
-Dbuild-testsuite=false
|
||||
@@ -438,7 +460,6 @@ reference:
|
||||
- mv _build/docs/reference/gdk/gdk4-wayland/ _reference/gdk4-wayland/
|
||||
- mv _build/docs/reference/gsk/gsk4/ _reference/gsk4/
|
||||
- mv _build/docs/reference/gtk/gtk4/ _reference/gtk4/
|
||||
- mv _build/docs/reference/gtk/*.html _reference/gtk4/
|
||||
- mv _build/subprojects/pango/docs/Pango/ _reference/Pango/
|
||||
- mv _build/subprojects/pango/docs/PangoCairo/ _reference/PangoCairo/
|
||||
- mv _build/subprojects/pango/docs/PangoFc/ _reference/PangoFc/
|
||||
|
BIN
.gitlab-ci/.fedora.Dockerfile.swp
Normal file
@@ -1,4 +1,4 @@
|
||||
FROM fedora:40
|
||||
FROM fedora:39
|
||||
|
||||
RUN dnf -y install \
|
||||
adwaita-icon-theme \
|
||||
@@ -99,11 +99,8 @@ RUN dnf -y install \
|
||||
which \
|
||||
wireplumber \
|
||||
xorg-x11-server-Xvfb \
|
||||
&& dnf -y update \
|
||||
&& dnf clean all
|
||||
|
||||
RUN rm /usr/share/vulkan/icd.d/powervr_mesa_icd.x86_64.json
|
||||
|
||||
# Enable sudo for wheel users
|
||||
RUN sed -i -e 's/# %wheel/%wheel/' -e '0,/%wheel/{s/%wheel/# %wheel/}' /etc/sudoers
|
||||
|
||||
|
@@ -19,12 +19,13 @@ flatpak build ${builddir} meson \
|
||||
--buildtype=debugoptimized \
|
||||
-Dx11-backend=true \
|
||||
-Dwayland-backend=true \
|
||||
-Dvulkan=disabled \
|
||||
-Dbuild-tests=false \
|
||||
-Dbuild-testsuite=false \
|
||||
-Dbuild-examples=false \
|
||||
-Dintrospection=disabled \
|
||||
-Dbuild-demos=true \
|
||||
-Dprofile=devel \
|
||||
-Ddemo-profile=devel \
|
||||
_flatpak_build
|
||||
|
||||
flatpak build --env=CI_COMMIT_SHORT_SHA=$CI_COMMIT_SHORT_SHA ${builddir} ninja -C _flatpak_build install
|
||||
|
@@ -1,91 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
usage() {
|
||||
cat <<-EOF
|
||||
Usage: $(basename $0) [OPTION…] REPO_URL COMMIT
|
||||
|
||||
Check out and install a meson project
|
||||
|
||||
Options:
|
||||
-Dkey=val Option to pass on to meson
|
||||
--prefix Prefix to install to
|
||||
--subdir Build subdirectory instead of whole project
|
||||
--prepare Script to run before build
|
||||
|
||||
-h, --help Display this help
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
TEMP=$(getopt \
|
||||
--name=$(basename $0) \
|
||||
--options='D:h' \
|
||||
--longoptions='prefix:' \
|
||||
--longoptions='subdir:' \
|
||||
--longoptions='prepare:' \
|
||||
--longoptions='help' \
|
||||
-- "$@")
|
||||
|
||||
eval set -- "$TEMP"
|
||||
unset TEMP
|
||||
|
||||
MESON_OPTIONS=()
|
||||
PREFIX=/usr
|
||||
SUBDIR=.
|
||||
PREPARE=:
|
||||
|
||||
while true; do
|
||||
case "$1" in
|
||||
-D)
|
||||
MESON_OPTIONS+=( -D$2 )
|
||||
shift 2
|
||||
;;
|
||||
|
||||
--prefix)
|
||||
PREFIX=$2
|
||||
shift 2
|
||||
;;
|
||||
|
||||
--subdir)
|
||||
SUBDIR=$2
|
||||
shift 2
|
||||
;;
|
||||
|
||||
--prepare)
|
||||
PREPARE=$2
|
||||
shift 2
|
||||
;;
|
||||
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ $# -lt 2 ]]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
REPO_URL="$1"
|
||||
COMMIT="$2"
|
||||
|
||||
CHECKOUT_DIR=$(mktemp --directory)
|
||||
trap "rm -rf $CHECKOUT_DIR" EXIT
|
||||
|
||||
git clone --depth 1 "$REPO_URL" -b "$COMMIT" "$CHECKOUT_DIR"
|
||||
|
||||
pushd "$CHECKOUT_DIR/$SUBDIR"
|
||||
sh -c "$PREPARE"
|
||||
meson setup --prefix "$PREFIX" _build "${MESON_OPTIONS[@]}"
|
||||
meson compile -C _build
|
||||
meson install -C _build
|
||||
popd
|
@@ -8,21 +8,17 @@ builddir=$1
|
||||
setup=$2
|
||||
suite=$3
|
||||
multiplier=${MESON_TEST_TIMEOUT_MULTIPLIER:-1}
|
||||
n_processes=${MESON_TEST_MAX_PROCESSES:-1}
|
||||
|
||||
# Ignore memory leaks lower in dependencies
|
||||
export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp:print_suppressions=0:detect_leaks=0:allocator_may_return_null=1:symbolize=1
|
||||
export ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer
|
||||
|
||||
export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp:print_suppressions=0:detect_leaks=0:allocator_may_return_null=1
|
||||
export G_SLICE=always-malloc
|
||||
|
||||
case "${setup}" in
|
||||
x11*)
|
||||
dbus-run-session -- \
|
||||
xvfb-run -a -s "-screen 0 1024x768x24 -noreset" \
|
||||
xvfb-run -a -s "-screen 0 1024x768x24 -noreset" \
|
||||
meson test -C ${builddir} \
|
||||
--quiet \
|
||||
--timeout-multiplier "${multiplier}" \
|
||||
--num-processes "${n_processes}" \
|
||||
--print-errorlogs \
|
||||
--setup=${setup} \
|
||||
--suite=${suite//,/ --suite=} \
|
||||
@@ -44,11 +40,9 @@ case "${setup}" in
|
||||
compositor=$!
|
||||
export WAYLAND_DISPLAY=wayland-5
|
||||
|
||||
dbus-run-session -- \
|
||||
meson test -C ${builddir} \
|
||||
meson test -C ${builddir} \
|
||||
--quiet \
|
||||
--timeout-multiplier "${multiplier}" \
|
||||
--num-processes "${n_processes}" \
|
||||
--print-errorlogs \
|
||||
--setup=${setup} \
|
||||
--suite=${suite//,/ --suite=} \
|
||||
@@ -69,11 +63,9 @@ case "${setup}" in
|
||||
server=$!
|
||||
export BROADWAY_DISPLAY=:5
|
||||
|
||||
dbus-run-session -- \
|
||||
meson test -C ${builddir} \
|
||||
meson test -C ${builddir} \
|
||||
--quiet \
|
||||
--timeout-multiplier "${multiplier}" \
|
||||
--num-processes "${n_processes}" \
|
||||
--print-errorlogs \
|
||||
--setup=${setup} \
|
||||
--suite=${suite//,/ --suite=} \
|
||||
@@ -95,6 +87,13 @@ esac
|
||||
|
||||
cd ${builddir}
|
||||
|
||||
$srcdir/.gitlab-ci/meson-junit-report.py \
|
||||
--project-name=gtk \
|
||||
--backend="${setup}" \
|
||||
--job-id="${CI_JOB_NAME}" \
|
||||
--output="report-${setup}.xml" \
|
||||
"meson-logs/testlog-${setup}.json"
|
||||
|
||||
$srcdir/.gitlab-ci/meson-html-report.py \
|
||||
--project-name=gtk \
|
||||
--backend="${setup}" \
|
||||
|
@@ -1,11 +1,12 @@
|
||||
@echo on
|
||||
:: vcvarsall.bat sets various env vars like PATH, INCLUDE, LIB, LIBPATH for the
|
||||
:: specified build architecture
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" x64
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" x64
|
||||
@echo on
|
||||
|
||||
pip3 install --upgrade --user meson~=1.2 || goto :error
|
||||
meson setup -Dbackend_max_links=1 -Ddebug=false -Dmedia-gstreamer=disabled -Dvulkan=disabled %~1 _build || goto :error
|
||||
:: FIXME: make warnings fatal
|
||||
pip3 install --upgrade --user meson~=0.64 || goto :error
|
||||
meson setup -Dbackend_max_links=1 -Ddebug=false -Dmedia-gstreamer=disabled -Dvulkan=disabled _build || goto :error
|
||||
ninja -C _build || goto :error
|
||||
|
||||
goto :EOF
|
||||
|
@@ -2,6 +2,12 @@
|
||||
|
||||
set -e
|
||||
|
||||
if [[ "$MSYSTEM" == "MINGW32" ]]; then
|
||||
export MSYS2_ARCH="i686"
|
||||
else
|
||||
export MSYS2_ARCH="x86_64"
|
||||
fi
|
||||
|
||||
# Update everything
|
||||
pacman --noconfirm -Suy
|
||||
|
||||
@@ -9,27 +15,26 @@ pacman --noconfirm -Suy
|
||||
pacman --noconfirm -S --needed \
|
||||
base-devel \
|
||||
git \
|
||||
${MINGW_PACKAGE_PREFIX}-cc \
|
||||
${MINGW_PACKAGE_PREFIX}-ccache \
|
||||
${MINGW_PACKAGE_PREFIX}-pkgconf \
|
||||
${MINGW_PACKAGE_PREFIX}-gobject-introspection \
|
||||
${MINGW_PACKAGE_PREFIX}-meson \
|
||||
${MINGW_PACKAGE_PREFIX}-adwaita-icon-theme \
|
||||
${MINGW_PACKAGE_PREFIX}-atk \
|
||||
${MINGW_PACKAGE_PREFIX}-cairo \
|
||||
${MINGW_PACKAGE_PREFIX}-gdk-pixbuf2 \
|
||||
${MINGW_PACKAGE_PREFIX}-glib2 \
|
||||
${MINGW_PACKAGE_PREFIX}-graphene \
|
||||
${MINGW_PACKAGE_PREFIX}-json-glib \
|
||||
${MINGW_PACKAGE_PREFIX}-libepoxy \
|
||||
${MINGW_PACKAGE_PREFIX}-pango \
|
||||
${MINGW_PACKAGE_PREFIX}-fribidi \
|
||||
${MINGW_PACKAGE_PREFIX}-gst-plugins-bad-libs \
|
||||
${MINGW_PACKAGE_PREFIX}-shared-mime-info \
|
||||
${MINGW_PACKAGE_PREFIX}-python-gobject \
|
||||
${MINGW_PACKAGE_PREFIX}-shaderc \
|
||||
${MINGW_PACKAGE_PREFIX}-vulkan \
|
||||
${MINGW_PACKAGE_PREFIX}-vulkan-headers
|
||||
mingw-w64-$MSYS2_ARCH-cc \
|
||||
mingw-w64-$MSYS2_ARCH-ccache \
|
||||
mingw-w64-$MSYS2_ARCH-pkgconf \
|
||||
mingw-w64-$MSYS2_ARCH-gobject-introspection \
|
||||
mingw-w64-$MSYS2_ARCH-meson \
|
||||
mingw-w64-$MSYS2_ARCH-adwaita-icon-theme \
|
||||
mingw-w64-$MSYS2_ARCH-atk \
|
||||
mingw-w64-$MSYS2_ARCH-cairo \
|
||||
mingw-w64-$MSYS2_ARCH-gdk-pixbuf2 \
|
||||
mingw-w64-$MSYS2_ARCH-glib2 \
|
||||
mingw-w64-$MSYS2_ARCH-graphene \
|
||||
mingw-w64-$MSYS2_ARCH-json-glib \
|
||||
mingw-w64-$MSYS2_ARCH-libepoxy \
|
||||
mingw-w64-$MSYS2_ARCH-pango \
|
||||
mingw-w64-$MSYS2_ARCH-fribidi \
|
||||
mingw-w64-$MSYS2_ARCH-gst-plugins-bad-libs \
|
||||
mingw-w64-$MSYS2_ARCH-shared-mime-info \
|
||||
mingw-w64-$MSYS2_ARCH-python-gobject \
|
||||
mingw-w64-$MSYS2_ARCH-shaderc \
|
||||
mingw-w64-$MSYS2_ARCH-vulkan
|
||||
|
||||
mkdir -p _ccache
|
||||
export CCACHE_BASEDIR="$(pwd)"
|
||||
@@ -39,7 +44,7 @@ export CCACHE_DIR="${CCACHE_BASEDIR}/_ccache"
|
||||
ccache --zero-stats
|
||||
ccache --show-stats
|
||||
export CCACHE_DISABLE=true
|
||||
meson setup \
|
||||
meson \
|
||||
-Dx11-backend=false \
|
||||
-Dwayland-backend=false \
|
||||
-Dwin32-backend=true \
|
||||
|
@@ -34,9 +34,7 @@
|
||||
<!--
|
||||
- Which version of GTK you are using
|
||||
- What operating system and version
|
||||
- What windowing system (X11 or Wayland)
|
||||
- What graphics driver / mesa version
|
||||
- For Linux, which distribution
|
||||
- For Linux, which distribution
|
||||
- If you built GTK yourself, the list of options used to configure the build
|
||||
-->
|
||||
|
||||
|
@@ -35,7 +35,7 @@ The issue tracker is meant to be used for actionable issues only.
|
||||
|
||||
You should not open a new issue for security related questions.
|
||||
|
||||
When in doubt, follow the process for [GNOME security issues](https://security.gnome.org/).
|
||||
When in doubt, follow [security](https://security.gnome.org/).
|
||||
|
||||
### Bug reports
|
||||
|
||||
@@ -100,16 +100,14 @@ development tools appropriate for your operating system, including:
|
||||
- Meson
|
||||
- Ninja
|
||||
- Gettext (19.7 or newer)
|
||||
- a [C99 compatible compiler][glib-toolchain-reqs]
|
||||
- a [C99 compatible compiler](https://wiki.gnome.org/Projects/GLib/CompilerRequirements)
|
||||
|
||||
Up-to-date instructions about developing GNOME applications and libraries
|
||||
can be found on [the GNOME Developer Center](https://developer.gnome.org).
|
||||
|
||||
The GTK project uses GitLab for code hosting and for tracking issues. More
|
||||
information about using GitLab can be found on [the GNOME handbook][handbook].
|
||||
|
||||
[glib-toolchain-reqs]: https://gitlab.gnome.org/GNOME/glib/-/blob/main/docs/toolchain-requirements.md
|
||||
[handbook]: https://handbook.gnome.org/infrastructure/gitlab.html
|
||||
information about using GitLab can be found [on the GNOME
|
||||
wiki](https://wiki.gnome.org/GitLab).
|
||||
|
||||
### Dependencies
|
||||
|
||||
@@ -133,7 +131,7 @@ GTK will attempt to download and build some of these dependencies if it
|
||||
cannot find them on your system.
|
||||
|
||||
Additionally, you may want to look at projects that create a development
|
||||
environment for you, like [jhbuild](https://gitlab.gnome.org/GNOME/jhbuild)
|
||||
environment for you, like [jhbuild](https://wiki.gnome.org/HowDoI/Jhbuild)
|
||||
and [gvsbuild](https://github.com/wingtk/gvsbuild).
|
||||
|
||||
### Getting started
|
||||
@@ -146,28 +144,33 @@ $ git clone https://gitlab.gnome.org/yourusername/gtk.git
|
||||
$ cd gtk
|
||||
```
|
||||
|
||||
**Note**: if you plan to push changes to back to the main repository and
|
||||
have a GNOME account, you can skip the fork, and use the following instead:
|
||||
|
||||
```sh
|
||||
$ git clone git@gitlab.gnome.org:GNOME/gtk.git
|
||||
$ cd gtk
|
||||
```
|
||||
|
||||
To compile the Git version of GTK on your system, you will need to
|
||||
configure your build using Meson:
|
||||
|
||||
```sh
|
||||
$ meson setup _builddir .
|
||||
$ meson compile -C _builddir
|
||||
$ meson _builddir .
|
||||
$ cd _builddir
|
||||
$ ninja
|
||||
```
|
||||
|
||||
Typically, you should work on your own branch:
|
||||
|
||||
```sh
|
||||
$ git switch -C your-branch
|
||||
$ git checkout -b your-branch
|
||||
```
|
||||
|
||||
Once you've finished working on the bug fix or feature, push the branch
|
||||
to the Git repository and open a new merge request, to let the GTK
|
||||
maintainers review your contribution.
|
||||
|
||||
**Important**: Do **not** attach a diff or a patch file to a GitLab issue.
|
||||
Patches cannot be reviewed, and do not not go through the CI pipeline. If
|
||||
you wish to submit your changes to GTK, always use a merge request.
|
||||
|
||||
### Code reviews
|
||||
|
||||
Each contribution is reviewed by the core developers of the GTK project.
|
||||
@@ -259,4 +262,4 @@ people committing to GTK to follow a few rules:
|
||||
|
||||
If you have been contributing to GTK for a while and you don't have commit
|
||||
access to the repository, you may ask to obtain it following the [GNOME account
|
||||
process](https://handbook.gnome.org/infrastructure/developer-access.html).
|
||||
process](https://wiki.gnome.org/AccountsTeam/NewAccounts).
|
||||
|
755
NEWS
@@ -1,759 +1,6 @@
|
||||
Overview of Changes in 4.17.1, xx-xx-xxxx
|
||||
Overview of Changes in 4.14.2, xx-xx-xxxx
|
||||
=========================================
|
||||
|
||||
Overview of Changes in 4.17.0, 06-11-2024
|
||||
=========================================
|
||||
|
||||
* GtkScrolledWindow
|
||||
- Fix criticals in size allocation code
|
||||
|
||||
* GtkFileChooser
|
||||
- Fix a crash in the portal code
|
||||
|
||||
* GtkFontChoser
|
||||
- Make the dialog more shrinkable
|
||||
|
||||
* GtkPicture
|
||||
- Avoid unnecessary resizes
|
||||
|
||||
* GtkVideo
|
||||
- Make dmabufs work without GL
|
||||
|
||||
* GtkListBox:
|
||||
- Add a tab-behavior property to influence keynav
|
||||
|
||||
* GtkEmojiChooser:
|
||||
- Fix problems with insertion and selection
|
||||
|
||||
* GtkStringList:
|
||||
- Add gtk_string_list_find
|
||||
|
||||
* GtkApplication:
|
||||
- Respect GDK_DEBUG=no-portals
|
||||
- Set default window icon from app ID
|
||||
|
||||
* GtkTextView:
|
||||
- Vertical and horizontal positioning of the textview is now quantized
|
||||
to the nearest device pixel. This should improve the perceived smoothness
|
||||
of scrolling with fractional scaling and font hinting.
|
||||
- Incorrect re-use of cached styling was fixed
|
||||
- Fix some missing CSS invalidation
|
||||
- Handle charsets in clipboard datatypes
|
||||
|
||||
* Printing:
|
||||
- Avoid warnings for avahi errors
|
||||
- Fix a segfault in the print dialog setup code
|
||||
|
||||
* Accessibility:
|
||||
- Always realize non-widget accessibles, to help webkit
|
||||
- Fix list view selection implementation
|
||||
- Handle NULL values in more places
|
||||
|
||||
* Gstreamer:
|
||||
- Make dmabufs works without GL
|
||||
|
||||
* Gdk:
|
||||
- Add OKLAB and OKLCH color states
|
||||
- GL: Drop support for GLES 2 and GL < 3.3
|
||||
- GL: Use the ngl dmabuf downloader instead of the GL downloader
|
||||
- Vulkan: Drop the GDK_VULKAN_DEVICE env var. Use MESA_VK_DEVICE_SELECT instead
|
||||
- Vulkan: Use the swapchain maintenance extension to release swap images
|
||||
- Forbid opening displays before gtk_init()
|
||||
|
||||
* Gsk:
|
||||
- Many improvements to the dmabuf downloaders
|
||||
- ngl: Avoid glBufferSubData for globals, speeding up llvmpipe
|
||||
- Renderer selection will no longer consider the GL renderer
|
||||
- Allow Vulkan software rendering as fallback
|
||||
- Support gradient interpolation in different color states
|
||||
|
||||
* Wayland:
|
||||
- Improve settings portal handling
|
||||
- Improve fallback for cursor themes
|
||||
- Make cursor theme changes apply immediately
|
||||
- Use a viewporter for cursor image scaling
|
||||
- Improve cursor size handling
|
||||
- Use the system bell protocol if available
|
||||
- Fix possible deadlock with high-priority sources triggering roundtrips
|
||||
|
||||
* Windows:
|
||||
- Improve the backend code
|
||||
- Fix some problems with WGL on NVidia
|
||||
- Many testsuite fixes for Windows compatibility
|
||||
- Make all pixbuf loaders builtin in the gdk-pixbuf subproject
|
||||
- Add GDK_DISABLE=aerosnap to disable aerosnap
|
||||
- Improve clipboard handling
|
||||
- Fix behavior or gdk_display_open() on Windows
|
||||
- Numerous papercut fixes
|
||||
- Require Windows 10
|
||||
|
||||
* Macos:
|
||||
- Fix crashes when dragging libadwaita TabView tabs
|
||||
- Require macOS 10.15
|
||||
|
||||
* Tools and demos
|
||||
- gtk4-demo: Make demos standalone
|
||||
- gtk4-demo: Drop GL shader demos
|
||||
- gtk4-demo: Improve scrolling benchmarks
|
||||
- gtk4-builder-tool: Improve separator handling
|
||||
- gtk4-image-tool: Better color state support
|
||||
|
||||
* Build:
|
||||
- Don't set GSK_RENDERER in our flatpaks
|
||||
- Require meson 1.2
|
||||
|
||||
* Translation updates
|
||||
Belarusian
|
||||
Brazilian Portuguese
|
||||
British English
|
||||
Galician
|
||||
Lithuanian
|
||||
Romanian
|
||||
Slovenian
|
||||
Swedish
|
||||
|
||||
|
||||
Overview of Changes in 4.16.2, 09-25-2024
|
||||
=========================================
|
||||
|
||||
* GtkLabel:
|
||||
- Fix centered text in RTL
|
||||
|
||||
* Gsk:
|
||||
- Speed up some Vulkan operations
|
||||
- Improve startup speed by avoiding initialization
|
||||
of GL and Vulkan in most cases
|
||||
- Reduce critials at startup to warnings
|
||||
- Fix a crash on startup with some Vulkan drivers
|
||||
- Fix a big texture leak in NGL
|
||||
|
||||
* Gdk:
|
||||
- Speed up memory format conversions
|
||||
|
||||
* Wayland:
|
||||
- Be more careful with mimetypes during DND or copy-paste
|
||||
|
||||
* Tools:
|
||||
- builder-tool: Improve conversion of boxes
|
||||
|
||||
* Translation updates:
|
||||
Brazilian Portuguese
|
||||
Bulgarian
|
||||
Catalan
|
||||
Chinese (China)
|
||||
Georgian
|
||||
German
|
||||
Hebrew
|
||||
Indonesian
|
||||
Persian
|
||||
Polish
|
||||
Portuguese
|
||||
Slovenian
|
||||
Spanish
|
||||
Turkish
|
||||
Ukrainian
|
||||
|
||||
|
||||
Overview of Changes in 4.16.1, 09-16-2024
|
||||
=========================================
|
||||
|
||||
* GtkFileChooser:
|
||||
- Plug a memory leak
|
||||
|
||||
* GtkCalendar:
|
||||
- Avoid ending up with invalid dates
|
||||
|
||||
* Printing:
|
||||
- Fix initial printer selection in the print dialog
|
||||
|
||||
* Gsk:
|
||||
- Fix shadows for opaque textures
|
||||
- Fix a crash in a corner case
|
||||
|
||||
* Css:
|
||||
- Make relative paths work again in theme files
|
||||
|
||||
* Accessibility:
|
||||
- Fix detection of the Flatpak portal
|
||||
|
||||
* MacOS:
|
||||
- Fix keyboard input in popovers
|
||||
- Keep DND icons above regular windows
|
||||
- Ignore events from DND icons
|
||||
|
||||
* Translation updates
|
||||
Basque
|
||||
British English
|
||||
Bulgarian
|
||||
Czech
|
||||
Danish
|
||||
Georgian
|
||||
Hungarian
|
||||
Lithuanian
|
||||
Portuguese
|
||||
Spanish
|
||||
Swedish
|
||||
|
||||
|
||||
Overview of Changes in 4.16.0, 09-06-2024
|
||||
=========================================
|
||||
|
||||
Note: This release changes the default GSK renderer to be Vulkan,
|
||||
on Wayland. Other platforms still use ngl. The intent of this change
|
||||
is to use the best available platform APIs. You can still override
|
||||
the renderer choice using the GSK_RENDERER environment variable.
|
||||
|
||||
We believe that most of the problems reported with the new renderers
|
||||
during the 4.13 and 4.15 development cycles have been addressed by now.
|
||||
|
||||
But the new renderers and dmabuf support are using graphics drivers
|
||||
in different ways than the old gl renderer, and trigger new driver bugs.
|
||||
Therefore, it is recommended to use the latest mesa release (24.2)
|
||||
with the new renderers.
|
||||
|
||||
* GtkScale:
|
||||
- Fix positioning of scale values
|
||||
|
||||
* GtkEmojiChooser:
|
||||
- Make Control-clicks work for the recent section
|
||||
|
||||
* GtkPopover:
|
||||
- Make sure focus lands on the right widget when cascading
|
||||
|
||||
* GtkSpinButton:
|
||||
- Disable Emoji input for numeric spin buttons
|
||||
|
||||
* GtkSingleSelection:
|
||||
- Implement unselect_all
|
||||
|
||||
* Accssibility:
|
||||
- Fix roles for radio buttons
|
||||
- Check if ATs are listening before exporting trees
|
||||
- Add a check for sandboxed accessibility bus
|
||||
- Fix handling of the error message relation
|
||||
- Turn criticals into debug messages
|
||||
- Set expanded states properly in menus
|
||||
|
||||
* CSS:
|
||||
- Fix a few issues on bigendian systems
|
||||
- Avoid a crash with relative colors
|
||||
|
||||
* GSK:
|
||||
- Use the right GL context when exporting textures
|
||||
- Don't let colors influence depth decisions
|
||||
- Allow uploading of mipmap levels when tiling textures
|
||||
|
||||
* GDK:
|
||||
- Update keysyms from libX11 1.8.10
|
||||
- Implement cpu-side mipmapping
|
||||
- Use a thread pool for color conversions and mipmapping
|
||||
|
||||
* Vulkan:
|
||||
- Fix drag surface offsets
|
||||
|
||||
* Wayland:
|
||||
- Fix a crash
|
||||
- Associate EGL windows with context later
|
||||
|
||||
* X11:
|
||||
- Fix initial EGL context creation
|
||||
- Fix a problem with GL context creation
|
||||
|
||||
* Broadway:
|
||||
- Implement compute_size and request_layout
|
||||
|
||||
* MacOS:
|
||||
- Set transparent backgroiund for toplevel windows
|
||||
|
||||
* Windows:
|
||||
- Improve debug output
|
||||
- Detect Mesas d3d12 driver and request GDI compat
|
||||
|
||||
* Demos:
|
||||
- Set window icons in demos
|
||||
- Add a 64k x 64k image to the image scaling demo
|
||||
|
||||
* Translation updates
|
||||
Belarusian
|
||||
Brazilian Portuguese
|
||||
Catalan
|
||||
Czech
|
||||
Galician
|
||||
German
|
||||
Hebrew
|
||||
Indonesian
|
||||
Korean
|
||||
Lithuanian
|
||||
Persian
|
||||
Polish
|
||||
Portuguese
|
||||
Slovenian
|
||||
Spanish
|
||||
Turkish
|
||||
Ukrainian
|
||||
|
||||
|
||||
Overview of Changes in 4.15.6, 08-26-2024
|
||||
=========================================
|
||||
|
||||
* GtkCheckButton:
|
||||
- Add a grouped style class for radio buttons
|
||||
|
||||
* GtkScale:
|
||||
- Fix alignment and positioning problems
|
||||
|
||||
* Css:
|
||||
- Fix crashes in the variable support
|
||||
|
||||
* Gsk:
|
||||
- Make graphics offloading work better with kwin
|
||||
- Make colorstate transfer functions more robust
|
||||
- GC dead textures more agressively
|
||||
- Only use a single render pass per frame
|
||||
|
||||
* GL:
|
||||
- Round damage rectangles properly
|
||||
- Use the shared context when creating textures
|
||||
- Fix a file descriptor leak in dmabuf export
|
||||
|
||||
* Vulkan:
|
||||
- Round damage rectangles properly
|
||||
|
||||
* Wayland:
|
||||
- Work with the kwin implementation of xx-color-management-v4
|
||||
|
||||
* Windows:
|
||||
- Make gtk_show_uri use SHOpenWithDialog()
|
||||
- Enable incremental rendering with WGL
|
||||
|
||||
* Macos:
|
||||
- Open context menus on Ctrl-left click
|
||||
|
||||
* Debugging:
|
||||
- Show color state information in the inspector
|
||||
- Collect input event traces in the recorder
|
||||
- Add shortcuts for toggling recording: Super-r
|
||||
and for screenshots: Super-c
|
||||
- Split the GDK_DEBUG env var into GDK_DEBUG and GDK_DISABLE
|
||||
- Add GDK_DISABLE=color-mgmt and GDK_DISABLE=offload
|
||||
|
||||
* Tools:
|
||||
- Add a 'Paste as node' action in gtk4-node-editor
|
||||
|
||||
* Translations updates
|
||||
Basque
|
||||
Belarusian
|
||||
Brazilian Portuguese
|
||||
Chinese (China)
|
||||
Georgian
|
||||
Hebrew
|
||||
Hindi
|
||||
Russian
|
||||
Slovenian
|
||||
Turkish
|
||||
Ukrainian
|
||||
|
||||
|
||||
Overview of Changes in 4.15.5, 11-08-2024
|
||||
=========================================
|
||||
|
||||
* GtkTextView:
|
||||
- ADd GtkTextBufferCommitNotify
|
||||
|
||||
* CSS:
|
||||
- Propagate color state information to GSK for many features:
|
||||
colors, borders, shadows, text
|
||||
|
||||
* Gdk:
|
||||
- Fix an fd leak in the Vulkan code
|
||||
- Fix a leak of EGLSurfaces and DMA buffers
|
||||
- Set the opaque region of surfaces automatically based on their content
|
||||
|
||||
* Gsk:
|
||||
- Fix Emoji rendering in Vulkan
|
||||
- Rework color handling to take color states into account
|
||||
- Implement more powerful occlusion culling
|
||||
- Minimize our use of renderpasses
|
||||
|
||||
* Macos:
|
||||
- Fix window transparency
|
||||
|
||||
* Debugging:
|
||||
- The inspector shows details about color states
|
||||
|
||||
* Deprecations:
|
||||
- gdk_draw_context_begin/end_frame
|
||||
- gdk_surface_set_opaque_region
|
||||
|
||||
* Build:
|
||||
- Require gstreamer 1.24
|
||||
|
||||
* Translation updates
|
||||
Romanian
|
||||
|
||||
|
||||
Overview of Changes in 4.15.4, 30-07-2024
|
||||
=========================================
|
||||
|
||||
* GtkPopover:
|
||||
- Fix size allocation with wrapping labels
|
||||
|
||||
* GtkColumnView:
|
||||
- Check column visibility when measuring
|
||||
|
||||
* CSS:
|
||||
- Fix fallout from recent changes
|
||||
- Make implementation of currentcolor inheritance match browsers
|
||||
|
||||
* Gdk:
|
||||
- Introduce GdkColorState for encoding color space information
|
||||
Currently, we support srgb, srgb-linear, rec2100-pq and rec2100-linear
|
||||
- Add color states to GdkTexture, as well as to the texture builder
|
||||
and downloader objects, and convert as necessary
|
||||
- Add GdkMemoryTextureBuilder
|
||||
- Attach color states when loading or saving textures
|
||||
- Add GdkCicpParams to create color state objects for cicp tuples
|
||||
- Drop GDK_DEBUG=vulkan-validate
|
||||
Use VK_INSTEANCE_LAYERS=VK_LAYER_KHRONOS_validation instead
|
||||
|
||||
* Gsk:
|
||||
- Improve caching of glyphs and textures
|
||||
- Remove the uber shader
|
||||
- Numerous bug fixes
|
||||
- Fix corner cases in offload handling
|
||||
- Implement occlusion culling for opaque content
|
||||
- Allow offloading (some) transformed textures
|
||||
- Take colorstate into account when compositing
|
||||
- Add GDK_DEBUG=linear to opt into linear compositing
|
||||
- Implement tiling for large textures
|
||||
- Stop using descriptors and go back to simpler texture
|
||||
management that should work better with older GL
|
||||
- Use correct shader clip mode for glyphs
|
||||
- Improve shadow rendering
|
||||
|
||||
* Media:
|
||||
- Attach color states to textures obtained from gstreamer
|
||||
|
||||
* Wayland:
|
||||
- Allow offloading GL textures via dmabuf export
|
||||
- Suppot the xx-color-management-v4 protocol
|
||||
|
||||
* Deprecations:
|
||||
- GskGLShader and the render node
|
||||
|
||||
* Tools:
|
||||
- Improve the rendernode tool extract command
|
||||
- Add an image tool that is about manipulating textures
|
||||
|
||||
* Build:
|
||||
- GTK now requires a C11 compiler
|
||||
|
||||
* Translation updates
|
||||
Georgian
|
||||
Hebrew
|
||||
Hindi
|
||||
Occitan
|
||||
Slovenian
|
||||
|
||||
|
||||
Overview of Changes in 4.15.3, 29-06-2024
|
||||
=========================================
|
||||
|
||||
* Accessibility:
|
||||
- Only emit notifications when cursor positions change in GtkText
|
||||
- Fix handling of help text properties
|
||||
|
||||
* CSS:
|
||||
- Fix some crashes introduced in recent currentcolor changes
|
||||
|
||||
* DND:
|
||||
- Avoid a critical
|
||||
|
||||
* Documentation:
|
||||
- Fix many oversights and missing docs
|
||||
|
||||
* maxOS:
|
||||
- Add native keyboard shortcuts
|
||||
|
||||
|
||||
Overview of Changes in 4.15.2, 28-06-2024
|
||||
=========================================
|
||||
|
||||
* GtkFileChooserWidget:
|
||||
- Plug some memory leaks
|
||||
- Make Ctrl-Shift-N create a new folder
|
||||
|
||||
* GtkPopover:
|
||||
- Handle resizing and position changes better
|
||||
|
||||
* CSS:
|
||||
- Support color(), oklab(), etc (https://www.w3.org/TR/css-color-4/)
|
||||
- Support color-mix() (https://www.w3.org/TR/css-color-5/)
|
||||
- Support relative colors (https://www.w3.org/TR/css-color-5/)
|
||||
- Support more colorspaces in color()
|
||||
- Allow percentages for opacity
|
||||
- Handle currentcolor more correctly
|
||||
|
||||
* Accessibility:
|
||||
- Avoid markup when reading labels
|
||||
|
||||
* GSK:
|
||||
- Subset fonts when serializing node trees
|
||||
- Make ngl export render_texture results as dmabufs
|
||||
|
||||
* Wayland:
|
||||
- Use xdg-dialog protocol for attached dialogs
|
||||
|
||||
* Windows:
|
||||
- Build with UNICODE
|
||||
|
||||
* macOS:
|
||||
- Implement fullscreen-on-monitor
|
||||
|
||||
* Documentation:
|
||||
- Widget shortcuts and actions are now described in the docs
|
||||
|
||||
* Debugging:
|
||||
- Add GTK_DEBUG=css for warning about deprecated css syntax
|
||||
|
||||
* Tools:
|
||||
- rendernode-tool: Add an extract command for data urls
|
||||
|
||||
* Deprecations:
|
||||
- CSS Color functions shade(), lighter(), darker(), alpha(), mix()
|
||||
|
||||
* Translation updates:
|
||||
Czech
|
||||
Hebrew
|
||||
Serbian
|
||||
|
||||
|
||||
Overview of Changes in 4.15.1, 21-05-2024
|
||||
=========================================
|
||||
|
||||
* GtkGraphicsOffload:
|
||||
- Don't crash without a child
|
||||
|
||||
* GtkSpinner:
|
||||
- Don't animate when unmapped
|
||||
|
||||
* CSS:
|
||||
- Support the :root selector
|
||||
- Support variables and custom properties (https://www.w3.org/TR/css-variables-1/)
|
||||
- Implement math functions (https://www.w3.org/TR/css-values-4/)
|
||||
- Support modern syntax and calc in rgb() and hsl()
|
||||
|
||||
* Icontheme:
|
||||
- Make symbolic svg loading more efficient
|
||||
- Handle color-free symbolics more efficiently
|
||||
|
||||
* Accessibility:
|
||||
- Make the gtk-demo sidebar search more accessible
|
||||
- Stop emitting focus events
|
||||
- Realize child contexts when necessary
|
||||
|
||||
* GDK:
|
||||
- Support XDG_ACTIVATION_TOKEN
|
||||
- dmabuf: Be more defensive when importing unknown formats to GL
|
||||
- dmabuf: Use narrow range for YUV
|
||||
- vulkan: Recreate swapchains when necessary or beneficial
|
||||
|
||||
* GSK:
|
||||
- Improve logging for GDK_DEBUG=offload
|
||||
- Improve logging for GSK_DEBUG=renderer
|
||||
- gpu: Warn about inefficient texture import
|
||||
- gpu: Handle tiny offscreens correctly
|
||||
- vulkan: Add profiler marks in various places
|
||||
- vulkan: Fix a problem with imported dmabufs showing up black
|
||||
- cairo: Speed up mask nodes, since we use them for symbolic icons
|
||||
|
||||
* Wayland:
|
||||
- Use wl_compositor version 6
|
||||
|
||||
* X11:
|
||||
- Implement a missing method
|
||||
|
||||
* Build:
|
||||
- Fix many ubsan warnings
|
||||
|
||||
* Debugging:
|
||||
- Show more texture details in the recorder
|
||||
- Use GTK_DEBUG=css to see CSS deprecations
|
||||
|
||||
* macOS:
|
||||
- Fix problems with events handed back to the OS
|
||||
- Respect GDK_DEBUG=default-settings
|
||||
- Allow applictions to handle Dock > Quit
|
||||
|
||||
* Deprecations:
|
||||
- Use of @name colors in CSS
|
||||
|
||||
* Translation updates:
|
||||
Catalan
|
||||
Georgian
|
||||
Hungarian
|
||||
Korean
|
||||
Portuguese
|
||||
Turkish
|
||||
|
||||
|
||||
Overview of Changes in 4.15.0, 21-04-2024
|
||||
=========================================
|
||||
|
||||
This release changes the default GSK renderer to be Vulkan, on
|
||||
Wayland. Other platforms still use ngl.
|
||||
|
||||
The intent of this change is to get wider testing and verify that
|
||||
Vulkan drivers are good enough for us to rely on. If significant
|
||||
problems show up, we will revert this change for 4.16.
|
||||
|
||||
You can still override the renderer choice using the GSK_RENDERER
|
||||
environment variable.
|
||||
|
||||
---
|
||||
|
||||
This release also changes font rendering settings by introducing
|
||||
a new high-level gtk-font-rendering settings which gives GTK more
|
||||
freedom to decide on font rendering.
|
||||
|
||||
You can still use the low-level font-related settings by changing
|
||||
the new property to 'manual'.
|
||||
|
||||
---
|
||||
|
||||
* GtkColumnView:
|
||||
- Fix infinite loops in dispose
|
||||
- Fix problems with weak ref cycles in GtkExpression
|
||||
|
||||
* GtkListView:
|
||||
* GtkShortcutManager:
|
||||
- Track the propagation phase of added controllers
|
||||
|
||||
* GtkGLArea:
|
||||
- Produce dmabuf textures, so graphics offload is possible
|
||||
|
||||
* GtkTextView:
|
||||
- Support text shadows
|
||||
|
||||
* GtkGraphicsOffload:
|
||||
- Add a black-background property
|
||||
|
||||
* Settings:
|
||||
- Add a new gtk-font-rendering setting
|
||||
|
||||
* Accessibility:
|
||||
- Add support for GetRangeExtents to GtkAccessibleText
|
||||
- Add support for GetOffsetAtPoint to GtkAccessibleText
|
||||
- Implement GtkAccessibleRange for scrollbars
|
||||
|
||||
* GDK:
|
||||
- Add a callback-based cursor API
|
||||
|
||||
* GSK:
|
||||
- Use the Vulkan renderer by default
|
||||
- Avoid an infinite recursion with offscreens in some cases
|
||||
- Optimize graphics offload to make it more likely that compositors
|
||||
can use direct scanout
|
||||
|
||||
* X11:
|
||||
- Fix some confusing debug messages
|
||||
- Drop a no-longer-relevant optimization that was interfering with
|
||||
getting the current window manager capabilities
|
||||
|
||||
* macOS:
|
||||
- Implement the color picker for macOS 10.15+
|
||||
|
||||
* Debugging:
|
||||
- Snow monitor resolution in the inspector
|
||||
|
||||
* Demos:
|
||||
- Use graphics offload in the shadertoy demo
|
||||
- Show more reliable fps numbers in the fishbowl demo
|
||||
|
||||
* Tools:
|
||||
- Support generating pdf in gtk4-rendernode-tool
|
||||
|
||||
* Build:
|
||||
- Require pango 1.52
|
||||
- Require cairo 1.18
|
||||
- Add a missing dependency that was causing build failures
|
||||
- Drop deprecated build options:
|
||||
gtk_doc -> documentation
|
||||
update_screenshots -> screenshots
|
||||
demo-profile -> profile
|
||||
demos -> build-demos
|
||||
|
||||
* Deprecations:
|
||||
- gdk_widget_set/get_font_options
|
||||
- gdk_wayland/x11_display_set_cursor_theme
|
||||
|
||||
* Translation updates:
|
||||
Basque
|
||||
Brazilian Portuguese
|
||||
British English
|
||||
Chinese (China)
|
||||
Hebrew
|
||||
Kabyle
|
||||
Persian
|
||||
Polish
|
||||
Russian
|
||||
Slovenian
|
||||
Swedish
|
||||
Turkish
|
||||
|
||||
|
||||
Overview of Changes in 4.14.2, 03-04-2024
|
||||
=========================================
|
||||
|
||||
* GtkScale:
|
||||
- Improve positioning of values in some cases
|
||||
|
||||
* Theme:
|
||||
- Make progress in entries visible
|
||||
|
||||
* Accessibility:
|
||||
- Fix text insertion handling
|
||||
|
||||
* GDK:
|
||||
- dnd: Use the default cursor durion motion
|
||||
- dnd: Use a better cursor for indicating the move action
|
||||
|
||||
* GSK:
|
||||
- gl: Handle offloads in offscreen context better
|
||||
- Fix text rendering problems with some fonts
|
||||
|
||||
* Wayland:
|
||||
- Tighten up some protocol version checks
|
||||
- Use the presentation time protocol
|
||||
- Fix a crash with subsurfaces
|
||||
- Improve settings portal handling
|
||||
|
||||
* macOS:
|
||||
- Fix up the app menu support
|
||||
|
||||
* Windows:
|
||||
- Fix problems with minimization
|
||||
- Fix build without fontconfig
|
||||
|
||||
* Debugging:
|
||||
- Add font settings in the inspector
|
||||
|
||||
* Demos:
|
||||
- Clean up the application demo
|
||||
- Update cursor images for the cursor demo
|
||||
|
||||
* Translation updates:
|
||||
Catalan
|
||||
Czech
|
||||
French
|
||||
Georgian
|
||||
Hebrew
|
||||
Persian
|
||||
Slovenian
|
||||
Turkish
|
||||
Ukrainian
|
||||
|
||||
|
||||
Overview of Changes in 4.14.1, 16-03-2024
|
||||
=========================================
|
||||
|
||||
|
21
README.md
@@ -39,21 +39,18 @@ Nightly documentation can be found at
|
||||
- Gsk: https://gnome.pages.gitlab.gnome.org/gtk/gsk4/
|
||||
|
||||
Nightly flatpaks of our demos can be installed from the
|
||||
[GNOME Nightly](https://nightly.gnome.org/) repository:
|
||||
|
||||
```sh
|
||||
flatpak remote-add --if-not-exists gnome-nightly https://nightly.gnome.org/gnome-nightly.flatpakrepo
|
||||
flatpak install gnome-nightly org.gtk.Demo4
|
||||
flatpak install gnome-nightly org.gtk.WidgetFactory4
|
||||
flatpak install gnome-nightly org.gtk.IconBrowser4
|
||||
```
|
||||
[GNOME Nightly](https://wiki.gnome.org/Apps/Nightly) repository:
|
||||
- `flatpak remote-add --if-not-exists gnome-nightly https://nightly.gnome.org/gnome-nightly.flatpakrepo`
|
||||
- `flatpak install gnome-nightly org.gtk.Demo4`
|
||||
- `flatpak install gnome-nightly org.gtk.WidgetFactory4`
|
||||
- `flatpak install gnome-nightly org.gtk.IconBrowser4`
|
||||
|
||||
Building and installing
|
||||
-----------------------
|
||||
|
||||
In order to build GTK you will need:
|
||||
|
||||
- [a C11 compatible compiler](https://gitlab.gnome.org/GNOME/glib/-/blob/main/docs/toolchain-requirements.md)
|
||||
- [a C99 compatible compiler](https://wiki.gnome.org/Projects/GLib/CompilerRequirements)
|
||||
- [Python 3](https://www.python.org/)
|
||||
- [Meson](http://mesonbuild.com)
|
||||
- [Ninja](https://ninja-build.org)
|
||||
@@ -128,7 +125,7 @@ version, for example `gtk-4-10`.
|
||||
How to report bugs
|
||||
------------------
|
||||
|
||||
Bugs should be reported on the [issues page](https://gitlab.gnome.org/GNOME/gtk/issues/).
|
||||
Bugs should be reported on the [issues page](https://gitlab.gnome.org/GNOME/gtk/issues/new).
|
||||
|
||||
In the bug report please include:
|
||||
|
||||
@@ -136,13 +133,9 @@ In the bug report please include:
|
||||
|
||||
- which version of GTK you are using
|
||||
- what operating system and version
|
||||
- what windowing system (X11 or Wayland)
|
||||
- what graphics driver / mesa version
|
||||
- for Linux, which distribution
|
||||
- if you built GTK, the list of options used to configure the build
|
||||
|
||||
Most of this information can be found in the GTK inspector.
|
||||
|
||||
And anything else you think is relevant.
|
||||
|
||||
* How to reproduce the bug.
|
||||
|
@@ -185,8 +185,9 @@
|
||||
"builddir" : true,
|
||||
"config-opts" : [
|
||||
"--libdir=/app/lib",
|
||||
"-Dvulkan=disabled",
|
||||
"-Dbuildtype=debugoptimized",
|
||||
"-Dprofile=devel"
|
||||
"-Ddemo-profile=devel"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
@@ -196,5 +197,10 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
"build-options" : {
|
||||
"env" : {
|
||||
"GSK_RENDERER" : "opengl"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -114,8 +114,9 @@
|
||||
"builddir" : true,
|
||||
"config-opts" : [
|
||||
"--libdir=/app/lib",
|
||||
"-Dvulkan=disabled",
|
||||
"-Dbuildtype=debugoptimized",
|
||||
"-Dprofile=devel"
|
||||
"-Ddemo-profile=devel"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
|
@@ -114,8 +114,9 @@
|
||||
"builddir" : true,
|
||||
"config-opts" : [
|
||||
"--libdir=/app/lib",
|
||||
"-Dvulkan=disabled",
|
||||
"-Dbuildtype=debugoptimized",
|
||||
"-Dprofile=devel"
|
||||
"-Ddemo-profile=devel"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
@@ -129,6 +130,8 @@
|
||||
"build-options" : {
|
||||
"env" : {
|
||||
"DBUS_SESSION_BUS_ADDRESS" : "''",
|
||||
"GSK_RENDERER" : "opengl",
|
||||
"GDK_DEBUG" : "vulkan-disable",
|
||||
"G_ENABLE_DEBUG" : "true"
|
||||
}
|
||||
}
|
||||
|
@@ -114,8 +114,9 @@
|
||||
"builddir" : true,
|
||||
"config-opts" : [
|
||||
"--libdir=/app/lib",
|
||||
"-Dvulkan=disabled",
|
||||
"-Dbuildtype=debugoptimized",
|
||||
"-Dprofile=devel"
|
||||
"-Ddemo-profile=devel"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
@@ -129,6 +130,8 @@
|
||||
"build-options" : {
|
||||
"env" : {
|
||||
"DBUS_SESSION_BUS_ADDRESS" : "''",
|
||||
"GSK_RENDERER" : "opengl",
|
||||
"GDK_DEBUG" : "vulkan-disable",
|
||||
"G_ENABLE_DEBUG" : "true"
|
||||
}
|
||||
}
|
||||
|
115
demos/constraint-editor/constraint-editor-application.c
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright © 2019 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Matthias Clasen
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "constraint-editor-application.h"
|
||||
#include "constraint-editor-window.h"
|
||||
|
||||
struct _ConstraintEditorApplication
|
||||
{
|
||||
GtkApplication parent_instance;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(ConstraintEditorApplication, constraint_editor_application, GTK_TYPE_APPLICATION);
|
||||
|
||||
static void
|
||||
constraint_editor_application_init (ConstraintEditorApplication *app)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
quit_activated (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer data)
|
||||
{
|
||||
g_application_quit (G_APPLICATION (data));
|
||||
}
|
||||
|
||||
static GActionEntry app_entries[] =
|
||||
{
|
||||
{ "quit", quit_activated, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static void
|
||||
constraint_editor_application_startup (GApplication *app)
|
||||
{
|
||||
const char *quit_accels[2] = { "<Ctrl>Q", NULL };
|
||||
const char *open_accels[2] = { "<Ctrl>O", NULL };
|
||||
GtkCssProvider *provider;
|
||||
|
||||
G_APPLICATION_CLASS (constraint_editor_application_parent_class)->startup (app);
|
||||
|
||||
g_action_map_add_action_entries (G_ACTION_MAP (app),
|
||||
app_entries, G_N_ELEMENTS (app_entries),
|
||||
app);
|
||||
gtk_application_set_accels_for_action (GTK_APPLICATION (app), "app.quit", quit_accels);
|
||||
gtk_application_set_accels_for_action (GTK_APPLICATION (app), "win.open", open_accels);
|
||||
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_resource (provider, "/org/gtk/gtk4/constraint-editor/constraint-editor.css");
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_application_activate (GApplication *app)
|
||||
{
|
||||
ConstraintEditorWindow *win;
|
||||
|
||||
win = constraint_editor_window_new (CONSTRAINT_EDITOR_APPLICATION (app));
|
||||
gtk_window_present (GTK_WINDOW (win));
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_application_open (GApplication *app,
|
||||
GFile **files,
|
||||
int n_files,
|
||||
const char *hint)
|
||||
{
|
||||
ConstraintEditorWindow *win;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_files; i++)
|
||||
{
|
||||
win = constraint_editor_window_new (CONSTRAINT_EDITOR_APPLICATION (app));
|
||||
constraint_editor_window_load (win, files[i]);
|
||||
gtk_window_present (GTK_WINDOW (win));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_application_class_init (ConstraintEditorApplicationClass *class)
|
||||
{
|
||||
GApplicationClass *application_class = G_APPLICATION_CLASS (class);
|
||||
|
||||
application_class->startup = constraint_editor_application_startup;
|
||||
application_class->activate = constraint_editor_application_activate;
|
||||
application_class->open = constraint_editor_application_open;
|
||||
}
|
||||
|
||||
ConstraintEditorApplication *
|
||||
constraint_editor_application_new (void)
|
||||
{
|
||||
return g_object_new (CONSTRAINT_EDITOR_APPLICATION_TYPE,
|
||||
"application-id", "org.gtk.gtk4.ConstraintEditor",
|
||||
"flags", G_APPLICATION_HANDLES_OPEN,
|
||||
NULL);
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Benjamin Otte
|
||||
* Copyright © 2019 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -14,19 +14,15 @@
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
* Authors: Matthias Clasen
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
#define CONSTRAINT_EDITOR_APPLICATION_TYPE (constraint_editor_application_get_type ())
|
||||
|
||||
typedef void (* GdkTaskFunc) (gpointer user_data);
|
||||
|
||||
void gdk_parallel_task_run (GdkTaskFunc task_func,
|
||||
gpointer task_data);
|
||||
|
||||
G_END_DECLS
|
||||
G_DECLARE_FINAL_TYPE (ConstraintEditorApplication, constraint_editor_application, CONSTRAINT, EDITOR_APPLICATION, GtkApplication)
|
||||
|
||||
ConstraintEditorApplication *constraint_editor_application_new (void);
|
652
demos/constraint-editor/constraint-editor-window.c
Normal file
@@ -0,0 +1,652 @@
|
||||
/*
|
||||
* Copyright © 2019 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Matthias Clasen
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "constraint-editor-window.h"
|
||||
#include "constraint-view.h"
|
||||
#include "constraint-editor.h"
|
||||
#include "guide-editor.h"
|
||||
|
||||
struct _ConstraintEditorWindow
|
||||
{
|
||||
GtkApplicationWindow parent_instance;
|
||||
|
||||
GtkWidget *paned;
|
||||
GtkWidget *view;
|
||||
GtkWidget *list;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(ConstraintEditorWindow, constraint_editor_window, GTK_TYPE_APPLICATION_WINDOW);
|
||||
|
||||
static GtkConstraintTarget *
|
||||
find_target (GListModel *model,
|
||||
GtkConstraintTarget *orig)
|
||||
{
|
||||
const char *name;
|
||||
const char *model_name;
|
||||
gpointer item;
|
||||
int i;
|
||||
|
||||
if (orig == NULL)
|
||||
return NULL;
|
||||
|
||||
if (GTK_IS_LABEL (orig))
|
||||
name = gtk_label_get_label (GTK_LABEL (orig));
|
||||
else if (GTK_IS_CONSTRAINT_GUIDE (orig))
|
||||
name = gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (orig));
|
||||
else
|
||||
{
|
||||
g_warning ("Don't know how to handle %s targets", G_OBJECT_TYPE_NAME (orig));
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < g_list_model_get_n_items (model); i++)
|
||||
{
|
||||
item = g_list_model_get_item (model, i);
|
||||
g_object_unref (item);
|
||||
if (GTK_IS_WIDGET (item))
|
||||
model_name = gtk_widget_get_name (GTK_WIDGET (item));
|
||||
else
|
||||
model_name = gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (item));
|
||||
|
||||
if (strcmp (name, model_name) == 0)
|
||||
return GTK_CONSTRAINT_TARGET (item);
|
||||
}
|
||||
g_warning ("Failed to find target '%s'", name);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
constraint_editor_window_load (ConstraintEditorWindow *self,
|
||||
GFile *file)
|
||||
{
|
||||
char *path;
|
||||
GtkBuilder *builder;
|
||||
GError *error = NULL;
|
||||
GtkWidget *view;
|
||||
GtkLayoutManager *layout;
|
||||
GtkWidget *child;
|
||||
const char *name;
|
||||
gpointer item;
|
||||
int i;
|
||||
GListModel *list;
|
||||
|
||||
path = g_file_get_path (file);
|
||||
|
||||
builder = gtk_builder_new ();
|
||||
if (!gtk_builder_add_from_file (builder, path, &error))
|
||||
{
|
||||
g_print ("Could not load %s: %s", path, error->message);
|
||||
g_error_free (error);
|
||||
g_free (path);
|
||||
g_object_unref (builder);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
view = GTK_WIDGET (gtk_builder_get_object (builder, "view"));
|
||||
if (!GTK_IS_BOX (view))
|
||||
{
|
||||
g_print ("Could not load %s: No GtkBox named 'view'", path);
|
||||
g_free (path);
|
||||
g_object_unref (builder);
|
||||
return FALSE;
|
||||
}
|
||||
layout = gtk_widget_get_layout_manager (view);
|
||||
if (!GTK_IS_CONSTRAINT_LAYOUT (layout))
|
||||
{
|
||||
g_print ("Could not load %s: Widget 'view' does not use GtkConstraintLayout", path);
|
||||
g_free (path);
|
||||
g_object_unref (builder);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (child = gtk_widget_get_first_child (view);
|
||||
child;
|
||||
child = gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
if (!GTK_IS_LABEL (child))
|
||||
{
|
||||
g_print ("Skipping non-GtkLabel child\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
name = gtk_label_get_label (GTK_LABEL (child));
|
||||
constraint_view_add_child (CONSTRAINT_VIEW (self->view), name);
|
||||
}
|
||||
|
||||
list = gtk_constraint_layout_observe_guides (GTK_CONSTRAINT_LAYOUT (layout));
|
||||
for (i = 0; i < g_list_model_get_n_items (list); i++)
|
||||
{
|
||||
GtkConstraintGuide *guide, *clone;
|
||||
int w, h;
|
||||
|
||||
item = g_list_model_get_item (list, i);
|
||||
guide = GTK_CONSTRAINT_GUIDE (item);
|
||||
|
||||
/* need to clone here, to attach to the right targets */
|
||||
clone = gtk_constraint_guide_new ();
|
||||
gtk_constraint_guide_set_name (clone, gtk_constraint_guide_get_name (guide));
|
||||
gtk_constraint_guide_set_strength (clone, gtk_constraint_guide_get_strength (guide));
|
||||
gtk_constraint_guide_get_min_size (guide, &w, &h);
|
||||
gtk_constraint_guide_set_min_size (clone, w, h);
|
||||
gtk_constraint_guide_get_nat_size (guide, &w, &h);
|
||||
gtk_constraint_guide_set_nat_size (clone, w, h);
|
||||
gtk_constraint_guide_get_max_size (guide, &w, &h);
|
||||
gtk_constraint_guide_set_max_size (clone, w, h);
|
||||
constraint_view_add_guide (CONSTRAINT_VIEW (self->view), clone);
|
||||
g_object_unref (guide);
|
||||
g_object_unref (clone);
|
||||
}
|
||||
g_object_unref (list);
|
||||
|
||||
list = gtk_constraint_layout_observe_constraints (GTK_CONSTRAINT_LAYOUT (layout));
|
||||
for (i = 0; i < g_list_model_get_n_items (list); i++)
|
||||
{
|
||||
GtkConstraint *constraint;
|
||||
GtkConstraint *clone;
|
||||
GtkConstraintTarget *target;
|
||||
GtkConstraintTarget *source;
|
||||
GtkConstraintAttribute source_attr;
|
||||
|
||||
item = g_list_model_get_item (list, i);
|
||||
constraint = GTK_CONSTRAINT (item);
|
||||
|
||||
target = gtk_constraint_get_target (constraint);
|
||||
source = gtk_constraint_get_source (constraint);
|
||||
source_attr = gtk_constraint_get_source_attribute (constraint);
|
||||
|
||||
if (source == NULL && source_attr == GTK_CONSTRAINT_ATTRIBUTE_NONE)
|
||||
clone = gtk_constraint_new_constant (find_target (constraint_view_get_model (CONSTRAINT_VIEW (self->view)), target),
|
||||
gtk_constraint_get_target_attribute (constraint),
|
||||
gtk_constraint_get_relation (constraint),
|
||||
gtk_constraint_get_constant (constraint),
|
||||
gtk_constraint_get_strength (constraint));
|
||||
else
|
||||
clone = gtk_constraint_new (find_target (constraint_view_get_model (CONSTRAINT_VIEW (self->view)), target),
|
||||
gtk_constraint_get_target_attribute (constraint),
|
||||
gtk_constraint_get_relation (constraint),
|
||||
find_target (constraint_view_get_model (CONSTRAINT_VIEW (self->view)), source),
|
||||
source_attr,
|
||||
gtk_constraint_get_multiplier (constraint),
|
||||
gtk_constraint_get_constant (constraint),
|
||||
gtk_constraint_get_strength (constraint));
|
||||
|
||||
constraint_view_add_constraint (CONSTRAINT_VIEW (self->view), clone);
|
||||
|
||||
g_object_unref (constraint);
|
||||
g_object_unref (clone);
|
||||
}
|
||||
g_object_unref (list);
|
||||
|
||||
g_free (path);
|
||||
g_object_unref (builder);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
open_response_cb (GObject *source,
|
||||
GAsyncResult *result,
|
||||
void *user_data)
|
||||
{
|
||||
GtkFileDialog *dialog = GTK_FILE_DIALOG (source);
|
||||
ConstraintEditorWindow *self = user_data;
|
||||
GFile *file;
|
||||
|
||||
file = gtk_file_dialog_open_finish (dialog, result, NULL);
|
||||
if (file)
|
||||
{
|
||||
constraint_editor_window_load (self, file);
|
||||
g_object_unref (file);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
open_cb (GtkWidget *button,
|
||||
ConstraintEditorWindow *self)
|
||||
{
|
||||
GtkFileDialog *dialog;
|
||||
GFile *cwd;
|
||||
|
||||
dialog = gtk_file_dialog_new ();
|
||||
gtk_file_dialog_set_title (dialog, "Open file");
|
||||
cwd = g_file_new_for_path (".");
|
||||
gtk_file_dialog_set_initial_folder (dialog, cwd);
|
||||
g_object_unref (cwd);
|
||||
gtk_file_dialog_open (dialog, GTK_WINDOW (self), NULL, open_response_cb, self);
|
||||
g_object_unref (dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
serialize_child (GString *str,
|
||||
int indent,
|
||||
GtkWidget *child)
|
||||
{
|
||||
const char *name;
|
||||
|
||||
name = gtk_widget_get_name (child);
|
||||
g_string_append_printf (str, "%*s<child>\n", indent, "");
|
||||
g_string_append_printf (str, "%*s <object class=\"GtkLabel\" id=\"%s\">\n", indent, "", name);
|
||||
g_string_append_printf (str, "%*s <property name=\"label\">%s</property>\n", indent, "", name);
|
||||
g_string_append_printf (str, "%*s </object>\n", indent, "");
|
||||
g_string_append_printf (str, "%*s</child>\n", indent, "");
|
||||
}
|
||||
|
||||
static char *
|
||||
serialize_model (GListModel *list)
|
||||
{
|
||||
GString *str = g_string_new ("");
|
||||
int i;
|
||||
|
||||
g_string_append (str, "<interface>\n");
|
||||
g_string_append (str, " <object class=\"GtkBox\" id=\"view\">\n");
|
||||
g_string_append (str, " <property name=\"layout-manager\">\n");
|
||||
g_string_append (str, " <object class=\"GtkConstraintLayout\">\n");
|
||||
g_string_append (str, " <constraints>\n");
|
||||
for (i = 0; i < g_list_model_get_n_items (list); i++)
|
||||
{
|
||||
gpointer item = g_list_model_get_item (list, i);
|
||||
g_object_unref (item);
|
||||
if (GTK_IS_CONSTRAINT (item))
|
||||
constraint_editor_serialize_constraint (str, 10, GTK_CONSTRAINT (item));
|
||||
else if (GTK_IS_CONSTRAINT_GUIDE (item))
|
||||
guide_editor_serialize_guide (str, 10, GTK_CONSTRAINT_GUIDE (item));
|
||||
}
|
||||
g_string_append (str, " </constraints>\n");
|
||||
g_string_append (str, " </object>\n");
|
||||
g_string_append (str, " </property>\n");
|
||||
for (i = 0; i < g_list_model_get_n_items (list); i++)
|
||||
{
|
||||
gpointer item = g_list_model_get_item (list, i);
|
||||
g_object_unref (item);
|
||||
if (GTK_IS_WIDGET (item))
|
||||
serialize_child (str, 4, GTK_WIDGET (item));
|
||||
}
|
||||
g_string_append (str, " </object>\n");
|
||||
g_string_append (str, "</interface>\n");
|
||||
|
||||
return g_string_free (str, FALSE);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
save_response_cb (GObject *source,
|
||||
GAsyncResult *result,
|
||||
void *user_data)
|
||||
{
|
||||
GtkFileDialog *dialog = GTK_FILE_DIALOG (source);
|
||||
ConstraintEditorWindow *self = user_data;
|
||||
GFile *file;
|
||||
|
||||
file = gtk_file_dialog_save_finish (dialog, result, NULL);
|
||||
if (file)
|
||||
{
|
||||
GListModel *model;
|
||||
char *text;
|
||||
GError *error = NULL;
|
||||
|
||||
model = constraint_view_get_model (CONSTRAINT_VIEW (self->view));
|
||||
text = serialize_model (model);
|
||||
g_file_replace_contents (file, text, strlen (text),
|
||||
NULL, FALSE,
|
||||
G_FILE_CREATE_NONE,
|
||||
NULL,
|
||||
NULL,
|
||||
&error);
|
||||
if (error != NULL)
|
||||
{
|
||||
GtkAlertDialog *alert;
|
||||
|
||||
alert = gtk_alert_dialog_new ("Saving failed");
|
||||
gtk_alert_dialog_set_detail (alert, error->message);
|
||||
gtk_alert_dialog_show (alert,
|
||||
GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self))));
|
||||
g_object_unref (alert);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_free (text);
|
||||
g_object_unref (file);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
save_cb (GtkWidget *button,
|
||||
ConstraintEditorWindow *self)
|
||||
{
|
||||
GtkFileDialog *dialog;
|
||||
GFile *cwd;
|
||||
|
||||
dialog = gtk_file_dialog_new ();
|
||||
gtk_file_dialog_set_title (dialog, "Save constraints");
|
||||
cwd = g_file_new_for_path (".");
|
||||
gtk_file_dialog_set_initial_folder (dialog, cwd);
|
||||
g_object_unref (cwd);
|
||||
gtk_file_dialog_save (dialog,
|
||||
GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (button))),
|
||||
NULL,
|
||||
save_response_cb, self);
|
||||
g_object_unref (dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_window_dispose (GObject *object)
|
||||
{
|
||||
gtk_widget_dispose_template (GTK_WIDGET (object), CONSTRAINT_EDITOR_WINDOW_TYPE);
|
||||
|
||||
G_OBJECT_CLASS (constraint_editor_window_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static int child_counter;
|
||||
static int guide_counter;
|
||||
|
||||
static void
|
||||
add_child (ConstraintEditorWindow *win)
|
||||
{
|
||||
char *name;
|
||||
|
||||
child_counter++;
|
||||
name = g_strdup_printf ("Child %d", child_counter);
|
||||
constraint_view_add_child (CONSTRAINT_VIEW (win->view), name);
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
static void
|
||||
add_guide (ConstraintEditorWindow *win)
|
||||
{
|
||||
char *name;
|
||||
GtkConstraintGuide *guide;
|
||||
|
||||
guide_counter++;
|
||||
name = g_strdup_printf ("Guide %d", guide_counter);
|
||||
guide = gtk_constraint_guide_new ();
|
||||
gtk_constraint_guide_set_name (guide, name);
|
||||
g_free (name);
|
||||
|
||||
constraint_view_add_guide (CONSTRAINT_VIEW (win->view), guide);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_done (ConstraintEditor *editor,
|
||||
GtkConstraint *constraint,
|
||||
ConstraintEditorWindow *win)
|
||||
{
|
||||
GtkConstraint *old_constraint;
|
||||
|
||||
g_object_get (editor, "constraint", &old_constraint, NULL);
|
||||
|
||||
if (old_constraint)
|
||||
constraint_view_remove_constraint (CONSTRAINT_VIEW (win->view), old_constraint);
|
||||
|
||||
constraint_view_add_constraint (CONSTRAINT_VIEW (win->view), constraint);
|
||||
|
||||
g_clear_object (&old_constraint);
|
||||
|
||||
gtk_window_destroy (GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (editor), GTK_TYPE_WINDOW)));
|
||||
}
|
||||
|
||||
static void
|
||||
edit_constraint (ConstraintEditorWindow *win,
|
||||
GtkConstraint *constraint)
|
||||
{
|
||||
GtkWidget *window;
|
||||
ConstraintEditor *editor;
|
||||
GListModel *model;
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (win));
|
||||
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
|
||||
if (constraint)
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Edit Constraint");
|
||||
else
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Create Constraint");
|
||||
|
||||
model = constraint_view_get_model (CONSTRAINT_VIEW (win->view));
|
||||
|
||||
editor = constraint_editor_new (model, constraint);
|
||||
|
||||
gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (editor));
|
||||
|
||||
g_signal_connect (editor, "done", G_CALLBACK (constraint_editor_done), win);
|
||||
|
||||
gtk_window_present (GTK_WINDOW (window));
|
||||
}
|
||||
|
||||
static void
|
||||
add_constraint (ConstraintEditorWindow *win)
|
||||
{
|
||||
edit_constraint (win, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
guide_editor_done (GuideEditor *editor,
|
||||
GtkConstraintGuide *guide,
|
||||
ConstraintEditorWindow *win)
|
||||
{
|
||||
gtk_window_destroy (GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (editor), GTK_TYPE_WINDOW)));
|
||||
}
|
||||
|
||||
static void
|
||||
edit_guide (ConstraintEditorWindow *win,
|
||||
GtkConstraintGuide *guide)
|
||||
{
|
||||
GtkWidget *window;
|
||||
GuideEditor *editor;
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
|
||||
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (win));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Edit Guide");
|
||||
|
||||
editor = guide_editor_new (guide);
|
||||
gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (editor));
|
||||
|
||||
g_signal_connect (editor, "done", G_CALLBACK (guide_editor_done), win);
|
||||
gtk_window_present (GTK_WINDOW (window));
|
||||
}
|
||||
|
||||
static void
|
||||
row_activated (GtkListBox *list,
|
||||
GtkListBoxRow *row,
|
||||
ConstraintEditorWindow *win)
|
||||
{
|
||||
GObject *item;
|
||||
|
||||
item = G_OBJECT (g_object_get_data (G_OBJECT (row), "item"));
|
||||
|
||||
if (GTK_IS_CONSTRAINT (item))
|
||||
edit_constraint (win, GTK_CONSTRAINT (item));
|
||||
else if (GTK_IS_CONSTRAINT_GUIDE (item))
|
||||
edit_guide (win, GTK_CONSTRAINT_GUIDE (item));
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_window_class_init (ConstraintEditorWindowClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
|
||||
g_type_ensure (CONSTRAINT_VIEW_TYPE);
|
||||
|
||||
object_class->dispose = constraint_editor_window_dispose;
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class,
|
||||
"/org/gtk/gtk4/constraint-editor/constraint-editor-window.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditorWindow, paned);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditorWindow, view);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditorWindow, list);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, open_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, save_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, add_child);
|
||||
gtk_widget_class_bind_template_callback (widget_class, add_guide);
|
||||
gtk_widget_class_bind_template_callback (widget_class, add_constraint);
|
||||
gtk_widget_class_bind_template_callback (widget_class, row_activated);
|
||||
}
|
||||
|
||||
static void
|
||||
row_edit (GtkButton *button,
|
||||
ConstraintEditorWindow *win)
|
||||
{
|
||||
GtkWidget *row;
|
||||
GObject *item;
|
||||
|
||||
row = gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_LIST_BOX_ROW);
|
||||
item = (GObject *)g_object_get_data (G_OBJECT (row), "item");
|
||||
if (GTK_IS_CONSTRAINT (item))
|
||||
edit_constraint (win, GTK_CONSTRAINT (item));
|
||||
else if (GTK_IS_CONSTRAINT_GUIDE (item))
|
||||
edit_guide (win, GTK_CONSTRAINT_GUIDE (item));
|
||||
}
|
||||
|
||||
static void
|
||||
mark_constraints_invalid (ConstraintEditorWindow *win,
|
||||
gpointer removed)
|
||||
{
|
||||
GtkWidget *child;
|
||||
GObject *item;
|
||||
|
||||
for (child = gtk_widget_get_first_child (win->list);
|
||||
child;
|
||||
child = gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
item = (GObject *)g_object_get_data (G_OBJECT (child), "item");
|
||||
if (GTK_IS_CONSTRAINT (item))
|
||||
{
|
||||
GtkConstraint *constraint = GTK_CONSTRAINT (item);
|
||||
|
||||
if (gtk_constraint_get_target (constraint) == (GtkConstraintTarget *)removed ||
|
||||
gtk_constraint_get_source (constraint) == (GtkConstraintTarget *)removed)
|
||||
{
|
||||
GtkWidget *button;
|
||||
button = (GtkWidget *)g_object_get_data (G_OBJECT (child), "edit");
|
||||
gtk_button_set_icon_name (GTK_BUTTON (button), "dialog-warning-symbolic");
|
||||
gtk_widget_set_tooltip_text (button, "Constraint is invalid");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
row_delete (GtkButton *button,
|
||||
ConstraintEditorWindow *win)
|
||||
{
|
||||
GtkWidget *row;
|
||||
GObject *item;
|
||||
|
||||
row = gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_LIST_BOX_ROW);
|
||||
item = (GObject *)g_object_get_data (G_OBJECT (row), "item");
|
||||
if (GTK_IS_CONSTRAINT (item))
|
||||
constraint_view_remove_constraint (CONSTRAINT_VIEW (win->view),
|
||||
GTK_CONSTRAINT (item));
|
||||
else if (GTK_IS_CONSTRAINT_GUIDE (item))
|
||||
{
|
||||
mark_constraints_invalid (win, item);
|
||||
constraint_view_remove_guide (CONSTRAINT_VIEW (win->view),
|
||||
GTK_CONSTRAINT_GUIDE (item));
|
||||
}
|
||||
else if (GTK_IS_WIDGET (item))
|
||||
{
|
||||
mark_constraints_invalid (win, item);
|
||||
constraint_view_remove_child (CONSTRAINT_VIEW (win->view),
|
||||
GTK_WIDGET (item));
|
||||
}
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
create_widget_func (gpointer item,
|
||||
gpointer user_data)
|
||||
{
|
||||
ConstraintEditorWindow *win = user_data;
|
||||
const char *name;
|
||||
char *freeme = NULL;
|
||||
GtkWidget *row, *box, *label, *button;
|
||||
|
||||
if (GTK_IS_WIDGET (item))
|
||||
name = gtk_widget_get_name (GTK_WIDGET (item));
|
||||
else if (GTK_IS_CONSTRAINT_GUIDE (item))
|
||||
name = gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (item));
|
||||
else if (GTK_IS_CONSTRAINT (item))
|
||||
name = freeme = constraint_editor_constraint_to_string (GTK_CONSTRAINT (item));
|
||||
else
|
||||
name = "";
|
||||
|
||||
row = gtk_list_box_row_new ();
|
||||
g_object_set_data_full (G_OBJECT (row), "item", g_object_ref (item), g_object_unref);
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
label = gtk_label_new (name);
|
||||
if (GTK_IS_WIDGET (item) || GTK_IS_CONSTRAINT_GUIDE (item))
|
||||
g_object_bind_property (item, "name",
|
||||
label, "label",
|
||||
G_BINDING_DEFAULT);
|
||||
gtk_widget_set_margin_start (label, 10);
|
||||
gtk_widget_set_margin_end (label, 10);
|
||||
gtk_widget_set_margin_top (label, 10);
|
||||
gtk_widget_set_margin_bottom (label, 10);
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
|
||||
gtk_widget_set_hexpand (label, TRUE);
|
||||
gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), box);
|
||||
gtk_box_append (GTK_BOX (box), label);
|
||||
|
||||
if (GTK_IS_CONSTRAINT (item) || GTK_IS_CONSTRAINT_GUIDE (item))
|
||||
{
|
||||
button = gtk_button_new_from_icon_name ("document-edit-symbolic");
|
||||
gtk_button_set_has_frame (GTK_BUTTON (button), FALSE);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (row_edit), win);
|
||||
g_object_set_data (G_OBJECT (row), "edit", button);
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
|
||||
gtk_button_set_has_frame (GTK_BUTTON (button), FALSE);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (row_delete), win);
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
}
|
||||
else if (GTK_IS_WIDGET (item))
|
||||
{
|
||||
button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
|
||||
gtk_button_set_has_frame (GTK_BUTTON (button), FALSE);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (row_delete), win);
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
}
|
||||
|
||||
g_free (freeme);
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_window_init (ConstraintEditorWindow *self)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
|
||||
gtk_list_box_bind_model (GTK_LIST_BOX (self->list),
|
||||
constraint_view_get_model (CONSTRAINT_VIEW (self->view)),
|
||||
create_widget_func,
|
||||
self,
|
||||
NULL);
|
||||
}
|
||||
|
||||
ConstraintEditorWindow *
|
||||
constraint_editor_window_new (ConstraintEditorApplication *application)
|
||||
{
|
||||
return g_object_new (CONSTRAINT_EDITOR_WINDOW_TYPE,
|
||||
"application", application,
|
||||
NULL);
|
||||
}
|
34
demos/constraint-editor/constraint-editor-window.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright © 2019 Red Hat, Inc
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Matthias Clasen
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "constraint-editor-application.h"
|
||||
|
||||
|
||||
#define CONSTRAINT_EDITOR_WINDOW_TYPE (constraint_editor_window_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ConstraintEditorWindow, constraint_editor_window, CONSTRAINT, EDITOR_WINDOW, GtkApplicationWindow)
|
||||
|
||||
ConstraintEditorWindow * constraint_editor_window_new (ConstraintEditorApplication *application);
|
||||
|
||||
gboolean constraint_editor_window_load (ConstraintEditorWindow *self,
|
||||
GFile *file);
|
77
demos/constraint-editor/constraint-editor-window.ui
Normal file
@@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="ConstraintEditorWindow" parent="GtkApplicationWindow">
|
||||
<property name="title" translatable="yes">GTK Constraint Editor</property>
|
||||
<property name="default-width">1024</property>
|
||||
<property name="default-height">768</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<child type="start">
|
||||
<object class="GtkButton">
|
||||
<property name="icon-name">document-open-symbolic</property>
|
||||
<property name="tooltip-text">Open ui file</property>
|
||||
<signal name="clicked" handler="open_cb"/>
|
||||
</object>
|
||||
</child>
|
||||
<child type="start">
|
||||
<object class="GtkButton">
|
||||
<property name="icon-name">document-save-symbolic</property>
|
||||
<property name="tooltip-text">Save to ui file</property>
|
||||
<signal name="clicked" handler="save_cb"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkPaned" id="paned">
|
||||
<property name="orientation">horizontal</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">horizontal</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label">Add Child</property>
|
||||
<signal name="clicked" handler="add_child" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label">Add Guide</property>
|
||||
<signal name="clicked" handler="add_guide" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label">Add Constraint</property>
|
||||
<signal name="clicked" handler="add_constraint" swapped="yes"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="vscrollbar-policy">automatic</property>
|
||||
<property name="vexpand">1</property>
|
||||
<child>
|
||||
<object class="GtkListBox" id="list">
|
||||
<property name="show-separators">1</property>
|
||||
<property name="selection-mode">none</property>
|
||||
<signal name="row-activated" handler="row_activated"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="ConstraintView" id="view">
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
716
demos/constraint-editor/constraint-editor.c
Normal file
@@ -0,0 +1,716 @@
|
||||
/*
|
||||
* Copyright © 2019 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Matthias Clasen
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "constraint-editor.h"
|
||||
#include "constraint-view.h"
|
||||
|
||||
struct _ConstraintEditor
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GtkWidget *grid;
|
||||
GtkWidget *target;
|
||||
GtkWidget *target_attr;
|
||||
GtkWidget *relation;
|
||||
GtkWidget *source;
|
||||
GtkWidget *source_attr;
|
||||
GtkWidget *multiplier;
|
||||
GtkWidget *constant;
|
||||
GtkWidget *strength;
|
||||
GtkWidget *preview;
|
||||
GtkWidget *button;
|
||||
|
||||
GtkConstraint *constraint;
|
||||
GListModel *model;
|
||||
|
||||
gboolean constructed;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_MODEL = 1,
|
||||
PROP_CONSTRAINT,
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
static GParamSpec *pspecs[LAST_PROP];
|
||||
|
||||
enum {
|
||||
DONE,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
G_DEFINE_TYPE(ConstraintEditor, constraint_editor, GTK_TYPE_WIDGET);
|
||||
|
||||
static const char *
|
||||
get_target_name (GtkConstraintTarget *target)
|
||||
{
|
||||
if (target == NULL)
|
||||
return "Super";
|
||||
else if (GTK_IS_WIDGET (target))
|
||||
return gtk_widget_get_name (GTK_WIDGET (target));
|
||||
else if (GTK_IS_CONSTRAINT_GUIDE (target))
|
||||
return gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (target));
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_target_combo (GListModel *model,
|
||||
GtkWidget *combo,
|
||||
gboolean is_source)
|
||||
{
|
||||
GtkStringList *targets;
|
||||
int i;
|
||||
|
||||
targets = gtk_string_list_new (NULL);
|
||||
|
||||
gtk_string_list_append (targets, "Super");
|
||||
|
||||
if (model)
|
||||
{
|
||||
for (i = 0; i < g_list_model_get_n_items (model); i++)
|
||||
{
|
||||
GObject *item = g_list_model_get_object (model, i);
|
||||
|
||||
if (GTK_IS_CONSTRAINT (item))
|
||||
continue;
|
||||
|
||||
gtk_string_list_append (targets, get_target_name (GTK_CONSTRAINT_TARGET (item)));
|
||||
g_object_unref (item);
|
||||
}
|
||||
}
|
||||
|
||||
gtk_drop_down_set_model (GTK_DROP_DOWN (combo), G_LIST_MODEL (targets));
|
||||
g_object_unref (targets);
|
||||
}
|
||||
|
||||
static gpointer
|
||||
get_target (GListModel *model,
|
||||
const char *id)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (id == NULL)
|
||||
return NULL;
|
||||
|
||||
if (strcmp ("Super", id) == 0)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < g_list_model_get_n_items (model); i++)
|
||||
{
|
||||
GObject *item = g_list_model_get_object (model, i);
|
||||
g_object_unref (item);
|
||||
if (GTK_IS_CONSTRAINT (item))
|
||||
continue;
|
||||
else if (GTK_IS_WIDGET (item))
|
||||
{
|
||||
if (strcmp (id, gtk_widget_get_name (GTK_WIDGET (item))) == 0)
|
||||
return item;
|
||||
}
|
||||
else if (GTK_IS_CONSTRAINT_GUIDE (item))
|
||||
{
|
||||
if (strcmp (id, gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (item))) == 0)
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
select_target (GtkDropDown *combo,
|
||||
const char *target_name)
|
||||
{
|
||||
GListModel *model = gtk_drop_down_get_model (combo);
|
||||
|
||||
for (unsigned int i = 0; i < g_list_model_get_n_items (model); i++)
|
||||
{
|
||||
GtkStringObject *s = g_list_model_get_item (model, i);
|
||||
|
||||
g_object_unref (s);
|
||||
if (strcmp (target_name, gtk_string_object_get_string (s)) == 0)
|
||||
{
|
||||
gtk_drop_down_set_selected (GTK_DROP_DOWN (combo), i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static GtkConstraintAttribute
|
||||
get_attr (unsigned int id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case 0: return GTK_CONSTRAINT_ATTRIBUTE_NONE;
|
||||
case 1: return GTK_CONSTRAINT_ATTRIBUTE_LEFT;
|
||||
case 2: return GTK_CONSTRAINT_ATTRIBUTE_RIGHT;
|
||||
case 3: return GTK_CONSTRAINT_ATTRIBUTE_TOP;
|
||||
case 4: return GTK_CONSTRAINT_ATTRIBUTE_BOTTOM;
|
||||
case 5: return GTK_CONSTRAINT_ATTRIBUTE_START;
|
||||
case 6: return GTK_CONSTRAINT_ATTRIBUTE_END;
|
||||
case 7: return GTK_CONSTRAINT_ATTRIBUTE_WIDTH;
|
||||
case 8: return GTK_CONSTRAINT_ATTRIBUTE_HEIGHT;
|
||||
case 9: return GTK_CONSTRAINT_ATTRIBUTE_CENTER_X;
|
||||
case 10: return GTK_CONSTRAINT_ATTRIBUTE_CENTER_Y;
|
||||
case 11: return GTK_CONSTRAINT_ATTRIBUTE_BASELINE;
|
||||
default: g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
get_attr_id (GtkConstraintAttribute attr)
|
||||
{
|
||||
switch (attr)
|
||||
{
|
||||
case GTK_CONSTRAINT_ATTRIBUTE_NONE: return 0;
|
||||
case GTK_CONSTRAINT_ATTRIBUTE_LEFT: return 1;
|
||||
case GTK_CONSTRAINT_ATTRIBUTE_RIGHT: return 2;
|
||||
case GTK_CONSTRAINT_ATTRIBUTE_TOP: return 3;
|
||||
case GTK_CONSTRAINT_ATTRIBUTE_BOTTOM: return 4;
|
||||
case GTK_CONSTRAINT_ATTRIBUTE_START: return 5;
|
||||
case GTK_CONSTRAINT_ATTRIBUTE_END: return 6;
|
||||
case GTK_CONSTRAINT_ATTRIBUTE_WIDTH: return 7;
|
||||
case GTK_CONSTRAINT_ATTRIBUTE_HEIGHT: return 8;
|
||||
case GTK_CONSTRAINT_ATTRIBUTE_CENTER_X: return 9;
|
||||
case GTK_CONSTRAINT_ATTRIBUTE_CENTER_Y: return 10;
|
||||
case GTK_CONSTRAINT_ATTRIBUTE_BASELINE: return 11;
|
||||
default: g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_attr_nick (GtkConstraintAttribute attr)
|
||||
{
|
||||
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_ATTRIBUTE);
|
||||
GEnumValue *value = g_enum_get_value (class, attr);
|
||||
const char *nick = value->value_nick;
|
||||
g_type_class_unref (class);
|
||||
|
||||
return nick;
|
||||
}
|
||||
|
||||
static GtkConstraintRelation
|
||||
get_relation (unsigned int id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case 0: return GTK_CONSTRAINT_RELATION_LE;
|
||||
case 1: return GTK_CONSTRAINT_RELATION_EQ;
|
||||
case 2: return GTK_CONSTRAINT_RELATION_GE;
|
||||
default: g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
get_relation_id (GtkConstraintRelation relation)
|
||||
{
|
||||
switch (relation)
|
||||
{
|
||||
case GTK_CONSTRAINT_RELATION_LE: return 0;
|
||||
case GTK_CONSTRAINT_RELATION_EQ: return 1;
|
||||
case GTK_CONSTRAINT_RELATION_GE: return 2;
|
||||
default: g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_relation_nick (GtkConstraintRelation relation)
|
||||
{
|
||||
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_RELATION);
|
||||
GEnumValue *value = g_enum_get_value (class, relation);
|
||||
const char *nick = value->value_nick;
|
||||
g_type_class_unref (class);
|
||||
|
||||
return nick;
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_relation_display_name (GtkConstraintRelation relation)
|
||||
{
|
||||
switch (relation)
|
||||
{
|
||||
case GTK_CONSTRAINT_RELATION_LE:
|
||||
return "≤";
|
||||
case GTK_CONSTRAINT_RELATION_EQ:
|
||||
return "=";
|
||||
case GTK_CONSTRAINT_RELATION_GE:
|
||||
return "≥";
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
static GtkConstraintStrength
|
||||
get_strength (unsigned int id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case 0: return GTK_CONSTRAINT_STRENGTH_WEAK;
|
||||
case 1: return GTK_CONSTRAINT_STRENGTH_MEDIUM;
|
||||
case 2: return GTK_CONSTRAINT_STRENGTH_STRONG;
|
||||
case 3: return GTK_CONSTRAINT_STRENGTH_REQUIRED;
|
||||
default: g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
get_strength_id (GtkConstraintStrength strength)
|
||||
{
|
||||
switch (strength)
|
||||
{
|
||||
case GTK_CONSTRAINT_STRENGTH_WEAK: return 0;
|
||||
case GTK_CONSTRAINT_STRENGTH_MEDIUM: return 1;
|
||||
case GTK_CONSTRAINT_STRENGTH_STRONG: return 2;
|
||||
case GTK_CONSTRAINT_STRENGTH_REQUIRED: return 3;
|
||||
default: g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_strength_nick (GtkConstraintStrength strength)
|
||||
{
|
||||
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_STRENGTH);
|
||||
GEnumValue *value = g_enum_get_value (class, strength);
|
||||
const char *nick = value->value_nick;
|
||||
g_type_class_unref (class);
|
||||
|
||||
return nick;
|
||||
}
|
||||
|
||||
void
|
||||
constraint_editor_serialize_constraint (GString *str,
|
||||
int indent,
|
||||
GtkConstraint *constraint)
|
||||
{
|
||||
const char *target;
|
||||
const char *target_attr;
|
||||
const char *relation;
|
||||
const char *source;
|
||||
const char *source_attr;
|
||||
double multiplier;
|
||||
double constant;
|
||||
const char *strength;
|
||||
|
||||
target = get_target_name (gtk_constraint_get_target (constraint));
|
||||
target_attr = get_attr_nick (gtk_constraint_get_target_attribute (constraint));
|
||||
relation = get_relation_nick (gtk_constraint_get_relation (constraint));
|
||||
source = get_target_name (gtk_constraint_get_source (constraint));
|
||||
source_attr = get_attr_nick (gtk_constraint_get_source_attribute (constraint));
|
||||
multiplier = gtk_constraint_get_multiplier (constraint);
|
||||
constant = gtk_constraint_get_constant (constraint);
|
||||
strength = get_strength_nick (gtk_constraint_get_strength (constraint));
|
||||
|
||||
g_string_append_printf (str, "%*s<constraint target=\"%s\" target-attribute=\"%s\"\n", indent, "", target, target_attr);
|
||||
g_string_append_printf (str, "%*s relation=\"%s\"\n", indent, "", relation);
|
||||
if (strcmp (source_attr, "none") != 0)
|
||||
{
|
||||
g_string_append_printf (str, "%*s source=\"%s\" source-attribute=\"%s\"\n", indent, "", source, source_attr);
|
||||
g_string_append_printf (str, "%*s multiplier=\"%g\"\n", indent, "", multiplier);
|
||||
}
|
||||
g_string_append_printf (str, "%*s constant=\"%g\"\n", indent, "", constant);
|
||||
g_string_append_printf (str, "%*s strength=\"%s\" />\n", indent, "", strength);
|
||||
}
|
||||
|
||||
static void
|
||||
create_constraint (GtkButton *button,
|
||||
ConstraintEditor *editor)
|
||||
{
|
||||
gpointer obj;
|
||||
gpointer target;
|
||||
GtkConstraintAttribute target_attr;
|
||||
gpointer source;
|
||||
GtkConstraintAttribute source_attr;
|
||||
GtkConstraintRelation relation;
|
||||
double multiplier;
|
||||
double constant;
|
||||
int strength;
|
||||
GtkConstraint *constraint;
|
||||
|
||||
obj = gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->target));
|
||||
if (obj)
|
||||
target = get_target (editor->model, gtk_string_object_get_string (GTK_STRING_OBJECT (obj)));
|
||||
else
|
||||
target = NULL;
|
||||
target_attr = get_attr (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->target_attr)));
|
||||
|
||||
obj = gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->source));
|
||||
if (obj)
|
||||
source = get_target (editor->model, gtk_string_object_get_string (GTK_STRING_OBJECT (obj)));
|
||||
else
|
||||
source = NULL;
|
||||
source_attr = get_attr (gtk_drop_down_get_selected (GTK_DROP_DOWN(editor->source_attr)));
|
||||
|
||||
relation = get_relation (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->relation)));
|
||||
|
||||
multiplier = g_ascii_strtod (gtk_editable_get_text (GTK_EDITABLE (editor->multiplier)), NULL);
|
||||
|
||||
constant = g_ascii_strtod (gtk_editable_get_text (GTK_EDITABLE (editor->constant)), NULL);
|
||||
|
||||
strength = get_strength (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->strength)));
|
||||
|
||||
constraint = gtk_constraint_new (target, target_attr,
|
||||
relation,
|
||||
source, source_attr,
|
||||
multiplier,
|
||||
constant,
|
||||
strength);
|
||||
g_signal_emit (editor, signals[DONE], 0, constraint);
|
||||
g_object_unref (constraint);
|
||||
}
|
||||
|
||||
static void
|
||||
source_attr_changed (ConstraintEditor *editor)
|
||||
{
|
||||
if (get_attr (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->source_attr))) == GTK_CONSTRAINT_ATTRIBUTE_NONE)
|
||||
{
|
||||
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->source), GTK_INVALID_LIST_POSITION);
|
||||
gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), "");
|
||||
gtk_widget_set_sensitive (editor->source, FALSE);
|
||||
gtk_widget_set_sensitive (editor->multiplier, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_set_sensitive (editor->source, TRUE);
|
||||
gtk_widget_set_sensitive (editor->multiplier, TRUE);
|
||||
gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), "1");
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
constraint_editor_constraint_to_string (GtkConstraint *constraint)
|
||||
{
|
||||
GString *str;
|
||||
const char *name;
|
||||
const char *attr;
|
||||
const char *relation;
|
||||
double c, m;
|
||||
|
||||
str = g_string_new ("");
|
||||
|
||||
name = get_target_name (gtk_constraint_get_target (constraint));
|
||||
attr = get_attr_nick (gtk_constraint_get_target_attribute (constraint));
|
||||
relation = get_relation_display_name (gtk_constraint_get_relation (constraint));
|
||||
|
||||
if (name == NULL)
|
||||
name = "[ ]";
|
||||
|
||||
g_string_append_printf (str, "%s.%s %s ", name, attr, relation);
|
||||
|
||||
c = gtk_constraint_get_constant (constraint);
|
||||
|
||||
attr = get_attr_nick (gtk_constraint_get_source_attribute (constraint));
|
||||
if (strcmp (attr, "none") != 0)
|
||||
{
|
||||
name = get_target_name (gtk_constraint_get_source (constraint));
|
||||
m = gtk_constraint_get_multiplier (constraint);
|
||||
|
||||
if (name == NULL)
|
||||
name = "[ ]";
|
||||
|
||||
g_string_append_printf (str, "%s.%s", name, attr);
|
||||
|
||||
if (m != 1.0)
|
||||
g_string_append_printf (str, " × %g", m);
|
||||
|
||||
if (c > 0.0)
|
||||
g_string_append_printf (str, " + %g", c);
|
||||
else if (c < 0.0)
|
||||
g_string_append_printf (str, " - %g", -c);
|
||||
}
|
||||
else
|
||||
g_string_append_printf (str, "%g", c);
|
||||
|
||||
return g_string_free (str, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
update_preview (ConstraintEditor *editor)
|
||||
{
|
||||
GString *str;
|
||||
const char *name;
|
||||
const char *attr;
|
||||
const char *relation;
|
||||
const char *multiplier;
|
||||
const char *constant;
|
||||
double c, m;
|
||||
|
||||
if (!editor->constructed)
|
||||
return;
|
||||
|
||||
str = g_string_new ("");
|
||||
|
||||
name = gtk_string_object_get_string (GTK_STRING_OBJECT (gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->target))));
|
||||
attr = get_attr_nick (get_attr (gtk_drop_down_get_selected ((GTK_DROP_DOWN (editor->target_attr)))));
|
||||
relation = get_relation_nick (get_relation (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->relation))));
|
||||
|
||||
if (name == NULL)
|
||||
name = "[ ]";
|
||||
|
||||
g_string_append_printf (str, "%s.%s %s ", name, attr, relation);
|
||||
|
||||
constant = gtk_editable_get_text (GTK_EDITABLE (editor->constant));
|
||||
c = g_ascii_strtod (constant, NULL);
|
||||
|
||||
attr = get_attr_nick (get_attr (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->source_attr))));
|
||||
if (strcmp (attr, "none") != 0)
|
||||
{
|
||||
name = gtk_string_object_get_string (GTK_STRING_OBJECT (gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->source))));
|
||||
multiplier = gtk_editable_get_text (GTK_EDITABLE (editor->multiplier));
|
||||
m = g_ascii_strtod (multiplier, NULL);
|
||||
|
||||
if (name == NULL)
|
||||
name = "[ ]";
|
||||
|
||||
g_string_append_printf (str, "%s.%s", name, attr);
|
||||
|
||||
if (m != 1.0)
|
||||
g_string_append_printf (str, " × %g", m);
|
||||
|
||||
if (c > 0.0)
|
||||
g_string_append_printf (str, " + %g", c);
|
||||
else if (c < 0.0)
|
||||
g_string_append_printf (str, " - %g", -c);
|
||||
}
|
||||
else
|
||||
g_string_append_printf (str, "%g", c);
|
||||
|
||||
gtk_label_set_label (GTK_LABEL (editor->preview), str->str);
|
||||
|
||||
g_string_free (str, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
update_button (ConstraintEditor *editor)
|
||||
{
|
||||
gpointer obj;
|
||||
const char *target;
|
||||
const char *source;
|
||||
GtkConstraintAttribute source_attr = get_attr (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->source_attr)));
|
||||
|
||||
obj = gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->target));
|
||||
target = obj ? gtk_string_object_get_string (GTK_STRING_OBJECT (obj)) : NULL;
|
||||
|
||||
obj = gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->source));
|
||||
source = obj ? gtk_string_object_get_string (GTK_STRING_OBJECT (obj)) : NULL;
|
||||
|
||||
if (target && (source || (source_attr == GTK_CONSTRAINT_ATTRIBUTE_NONE)))
|
||||
gtk_widget_set_sensitive (editor->button, TRUE);
|
||||
else
|
||||
gtk_widget_set_sensitive (editor->button, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_init (ConstraintEditor *editor)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (editor));
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_constructed (GObject *object)
|
||||
{
|
||||
ConstraintEditor *editor = CONSTRAINT_EDITOR (object);
|
||||
|
||||
constraint_target_combo (editor->model, editor->target, FALSE);
|
||||
constraint_target_combo (editor->model, editor->source, TRUE);
|
||||
|
||||
if (editor->constraint)
|
||||
{
|
||||
GtkConstraintTarget *target;
|
||||
GtkConstraintAttribute attr;
|
||||
GtkConstraintRelation relation;
|
||||
GtkConstraintStrength strength;
|
||||
char *val;
|
||||
double multiplier;
|
||||
double constant;
|
||||
|
||||
target = gtk_constraint_get_target (editor->constraint);
|
||||
select_target (GTK_DROP_DOWN (editor->target), get_target_name (target));
|
||||
|
||||
attr = gtk_constraint_get_target_attribute (editor->constraint);
|
||||
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->target_attr), get_attr_id (attr));
|
||||
|
||||
target = gtk_constraint_get_source (editor->constraint);
|
||||
select_target (GTK_DROP_DOWN (editor->source), get_target_name (target));
|
||||
|
||||
attr = gtk_constraint_get_source_attribute (editor->constraint);
|
||||
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->source_attr), get_attr_id (attr));
|
||||
|
||||
relation = gtk_constraint_get_relation (editor->constraint);
|
||||
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->relation), get_relation_id (relation));
|
||||
|
||||
multiplier = gtk_constraint_get_multiplier (editor->constraint);
|
||||
val = g_strdup_printf ("%g", multiplier);
|
||||
gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), val);
|
||||
g_free (val);
|
||||
|
||||
constant = gtk_constraint_get_constant (editor->constraint);
|
||||
val = g_strdup_printf ("%g", constant);
|
||||
gtk_editable_set_text (GTK_EDITABLE (editor->constant), val);
|
||||
g_free (val);
|
||||
|
||||
strength = gtk_constraint_get_strength (editor->constraint);
|
||||
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->strength), get_strength_id (strength));
|
||||
|
||||
gtk_button_set_label (GTK_BUTTON (editor->button), "Apply");
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->target_attr), get_attr_id (GTK_CONSTRAINT_ATTRIBUTE_LEFT));
|
||||
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->source_attr), get_attr_id (GTK_CONSTRAINT_ATTRIBUTE_LEFT));
|
||||
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->relation), get_relation_id (GTK_CONSTRAINT_RELATION_EQ));
|
||||
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->strength), get_strength_id (GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
|
||||
gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), "1.0");
|
||||
gtk_editable_set_text (GTK_EDITABLE (editor->constant), "0.0");
|
||||
|
||||
gtk_button_set_label (GTK_BUTTON (editor->button), "Create");
|
||||
}
|
||||
|
||||
editor->constructed = TRUE;
|
||||
update_preview (editor);
|
||||
update_button (editor);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ConstraintEditor *self = CONSTRAINT_EDITOR (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_MODEL:
|
||||
self->model = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
case PROP_CONSTRAINT:
|
||||
self->constraint = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ConstraintEditor *self = CONSTRAINT_EDITOR (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_MODEL:
|
||||
g_value_set_object (value, self->model);
|
||||
break;
|
||||
|
||||
case PROP_CONSTRAINT:
|
||||
g_value_set_object (value, self->constraint);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_dispose (GObject *object)
|
||||
{
|
||||
ConstraintEditor *self = (ConstraintEditor *)object;
|
||||
|
||||
g_clear_object (&self->model);
|
||||
g_clear_object (&self->constraint);
|
||||
|
||||
gtk_widget_dispose_template (GTK_WIDGET (object), CONSTRAINT_EDITOR_TYPE);
|
||||
|
||||
G_OBJECT_CLASS (constraint_editor_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_editor_class_init (ConstraintEditorClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
|
||||
object_class->constructed = constraint_editor_constructed;
|
||||
object_class->dispose = constraint_editor_dispose;
|
||||
object_class->set_property = constraint_editor_set_property;
|
||||
object_class->get_property = constraint_editor_get_property;
|
||||
|
||||
pspecs[PROP_CONSTRAINT] =
|
||||
g_param_spec_object ("constraint", "constraint", "constraint",
|
||||
GTK_TYPE_CONSTRAINT,
|
||||
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
pspecs[PROP_MODEL] =
|
||||
g_param_spec_object ("model", "model", "model",
|
||||
G_TYPE_LIST_MODEL,
|
||||
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_properties (object_class, LAST_PROP, pspecs);
|
||||
|
||||
signals[DONE] =
|
||||
g_signal_new ("done",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE, 1, GTK_TYPE_CONSTRAINT);
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class,
|
||||
"/org/gtk/gtk4/constraint-editor/constraint-editor.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, grid);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, target);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, target_attr);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, relation);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, source);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, source_attr);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, multiplier);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, constant);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, strength);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, preview);
|
||||
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, button);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, update_preview);
|
||||
gtk_widget_class_bind_template_callback (widget_class, update_button);
|
||||
gtk_widget_class_bind_template_callback (widget_class, create_constraint);
|
||||
gtk_widget_class_bind_template_callback (widget_class, source_attr_changed);
|
||||
}
|
||||
|
||||
ConstraintEditor *
|
||||
constraint_editor_new (GListModel *model,
|
||||
GtkConstraint *constraint)
|
||||
{
|
||||
return g_object_new (CONSTRAINT_EDITOR_TYPE,
|
||||
"model", model,
|
||||
"constraint", constraint,
|
||||
NULL);
|
||||
}
|
12
demos/constraint-editor/constraint-editor.css
Normal file
@@ -0,0 +1,12 @@
|
||||
constraintview {
|
||||
background: black;
|
||||
color: white;
|
||||
}
|
||||
|
||||
constraintview .child {
|
||||
background: red;
|
||||
}
|
||||
|
||||
constraintview .guide {
|
||||
background: blue;
|
||||
}
|
9
demos/constraint-editor/constraint-editor.gresource.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/org/gtk/gtk4/constraint-editor">
|
||||
<file preprocess="xml-stripblanks">constraint-editor-window.ui</file>
|
||||
<file preprocess="xml-stripblanks">constraint-editor.ui</file>
|
||||
<file preprocess="xml-stripblanks">guide-editor.ui</file>
|
||||
<file>constraint-editor.css</file>
|
||||
</gresource>
|
||||
</gresources>
|
34
demos/constraint-editor/constraint-editor.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright © 2019 Red Hat, Inc
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Matthias Clasen
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#define CONSTRAINT_EDITOR_TYPE (constraint_editor_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ConstraintEditor, constraint_editor, CONSTRAINT, EDITOR, GtkWidget)
|
||||
|
||||
ConstraintEditor * constraint_editor_new (GListModel *model,
|
||||
GtkConstraint *constraint);
|
||||
|
||||
void constraint_editor_serialize_constraint (GString *str,
|
||||
int indent,
|
||||
GtkConstraint *constraint);
|
||||
char *constraint_editor_constraint_to_string (GtkConstraint *constraint);
|
204
demos/constraint-editor/constraint-editor.ui
Normal file
@@ -0,0 +1,204 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<object class="GtkStringList" id="targets">
|
||||
<items>
|
||||
<item>None</item>
|
||||
<item>Left</item>
|
||||
<item>Right</item>
|
||||
<item>Top</item>
|
||||
<item>Bottom</item>
|
||||
<item>Start</item>
|
||||
<item>End</item>
|
||||
<item>Width</item>
|
||||
<item>Height</item>
|
||||
<item>Center X</item>
|
||||
<item>Center Y</item>
|
||||
<item>Baseline</item>
|
||||
</items>
|
||||
</object>
|
||||
<template class="ConstraintEditor" parent="GtkWidget">
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid">
|
||||
<property name="margin-start">20</property>
|
||||
<property name="margin-end">20</property>
|
||||
<property name="margin-top">20</property>
|
||||
<property name="margin-bottom">20</property>
|
||||
<property name="row-spacing">10</property>
|
||||
<property name="column-spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Target</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropDown" id="target">
|
||||
<signal name="notify::selected" handler="update_preview" swapped="yes"/>
|
||||
<signal name="notify::selected" handler="update_button" swapped="yes"/>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropDown" id="target_attr">
|
||||
<property name="model">targets</property>
|
||||
<signal name="notify::selected" handler="update_preview" swapped="yes"/>
|
||||
<layout>
|
||||
<property name="column">2</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Relation</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropDown" id="relation">
|
||||
<signal name="notify::selected" handler="update_preview" swapped="yes"/>
|
||||
<property name="model">
|
||||
<object class="GtkStringList">
|
||||
<items>
|
||||
<item>≤</item>
|
||||
<item>=</item>
|
||||
<item>≥</item>
|
||||
</items>
|
||||
</object>
|
||||
</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Source</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropDown" id="source">
|
||||
<signal name="notify::selected" handler="update_preview" swapped="yes"/>
|
||||
<signal name="notify::selected" handler="update_button" swapped="yes"/>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropDown" id="source_attr">
|
||||
<property name="model">targets</property>
|
||||
<signal name="notify::selected" handler="update_preview" swapped="yes"/>
|
||||
<signal name="notify::selected" handler="source_attr_changed" swapped="yes"/>
|
||||
<signal name="notify::selected" handler="update_button" swapped="yes"/>
|
||||
<layout>
|
||||
<property name="column">2</property>
|
||||
<property name="row">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Multiplier</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">4</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="multiplier">
|
||||
<signal name="changed" handler="update_preview" swapped="yes"/>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">4</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Constant</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">5</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="constant">
|
||||
<signal name="changed" handler="update_preview" swapped="yes"/>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">5</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Strength</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">6</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropDown" id="strength">
|
||||
<property name="model">
|
||||
<object class="GtkStringList">
|
||||
<items>
|
||||
<item>Weak</item>
|
||||
<item>Medium</item>
|
||||
<item>Strong</item>
|
||||
<item>Required</item>
|
||||
</items>
|
||||
</object>
|
||||
</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">6</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="preview">
|
||||
<property name="xalign">0</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">7</property>
|
||||
<property name="column-span">2</property>
|
||||
</layout>
|
||||
<attributes>
|
||||
<attribute name="scale" value="1.44"/>
|
||||
</attributes>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button">
|
||||
<property name="label">Create</property>
|
||||
<signal name="clicked" handler="create_constraint"/>
|
||||
<layout>
|
||||
<property name="column">2</property>
|
||||
<property name="row">8</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
93
demos/constraint-editor/constraint-view-child.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright © 2019 Red Hat, Inc
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Matthias Clasen
|
||||
*/
|
||||
|
||||
#include "constraint-view-child.h"
|
||||
|
||||
struct _ConstraintViewChild
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
char *name;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_NAME = 1,
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
static GParamSpec props[LAST_PROP];
|
||||
|
||||
G_DEFINE_TYPE (ConstraintViewChild, constraint_view_child, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
constraint_view_child_init (ConstraintViewChild *child)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_view_child_finalize (GObject *object)
|
||||
{
|
||||
ConstraintViewChild *child = CONSTRAINT_VIEW_CHILD (object);
|
||||
|
||||
g_free (child->name);
|
||||
|
||||
G_OBJECT_CLASS (constraint_view_child_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_view_child_set_property (GObject *object,
|
||||
|
||||
static void
|
||||
constraint_view_child_class_init (ConstraintViewChildClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
object_class->finalize = constraint_view_child_finalize;
|
||||
object_class->get_property = constraint_view_child_get_property;
|
||||
object_class->set_property = constraint_view_child_set_property;
|
||||
|
||||
props[PROP_NAME] =
|
||||
g_param_spec_string ("name", "name", "name",
|
||||
NULL,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_properties (object_class, LAST_PROP, props);
|
||||
}
|
||||
|
||||
#define CONSTRAINT_VIEW_CHILD_TYPE (constraint_view_get_type ())
|
||||
|
||||
G_DECLARE_TYPE (ConstraintViewChild, constraint_view_child, CONSTRAINT, VIEW_CHILD, GObject)
|
||||
|
||||
#define CONSTRAINT_VIEW_WIDGET_TYPE (constraint_view_widget_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ConstraintViewWidget, constraint_view_widget, CONSTRAINT, VIEW_WIDGET, ConstraintViewChild)
|
||||
|
||||
ConstraintViewWidget * constraint_view_widget_new (void);
|
||||
|
||||
#define CONSTRAINT_VIEW_GUIDE_TYPE (constraint_view_guide_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ConstraintViewGuide, constraint_view_guide, CONSTRAINT, VIEW_GUIDE, ConstraintViewChild)
|
||||
|
||||
ConstraintViewGuide * constraint_view_guide_new (void);
|
||||
|
||||
#define CONSTRAINT_VIEW_CONSTRAINT_TYPE (constraint_view_constraint_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ConstraintViewConstraint, constraint_view_constraint, CONSTRAINT, VIEW_CONSTRAINT, ConstraintViewChild)
|
||||
|
||||
ConstraintViewGuide * constraint_view_constraint_new (void);
|
44
demos/constraint-editor/constraint-view-child.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright © 2019 Red Hat, Inc
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Matthias Clasen
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#define CONSTRAINT_VIEW_CHILD_TYPE (constraint_view_get_type ())
|
||||
|
||||
G_DECLARE_TYPE (ConstraintViewChild, constraint_view_child, CONSTRAINT, VIEW_CHILD, GObject)
|
||||
|
||||
#define CONSTRAINT_VIEW_WIDGET_TYPE (constraint_view_widget_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ConstraintViewWidget, constraint_view_widget, CONSTRAINT, VIEW_WIDGET, ConstraintViewChild)
|
||||
|
||||
ConstraintViewWidget * constraint_view_widget_new (void);
|
||||
|
||||
#define CONSTRAINT_VIEW_GUIDE_TYPE (constraint_view_guide_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ConstraintViewGuide, constraint_view_guide, CONSTRAINT, VIEW_GUIDE, ConstraintViewChild)
|
||||
|
||||
ConstraintViewGuide * constraint_view_guide_new (void);
|
||||
|
||||
#define CONSTRAINT_VIEW_CONSTRAINT_TYPE (constraint_view_constraint_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ConstraintViewConstraint, constraint_view_constraint, CONSTRAINT, VIEW_CONSTRAINT, ConstraintViewChild)
|
||||
|
||||
ConstraintViewGuide * constraint_view_constraint_new (void);
|
345
demos/constraint-editor/constraint-view.c
Normal file
@@ -0,0 +1,345 @@
|
||||
/* Copyright (C) 2019 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "constraint-view.h"
|
||||
|
||||
struct _ConstraintView
|
||||
{
|
||||
GtkWidget parent;
|
||||
|
||||
GListModel *model;
|
||||
|
||||
GtkWidget *drag_widget;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (ConstraintView, constraint_view, GTK_TYPE_WIDGET);
|
||||
|
||||
static void
|
||||
constraint_view_dispose (GObject *object)
|
||||
{
|
||||
ConstraintView *view = CONSTRAINT_VIEW (object);
|
||||
GtkWidget *child;
|
||||
|
||||
while ((child = gtk_widget_get_first_child (GTK_WIDGET (view))) != NULL)
|
||||
gtk_widget_unparent (child);
|
||||
|
||||
g_clear_object (&view->model);
|
||||
|
||||
G_OBJECT_CLASS (constraint_view_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_view_class_init (ConstraintViewClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->dispose = constraint_view_dispose;
|
||||
|
||||
gtk_widget_class_set_css_name (widget_class, "constraintview");
|
||||
}
|
||||
|
||||
static void
|
||||
update_weak_position (ConstraintView *self,
|
||||
GtkWidget *child,
|
||||
double x,
|
||||
double y)
|
||||
{
|
||||
GtkLayoutManager *manager;
|
||||
GtkConstraint *constraint;
|
||||
|
||||
manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
|
||||
constraint = (GtkConstraint *)g_object_get_data (G_OBJECT (child), "x-constraint");
|
||||
if (constraint)
|
||||
{
|
||||
gtk_constraint_layout_remove_constraint (GTK_CONSTRAINT_LAYOUT (manager),
|
||||
constraint);
|
||||
g_object_set_data (G_OBJECT (child), "x-constraint", NULL);
|
||||
}
|
||||
if (x != -100)
|
||||
{
|
||||
constraint = gtk_constraint_new_constant (child,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_CENTER_X,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
x,
|
||||
GTK_CONSTRAINT_STRENGTH_WEAK);
|
||||
g_object_set_data (G_OBJECT (constraint), "internal", (char *)"yes");
|
||||
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (manager),
|
||||
constraint);
|
||||
g_object_set_data (G_OBJECT (child), "x-constraint", constraint);
|
||||
}
|
||||
|
||||
constraint = (GtkConstraint *)g_object_get_data (G_OBJECT (child), "y-constraint");
|
||||
if (constraint)
|
||||
{
|
||||
gtk_constraint_layout_remove_constraint (GTK_CONSTRAINT_LAYOUT (manager),
|
||||
constraint);
|
||||
g_object_set_data (G_OBJECT (child), "y-constraint", NULL);
|
||||
}
|
||||
if (y != -100)
|
||||
{
|
||||
constraint = gtk_constraint_new_constant (child,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_CENTER_Y,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
y,
|
||||
GTK_CONSTRAINT_STRENGTH_WEAK);
|
||||
g_object_set_data (G_OBJECT (constraint), "internal", (char *)"yes");
|
||||
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (manager),
|
||||
constraint);
|
||||
g_object_set_data (G_OBJECT (child), "y-constraint", constraint);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
drag_begin (GtkGestureDrag *drag,
|
||||
double start_x,
|
||||
double start_y,
|
||||
ConstraintView *self)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
widget = gtk_widget_pick (GTK_WIDGET (self), start_x, start_y, GTK_PICK_DEFAULT);
|
||||
|
||||
if (GTK_IS_LABEL (widget))
|
||||
{
|
||||
widget = gtk_widget_get_ancestor (widget, GTK_TYPE_FRAME);
|
||||
if (widget &&
|
||||
gtk_widget_get_parent (widget) == (GtkWidget *)self)
|
||||
{
|
||||
self->drag_widget = widget;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
drag_update (GtkGestureDrag *drag,
|
||||
double offset_x,
|
||||
double offset_y,
|
||||
ConstraintView *self)
|
||||
{
|
||||
double x, y;
|
||||
|
||||
if (!self->drag_widget)
|
||||
return;
|
||||
|
||||
gtk_gesture_drag_get_start_point (drag, &x, &y);
|
||||
update_weak_position (self, self->drag_widget, x + offset_x, y + offset_y);
|
||||
}
|
||||
|
||||
static void
|
||||
drag_end (GtkGestureDrag *drag,
|
||||
double offset_x,
|
||||
double offset_y,
|
||||
ConstraintView *self)
|
||||
{
|
||||
self->drag_widget = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
omit_internal (gpointer item, gpointer user_data)
|
||||
{
|
||||
if (g_object_get_data (G_OBJECT (item), "internal"))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_view_init (ConstraintView *self)
|
||||
{
|
||||
GtkLayoutManager *manager;
|
||||
GtkEventController *controller;
|
||||
GListStore *list;
|
||||
GListModel *all_children;
|
||||
GListModel *all_constraints;
|
||||
GListModel *guides;
|
||||
GListModel *children;
|
||||
GListModel *constraints;
|
||||
GtkFilter *filter;
|
||||
|
||||
manager = gtk_constraint_layout_new ();
|
||||
gtk_widget_set_layout_manager (GTK_WIDGET (self), manager);
|
||||
|
||||
guides = gtk_constraint_layout_observe_guides (GTK_CONSTRAINT_LAYOUT (manager));
|
||||
|
||||
all_constraints = gtk_constraint_layout_observe_constraints (GTK_CONSTRAINT_LAYOUT (manager));
|
||||
filter = GTK_FILTER (gtk_custom_filter_new (omit_internal, NULL, NULL));
|
||||
constraints = (GListModel *)gtk_filter_list_model_new (all_constraints, filter);
|
||||
|
||||
all_children = gtk_widget_observe_children (GTK_WIDGET (self));
|
||||
filter = GTK_FILTER (gtk_custom_filter_new (omit_internal, NULL, NULL));
|
||||
children = (GListModel *)gtk_filter_list_model_new (all_children, filter);
|
||||
|
||||
list = g_list_store_new (G_TYPE_LIST_MODEL);
|
||||
g_list_store_append (list, children);
|
||||
g_list_store_append (list, guides);
|
||||
g_list_store_append (list, constraints);
|
||||
g_object_unref (children);
|
||||
g_object_unref (guides);
|
||||
g_object_unref (constraints);
|
||||
|
||||
self->model = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (list)));
|
||||
|
||||
controller = (GtkEventController *)gtk_gesture_drag_new ();
|
||||
g_signal_connect (controller, "drag-begin", G_CALLBACK (drag_begin), self);
|
||||
g_signal_connect (controller, "drag-update", G_CALLBACK (drag_update), self);
|
||||
g_signal_connect (controller, "drag-end", G_CALLBACK (drag_end), self);
|
||||
gtk_widget_add_controller (GTK_WIDGET (self), controller);
|
||||
}
|
||||
|
||||
ConstraintView *
|
||||
constraint_view_new (void)
|
||||
{
|
||||
return g_object_new (CONSTRAINT_VIEW_TYPE, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
constraint_view_add_child (ConstraintView *view,
|
||||
const char *name)
|
||||
{
|
||||
GtkWidget *frame;
|
||||
GtkWidget *label;
|
||||
|
||||
label = gtk_label_new (name);
|
||||
frame = gtk_frame_new (NULL);
|
||||
gtk_widget_add_css_class (frame, "child");
|
||||
gtk_widget_set_name (frame, name);
|
||||
gtk_frame_set_child (GTK_FRAME (frame), label);
|
||||
gtk_widget_set_parent (frame, GTK_WIDGET (view));
|
||||
|
||||
update_weak_position (view, frame, 100, 100);
|
||||
}
|
||||
|
||||
void
|
||||
constraint_view_remove_child (ConstraintView *view,
|
||||
GtkWidget *child)
|
||||
{
|
||||
update_weak_position (view, child, -100, -100);
|
||||
gtk_widget_unparent (child);
|
||||
}
|
||||
|
||||
void
|
||||
constraint_view_add_guide (ConstraintView *view,
|
||||
GtkConstraintGuide *guide)
|
||||
{
|
||||
GtkConstraintLayout *layout;
|
||||
GtkWidget *frame;
|
||||
GtkWidget *label;
|
||||
const char *name;
|
||||
GtkConstraint *constraint;
|
||||
struct {
|
||||
const char *name;
|
||||
GtkConstraintAttribute attr;
|
||||
} names[] = {
|
||||
{ "left-constraint", GTK_CONSTRAINT_ATTRIBUTE_LEFT },
|
||||
{ "top-constraint", GTK_CONSTRAINT_ATTRIBUTE_TOP },
|
||||
{ "width-constraint", GTK_CONSTRAINT_ATTRIBUTE_WIDTH },
|
||||
{ "height-constraint", GTK_CONSTRAINT_ATTRIBUTE_HEIGHT },
|
||||
};
|
||||
int i;
|
||||
|
||||
name = gtk_constraint_guide_get_name (guide);
|
||||
label = gtk_label_new (name);
|
||||
g_object_bind_property (guide, "name",
|
||||
label, "label",
|
||||
G_BINDING_DEFAULT);
|
||||
|
||||
frame = gtk_frame_new (NULL);
|
||||
gtk_widget_add_css_class (frame, "guide");
|
||||
g_object_set_data (G_OBJECT (frame), "internal", (char *)"yes");
|
||||
gtk_frame_set_child (GTK_FRAME (frame), label);
|
||||
gtk_widget_insert_after (frame, GTK_WIDGET (view), NULL);
|
||||
|
||||
g_object_set_data (G_OBJECT (guide), "frame", frame);
|
||||
|
||||
layout = GTK_CONSTRAINT_LAYOUT (gtk_widget_get_layout_manager (GTK_WIDGET (view)));
|
||||
gtk_constraint_layout_add_guide (layout, g_object_ref (guide));
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (names); i++)
|
||||
{
|
||||
constraint = gtk_constraint_new (frame,
|
||||
names[i].attr,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
guide,
|
||||
names[i].attr,
|
||||
1.0, 0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
g_object_set_data (G_OBJECT (constraint), "internal", (char *)"yes");
|
||||
gtk_constraint_layout_add_constraint (layout, constraint);
|
||||
g_object_set_data (G_OBJECT (guide), names[i].name, constraint);
|
||||
}
|
||||
|
||||
update_weak_position (view, frame, 150, 150);
|
||||
}
|
||||
|
||||
void
|
||||
constraint_view_remove_guide (ConstraintView *view,
|
||||
GtkConstraintGuide *guide)
|
||||
{
|
||||
GtkConstraintLayout *layout;
|
||||
GtkWidget *frame;
|
||||
GtkConstraint *constraint;
|
||||
const char *names[] = {
|
||||
"left-constraint",
|
||||
"top-constraint",
|
||||
"width-constraint",
|
||||
"height-constraint"
|
||||
};
|
||||
int i;
|
||||
|
||||
layout = GTK_CONSTRAINT_LAYOUT (gtk_widget_get_layout_manager (GTK_WIDGET (view)));
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (names); i++)
|
||||
{
|
||||
constraint = (GtkConstraint*)g_object_get_data (G_OBJECT (guide), names[i]);
|
||||
gtk_constraint_layout_remove_constraint (layout, constraint);
|
||||
}
|
||||
|
||||
frame = (GtkWidget *)g_object_get_data (G_OBJECT (guide), "frame");
|
||||
update_weak_position (view, frame, -100, -100);
|
||||
gtk_widget_unparent (frame);
|
||||
|
||||
gtk_constraint_layout_remove_guide (layout, guide);
|
||||
}
|
||||
|
||||
void
|
||||
constraint_view_add_constraint (ConstraintView *view,
|
||||
GtkConstraint *constraint)
|
||||
{
|
||||
GtkLayoutManager *manager;
|
||||
|
||||
manager = gtk_widget_get_layout_manager (GTK_WIDGET (view));
|
||||
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (manager),
|
||||
g_object_ref (constraint));
|
||||
}
|
||||
|
||||
void
|
||||
constraint_view_remove_constraint (ConstraintView *view,
|
||||
GtkConstraint *constraint)
|
||||
{
|
||||
GtkLayoutManager *manager;
|
||||
|
||||
manager = gtk_widget_get_layout_manager (GTK_WIDGET (view));
|
||||
gtk_constraint_layout_remove_constraint (GTK_CONSTRAINT_LAYOUT (manager),
|
||||
constraint);
|
||||
}
|
||||
|
||||
GListModel *
|
||||
constraint_view_get_model (ConstraintView *view)
|
||||
{
|
||||
return view->model;
|
||||
}
|
45
demos/constraint-editor/constraint-view.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright © 2019 Red Hat, Inc
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Matthias Clasen
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#define CONSTRAINT_VIEW_TYPE (constraint_view_get_type ())
|
||||
|
||||
G_MODULE_EXPORT
|
||||
G_DECLARE_FINAL_TYPE (ConstraintView, constraint_view, CONSTRAINT, VIEW, GtkWidget)
|
||||
|
||||
ConstraintView * constraint_view_new (void);
|
||||
|
||||
void constraint_view_add_child (ConstraintView *view,
|
||||
const char *name);
|
||||
void constraint_view_remove_child (ConstraintView *view,
|
||||
GtkWidget *child);
|
||||
void constraint_view_add_guide (ConstraintView *view,
|
||||
GtkConstraintGuide *guide);
|
||||
void constraint_view_remove_guide (ConstraintView *view,
|
||||
GtkConstraintGuide *guide);
|
||||
void constraint_view_guide_changed (ConstraintView *view,
|
||||
GtkConstraintGuide *guide);
|
||||
void constraint_view_add_constraint (ConstraintView *view,
|
||||
GtkConstraint *constraint);
|
||||
void constraint_view_remove_constraint (ConstraintView *view,
|
||||
GtkConstraint *constraint);
|
||||
GListModel * constraint_view_get_model (ConstraintView *view);
|
355
demos/constraint-editor/guide-editor.c
Normal file
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
* Copyright © 2019 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Matthias Clasen
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "guide-editor.h"
|
||||
|
||||
struct _GuideEditor
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GtkWidget *grid;
|
||||
GtkWidget *name;
|
||||
GtkWidget *min_width;
|
||||
GtkWidget *min_height;
|
||||
GtkWidget *nat_width;
|
||||
GtkWidget *nat_height;
|
||||
GtkWidget *max_width;
|
||||
GtkWidget *max_height;
|
||||
GtkWidget *strength;
|
||||
GtkWidget *button;
|
||||
|
||||
GtkConstraintGuide *guide;
|
||||
|
||||
gboolean constructed;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_GUIDE = 1,
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
static GParamSpec *pspecs[LAST_PROP];
|
||||
|
||||
enum {
|
||||
DONE,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
G_DEFINE_TYPE(GuideEditor, guide_editor, GTK_TYPE_WIDGET);
|
||||
|
||||
static GtkConstraintStrength
|
||||
get_strength (unsigned int id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case 0: return GTK_CONSTRAINT_STRENGTH_WEAK;
|
||||
case 1: return GTK_CONSTRAINT_STRENGTH_MEDIUM;
|
||||
case 2: return GTK_CONSTRAINT_STRENGTH_STRONG;
|
||||
case 3: return GTK_CONSTRAINT_STRENGTH_REQUIRED;
|
||||
default: g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
get_strength_id (GtkConstraintStrength strength)
|
||||
{
|
||||
switch (strength)
|
||||
{
|
||||
case GTK_CONSTRAINT_STRENGTH_WEAK: return 0;
|
||||
case GTK_CONSTRAINT_STRENGTH_MEDIUM: return 1;
|
||||
case GTK_CONSTRAINT_STRENGTH_STRONG: return 2;
|
||||
case GTK_CONSTRAINT_STRENGTH_REQUIRED: return 3;
|
||||
default: g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_strength_nick (GtkConstraintStrength strength)
|
||||
{
|
||||
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_STRENGTH);
|
||||
GEnumValue *value = g_enum_get_value (class, strength);
|
||||
const char *nick = value->value_nick;
|
||||
g_type_class_unref (class);
|
||||
|
||||
return nick;
|
||||
}
|
||||
|
||||
void
|
||||
guide_editor_serialize_guide (GString *str,
|
||||
int indent,
|
||||
GtkConstraintGuide *guide)
|
||||
{
|
||||
int min_width, min_height;
|
||||
int nat_width, nat_height;
|
||||
int max_width, max_height;
|
||||
const char *name;
|
||||
const char *strength;
|
||||
|
||||
gtk_constraint_guide_get_min_size (guide, &min_width, &min_height);
|
||||
gtk_constraint_guide_get_nat_size (guide, &nat_width, &nat_height);
|
||||
gtk_constraint_guide_get_max_size (guide, &max_width, &max_height);
|
||||
name = gtk_constraint_guide_get_name (guide);
|
||||
strength = get_strength_nick (gtk_constraint_guide_get_strength (guide));
|
||||
|
||||
g_string_append_printf (str, "%*s<guide min-width=\"%d\" min-height=\"%d\"\n", indent, "", min_width, min_height);
|
||||
g_string_append_printf (str, "%*s nat-width=\"%d\" nat-height=\"%d\"\n", indent, "", nat_width, nat_height);
|
||||
g_string_append_printf (str, "%*s max-width=\"%d\" max-height=\"%d\"\n", indent, "", max_width, max_height);
|
||||
g_string_append_printf (str, "%*s name=\"%s\" strength=\"%s\" />\n", indent, "", name, strength);
|
||||
}
|
||||
|
||||
static void
|
||||
create_guide (GtkButton *button,
|
||||
GuideEditor *editor)
|
||||
{
|
||||
int strength;
|
||||
const char *name;
|
||||
int w, h;
|
||||
GtkConstraintGuide *guide;
|
||||
unsigned int id;
|
||||
|
||||
if (editor->guide)
|
||||
guide = g_object_ref (editor->guide);
|
||||
else
|
||||
guide = gtk_constraint_guide_new ();
|
||||
|
||||
name = gtk_editable_get_text (GTK_EDITABLE (editor->name));
|
||||
gtk_constraint_guide_set_name (guide, name);
|
||||
|
||||
w = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->min_width));
|
||||
h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->min_height));
|
||||
gtk_constraint_guide_set_min_size (guide, w, h);
|
||||
|
||||
w = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->nat_width));
|
||||
h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->nat_height));
|
||||
gtk_constraint_guide_set_nat_size (guide, w, h);
|
||||
|
||||
w = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->max_width));
|
||||
h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->max_height));
|
||||
gtk_constraint_guide_set_max_size (guide, w, h);
|
||||
|
||||
id = gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->strength));
|
||||
strength = get_strength (id);
|
||||
gtk_constraint_guide_set_strength (guide, strength);
|
||||
|
||||
g_signal_emit (editor, signals[DONE], 0, guide);
|
||||
g_object_unref (guide);
|
||||
}
|
||||
|
||||
static void
|
||||
guide_editor_init (GuideEditor *editor)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (editor));
|
||||
}
|
||||
|
||||
static int guide_counter;
|
||||
|
||||
static int
|
||||
min_input (GtkSpinButton *spin_button,
|
||||
double *new_val)
|
||||
{
|
||||
if (strcmp (gtk_editable_get_text (GTK_EDITABLE (spin_button)), "") == 0)
|
||||
{
|
||||
*new_val = 0.0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int
|
||||
max_input (GtkSpinButton *spin_button,
|
||||
double *new_val)
|
||||
{
|
||||
if (strcmp (gtk_editable_get_text (GTK_EDITABLE (spin_button)), "") == 0)
|
||||
{
|
||||
*new_val = G_MAXINT;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
guide_editor_constructed (GObject *object)
|
||||
{
|
||||
GuideEditor *editor = GUIDE_EDITOR (object);
|
||||
|
||||
g_signal_connect (editor->min_width, "input", G_CALLBACK (min_input), NULL);
|
||||
g_signal_connect (editor->min_height, "input", G_CALLBACK (min_input), NULL);
|
||||
g_signal_connect (editor->max_width, "input", G_CALLBACK (max_input), NULL);
|
||||
g_signal_connect (editor->max_height, "input", G_CALLBACK (max_input), NULL);
|
||||
|
||||
if (editor->guide)
|
||||
{
|
||||
GtkConstraintStrength strength;
|
||||
const char *nick;
|
||||
int w, h;
|
||||
|
||||
nick = gtk_constraint_guide_get_name (editor->guide);
|
||||
if (nick)
|
||||
gtk_editable_set_text (GTK_EDITABLE (editor->name), nick);
|
||||
|
||||
gtk_constraint_guide_get_min_size (editor->guide, &w, &h);
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->min_width), w);
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->min_height), h);
|
||||
|
||||
gtk_constraint_guide_get_nat_size (editor->guide, &w, &h);
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->nat_width), w);
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->nat_height), h);
|
||||
|
||||
gtk_constraint_guide_get_max_size (editor->guide, &w, &h);
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_width), w);
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_height), h);
|
||||
|
||||
strength = gtk_constraint_guide_get_strength (editor->guide);
|
||||
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->strength), get_strength_id (strength));
|
||||
|
||||
gtk_button_set_label (GTK_BUTTON (editor->button), "Apply");
|
||||
}
|
||||
else
|
||||
{
|
||||
char *name;
|
||||
|
||||
guide_counter++;
|
||||
name = g_strdup_printf ("Guide %d", guide_counter);
|
||||
gtk_editable_set_text (GTK_EDITABLE (editor->name), name);
|
||||
g_free (name);
|
||||
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->min_width), 0.0);
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->min_height), 0.0);
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->nat_width), 0.0);
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->nat_height), 0.0);
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_width), G_MAXINT);
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_height), G_MAXINT);
|
||||
|
||||
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->strength), get_strength_id (GTK_CONSTRAINT_STRENGTH_MEDIUM));
|
||||
|
||||
gtk_button_set_label (GTK_BUTTON (editor->button), "Create");
|
||||
}
|
||||
|
||||
editor->constructed = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
guide_editor_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GuideEditor *self = GUIDE_EDITOR (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_GUIDE:
|
||||
self->guide = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
guide_editor_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GuideEditor *self = GUIDE_EDITOR (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_GUIDE:
|
||||
g_value_set_object (value, self->guide);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
guide_editor_dispose (GObject *object)
|
||||
{
|
||||
GuideEditor *self = (GuideEditor *)object;
|
||||
|
||||
g_clear_object (&self->guide);
|
||||
|
||||
gtk_widget_dispose_template (GTK_WIDGET (self), GUIDE_EDITOR_TYPE);
|
||||
|
||||
G_OBJECT_CLASS (guide_editor_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
guide_editor_class_init (GuideEditorClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
|
||||
object_class->constructed = guide_editor_constructed;
|
||||
object_class->dispose = guide_editor_dispose;
|
||||
object_class->set_property = guide_editor_set_property;
|
||||
object_class->get_property = guide_editor_get_property;
|
||||
|
||||
pspecs[PROP_GUIDE] =
|
||||
g_param_spec_object ("guide", "guide", "guide",
|
||||
GTK_TYPE_CONSTRAINT_GUIDE,
|
||||
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_properties (object_class, LAST_PROP, pspecs);
|
||||
|
||||
signals[DONE] =
|
||||
g_signal_new ("done",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE, 1, GTK_TYPE_CONSTRAINT_GUIDE);
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class,
|
||||
"/org/gtk/gtk4/constraint-editor/guide-editor.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, GuideEditor, grid);
|
||||
gtk_widget_class_bind_template_child (widget_class, GuideEditor, name);
|
||||
gtk_widget_class_bind_template_child (widget_class, GuideEditor, min_width);
|
||||
gtk_widget_class_bind_template_child (widget_class, GuideEditor, min_height);
|
||||
gtk_widget_class_bind_template_child (widget_class, GuideEditor, nat_width);
|
||||
gtk_widget_class_bind_template_child (widget_class, GuideEditor, nat_height);
|
||||
gtk_widget_class_bind_template_child (widget_class, GuideEditor, max_width);
|
||||
gtk_widget_class_bind_template_child (widget_class, GuideEditor, max_height);
|
||||
gtk_widget_class_bind_template_child (widget_class, GuideEditor, strength);
|
||||
gtk_widget_class_bind_template_child (widget_class, GuideEditor, button);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, create_guide);
|
||||
}
|
||||
|
||||
GuideEditor *
|
||||
guide_editor_new (GtkConstraintGuide *guide)
|
||||
{
|
||||
return g_object_new (GUIDE_EDITOR_TYPE,
|
||||
"guide", guide,
|
||||
NULL);
|
||||
}
|
@@ -1,10 +1,10 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2024 the GTK team
|
||||
/*
|
||||
* Copyright © 2019 Red Hat, Inc
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
@@ -13,24 +13,20 @@
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Matthias Clasen
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
#define GUIDE_EDITOR_TYPE (guide_editor_get_type ())
|
||||
|
||||
#include <gtk/gtkcolorpickerprivate.h>
|
||||
G_DECLARE_FINAL_TYPE (GuideEditor, guide_editor, GUIDE, EDITOR, GtkWidget)
|
||||
|
||||
G_BEGIN_DECLS
|
||||
GuideEditor * guide_editor_new (GtkConstraintGuide *guide);
|
||||
|
||||
|
||||
#define GTK_TYPE_COLOR_PICKER_QUARTZ gtk_color_picker_quartz_get_type ()
|
||||
G_DECLARE_FINAL_TYPE (GtkColorPickerQuartz, gtk_color_picker_quartz, GTK, COLOR_PICKER_QUARTZ, GObject)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkColorPicker * gtk_color_picker_quartz_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
void guide_editor_serialize_guide (GString *str,
|
||||
int indent,
|
||||
GtkConstraintGuide *guide);
|
201
demos/constraint-editor/guide-editor.ui
Normal file
@@ -0,0 +1,201 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<object class="GtkAdjustment" id="min_width_adj">
|
||||
<property name="lower">0</property>
|
||||
<property name="upper">2147483647</property>
|
||||
<property name="step-increment">1</property>
|
||||
<property name="page-increment">10</property>
|
||||
<property name="page-size">0</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="min_height_adj">
|
||||
<property name="lower">0</property>
|
||||
<property name="upper">2147483647</property>
|
||||
<property name="step-increment">1</property>
|
||||
<property name="page-increment">10</property>
|
||||
<property name="page-size">0</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="nat_width_adj">
|
||||
<property name="lower">0</property>
|
||||
<property name="upper">2147483647</property>
|
||||
<property name="step-increment">1</property>
|
||||
<property name="page-increment">10</property>
|
||||
<property name="page-size">0</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="nat_height_adj">
|
||||
<property name="lower">0</property>
|
||||
<property name="upper">2147483647</property>
|
||||
<property name="step-increment">1</property>
|
||||
<property name="page-increment">10</property>
|
||||
<property name="page-size">0</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="max_width_adj">
|
||||
<property name="lower">0</property>
|
||||
<property name="upper">2147483647</property>
|
||||
<property name="step-increment">1</property>
|
||||
<property name="page-increment">10</property>
|
||||
<property name="page-size">0</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="max_height_adj">
|
||||
<property name="lower">0</property>
|
||||
<property name="upper">2147483647</property>
|
||||
<property name="step-increment">1</property>
|
||||
<property name="page-increment">10</property>
|
||||
<property name="page-size">0</property>
|
||||
</object>
|
||||
<template class="GuideEditor" parent="GtkWidget">
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid">
|
||||
<property name="margin-start">20</property>
|
||||
<property name="margin-end">20</property>
|
||||
<property name="margin-top">20</property>
|
||||
<property name="margin-bottom">20</property>
|
||||
<property name="row-spacing">10</property>
|
||||
<property name="column-spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Name</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="name">
|
||||
<property name="max-width-chars">20</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">0</property>
|
||||
<property name="column-span">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Min Size</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="min_width">
|
||||
<property name="adjustment">min_width_adj</property>
|
||||
<property name="max-width-chars">5</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="min_height">
|
||||
<property name="adjustment">min_height_adj</property>
|
||||
<property name="max-width-chars">5</property>
|
||||
<layout>
|
||||
<property name="column">2</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Nat Size</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="nat_width">
|
||||
<property name="adjustment">nat_width_adj</property>
|
||||
<property name="max-width-chars">5</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="nat_height">
|
||||
<property name="adjustment">nat_height_adj</property>
|
||||
<property name="max-width-chars">5</property>
|
||||
<layout>
|
||||
<property name="column">2</property>
|
||||
<property name="row">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Max Size</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="max_width">
|
||||
<property name="adjustment">max_width_adj</property>
|
||||
<property name="max-width-chars">5</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="max_height">
|
||||
<property name="adjustment">max_height_adj</property>
|
||||
<property name="max-width-chars">5</property>
|
||||
<layout>
|
||||
<property name="column">2</property>
|
||||
<property name="row">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Strength</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">4</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropDown" id="strength">
|
||||
<property name="model">
|
||||
<object class="GtkStringList">
|
||||
<items>
|
||||
<item>Weak</item>
|
||||
<item>Medium</item>
|
||||
<item>Strong</item>
|
||||
<item>Required</item>
|
||||
</items>
|
||||
</object>
|
||||
</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">4</property>
|
||||
<property name="column-span">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button">
|
||||
<property name="label">Create</property>
|
||||
<signal name="clicked" handler="create_guide"/>
|
||||
<layout>
|
||||
<property name="column">2</property>
|
||||
<property name="row">5</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
28
demos/constraint-editor/main.c
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright © 2019 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Matthias Clasen <mclasen@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <constraint-editor-application.h>
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
return g_application_run (G_APPLICATION (constraint_editor_application_new ()), argc, argv);
|
||||
}
|
23
demos/constraint-editor/meson.build
Normal file
@@ -0,0 +1,23 @@
|
||||
constraint_editor_sources = [
|
||||
'main.c',
|
||||
'constraint-editor-application.c',
|
||||
'constraint-editor-window.c',
|
||||
'constraint-view.c',
|
||||
'constraint-editor.c',
|
||||
'guide-editor.c',
|
||||
]
|
||||
|
||||
constraint_editor_resources = gnome.compile_resources('constraint_editor_resources',
|
||||
'constraint-editor.gresource.xml',
|
||||
source_dir: meson.current_source_dir(),
|
||||
)
|
||||
|
||||
executable('gtk4-constraint-editor',
|
||||
sources: [ constraint_editor_sources, constraint_editor_resources, ],
|
||||
c_args: common_cflags,
|
||||
dependencies: libgtk_dep,
|
||||
include_directories: confinc,
|
||||
win_subsystem: 'windows',
|
||||
link_args: extra_demo_ldflags,
|
||||
install: false,
|
||||
)
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.6 KiB |
26
demos/gtk-demo/background.glsl
Normal file
@@ -0,0 +1,26 @@
|
||||
uniform float u_time;
|
||||
|
||||
void
|
||||
mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv)
|
||||
{
|
||||
vec2 pos = (fragCoord.xy * 2.0 - resolution.xy)/ min (resolution.x, resolution.y) ;
|
||||
|
||||
float t0 = sin ((u_time + 0.00)*1.0);
|
||||
float t1 = sin ((u_time + 0.30)*0.4);
|
||||
float t2 = cos ((u_time + 0.23)*0.9);
|
||||
float t3 = cos ((u_time + 0.41)*0.6);
|
||||
float t4 = cos ((u_time + 0.11)*0.3);
|
||||
|
||||
vec2 p0 = vec2 (t1, t0) ;
|
||||
vec2 p1 = vec2 (t2, t3) ;
|
||||
vec2 p2 = vec2 (t4, t3) ;
|
||||
|
||||
float r = 1.0/distance (pos, p0);
|
||||
float g = 1.0/distance (pos, p1);
|
||||
float b = 1.0/distance (pos, p2);
|
||||
float sum = r + g + b;
|
||||
|
||||
float alpha = 1.0 - pow (1.0/(sum), 40.0)*pow (10.0, 40.0*0.7);
|
||||
|
||||
fragColor = vec4 (r*0.5, g*0.5, b*0.5, 1.0) * alpha;
|
||||
}
|
226
demos/gtk-demo/cogs2.glsl
Normal file
@@ -0,0 +1,226 @@
|
||||
uniform float iTime;
|
||||
|
||||
// Originally from: https://www.shadertoy.com/view/3ljyDD
|
||||
// License CC0: Hexagonal tiling + cog wheels
|
||||
// Nothing fancy, just hexagonal tiling + cog wheels
|
||||
|
||||
#define PI 3.141592654
|
||||
#define TAU (2.0*PI)
|
||||
#define MROT(a) mat2(cos(a), sin(a), -sin(a), cos(a))
|
||||
|
||||
float hash(in vec2 co) {
|
||||
return fract(sin(dot(co.xy ,vec2(12.9898,58.233))) * 13758.5453);
|
||||
}
|
||||
|
||||
float pcos(float a) {
|
||||
return 0.5 + 0.5*cos(a);
|
||||
}
|
||||
|
||||
void rot(inout vec2 p, float a) {
|
||||
float c = cos(a);
|
||||
float s = sin(a);
|
||||
p = vec2(c*p.x + s*p.y, -s*p.x + c*p.y);
|
||||
}
|
||||
|
||||
float modPolar(inout vec2 p, float repetitions) {
|
||||
float angle = 2.0*PI/repetitions;
|
||||
float a = atan(p.y, p.x) + angle/2.;
|
||||
float r = length(p);
|
||||
float c = floor(a/angle);
|
||||
a = mod(a,angle) - angle/2.;
|
||||
p = vec2(cos(a), sin(a))*r;
|
||||
// For an odd number of repetitions, fix cell index of the cell in -x direction
|
||||
// (cell index would be e.g. -5 and 5 in the two halves of the cell):
|
||||
if (abs(c) >= (repetitions/2.0)) c = abs(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
float pmin(float a, float b, float k) {
|
||||
float h = clamp( 0.5+0.5*(b-a)/k, 0.0, 1.0 );
|
||||
return mix( b, a, h ) - k*h*(1.0-h);
|
||||
}
|
||||
|
||||
const vec2 sz = vec2(1.0, sqrt(3.0));
|
||||
const vec2 hsz = 0.5*sz;
|
||||
const float smallCount = 16.0;
|
||||
|
||||
vec2 hextile(inout vec2 p) {
|
||||
// See Art of Code: Hexagonal Tiling Explained!
|
||||
// https://www.youtube.com/watch?v=VmrIDyYiJBA
|
||||
|
||||
vec2 p1 = mod(p, sz)-hsz;
|
||||
vec2 p2 = mod(p - hsz*1.0, sz)-hsz;
|
||||
vec2 p3 = mix(p2, p1, vec2(length(p1) < length(p2)));
|
||||
vec2 n = p3 - p;
|
||||
p = p3;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
float circle(vec2 p, float r) {
|
||||
return length(p) - r;
|
||||
}
|
||||
|
||||
float box(vec2 p, vec2 b) {
|
||||
vec2 d = abs(p)-b;
|
||||
return length(max(d,0.0)) + min(max(d.x,d.y),0.0);
|
||||
}
|
||||
|
||||
float unevenCapsule(vec2 p, float r1, float r2, float h) {
|
||||
p.x = abs(p.x);
|
||||
float b = (r1-r2)/h;
|
||||
float a = sqrt(1.0-b*b);
|
||||
float k = dot(p,vec2(-b,a));
|
||||
if( k < 0.0 ) return length(p) - r1;
|
||||
if( k > a*h ) return length(p-vec2(0.0,h)) - r2;
|
||||
return dot(p, vec2(a,b) ) - r1;
|
||||
}
|
||||
|
||||
float cogwheel(vec2 p, float innerRadius, float outerRadius, float cogs, float holes) {
|
||||
float cogWidth = 0.25*innerRadius*TAU/cogs;
|
||||
|
||||
float d0 = circle(p, innerRadius);
|
||||
|
||||
vec2 icp = p;
|
||||
modPolar(icp, holes);
|
||||
icp -= vec2(innerRadius*0.55, 0.0);
|
||||
float d1 = circle(icp, innerRadius*0.25);
|
||||
|
||||
vec2 cp = p;
|
||||
modPolar(cp, cogs);
|
||||
cp -= vec2(innerRadius, 0.0);
|
||||
float d2 = unevenCapsule(cp.yx, cogWidth, cogWidth*0.75, (outerRadius-innerRadius));
|
||||
|
||||
float d3 = circle(p, innerRadius*0.20);
|
||||
|
||||
float d = 1E6;
|
||||
d = min(d, d0);
|
||||
d = pmin(d, d2, 0.5*cogWidth);
|
||||
d = min(d, d2);
|
||||
d = max(d, -d1);
|
||||
d = max(d, -d3);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
float ccell1(vec2 p, float r) {
|
||||
float d = 1E6;
|
||||
const float bigCount = 60.0;
|
||||
|
||||
vec2 cp0 = p;
|
||||
rot(cp0, -iTime*TAU/bigCount);
|
||||
float d0 = cogwheel(cp0, 0.36, 0.38, bigCount, 5.0);
|
||||
|
||||
vec2 cp1 = p;
|
||||
float nm = modPolar(cp1, 6.0);
|
||||
|
||||
cp1 -= vec2(0.5, 0.0);
|
||||
rot(cp1, 0.2+TAU*nm/2.0 + iTime*TAU/smallCount);
|
||||
float d1 = cogwheel(cp1, 0.11, 0.125, smallCount, 5.0);
|
||||
|
||||
d = min(d, d0);
|
||||
d = min(d, d1);
|
||||
return d;
|
||||
}
|
||||
|
||||
float ccell2(vec2 p, float r) {
|
||||
float d = 1E6;
|
||||
vec2 cp0 = p;
|
||||
float nm = modPolar(cp0, 6.0);
|
||||
vec2 cp1 = cp0;
|
||||
const float off = 0.275;
|
||||
const float count = smallCount + 2.0;
|
||||
cp0 -= vec2(off, 0.0);
|
||||
rot(cp0, 0.+TAU*nm/2.0 - iTime*TAU/count);
|
||||
float d0 = cogwheel(cp0, 0.09, 0.105, count, 5.0);
|
||||
|
||||
|
||||
cp1 -= vec2(0.5, 0.0);
|
||||
rot(cp1, 0.2+TAU*nm/2.0 + iTime*TAU/smallCount);
|
||||
float d1 = cogwheel(cp1, 0.11, 0.125, smallCount, 5.0);
|
||||
|
||||
float l = length(p);
|
||||
float d2 = l - (off+0.055);
|
||||
float d3 = d2 + 0.020;;
|
||||
|
||||
vec2 tp0 = p;
|
||||
modPolar(tp0, 60.0);
|
||||
tp0.x -= off;
|
||||
float d4 = box(tp0, vec2(0.0125, 0.005));
|
||||
|
||||
float ctime = -(iTime*0.05 + r)*TAU;
|
||||
|
||||
vec2 tp1 = p;
|
||||
rot(tp1, ctime*12.0);
|
||||
tp1.x -= 0.13;
|
||||
float d5 = box(tp1, vec2(0.125, 0.005));
|
||||
|
||||
vec2 tp2 = p;
|
||||
rot(tp2, ctime);
|
||||
tp2.x -= 0.13*0.5;
|
||||
float d6 = box(tp2, vec2(0.125*0.5, 0.0075));
|
||||
|
||||
float d7 = l - 0.025;
|
||||
float d8 = l - 0.0125;
|
||||
|
||||
d = min(d, d0);
|
||||
d = min(d, d1);
|
||||
d = min(d, d2);
|
||||
d = max(d, -d3);
|
||||
d = min(d, d4);
|
||||
d = min(d, d5);
|
||||
d = min(d, d6);
|
||||
d = min(d, d7);
|
||||
d = max(d, -d8);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
float df(vec2 p, float scale, inout vec2 nn) {
|
||||
p /= scale;
|
||||
nn = hextile(p);
|
||||
nn = floor(nn + 0.5);
|
||||
float r = hash(nn);
|
||||
|
||||
float d;;
|
||||
|
||||
if (r < 0.5) {
|
||||
d = ccell1(p, r);
|
||||
} else {
|
||||
d = ccell2(p, r);
|
||||
}
|
||||
|
||||
return d*scale;
|
||||
}
|
||||
|
||||
vec3 postProcess(vec3 col, vec2 q) {
|
||||
//col = saturate(col);
|
||||
col=pow(clamp(col,0.0,1.0),vec3(0.75));
|
||||
col=col*0.6+0.4*col*col*(3.0-2.0*col); // contrast
|
||||
col=mix(col, vec3(dot(col, vec3(0.33))), -0.4); // satuation
|
||||
col*=0.5+0.5*pow(19.0*q.x*q.y*(1.0-q.x)*(1.0-q.y),0.7); // vigneting
|
||||
return col;
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv) {
|
||||
vec2 q = fragCoord/resolution.xy;
|
||||
vec2 p = -1.0 + 2.0*q;
|
||||
p.x *= resolution.x/resolution.y;
|
||||
float tm = iTime*0.1;
|
||||
p += vec2(cos(tm), sin(tm*sqrt(0.5)));
|
||||
float z = mix(0.5, 1.0, pcos(tm*sqrt(0.3)));
|
||||
float aa = 4.0 / resolution.y;
|
||||
|
||||
vec2 nn = vec2(0.0);
|
||||
float d = df(p, z, nn);
|
||||
|
||||
vec3 col = vec3(160.0)/vec3(255.0);
|
||||
vec3 baseCol = vec3(0.3);
|
||||
vec4 logoCol = vec4(baseCol, 1.0)*smoothstep(-aa, 0.0, -d);
|
||||
col = mix(col, logoCol.xyz, pow(logoCol.w, 8.0));
|
||||
col += 0.4*pow(abs(sin(20.0*d)), 0.6);
|
||||
|
||||
col = postProcess(col, q);
|
||||
|
||||
fragColor = vec4(col, 1.0);
|
||||
}
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
27
demos/gtk-demo/crosswarp.glsl
Normal file
@@ -0,0 +1,27 @@
|
||||
uniform float progress;
|
||||
uniform sampler2D u_texture1;
|
||||
uniform sampler2D u_texture2;
|
||||
|
||||
vec4 getFromColor (vec2 uv) {
|
||||
return GskTexture(u_texture1, uv);
|
||||
}
|
||||
|
||||
vec4 getToColor (vec2 uv) {
|
||||
return GskTexture(u_texture2, uv);
|
||||
}
|
||||
|
||||
// Source: https://gl-transitions.com/editor/crosswarp
|
||||
// Author: Eke Péter <peterekepeter@gmail.com>
|
||||
// License: MIT
|
||||
|
||||
vec4 transition(vec2 p) {
|
||||
float x = progress;
|
||||
x=smoothstep(.0,1.0,(x*2.0+p.x-1.0));
|
||||
return mix(getFromColor((p-.5)*(1.-x)+.5), getToColor((p-.5)*x+.5), x);
|
||||
}
|
||||
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv)
|
||||
{
|
||||
fragColor = transition(uv);
|
||||
}
|
@@ -15,54 +15,12 @@ on_destroy (gpointer data)
|
||||
window = NULL;
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
cursor_callback (GdkCursor *cursor,
|
||||
int cursor_size,
|
||||
double scale,
|
||||
int *width,
|
||||
int *height,
|
||||
int *hotspot_x,
|
||||
int *hotspot_y,
|
||||
gpointer data)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
GdkTexture *texture;
|
||||
GError *error = NULL;
|
||||
int scaled_size;
|
||||
|
||||
scaled_size = ceil (cursor_size * scale);
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_resource_at_scale ("/cursors/images/gtk-logo.svg",
|
||||
scaled_size, scaled_size,
|
||||
TRUE,
|
||||
&error);
|
||||
if (!pixbuf)
|
||||
{
|
||||
g_print ("%s\n", error->message);
|
||||
g_error_free (error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
texture = gdk_texture_new_for_pixbuf (pixbuf);
|
||||
|
||||
g_object_unref (pixbuf);
|
||||
|
||||
*width = cursor_size;
|
||||
*height = cursor_size;
|
||||
*hotspot_x = 18 * cursor_size / 32.0;
|
||||
*hotspot_y = 2 * cursor_size / 32.0;
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_cursors (GtkWidget *do_widget)
|
||||
{
|
||||
if (!window)
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
GtkWidget *logo_callback;
|
||||
GdkCursor *cursor;
|
||||
|
||||
builder = gtk_builder_new_from_resource ("/cursors/cursors.ui");
|
||||
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
|
||||
@@ -71,10 +29,6 @@ do_cursors (GtkWidget *do_widget)
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (on_destroy), NULL);
|
||||
logo_callback = GTK_WIDGET (gtk_builder_get_object (builder, "logo_callback"));
|
||||
cursor = gdk_cursor_new_from_callback (cursor_callback, NULL, NULL, NULL);
|
||||
gtk_widget_set_cursor (logo_callback, cursor);
|
||||
g_object_unref (cursor);
|
||||
g_object_unref (builder);
|
||||
}
|
||||
|
||||
|
@@ -116,7 +116,6 @@
|
||||
<file>w_resize_cursor.png</file>
|
||||
<file>zoom_in_cursor.png</file>
|
||||
<file>zoom_out_cursor.png</file>
|
||||
<file>gtk-logo.svg</file>
|
||||
</gresource>
|
||||
<gresource prefix="/dnd">
|
||||
<file>dnd.css</file>
|
||||
@@ -146,6 +145,21 @@
|
||||
<file>cogs.glsl</file>
|
||||
<file>glowingstars.glsl</file>
|
||||
</gresource>
|
||||
<gresource prefix="/gltransition">
|
||||
<file>gtkshaderstack.c</file>
|
||||
<file>gtkshaderstack.h</file>
|
||||
<file>gtkshaderbin.h</file>
|
||||
<file>gtkshaderbin.c</file>
|
||||
<file>gskshaderpaintable.h</file>
|
||||
<file>gskshaderpaintable.c</file>
|
||||
<file>wind.glsl</file>
|
||||
<file>radial.glsl</file>
|
||||
<file>crosswarp.glsl</file>
|
||||
<file>kaleidoscope.glsl</file>
|
||||
<file>cogs2.glsl</file>
|
||||
<file>ripple.glsl</file>
|
||||
<file>background.glsl</file>
|
||||
</gresource>
|
||||
<gresource prefix="/iconscroll">
|
||||
<file>iconscroll.ui</file>
|
||||
</gresource>
|
||||
@@ -281,6 +295,7 @@
|
||||
<file>gears.c</file>
|
||||
<file>gestures.c</file>
|
||||
<file>glarea.c</file>
|
||||
<file>gltransition.c</file>
|
||||
<file>headerbar.c</file>
|
||||
<file>hypertext.c</file>
|
||||
<file>iconscroll.c</file>
|
||||
@@ -438,10 +453,6 @@
|
||||
<file>icons/16x16/categories/applications-other.png</file>
|
||||
<file>icons/48x48/status/starred.png</file>
|
||||
<file alias="icons/scalable/apps/org.gtk.Demo4.svg">data/scalable/apps/org.gtk.Demo4.svg</file>
|
||||
<file>portland-rose-thumbnail.png</file>
|
||||
<file>large-image-thumbnail.png</file>
|
||||
<file compressed="true">large-image.png</file>
|
||||
<file compressed="true">Moby-Dick.txt</file>
|
||||
</gresource>
|
||||
<gresource prefix="/org/gtk/Demo4/gtk">
|
||||
<file preprocess="xml-stripblanks">help-overlay.ui</file>
|
||||
|
@@ -579,8 +579,6 @@ released_cb (GtkGesture *gesture,
|
||||
|
||||
widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
|
||||
child = gtk_widget_pick (widget, x, y, 0);
|
||||
if (!child)
|
||||
return;
|
||||
item = (CanvasItem *)gtk_widget_get_ancestor (child, canvas_item_get_type ());
|
||||
if (!item)
|
||||
return;
|
||||
|
@@ -55,7 +55,7 @@ mode_switch_state_set (GtkSwitch *sw,
|
||||
{
|
||||
gtk_widget_set_visible (label, TRUE);
|
||||
gtk_accessible_update_relation (GTK_ACCESSIBLE (sw),
|
||||
GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE, label, NULL,
|
||||
GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE, label,
|
||||
-1);
|
||||
gtk_accessible_update_state (GTK_ACCESSIBLE (sw),
|
||||
GTK_ACCESSIBLE_STATE_INVALID, GTK_ACCESSIBLE_INVALID_TRUE,
|
||||
|
@@ -12,13 +12,11 @@
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
static gboolean
|
||||
close_request_cb (GtkWidget *win, gpointer user_data)
|
||||
static void
|
||||
response_cb (GtkDialog *dialog, int response_id)
|
||||
{
|
||||
g_assert (window == win);
|
||||
gtk_window_destroy ((GtkWindow *)window);
|
||||
gtk_window_destroy (GTK_WINDOW (window));
|
||||
window = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -119,7 +117,7 @@ do_expander (GtkWidget *do_widget)
|
||||
g_signal_connect (expander, "notify::expanded",
|
||||
G_CALLBACK (expander_cb), window);
|
||||
|
||||
g_signal_connect (window, "close-request", G_CALLBACK (close_request_cb), NULL);
|
||||
g_signal_connect (window, "response", G_CALLBACK (response_cb), NULL);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "gtkfishbowl.h"
|
||||
#include "gtkgears.h"
|
||||
#include "gskshaderpaintable.h"
|
||||
|
||||
#include "nodewidget.h"
|
||||
#include "graphwidget.h"
|
||||
@@ -151,6 +152,44 @@ create_switch (void)
|
||||
return w;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
update_paintable (GtkWidget *widget,
|
||||
GdkFrameClock *frame_clock,
|
||||
gpointer user_data)
|
||||
{
|
||||
GskShaderPaintable *paintable;
|
||||
gint64 frame_time;
|
||||
|
||||
paintable = GSK_SHADER_PAINTABLE (gtk_picture_get_paintable (GTK_PICTURE (widget)));
|
||||
frame_time = gdk_frame_clock_get_frame_time (frame_clock);
|
||||
gsk_shader_paintable_update_time (paintable, 0, frame_time);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
create_cogs (void)
|
||||
{
|
||||
GtkWidget *picture;
|
||||
static GskGLShader *cog_shader = NULL;
|
||||
GdkPaintable *paintable;
|
||||
|
||||
if (cog_shader == NULL)
|
||||
cog_shader = gsk_gl_shader_new_from_resource ("/gltransition/cogs2.glsl");
|
||||
paintable = gsk_shader_paintable_new (g_object_ref (cog_shader), NULL);
|
||||
picture = gtk_picture_new_for_paintable (paintable);
|
||||
gtk_widget_set_size_request (picture, 150, 75);
|
||||
gtk_widget_add_tick_callback (picture, update_paintable, NULL, NULL);
|
||||
|
||||
return picture;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_cogs (GtkFishbowl *fb)
|
||||
{
|
||||
return GSK_IS_GL_RENDERER (gtk_native_get_renderer (gtk_widget_get_native (GTK_WIDGET (fb))));
|
||||
}
|
||||
|
||||
static void
|
||||
mapped (GtkWidget *w)
|
||||
{
|
||||
@@ -200,6 +239,7 @@ static const struct {
|
||||
{ "Gears", create_gears, NULL },
|
||||
{ "Switch", create_switch, NULL },
|
||||
{ "Menubutton", create_menu_button, NULL },
|
||||
{ "Shader", create_cogs, check_cogs },
|
||||
{ "Tiger", create_tiger, NULL },
|
||||
{ "Graph", create_graph, NULL },
|
||||
};
|
||||
|
@@ -811,7 +811,7 @@ tag_pair_equal (gconstpointer a, gconstpointer b)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
static GtkOrdering
|
||||
script_sort (const void *item1,
|
||||
const void *item2,
|
||||
void *data)
|
||||
@@ -1869,4 +1869,4 @@ do_font_features (GtkWidget *do_widget)
|
||||
return window;
|
||||
}
|
||||
|
||||
/* vim:set foldmethod=marker: */
|
||||
/* vim:set foldmethod=marker expandtab: */
|
||||
|
@@ -363,9 +363,7 @@ insert_markup_idle (gpointer data)
|
||||
|
||||
if (g_get_monotonic_time () - begin > G_TIME_SPAN_MILLISECOND)
|
||||
{
|
||||
guint id;
|
||||
id = g_idle_add (insert_markup_idle, data);
|
||||
g_source_set_name_by_id (id, "[gtk-demo] insert_markup_idle");
|
||||
g_idle_add (insert_markup_idle, data);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
@@ -400,9 +398,7 @@ parse_markup_idle (gpointer data)
|
||||
do {
|
||||
if (g_get_monotonic_time () - begin > G_TIME_SPAN_MILLISECOND)
|
||||
{
|
||||
guint id;
|
||||
id = g_idle_add (parse_markup_idle, data);
|
||||
g_source_set_name_by_id (id, "[gtk-demo] parse_markup_idle");
|
||||
g_idle_add (parse_markup_idle, data);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
|
@@ -276,7 +276,7 @@ gtk_font_plane_class_init (GtkFontPlaneClass *class)
|
||||
|
||||
GtkWidget *
|
||||
gtk_font_plane_new (GtkAdjustment *weight_adj,
|
||||
GtkAdjustment *width_adj)
|
||||
GtkAdjustment *width_adj)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_FONT_PLANE,
|
||||
"weight-adjustment", weight_adj,
|
||||
|
@@ -55,7 +55,7 @@ struct _GtkFontPlaneClass
|
||||
|
||||
|
||||
GType gtk_font_plane_get_type (void) G_GNUC_CONST;
|
||||
GtkWidget * gtk_font_plane_new (GtkAdjustment *weight_adj,
|
||||
GtkAdjustment *width_adj);
|
||||
GtkWidget * gtk_font_plane_new (GtkAdjustment *width_adj,
|
||||
GtkAdjustment *weight_adj);
|
||||
|
||||
G_END_DECLS
|
||||
|
362
demos/gtk-demo/gltransition.c
Normal file
@@ -0,0 +1,362 @@
|
||||
/* OpenGL/Transitions and Effects
|
||||
* #Keywords: OpenGL, shader, effect
|
||||
*
|
||||
* Create transitions between pages using a custom fragment shader.
|
||||
*
|
||||
* The example transitions here are taken from gl-transitions.com, and you
|
||||
* can edit the shader code itself on the last page of the stack.
|
||||
*
|
||||
* The transitions work with arbitrary content. We use images, shaders
|
||||
* GL areas and plain old widgets to demonstrate this.
|
||||
*
|
||||
* The demo also shows some over-the-top effects like wobbly widgets,
|
||||
* and animated backgrounds.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include "gtkshaderstack.h"
|
||||
#include "gtkshaderbin.h"
|
||||
#include "gtkshadertoy.h"
|
||||
#include "gskshaderpaintable.h"
|
||||
|
||||
static GtkWidget *demo_window = NULL;
|
||||
|
||||
static void
|
||||
close_window (GtkWidget *widget)
|
||||
{
|
||||
/* Reset the state */
|
||||
demo_window = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
text_changed (GtkTextBuffer *buffer,
|
||||
GtkWidget *button)
|
||||
{
|
||||
gtk_widget_set_visible (button, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
apply_text (GtkWidget *button,
|
||||
GtkTextBuffer *buffer)
|
||||
{
|
||||
GtkWidget *stack;
|
||||
GskGLShader *shader;
|
||||
GtkTextIter start, end;
|
||||
char *text;
|
||||
|
||||
stack = g_object_get_data (G_OBJECT (button), "the-stack");
|
||||
|
||||
gtk_text_buffer_get_bounds (buffer, &start, &end);
|
||||
text = gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
|
||||
|
||||
GBytes *bytes = g_bytes_new_take (text, strlen (text));
|
||||
shader = gsk_gl_shader_new_from_bytes (bytes);
|
||||
|
||||
gtk_shader_stack_set_shader (GTK_SHADER_STACK (stack), shader);
|
||||
|
||||
g_object_unref (shader);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
gtk_widget_set_visible (button, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
go_back (GtkWidget *button,
|
||||
GtkWidget *stack)
|
||||
{
|
||||
gtk_shader_stack_transition (GTK_SHADER_STACK (stack), FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
go_forward (GtkWidget *button,
|
||||
GtkWidget *stack)
|
||||
{
|
||||
gtk_shader_stack_transition (GTK_SHADER_STACK (stack), TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
clicked_cb (GtkGestureClick *gesture,
|
||||
guint n_pressed,
|
||||
double x,
|
||||
double y,
|
||||
gpointer data)
|
||||
{
|
||||
gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
ripple_bin_new (void)
|
||||
{
|
||||
GtkWidget *bin = gtk_shader_bin_new ();
|
||||
static GskGLShader *shader = NULL;
|
||||
|
||||
if (shader == NULL)
|
||||
shader = gsk_gl_shader_new_from_resource ("/gltransition/ripple.glsl");
|
||||
|
||||
gtk_shader_bin_add_shader (GTK_SHADER_BIN (bin), shader, GTK_STATE_FLAG_PRELIGHT, GTK_STATE_FLAG_PRELIGHT, 20);
|
||||
|
||||
return bin;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
new_shadertoy (const char *path)
|
||||
{
|
||||
GBytes *shader;
|
||||
GtkWidget *toy;
|
||||
|
||||
toy = gtk_shadertoy_new ();
|
||||
shader = g_resources_lookup_data (path, 0, NULL);
|
||||
gtk_shadertoy_set_image_shader (GTK_SHADERTOY (toy),
|
||||
g_bytes_get_data (shader, NULL));
|
||||
g_bytes_unref (shader);
|
||||
|
||||
return toy;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
update_paintable (GtkWidget *widget,
|
||||
GdkFrameClock *frame_clock,
|
||||
gpointer user_data)
|
||||
{
|
||||
GskShaderPaintable *paintable;
|
||||
gint64 frame_time;
|
||||
|
||||
paintable = GSK_SHADER_PAINTABLE (gtk_picture_get_paintable (GTK_PICTURE (widget)));
|
||||
frame_time = gdk_frame_clock_get_frame_time (frame_clock);
|
||||
gsk_shader_paintable_update_time (paintable, 0, frame_time);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
make_shader_stack (const char *name,
|
||||
const char *resource_path,
|
||||
int active_child,
|
||||
GtkWidget *scale)
|
||||
{
|
||||
GtkWidget *stack, *child, *widget, *vbox, *hbox, *bin;
|
||||
GtkWidget *label, *button, *tv;
|
||||
GskGLShader *shader;
|
||||
GObjectClass *class;
|
||||
GParamSpecFloat *pspec;
|
||||
GtkAdjustment *adjustment;
|
||||
GtkTextBuffer *buffer;
|
||||
GBytes *bytes;
|
||||
GtkEventController *controller;
|
||||
GdkPaintable *paintable;
|
||||
|
||||
stack = gtk_shader_stack_new ();
|
||||
shader = gsk_gl_shader_new_from_resource (resource_path);
|
||||
gtk_shader_stack_set_shader (GTK_SHADER_STACK (stack), shader);
|
||||
g_object_unref (shader);
|
||||
|
||||
child = gtk_picture_new_for_resource ("/css_blendmodes/ducky.png");
|
||||
gtk_picture_set_can_shrink (GTK_PICTURE (child), TRUE);
|
||||
gtk_shader_stack_add_child (GTK_SHADER_STACK (stack), child);
|
||||
|
||||
shader = gsk_gl_shader_new_from_resource ("/gltransition/cogs2.glsl");
|
||||
paintable = gsk_shader_paintable_new (shader, NULL);
|
||||
|
||||
child = gtk_picture_new_for_paintable (paintable);
|
||||
gtk_widget_add_tick_callback (child, update_paintable, NULL, NULL);
|
||||
gtk_picture_set_can_shrink (GTK_PICTURE (child), TRUE);
|
||||
gtk_shader_stack_add_child (GTK_SHADER_STACK (stack), child);
|
||||
|
||||
child = gtk_picture_new_for_resource ("/transparent/portland-rose.jpg");
|
||||
gtk_picture_set_can_shrink (GTK_PICTURE (child), TRUE);
|
||||
gtk_shader_stack_add_child (GTK_SHADER_STACK (stack), child);
|
||||
|
||||
child = new_shadertoy ("/shadertoy/neon.glsl");
|
||||
gtk_shader_stack_add_child (GTK_SHADER_STACK (stack), child);
|
||||
|
||||
child = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
||||
|
||||
class = g_type_class_ref (GTK_TYPE_SHADER_STACK);
|
||||
pspec = G_PARAM_SPEC_FLOAT (g_object_class_find_property (class, "duration"));
|
||||
|
||||
adjustment = gtk_range_get_adjustment (GTK_RANGE (scale));
|
||||
if (gtk_adjustment_get_lower (adjustment) == 0.0 &&
|
||||
gtk_adjustment_get_upper (adjustment) == 0.0)
|
||||
{
|
||||
gtk_adjustment_configure (adjustment,
|
||||
pspec->default_value,
|
||||
pspec->minimum,
|
||||
pspec->maximum,
|
||||
0.1, 0.5, 0);
|
||||
}
|
||||
|
||||
g_type_class_unref (class);
|
||||
|
||||
g_object_bind_property (adjustment, "value",
|
||||
stack, "duration",
|
||||
G_BINDING_DEFAULT);
|
||||
|
||||
widget = gtk_scrolled_window_new ();
|
||||
gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (widget), TRUE);
|
||||
gtk_widget_set_hexpand (widget, TRUE);
|
||||
gtk_widget_set_vexpand (widget, TRUE);
|
||||
|
||||
controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ());
|
||||
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (controller), 0);
|
||||
g_signal_connect (controller, "released", G_CALLBACK (clicked_cb), NULL);
|
||||
gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_BUBBLE);
|
||||
gtk_widget_add_controller (GTK_WIDGET (widget), controller);
|
||||
|
||||
tv = gtk_text_view_new ();
|
||||
gtk_text_view_set_left_margin (GTK_TEXT_VIEW (tv), 4);
|
||||
gtk_text_view_set_right_margin (GTK_TEXT_VIEW (tv), 4);
|
||||
gtk_text_view_set_top_margin (GTK_TEXT_VIEW (tv), 4);
|
||||
gtk_text_view_set_bottom_margin (GTK_TEXT_VIEW (tv), 4);
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));
|
||||
bytes = g_resources_lookup_data (resource_path, 0, NULL);
|
||||
gtk_text_buffer_set_text (buffer,
|
||||
(const char *)g_bytes_get_data (bytes, NULL),
|
||||
g_bytes_get_size (bytes));
|
||||
g_bytes_unref (bytes);
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (widget), tv);
|
||||
|
||||
gtk_box_append (GTK_BOX (child), widget);
|
||||
|
||||
gtk_shader_stack_add_child (GTK_SHADER_STACK (stack), child);
|
||||
|
||||
gtk_shader_stack_set_active (GTK_SHADER_STACK (stack), active_child);
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
||||
|
||||
widget = gtk_center_box_new ();
|
||||
label = gtk_label_new (name);
|
||||
gtk_widget_add_css_class (label, "title-4");
|
||||
gtk_widget_set_size_request (label, -1, 26);
|
||||
gtk_center_box_set_center_widget (GTK_CENTER_BOX (widget), label);
|
||||
|
||||
button = gtk_button_new_from_icon_name ("view-refresh-symbolic");
|
||||
g_signal_connect (buffer, "changed", G_CALLBACK (text_changed), button);
|
||||
g_object_set_data (G_OBJECT (button), "the-stack", stack);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (apply_text), buffer);
|
||||
gtk_widget_set_halign (button, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
|
||||
gtk_widget_add_css_class (button, "small");
|
||||
gtk_widget_set_visible (button, FALSE);
|
||||
gtk_center_box_set_end_widget (GTK_CENTER_BOX (widget), button);
|
||||
|
||||
gtk_box_append (GTK_BOX (vbox), widget);
|
||||
|
||||
GtkWidget *bin2 = ripple_bin_new ();
|
||||
gtk_shader_bin_set_child (GTK_SHADER_BIN (bin2), stack);
|
||||
|
||||
gtk_box_append (GTK_BOX (vbox), bin2);
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
gtk_widget_set_halign (hbox, GTK_ALIGN_CENTER);
|
||||
|
||||
gtk_box_append (GTK_BOX (vbox), hbox);
|
||||
|
||||
button = gtk_button_new_from_icon_name ("go-previous-symbolic");
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (go_back), stack);
|
||||
bin = ripple_bin_new ();
|
||||
gtk_shader_bin_set_child (GTK_SHADER_BIN (bin), button);
|
||||
gtk_box_append (GTK_BOX (hbox), bin);
|
||||
|
||||
button = gtk_button_new_from_icon_name ("go-next-symbolic");
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (go_forward), stack);
|
||||
bin = ripple_bin_new ();
|
||||
gtk_shader_bin_set_child (GTK_SHADER_BIN (bin), button);
|
||||
gtk_box_append (GTK_BOX (hbox), bin);
|
||||
|
||||
return vbox;
|
||||
}
|
||||
|
||||
static void
|
||||
remove_provider (gpointer data)
|
||||
{
|
||||
GtkStyleProvider *provider = GTK_STYLE_PROVIDER (data);
|
||||
|
||||
gtk_style_context_remove_provider_for_display (gdk_display_get_default (), provider);
|
||||
g_object_unref (provider);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
create_gltransition_window (GtkWidget *do_widget)
|
||||
{
|
||||
GtkWidget *window, *headerbar, *scale, *outer_grid, *grid, *background;
|
||||
GdkPaintable *paintable;
|
||||
GtkCssProvider *provider;
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Transitions and Effects");
|
||||
headerbar = gtk_header_bar_new ();
|
||||
scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, NULL);
|
||||
gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE);
|
||||
gtk_widget_set_size_request (scale, 100, -1);
|
||||
gtk_widget_set_tooltip_text (scale, "Transition duration");
|
||||
gtk_header_bar_pack_end (GTK_HEADER_BAR (headerbar), scale);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), headerbar);
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 800, 600);
|
||||
g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);
|
||||
|
||||
outer_grid = gtk_grid_new ();
|
||||
gtk_window_set_child (GTK_WINDOW (window), outer_grid);
|
||||
|
||||
paintable = gsk_shader_paintable_new (gsk_gl_shader_new_from_resource ("/gltransition/background.glsl"), NULL);
|
||||
background = gtk_picture_new_for_paintable (paintable);
|
||||
gtk_widget_add_tick_callback (background, update_paintable, NULL, NULL);
|
||||
|
||||
gtk_grid_attach (GTK_GRID (outer_grid),
|
||||
background,
|
||||
0, 0, 1, 1);
|
||||
|
||||
grid = gtk_grid_new ();
|
||||
gtk_grid_attach (GTK_GRID (outer_grid),
|
||||
grid,
|
||||
0, 0, 1, 1);
|
||||
|
||||
gtk_widget_set_halign (grid, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_valign (grid, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_margin_start (grid, 12);
|
||||
gtk_widget_set_margin_end (grid, 12);
|
||||
gtk_widget_set_margin_top (grid, 12);
|
||||
gtk_widget_set_margin_bottom (grid, 12);
|
||||
gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
|
||||
gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
|
||||
gtk_grid_set_row_homogeneous (GTK_GRID (grid), TRUE);
|
||||
gtk_grid_set_column_homogeneous (GTK_GRID (grid), TRUE);
|
||||
|
||||
gtk_grid_attach (GTK_GRID (grid),
|
||||
make_shader_stack ("Wind", "/gltransition/wind.glsl", 0, scale),
|
||||
0, 0, 1, 1);
|
||||
gtk_grid_attach (GTK_GRID (grid),
|
||||
make_shader_stack ("Radial", "/gltransition/radial.glsl", 1, scale),
|
||||
1, 0, 1, 1);
|
||||
gtk_grid_attach (GTK_GRID (grid),
|
||||
make_shader_stack ("Crosswarp", "/gltransition/crosswarp.glsl", 2, scale),
|
||||
0, 1, 1, 1);
|
||||
gtk_grid_attach (GTK_GRID (grid),
|
||||
make_shader_stack ("Kaleidoscope", "/gltransition/kaleidoscope.glsl", 3, scale),
|
||||
1, 1, 1, 1);
|
||||
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_string (provider, "button.small { padding: 0; }");
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
|
||||
g_object_set_data_full (G_OBJECT (window), "provider", provider, remove_provider);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_gltransition (GtkWidget *do_widget)
|
||||
{
|
||||
if (!demo_window)
|
||||
demo_window = create_gltransition_window (do_widget);
|
||||
|
||||
if (!gtk_widget_get_visible (demo_window))
|
||||
gtk_widget_set_visible (demo_window, TRUE);
|
||||
else
|
||||
gtk_window_destroy (GTK_WINDOW (demo_window));
|
||||
|
||||
return demo_window;
|
||||
}
|
334
demos/gtk-demo/gskshaderpaintable.c
Normal file
@@ -0,0 +1,334 @@
|
||||
/*
|
||||
* Copyright © 2020 Red Hat, Inc
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Matthias Clasen <mclasen@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "gskshaderpaintable.h"
|
||||
|
||||
/**
|
||||
* GskShaderPaintable:
|
||||
*
|
||||
* `GskShaderPaintable` is an implementation of the `GdkPaintable` interface
|
||||
* that uses a `GskGLShader` to create pixels.
|
||||
*
|
||||
* You can set the uniform data that the shader needs for rendering
|
||||
* using gsk_shader_paintable_set_args(). This function can
|
||||
* be called repeatedly to change the uniform data for the next
|
||||
* snapshot.
|
||||
*
|
||||
* Commonly, time is passed to shaders as a float uniform containing
|
||||
* the elapsed time in seconds. The convenience API
|
||||
* gsk_shader_paintable_update_time() can be called from a `GtkTickCallback`
|
||||
* to update the time based on the frame time of the frame clock.
|
||||
*/
|
||||
|
||||
|
||||
struct _GskShaderPaintable
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GskGLShader *shader;
|
||||
GBytes *args;
|
||||
|
||||
gint64 start_time;
|
||||
};
|
||||
|
||||
struct _GskShaderPaintableClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_SHADER,
|
||||
PROP_ARGS,
|
||||
|
||||
N_PROPS,
|
||||
};
|
||||
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
gsk_shader_paintable_paintable_snapshot (GdkPaintable *paintable,
|
||||
GdkSnapshot *snapshot,
|
||||
double width,
|
||||
double height)
|
||||
{
|
||||
GskShaderPaintable *self = GSK_SHADER_PAINTABLE (paintable);
|
||||
|
||||
gtk_snapshot_push_gl_shader (snapshot, self->shader, &GRAPHENE_RECT_INIT(0, 0, width, height), g_bytes_ref (self->args));
|
||||
gtk_snapshot_pop (snapshot);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_shader_paintable_paintable_init (GdkPaintableInterface *iface)
|
||||
{
|
||||
iface->snapshot = gsk_shader_paintable_paintable_snapshot;
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE_EXTENDED (GskShaderPaintable, gsk_shader_paintable, G_TYPE_OBJECT, 0,
|
||||
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
|
||||
gsk_shader_paintable_paintable_init))
|
||||
|
||||
static void
|
||||
gsk_shader_paintable_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
|
||||
{
|
||||
GskShaderPaintable *self = GSK_SHADER_PAINTABLE (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SHADER:
|
||||
gsk_shader_paintable_set_shader (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_ARGS:
|
||||
gsk_shader_paintable_set_args (self, g_value_get_boxed (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_shader_paintable_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GskShaderPaintable *self = GSK_SHADER_PAINTABLE (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SHADER:
|
||||
g_value_set_object (value, self->shader);
|
||||
break;
|
||||
|
||||
case PROP_ARGS:
|
||||
g_value_set_boxed (value, self->args);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_shader_paintable_finalize (GObject *object)
|
||||
{
|
||||
GskShaderPaintable *self = GSK_SHADER_PAINTABLE (object);
|
||||
|
||||
g_clear_pointer (&self->args, g_bytes_unref);
|
||||
g_clear_object (&self->shader);
|
||||
|
||||
G_OBJECT_CLASS (gsk_shader_paintable_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_shader_paintable_class_init (GskShaderPaintableClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->get_property = gsk_shader_paintable_get_property;
|
||||
gobject_class->set_property = gsk_shader_paintable_set_property;
|
||||
gobject_class->finalize = gsk_shader_paintable_finalize;
|
||||
|
||||
properties[PROP_SHADER] =
|
||||
g_param_spec_object ("shader", "Shader", "The shader",
|
||||
GSK_TYPE_GL_SHADER,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_ARGS] =
|
||||
g_param_spec_boxed ("args", "Arguments", "The uniform arguments",
|
||||
G_TYPE_BYTES,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_shader_paintable_init (GskShaderPaintable *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_shader_paintable_new:
|
||||
* @shader: (transfer full) (nullable): the shader to use
|
||||
* @data: (transfer full) (nullable): uniform data
|
||||
*
|
||||
* Creates a paintable that uses the @shader to create
|
||||
* pixels. The shader must not require input textures.
|
||||
* If @data is %NULL, all uniform values are set to zero.
|
||||
*
|
||||
* Returns: (transfer full): a new `GskShaderPaintable`
|
||||
*/
|
||||
GdkPaintable *
|
||||
gsk_shader_paintable_new (GskGLShader *shader,
|
||||
GBytes *data)
|
||||
{
|
||||
GdkPaintable *ret;
|
||||
|
||||
g_return_val_if_fail (shader == NULL || GSK_IS_GL_SHADER (shader), NULL);
|
||||
|
||||
if (shader && !data)
|
||||
{
|
||||
int size = gsk_gl_shader_get_args_size (shader);
|
||||
data = g_bytes_new_take (g_new0 (guchar, size), size);
|
||||
}
|
||||
|
||||
ret = g_object_new (GSK_TYPE_SHADER_PAINTABLE,
|
||||
"shader", shader,
|
||||
"args", data,
|
||||
NULL);
|
||||
|
||||
g_clear_object (&shader);
|
||||
g_clear_pointer (&data, g_bytes_unref);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_shader_paintable_set_shader:
|
||||
* @self: a `GskShaderPaintable`
|
||||
* @shader: the `GskGLShader` to use
|
||||
*
|
||||
* Sets the shader that the paintable will use
|
||||
* to create pixels. The shader must not require
|
||||
* input textures.
|
||||
*/
|
||||
void
|
||||
gsk_shader_paintable_set_shader (GskShaderPaintable *self,
|
||||
GskGLShader *shader)
|
||||
{
|
||||
g_return_if_fail (GSK_IS_SHADER_PAINTABLE (self));
|
||||
g_return_if_fail (shader == NULL || GSK_IS_GL_SHADER (shader));
|
||||
g_return_if_fail (shader == NULL || gsk_gl_shader_get_n_textures (shader) == 0);
|
||||
|
||||
if (!g_set_object (&self->shader, shader))
|
||||
return;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SHADER]);
|
||||
gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
|
||||
|
||||
g_clear_pointer (&self->args, g_bytes_unref);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_shader_paintable_get_shader:
|
||||
* @self: a `GskShaderPaintable`
|
||||
*
|
||||
* Returns the shader that the paintable is using.
|
||||
*
|
||||
* Returns: (transfer none): the `GskGLShader` that is used
|
||||
*/
|
||||
GskGLShader *
|
||||
gsk_shader_paintable_get_shader (GskShaderPaintable *self)
|
||||
{
|
||||
g_return_val_if_fail (GSK_IS_SHADER_PAINTABLE (self), NULL);
|
||||
|
||||
return self->shader;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_shader_paintable_set_args:
|
||||
* @self: a `GskShaderPaintable`
|
||||
* @data: Data block with uniform data for the shader
|
||||
*
|
||||
* Sets the uniform data that will be passed to the
|
||||
* shader when rendering. The @data will typically
|
||||
* be produced by a `GskUniformDataBuilder`.
|
||||
*
|
||||
* Note that the @data should be considered immutable
|
||||
* after it has been passed to this function.
|
||||
*/
|
||||
void
|
||||
gsk_shader_paintable_set_args (GskShaderPaintable *self,
|
||||
GBytes *data)
|
||||
{
|
||||
g_return_if_fail (GSK_IS_SHADER_PAINTABLE (self));
|
||||
g_return_if_fail (data == NULL || g_bytes_get_size (data) == gsk_gl_shader_get_args_size (self->shader));
|
||||
|
||||
g_clear_pointer (&self->args, g_bytes_unref);
|
||||
if (data)
|
||||
self->args = g_bytes_ref (data);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ARGS]);
|
||||
gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_shader_paintable_get_args:
|
||||
* @self: a `GskShaderPaintable`
|
||||
*
|
||||
* Returns the uniform data set with
|
||||
* gsk_shader_paintable_get_args().
|
||||
*
|
||||
* Returns: (transfer none): the uniform data
|
||||
*/
|
||||
GBytes *
|
||||
gsk_shader_paintable_get_args (GskShaderPaintable *self)
|
||||
{
|
||||
g_return_val_if_fail (GSK_IS_SHADER_PAINTABLE (self), NULL);
|
||||
|
||||
return self->args;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_shader_paintable_update_time:
|
||||
* @self: a `GskShaderPaintable`
|
||||
* @time_idx: the index of the uniform for time in seconds as float
|
||||
* @frame_time: the current frame time, as returned by `GdkFrameClock`
|
||||
*
|
||||
* This function is a convenience wrapper for
|
||||
* gsk_shader_paintable_set_args() that leaves all
|
||||
* uniform values unchanged, except for the uniform with
|
||||
* index @time_idx, which will be set to the elapsed time
|
||||
* in seconds, since the first call to this function.
|
||||
*
|
||||
* This function is usually called from a `GtkTickCallback`.
|
||||
*/
|
||||
void
|
||||
gsk_shader_paintable_update_time (GskShaderPaintable *self,
|
||||
int time_idx,
|
||||
gint64 frame_time)
|
||||
{
|
||||
GskShaderArgsBuilder *builder;
|
||||
GBytes *args;
|
||||
float time;
|
||||
|
||||
if (self->start_time == 0)
|
||||
self->start_time = frame_time;
|
||||
|
||||
time = (frame_time - self->start_time) / (float)G_TIME_SPAN_SECOND;
|
||||
|
||||
builder = gsk_shader_args_builder_new (self->shader, self->args);
|
||||
gsk_shader_args_builder_set_float (builder, time_idx, time);
|
||||
args = gsk_shader_args_builder_free_to_args (builder);
|
||||
|
||||
gsk_shader_paintable_set_args (self, args);
|
||||
|
||||
g_bytes_unref (args);
|
||||
}
|
43
demos/gtk-demo/gskshaderpaintable.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Matthias Clasen <mclasen@redhat.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gsk/gsk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_SHADER_PAINTABLE (gsk_shader_paintable_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GskShaderPaintable, gsk_shader_paintable, GSK, SHADER_PAINTABLE, GObject)
|
||||
|
||||
GdkPaintable * gsk_shader_paintable_new (GskGLShader *shader,
|
||||
GBytes *data);
|
||||
|
||||
GskGLShader * gsk_shader_paintable_get_shader (GskShaderPaintable *self);
|
||||
void gsk_shader_paintable_set_shader (GskShaderPaintable *self,
|
||||
GskGLShader *shader);
|
||||
GBytes * gsk_shader_paintable_get_args (GskShaderPaintable *self);
|
||||
void gsk_shader_paintable_set_args (GskShaderPaintable *self,
|
||||
GBytes *data);
|
||||
void gsk_shader_paintable_update_time (GskShaderPaintable *self,
|
||||
int time_idx,
|
||||
gint64 frame_time);
|
||||
G_END_DECLS
|
@@ -1,138 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="128"
|
||||
height="128"
|
||||
id="svg6843"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.92.4 5da689c313, 2019-01-14"
|
||||
version="1.0"
|
||||
sodipodi:docname="gtk-logo.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
inkscape:export-filename="/home/ebassi/Pictures/gtk-logo-256.png"
|
||||
inkscape:export-xdpi="192"
|
||||
inkscape:export-ydpi="192">
|
||||
<defs
|
||||
id="defs6845">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="-50 : 600 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="700 : 600 : 1"
|
||||
inkscape:persp3d-origin="300 : 400 : 1"
|
||||
id="perspective13" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="2.8284271"
|
||||
inkscape:cx="69.874353"
|
||||
inkscape:cy="64.313526"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
width="128px"
|
||||
height="128px"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1016"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid7947" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata6848">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
<dc:date />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title />
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title />
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title />
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<dc:identifier />
|
||||
<dc:source />
|
||||
<dc:relation />
|
||||
<dc:language />
|
||||
<dc:subject>
|
||||
<rdf:Bag />
|
||||
</dc:subject>
|
||||
<dc:coverage />
|
||||
<dc:description />
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title />
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<cc:license
|
||||
rdf:resource="" />
|
||||
</cc:Work>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
id="path6976"
|
||||
d="M 20.88413,30.82696 L 53.816977,55.527708 L 107.33282,39.060543 L 70.587303,17.177763 L 20.88413,30.82696 z"
|
||||
style="fill:#729fcf;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.12364459;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline" />
|
||||
<path
|
||||
id="path6978"
|
||||
d="M 22.94243,82.287118 L 20.88413,30.82696 L 53.816977,55.527708 L 53.816977,111.10486 L 22.94243,82.287118 z"
|
||||
style="fill:#e40000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.12364459;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline" />
|
||||
<path
|
||||
id="path6980"
|
||||
d="M 53.816977,111.10486 L 103.21619,90.5207 L 107.33282,39.060543 L 53.816977,55.527708 L 53.816977,111.10486 z"
|
||||
style="fill:#7fe719;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.12364459;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccc"
|
||||
id="path6982"
|
||||
d="M 23.216626,81.319479 L 70.48573,67.361442 L 103.38422,90.444516"
|
||||
style="opacity:1;fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
id="path6984"
|
||||
d="M 70.434539,17.875593 L 70.434539,66.984877"
|
||||
style="opacity:1;fill:#babdb6;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 4.8 KiB |
@@ -456,33 +456,43 @@ gtk_fishbowl_do_update (GtkFishbowl *fishbowl)
|
||||
{
|
||||
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
|
||||
GdkFrameClock *frame_clock;
|
||||
GdkFrameTimings *end;
|
||||
gint64 end_counter;
|
||||
double fps, expected_fps;
|
||||
GdkFrameTimings *start, *end;
|
||||
gint64 start_counter, end_counter;
|
||||
gint64 n_frames, expected_frames;
|
||||
gint64 start_timestamp, end_timestamp;
|
||||
gint64 interval;
|
||||
|
||||
frame_clock = gtk_widget_get_frame_clock (GTK_WIDGET (fishbowl));
|
||||
if (frame_clock == NULL)
|
||||
return;
|
||||
|
||||
fps = gdk_frame_clock_get_fps (frame_clock);
|
||||
if (fps <= 0.0)
|
||||
start_counter = gdk_frame_clock_get_history_start (frame_clock);
|
||||
end_counter = gdk_frame_clock_get_frame_counter (frame_clock);
|
||||
start = gdk_frame_clock_get_timings (frame_clock, start_counter);
|
||||
for (end = gdk_frame_clock_get_timings (frame_clock, end_counter);
|
||||
end_counter > start_counter && end != NULL && !gdk_frame_timings_get_complete (end);
|
||||
end = gdk_frame_clock_get_timings (frame_clock, end_counter))
|
||||
end_counter--;
|
||||
if (end_counter - start_counter < 4)
|
||||
return;
|
||||
|
||||
priv->framerate = fps;
|
||||
start_timestamp = gdk_frame_timings_get_presentation_time (start);
|
||||
end_timestamp = gdk_frame_timings_get_presentation_time (end);
|
||||
if (start_timestamp == 0 || end_timestamp == 0)
|
||||
{
|
||||
start_timestamp = gdk_frame_timings_get_frame_time (start);
|
||||
end_timestamp = gdk_frame_timings_get_frame_time (end);
|
||||
}
|
||||
|
||||
n_frames = end_counter - start_counter;
|
||||
priv->framerate = ((double) n_frames) * G_USEC_PER_SEC / (end_timestamp - start_timestamp);
|
||||
priv->framerate = ((int)(priv->framerate * 100))/100.0;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_FRAMERATE]);
|
||||
|
||||
if (!priv->benchmark)
|
||||
return;
|
||||
|
||||
end_counter = gdk_frame_clock_get_frame_counter (frame_clock);
|
||||
for (end = gdk_frame_clock_get_timings (frame_clock, end_counter);
|
||||
end != NULL && !gdk_frame_timings_get_complete (end);
|
||||
end = gdk_frame_clock_get_timings (frame_clock, end_counter))
|
||||
end_counter--;
|
||||
if (end == NULL)
|
||||
return;
|
||||
|
||||
interval = gdk_frame_timings_get_refresh_interval (end);
|
||||
if (interval == 0)
|
||||
{
|
||||
@@ -490,16 +500,16 @@ gtk_fishbowl_do_update (GtkFishbowl *fishbowl)
|
||||
if (interval == 0)
|
||||
return;
|
||||
}
|
||||
expected_fps = (double) G_USEC_PER_SEC / interval;
|
||||
expected_frames = round ((double) (end_timestamp - start_timestamp) / interval);
|
||||
|
||||
if (fps > (expected_fps - 1))
|
||||
if (n_frames >= expected_frames)
|
||||
{
|
||||
if (priv->last_benchmark_change > 0)
|
||||
priv->last_benchmark_change *= 2;
|
||||
else
|
||||
priv->last_benchmark_change = 1;
|
||||
}
|
||||
else if (0.95 * fps < expected_fps)
|
||||
else if (n_frames + 1 < expected_frames)
|
||||
{
|
||||
if (priv->last_benchmark_change < 0)
|
||||
priv->last_benchmark_change--;
|
||||
|
@@ -55,7 +55,7 @@ void gtk_fishbowl_set_animating (GtkFishbowl *fishbowl,
|
||||
gboolean animating);
|
||||
gboolean gtk_fishbowl_get_benchmark (GtkFishbowl *fishbowl);
|
||||
void gtk_fishbowl_set_benchmark (GtkFishbowl *fishbowl,
|
||||
gboolean benchmark);
|
||||
gboolean animating);
|
||||
double gtk_fishbowl_get_framerate (GtkFishbowl *fishbowl);
|
||||
gint64 gtk_fishbowl_get_update_delay (GtkFishbowl *fishbowl);
|
||||
void gtk_fishbowl_set_update_delay (GtkFishbowl *fishbowl,
|
||||
|
264
demos/gtk-demo/gtkshaderbin.c
Normal file
@@ -0,0 +1,264 @@
|
||||
#include "gtkshaderbin.h"
|
||||
|
||||
typedef struct {
|
||||
GskGLShader *shader;
|
||||
GtkStateFlags state;
|
||||
GtkStateFlags state_mask;
|
||||
float extra_border;
|
||||
gboolean compiled;
|
||||
gboolean compiled_ok;
|
||||
} ShaderInfo;
|
||||
|
||||
struct _GtkShaderBin
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
GtkWidget *child;
|
||||
ShaderInfo *active_shader;
|
||||
GPtrArray *shaders;
|
||||
guint tick_id;
|
||||
float time;
|
||||
float mouse_x, mouse_y;
|
||||
gint64 first_frame_time;
|
||||
};
|
||||
|
||||
struct _GtkShaderBinClass
|
||||
{
|
||||
GtkWidgetClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkShaderBin, gtk_shader_bin, GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
shader_info_free (ShaderInfo *info)
|
||||
{
|
||||
g_object_unref (info->shader);
|
||||
g_free (info);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_bin_finalize (GObject *object)
|
||||
{
|
||||
GtkShaderBin *self = GTK_SHADER_BIN (object);
|
||||
|
||||
g_ptr_array_free (self->shaders, TRUE);
|
||||
|
||||
G_OBJECT_CLASS (gtk_shader_bin_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_bin_dispose (GObject *object)
|
||||
{
|
||||
GtkShaderBin *self = GTK_SHADER_BIN (object);
|
||||
|
||||
g_clear_pointer (&self->child, gtk_widget_unparent);
|
||||
|
||||
G_OBJECT_CLASS (gtk_shader_bin_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_shader_bin_tick (GtkWidget *widget,
|
||||
GdkFrameClock *frame_clock,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkShaderBin *self = GTK_SHADER_BIN (widget);
|
||||
gint64 frame_time;
|
||||
|
||||
frame_time = gdk_frame_clock_get_frame_time (frame_clock);
|
||||
if (self->first_frame_time == 0)
|
||||
self->first_frame_time = frame_time;
|
||||
self->time = (frame_time - self->first_frame_time) / (float)G_USEC_PER_SEC;
|
||||
|
||||
gtk_widget_queue_draw (widget);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
motion_cb (GtkEventControllerMotion *controller,
|
||||
double x,
|
||||
double y,
|
||||
GtkShaderBin *self)
|
||||
{
|
||||
self->mouse_x = x;
|
||||
self->mouse_y = y;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_bin_init (GtkShaderBin *self)
|
||||
{
|
||||
GtkEventController *controller;
|
||||
self->shaders = g_ptr_array_new_with_free_func ((GDestroyNotify)shader_info_free);
|
||||
|
||||
controller = gtk_event_controller_motion_new ();
|
||||
g_signal_connect (controller, "motion", G_CALLBACK (motion_cb), self);
|
||||
gtk_widget_add_controller (GTK_WIDGET (self), controller);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_shader_bin_update_active_shader (GtkShaderBin *self)
|
||||
{
|
||||
GtkStateFlags new_state = gtk_widget_get_state_flags (GTK_WIDGET (self));
|
||||
ShaderInfo *new_shader = NULL;
|
||||
|
||||
for (int i = 0; i < self->shaders->len; i++)
|
||||
{
|
||||
ShaderInfo *info = g_ptr_array_index (self->shaders, i);
|
||||
|
||||
if ((info->state_mask & new_state) == info->state)
|
||||
{
|
||||
new_shader = info;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (self->active_shader == new_shader)
|
||||
return;
|
||||
|
||||
self->active_shader = new_shader;
|
||||
self->first_frame_time = 0;
|
||||
|
||||
if (self->active_shader)
|
||||
{
|
||||
if (self->tick_id == 0)
|
||||
self->tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (self),
|
||||
gtk_shader_bin_tick,
|
||||
NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self->tick_id != 0)
|
||||
{
|
||||
gtk_widget_remove_tick_callback (GTK_WIDGET (self), self->tick_id);
|
||||
self->tick_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_bin_state_flags_changed (GtkWidget *widget,
|
||||
GtkStateFlags previous_state_flags)
|
||||
{
|
||||
GtkShaderBin *self = GTK_SHADER_BIN (widget);
|
||||
|
||||
gtk_shader_bin_update_active_shader (self);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_shader_bin_add_shader (GtkShaderBin *self,
|
||||
GskGLShader *shader,
|
||||
GtkStateFlags state,
|
||||
GtkStateFlags state_mask,
|
||||
float extra_border)
|
||||
{
|
||||
ShaderInfo *info = g_new0 (ShaderInfo, 1);
|
||||
info->shader = g_object_ref (shader);
|
||||
info->state = state;
|
||||
info->state_mask = state_mask;
|
||||
info->extra_border = extra_border;
|
||||
|
||||
g_ptr_array_add (self->shaders, info);
|
||||
|
||||
gtk_shader_bin_update_active_shader (self);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_shader_bin_set_child (GtkShaderBin *self,
|
||||
GtkWidget *child)
|
||||
{
|
||||
|
||||
if (self->child == child)
|
||||
return;
|
||||
|
||||
g_clear_pointer (&self->child, gtk_widget_unparent);
|
||||
|
||||
if (child)
|
||||
{
|
||||
self->child = child;
|
||||
gtk_widget_set_parent (child, GTK_WIDGET (self));
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gtk_shader_bin_get_child (GtkShaderBin *self)
|
||||
{
|
||||
return self->child;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_bin_snapshot (GtkWidget *widget,
|
||||
GtkSnapshot *snapshot)
|
||||
{
|
||||
GtkShaderBin *self = GTK_SHADER_BIN (widget);
|
||||
int width, height;
|
||||
|
||||
width = gtk_widget_get_width (widget);
|
||||
height = gtk_widget_get_height (widget);
|
||||
|
||||
if (self->active_shader)
|
||||
{
|
||||
if (!self->active_shader->compiled)
|
||||
{
|
||||
GtkNative *native = gtk_widget_get_native (widget);
|
||||
GskRenderer *renderer = gtk_native_get_renderer (native);
|
||||
GError *error = NULL;
|
||||
|
||||
self->active_shader->compiled = TRUE;
|
||||
self->active_shader->compiled_ok =
|
||||
gsk_gl_shader_compile (self->active_shader->shader,
|
||||
renderer, &error);
|
||||
if (!self->active_shader->compiled_ok)
|
||||
{
|
||||
g_warning ("GtkShaderBin failed to compile shader: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
|
||||
if (self->active_shader->compiled_ok)
|
||||
{
|
||||
float border = self->active_shader->extra_border;
|
||||
graphene_vec2_t mouse;
|
||||
graphene_vec2_init (&mouse, self->mouse_x + border, self->mouse_y + border);
|
||||
gtk_snapshot_push_gl_shader (snapshot, self->active_shader->shader,
|
||||
&GRAPHENE_RECT_INIT(-border, -border, width+2*border, height+2*border),
|
||||
gsk_gl_shader_format_args (self->active_shader->shader,
|
||||
"u_time", self->time,
|
||||
"u_mouse", &mouse,
|
||||
NULL));
|
||||
gtk_widget_snapshot_child (widget, self->child, snapshot);
|
||||
gtk_snapshot_gl_shader_pop_texture (snapshot);
|
||||
gtk_snapshot_pop (snapshot);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Non-shader fallback */
|
||||
gtk_widget_snapshot_child (widget, self->child, snapshot);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_bin_class_init (GtkShaderBinClass *class)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
object_class->finalize = gtk_shader_bin_finalize;
|
||||
object_class->dispose = gtk_shader_bin_dispose;
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
|
||||
|
||||
widget_class->snapshot = gtk_shader_bin_snapshot;
|
||||
widget_class->state_flags_changed = gtk_shader_bin_state_flags_changed;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gtk_shader_bin_new (void)
|
||||
{
|
||||
GtkShaderBin *self;
|
||||
|
||||
self = g_object_new (GTK_TYPE_SHADER_BIN, NULL);
|
||||
|
||||
return GTK_WIDGET (self);
|
||||
}
|
20
demos/gtk-demo/gtkshaderbin.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_SHADER_BIN (gtk_shader_bin_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (GtkShaderBin, gtk_shader_bin, GTK, SHADER_BIN, GtkWidget)
|
||||
|
||||
GtkWidget *gtk_shader_bin_new (void);
|
||||
void gtk_shader_bin_add_shader (GtkShaderBin *self,
|
||||
GskGLShader *shader,
|
||||
GtkStateFlags state,
|
||||
GtkStateFlags state_mask,
|
||||
float extra_border);
|
||||
void gtk_shader_bin_set_child (GtkShaderBin *self,
|
||||
GtkWidget *child);
|
||||
GtkWidget *gtk_shader_bin_get_child (GtkShaderBin *self);
|
||||
|
||||
G_END_DECLS
|
361
demos/gtk-demo/gtkshaderstack.c
Normal file
@@ -0,0 +1,361 @@
|
||||
#include "gtkshaderstack.h"
|
||||
|
||||
struct _GtkShaderStack
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GskGLShader *shader;
|
||||
GPtrArray *children;
|
||||
int current;
|
||||
int next;
|
||||
gboolean backwards;
|
||||
|
||||
guint tick_id;
|
||||
float time;
|
||||
float duration;
|
||||
gint64 start_time;
|
||||
};
|
||||
|
||||
struct _GtkShaderStackClass
|
||||
{
|
||||
GtkWidgetClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
enum {
|
||||
PROP_DURATION = 1,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *properties[NUM_PROPERTIES] = { NULL };
|
||||
|
||||
G_DEFINE_TYPE (GtkShaderStack, gtk_shader_stack, GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
gtk_shader_stack_finalize (GObject *object)
|
||||
{
|
||||
GtkShaderStack *self = GTK_SHADER_STACK (object);
|
||||
|
||||
g_object_unref (self->shader);
|
||||
|
||||
G_OBJECT_CLASS (gtk_shader_stack_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
update_child_visible (GtkShaderStack *self)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < self->children->len; i++)
|
||||
{
|
||||
GtkWidget *child = g_ptr_array_index (self->children, i);
|
||||
|
||||
gtk_widget_set_child_visible (child,
|
||||
i == self->current || i == self->next);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
transition_cb (GtkWidget *widget,
|
||||
GdkFrameClock *clock,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkShaderStack *self = GTK_SHADER_STACK (widget);
|
||||
gint64 frame_time;
|
||||
|
||||
frame_time = gdk_frame_clock_get_frame_time (clock);
|
||||
|
||||
if (self->start_time == 0)
|
||||
self->start_time = frame_time;
|
||||
|
||||
self->time = (frame_time - self->start_time) / (float)G_USEC_PER_SEC;
|
||||
|
||||
gtk_widget_queue_draw (widget);
|
||||
|
||||
if (self->time >= self->duration)
|
||||
{
|
||||
self->current = self->next;
|
||||
self->next = -1;
|
||||
|
||||
update_child_visible (self);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
else
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
start_transition (GtkShaderStack *self)
|
||||
{
|
||||
self->start_time = 0;
|
||||
self->tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (self),
|
||||
transition_cb,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
stop_transition (GtkShaderStack *self)
|
||||
{
|
||||
if (self->tick_id != 0)
|
||||
{
|
||||
gtk_widget_remove_tick_callback (GTK_WIDGET (self), self->tick_id);
|
||||
self->tick_id = 0;
|
||||
}
|
||||
|
||||
if (self->next != -1)
|
||||
self->current = self->next;
|
||||
self->next = -1;
|
||||
|
||||
update_child_visible (self);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_stack_dispose (GObject *object)
|
||||
{
|
||||
GtkShaderStack *self = GTK_SHADER_STACK (object);
|
||||
|
||||
stop_transition (self);
|
||||
|
||||
g_clear_pointer (&self->children, g_ptr_array_unref);
|
||||
|
||||
G_OBJECT_CLASS (gtk_shader_stack_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_shader_stack_transition (GtkShaderStack *self,
|
||||
gboolean forward)
|
||||
{
|
||||
stop_transition (self);
|
||||
|
||||
self->backwards = !forward;
|
||||
if (self->backwards)
|
||||
self->next = (self->current + self->children->len - 1) % self->children->len;
|
||||
else
|
||||
self->next = (self->current + 1) % self->children->len;
|
||||
|
||||
update_child_visible (self);
|
||||
|
||||
start_transition (self);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_stack_init (GtkShaderStack *self)
|
||||
{
|
||||
self->children = g_ptr_array_new_with_free_func ((GDestroyNotify)gtk_widget_unparent);
|
||||
self->current = -1;
|
||||
self->next = -1;
|
||||
self->backwards = FALSE;
|
||||
self->duration = 1.0;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_stack_measure (GtkWidget *widget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural,
|
||||
int *minimum_baseline,
|
||||
int *natural_baseline)
|
||||
{
|
||||
GtkShaderStack *self = GTK_SHADER_STACK (widget);
|
||||
int i;
|
||||
|
||||
*minimum = 0;
|
||||
*natural = 0;
|
||||
|
||||
for (i = 0; i < self->children->len; i++)
|
||||
{
|
||||
GtkWidget *child = g_ptr_array_index (self->children, i);
|
||||
int child_min, child_nat;
|
||||
|
||||
if (gtk_widget_get_visible (child))
|
||||
{
|
||||
gtk_widget_measure (child, orientation, for_size, &child_min, &child_nat, NULL, NULL);
|
||||
|
||||
*minimum = MAX (*minimum, child_min);
|
||||
*natural = MAX (*natural, child_nat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_stack_size_allocate (GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int baseline)
|
||||
{
|
||||
GtkShaderStack *self = GTK_SHADER_STACK (widget);
|
||||
GtkAllocation child_allocation;
|
||||
GtkWidget *child;
|
||||
int i;
|
||||
|
||||
child_allocation.x = 0;
|
||||
child_allocation.y = 0;
|
||||
child_allocation.width = width;
|
||||
child_allocation.height = height;
|
||||
|
||||
for (i = 0; i < self->children->len; i++)
|
||||
{
|
||||
child = g_ptr_array_index (self->children, i);
|
||||
if (gtk_widget_get_visible (child))
|
||||
gtk_widget_size_allocate (child, &child_allocation, -1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_stack_snapshot (GtkWidget *widget,
|
||||
GtkSnapshot *snapshot)
|
||||
{
|
||||
GtkShaderStack *self = GTK_SHADER_STACK (widget);
|
||||
int width, height;
|
||||
GtkWidget *current, *next;
|
||||
|
||||
width = gtk_widget_get_width (widget);
|
||||
height = gtk_widget_get_height (widget);
|
||||
|
||||
current = g_ptr_array_index (self->children, self->current);
|
||||
|
||||
if (self->next == -1)
|
||||
{
|
||||
gtk_widget_snapshot_child (widget, current, snapshot);
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkNative *native = gtk_widget_get_native (widget);
|
||||
GskRenderer *renderer = gtk_native_get_renderer (native);
|
||||
float progress;
|
||||
|
||||
next = g_ptr_array_index (self->children, self->next);
|
||||
|
||||
progress = self->time / self->duration;
|
||||
|
||||
if (self->backwards)
|
||||
{
|
||||
GtkWidget *tmp = next;
|
||||
next = current;
|
||||
current = tmp;
|
||||
progress = 1. - progress;
|
||||
}
|
||||
|
||||
if (gsk_gl_shader_compile (self->shader, renderer, NULL))
|
||||
{
|
||||
gtk_snapshot_push_gl_shader (snapshot,
|
||||
self->shader,
|
||||
&GRAPHENE_RECT_INIT(0, 0, width, height),
|
||||
gsk_gl_shader_format_args (self->shader,
|
||||
"progress", progress,
|
||||
NULL));
|
||||
|
||||
gtk_widget_snapshot_child (widget, current, snapshot);
|
||||
gtk_snapshot_gl_shader_pop_texture (snapshot); /* current child */
|
||||
gtk_widget_snapshot_child (widget, next, snapshot);
|
||||
gtk_snapshot_gl_shader_pop_texture (snapshot); /* next child */
|
||||
gtk_snapshot_pop (snapshot);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Non-shader fallback */
|
||||
gtk_widget_snapshot_child (widget, current, snapshot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_stack_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkShaderStack *self = GTK_SHADER_STACK (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DURATION:
|
||||
g_value_set_float (value, self->duration);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_stack_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkShaderStack *self = GTK_SHADER_STACK (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DURATION:
|
||||
self->duration = g_value_get_float (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_stack_class_init (GtkShaderStackClass *class)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
object_class->finalize = gtk_shader_stack_finalize;
|
||||
object_class->dispose = gtk_shader_stack_dispose;
|
||||
object_class->get_property = gtk_shader_stack_get_property;
|
||||
object_class->set_property = gtk_shader_stack_set_property;
|
||||
|
||||
widget_class->snapshot = gtk_shader_stack_snapshot;
|
||||
widget_class->measure = gtk_shader_stack_measure;
|
||||
widget_class->size_allocate = gtk_shader_stack_size_allocate;
|
||||
|
||||
properties[PROP_DURATION] =
|
||||
g_param_spec_float ("duration", "Duration", "Duration",
|
||||
0.1, 3.0, 1.0,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gtk_shader_stack_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_SHADER_STACK, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_shader_stack_set_shader (GtkShaderStack *self,
|
||||
GskGLShader *shader)
|
||||
{
|
||||
g_set_object (&self->shader, shader);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_shader_stack_add_child (GtkShaderStack *self,
|
||||
GtkWidget *child)
|
||||
{
|
||||
g_ptr_array_add (self->children, child);
|
||||
gtk_widget_set_parent (child, GTK_WIDGET (self));
|
||||
gtk_widget_queue_resize (GTK_WIDGET (self));
|
||||
|
||||
if (self->current == -1)
|
||||
self->current = 0;
|
||||
else
|
||||
gtk_widget_set_child_visible (child, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_shader_stack_set_active (GtkShaderStack *self,
|
||||
int index)
|
||||
{
|
||||
stop_transition (self);
|
||||
self->current = MIN (index, self->children->len);
|
||||
update_child_visible (self);
|
||||
}
|
20
demos/gtk-demo/gtkshaderstack.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_SHADER_STACK (gtk_shader_stack_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (GtkShaderStack, gtk_shader_stack, GTK, SHADER_STACK, GtkWidget)
|
||||
|
||||
GtkWidget * gtk_shader_stack_new (void);
|
||||
void gtk_shader_stack_set_shader (GtkShaderStack *self,
|
||||
GskGLShader *shader);
|
||||
void gtk_shader_stack_add_child (GtkShaderStack *self,
|
||||
GtkWidget *child);
|
||||
void gtk_shader_stack_transition (GtkShaderStack *self,
|
||||
gboolean forward);
|
||||
void gtk_shader_stack_set_active (GtkShaderStack *self,
|
||||
int index);
|
||||
|
||||
G_END_DECLS
|
@@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
typedef struct _GdkHSLA GdkHSLA;
|
||||
|
||||
struct _GdkHSLA {
|
||||
|
@@ -13,7 +13,7 @@ static GtkWidget *window = NULL;
|
||||
static GtkWidget *scrolledwindow;
|
||||
static int selected;
|
||||
|
||||
#define N_WIDGET_TYPES 9
|
||||
#define N_WIDGET_TYPES 8
|
||||
|
||||
|
||||
static int hincrement = 5;
|
||||
@@ -73,77 +73,30 @@ populate_icons (void)
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolledwindow), grid);
|
||||
}
|
||||
|
||||
static char *content;
|
||||
static gsize content_len;
|
||||
|
||||
extern void fontify (const char *format, GtkTextBuffer *buffer);
|
||||
|
||||
enum {
|
||||
PLAIN_TEXT,
|
||||
HIGHLIGHTED_TEXT,
|
||||
UNDERLINED_TEXT,
|
||||
};
|
||||
|
||||
static void
|
||||
underlinify (GtkTextBuffer *buffer)
|
||||
{
|
||||
GtkTextTagTable *tags;
|
||||
GtkTextTag *tag[3];
|
||||
GtkTextIter start, end;
|
||||
|
||||
tags = gtk_text_buffer_get_tag_table (buffer);
|
||||
tag[0] = gtk_text_tag_new ("error");
|
||||
tag[1] = gtk_text_tag_new ("strikeout");
|
||||
tag[2] = gtk_text_tag_new ("double");
|
||||
g_object_set (tag[0], "underline", PANGO_UNDERLINE_ERROR, NULL);
|
||||
g_object_set (tag[1], "strikethrough", TRUE, NULL);
|
||||
g_object_set (tag[2],
|
||||
"underline", PANGO_UNDERLINE_DOUBLE,
|
||||
"underline-rgba", &(GdkRGBA){0., 1., 1., 1. },
|
||||
NULL);
|
||||
gtk_text_tag_table_add (tags, tag[0]);
|
||||
gtk_text_tag_table_add (tags, tag[1]);
|
||||
gtk_text_tag_table_add (tags, tag[2]);
|
||||
|
||||
gtk_text_buffer_get_start_iter (buffer, &end);
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
gtk_text_iter_forward_word_end (&end);
|
||||
start = end;
|
||||
gtk_text_iter_backward_word_start (&start);
|
||||
gtk_text_buffer_apply_tag (buffer, tag[g_random_int_range (0, 3)], &start, &end);
|
||||
if (!gtk_text_iter_forward_word_ends (&end, 3))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
populate_text (const char *resource, int kind)
|
||||
populate_text (gboolean highlight)
|
||||
{
|
||||
GtkWidget *textview;
|
||||
GtkTextBuffer *buffer;
|
||||
char *content;
|
||||
gsize content_len;
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = g_resources_lookup_data (resource, 0, NULL);
|
||||
content = g_bytes_unref_to_data (bytes, &content_len);
|
||||
if (!content)
|
||||
{
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = g_resources_lookup_data ("/sources/font_features.c", 0, NULL);
|
||||
content = g_bytes_unref_to_data (bytes, &content_len);
|
||||
}
|
||||
|
||||
buffer = gtk_text_buffer_new (NULL);
|
||||
gtk_text_buffer_set_text (buffer, content, (int)content_len);
|
||||
|
||||
switch (kind)
|
||||
{
|
||||
case HIGHLIGHTED_TEXT:
|
||||
fontify ("c", buffer);
|
||||
break;
|
||||
|
||||
case UNDERLINED_TEXT:
|
||||
underlinify (buffer);
|
||||
break;
|
||||
|
||||
case PLAIN_TEXT:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (highlight)
|
||||
fontify ("c", buffer);
|
||||
|
||||
textview = gtk_text_view_new ();
|
||||
gtk_text_view_set_buffer (GTK_TEXT_VIEW (textview), buffer);
|
||||
@@ -202,6 +155,14 @@ populate_image (void)
|
||||
{
|
||||
GtkWidget *image;
|
||||
|
||||
if (!content)
|
||||
{
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = g_resources_lookup_data ("/sources/font_features.c", 0, NULL);
|
||||
content = g_bytes_unref_to_data (bytes, &content_len);
|
||||
}
|
||||
|
||||
image = gtk_picture_new_for_resource ("/sliding_puzzle/portland-rose.jpg");
|
||||
gtk_picture_set_can_shrink (GTK_PICTURE (image), FALSE);
|
||||
|
||||
@@ -294,40 +255,35 @@ set_widget_type (int type)
|
||||
|
||||
case 1:
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Scrolling plain text");
|
||||
populate_text ("/sources/font_features.c", PLAIN_TEXT);
|
||||
populate_text (FALSE);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Scrolling colored text");
|
||||
populate_text ("/sources/font_features.c", HIGHLIGHTED_TEXT);
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Scrolling complex text");
|
||||
populate_text (TRUE);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Scrolling text with underlines");
|
||||
populate_text ("/org/gtk/Demo4/Moby-Dick.txt", UNDERLINED_TEXT);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Scrolling text with Emoji");
|
||||
populate_emoji_text ();
|
||||
break;
|
||||
|
||||
case 5:
|
||||
case 4:
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Scrolling a big image");
|
||||
populate_image ();
|
||||
break;
|
||||
|
||||
case 6:
|
||||
case 5:
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Scrolling a list");
|
||||
populate_list ();
|
||||
break;
|
||||
|
||||
case 7:
|
||||
case 6:
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Scrolling a columned list");
|
||||
populate_list2 ();
|
||||
break;
|
||||
|
||||
case 8:
|
||||
case 7:
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Scrolling a grid");
|
||||
populate_grid ();
|
||||
break;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<object class="GtkWindow" id="window">
|
||||
<property name="resizable">1</property>
|
||||
<property name="resizable">0</property>
|
||||
<property name="default-width">500</property>
|
||||
<property name="default-height">500</property>
|
||||
<child type="titlebar">
|
||||
|
@@ -14,103 +14,6 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include "demo3widget.h"
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
static GCancellable *cancellable = NULL;
|
||||
|
||||
static void
|
||||
load_texture (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cable)
|
||||
{
|
||||
GFile *file = task_data;
|
||||
GdkTexture *texture;
|
||||
GError *error = NULL;
|
||||
|
||||
texture = gdk_texture_new_from_file (file, &error);
|
||||
|
||||
if (texture)
|
||||
g_task_return_pointer (task, texture, g_object_unref);
|
||||
else
|
||||
g_task_return_error (task, error);
|
||||
}
|
||||
|
||||
static void
|
||||
set_wait_cursor (GtkWidget *widget)
|
||||
{
|
||||
gtk_widget_set_cursor_from_name (GTK_WIDGET (gtk_widget_get_root (widget)), "wait");
|
||||
}
|
||||
|
||||
static void
|
||||
unset_wait_cursor (GtkWidget *widget)
|
||||
{
|
||||
gtk_widget_set_cursor (GTK_WIDGET (gtk_widget_get_root (widget)), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
texture_loaded (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GdkTexture *texture;
|
||||
GError *error = NULL;
|
||||
|
||||
texture = g_task_propagate_pointer (G_TASK (result), &error);
|
||||
|
||||
if (!texture)
|
||||
{
|
||||
g_print ("%s\n", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!window)
|
||||
{
|
||||
g_object_unref (texture);
|
||||
return;
|
||||
}
|
||||
|
||||
unset_wait_cursor (GTK_WIDGET (data));
|
||||
|
||||
g_object_set (G_OBJECT (data), "texture", texture, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
open_file_async (GFile *file,
|
||||
GtkWidget *demo)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
set_wait_cursor (demo);
|
||||
|
||||
task = g_task_new (demo, cancellable, texture_loaded, demo);
|
||||
g_task_set_task_data (task, g_object_ref (file), g_object_unref);
|
||||
g_task_run_in_thread (task, load_texture);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
open_portland_rose (GtkWidget *button,
|
||||
GtkWidget *demo)
|
||||
{
|
||||
GFile *file;
|
||||
|
||||
file = g_file_new_for_uri ("resource:///transparent/portland-rose.jpg");
|
||||
open_file_async (file, demo);
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
static void
|
||||
open_large_image (GtkWidget *button,
|
||||
GtkWidget *demo)
|
||||
{
|
||||
GFile *file;
|
||||
|
||||
file = g_file_new_for_uri ("resource:///org/gtk/Demo4/large-image.png");
|
||||
open_file_async (file, demo);
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
static void
|
||||
file_opened (GObject *source,
|
||||
GAsyncResult *result,
|
||||
@@ -118,6 +21,7 @@ file_opened (GObject *source,
|
||||
{
|
||||
GFile *file;
|
||||
GError *error = NULL;
|
||||
GdkTexture *texture;
|
||||
|
||||
file = gtk_file_dialog_open_finish (GTK_FILE_DIALOG (source), result, &error);
|
||||
|
||||
@@ -128,9 +32,17 @@ file_opened (GObject *source,
|
||||
return;
|
||||
}
|
||||
|
||||
open_file_async (file, data);
|
||||
|
||||
texture = gdk_texture_new_from_file (file, &error);
|
||||
g_object_unref (file);
|
||||
if (!texture)
|
||||
{
|
||||
g_print ("%s\n", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_set (G_OBJECT (data), "texture", texture, NULL);
|
||||
g_object_unref (texture);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -204,26 +116,11 @@ transform_from (GBinding *binding,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
free_cancellable (gpointer data)
|
||||
{
|
||||
g_cancellable_cancel (cancellable);
|
||||
g_clear_object (&cancellable);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cancel_load (GtkWidget *widget,
|
||||
GVariant *args,
|
||||
gpointer data)
|
||||
{
|
||||
unset_wait_cursor (widget);
|
||||
g_cancellable_cancel (G_CANCELLABLE (data));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_image_scaling (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *box;
|
||||
@@ -233,7 +130,6 @@ do_image_scaling (GtkWidget *do_widget)
|
||||
GtkWidget *scale;
|
||||
GtkWidget *dropdown;
|
||||
GtkWidget *button;
|
||||
GtkEventController *controller;
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Image Scaling");
|
||||
@@ -242,20 +138,6 @@ do_image_scaling (GtkWidget *do_widget)
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
cancellable = g_cancellable_new ();
|
||||
g_object_set_data_full (G_OBJECT (window), "cancellable",
|
||||
cancellable, free_cancellable);
|
||||
|
||||
controller = gtk_shortcut_controller_new ();
|
||||
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller),
|
||||
gtk_shortcut_new (
|
||||
gtk_keyval_trigger_new (GDK_KEY_Escape, 0),
|
||||
gtk_callback_action_new (cancel_load, cancellable, NULL)
|
||||
));
|
||||
gtk_shortcut_controller_set_scope (GTK_SHORTCUT_CONTROLLER (controller),
|
||||
GTK_SHORTCUT_SCOPE_GLOBAL);
|
||||
gtk_widget_add_controller (window, controller);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_window_set_child (GTK_WINDOW (window), box);
|
||||
|
||||
@@ -274,22 +156,6 @@ do_image_scaling (GtkWidget *do_widget)
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (open_file), widget);
|
||||
gtk_box_append (GTK_BOX (box2), button);
|
||||
|
||||
button = gtk_button_new ();
|
||||
gtk_button_set_child (GTK_BUTTON (button),
|
||||
gtk_image_new_from_resource ("/org/gtk/Demo4/portland-rose-thumbnail.png"));
|
||||
gtk_widget_add_css_class (button, "image-button");
|
||||
gtk_widget_set_tooltip_text (button, "Portland Rose");
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (open_portland_rose), widget);
|
||||
gtk_box_append (GTK_BOX (box2), button);
|
||||
|
||||
button = gtk_button_new ();
|
||||
gtk_button_set_child (GTK_BUTTON (button),
|
||||
gtk_image_new_from_resource ("/org/gtk/Demo4/large-image-thumbnail.png"));
|
||||
gtk_widget_add_css_class (button, "image-button");
|
||||
gtk_widget_set_tooltip_text (button, "Large image");
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (open_large_image), widget);
|
||||
gtk_box_append (GTK_BOX (box2), button);
|
||||
|
||||
button = gtk_button_new_from_icon_name ("object-rotate-right-symbolic");
|
||||
gtk_widget_set_tooltip_text (button, "Rotate");
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (rotate), widget);
|
||||
@@ -325,9 +191,7 @@ do_image_scaling (GtkWidget *do_widget)
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_set_visible (window, TRUE);
|
||||
else
|
||||
{
|
||||
gtk_window_destroy (GTK_WINDOW (window));
|
||||
}
|
||||
gtk_window_destroy (GTK_WINDOW (window));
|
||||
|
||||
return window;
|
||||
}
|
||||
|
41
demos/gtk-demo/kaleidoscope.glsl
Normal file
@@ -0,0 +1,41 @@
|
||||
uniform float progress;
|
||||
uniform sampler2D u_texture1;
|
||||
uniform sampler2D u_texture2;
|
||||
|
||||
vec4 getFromColor (vec2 uv) {
|
||||
return GskTexture(u_texture1, uv);
|
||||
}
|
||||
|
||||
vec4 getToColor (vec2 uv) {
|
||||
return GskTexture(u_texture2, uv);
|
||||
}
|
||||
|
||||
// Source: https://gl-transitions.com/editor/kaleidoscope
|
||||
// Author: nwoeanhinnogaehr
|
||||
// License: MIT
|
||||
|
||||
const float speed = 1.0;
|
||||
const float angle = 1.0;
|
||||
const float power = 1.5;
|
||||
|
||||
vec4 transition(vec2 uv) {
|
||||
vec2 p = uv.xy / vec2(1.0).xy;
|
||||
vec2 q = p;
|
||||
float t = pow(progress, power)*speed;
|
||||
p = p -0.5;
|
||||
for (int i = 0; i < 7; i++) {
|
||||
p = vec2(sin(t)*p.x + cos(t)*p.y, sin(t)*p.y - cos(t)*p.x);
|
||||
t += angle;
|
||||
p = abs(mod(p, 2.0) - 1.0);
|
||||
}
|
||||
abs(mod(p, 1.0));
|
||||
return mix(
|
||||
mix(getFromColor(q), getToColor(q), progress),
|
||||
mix(getFromColor(p), getToColor(p), progress), 1.0 - 2.0*abs(progress - 0.5));
|
||||
}
|
||||
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv)
|
||||
{
|
||||
fragColor = transition(uv);
|
||||
}
|
@@ -40,7 +40,7 @@ get_win32_all_locales_scripts (LPWSTR locale_w, DWORD flags, LPARAM param)
|
||||
{
|
||||
wchar_t *langname_w = NULL;
|
||||
wchar_t locale_abbrev_w[9];
|
||||
gchar *langname, *locale_abbrev, *locale;
|
||||
gchar *langname, *locale_abbrev, *locale, *p;
|
||||
gint i;
|
||||
const LCTYPE iso639_lctypes[] = { LOCALE_SISO639LANGNAME, LOCALE_SISO639LANGNAME2 };
|
||||
GHashTable *ht_scripts_langs = (GHashTable *) param;
|
||||
@@ -59,6 +59,7 @@ get_win32_all_locales_scripts (LPWSTR locale_w, DWORD flags, LPARAM param)
|
||||
GetLocaleInfoEx (locale_w, LOCALE_SLOCALIZEDDISPLAYNAME, langname_w, langname_size);
|
||||
langname = g_utf16_to_utf8 (langname_w, -1, NULL, NULL, NULL);
|
||||
locale = g_utf16_to_utf8 (locale_w, -1, NULL, NULL, NULL);
|
||||
p = strchr (locale, '-');
|
||||
lang = pango_language_from_string (locale);
|
||||
if (g_hash_table_lookup (ht_scripts_langs, lang) == NULL)
|
||||
g_hash_table_insert (ht_scripts_langs, lang, langname);
|
||||
|
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 622 KiB |
@@ -355,28 +355,28 @@ create_clocks_model (void)
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
/* A bunch of timezones with GTK hackers */
|
||||
clock = gtk_clock_new ("San Francisco", g_time_zone_new_identifier ("America/Los_Angeles"));
|
||||
clock = gtk_clock_new ("San Francisco", g_time_zone_new ("America/Los_Angeles"));
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
clock = gtk_clock_new ("Xalapa", g_time_zone_new_identifier ("America/Mexico_City"));
|
||||
clock = gtk_clock_new ("Xalapa", g_time_zone_new ("America/Mexico_City"));
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
clock = gtk_clock_new ("Boston", g_time_zone_new_identifier ("America/New_York"));
|
||||
clock = gtk_clock_new ("Boston", g_time_zone_new ("America/New_York"));
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
clock = gtk_clock_new ("London", g_time_zone_new_identifier ("Europe/London"));
|
||||
clock = gtk_clock_new ("London", g_time_zone_new ("Europe/London"));
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
clock = gtk_clock_new ("Berlin", g_time_zone_new_identifier ("Europe/Berlin"));
|
||||
clock = gtk_clock_new ("Berlin", g_time_zone_new ("Europe/Berlin"));
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
clock = gtk_clock_new ("Moscow", g_time_zone_new_identifier ("Europe/Moscow"));
|
||||
clock = gtk_clock_new ("Moscow", g_time_zone_new ("Europe/Moscow"));
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
clock = gtk_clock_new ("New Delhi", g_time_zone_new_identifier ("Asia/Kolkata"));
|
||||
clock = gtk_clock_new ("New Delhi", g_time_zone_new ("Asia/Kolkata"));
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
clock = gtk_clock_new ("Shanghai", g_time_zone_new_identifier ("Asia/Shanghai"));
|
||||
clock = gtk_clock_new ("Shanghai", g_time_zone_new ("Asia/Shanghai"));
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
|
||||
|
@@ -101,7 +101,7 @@ setup_centered_label (GtkSignalListItemFactory *factory,
|
||||
GObject *listitem)
|
||||
{
|
||||
GtkWidget *label;
|
||||
label = gtk_inscription_new ("");
|
||||
label = gtk_label_new ("");
|
||||
gtk_list_item_set_child (GTK_LIST_ITEM (listitem), label);
|
||||
}
|
||||
|
||||
@@ -110,8 +110,8 @@ setup_label (GtkSignalListItemFactory *factory,
|
||||
GObject *listitem)
|
||||
{
|
||||
GtkWidget *label;
|
||||
label = gtk_inscription_new ("");
|
||||
gtk_inscription_set_xalign (GTK_INSCRIPTION (label), 0);
|
||||
label = gtk_label_new ("");
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0);
|
||||
gtk_list_item_set_child (GTK_LIST_ITEM (listitem), label);
|
||||
}
|
||||
|
||||
@@ -120,10 +120,10 @@ setup_ellipsizing_label (GtkSignalListItemFactory *factory,
|
||||
GObject *listitem)
|
||||
{
|
||||
GtkWidget *label;
|
||||
label = gtk_inscription_new ("");
|
||||
gtk_inscription_set_xalign (GTK_INSCRIPTION (label), 0);
|
||||
gtk_inscription_set_text_overflow (GTK_INSCRIPTION (label), GTK_INSCRIPTION_OVERFLOW_ELLIPSIZE_END);
|
||||
gtk_inscription_set_nat_chars (GTK_INSCRIPTION (label), 20);
|
||||
label = gtk_label_new ("");
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0);
|
||||
gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
|
||||
gtk_label_set_width_chars (GTK_LABEL (label), 20);
|
||||
gtk_list_item_set_child (GTK_LIST_ITEM (listitem), label);
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ bind_codepoint (GtkSignalListItemFactory *factory,
|
||||
codepoint = ucd_item_get_codepoint (UCD_ITEM (item));
|
||||
|
||||
g_snprintf (buffer, 10, "%#06x", codepoint);
|
||||
gtk_inscription_set_text (GTK_INSCRIPTION (label), buffer);
|
||||
gtk_label_set_label (GTK_LABEL (label), buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -160,7 +160,7 @@ bind_char (GtkSignalListItemFactory *factory,
|
||||
if (g_unichar_isprint (codepoint))
|
||||
g_unichar_to_utf8 (codepoint, buffer);
|
||||
|
||||
gtk_inscription_set_text (GTK_INSCRIPTION (label), buffer);
|
||||
gtk_label_set_label (GTK_LABEL (label), buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -175,7 +175,7 @@ bind_name (GtkSignalListItemFactory *factory,
|
||||
item = gtk_list_item_get_item (GTK_LIST_ITEM (listitem));
|
||||
name = ucd_item_get_name (UCD_ITEM (item));
|
||||
|
||||
gtk_inscription_set_text (GTK_INSCRIPTION (label), name);
|
||||
gtk_label_set_label (GTK_LABEL (label), name);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -190,7 +190,7 @@ bind_type (GtkSignalListItemFactory *factory,
|
||||
item = gtk_list_item_get_item (GTK_LIST_ITEM (listitem));
|
||||
codepoint = ucd_item_get_codepoint (UCD_ITEM (item));
|
||||
|
||||
gtk_inscription_set_text (GTK_INSCRIPTION (label), get_unicode_type_name (g_unichar_type (codepoint)));
|
||||
gtk_label_set_label (GTK_LABEL (label), get_unicode_type_name (g_unichar_type (codepoint)));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -205,7 +205,7 @@ bind_break_type (GtkSignalListItemFactory *factory,
|
||||
item = gtk_list_item_get_item (GTK_LIST_ITEM (listitem));
|
||||
codepoint = ucd_item_get_codepoint (UCD_ITEM (item));
|
||||
|
||||
gtk_inscription_set_text (GTK_INSCRIPTION (label), get_break_type_name (g_unichar_break_type (codepoint)));
|
||||
gtk_label_set_label (GTK_LABEL (label), get_break_type_name (g_unichar_break_type (codepoint)));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -220,7 +220,7 @@ bind_combining_class (GtkSignalListItemFactory *factory,
|
||||
item = gtk_list_item_get_item (GTK_LIST_ITEM (listitem));
|
||||
codepoint = ucd_item_get_codepoint (UCD_ITEM (item));
|
||||
|
||||
gtk_inscription_set_text (GTK_INSCRIPTION (label), get_combining_class_name (g_unichar_combining_class (codepoint)));
|
||||
gtk_label_set_label (GTK_LABEL (label), get_combining_class_name (g_unichar_combining_class (codepoint)));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -237,7 +237,7 @@ bind_script (GtkSignalListItemFactory *factory,
|
||||
codepoint = ucd_item_get_codepoint (UCD_ITEM (item));
|
||||
script = g_unichar_get_script (codepoint);
|
||||
|
||||
gtk_inscription_set_text (GTK_INSCRIPTION (label), get_script_name (script));
|
||||
gtk_label_set_label (GTK_LABEL (label), get_script_name (script));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -255,7 +255,7 @@ selection_changed (GObject *object,
|
||||
if (g_unichar_isprint (codepoint))
|
||||
g_unichar_to_utf8 (codepoint, buffer);
|
||||
|
||||
gtk_inscription_set_text (GTK_INSCRIPTION (label), buffer);
|
||||
gtk_label_set_label (GTK_LABEL (label), buffer);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
|
@@ -20,7 +20,6 @@
|
||||
#include "config.h"
|
||||
#include <gtk/gtk.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "demos.h"
|
||||
#include "fontify.h"
|
||||
@@ -156,6 +155,11 @@ gtk_demo_run (GtkDemo *self,
|
||||
if (result == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (GTK_IS_WINDOW (result))
|
||||
{
|
||||
gtk_window_set_transient_for (GTK_WINDOW (result), GTK_WINDOW (window));
|
||||
gtk_window_set_modal (GTK_WINDOW (result), TRUE);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -165,6 +169,10 @@ activate_about (GSimpleAction *action,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkApplication *app = user_data;
|
||||
const char *authors[] = {
|
||||
"The GTK Team",
|
||||
NULL
|
||||
};
|
||||
char *version;
|
||||
char *os_name;
|
||||
char *os_version;
|
||||
@@ -202,11 +210,11 @@ activate_about (GSimpleAction *action,
|
||||
? "GTK Demo (Development)"
|
||||
: "GTK Demo",
|
||||
"version", version,
|
||||
"copyright", "© 1997—2024 The GTK Team",
|
||||
"copyright", "© 1997—2021 The GTK Team",
|
||||
"license-type", GTK_LICENSE_LGPL_2_1,
|
||||
"website", "http://www.gtk.org",
|
||||
"comments", "Program to demonstrate GTK widgets",
|
||||
"authors", (const char *[]) { "The GTK Team", NULL },
|
||||
"authors", authors,
|
||||
"logo-icon-name", "org.gtk.Demo4",
|
||||
"title", "About GTK Demo",
|
||||
"system-information", s->str,
|
||||
@@ -823,6 +831,9 @@ static gboolean
|
||||
demo_can_run (GtkWidget *window,
|
||||
const char *name)
|
||||
{
|
||||
if (name != NULL && strcmp (name, "gltransition") == 0)
|
||||
return GSK_IS_GL_RENDERER (gtk_native_get_renderer (GTK_NATIVE (window)));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -912,34 +923,6 @@ clear_search (GtkSearchBar *bar)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
search_results_update (GObject *filter_model,
|
||||
GParamSpec *pspec,
|
||||
GtkEntry *entry)
|
||||
{
|
||||
gsize n_items = g_list_model_get_n_items (G_LIST_MODEL (filter_model));
|
||||
|
||||
if (strlen (gtk_editable_get_text (GTK_EDITABLE (entry))) > 0)
|
||||
{
|
||||
char *text;
|
||||
|
||||
if (n_items > 0)
|
||||
text = g_strdup_printf (ngettext ("%ld search result", "%ld search results", (long) n_items), (long) n_items);
|
||||
else
|
||||
text = g_strdup (_("No search results"));
|
||||
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (entry),
|
||||
GTK_ACCESSIBLE_PROPERTY_DESCRIPTION, text,
|
||||
-1);
|
||||
|
||||
g_free (text);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_accessible_reset_property (GTK_ACCESSIBLE (entry), GTK_ACCESSIBLE_PROPERTY_DESCRIPTION);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
activate (GApplication *app)
|
||||
{
|
||||
@@ -987,7 +970,6 @@ activate (GApplication *app)
|
||||
|
||||
search_entry = GTK_WIDGET (gtk_builder_get_object (builder, "search-entry"));
|
||||
g_signal_connect (search_entry, "search-changed", G_CALLBACK (demo_search_changed_cb), filter);
|
||||
g_signal_connect (filter_model, "notify::n-items", G_CALLBACK (search_results_update), search_entry);
|
||||
|
||||
selection = gtk_single_selection_new (G_LIST_MODEL (filter_model));
|
||||
g_signal_connect (selection, "notify::selected-item", G_CALLBACK (selection_cb), NULL);
|
||||
@@ -1144,8 +1126,6 @@ main (int argc, char **argv)
|
||||
};
|
||||
int i;
|
||||
|
||||
gtk_init ();
|
||||
|
||||
app = gtk_application_new ("org.gtk.Demo4", G_APPLICATION_NON_UNIQUE|G_APPLICATION_HANDLES_COMMAND_LINE);
|
||||
|
||||
g_action_map_add_action_entries (G_ACTION_MAP (app),
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<interface>
|
||||
<menu id="menubar">
|
||||
<submenu>
|
||||
<attribute name="label" translatable="yes">_File</attribute>
|
||||
<attribute name="label" translatable="yes">_Application</attribute>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_New</attribute>
|
||||
@@ -33,7 +33,7 @@
|
||||
</section>
|
||||
</submenu>
|
||||
<submenu>
|
||||
<attribute name="label" translatable="yes">_Preferences</attribute>
|
||||
<attribute name="label" translatable="yes">_File</attribute>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Prefer Dark Theme</attribute>
|
||||
|
@@ -33,6 +33,7 @@ demos = files([
|
||||
'gears.c',
|
||||
'gestures.c',
|
||||
'glarea.c',
|
||||
'gltransition.c',
|
||||
'headerbar.c',
|
||||
'hypertext.c',
|
||||
'iconscroll.c',
|
||||
@@ -116,7 +117,10 @@ extra_demo_sources = files([
|
||||
'gtkfishbowl.c',
|
||||
'fontplane.c',
|
||||
'gtkgears.c',
|
||||
'gtkshaderbin.c',
|
||||
'gtkshadertoy.c',
|
||||
'gtkshaderstack.c',
|
||||
'gskshaderpaintable.c',
|
||||
'hsla.c',
|
||||
'puzzlepiece.c',
|
||||
'bluroverlay.c',
|
||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
@@ -5,4 +5,4 @@
|
||||
#define NODE_TYPE_WIDGET (node_widget_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (NodeWidget, node_widget, NODE, WIDGET, GtkWidget)
|
||||
|
||||
GtkWidget * node_widget_new (const char *resource);
|
||||
GtkWidget * node_widget_new (const char *file);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component xmlns="https://specifications.freedesktop.org/metainfo/1.0" type="desktop">
|
||||
<component type="desktop">
|
||||
<id>org.gtk.Demo4</id>
|
||||
<launchable type="desktop-id">org.gtk.Demo4.desktop</launchable>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
|
@@ -225,8 +225,7 @@ print_ready (GObject *source,
|
||||
|
||||
if (!g_output_stream_close (stream, NULL, &error))
|
||||
{
|
||||
if (!g_error_matches (error, GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_DISMISSED))
|
||||
g_print ("Error from close: %s\n", error->message);
|
||||
g_print ("Error from close: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 3.5 KiB |
34
demos/gtk-demo/radial.glsl
Normal file
@@ -0,0 +1,34 @@
|
||||
uniform float progress;
|
||||
uniform sampler2D u_texture1;
|
||||
uniform sampler2D u_texture2;
|
||||
|
||||
vec4 getFromColor (vec2 uv) {
|
||||
return GskTexture(u_texture1, uv);
|
||||
}
|
||||
|
||||
vec4 getToColor (vec2 uv) {
|
||||
return GskTexture(u_texture2, uv);
|
||||
}
|
||||
|
||||
// Source: https://gl-transitions.com/editor/Radial
|
||||
// License: MIT
|
||||
// Author: Xaychru
|
||||
|
||||
const float smoothness = 1.0;
|
||||
|
||||
const float PI = 3.141592653589;
|
||||
|
||||
vec4 transition(vec2 p) {
|
||||
vec2 rp = p*2.-1.;
|
||||
return mix(
|
||||
getToColor(p),
|
||||
getFromColor(p),
|
||||
smoothstep(0., smoothness, atan(rp.y,rp.x) - (progress-.5) * PI * 2.5)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv)
|
||||
{
|
||||
fragColor = transition(uv);
|
||||
}
|
43
demos/gtk-demo/ripple.glsl
Normal file
@@ -0,0 +1,43 @@
|
||||
uniform float u_time;
|
||||
uniform vec2 u_mouse;
|
||||
uniform sampler2D u_texture1;
|
||||
|
||||
#define PI 3.141592654
|
||||
|
||||
float decay(float v, float t)
|
||||
{
|
||||
return v * (1.0 / (1.0 + t*t));
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv)
|
||||
{
|
||||
// Temporary to loop time every 1 sec
|
||||
float time = u_time;
|
||||
// we normalize all the effects according to the min height/width
|
||||
float size = min(resolution.x, resolution.y);
|
||||
|
||||
// Animate one wave over size in 0.3 sec
|
||||
float wave_speed = size / 0.3;
|
||||
float wave_length = size / 1.0;
|
||||
float wave_height = size * 0.1;
|
||||
|
||||
vec2 center = u_mouse;
|
||||
vec2 direction_from_center = fragCoord - center;
|
||||
float distance_from_center = length(direction_from_center);
|
||||
|
||||
/* Normalize direction */
|
||||
direction_from_center = direction_from_center / distance_from_center;
|
||||
|
||||
float propagation_length = time * wave_speed;
|
||||
|
||||
float t = (propagation_length - distance_from_center) / wave_length;
|
||||
float offset_magnitude = 0.0;
|
||||
if (t > 0.0)
|
||||
offset_magnitude = decay(wave_height * sin(t * 2.0 * PI), t);
|
||||
|
||||
vec2 offset = direction_from_center * min(offset_magnitude, distance_from_center);
|
||||
vec2 source = fragCoord - offset;
|
||||
|
||||
vec2 uv2 = source / resolution;
|
||||
fragColor = GskTexture(u_texture1, vec2(uv2.x, 1.0-uv2.y));
|
||||
}
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -120,7 +120,7 @@ create_shadertoy_window (GtkWidget *do_widget)
|
||||
gtk_box_append (GTK_BOX (box), aspect);
|
||||
|
||||
shadertoy = new_shadertoy ("/shadertoy/alienplanet.glsl");
|
||||
gtk_aspect_frame_set_child (GTK_ASPECT_FRAME (aspect), gtk_graphics_offload_new (shadertoy));
|
||||
gtk_aspect_frame_set_child (GTK_ASPECT_FRAME (aspect), shadertoy);
|
||||
|
||||
sw = gtk_scrolled_window_new ();
|
||||
gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (sw), 250);
|
||||
|
@@ -43,7 +43,7 @@ GtkListItemFactory *
|
||||
suggestion_entry_get_factory (SuggestionEntry *self);
|
||||
|
||||
void suggestion_entry_set_use_filter (SuggestionEntry *self,
|
||||
gboolean use_filter);
|
||||
gboolean use_ilter);
|
||||
gboolean suggestion_entry_get_use_filter (SuggestionEntry *self);
|
||||
|
||||
void suggestion_entry_set_expression (SuggestionEntry *self,
|
||||
|
33
demos/gtk-demo/wind.glsl
Normal file
@@ -0,0 +1,33 @@
|
||||
uniform float progress;
|
||||
uniform sampler2D u_texture1;
|
||||
uniform sampler2D u_texture2;
|
||||
|
||||
vec4 getFromColor (vec2 uv) {
|
||||
return GskTexture(u_texture1, uv);
|
||||
}
|
||||
|
||||
vec4 getToColor (vec2 uv) {
|
||||
return GskTexture(u_texture2, uv);
|
||||
}
|
||||
|
||||
// Source: https://gl-transitions.com/editor/wind
|
||||
// Author: gre
|
||||
// License: MIT
|
||||
|
||||
const float size = 0.2;
|
||||
|
||||
float rand(vec2 co) {
|
||||
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
|
||||
}
|
||||
|
||||
vec4 transition(vec2 p) {
|
||||
float r = rand(vec2(0, p.y));
|
||||
float m = smoothstep(0.0, -size, p.x*(1.0-size) + size*r - (progress * (1.0 + size)));
|
||||
return mix(getFromColor(p), getToColor(p), m);
|
||||
}
|
||||
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv)
|
||||
{
|
||||
fragColor = transition(uv);
|
||||
}
|
After Width: | Height: | Size: 5.2 KiB |
@@ -0,0 +1,136 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
sodipodi:docname="org.gtk.IconBrowser4-symbolic.svg"
|
||||
height="16.03125"
|
||||
id="svg7384"
|
||||
inkscape:version="0.92.4 5da689c313, 2019-01-14"
|
||||
version="1.1"
|
||||
width="16">
|
||||
<metadata
|
||||
id="metadata90">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>Gnome Symbolic Icon Theme</dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<sodipodi:namedview
|
||||
inkscape:bbox-paths="true"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
inkscape:current-layer="layer9"
|
||||
inkscape:cx="-2.5662459"
|
||||
inkscape:cy="11.558672"
|
||||
gridtolerance="10"
|
||||
inkscape:guide-bbox="true"
|
||||
guidetolerance="10"
|
||||
id="namedview88"
|
||||
inkscape:object-nodes="false"
|
||||
inkscape:object-paths="false"
|
||||
objecttolerance="10"
|
||||
pagecolor="#555753"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
showborder="true"
|
||||
showgrid="false"
|
||||
showguides="true"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:snap-bbox-midpoints="false"
|
||||
inkscape:snap-global="true"
|
||||
inkscape:snap-grids="true"
|
||||
inkscape:snap-nodes="true"
|
||||
inkscape:snap-others="false"
|
||||
inkscape:snap-to-guides="true"
|
||||
inkscape:window-height="1375"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:zoom="1">
|
||||
<inkscape:grid
|
||||
empspacing="2"
|
||||
enabled="true"
|
||||
id="grid4866"
|
||||
originx="-203"
|
||||
originy="-251.96875"
|
||||
snapvisiblegridlinesonly="true"
|
||||
spacingx="1"
|
||||
spacingy="1"
|
||||
type="xygrid"
|
||||
visible="true" />
|
||||
</sodipodi:namedview>
|
||||
<title
|
||||
id="title9167">Gnome Symbolic Icon Theme</title>
|
||||
<defs
|
||||
id="defs7386">
|
||||
<linearGradient
|
||||
id="linearGradient7212"
|
||||
osb:paint="solid">
|
||||
<stop
|
||||
id="stop7214"
|
||||
offset="0"
|
||||
style="stop-color:#000000;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer9"
|
||||
inkscape:label="apps"
|
||||
style="display:inline"
|
||||
transform="translate(-444.0002,35)">
|
||||
<path
|
||||
style="display:inline;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new"
|
||||
d="m 457.9846,-27.96875 v -3 h 1 l -3,-3 -3,3 h 1 v 3 z"
|
||||
id="path2809"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
<path
|
||||
style="display:inline;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new"
|
||||
d="m 451.9846,-23.96875 v 2 h 1 l 2,2 v -6 l -2,2 z"
|
||||
id="path2811"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="display:inline;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new"
|
||||
d="m 455.9846,-24.96875 v 4 c 0,0 1,-1 1,-2 0,-1.31515 -1,-2 -1,-2 z"
|
||||
id="path2813"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccsc" />
|
||||
<path
|
||||
style="display:inline;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new"
|
||||
d="m 457.9846,-25.96875 v 6 c 0,0 1,-1.94591 1,-3 0,-1.05409 -1,-3 -1,-3 z"
|
||||
id="path2815"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccsc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;enable-background:new"
|
||||
d="m 450.53751,-25.96846 c 0.24647,0 0.44708,0.19694 0.44708,0.44708 v 0.0289 c -0.008,3.05189 -2.48438,5.5237 -5.53812,5.5237 h -0.0148 c -0.25145,0 -0.44711,-0.20581 -0.44711,-0.4615 v -0.46152 -0.92302 c 0,-0.25567 0.20581,-0.4615 0.4615,-0.4615 h 0.92302 c 0.25569,0 0.46152,0.20581 0.46152,0.4615 v 0.21634 c 1.18002,-0.41715 2.10674,-1.34386 2.52389,-2.52388 h -0.21635 c -0.25566,0 -0.4615,-0.20581 -0.4615,-0.46152 v -0.92302 c 0,-0.25567 0.20581,-0.4615 0.4615,-0.4615 h 0.46152 0.4615 0.44709 0.0148 0.0148 z"
|
||||
id="rect5922-7-3" />
|
||||
<g
|
||||
id="g904-6"
|
||||
transform="matrix(0.26785369,0,0,0.26785369,436.44908,-87.00581)"
|
||||
style="display:inline;fill:#000000;fill-opacity:1;stroke-width:3.73338151;enable-background:new">
|
||||
<path
|
||||
sodipodi:nodetypes="csscccssssccccccsccsssssccccccsssss"
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.46676302;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 37,198.00759 c -2.76142,0 -5,2.23858 -5,5 0,2.76142 2.23858,5 5,5 0.89216,0 1.71236,-0.27804 2.4375,-0.6875 l 3.9375,3.6875 -3.9375,3.6875 c -0.72514,-0.40946 -1.54534,-0.6875 -2.4375,-0.6875 -2.76142,0 -5,2.23858 -5,5 0,2.76142 2.23858,5 5,5 2.76142,0 5,-2.23858 5,-5 0,-0.45832 -0.072,-0.89082 -0.1874,-1.3125 l 4.25,-4.125 8.9374,8.4375 h 3 v -2 l -16.1875,-15.6875 c 0.1156,-0.42168 0.1874,-0.85418 0.1874,-1.3125 0,-2.76142 -2.23858,-5 -5,-5 z m 0,3 c 1.10456,0 2,0.89544 2,2 0,1.10456 -0.89544,2 -2,2 -1.10456,0 -2,-0.89544 -2,-2 0,-1.10456 0.89544,-2 2,-2 z m 18,-1 -7.875,7.4375 2.625,2.5625 8.25,-8 v -2 z m -18,17 c 1.10456,0 2,0.89544 2,2 0,1.10456 -0.89544,2 -2,2 -1.10456,0 -2,-0.89544 -2,-2 0,-1.10456 0.89544,-2 2,-2 z"
|
||||
id="path1079-7" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 7.1 KiB |
517
demos/icon-browser/icon.list
Normal file
@@ -0,0 +1,517 @@
|
||||
[volume]
|
||||
Name=Volume
|
||||
Description=Icons related to audio input and output volume
|
||||
|
||||
audio-volume-high=The icon used to indicate high audio volume
|
||||
audio-volume-low=The icon used to indicate low audio volume
|
||||
audio-volume-medium=The icon used to indicate medium audio volume
|
||||
audio-volume-muted=The icon used to indicate the muted state for audio playback
|
||||
microphone-sensitivity-high=The icon used to indicate high microphone sensitivity
|
||||
microphone-sensitivity-low=The icon used to indicate low microphone sensitivity
|
||||
microphone-sensitivity-medium=The icon used to indicate medium microphone sensitivity
|
||||
microphone-sensitivity-muted=The icon used to indicate that a microphone is muted
|
||||
|
||||
[multimedia]
|
||||
Name=Multimedia
|
||||
Description=Icons related to playback of media
|
||||
|
||||
media-playlist-repeat=The icon for the repeat mode of a media player
|
||||
media-playlist-repeat-song=The icon for repeating a song in a media player
|
||||
media-playlist-shuffle=The icon for the shuffle mode of a media player
|
||||
media-playlist-consecutive=The icon for consecutive mode of a media player
|
||||
media-skip-backward=The icon for the skip backward action of a media player
|
||||
media-seek-backward=The icon for the seek backward action of a media player
|
||||
media-playback-start=The icon for the start playback action of a media player
|
||||
media-seek-forward=The icon for the seek forward action of a media player
|
||||
media-skip-forward=The icon for the skip forward action of a media player
|
||||
media-playback-stop=The icon for the stop action of a media player
|
||||
media-playback-pause=The icon for the pause action of a media player
|
||||
media-eject=The icon for the eject action of a media player or file manager
|
||||
media-record=The icon for the record action of a media application
|
||||
media-view-subtitles=The icon used to show subtitles in a media player
|
||||
|
||||
[network]
|
||||
Name=Network
|
||||
Description=Icons related to network status
|
||||
|
||||
network-transmit-receive=The icon used data is being both transmitted and received simultaneously, while the computing device is connected to a network
|
||||
network-transmit=The icon used when data is being transmitted, while the computing device is connected to a network
|
||||
network-receive=The icon used when data is being received, while the computing device is connected to a network
|
||||
network-idle=The icon used when no data is being transmitted or received, while the computing device is connected to a network
|
||||
network-error=The icon used when an error occurs trying to initialize the network connection of the computing device
|
||||
network-offline=The icon used when the computing device is disconnected from the network
|
||||
|
||||
[weather]
|
||||
Name=Weather
|
||||
Description=Icons about weather conditions
|
||||
|
||||
weather-clear=The icon used while the weather for a region is “clear skies”
|
||||
weather-clear-night=The icon used while the weather for a region is “clear skies” during the night
|
||||
weather-few-clouds=The icon used while the weather for a region is “partly cloudy”
|
||||
weather-few-clouds-night=The icon used while the weather for a region is “partly cloudy” during the night
|
||||
weather-fog=The icon used while the weather for a region is “foggy”
|
||||
weather-overcast=The icon used while the weather for a region is “overcast”
|
||||
weather-severe-alert=The icon used while a sever weather alert is in effect for a region
|
||||
weather-showers=The icon used while rain showers are occurring in a region
|
||||
weather-showers-scattered=The icon used while scattered rain showers are occurring in a region
|
||||
weather-snow=The icon used while snow showers are occurring in a region
|
||||
weather-storm=The icon used while storms are occurring in a region
|
||||
weather-windy=The icon used while the weather is windy
|
||||
|
||||
[navigation]
|
||||
Name=Navigation
|
||||
Description=Icons for navigation in the user interface of a program
|
||||
|
||||
go-first=The icon for the go to the first item in a list
|
||||
go-previous=The icon for the go to the previous item in a list
|
||||
go-next=The icon for the go to the next item in a list
|
||||
go-last=The icon for the go to the last item in a list
|
||||
go-bottom=The icon for the go to bottom of a list
|
||||
go-down=The icon for the go down in a list
|
||||
go-up=The icon for the go up in a list
|
||||
go-top=The icon for the go to the top of a list
|
||||
go-home=The icon for the go to home location
|
||||
go-jump=The icon for the jump to action
|
||||
|
||||
[editing]
|
||||
Name=Editing
|
||||
Description=Icons related to editing a document
|
||||
format-indent-less=The icon for the decrease indent formatting action
|
||||
format-indent-more=The icon for the increase indent formatting action
|
||||
format-justify-center=The icon for the center justification formatting action
|
||||
format-justify-fill=The icon for the fill justification formatting action
|
||||
format-justify-left=The icon for the left justification formatting action
|
||||
format-justify-right=The icon for the right justification action
|
||||
format-text-direction-ltr=The icon for the left-to-right text formatting action
|
||||
format-text-direction-rtl=The icon for the right-to-left formatting action
|
||||
format-text-bold=The icon for the bold text formatting action
|
||||
format-text-italic=The icon for the italic text formatting action
|
||||
format-text-underline=The icon for the underlined text formatting action
|
||||
format-text-strikethrough=The icon for the strikethrough text formatting action
|
||||
edit-clear=The icon for the clear action
|
||||
edit-clear-all=
|
||||
edit-copy=The icon for the copy action
|
||||
edit-cut=The icon for the cut action
|
||||
edit-delete=The icon for the delete action
|
||||
edit-find-replace=The icon for the find and replace action
|
||||
edit-paste=The icon for the paste action
|
||||
edit-redo=The icon for the redo action
|
||||
edit-select-all=The icon for the select all action
|
||||
edit-select=
|
||||
edit-undo=The icon for the undo action
|
||||
error-correct=
|
||||
document-properties=The icon for the action to view the properties of a document in an application
|
||||
document-new=The icon used for the action to create a new document
|
||||
document-open=The icon used for the action to open a document
|
||||
document-open-recent=The icon used for the action to open a document that was recently opened
|
||||
document-save=The icon for the save action. Should be an arrow pointing down and toward a hard disk
|
||||
document-save-as=The icon for the save as action
|
||||
document-send=The icon for the send action. Should be an arrow pointing up and away from a hard disk
|
||||
document-page-setup=The icon for the page setup action of a document editor
|
||||
document-edit=The icon for the action to edit a document
|
||||
object-flip-horizontal=The icon for the action to flip an object horizontally
|
||||
object-flip-vertical=The icon for the action to flip an object vertically
|
||||
object-rotate-left=The icon for the rotate left action performed on an object
|
||||
object-rotate-right=The icon for the rotate right action performed on an object
|
||||
insert-image=The icon for the insert image action of an application
|
||||
insert-link=The icon for the insert link action of an application
|
||||
insert-object=The icon for the insert object action of an application
|
||||
insert-text=The icon for the insert text action of an application
|
||||
accessories-text-editor=The icon used for the desktop's text editing accessory program
|
||||
|
||||
[view]
|
||||
Name=View Controls
|
||||
Description=Icons for view controls in a user interface
|
||||
|
||||
view-list=The icon used for “List“ view mode
|
||||
view-grid=The icon used for “Grid“ view mode (as opposed to “List“)
|
||||
view-fullscreen=The icon used for the “Fullscreen” item in the application's “View” menu
|
||||
view-restore=The icon used by an application for leaving the fullscreen view, and returning to a normal windowed view
|
||||
zoom-fit-best=The icon used for the “Best Fit” item in the application's “View” menu
|
||||
zoom-in=The icon used for the “Zoom in” item in the application's “View” menu
|
||||
zoom-out=The icon used for the “Zoom Out” item in the application's “View” menu
|
||||
zoom-original=The icon used for the “Original Size” item in the application's “View” menu
|
||||
view-continuous=The icon used for a continuous view mode
|
||||
view-paged=The icon used for a paged view mode (as opposed to continuous)
|
||||
view-dual=The icon used for a side-by-side view of paginated content
|
||||
view-wrapped=The icon used to indicate a wrap-around to the beginning
|
||||
view-pin=The icon used for 'pin a view'
|
||||
|
||||
[calendar]
|
||||
Name=Calendar, Tasks and Alarms
|
||||
Description=Icons related to calendars, tasks and alarms
|
||||
|
||||
task-due=The icon used when a task is due soon
|
||||
task-past-due=The icon used when a task that was due, has been left incomplete
|
||||
appointment-soon=The icon used when an appointment will occur soon
|
||||
appointment-missed=The icon used when an appointment was missed
|
||||
alarm=The icon used for alarms when a task or appointment is due
|
||||
|
||||
[communication]
|
||||
Name=Communication
|
||||
Description=Icons related email, phone calls, IM and other forms of communication
|
||||
|
||||
mail-unread=The icon used for an electronic mail that is unread
|
||||
mail-read=The icon used for an electronic mail that is read
|
||||
mail-replied=The icon used for an electronic mail that has been replied to
|
||||
mail-attachment=The icon used for an electronic mail that contains attachments
|
||||
mail-mark-important=The icon for the mark as important action of an electronic mail application
|
||||
mail-send=The icon for the send action of an electronic mail application
|
||||
mail-send-receive=The icon for the send and receive action of an electronic mail application
|
||||
call-start=The icon used for initiating or accepting a call
|
||||
call-stop=The icon used for stopping a current call
|
||||
call-missed=The icon used to show a missed call
|
||||
user-available=The icon used when a user on a chat network is available to initiate a conversation with
|
||||
user-offline=The icon used when a user on a chat network is not available
|
||||
user-idle=The icon used when a user on a chat network has not been an active participant in any chats on the network, for an extended period of time
|
||||
user-invisible=The icon used when a user is on a chat network, but is invisible to others
|
||||
user-busy=The icon used when a user is on a chat network, and has marked himself as busy
|
||||
user-away=The icon used when a user on a chat network is away from their keyboard and the chat program
|
||||
user-status-pending=The icon used when the current user status on a chat network is not known
|
||||
|
||||
[devices]
|
||||
Name=Devices and Media
|
||||
Description=Icons for devices and media
|
||||
|
||||
audio-input-microphone=The icon used for the microphone audio input device
|
||||
camera-web=The fallback icon for web cameras
|
||||
camera-photo=The icon used for a digital still camera devices
|
||||
input-keyboard=The icon used for the keyboard input device
|
||||
printer=The icon used for a printer device
|
||||
video-display=The icon used for the monitor that video gets displayed to
|
||||
computer=The icon used for the computing device as a whole
|
||||
media-optical=The icon used for physical optical media such as CD and DVD
|
||||
phone=The icon used for phone devices which support connectivity to the PC, such as VoIP, cellular, or possibly landline phones
|
||||
input-dialpad=The icon used for dialpad input devices
|
||||
input-touchpad=The icon used for touchpad input devices
|
||||
scanner=The icon used for a scanner device
|
||||
audio-card=The icon used for the audio rendering device
|
||||
input-gaming=The icon used for the gaming input device
|
||||
input-mouse=The icon used for the mousing input device
|
||||
multimedia-player=The icon used for generic multimedia playing devices
|
||||
audio-headphones=The icon used for headphones
|
||||
audio-headset=The icon used for headsets
|
||||
display-projector=The icon used for projectors
|
||||
media-removable=The icon used for generic removable media
|
||||
printer-network=The icon used for printers which are connected via the network
|
||||
audio-speakers=The icon used for speakers
|
||||
camera-video=The fallback icon for video cameras
|
||||
drive-optical=The icon used for optical media drives such as CD and DVD
|
||||
drive-removable-media=The icon used for removable media drives
|
||||
input-tablet=The icon used for graphics tablet input devices
|
||||
network-wireless=The icon used for wireless network connections
|
||||
network-wired=The icon used for wired network connections
|
||||
media-floppy=The icon used for physical floppy disk media
|
||||
media-flash=The fallback icon used for flash media, such as memory stick and SD
|
||||
|
||||
[contenttypes]
|
||||
Name=Content Types
|
||||
Description=Icons for different types of data, such as audio or image files
|
||||
|
||||
application-certificate=
|
||||
application-rss+xml=
|
||||
application-x-appliance=
|
||||
audio-x-generic=The icon used for generic audio file types
|
||||
folder=The standard folder icon used to represent directories on local filesystems, mail folders, and other hierarchical groups
|
||||
text-x-generic=The icon used for generic text file types
|
||||
video-x-generic=The icon used for generic video file types
|
||||
x-office-calendar=The icon used for generic calendar file types
|
||||
|
||||
[emotes]
|
||||
Name=Emotes
|
||||
Description=Icons for emotions that are expressed through text chat applications such as :-) or :-P in IRC or instant messengers
|
||||
|
||||
face-angel=The icon used for the 0:-) emote
|
||||
face-angry=The icon used for the X-( emote
|
||||
face-cool=The icon used for the B-) emote
|
||||
face-crying=The icon used for the :'( emote
|
||||
face-devilish=The icon used for the >:-) emote
|
||||
face-embarrassed=The icon used for the :-[ emote
|
||||
face-kiss=The icon used for the :-* emote
|
||||
face-laugh=The icon used for the :-)) emote
|
||||
face-monkey=The icon used for the :-(|) emote
|
||||
face-plain=The icon used for the :-| emote
|
||||
face-raspberry=The icon used for the :-P emote
|
||||
face-sad=The icon used for the :-( emote
|
||||
face-shutmouth=The 'shut mouth' emote
|
||||
face-sick=The icon used for the :-& emote
|
||||
face-smile=The icon used for the :-) emote
|
||||
face-smile-big=The icon used for the :-D emote
|
||||
face-smirk=The icon used for the :-! emote
|
||||
face-surprise=The icon used for the :-0 emote
|
||||
face-tired=The icon used for the |-) emote
|
||||
face-uncertain=The icon used for the :-/ emote
|
||||
face-wink=The icon used for the ;-) emote
|
||||
face-worried=The icon used for the :-S emote
|
||||
face-yawn=
|
||||
|
||||
[general]
|
||||
Name=General
|
||||
Description=Generally useful icons that don't fit in a particular category
|
||||
|
||||
edit-find=The icon for generic search actions
|
||||
content-loading=The icon used to indicate that content is loading
|
||||
open-menu=The icon used for a menu button in the header bar
|
||||
view-more=The icon used for a “View More“ action
|
||||
tab-new=The icon used for a “New Tab“ action
|
||||
bookmark-new=The icon used for creating a new bookmark
|
||||
mark-location=The icon used to mark a location on a map
|
||||
find-location=The icon used for a “Search location“ action
|
||||
send-to=The icon used for a “Send to“ action
|
||||
object-select=The icon used for generic selection actions
|
||||
window-close=The icon used for actions that close a view, such as window or tab close button
|
||||
view-refresh=The icon used for the “Refresh” item in the application's “View” menu
|
||||
process-stop=The icon used for the “Stop” action in applications with actions that may take a while to process, such as web page loading in a browser
|
||||
action-unavailable=The icon used to indicate that an action is currently unavailable, such as “Pause“ when no media is playing
|
||||
document-print=The icon for the print action of an application
|
||||
printer-printing=The icon used while a print job is successfully being spooled to a printing device
|
||||
printer-warning=The icon used when a recoverable problem occurs while attempting to printing
|
||||
printer-error=The icon used when an error occurs while attempting to print
|
||||
dialog-information=The icon used when a dialog is opened to give information to the user that may be pertinent to the requested action
|
||||
dialog-question=The icon used when a dialog is opened to ask a simple question of the user
|
||||
dialog-warning=The icon used when a dialog is opened to warn the user of impending issues with the requested action
|
||||
dialog-password=The icon used when a dialog requesting the authentication credentials for a user is opened
|
||||
dialog-error=The icon used when a dialog is opened to explain an error condition to the user
|
||||
list-add=The icon for the add to list action
|
||||
list-remove=The icon for the remove from list action
|
||||
non-starred=The icon used to indicate that an object is not 'starred'
|
||||
semi-starred=The icon used to indicate that an object has is 'half-starred'
|
||||
starred=The icon used to indicate that an object is 'starred'
|
||||
star-new=The used for the “New Star“ action
|
||||
security-low=The icon used to indicate that the security level of a connection is presumed to be insecure, either by using weak encryption, or by using a certificate that the could not be automatically verified, and which the user has not chosent to trust
|
||||
security-medium=The icon used to indicate that the security level of a connection is presumed to be secure, using strong encryption, and a certificate that could not be automatically verified, but which the user has chosen to trust
|
||||
security-high=The icon used to indicate that the security level of a connection is known to be secure, using strong encryption and a valid certificate
|
||||
user-trash=The icon for the user's “Trash” place in the file system
|
||||
user-trash-full=The icon for the user's “Trash” in the file system, when there are items in the “Trash” waiting for disposal or recovery
|
||||
emblem-system=The icon used as an emblem for directories that contain system libraries, settings, and data
|
||||
avatar-default=The generic avatar icon, which is used to represent a user that doesn't have a personalized avatar
|
||||
emblem-synchronizing=The icon used as an emblem to indicate that a synchronizing operation is in process
|
||||
emblem-shared=The icon used as an emblem for files and directories that are shared to other users
|
||||
help-browser=The icon used for the desktop's help browsing application
|
||||
|
||||
[other]
|
||||
Name=Other
|
||||
Description=Icons which have may be too specialized and not of general interest
|
||||
|
||||
changes-allow=
|
||||
changes-prevent=
|
||||
view-sort-ascending=The icon used for the “Sort Ascending” item in the application's “View” menu, or in a button for changing the sort method for a list
|
||||
view-sort-descending=The icon used for the “Sort Descending” item in the application's “View” menu, or in a button for changing the sort method for a list
|
||||
document-revert=The icon for the action of reverting to a previous version of a document
|
||||
address-book-new=The icon used for the action to create a new address book
|
||||
application-exit=The icon used for exiting an application. Typically this is seen in the application's menus as File->Quit
|
||||
appointment-new=The icon used for the action to create a new appointment in a calendaring application
|
||||
contact-new=The icon used for the action to create a new contact in an address book application
|
||||
document-print-preview=The icon for the print preview action of an application
|
||||
folder-new=The icon for creating a new folder
|
||||
help-about=The icon for the About item in the Help menu
|
||||
help-contents=The icon for Contents item in the Help menu
|
||||
help-faq=The icon for the FAQ item in the Help menu
|
||||
list-remove-all=
|
||||
mail-forward=The icon for the forward action of an electronic mail application
|
||||
mail-mark-junk=The icon for the mark as junk action of an electronic mail application
|
||||
mail-mark-notjunk=The icon for the mark as not junk action of an electronic mail application
|
||||
mail-mark-read=The icon for the mark as read action of an electronic mail application
|
||||
mail-mark-unread=The icon for the mark as unread action of an electronic mail application
|
||||
mail-message-new=The icon for the compose new mail action of an electronic mail application
|
||||
mail-reply-all=The icon for the reply to all action of an electronic mail application
|
||||
mail-reply-sender=The icon for the reply to sender action of an electronic mail application
|
||||
pan-down=
|
||||
pan-end=
|
||||
pan-start=
|
||||
pan-up=
|
||||
system-lock-screen=The icon used for the “Lock Screen” item in the desktop's panel application
|
||||
system-log-out=The icon used for the “Log Out” item in the desktop's panel application
|
||||
system-run=The icon used for the “Run Application...” item in the desktop's panel application
|
||||
system-search=The icon used for the “Search” item in the desktop's panel application
|
||||
system-reboot=The icon used for the “Reboot” item in the desktop's panel application
|
||||
system-shutdown=The icon used for the “Shutdown” item in the desktop's panel application
|
||||
tools-check-spelling=The icon used for the “Check Spelling” item in the application's “Tools” menu
|
||||
window-maximize=
|
||||
window-minimize=
|
||||
window-restore=
|
||||
window-new=The icon used for the “New Window” item in the application's “Windows” menu
|
||||
accessories-calculator=The icon used for the desktop's calculator accessory program
|
||||
accessories-character-map=The icon used for the desktop's international and extended text character accessory program
|
||||
accessories-dictionary=The icon used for the desktop's dictionary accessory program
|
||||
multimedia-volume-control=The icon used for the desktop's hardware volume control application
|
||||
preferences-desktop-accessibility=The icon used for the desktop's accessibility preferences
|
||||
preferences-desktop-display=
|
||||
preferences-desktop-font=The icon used for the desktop's font preferences
|
||||
preferences-desktop-keyboard=The icon used for the desktop's keyboard preferences
|
||||
preferences-desktop-keyboard-shortcuts=
|
||||
preferences-desktop-locale=The icon used for the desktop's locale preferences
|
||||
preferences-desktop-remote-desktop=
|
||||
preferences-desktop-multimedia=The icon used for the desktop's multimedia preferences
|
||||
preferences-desktop-screensaver=The icon used for the desktop's screen saving preferences
|
||||
preferences-desktop-theme=The icon used for the desktop's theme preferences
|
||||
preferences-desktop-wallpaper=The icon used for the desktop's wallpaper preferences
|
||||
preferences-system-privacy=
|
||||
preferences-system-windows=
|
||||
system-file-manager=The icon used for the desktop's file management application
|
||||
system-software-install=The icon used for the desktop's software installer application
|
||||
system-software-update=The icon used for the desktop's software updating application
|
||||
system-users=
|
||||
user-info=
|
||||
utilities-system-monitor=The icon used for the desktop's system resource monitor application
|
||||
utilities-terminal=The icon used for the desktop's terminal emulation application.
|
||||
application-x-addon=
|
||||
application-x-executable=The icon used for executable file types
|
||||
font-x-generic=The icon used for generic font file types
|
||||
image-x-generic=The icon used for generic image file types
|
||||
package-x-generic=The icon used for generic package file types
|
||||
text-html=The icon used for HTML text file types
|
||||
text-x-generic-template=The icon used for generic text templates
|
||||
text-x-preview=
|
||||
text-x-script=The icon used for script file types, such as shell scripts
|
||||
x-office-address-book=The icon used for generic address book file types
|
||||
x-office-document=The icon used for generic document and letter file types
|
||||
x-office-document-template=
|
||||
x-office-presentation=The icon used for generic presentation file types
|
||||
x-office-presentation-template=
|
||||
x-office-spreadsheet=The icon used for generic spreadsheet file types
|
||||
x-office-spreadsheet-template=
|
||||
x-package-repository=
|
||||
applications-accessories=The icon for the “Accessories” sub-menu of the Programs menu
|
||||
applications-development=The icon for the “Programming” sub-menu of the Programs menu
|
||||
applications-engineering=The icon for the “Engineering” sub-menu of the Programs menu
|
||||
applications-games=The icon for the “Games” sub-menu of the Programs menu
|
||||
applications-graphics=The icon for the “Graphics” sub-menu of the Programs menu
|
||||
applications-internet=The icon for the “Internet” sub-menu of the Programs menu
|
||||
applications-multimedia=The icon for the “Multimedia” sub-menu of the Programs menu
|
||||
applications-office=The icon for the “Office” sub-menu of the Programs menu
|
||||
applications-other=The icon for the “Other” sub-menu of the Programs menu
|
||||
applications-science=The icon for the “Science” sub-menu of the Programs menu
|
||||
applications-system=The icon for the “System Tools” sub-menu of the Programs menu
|
||||
applications-utilities=The icon for the “Utilities” sub-menu of the Programs menu
|
||||
preferences-desktop=The icon for the “Desktop Preferences” category
|
||||
preferences-desktop-peripherals=The icon for the “Peripherals” sub-category of the “Desktop Preferences” category
|
||||
preferences-desktop-personal=The icon for the “Personal” sub-category of the “Desktop Preferences” category
|
||||
preferences-other=The icon for the “Other” preferences category
|
||||
preferences-system=The icon for the “System Preferences” category
|
||||
preferences-system-network=The icon for the “Network” sub-category of the “System Preferences” category
|
||||
system-help=The icon for the “Help” system category
|
||||
battery=The icon used for the system battery device
|
||||
computer-apple-ipad=
|
||||
colorimeter-colorhug=
|
||||
drive-harddisk=The icon used for hard disk drives
|
||||
drive-harddisk-ieee1394=
|
||||
drive-harddisk-system=
|
||||
drive-multidisk=
|
||||
media-optical-bd=
|
||||
media-optical-cd-audio=
|
||||
media-optical-dvd=
|
||||
media-tape=The icon used for generic physical tape media
|
||||
media-zip=
|
||||
modem=The icon used for modem devices
|
||||
multimedia-player-apple-ipod-touch=
|
||||
network-vpn=
|
||||
pda=This is the fallback icon for Personal Digital Assistant devices. Primary use of this icon is for PDA devices connected to the PC. Connection medium is not an important aspect of the icon. The metaphor for this fallback icon should be a generic PDA device icon
|
||||
phone-apple-iphone=
|
||||
uninterruptible-power-supply=
|
||||
emblem-default=The icon used as an emblem to specify the default selection of a printer for example
|
||||
emblem-documents=The icon used as an emblem for the directory where a user's documents are stored
|
||||
emblem-downloads=The icon used as an emblem for the directory where a user's downloads from the internet are stored
|
||||
emblem-favorite=The icon used as an emblem for files and directories that the user marks as favorites
|
||||
emblem-generic=
|
||||
emblem-important=The icon used as an emblem for files and directories that are marked as important by the user
|
||||
emblem-mail=The icon used as an emblem to specify the directory where the user's electronic mail is stored
|
||||
emblem-new=
|
||||
emblem-ok=
|
||||
emblem-package=
|
||||
emblem-photos=The icon used as an emblem to specify the directory where the user stores photographs
|
||||
emblem-readonly=The icon used as an emblem for files and directories which can not be written to by the user
|
||||
emblem-symbolic-link=The icon used as an emblem for files and direcotires that are links to other files or directories on the filesystem
|
||||
emblem-synchronized=The icon used as an emblem for files or directories that are configured to be synchronized to another device
|
||||
emblem-unreadable=The icon used as an emblem for files and directories that are inaccessible.
|
||||
emblem-urgent=
|
||||
emblem-videos=
|
||||
emblem-web=
|
||||
folder-documents=
|
||||
folder-download=The icon representing the location in the file system where downloaded files are stored
|
||||
folder-music=
|
||||
folder-pictures=
|
||||
folder-publicshare=
|
||||
folder-remote=The icon used for normal directories on a remote filesystem
|
||||
folder-saved-search=
|
||||
folder-templates=
|
||||
folder-videos=
|
||||
network-server=The icon used for individual host machines under the “Network Servers” place in the file manager
|
||||
network-workgroup=The icon for the “Network Servers” place in the desktop's file manager, and workgroups within the network
|
||||
start-here=The icon used by the desktop's main menu for accessing places, applications, and other features
|
||||
user-bookmarks=The icon for the user's special “Bookmarks” place
|
||||
user-desktop=The icon for the special “Desktop” directory of the user
|
||||
user-home=The icon for the special “Home” directory of the user
|
||||
airplane-mode=
|
||||
battery-caution-charging=
|
||||
battery-caution=The icon used when the battery is below 40%
|
||||
battery-empty-charging=
|
||||
battery-empty=
|
||||
battery-full-charged=
|
||||
battery-full-charging=
|
||||
battery-full=
|
||||
battery-good-charging=
|
||||
battery-good=
|
||||
battery-low-charging=
|
||||
battery-low=The icon used when the battery is below 20%
|
||||
battery-missing=
|
||||
bluetooth-active=
|
||||
bluetooth-disabled=
|
||||
channel-insecure=
|
||||
channel-secure=
|
||||
computer-fail=
|
||||
display-brightness=
|
||||
keyboard-brightness=
|
||||
folder-drag-accept=The icon used for a folder while an object is being dragged onto it, that is of a type that the directory can contain
|
||||
folder-open=The icon used for folders, while their contents are being displayed within the same window. This icon would normally be shown in a tree or list view, next to the main view of a folder's contents
|
||||
folder-visiting=The icon used for folders, while their contents are being displayed in another window. This icon would typically be used when using multiple windows to navigate the hierarchy, such as in Nautilus's spatial mode
|
||||
image-loading=The icon used when another image is being loaded, such as thumnails for larger images in the file manager
|
||||
image-missing=The icon used when another image could not be loaded
|
||||
mail-signed=The icon used for an electronic mail that contains a signature
|
||||
mail-signed-verified=The icon used for an electronic mail that contains a signature which has also been verified by the security system
|
||||
network-cellular-3g=
|
||||
network-cellular-4g=
|
||||
network-cellular-edge=
|
||||
network-cellular-gprs=
|
||||
network-cellular-umts=
|
||||
network-cellular-acquiring=
|
||||
network-cellular-connected=
|
||||
network-cellular-no-route=
|
||||
network-cellular-offline=
|
||||
network-cellular-signal-excellent=
|
||||
network-cellular-signal-good=
|
||||
network-cellular-signal-ok=
|
||||
network-cellular-signal-weak=
|
||||
network-cellular-signal-none=
|
||||
network-vpn-acquiring=
|
||||
network-vpn=
|
||||
network-wired-acquiring=
|
||||
network-wired-disconnected=
|
||||
network-wired-no-route=
|
||||
network-wired-offline=
|
||||
network-wireless-acquiring=
|
||||
network-wireless-connected=
|
||||
network-wireless-encrypted=
|
||||
network-wireless-hotspot=
|
||||
network-wireless-no-route=
|
||||
network-wireless-offline=
|
||||
network-wireless-signal-excellent=
|
||||
network-wireless-signal-good=
|
||||
network-wireless-signal-ok=
|
||||
network-wireless-signal-weak=
|
||||
network-wireless-signal-none=
|
||||
rotation-allowed=
|
||||
rotation-locked=
|
||||
software-update-available=The icon used when an update is available for software installed on the computing device, through the system software update program
|
||||
software-update-urgent=The icon used when an urgent update is available through the system software update program
|
||||
sync-error=The icon used when an error occurs while attempting to synchronize data from the computing device, to another device
|
||||
sync-synchronizing=The icon used while data is successfully synchronizing to another device
|
||||
touchpad-disabled=
|
||||
trophy-bronze=
|
||||
trophy-silver=
|
||||
trophy-gold=
|
||||
night-light=
|
||||
daytime-sunrise=
|
||||
daytime-sunset=
|
||||
on=
|
||||
off=
|
7
demos/icon-browser/iconbrowser.gresource.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/org/gtk/iconbrowser/gtk">
|
||||
<file preprocess="xml-stripblanks">window.ui</file>
|
||||
<file>icon.list</file>
|
||||
</gresource>
|
||||
</gresources>
|
158
demos/icon-browser/iconbrowserapp.c
Normal file
@@ -0,0 +1,158 @@
|
||||
#include "config.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "iconbrowserapp.h"
|
||||
#include "iconbrowserwin.h"
|
||||
|
||||
#include "profile_conf.h"
|
||||
|
||||
struct _IconBrowserApp
|
||||
{
|
||||
GtkApplication parent;
|
||||
};
|
||||
|
||||
struct _IconBrowserAppClass
|
||||
{
|
||||
GtkApplicationClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(IconBrowserApp, icon_browser_app, GTK_TYPE_APPLICATION);
|
||||
|
||||
static void
|
||||
icon_browser_app_init (IconBrowserApp *app)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
quit_activated (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer app)
|
||||
{
|
||||
g_application_quit (G_APPLICATION (app));
|
||||
}
|
||||
|
||||
static void
|
||||
inspector_activated (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer app)
|
||||
{
|
||||
gtk_window_set_interactive_debugging (TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
about_activated (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkApplication *app = user_data;
|
||||
const char *authors[] = {
|
||||
"The GTK Team",
|
||||
NULL
|
||||
};
|
||||
char *icon_theme;
|
||||
char *version;
|
||||
GString *s;
|
||||
char *os_name;
|
||||
char *os_version;
|
||||
|
||||
g_object_get (gtk_settings_get_default (),
|
||||
"gtk-icon-theme-name", &icon_theme,
|
||||
NULL);
|
||||
|
||||
s = g_string_new ("");
|
||||
|
||||
os_name = g_get_os_info (G_OS_INFO_KEY_NAME);
|
||||
os_version = g_get_os_info (G_OS_INFO_KEY_VERSION_ID);
|
||||
if (os_name && os_version)
|
||||
g_string_append_printf (s, "OS\t%s %s\n\n", os_name, os_version);
|
||||
g_string_append (s, "System libraries\n");
|
||||
g_string_append_printf (s, "\tGLib\t%d.%d.%d\n",
|
||||
glib_major_version,
|
||||
glib_minor_version,
|
||||
glib_micro_version);
|
||||
g_string_append_printf (s, "\tPango\t%s\n",
|
||||
pango_version_string ());
|
||||
g_string_append_printf (s, "\tGTK \t%d.%d.%d\n",
|
||||
gtk_get_major_version (),
|
||||
gtk_get_minor_version (),
|
||||
gtk_get_micro_version ());
|
||||
g_string_append_printf (s, "\nIcon theme\n\t%s", icon_theme);
|
||||
version = g_strdup_printf ("%s%s%s\nRunning against GTK %d.%d.%d",
|
||||
PACKAGE_VERSION,
|
||||
g_strcmp0 (PROFILE, "devel") == 0 ? "-" : "",
|
||||
g_strcmp0 (PROFILE, "devel") == 0 ? VCS_TAG : "",
|
||||
gtk_get_major_version (),
|
||||
gtk_get_minor_version (),
|
||||
gtk_get_micro_version ());
|
||||
|
||||
gtk_show_about_dialog (GTK_WINDOW (gtk_application_get_active_window (app)),
|
||||
"program-name", g_strcmp0 (PROFILE, "devel") == 0
|
||||
? "GTK Icon Browser (Development)"
|
||||
: "GTK Icon Browser",
|
||||
"version", version,
|
||||
"copyright", "© 1997—2021 The GTK Team",
|
||||
"license-type", GTK_LICENSE_LGPL_2_1,
|
||||
"website", "http://www.gtk.org",
|
||||
"comments", "Program to browse themed icons",
|
||||
"authors", authors,
|
||||
"logo-icon-name", "org.gtk.IconBrowser4",
|
||||
"title", "About GTK Icon Browser",
|
||||
"system-information", s->str,
|
||||
NULL);
|
||||
|
||||
g_string_free (s, TRUE);
|
||||
g_free (version);
|
||||
g_free (icon_theme);
|
||||
g_free (os_name);
|
||||
g_free (os_version);
|
||||
}
|
||||
|
||||
static GActionEntry app_entries[] =
|
||||
{
|
||||
{ "quit", quit_activated, NULL, NULL, NULL },
|
||||
{ "inspector", inspector_activated, NULL, NULL, NULL },
|
||||
{ "about", about_activated, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static void
|
||||
icon_browser_app_startup (GApplication *app)
|
||||
{
|
||||
const char *quit_accels[2] = { "<Ctrl>Q", NULL };
|
||||
|
||||
G_APPLICATION_CLASS (icon_browser_app_parent_class)->startup (app);
|
||||
|
||||
g_action_map_add_action_entries (G_ACTION_MAP (app),
|
||||
app_entries, G_N_ELEMENTS (app_entries),
|
||||
app);
|
||||
gtk_application_set_accels_for_action (GTK_APPLICATION (app),
|
||||
"app.quit",
|
||||
quit_accels);
|
||||
}
|
||||
|
||||
static void
|
||||
icon_browser_app_activate (GApplication *app)
|
||||
{
|
||||
IconBrowserWindow *win;
|
||||
|
||||
win = icon_browser_window_new (ICON_BROWSER_APP (app));
|
||||
|
||||
if (g_strcmp0 (PROFILE, "devel") == 0)
|
||||
gtk_widget_add_css_class (GTK_WIDGET (win), "devel");
|
||||
|
||||
gtk_window_present (GTK_WINDOW (win));
|
||||
}
|
||||
|
||||
static void
|
||||
icon_browser_app_class_init (IconBrowserAppClass *class)
|
||||
{
|
||||
G_APPLICATION_CLASS (class)->startup = icon_browser_app_startup;
|
||||
G_APPLICATION_CLASS (class)->activate = icon_browser_app_activate;
|
||||
}
|
||||
|
||||
IconBrowserApp *
|
||||
icon_browser_app_new (void)
|
||||
{
|
||||
return g_object_new (ICON_BROWSER_APP_TYPE,
|
||||
"application-id", "org.gtk.IconBrowser4",
|
||||
NULL);
|
||||
}
|
15
demos/icon-browser/iconbrowserapp.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
|
||||
#define ICON_BROWSER_APP_TYPE (icon_browser_app_get_type ())
|
||||
#define ICON_BROWSER_APP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ICON_BROWSER_APP_TYPE, IconBrowserApp))
|
||||
|
||||
|
||||
typedef struct _IconBrowserApp IconBrowserApp;
|
||||
typedef struct _IconBrowserAppClass IconBrowserAppClass;
|
||||
|
||||
|
||||
GType icon_browser_app_get_type (void);
|
||||
IconBrowserApp *icon_browser_app_new (void);
|
156
demos/icon-browser/iconbrowsercontext.c
Normal file
@@ -0,0 +1,156 @@
|
||||
#include "iconbrowsercontext.h"
|
||||
|
||||
struct _IbContext
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
char *id;
|
||||
char *name;
|
||||
char *description;
|
||||
};
|
||||
|
||||
struct _IbContextClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_ID = 1,
|
||||
PROP_NAME,
|
||||
PROP_DESCRIPTION,
|
||||
PROP_NUM_PROPERTIES
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (IbContext, ib_context, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
ib_context_init (IbContext *context)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
ib_context_finalize (GObject *object)
|
||||
{
|
||||
IbContext *context = IB_CONTEXT (object);
|
||||
|
||||
g_free (context->id);
|
||||
g_free (context->name);
|
||||
g_free (context->description);
|
||||
|
||||
G_OBJECT_CLASS (ib_context_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ib_context_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
IbContext *context = IB_CONTEXT (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_ID:
|
||||
g_free (context->id);
|
||||
context->id = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
g_free (context->name);
|
||||
context->name = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_DESCRIPTION:
|
||||
g_free (context->description);
|
||||
context->description = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ib_context_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
IbContext *context = IB_CONTEXT (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_ID:
|
||||
g_value_set_string (value, context->id);
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, context->name);
|
||||
break;
|
||||
|
||||
case PROP_DESCRIPTION:
|
||||
g_value_set_string (value, context->description);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ib_context_class_init (IbContextClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
GParamSpec *pspec;
|
||||
|
||||
object_class->finalize = ib_context_finalize;
|
||||
object_class->set_property = ib_context_set_property;
|
||||
object_class->get_property = ib_context_get_property;
|
||||
|
||||
pspec = g_param_spec_string ("id", "Id", "Id",
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
g_object_class_install_property (object_class, PROP_ID, pspec);
|
||||
|
||||
pspec = g_param_spec_string ("name", "Name", "Name",
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
g_object_class_install_property (object_class, PROP_NAME, pspec);
|
||||
|
||||
pspec = g_param_spec_string ("description", "Description", "Description",
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
g_object_class_install_property (object_class, PROP_DESCRIPTION, pspec);
|
||||
}
|
||||
|
||||
IbContext *
|
||||
ib_context_new (const char *id,
|
||||
const char *name,
|
||||
const char *description)
|
||||
{
|
||||
return g_object_new (IB_TYPE_CONTEXT,
|
||||
"id", id,
|
||||
"name", name,
|
||||
"description", description,
|
||||
NULL);
|
||||
}
|
||||
|
||||
const char *
|
||||
ib_context_get_id (IbContext *context)
|
||||
{
|
||||
return context->id;
|
||||
}
|
||||
|
||||
const char *
|
||||
ib_context_get_name (IbContext *context)
|
||||
{
|
||||
return context->name;
|
||||
}
|
||||
|
||||
const char *
|
||||
ib_context_get_description (IbContext *context)
|
||||
{
|
||||
return context->description;
|
||||
}
|
14
demos/icon-browser/iconbrowsercontext.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <gtk.h>
|
||||
|
||||
#define IB_TYPE_CONTEXT (ib_context_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (IbContext, ib_context, IB, CONTEXT, GObject)
|
||||
|
||||
IbContext *ib_context_new (const char *id,
|
||||
const char *name,
|
||||
const char *description);
|
||||
|
||||
const char *ib_context_get_id (IbContext *context);
|
||||
const char *ib_context_get_name (IbContext *context);
|
||||
const char *ib_context_get_description (IbContext *context);
|
228
demos/icon-browser/iconbrowsericon.c
Normal file
@@ -0,0 +1,228 @@
|
||||
#include "iconbrowsericon.h"
|
||||
|
||||
struct _IbIcon
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
gboolean use_symbolic;
|
||||
|
||||
char *regular_name;
|
||||
char *symbolic_name;
|
||||
char *description;
|
||||
char *context;
|
||||
};
|
||||
|
||||
struct _IbIconClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_NAME = 1,
|
||||
PROP_REGULAR_NAME,
|
||||
PROP_SYMBOLIC_NAME,
|
||||
PROP_USE_SYMBOLIC,
|
||||
PROP_DESCRIPTION,
|
||||
PROP_CONTEXT,
|
||||
PROP_NUM_PROPERTIES
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (IbIcon, ib_icon, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
ib_icon_init (IbIcon *icon)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
ib_icon_finalize (GObject *object)
|
||||
{
|
||||
IbIcon *icon = IB_ICON (object);
|
||||
|
||||
g_free (icon->regular_name);
|
||||
g_free (icon->symbolic_name);
|
||||
g_free (icon->description);
|
||||
g_free (icon->context);
|
||||
|
||||
G_OBJECT_CLASS (ib_icon_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ib_icon_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
IbIcon *icon = IB_ICON (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_REGULAR_NAME:
|
||||
g_free (icon->regular_name);
|
||||
icon->regular_name = g_value_dup_string (value);
|
||||
if (!icon->use_symbolic)
|
||||
g_object_notify (object, "name");
|
||||
break;
|
||||
|
||||
case PROP_SYMBOLIC_NAME:
|
||||
g_free (icon->symbolic_name);
|
||||
icon->symbolic_name = g_value_dup_string (value);
|
||||
if (icon->use_symbolic)
|
||||
g_object_notify (object, "name");
|
||||
break;
|
||||
|
||||
case PROP_USE_SYMBOLIC:
|
||||
icon->use_symbolic = g_value_get_boolean (value);
|
||||
g_object_notify (object, "name");
|
||||
break;
|
||||
|
||||
case PROP_DESCRIPTION:
|
||||
g_free (icon->description);
|
||||
icon->description = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_CONTEXT:
|
||||
g_free (icon->context);
|
||||
icon->context = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ib_icon_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
IbIcon *icon = IB_ICON (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, ib_icon_get_name (icon));
|
||||
break;
|
||||
|
||||
case PROP_REGULAR_NAME:
|
||||
g_value_set_string (value, icon->regular_name);
|
||||
break;
|
||||
|
||||
case PROP_SYMBOLIC_NAME:
|
||||
g_value_set_string (value, icon->symbolic_name);
|
||||
break;
|
||||
|
||||
case PROP_USE_SYMBOLIC:
|
||||
g_value_set_boolean (value, icon->use_symbolic);
|
||||
break;
|
||||
|
||||
case PROP_DESCRIPTION:
|
||||
g_value_set_string (value, icon->description);
|
||||
break;
|
||||
|
||||
case PROP_CONTEXT:
|
||||
g_value_set_string (value, icon->context);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ib_icon_class_init (IbIconClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
GParamSpec *pspec;
|
||||
|
||||
object_class->finalize = ib_icon_finalize;
|
||||
object_class->set_property = ib_icon_set_property;
|
||||
object_class->get_property = ib_icon_get_property;
|
||||
|
||||
pspec = g_param_spec_string ("name", "Name", "Name",
|
||||
NULL,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
g_object_class_install_property (object_class, PROP_NAME, pspec);
|
||||
|
||||
pspec = g_param_spec_string ("regular-name", "Regular Name", "Regular Name",
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
g_object_class_install_property (object_class, PROP_REGULAR_NAME, pspec);
|
||||
|
||||
pspec = g_param_spec_string ("symbolic-name", "Symbolic Name", "Symbolic Name",
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
g_object_class_install_property (object_class, PROP_SYMBOLIC_NAME, pspec);
|
||||
|
||||
pspec = g_param_spec_boolean ("use-symbolic", "Use Symbolic", "Use Symbolic",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
g_object_class_install_property (object_class, PROP_USE_SYMBOLIC, pspec);
|
||||
|
||||
pspec = g_param_spec_string ("description", "Description", "Description",
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
g_object_class_install_property (object_class, PROP_DESCRIPTION, pspec);
|
||||
|
||||
pspec = g_param_spec_string ("context", "Context", "Context",
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
g_object_class_install_property (object_class, PROP_CONTEXT, pspec);
|
||||
}
|
||||
|
||||
IbIcon *
|
||||
ib_icon_new (const char *regular_name,
|
||||
const char *symbolic_name,
|
||||
const char *description,
|
||||
const char *context)
|
||||
{
|
||||
return g_object_new (IB_TYPE_ICON,
|
||||
"regular-name", regular_name,
|
||||
"symbolic-name", symbolic_name,
|
||||
"description", description,
|
||||
"context", context,
|
||||
NULL);
|
||||
}
|
||||
|
||||
const char *
|
||||
ib_icon_get_name (IbIcon *icon)
|
||||
{
|
||||
if (icon->use_symbolic)
|
||||
return icon->symbolic_name;
|
||||
else
|
||||
return icon->regular_name;
|
||||
}
|
||||
|
||||
const char *
|
||||
ib_icon_get_regular_name (IbIcon *icon)
|
||||
{
|
||||
return icon->regular_name;
|
||||
}
|
||||
|
||||
const char *
|
||||
ib_icon_get_symbolic_name (IbIcon *icon)
|
||||
{
|
||||
return icon->symbolic_name;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ib_icon_get_use_symbolic (IbIcon *icon)
|
||||
{
|
||||
return icon->use_symbolic;
|
||||
}
|
||||
|
||||
const char *
|
||||
ib_icon_get_description (IbIcon *icon)
|
||||
{
|
||||
return icon->description;
|
||||
}
|
||||
|
||||
const char *
|
||||
ib_icon_get_context (IbIcon *icon)
|
||||
{
|
||||
return icon->context;
|
||||
}
|
||||
|
18
demos/icon-browser/iconbrowsericon.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <gtk.h>
|
||||
|
||||
#define IB_TYPE_ICON (ib_icon_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (IbIcon, ib_icon, IB, ICON, GObject)
|
||||
|
||||
IbIcon *ib_icon_new (const char *regular_name,
|
||||
const char *symbolic_name,
|
||||
const char *description,
|
||||
const char *context);
|
||||
|
||||
const char *ib_icon_get_name (IbIcon *icon);
|
||||
const char *ib_icon_get_regular_name (IbIcon *icon);
|
||||
const char *ib_icon_get_symbolic_name (IbIcon *icon);
|
||||
gboolean ib_icon_get_use_symbolic (IbIcon *icon);
|
||||
const char *ib_icon_get_description (IbIcon *icon);
|
||||
const char *ib_icon_get_context (IbIcon *icon);
|
460
demos/icon-browser/iconbrowserwin.c
Normal file
@@ -0,0 +1,460 @@
|
||||
#include <string.h>
|
||||
#include "iconbrowserapp.h"
|
||||
#include "iconbrowserwin.h"
|
||||
#include "iconbrowsericon.h"
|
||||
#include "iconbrowsercontext.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
|
||||
struct _IconBrowserWindow
|
||||
{
|
||||
GtkApplicationWindow parent;
|
||||
|
||||
GtkWidget *symbolic_radio;
|
||||
GtkWidget *searchbar;
|
||||
GListModel *icon_filter_model;
|
||||
GListStore *icon_store;
|
||||
GListModel *context_model;
|
||||
GListStore *context_store;
|
||||
GtkFilter *name_filter;
|
||||
GtkFilter *search_mode_filter;
|
||||
GtkWidget *details;
|
||||
GtkWidget *image1;
|
||||
GtkWidget *image2;
|
||||
GtkWidget *image3;
|
||||
GtkWidget *image4;
|
||||
GtkWidget *image5;
|
||||
GtkWidget *image6;
|
||||
GtkWidget *image7;
|
||||
GtkWidget *image8;
|
||||
GtkWidget *label8;
|
||||
GtkWidget *description;
|
||||
};
|
||||
|
||||
struct _IconBrowserWindowClass
|
||||
{
|
||||
GtkApplicationWindowClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(IconBrowserWindow, icon_browser_window, GTK_TYPE_APPLICATION_WINDOW);
|
||||
|
||||
static GtkIconTheme *
|
||||
icon_browser_window_get_icon_theme (IconBrowserWindow *win)
|
||||
{
|
||||
return gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (win)));
|
||||
}
|
||||
|
||||
static void
|
||||
add_icon (IconBrowserWindow *win,
|
||||
const char *name,
|
||||
const char *description,
|
||||
const char *context)
|
||||
{
|
||||
GtkIconTheme *icon_theme = icon_browser_window_get_icon_theme (win);
|
||||
char *regular_name;
|
||||
char *symbolic_name;
|
||||
IbIcon *icon;
|
||||
|
||||
regular_name = g_strdup (name);
|
||||
if (!gtk_icon_theme_has_icon (icon_theme, regular_name))
|
||||
{
|
||||
g_free (regular_name);
|
||||
regular_name = NULL;
|
||||
}
|
||||
|
||||
symbolic_name = g_strconcat (name, "-symbolic", NULL);
|
||||
if (!gtk_icon_theme_has_icon (icon_theme, symbolic_name))
|
||||
{
|
||||
g_free (symbolic_name);
|
||||
symbolic_name = NULL;
|
||||
}
|
||||
|
||||
icon = ib_icon_new (regular_name, symbolic_name, description, context);
|
||||
g_object_bind_property (win->symbolic_radio, "active",
|
||||
icon, "use-symbolic",
|
||||
G_BINDING_DEFAULT);
|
||||
g_list_store_append (win->icon_store, icon);
|
||||
g_object_unref (icon);
|
||||
}
|
||||
|
||||
static void
|
||||
add_context (IconBrowserWindow *win,
|
||||
const char *id,
|
||||
const char *name,
|
||||
const char *description)
|
||||
{
|
||||
IbContext *context;
|
||||
|
||||
context = ib_context_new (id, name, description);
|
||||
g_list_store_append (win->context_store, context);
|
||||
g_object_unref (context);
|
||||
}
|
||||
|
||||
static void
|
||||
populate (IconBrowserWindow *win)
|
||||
{
|
||||
GFile *file;
|
||||
GKeyFile *kf;
|
||||
char *data;
|
||||
gsize length;
|
||||
char **groups;
|
||||
int i;
|
||||
|
||||
file = g_file_new_for_uri ("resource:/org/gtk/iconbrowser/gtk/icon.list");
|
||||
g_file_load_contents (file, NULL, &data, &length, NULL, NULL);
|
||||
|
||||
kf = g_key_file_new ();
|
||||
g_key_file_load_from_data (kf, data, length, G_KEY_FILE_NONE, NULL);
|
||||
|
||||
groups = g_key_file_get_groups (kf, &length);
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
const char *context;
|
||||
const char *name;
|
||||
const char *description;
|
||||
char **keys;
|
||||
gsize len;
|
||||
int j;
|
||||
|
||||
context = groups[i];
|
||||
name = g_key_file_get_string (kf, context, "Name", NULL);
|
||||
description = g_key_file_get_string (kf, context, "Description", NULL);
|
||||
add_context (win, context, name, description);
|
||||
|
||||
keys = g_key_file_get_keys (kf, context, &len, NULL);
|
||||
for (j = 0; j < len; j++)
|
||||
{
|
||||
const char *key = keys[j];
|
||||
const char *value;
|
||||
|
||||
if (strcmp (key, "Name") == 0 || strcmp (key, "Description") == 0)
|
||||
continue;
|
||||
|
||||
value = g_key_file_get_string (kf, context, key, NULL);
|
||||
|
||||
add_icon (win, key, value, context);
|
||||
}
|
||||
g_strfreev (keys);
|
||||
}
|
||||
g_strfreev (groups);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
filter_by_icon_name (gpointer item,
|
||||
gpointer data)
|
||||
{
|
||||
return ib_icon_get_name (IB_ICON (item)) != NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
symbolic_toggled (IconBrowserWindow *win)
|
||||
{
|
||||
gtk_filter_changed (win->name_filter, GTK_FILTER_CHANGE_DIFFERENT);
|
||||
}
|
||||
|
||||
static void
|
||||
copy_to_clipboard (GtkButton *button,
|
||||
IconBrowserWindow *win)
|
||||
{
|
||||
GdkClipboard *clipboard;
|
||||
|
||||
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (win));
|
||||
gdk_clipboard_set_text (clipboard, gtk_window_get_title (GTK_WINDOW (win->details)));
|
||||
}
|
||||
|
||||
static void
|
||||
set_image (GtkWidget *image, const char *name, int size)
|
||||
{
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (image), name);
|
||||
gtk_image_set_pixel_size (GTK_IMAGE (image), size);
|
||||
}
|
||||
|
||||
static void
|
||||
item_activated (GtkGridView *view,
|
||||
guint position,
|
||||
IconBrowserWindow *win)
|
||||
{
|
||||
GListModel *model = G_LIST_MODEL (gtk_grid_view_get_model (view));
|
||||
IbIcon *icon = g_list_model_get_item (model, position);
|
||||
const char *name;
|
||||
const char *description;
|
||||
gboolean symbolic;
|
||||
|
||||
name = ib_icon_get_name (icon);
|
||||
description = ib_icon_get_description (icon);
|
||||
symbolic = ib_icon_get_use_symbolic (icon);
|
||||
|
||||
gtk_window_set_title (GTK_WINDOW (win->details), name);
|
||||
set_image (win->image1, name, 8);
|
||||
set_image (win->image2, name, 16);
|
||||
set_image (win->image3, name, 18);
|
||||
set_image (win->image4, name, 24);
|
||||
set_image (win->image5, name, 32);
|
||||
set_image (win->image6, name, 48);
|
||||
set_image (win->image7, name, 64);
|
||||
gtk_widget_set_visible (win->image8, symbolic);
|
||||
gtk_widget_set_visible (win->label8, symbolic);
|
||||
if (symbolic)
|
||||
set_image (win->image8, name, 64);
|
||||
gtk_widget_set_visible (win->description, description && description[0]);
|
||||
if (description && description[0])
|
||||
gtk_label_set_text (GTK_LABEL (win->description), description);
|
||||
|
||||
gtk_window_present (GTK_WINDOW (win->details));
|
||||
|
||||
g_object_unref (icon);
|
||||
}
|
||||
|
||||
static GdkPaintable *
|
||||
get_image_paintable (GtkImage *image)
|
||||
{
|
||||
const char *icon_name;
|
||||
GtkIconTheme *icon_theme;
|
||||
GtkIconPaintable *icon;
|
||||
int size;
|
||||
|
||||
switch (gtk_image_get_storage_type (image))
|
||||
{
|
||||
case GTK_IMAGE_PAINTABLE:
|
||||
return g_object_ref (gtk_image_get_paintable (image));
|
||||
case GTK_IMAGE_ICON_NAME:
|
||||
icon_name = gtk_image_get_icon_name (image);
|
||||
size = gtk_image_get_pixel_size (image);
|
||||
icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (image)));
|
||||
icon = gtk_icon_theme_lookup_icon (icon_theme,
|
||||
icon_name,
|
||||
NULL,
|
||||
size, 1,
|
||||
gtk_widget_get_direction (GTK_WIDGET (image)),
|
||||
0);
|
||||
if (icon == NULL)
|
||||
{
|
||||
g_print ("no icon for %s\n", icon_name);
|
||||
return NULL;
|
||||
}
|
||||
return GDK_PAINTABLE (icon);
|
||||
case GTK_IMAGE_GICON:
|
||||
case GTK_IMAGE_EMPTY:
|
||||
default:
|
||||
g_warning ("Image storage type %d not handled",
|
||||
gtk_image_get_storage_type (image));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
drag_begin (GtkDragSource *source,
|
||||
GdkDrag *drag,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GdkPaintable *paintable;
|
||||
|
||||
paintable = get_image_paintable (GTK_IMAGE (widget));
|
||||
if (paintable)
|
||||
{
|
||||
int w, h;
|
||||
|
||||
w = gdk_paintable_get_intrinsic_width (paintable);
|
||||
h = gdk_paintable_get_intrinsic_height (paintable);
|
||||
gtk_drag_source_set_icon (source, paintable, w, h);
|
||||
g_object_unref (paintable);
|
||||
}
|
||||
}
|
||||
|
||||
static GdkContentProvider *
|
||||
drag_prepare_texture (GtkDragSource *source,
|
||||
double x,
|
||||
double y,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (widget));
|
||||
GtkSnapshot *snapshot;
|
||||
double width, height;
|
||||
GskRenderNode *node;
|
||||
GskRenderer *renderer;
|
||||
GdkTexture *texture;
|
||||
GdkContentProvider *ret;
|
||||
|
||||
if (!GDK_IS_PAINTABLE (paintable))
|
||||
return NULL;
|
||||
|
||||
snapshot = gtk_snapshot_new ();
|
||||
width = gdk_paintable_get_intrinsic_width (paintable);
|
||||
height = gdk_paintable_get_intrinsic_height (paintable);
|
||||
gdk_paintable_snapshot (paintable, snapshot, width, height);
|
||||
node = gtk_snapshot_free_to_node (snapshot);
|
||||
|
||||
renderer = gtk_native_get_renderer (gtk_widget_get_native (widget));
|
||||
texture = gsk_renderer_render_texture (renderer, node, &GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
|
||||
ret = gdk_content_provider_new_typed (GDK_TYPE_TEXTURE, texture);
|
||||
|
||||
g_object_unref (texture);
|
||||
gsk_render_node_unref (node);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GdkContentProvider *
|
||||
drag_prepare_file (GtkDragSource *source,
|
||||
double x,
|
||||
double y,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GdkContentProvider *content;
|
||||
GtkIconTheme *icon_theme;
|
||||
const char *name;
|
||||
GtkIconPaintable *info;
|
||||
|
||||
name = gtk_image_get_icon_name (GTK_IMAGE (widget));
|
||||
icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (widget));
|
||||
|
||||
info = gtk_icon_theme_lookup_icon (icon_theme,
|
||||
name,
|
||||
NULL,
|
||||
32, 1,
|
||||
gtk_widget_get_direction (widget),
|
||||
0);
|
||||
content = gdk_content_provider_new_typed (G_TYPE_FILE, gtk_icon_paintable_get_file (info));
|
||||
g_object_unref (info);
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
static void
|
||||
setup_image_dnd (GtkWidget *image)
|
||||
{
|
||||
GtkDragSource *source;
|
||||
|
||||
source = gtk_drag_source_new ();
|
||||
g_signal_connect (source, "prepare", G_CALLBACK (drag_prepare_texture), image);
|
||||
g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image);
|
||||
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (source));
|
||||
}
|
||||
|
||||
static void
|
||||
setup_scalable_image_dnd (GtkWidget *image)
|
||||
{
|
||||
GtkDragSource *source;
|
||||
|
||||
source = gtk_drag_source_new ();
|
||||
g_signal_connect (source, "prepare", G_CALLBACK (drag_prepare_file), image);
|
||||
g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image);
|
||||
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (source));
|
||||
}
|
||||
|
||||
static void
|
||||
search_mode_toggled (GtkSearchBar *searchbar,
|
||||
GParamSpec *pspec,
|
||||
IconBrowserWindow *win)
|
||||
{
|
||||
if (gtk_search_bar_get_search_mode (searchbar))
|
||||
gtk_single_selection_set_selected (GTK_SINGLE_SELECTION (win->context_model), GTK_INVALID_LIST_POSITION);
|
||||
else if (gtk_single_selection_get_selected (GTK_SINGLE_SELECTION (win->context_model)) == GTK_INVALID_LIST_POSITION)
|
||||
gtk_single_selection_set_selected (GTK_SINGLE_SELECTION (win->context_model), 0);
|
||||
|
||||
gtk_filter_changed (win->search_mode_filter, GTK_FILTER_CHANGE_DIFFERENT);
|
||||
}
|
||||
|
||||
static void
|
||||
selected_name_changed (GtkSingleSelection *selection,
|
||||
GParamSpec *pspec,
|
||||
IconBrowserWindow *win)
|
||||
{
|
||||
if (gtk_single_selection_get_selected (selection) != GTK_INVALID_LIST_POSITION)
|
||||
gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (win->searchbar), FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
icon_browser_window_init (IconBrowserWindow *win)
|
||||
{
|
||||
GtkFilter *filter;
|
||||
|
||||
gtk_widget_init_template (GTK_WIDGET (win));
|
||||
|
||||
setup_image_dnd (win->image1);
|
||||
setup_image_dnd (win->image2);
|
||||
setup_image_dnd (win->image3);
|
||||
setup_image_dnd (win->image4);
|
||||
setup_image_dnd (win->image5);
|
||||
setup_image_dnd (win->image6);
|
||||
setup_image_dnd (win->image7);
|
||||
setup_scalable_image_dnd (win->image8);
|
||||
|
||||
gtk_window_set_transient_for (GTK_WINDOW (win->details), GTK_WINDOW (win));
|
||||
gtk_search_bar_set_key_capture_widget (GTK_SEARCH_BAR (win->searchbar), GTK_WIDGET (win));
|
||||
|
||||
populate (win);
|
||||
|
||||
filter = gtk_filter_list_model_get_filter (GTK_FILTER_LIST_MODEL (win->icon_filter_model));
|
||||
|
||||
win->name_filter = GTK_FILTER (gtk_custom_filter_new (filter_by_icon_name, NULL, NULL));
|
||||
|
||||
gtk_multi_filter_append (GTK_MULTI_FILTER (filter), g_object_ref (win->name_filter));
|
||||
|
||||
g_signal_connect (win->searchbar, "notify::search-mode-enabled", G_CALLBACK (search_mode_toggled), win);
|
||||
g_signal_connect (win->context_model, "notify::selected", G_CALLBACK (selected_name_changed), win);
|
||||
}
|
||||
|
||||
static void
|
||||
icon_browser_window_dispose (GObject *object)
|
||||
{
|
||||
gtk_widget_dispose_template (GTK_WIDGET (object), ICON_BROWSER_WINDOW_TYPE);
|
||||
|
||||
G_OBJECT_CLASS (icon_browser_window_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
icon_browser_window_finalize (GObject *object)
|
||||
{
|
||||
IconBrowserWindow *win = ICON_BROWSER_WINDOW (object);
|
||||
|
||||
g_clear_object (&win->name_filter);
|
||||
|
||||
G_OBJECT_CLASS (icon_browser_window_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
icon_browser_window_class_init (IconBrowserWindowClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
object_class->dispose = icon_browser_window_dispose;
|
||||
object_class->finalize = icon_browser_window_finalize;
|
||||
|
||||
g_type_ensure (IB_TYPE_ICON);
|
||||
g_type_ensure (IB_TYPE_CONTEXT);
|
||||
|
||||
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
|
||||
"/org/gtk/iconbrowser/gtk/window.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, symbolic_radio);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, searchbar);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, icon_store);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, icon_filter_model);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, context_model);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, context_store);
|
||||
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, details);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image1);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image2);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image3);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image4);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image5);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image6);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image7);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image8);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, label8);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, description);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, search_mode_filter);
|
||||
|
||||
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), item_activated);
|
||||
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), copy_to_clipboard);
|
||||
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), symbolic_toggled);
|
||||
}
|
||||
|
||||
IconBrowserWindow *
|
||||
icon_browser_window_new (IconBrowserApp *app)
|
||||
{
|
||||
return g_object_new (ICON_BROWSER_WINDOW_TYPE, "application", app, NULL);
|
||||
}
|