Compare commits
165 Commits
3.98.2
...
wip/matthi
Author | SHA1 | Date | |
---|---|---|---|
|
11eb6e97c0 | ||
|
431a28b06b | ||
|
9788f9c493 | ||
|
a7d81347d2 | ||
|
4ac7108128 | ||
|
91f77ee1d1 | ||
|
58a3396560 | ||
|
e06a6241a6 | ||
|
9201399a0d | ||
|
e0236b401a | ||
|
564a01ffee | ||
|
1b0640970b | ||
|
89680a7410 | ||
|
43c7270f58 | ||
|
657e376b64 | ||
|
d7cb078947 | ||
|
630778bbed | ||
|
a1ebd0c3b1 | ||
|
a821aff383 | ||
|
21603f683a | ||
|
3e4b6b728e | ||
|
05e7f96e00 | ||
|
ea18bae6cc | ||
|
34c27ffe4a | ||
|
6e2324ea9c | ||
|
36e798e8a5 | ||
|
b5fd69b69a | ||
|
54159c2a15 | ||
|
84f398531d | ||
|
c860406797 | ||
|
c307850dcf | ||
|
2b2aef72d9 | ||
|
9f0d107a18 | ||
|
5470a3c6b4 | ||
|
2b733dfa08 | ||
|
e5e376ff7b | ||
|
71ace6763d | ||
|
ad6a6cd2f3 | ||
|
4d565a35aa | ||
|
7c44a95cea | ||
|
cb74edc958 | ||
|
65b638ac7d | ||
|
f6355cca76 | ||
|
18eb44ee6b | ||
|
9bfe96e397 | ||
|
a9d3dace47 | ||
|
ec1d462e1f | ||
|
22fd291d1f | ||
|
fcd7964a3b | ||
|
0121876c4a | ||
|
65d8941425 | ||
|
655bdcf95f | ||
|
7b41bef20e | ||
|
f23b392b2d | ||
|
875d676ad1 | ||
|
872bb2a43c | ||
|
99913833ea | ||
|
5cbfadf65c | ||
|
737b91ae35 | ||
|
6c13c8b0af | ||
|
69fc00b4b6 | ||
|
bb71155bfc | ||
|
60d07488be | ||
|
3c3de02a3e | ||
|
36e791fccf | ||
|
07d964ece6 | ||
|
7f4ab1db86 | ||
|
27f5c1b148 | ||
|
764760ee5d | ||
|
41c93153bf | ||
|
8eee9897a8 | ||
|
1d2b8af320 | ||
|
e5a4ea71a4 | ||
|
6a496603bd | ||
|
36621a7f7d | ||
|
ae86e6fe54 | ||
|
9d1509671b | ||
|
bd426eb89d | ||
|
be96154c85 | ||
|
5d4dc52ff5 | ||
|
d45422328a | ||
|
007c70310b | ||
|
9bf3725d20 | ||
|
9dc88eed5a | ||
|
1612741f32 | ||
|
9f35883ee1 | ||
|
7c3db57a59 | ||
|
ddf35d09e0 | ||
|
37906a099b | ||
|
bd42d344a3 | ||
|
233db07715 | ||
|
84e1a21e05 | ||
|
3f2f7bf074 | ||
|
8b67057c19 | ||
|
e5a5f2bd90 | ||
|
aea62f9f77 | ||
|
b22acbcff6 | ||
|
dfbcc9c50d | ||
|
c1e1e0e683 | ||
|
bfb3da854d | ||
|
b077952901 | ||
|
f1b300324e | ||
|
6a32109aed | ||
|
bd5562fe89 | ||
|
0556f13532 | ||
|
34e6840d0a | ||
|
922991a3d7 | ||
|
37e4a0eca9 | ||
|
345a18b1a1 | ||
|
6a3a936c4e | ||
|
4e98bd33a5 | ||
|
2d89a8380f | ||
|
d3be13875d | ||
|
40b8b9742e | ||
|
c06fee7460 | ||
|
7d152619bc | ||
|
c65be391db | ||
|
d516dd523e | ||
|
e431cd720f | ||
|
9098382b76 | ||
|
a3cd145cbd | ||
|
08b225dd13 | ||
|
cbea54bb5b | ||
|
058c7002d4 | ||
|
9722aef506 | ||
|
2fb4df8973 | ||
|
bc637da95c | ||
|
9575d54d4d | ||
|
c6a76c86c3 | ||
|
c04d63ff64 | ||
|
cde3f3bc9e | ||
|
c7344eef76 | ||
|
d2088059d7 | ||
|
052a3c531f | ||
|
8a07c5533e | ||
|
54a9c07138 | ||
|
bbc30a5810 | ||
|
3760289bbf | ||
|
f618c1b3ec | ||
|
c0f31f4236 | ||
|
5aeb9d3d8f | ||
|
38ee3ab8b6 | ||
|
f50cc76655 | ||
|
7a52d8d8eb | ||
|
c40fb49e38 | ||
|
196a64c380 | ||
|
211e8e6aec | ||
|
0094aca2c3 | ||
|
6d204848ca | ||
|
0a1cde18bb | ||
|
c13e615f70 | ||
|
3dc4257506 | ||
|
9b704bcda1 | ||
|
2f8537fe0d | ||
|
9bb71846ae | ||
|
bb42b71252 | ||
|
46451a5aa6 | ||
|
f06914e84a | ||
|
789a80f905 | ||
|
fbcc8a0afd | ||
|
41e19757db | ||
|
b7f99db780 | ||
|
51a535027f | ||
|
ed076838b5 | ||
|
5d2de89207 |
@@ -1,11 +0,0 @@
|
||||
# See https://wiki.apertis.org/Guidelines/Coding_conventions#Code_formatting
|
||||
BasedOnStyle: GNU
|
||||
AlwaysBreakAfterDefinitionReturnType: All
|
||||
BreakBeforeBinaryOperators: None
|
||||
BinPackParameters: false
|
||||
SpaceAfterCStyleCast: true
|
||||
# Our column limit is actually 80, but setting that results in clang-format
|
||||
# making a lot of dubious hanging-indent choices; disable it and assume the
|
||||
# developer will line wrap appropriately. clang-format will still check
|
||||
# existing hanging indents.
|
||||
ColumnLimit: 0
|
132
.gitlab-ci.yml
132
.gitlab-ci.yml
@@ -1,9 +1,7 @@
|
||||
stages:
|
||||
- build
|
||||
- analysis
|
||||
- docs
|
||||
- flatpak
|
||||
- deploy
|
||||
# - deploy
|
||||
|
||||
.cache-paths: &cache-paths
|
||||
paths:
|
||||
@@ -14,45 +12,16 @@ stages:
|
||||
- subprojects/libepoxy/
|
||||
- subprojects/pango/
|
||||
|
||||
# Common variables
|
||||
variables:
|
||||
COMMON_MESON_FLAGS: "--fatal-meson-warnings --werror"
|
||||
MESON_TEST_TIMEOUT_MULTIPLIER: 2
|
||||
|
||||
.only-default:
|
||||
only:
|
||||
- branches
|
||||
except:
|
||||
- tags
|
||||
|
||||
style-check-diff:
|
||||
extends: .only-default
|
||||
image: registry.gitlab.gnome.org/gnome/gtk/fedora:v15
|
||||
stage: .pre
|
||||
allow_failure: true
|
||||
script:
|
||||
- .gitlab-ci/run-style-check-diff.sh
|
||||
|
||||
fedora-x86_64:
|
||||
image: registry.gitlab.gnome.org/gnome/gtk/fedora:v15
|
||||
fedora-x86_64: &fedora-x86_64-defaults
|
||||
image: registry.gitlab.gnome.org/gnome/gtk/master:v7
|
||||
stage: build
|
||||
variables:
|
||||
EXTRA_MESON_FLAGS: "--buildtype=debug --default-library=both"
|
||||
script:
|
||||
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS}
|
||||
-Dx11-backend=true
|
||||
-Dwayland-backend=true
|
||||
-Dbroadway-backend=true
|
||||
-Dvulkan=yes
|
||||
-Dprofiler=true
|
||||
_build
|
||||
- ninja -C _build
|
||||
- .gitlab-ci/run-tests.sh _build
|
||||
- bash -x ./.gitlab-ci/test-docker.sh
|
||||
artifacts:
|
||||
when: always
|
||||
reports:
|
||||
junit:
|
||||
- "${CI_PROJECT_DIR}/_build/report.xml"
|
||||
- "${CI_PROJECT_DIR}/_build/report.xml"
|
||||
name: "gtk-${CI_COMMIT_REF_NAME}"
|
||||
paths:
|
||||
- "${CI_PROJECT_DIR}/_build/meson-logs"
|
||||
@@ -60,41 +29,14 @@ fedora-x86_64:
|
||||
- "${CI_PROJECT_DIR}/_build/report.html"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/reftests/output/*.png"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/gsk/compare/*/*.png"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/css/output/*.syscap"
|
||||
cache:
|
||||
key: "$CI_JOB_NAME"
|
||||
<<: *cache-paths
|
||||
|
||||
release-build:
|
||||
image: registry.gitlab.gnome.org/gnome/gtk/fedora:v15
|
||||
stage: build
|
||||
fedora-x86_64-staticlibs:
|
||||
variables:
|
||||
EXTRA_MESON_FLAGS: "--buildtype=release"
|
||||
script:
|
||||
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS}
|
||||
-Dx11-backend=true
|
||||
-Dwayland-backend=true
|
||||
-Dbroadway-backend=true
|
||||
-Dvulkan=yes
|
||||
_build
|
||||
- ninja -C _build
|
||||
- .gitlab-ci/run-tests.sh _build
|
||||
artifacts:
|
||||
when: always
|
||||
reports:
|
||||
junit:
|
||||
- "${CI_PROJECT_DIR}/_build/report.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/gsk/compare/*/*.png"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/css/output/*.syscap"
|
||||
cache:
|
||||
key: "$CI_JOB_NAME"
|
||||
<<: *cache-paths
|
||||
EXTRA_MESON_FLAGS: "-Ddefault_library=both"
|
||||
<<: *fedora-x86_64-defaults
|
||||
|
||||
.mingw-defaults: &mingw-defaults
|
||||
stage: build
|
||||
@@ -103,6 +45,7 @@ release-build:
|
||||
script:
|
||||
- C:\msys64\usr\bin\pacman --noconfirm -Syyuu
|
||||
- C:\msys64\usr\bin\bash -lc "bash -x ./.gitlab-ci/test-msys2.sh"
|
||||
allow_failure: true
|
||||
cache:
|
||||
key: "%CI_JOB_NAME%"
|
||||
<<: *cache-paths
|
||||
@@ -116,9 +59,6 @@ msys2-mingw32:
|
||||
.flatpak-defaults: &flatpak-defaults
|
||||
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master
|
||||
stage: flatpak
|
||||
allow_failure: true
|
||||
tags:
|
||||
- flatpak
|
||||
artifacts:
|
||||
paths:
|
||||
- "${APPID}-dev.flatpak"
|
||||
@@ -167,41 +107,19 @@ flatpak-master:icon-browser:
|
||||
APPID: org.gtk.IconBrowser4
|
||||
<<: *flatpak-master
|
||||
|
||||
static-scan:
|
||||
image: registry.gitlab.gnome.org/gnome/gtk/fedora:v15
|
||||
stage: analysis
|
||||
variables:
|
||||
EXTRA_MESON_FLAGS: "--buildtype=debug"
|
||||
script:
|
||||
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} _scan_build
|
||||
- ninja -C _scan_build scan-build
|
||||
artifacts:
|
||||
paths:
|
||||
- _scan_build/meson-logs
|
||||
allow_failure: true
|
||||
|
||||
reference:
|
||||
image: registry.gitlab.gnome.org/gnome/gtk/fedora:v15
|
||||
stage: docs
|
||||
variables:
|
||||
EXTRA_MESON_FLAGS: "--buildtype=release"
|
||||
script:
|
||||
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} -Dgtk_doc=true _build
|
||||
- ninja -C _build gdk4-doc gsk4-doc gtk4-doc
|
||||
- mkdir -p _reference/
|
||||
- mv _build/docs/reference/gdk/html/ _reference/gdk/
|
||||
- mv _build/docs/reference/gsk/html/ _reference/gsk/
|
||||
- mv _build/docs/reference/gtk/html/ _reference/gtk/
|
||||
artifacts:
|
||||
paths:
|
||||
- _reference
|
||||
|
||||
pages:
|
||||
stage: deploy
|
||||
script:
|
||||
- mv _reference/ public/
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
only:
|
||||
- master
|
||||
#pages:
|
||||
# image: registry.gitlab.gnome.org/gnome/gtk/master:v6
|
||||
# stage: deploy
|
||||
# script:
|
||||
# - meson -Dgtk_doc=true _build .
|
||||
# - ninja -C _build
|
||||
# - ninja -C _build gdk4-doc gsk4-doc gtk4-doc
|
||||
# - mkdir -p public/
|
||||
# - mv _build/docs/reference/gtk/html/ public/gtk/
|
||||
# - mv _build/docs/reference/gdk/html/ public/gdk/
|
||||
# - mv _build/docs/reference/gsk/html/ public/gsk/
|
||||
# artifacts:
|
||||
# paths:
|
||||
# - public
|
||||
# only:
|
||||
# - master
|
||||
|
@@ -8,12 +8,9 @@ RUN dnf -y install \
|
||||
cairo-devel \
|
||||
cairo-gobject-devel \
|
||||
ccache \
|
||||
clang \
|
||||
clang-analyzer \
|
||||
colord-devel \
|
||||
cups-devel \
|
||||
dbus-daemon \
|
||||
dbus-x11 \
|
||||
dejavu-sans-mono-fonts \
|
||||
desktop-file-utils \
|
||||
diffutils \
|
||||
@@ -26,7 +23,6 @@ RUN dnf -y install \
|
||||
gettext \
|
||||
git \
|
||||
glib2-devel \
|
||||
glib2-static \
|
||||
glibc-devel \
|
||||
glibc-headers \
|
||||
gobject-introspection-devel \
|
||||
@@ -57,7 +53,6 @@ RUN dnf -y install \
|
||||
libxkbcommon-devel \
|
||||
libXrandr-devel \
|
||||
libXrender-devel \
|
||||
libXtst-devel \
|
||||
libxslt \
|
||||
mesa-dri-drivers \
|
||||
mesa-libEGL-devel \
|
||||
@@ -65,15 +60,12 @@ RUN dnf -y install \
|
||||
ninja-build \
|
||||
pango-devel \
|
||||
pcre-devel \
|
||||
pcre-static \
|
||||
python3 \
|
||||
python3-jinja2 \
|
||||
python3-pip \
|
||||
python3-pygments \
|
||||
python3-wheel \
|
||||
redhat-rpm-config \
|
||||
sassc \
|
||||
sysprof-devel \
|
||||
systemtap-sdt-devel \
|
||||
vulkan-devel \
|
||||
wayland-devel \
|
||||
@@ -82,7 +74,7 @@ RUN dnf -y install \
|
||||
xorg-x11-server-Xvfb \
|
||||
&& dnf clean all
|
||||
|
||||
RUN pip3 install meson==0.52.1
|
||||
RUN pip3 install meson==0.50.1
|
||||
|
||||
ARG HOST_USER_ID=5555
|
||||
ENV HOST_USER_ID ${HOST_USER_ID}
|
@@ -1,38 +0,0 @@
|
||||
## GTK CI infrastructure
|
||||
|
||||
GTK uses different CI images depending on platform and jobs.
|
||||
|
||||
The CI images are Docker containers, generated either using `docker` or
|
||||
`podman`, and pushed to the GitLab [container registry][registry].
|
||||
|
||||
Each Docker image has a tag composed of two parts:
|
||||
|
||||
- `${image}`: the base image for a given platform, like "fedora" or
|
||||
"debian-stable"
|
||||
- `${number}`: an incremental version number, or `latest`
|
||||
|
||||
See the [container registry][registry] for the available images for each
|
||||
branch, as well as their available versions.
|
||||
|
||||
### Checklist for Updating a CI image
|
||||
|
||||
- [ ] Update the `${image}.Dockerfile` file with the dependencies
|
||||
- [ ] Run `./run-docker.sh build --base ${image} --base-version ${number}`
|
||||
- [ ] Run `./run-docker.sh push --base ${image} --base-version ${number}`
|
||||
once the Docker image is built; you may need to log in by using
|
||||
`docker login` or `podman login`
|
||||
- [ ] Update the `image` keys in the `.gitlab-ci.yml` file with the new
|
||||
image tag
|
||||
- [ ] Open a merge request with your changes and let it run
|
||||
|
||||
### Checklist for Adding a new CI image
|
||||
|
||||
- [ ] Write a new `${image}.Dockerfile` with the instructions to set up
|
||||
a build environment
|
||||
- [ ] Add the `pip3 install meson` incantation
|
||||
- [ ] Run `./run-docker.sh build --base ${image} --base-version ${number}`
|
||||
- [ ] Run `./run-docker.sh push --base ${image} --base-version ${number}`
|
||||
- [ ] Add the new job to `.gitlab-ci.yml` referencing the image
|
||||
- [ ] Open a merge request with your changes and let it run
|
||||
|
||||
[registry]: https://gitlab.gnome.org/GNOME/gtk/container_registry
|
@@ -1,133 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# === clang-format-diff.py - ClangFormat Diff Reformatter ---*- python -*-=== #
|
||||
#
|
||||
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
# See https://llvm.org/LICENSE.txt for license information.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
# ===---------------------------------------------------------------------=== #
|
||||
|
||||
"""
|
||||
This script reads input from a unified diff and reformats all the changed
|
||||
lines. This is useful to reformat all the lines touched by a specific patch.
|
||||
Example usage for git/svn users:
|
||||
|
||||
git diff -U0 --no-color HEAD^ | clang-format-diff.py -p1 -i
|
||||
svn diff --diff-cmd=diff -x-U0 | clang-format-diff.py -i
|
||||
|
||||
"""
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
import argparse
|
||||
import difflib
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
if sys.version_info.major >= 3:
|
||||
from io import StringIO
|
||||
else:
|
||||
from io import BytesIO as StringIO
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description=__doc__,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
parser.add_argument('-i', action='store_true', default=False,
|
||||
help='apply edits to files instead of displaying a '
|
||||
'diff')
|
||||
parser.add_argument('-p', metavar='NUM', default=0,
|
||||
help='strip the smallest prefix containing P slashes')
|
||||
parser.add_argument('-regex', metavar='PATTERN', default=None,
|
||||
help='custom pattern selecting file paths to reformat '
|
||||
'(case sensitive, overrides -iregex)')
|
||||
parser.add_argument('-iregex', metavar='PATTERN',
|
||||
default=r'.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hh|hpp|m|mm|inc'
|
||||
r'|js|ts|proto|protodevel|java|cs)',
|
||||
help='custom pattern selecting file paths to reformat '
|
||||
'(case insensitive, overridden by -regex)')
|
||||
parser.add_argument('-sort-includes', action='store_true', default=False,
|
||||
help='let clang-format sort include blocks')
|
||||
parser.add_argument('-v', '--verbose', action='store_true',
|
||||
help='be more verbose, ineffective without -i')
|
||||
parser.add_argument('-style',
|
||||
help='formatting style to apply (LLVM, Google, '
|
||||
'Chromium, Mozilla, WebKit)')
|
||||
parser.add_argument('-binary', default='clang-format',
|
||||
help='location of binary to use for clang-format')
|
||||
args = parser.parse_args()
|
||||
|
||||
# Extract changed lines for each file.
|
||||
filename = None
|
||||
lines_by_file = {}
|
||||
for line in sys.stdin:
|
||||
match = re.search(r'^\+\+\+\ (.*?/){%s}(\S*)' % args.p, line)
|
||||
if match:
|
||||
filename = match.group(2)
|
||||
if filename is None:
|
||||
continue
|
||||
|
||||
if args.regex is not None:
|
||||
if not re.match('^%s$' % args.regex, filename):
|
||||
continue
|
||||
else:
|
||||
if not re.match('^%s$' % args.iregex, filename, re.IGNORECASE):
|
||||
continue
|
||||
|
||||
match = re.search(r'^@@.*\+(\d+)(,(\d+))?', line)
|
||||
if match:
|
||||
start_line = int(match.group(1))
|
||||
line_count = 1
|
||||
if match.group(3):
|
||||
line_count = int(match.group(3))
|
||||
if line_count == 0:
|
||||
continue
|
||||
end_line = start_line + line_count - 1
|
||||
lines_by_file.setdefault(filename, []).extend(
|
||||
['-lines', str(start_line) + ':' + str(end_line)])
|
||||
|
||||
# Reformat files containing changes in place.
|
||||
# We need to count amount of bytes generated in the output of
|
||||
# clang-format-diff. If clang-format-diff doesn't generate any bytes it
|
||||
# means there is nothing to format.
|
||||
format_line_counter = 0
|
||||
for filename, lines in lines_by_file.items():
|
||||
if args.i and args.verbose:
|
||||
print('Formatting {}'.format(filename))
|
||||
command = [args.binary, filename]
|
||||
if args.i:
|
||||
command.append('-i')
|
||||
if args.sort_includes:
|
||||
command.append('-sort-includes')
|
||||
command.extend(lines)
|
||||
if args.style:
|
||||
command.extend(['-style', args.style])
|
||||
p = subprocess.Popen(command,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=None,
|
||||
stdin=subprocess.PIPE,
|
||||
universal_newlines=True)
|
||||
stdout, _ = p.communicate()
|
||||
if p.returncode != 0:
|
||||
sys.exit(p.returncode)
|
||||
|
||||
if not args.i:
|
||||
with open(filename) as f:
|
||||
code = f.readlines()
|
||||
formatted_code = StringIO(stdout).readlines()
|
||||
diff = difflib.unified_diff(code, formatted_code,
|
||||
filename, filename,
|
||||
'(before formatting)',
|
||||
'(after formatting)')
|
||||
diff_string = ''.join(diff)
|
||||
if diff_string:
|
||||
format_line_counter += sys.stdout.write(diff_string)
|
||||
|
||||
if format_line_counter > 0:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@@ -4,19 +4,20 @@ set -e
|
||||
|
||||
appid=$1
|
||||
|
||||
builddir=flatpak_app
|
||||
builddir=app
|
||||
repodir=repo
|
||||
|
||||
flatpak-builder \
|
||||
--user --disable-rofiles-fuse \
|
||||
--stop-at=gtk \
|
||||
${builddir} \
|
||||
build-aux/flatpak/${appid}.json
|
||||
|
||||
flatpak build ${builddir} meson \
|
||||
--prefix=/app \
|
||||
--libdir=/app/lib \
|
||||
--buildtype=release \
|
||||
flatpak-builder \
|
||||
--run ${builddir} build-aux/flatpak/${appid}.json \
|
||||
meson \
|
||||
--prefix /app \
|
||||
--libdir /app/lib \
|
||||
--buildtype debug \
|
||||
-Dx11-backend=true \
|
||||
-Dwayland-backend=true \
|
||||
-Dprint-backends=file \
|
||||
@@ -24,12 +25,13 @@ flatpak build ${builddir} meson \
|
||||
-Dbuild-examples=false \
|
||||
-Dintrospection=false \
|
||||
-Ddemos=true \
|
||||
_flatpak_build
|
||||
|
||||
flatpak build ${builddir} ninja -C _flatpak_build install
|
||||
_build .
|
||||
|
||||
flatpak-builder \
|
||||
--run ${builddir} build-aux/flatpak/${appid}.json \
|
||||
ninja -C _build install
|
||||
|
||||
flatpak-builder \
|
||||
--user --disable-rofiles-fuse \
|
||||
--finish-only \
|
||||
--repo=${repodir} \
|
||||
${builddir} \
|
||||
@@ -38,5 +40,5 @@ flatpak-builder \
|
||||
flatpak build-bundle \
|
||||
${repodir} \
|
||||
${appid}-dev.flatpak \
|
||||
--runtime-repo=https://nightly.gnome.org/gnome-nightly.flatpakrepo \
|
||||
--runtime-repo=https://flathub.org/repo/flathub.flatpakrepo \
|
||||
${appid}
|
||||
|
@@ -138,25 +138,22 @@ ul.images li {
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>{{ report.project_name }}/{{ report.branch_name }} :: Test Reports</h1>
|
||||
<h1>{{ report.project_name }} :: Test Reports</h1>
|
||||
<div class="report-meta">
|
||||
<p><strong>Branch:</strong> {{ report.branch_name }}</p>
|
||||
<p><strong>Date:</strong> <time datetime="{{ report.date.isoformat() }}">{{ report.locale_date }}</time></p>
|
||||
{% if report.job_id %}<p><strong>Job ID:</strong> {{ report.job_id }}</p>{% endif %}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<section>
|
||||
<div class="report-meta">
|
||||
<p><strong>Branch:</strong> {{ report.branch_name }}</p>
|
||||
<p><strong>Date:</strong> <time datetime="{{ report.date.isoformat() }}">{{ report.locale_date }}</time></p>
|
||||
{% if report.job_id %}<p><strong>Job ID:</strong> {{ report.job_id }}</p>{% endif %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="summary">
|
||||
<h3><a name="summary">Summary</a></h3>
|
||||
<ul>
|
||||
<li><strong>Total units:</strong> {{ report.total_units }}</li>
|
||||
<li><strong>Failed:</strong> {{ report.total_failures }}</li>
|
||||
<li><strong>Passed:</strong> {{ report.total_successes }}</li>
|
||||
<li><strong>Passed:</strong> <a href="#passed">{{ report.total_successes }}</a></li>
|
||||
<li><strong>Failed:</strong> <a href="#failures">{{ report.total_failures }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
@@ -167,56 +164,12 @@ ul.images li {
|
||||
<h3><a name="results">Suite: {{ suite_result.suite_name }}</a></h3>
|
||||
<ul>
|
||||
<li><strong>Units:</strong> {{ suite_result.n_units }}</li>
|
||||
<li><strong>Failed:</strong> <a href="#{{ suite_result.suite_name }}-failed">{{ suite_result.n_failures }}</a></li>
|
||||
<li><strong>Passed:</strong> <a href="#{{ suite_result.suite_name }}-passed">{{ suite_result.n_successes }}</a></li>
|
||||
<li><strong>Passed:</strong> {{ suite_result.n_successes }}</li>
|
||||
<li><strong>Failed:</strong> {{ suite_result.n_failures }}</li>
|
||||
</ul>
|
||||
|
||||
<div class="failures">
|
||||
<h4><a name="{{ suite_result.suite_name }}-failed">Failures</a></h4>
|
||||
<ul class="failed">
|
||||
{% for failure in suite_result.failures if failure.result in [ 'FAIL', 'UNEXPECTEDPASS' ] %}
|
||||
<li><a name="{{ failure.name }}">{{ failure.name }}</a> - result: <span class="result fail">{{ failure.result }}</span><br/>
|
||||
{% if failure.stdout %}
|
||||
Output: <pre>{{ failure.stdout }}</pre>
|
||||
{% endif %}
|
||||
{% if failure.image_data is defined %}
|
||||
<ul class="images">
|
||||
<li><img alt="ref" src="{{ failure.image_data.ref }}" /></li>
|
||||
<li><img alt="out" src="{{ failure.image_data.out }}" /></li>
|
||||
<li><img alt="diff" src="{{ failure.image_data.diff }}" /></li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% else %}
|
||||
<li>None</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<h4><a name="{{ suite_result.suite_name }}-timed-out">Timed out</a></h4>
|
||||
<ul class="failed">
|
||||
{% for failure in suite_result.failures if failure.result == 'TIMEOUT' %}
|
||||
<li><a name="{{ failure.name }}">{{ failure.name }}</a> - result: <span class="result fail">{{ failure.result }}</span><br/>
|
||||
{% if failure.stdout %}
|
||||
Output: <pre>{{ failure.stdout }}</pre>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% else %}
|
||||
<li>None</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="successes">
|
||||
<h4><a name="{{ suite_result.suite_name }}-skipped">Skipped</a></h4>
|
||||
<ul>
|
||||
{% for success in suite_result.successes if success.result == 'SKIP' %}
|
||||
<li>{{ success.name }} - result: <span class="result skip">{{ success.result }}</li>
|
||||
{% else %}
|
||||
<li>None</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<h4><a name="{{ suite_result.suite_name }}-passed">Passed</a></h4>
|
||||
<h4><a name="passed">Passed</a></h4>
|
||||
<ul class="passed">
|
||||
{% for success in suite_result.successes if success.result == 'OK' %}
|
||||
<li>{{ success.name }} - result: <span class="result pass">{{ success.result }}</li>
|
||||
@@ -225,7 +178,16 @@ ul.images li {
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<h4><a name="{{ suite_result.suite_name }}-expected-fail">Expected failures</a></h4>
|
||||
<h4><a name="skipped">Skipped</a></h4>
|
||||
<ul>
|
||||
{% for success in suite_result.successes if success.result == 'SKIP' %}
|
||||
<li>{{ success.name }} - result: <span class="result skip">{{ success.result }}</li>
|
||||
{% else %}
|
||||
<li>None</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<h4><a name="expected-fail">Expected failures</a></h4>
|
||||
<ul>
|
||||
{% for success in suite_result.successes if success.result == 'EXPECTEDFAIL' %}
|
||||
<li><a name="{{ success.name }}">{{ success.name }}</a> - result: <span class="result xfail">{{ success.result }}</span><br/>
|
||||
@@ -246,6 +208,41 @@ ul.images li {
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="failures">
|
||||
<h4><a name="failed">Failed</a></h4>
|
||||
<ul class="failed">
|
||||
{% for failure in suite_result.failures if failure.result == 'FAIL' %}
|
||||
<li><a name="{{ failure.name }}">{{ failure.name }}</a> - result: <span class="result fail">{{ failure.result }}</span><br/>
|
||||
{% if failure.stdout %}
|
||||
Output: <pre>{{ failure.stdout }}</pre>
|
||||
{% endif %}
|
||||
{% if failure.image_data is defined %}
|
||||
<ul class="images">
|
||||
<li><img alt="ref" src="{{ failure.image_data.ref }}" /></li>
|
||||
<li><img alt="out" src="{{ failure.image_data.out }}" /></li>
|
||||
<li><img alt="diff" src="{{ failure.image_data.diff }}" /></li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% else %}
|
||||
<li>None</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<h4><a name="timed-out">Timed out</a></h4>
|
||||
<ul class="failed">
|
||||
{% for failure in suite_result.failures if failure.result == 'TIMEOUT' %}
|
||||
<li><a name="{{ failure.name }}">{{ failure.name }}</a> - result: <span class="result fail">{{ failure.result }}</span><br/>
|
||||
{% if failure.stdout %}
|
||||
Output: <pre>{{ failure.stdout }}</pre>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% else %}
|
||||
<li>None</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
{% endfor %}
|
||||
@@ -331,7 +328,7 @@ for name, units in suites.items():
|
||||
print('Processing {} suite {}:'.format(project_name, suite_name))
|
||||
|
||||
def if_failed(unit):
|
||||
if unit['result'] in ['FAIL', 'UNEXPECTEDPASS', 'TIMEOUT']:
|
||||
if unit['result'] in ['FAIL', 'TIMEOUT']:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
@@ -51,7 +51,6 @@ for line in args.infile:
|
||||
|
||||
duration = data['duration']
|
||||
return_code = data['returncode']
|
||||
result = data['result']
|
||||
log = data['stdout']
|
||||
|
||||
unit = {
|
||||
@@ -59,7 +58,6 @@ for line in args.infile:
|
||||
'name': unit_name,
|
||||
'duration': duration,
|
||||
'returncode': return_code,
|
||||
'result': result,
|
||||
'stdout': log,
|
||||
}
|
||||
|
||||
@@ -70,12 +68,12 @@ for name, units in suites.items():
|
||||
print('Processing suite {} (units: {})'.format(name, len(units)))
|
||||
|
||||
def if_failed(unit):
|
||||
if unit['result'] in ['FAIL', 'UNEXPECTEDPASS', 'TIMEOUT']:
|
||||
if unit['returncode'] != 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
def if_succeded(unit):
|
||||
if unit['result'] in ['OK', 'EXPECTEDFAIL', 'SKIP']:
|
||||
if unit['returncode'] == 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
@@ -1,135 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
read_arg() {
|
||||
# $1 = arg name
|
||||
# $2 = arg value
|
||||
# $3 = arg parameter
|
||||
local rematch='^[^=]*=(.*)$'
|
||||
if [[ $2 =~ $rematch ]]; then
|
||||
read "$1" <<< "${BASH_REMATCH[1]}"
|
||||
else
|
||||
read "$1" <<< "$3"
|
||||
# There is no way to shift our callers args, so
|
||||
# return 1 to indicate they should do it instead.
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
set -e
|
||||
|
||||
build=0
|
||||
run=0
|
||||
push=0
|
||||
list=0
|
||||
print_help=0
|
||||
no_login=0
|
||||
TAG="registry.gitlab.gnome.org/gnome/gtk/master:v7"
|
||||
|
||||
while (($# > 0)); do
|
||||
case "${1%%=*}" in
|
||||
build) build=1;;
|
||||
run) run=1;;
|
||||
push) push=1;;
|
||||
list) list=1;;
|
||||
help) print_help=1;;
|
||||
--base|-b) read_arg base "$@" || shift;;
|
||||
--base-version) read_arg base_version "$@" || shift;;
|
||||
--no-login) no_login=1;;
|
||||
*) echo -e "\e[1;31mERROR\e[0m: Unknown option '$1'"; exit 1;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ $print_help == 1 ]; then
|
||||
echo "$0 - Build and run Docker images"
|
||||
echo ""
|
||||
echo "Usage: $0 <command> [options] [basename]"
|
||||
echo ""
|
||||
echo "Available commands"
|
||||
echo ""
|
||||
echo " build --base=<BASENAME> - Build Docker image <BASENAME>.Dockerfile"
|
||||
echo " run --base=<BASENAME> - Run Docker image <BASENAME>"
|
||||
echo " push --base=<BASENAME> - Push Docker image <BASENAME> to the registry"
|
||||
echo " list - List available images"
|
||||
echo " help - This help message"
|
||||
echo ""
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
if [ $list == 1 ]; then
|
||||
echo "Available Docker images:"
|
||||
for f in *.Dockerfile; do
|
||||
filename=$( basename -- "$f" )
|
||||
basename="${filename%.*}"
|
||||
|
||||
echo -e " \e[1;39m$basename\e[0m"
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# All commands after this require --base to be set
|
||||
if [ -z $base ]; then
|
||||
echo "Usage: $0 <command>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$base.Dockerfile" ]; then
|
||||
echo -e "\e[1;31mERROR\e[0m: Dockerfile for '$base' not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z $base_version ]; then
|
||||
base_version="latest"
|
||||
else
|
||||
base_version="v$base_version"
|
||||
fi
|
||||
|
||||
if [ ! -x "$(command -v docker)" ] || [ docker --help |& grep -q podman ]; then
|
||||
# Docker is actually implemented by podman, and its OCI output
|
||||
# is incompatible with some of the dockerd instances on GitLab
|
||||
# CI runners.
|
||||
echo "Using: Podman"
|
||||
format="--format docker"
|
||||
CMD="podman"
|
||||
else
|
||||
echo "Using: Docker"
|
||||
format=""
|
||||
CMD="sudo socker"
|
||||
fi
|
||||
|
||||
REGISTRY="registry.gitlab.gnome.org"
|
||||
TAG="${REGISTRY}/gnome/gtk/${base}:${base_version}"
|
||||
|
||||
if [ $build == 1 ]; then
|
||||
echo -e "\e[1;32mBUILDING\e[0m: ${base} as ${TAG}"
|
||||
${CMD} build \
|
||||
${format} \
|
||||
--build-arg HOST_USER_ID="$UID" \
|
||||
--tag "${TAG}" \
|
||||
--file "${base}.Dockerfile" .
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if [ $push == 1 ]; then
|
||||
echo -e "\e[1;32mPUSHING\e[0m: ${base} as ${TAG}"
|
||||
|
||||
if [ $no_login == 0 ]; then
|
||||
${CMD} login ${REGISTRY}
|
||||
fi
|
||||
|
||||
${CMD} push ${TAG}
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if [ $run == 1 ]; then
|
||||
echo -e "\e[1;32mRUNNING\e[0m: ${base} as ${TAG}"
|
||||
${CMD} run \
|
||||
--rm \
|
||||
--volume "$(pwd)/..:/home/user/app" \
|
||||
--workdir "/home/user/app" \
|
||||
--tty \
|
||||
--interactive "${TAG}" \
|
||||
bash
|
||||
exit $?
|
||||
fi
|
||||
sudo docker build --build-arg HOST_USER_ID="$UID" --tag "${TAG}" \
|
||||
--file "Dockerfile" .
|
||||
sudo docker run --rm --security-opt label=disable \
|
||||
--volume "$(pwd)/..:/home/user/app" --workdir "/home/user/app" \
|
||||
--tty --interactive "${TAG}" bash
|
||||
|
@@ -1,37 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# We need to add a new remote for the upstream master, since this script could
|
||||
# be running in a personal fork of the repository which has out of date branches.
|
||||
git remote add upstream https://gitlab.gnome.org/GNOME/gtk.git
|
||||
git fetch upstream
|
||||
|
||||
# Work out the newest common ancestor between the detached HEAD that this CI job
|
||||
# has checked out, and the upstream target branch (which will typically be
|
||||
# `upstream/master` or `upstream/gtk-3-24`).
|
||||
#
|
||||
# `${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}` is only defined if we’re running in
|
||||
# a merge request pipeline; fall back to `${CI_DEFAULT_BRANCH}` otherwise.
|
||||
newest_common_ancestor_sha=$(diff --old-line-format='' --new-line-format='' <(git rev-list --first-parent "upstream/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-${CI_DEFAULT_BRANCH}}") <(git rev-list --first-parent HEAD) | head -1)
|
||||
git diff -U0 --no-color "${newest_common_ancestor_sha}" | .gitlab-ci/clang-format-diff.py -binary "clang-format" -p1
|
||||
exit_status=$?
|
||||
|
||||
# The style check is not infallible. The clang-format configuration cannot
|
||||
# perfectly describe GTK’s coding style: in particular, it cannot align
|
||||
# function arguments. The documented coding style for GTK takes priority over
|
||||
# clang-format suggestions. Hopefully we can eventually improve clang-format to
|
||||
# be configurable enough for our coding style. That’s why this CI check is OK
|
||||
# to fail: the idea is that people can look through the output and ignore it if
|
||||
# it’s wrong. (That situation can also happen if someone touches pre-existing
|
||||
# badly formatted code and it doesn’t make sense to tidy up the wider coding
|
||||
# style with the changes they’re making.)
|
||||
echo ""
|
||||
echo "Note that clang-format output is advisory and cannot always match the"
|
||||
echo "GTK coding style, documented at:"
|
||||
echo " https://gitlab.gnome.org/GNOME/gtk/blob/master/docs/CODING-STYLE"
|
||||
echo "Warnings from this tool can be ignored in favour of the documented "
|
||||
echo "coding style, or in favour of matching the style of existing"
|
||||
echo "surrounding code."
|
||||
|
||||
exit ${exit_status}
|
@@ -1,34 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set +x
|
||||
set +e
|
||||
|
||||
srcdir=$( pwd )
|
||||
builddir=$1
|
||||
|
||||
export GDK_BACKEND=x11
|
||||
xvfb-run -a -s "-screen 0 1024x768x24" \
|
||||
meson test -C ${builddir} \
|
||||
--print-errorlogs \
|
||||
--suite=gtk \
|
||||
--no-suite=gtk:a11y
|
||||
|
||||
# Store the exit code for the CI run, but always
|
||||
# generate the reports
|
||||
exit_code=$?
|
||||
|
||||
cd ${builddir}
|
||||
|
||||
$srcdir/.gitlab-ci/meson-junit-report.py \
|
||||
--project-name=gtk \
|
||||
--job-id="${CI_JOB_NAME}" \
|
||||
--output=report.xml \
|
||||
meson-logs/testlog.json
|
||||
$srcdir/.gitlab-ci/meson-html-report.py \
|
||||
--project-name=gtk \
|
||||
--job-id="${CI_JOB_NAME}" \
|
||||
--reftest-output-dir="testsuite/reftests/output" \
|
||||
--output=report.html \
|
||||
meson-logs/testlog.json
|
||||
|
||||
exit $exit_code
|
@@ -16,7 +16,6 @@ meson \
|
||||
-Dwayland-backend=true \
|
||||
-Dbroadway-backend=true \
|
||||
-Dvulkan=yes \
|
||||
-Dprofiler=true \
|
||||
--werror \
|
||||
${EXTRA_MESON_FLAGS:-} \
|
||||
_build $srcdir
|
||||
|
@@ -33,10 +33,6 @@ pacman --noconfirm -S --needed \
|
||||
mingw-w64-$MSYS2_ARCH-gst-plugins-bad \
|
||||
mingw-w64-$MSYS2_ARCH-shared-mime-info
|
||||
|
||||
# https://gitlab.gnome.org/GNOME/gtk/issues/2243
|
||||
wget "https://gitlab.gnome.org/creiter/gitlab-ci-win32-runner/raw/master/pango/mingw-w64-$MSYS2_ARCH-pango-1.44.7-1-any.pkg.tar.xz"
|
||||
pacman --noconfirm -U "mingw-w64-$MSYS2_ARCH-pango-1.44.7-1-any.pkg.tar.xz"
|
||||
|
||||
mkdir -p _ccache
|
||||
export CCACHE_BASEDIR="$(pwd)"
|
||||
export CCACHE_DIR="${CCACHE_BASEDIR}/_ccache"
|
||||
|
@@ -174,7 +174,7 @@ maintainers review your contribution.
|
||||
|
||||
Each contribution is reviewed by the core developers of the GTK project.
|
||||
|
||||
The [CODEOWNERS](./docs/CODEOWNERS) document contains the list of core
|
||||
The [CODE-OWNERS](./docs/CODE-OWNERS) document contains the list of core
|
||||
contributors to GTK and the areas for which they are responsible; you
|
||||
should ensure to receive their review and signoff on your changes.
|
||||
|
||||
|
169
NEWS
169
NEWS
@@ -1,170 +1,3 @@
|
||||
Overview of Changes in GTK 3.98.2
|
||||
=================================
|
||||
|
||||
* Introduce GtkShortcutController, and replace key bindings,
|
||||
mnemonics and accelerators by GtkShortcut
|
||||
|
||||
* Derive the HighContrast theme from Adwaita
|
||||
|
||||
* GtkMenuButton: Add a use-underline property
|
||||
|
||||
* GtkTreeView: Fix cell editing
|
||||
|
||||
* Add gdk_toplevel_inhibit_system_shortcuts
|
||||
|
||||
* gtk-demo: Fix issues in multiple demos
|
||||
|
||||
* Translation updates:
|
||||
Polish
|
||||
|
||||
|
||||
Overview of Changes in GTK 3.98.1
|
||||
=================================
|
||||
|
||||
* GtkFileChooser:
|
||||
- Remove filename/uri api
|
||||
- Drop extra-widget
|
||||
- Remove overwrite confirmation
|
||||
- Remove show-hidden property
|
||||
- Remove local-only property
|
||||
- Remove GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
|
||||
- The portal file chooser supports selecting folders
|
||||
|
||||
* GtkSpinner:
|
||||
- Rename active property to spinning
|
||||
|
||||
* GtkRevealer:
|
||||
- Fix size allocation at small scales
|
||||
|
||||
* GtkPopover:
|
||||
- Drop :relative-to, it is always the :parent now
|
||||
|
||||
* GtkWindow:
|
||||
- Drop window-type, it is always a regular toplevel
|
||||
|
||||
* GtkWidget:
|
||||
- Drop expand property
|
||||
- Drop margin property
|
||||
- Drop gtk_grab_add, gtk_device_grab_add
|
||||
|
||||
* GtkTextView:
|
||||
- Support overlines in GtkTextTag
|
||||
- Support visible spaces in GtkTextTag
|
||||
- Support hyphenation control in GtkTextTag
|
||||
|
||||
* Split GtkEventControllerFocus from GtkEventControllerKey
|
||||
|
||||
* DND:
|
||||
- Fix local DND to avoid serialization
|
||||
- Add new content provider constructors
|
||||
- Split GtkDropTargetAsync and GtkDropTarget
|
||||
- Group DND events into event sequences
|
||||
- Propagate DND events like motion events
|
||||
- Introduce GtkDropControllerMotion
|
||||
- Remove GtkSelectionData
|
||||
|
||||
* Performance:
|
||||
- Clean up profiler marks
|
||||
- Share GL programs between renderers
|
||||
|
||||
* GDK:
|
||||
- Drop gdk_surface_new_temp
|
||||
- Make GdkEvent an immutable boxed type, not an object
|
||||
- Remove GdkAtom and property- and selection-related apis
|
||||
- Introduce GdkPopup and GdkToplevel interfaces
|
||||
- Implement them in backend-specific surface subtypes
|
||||
- Rename gdk_surface_input_shape_combine_region to
|
||||
gdk_surface_set_input_region
|
||||
- Drop X11-only concepts such as sticky or keep-below
|
||||
|
||||
* OS X: Fix OpenGL extension detection
|
||||
|
||||
* Broadway: implement scaling
|
||||
|
||||
* Translation updates:
|
||||
Dutch
|
||||
Japanese
|
||||
Persian
|
||||
|
||||
|
||||
Overview of Changes in GTK 3.98.0
|
||||
=================================
|
||||
|
||||
While this release gets significantly closer to what we aim for in GTK 4,
|
||||
there are still a few big items outstanding that we are currently working
|
||||
on:
|
||||
|
||||
- Event controllers for keyboard shortcuts
|
||||
- Movable popovers
|
||||
- Row-recycling list and grid views
|
||||
- Revamped accessibility infrastructure
|
||||
- Animation API
|
||||
|
||||
We will do further 3.98.x snapshots as these land.
|
||||
|
||||
*****************
|
||||
|
||||
* The DND refactoring has been completed. The GTK API for DND has been turned
|
||||
into event controllers: GtkDragSource and GtkDropTarget. Support for file
|
||||
transfers via file transfer portal has been added for both DND and the clipboard.
|
||||
|
||||
* Child surfaces have been removed. GDK only supports toplevel and popup surfaces
|
||||
now. The client-side window implementation has been removed too. On the GTK side,
|
||||
the GtkNative interface has been introduced for widgets that have their own
|
||||
surface. This cleanup is not 100% complete yet.
|
||||
|
||||
* Global positions and related apis such as gdk_surface_move are no longer available.
|
||||
|
||||
* A constraint-based layout manager has been added.
|
||||
|
||||
* Many classes have been made explicitly non-subclassable, and the widget hierarchy
|
||||
has been simplified, by making widgets derive directly from GtkWidget instead of
|
||||
a container.
|
||||
|
||||
* Menu-related changes:
|
||||
- GtkMenu, GtkMenuBar and related classes have been removed. They are being replaced
|
||||
by GMenu and popover-based variants. Popover menus can now do traditional, nested
|
||||
menus, and model buttons show accelerators.
|
||||
- Context menus are no longer created with ::populate-popup signals, but use menu
|
||||
models and actions.
|
||||
- Widget actions can be created in class_init, with gtk_widget_class_install_action.
|
||||
- GtkToolbar has been removed as well.
|
||||
|
||||
* Text-related changed:
|
||||
- Text cursor blinking has been made smooth.
|
||||
- GtkTextView is caching rendernodes for the visible text range now, improving the
|
||||
scrolling performance of text.
|
||||
- Add a simple undo stack for text edits has been added.
|
||||
|
||||
* The native Win32 filechooser backend supports choices.
|
||||
|
||||
* GtkTreeView renders tree and grid lines with textures.
|
||||
|
||||
* GtkEmojiChooser has been made public.
|
||||
|
||||
* GtkGestureMultiPress has been renamed to GtkGestureClick.
|
||||
|
||||
* GtkWidget has api to handle style classes: gtk_widget_add_style_class.
|
||||
This is the first step towards moving away from GtkStyleContext.
|
||||
|
||||
* X11-specific changes:
|
||||
- XI2 is now mandatory
|
||||
- The xim input method has been removed
|
||||
|
||||
* Wayland-specific changes:
|
||||
- The loading of cursor themes has been improved to load cursors on demand,
|
||||
and no longer relies on libwayland-cursor.
|
||||
|
||||
* The GL renderer is now sharing icon and glyph caches for all surfaces,
|
||||
and has better support for blurring and shadow rendering.
|
||||
|
||||
* Performance-related changes:
|
||||
- GTK provides profiling information for Sysprof when launched with GTK_TRACE=1.
|
||||
- Css computation has been optimized
|
||||
- Css lookups are using a Bloom filter
|
||||
- Icon loading IO has been moved to a thread
|
||||
|
||||
|
||||
Overview of Changes in GTK+ 3.96.0
|
||||
==================================
|
||||
|
||||
@@ -527,7 +360,7 @@ Overview of Changes in GTK+ 3.92.1, 重庆市
|
||||
The bulk of the preparation for this release was done during
|
||||
and after the fantastic GNOME.Asia Summit 2017 in Chongqing, China.
|
||||
|
||||
* Drop autotools support. Meson 0.42.1 is now required
|
||||
* Drop autotools support. Meson 0.42.1 is now required
|
||||
|
||||
* Implement most of CSS3 font-variant
|
||||
|
||||
|
@@ -54,36 +54,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "libsass",
|
||||
"buildsystem" : "meson",
|
||||
"builddir" : true,
|
||||
"config-opts": [
|
||||
"--libdir=/app/lib"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/lazka/libsass.git",
|
||||
"branch" : "meson"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "sassc",
|
||||
"buildsystem" : "meson",
|
||||
"builddir" : true,
|
||||
"config-opts": [
|
||||
"--libdir=/app/lib"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/lazka/sassc.git",
|
||||
"branch" : "meson"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "gtk",
|
||||
"buildsystem": "meson",
|
||||
|
@@ -54,36 +54,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "libsass",
|
||||
"buildsystem" : "meson",
|
||||
"builddir" : true,
|
||||
"config-opts": [
|
||||
"--libdir=/app/lib"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/lazka/libsass.git",
|
||||
"branch" : "meson"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "sassc",
|
||||
"buildsystem" : "meson",
|
||||
"builddir" : true,
|
||||
"config-opts": [
|
||||
"--libdir=/app/lib"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/lazka/sassc.git",
|
||||
"branch" : "meson"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "gtk",
|
||||
"buildsystem": "meson",
|
||||
|
@@ -54,36 +54,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "libsass",
|
||||
"buildsystem" : "meson",
|
||||
"builddir" : true,
|
||||
"config-opts": [
|
||||
"--libdir=/app/lib"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/lazka/libsass.git",
|
||||
"branch" : "meson"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "sassc",
|
||||
"buildsystem" : "meson",
|
||||
"builddir" : true,
|
||||
"config-opts": [
|
||||
"--libdir=/app/lib"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/lazka/sassc.git",
|
||||
"branch" : "meson"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "gtk",
|
||||
"buildsystem": "meson",
|
||||
|
@@ -221,12 +221,9 @@ open_cb (GtkWidget *button,
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
"_Load",
|
||||
"_Cancel");
|
||||
|
||||
gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (dialog), TRUE);
|
||||
|
||||
GFile *cwd = g_file_new_for_path (".");
|
||||
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), cwd, NULL);
|
||||
g_object_unref (cwd);
|
||||
|
||||
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), ".");
|
||||
g_signal_connect (dialog, "response", G_CALLBACK (open_response_cb), self);
|
||||
gtk_native_dialog_show (GTK_NATIVE_DIALOG (dialog));
|
||||
}
|
||||
@@ -293,37 +290,29 @@ save_response_cb (GtkNativeDialog *dialog,
|
||||
if (response == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
GListModel *model;
|
||||
GFile *file;
|
||||
char *text;
|
||||
char *text, *filename;
|
||||
GError *error = NULL;
|
||||
|
||||
model = constraint_view_get_model (CONSTRAINT_VIEW (self->view));
|
||||
text = serialize_model (model);
|
||||
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
|
||||
g_file_replace_contents (file, text, -1,
|
||||
NULL, FALSE,
|
||||
G_FILE_CREATE_NONE,
|
||||
NULL,
|
||||
NULL,
|
||||
&error);
|
||||
if (error != NULL)
|
||||
{
|
||||
GtkWidget *message_dialog;
|
||||
|
||||
message_dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self))),
|
||||
GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_INFO,
|
||||
GTK_BUTTONS_OK,
|
||||
"Saving failed");
|
||||
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message_dialog),
|
||||
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
|
||||
if (!g_file_set_contents (filename, text, -1, &error))
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
|
||||
dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self))),
|
||||
GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_INFO,
|
||||
GTK_BUTTONS_OK,
|
||||
"Saving failed");
|
||||
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
|
||||
"%s", error->message);
|
||||
g_signal_connect (message_dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
|
||||
gtk_widget_show (message_dialog);
|
||||
g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
|
||||
gtk_widget_show (dialog);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_free (text);
|
||||
g_object_unref (file);
|
||||
g_free (filename);
|
||||
}
|
||||
|
||||
gtk_native_dialog_destroy (dialog);
|
||||
@@ -340,12 +329,9 @@ save_cb (GtkWidget *button,
|
||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
"_Save",
|
||||
"_Cancel");
|
||||
|
||||
gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (dialog), TRUE);
|
||||
|
||||
GFile *cwd = g_file_new_for_path (".");
|
||||
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), cwd, NULL);
|
||||
g_object_unref (cwd);
|
||||
|
||||
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), ".");
|
||||
g_signal_connect (dialog, "response", G_CALLBACK (save_response_cb), self);
|
||||
gtk_native_dialog_show (GTK_NATIVE_DIALOG (dialog));
|
||||
}
|
||||
@@ -414,7 +400,7 @@ edit_constraint (ConstraintEditorWindow *win,
|
||||
ConstraintEditor *editor;
|
||||
GListModel *model;
|
||||
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (win));
|
||||
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
|
||||
if (constraint)
|
||||
@@ -454,7 +440,7 @@ edit_guide (ConstraintEditorWindow *win,
|
||||
GtkWidget *window;
|
||||
GuideEditor *editor;
|
||||
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
|
||||
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (win));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Edit Guide");
|
||||
@@ -601,10 +587,7 @@ create_widget_func (gpointer 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);
|
||||
g_object_set (label, "margin", 10, NULL);
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
|
||||
gtk_widget_set_hexpand (label, TRUE);
|
||||
gtk_container_add (GTK_CONTAINER (row), box);
|
||||
|
@@ -3,10 +3,7 @@
|
||||
<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="margin">20</property>
|
||||
<property name="row-spacing">10</property>
|
||||
<property name="column-spacing">10</property>
|
||||
<child>
|
||||
|
@@ -77,7 +77,7 @@ update_weak_position (ConstraintView *self,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
x,
|
||||
GTK_CONSTRAINT_STRENGTH_WEAK);
|
||||
g_object_set_data (G_OBJECT (constraint), "internal", (char *)"yes");
|
||||
g_object_set_data (G_OBJECT (constraint), "internal", "yes");
|
||||
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (manager),
|
||||
constraint);
|
||||
g_object_set_data (G_OBJECT (child), "x-constraint", constraint);
|
||||
@@ -97,7 +97,7 @@ update_weak_position (ConstraintView *self,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
y,
|
||||
GTK_CONSTRAINT_STRENGTH_WEAK);
|
||||
g_object_set_data (G_OBJECT (constraint), "internal", (char *)"yes");
|
||||
g_object_set_data (G_OBJECT (constraint), "internal", "yes");
|
||||
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (manager),
|
||||
constraint);
|
||||
g_object_set_data (G_OBJECT (child), "y-constraint", constraint);
|
||||
@@ -169,6 +169,7 @@ constraint_view_init (ConstraintView *self)
|
||||
GListModel *guides;
|
||||
GListModel *children;
|
||||
GListModel *constraints;
|
||||
GtkFilter *filter;
|
||||
|
||||
manager = gtk_constraint_layout_new ();
|
||||
gtk_widget_set_layout_manager (GTK_WIDGET (self), manager);
|
||||
@@ -176,8 +177,12 @@ constraint_view_init (ConstraintView *self)
|
||||
all_children = gtk_widget_observe_children (GTK_WIDGET (self));
|
||||
all_constraints = gtk_constraint_layout_observe_constraints (GTK_CONSTRAINT_LAYOUT (manager));
|
||||
guides = gtk_constraint_layout_observe_guides (GTK_CONSTRAINT_LAYOUT (manager));
|
||||
constraints = (GListModel *)gtk_filter_list_model_new (all_constraints, omit_internal, NULL, NULL);
|
||||
children = (GListModel *)gtk_filter_list_model_new (all_children, omit_internal, NULL, NULL);
|
||||
filter = gtk_custom_filter_new (omit_internal, NULL, NULL);
|
||||
constraints = (GListModel *)gtk_filter_list_model_new (all_constraints, filter);
|
||||
g_object_unref (filter);
|
||||
filter = gtk_custom_filter_new (omit_internal, NULL, NULL);
|
||||
children = (GListModel *)gtk_filter_list_model_new (all_children, filter);
|
||||
g_object_unref (filter);
|
||||
|
||||
list = g_list_store_new (G_TYPE_LIST_MODEL);
|
||||
g_list_store_append (list, children);
|
||||
@@ -258,7 +263,7 @@ constraint_view_add_guide (ConstraintView *view,
|
||||
|
||||
frame = gtk_frame_new (NULL);
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (frame), "guide");
|
||||
g_object_set_data (G_OBJECT (frame), "internal", (char *)"yes");
|
||||
g_object_set_data (G_OBJECT (frame), "internal", "yes");
|
||||
gtk_container_add (GTK_CONTAINER (frame), label);
|
||||
gtk_widget_insert_after (frame, GTK_WIDGET (view), NULL);
|
||||
|
||||
@@ -276,7 +281,7 @@ constraint_view_add_guide (ConstraintView *view,
|
||||
names[i].attr,
|
||||
1.0, 0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
g_object_set_data (G_OBJECT (constraint), "internal", (char *)"yes");
|
||||
g_object_set_data (G_OBJECT (constraint), "internal", "yes");
|
||||
gtk_constraint_layout_add_constraint (layout, constraint);
|
||||
g_object_set_data (G_OBJECT (guide), names[i].name, constraint);
|
||||
}
|
||||
|
@@ -78,7 +78,7 @@ get_strength (const char *id)
|
||||
return strength;
|
||||
}
|
||||
|
||||
static const char *
|
||||
const char *
|
||||
get_strength_nick (GtkConstraintStrength strength)
|
||||
{
|
||||
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_STRENGTH);
|
||||
@@ -184,58 +184,6 @@ max_input (GtkSpinButton *spin_button,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
min_output (GtkSpinButton *spin_button)
|
||||
{
|
||||
GtkAdjustment *adjustment;
|
||||
double value;
|
||||
GtkWidget *box, *text;
|
||||
|
||||
adjustment = gtk_spin_button_get_adjustment (spin_button);
|
||||
value = gtk_adjustment_get_value (adjustment);
|
||||
|
||||
box = gtk_widget_get_first_child (GTK_WIDGET (spin_button));
|
||||
text = gtk_widget_get_first_child (box);
|
||||
|
||||
if (value == 0.0)
|
||||
{
|
||||
gtk_editable_set_text (GTK_EDITABLE (spin_button), "");
|
||||
gtk_text_set_placeholder_text (GTK_TEXT (text), "unset");
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_text_set_placeholder_text (GTK_TEXT (text), "");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
max_output (GtkSpinButton *spin_button)
|
||||
{
|
||||
GtkAdjustment *adjustment;
|
||||
double value;
|
||||
GtkWidget *box, *text;
|
||||
|
||||
adjustment = gtk_spin_button_get_adjustment (spin_button);
|
||||
value = gtk_adjustment_get_value (adjustment);
|
||||
|
||||
box = gtk_widget_get_first_child (GTK_WIDGET (spin_button));
|
||||
text = gtk_widget_get_first_child (box);
|
||||
|
||||
if (value == (double)G_MAXINT)
|
||||
{
|
||||
gtk_editable_set_text (GTK_EDITABLE (spin_button), "");
|
||||
gtk_text_set_placeholder_text (GTK_TEXT (text), "unset");
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_text_set_placeholder_text (GTK_TEXT (text), "");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
guide_editor_constructed (GObject *object)
|
||||
{
|
||||
@@ -244,16 +192,12 @@ guide_editor_constructed (GObject *object)
|
||||
guide_strength_combo (editor->strength);
|
||||
|
||||
g_signal_connect (editor->min_width, "input", G_CALLBACK (min_input), NULL);
|
||||
g_signal_connect (editor->min_width, "output", G_CALLBACK (min_output), NULL);
|
||||
|
||||
g_signal_connect (editor->min_height, "input", G_CALLBACK (min_input), NULL);
|
||||
g_signal_connect (editor->min_height, "output", G_CALLBACK (min_output), NULL);
|
||||
|
||||
g_signal_connect (editor->max_width, "input", G_CALLBACK (max_input), NULL);
|
||||
g_signal_connect (editor->max_width, "output", G_CALLBACK (max_output), NULL);
|
||||
|
||||
g_signal_connect (editor->max_height, "input", G_CALLBACK (max_input), NULL);
|
||||
g_signal_connect (editor->max_height, "output", G_CALLBACK (max_output), NULL);
|
||||
|
||||
if (editor->guide)
|
||||
{
|
||||
|
@@ -45,10 +45,7 @@
|
||||
<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="margin">20</property>
|
||||
<property name="row-spacing">10</property>
|
||||
<property name="column-spacing">10</property>
|
||||
<child>
|
||||
|
@@ -13,7 +13,6 @@ constraint_editor_resources = gnome.compile_resources('constraint_editor_resourc
|
||||
|
||||
executable('gtk4-constraint-editor',
|
||||
constraint_editor_sources, constraint_editor_resources,
|
||||
c_args: common_cflags,
|
||||
dependencies: libgtk_dep,
|
||||
include_directories: confinc,
|
||||
gui_app: true,
|
||||
|
@@ -6,7 +6,6 @@
|
||||
typedef GtkApplication DemoApplication;
|
||||
typedef GtkApplicationClass DemoApplicationClass;
|
||||
|
||||
static GType demo_application_get_type (void);
|
||||
G_DEFINE_TYPE (DemoApplication, demo_application, GTK_TYPE_APPLICATION)
|
||||
|
||||
typedef struct {
|
||||
@@ -15,7 +14,7 @@ typedef struct {
|
||||
GtkWidget *message;
|
||||
GtkWidget *infobar;
|
||||
GtkWidget *status;
|
||||
GtkWidget *menubutton;
|
||||
GtkWidget *menutool;
|
||||
GMenuModel *toolmenu;
|
||||
GtkTextBuffer *buffer;
|
||||
|
||||
@@ -26,7 +25,6 @@ typedef struct {
|
||||
} DemoApplicationWindow;
|
||||
typedef GtkApplicationWindowClass DemoApplicationWindowClass;
|
||||
|
||||
static GType demo_application_window_get_type (void);
|
||||
G_DEFINE_TYPE (DemoApplicationWindow, demo_application_window, GTK_TYPE_APPLICATION_WINDOW)
|
||||
|
||||
static void create_window (GApplication *app, const char *contents);
|
||||
@@ -421,7 +419,7 @@ demo_application_window_load_state (DemoApplicationWindow *win)
|
||||
static void
|
||||
demo_application_window_init (DemoApplicationWindow *window)
|
||||
{
|
||||
GtkWidget *popover;
|
||||
GtkWidget *menu;
|
||||
|
||||
window->width = -1;
|
||||
window->height = -1;
|
||||
@@ -430,8 +428,8 @@ demo_application_window_init (DemoApplicationWindow *window)
|
||||
|
||||
gtk_widget_init_template (GTK_WIDGET (window));
|
||||
|
||||
popover = gtk_popover_menu_new_from_model (window->toolmenu);
|
||||
gtk_menu_button_set_popover (GTK_MENU_BUTTON (window->menubutton), popover);
|
||||
menu = gtk_menu_new_from_model (window->toolmenu);
|
||||
gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (window->menutool), menu);
|
||||
|
||||
g_action_map_add_action_entries (G_ACTION_MAP (window),
|
||||
win_entries, G_N_ELEMENTS (win_entries),
|
||||
@@ -479,7 +477,7 @@ surface_state_changed (GtkWidget *widget)
|
||||
DemoApplicationWindow *window = (DemoApplicationWindow *)widget;
|
||||
GdkSurfaceState new_state;
|
||||
|
||||
new_state = gdk_toplevel_get_state (GDK_TOPLEVEL (gtk_native_get_surface (GTK_NATIVE (widget))));
|
||||
new_state = gdk_surface_get_state (gtk_native_get_surface (GTK_NATIVE (widget)));
|
||||
window->maximized = (new_state & GDK_SURFACE_STATE_MAXIMIZED) != 0;
|
||||
window->fullscreen = (new_state & GDK_SURFACE_STATE_FULLSCREEN) != 0;
|
||||
}
|
||||
@@ -530,7 +528,7 @@ demo_application_window_class_init (DemoApplicationWindowClass *class)
|
||||
gtk_widget_class_bind_template_child (widget_class, DemoApplicationWindow, infobar);
|
||||
gtk_widget_class_bind_template_child (widget_class, DemoApplicationWindow, status);
|
||||
gtk_widget_class_bind_template_child (widget_class, DemoApplicationWindow, buffer);
|
||||
gtk_widget_class_bind_template_child (widget_class, DemoApplicationWindow, menubutton);
|
||||
gtk_widget_class_bind_template_child (widget_class, DemoApplicationWindow, menutool);
|
||||
gtk_widget_class_bind_template_child (widget_class, DemoApplicationWindow, toolmenu);
|
||||
gtk_widget_class_bind_template_callback (widget_class, clicked_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, update_statusbar);
|
||||
|
@@ -8,24 +8,27 @@
|
||||
<child>
|
||||
<object class="GtkGrid">
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<object class="GtkToolbar">
|
||||
<property name="hexpand">1</property>
|
||||
<style>
|
||||
<class name="primary-toolbar"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkMenuButton" id="menubutton">
|
||||
<object class="GtkMenuToolButton" id="menutool">
|
||||
<property name="icon-name">document-open</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<object class="GtkToolButton">
|
||||
<property name="icon-name">application-exit</property>
|
||||
<property name="action-name">app.quit</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator"/>
|
||||
<object class="GtkSeparatorToolItem"/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<object class="GtkToolButton">
|
||||
<property name="icon-name">applications-other</property>
|
||||
<property name="action-name">win.logo</property>
|
||||
</object>
|
||||
@@ -40,17 +43,25 @@
|
||||
<object class="GtkInfoBar" id="infobar">
|
||||
<property name="visible">0</property>
|
||||
<property name="hexpand">1</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="message">
|
||||
<property name="hexpand">1</property>
|
||||
<child internal-child="content_area">
|
||||
<object class="GtkBox" id="content_area">
|
||||
<child>
|
||||
<object class="GtkLabel" id="message">
|
||||
<property name="hexpand">1</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="action">
|
||||
<object class="GtkButton">
|
||||
<property name="valign">center</property>
|
||||
<property name="label" translatable="yes">_OK</property>
|
||||
<property name="use-underline">1</property>
|
||||
<signal name="clicked" handler="clicked_cb"/>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="valign">center</property>
|
||||
<property name="label" translatable="yes">_OK</property>
|
||||
<property name="use-underline">1</property>
|
||||
<signal name="clicked" handler="clicked_cb"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<layout>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/*static GtkWidget *assistant = NULL;*/
|
||||
static GtkWidget *assistant = NULL;
|
||||
static GtkWidget *progress_bar = NULL;
|
||||
|
||||
static gboolean
|
||||
@@ -27,7 +27,8 @@ apply_changes_gradually (gpointer data)
|
||||
else
|
||||
{
|
||||
/* Close automatically once changes are fully applied. */
|
||||
gtk_widget_destroy (data);
|
||||
gtk_widget_destroy (assistant);
|
||||
assistant = NULL;
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
}
|
||||
@@ -36,7 +37,7 @@ static void
|
||||
on_assistant_apply (GtkWidget *widget, gpointer data)
|
||||
{
|
||||
/* Start a timer to simulate changes taking a few seconds to apply. */
|
||||
g_timeout_add (100, apply_changes_gradually, widget);
|
||||
g_timeout_add (100, apply_changes_gradually, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -93,10 +94,6 @@ create_page1 (GtkWidget *assistant)
|
||||
GtkWidget *box, *label, *entry;
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
|
||||
gtk_widget_set_margin_start (box, 12);
|
||||
gtk_widget_set_margin_end (box, 12);
|
||||
gtk_widget_set_margin_top (box, 12);
|
||||
gtk_widget_set_margin_bottom (box, 12);
|
||||
|
||||
label = gtk_label_new ("You must fill out this entry to continue:");
|
||||
gtk_container_add (GTK_CONTAINER (box), label);
|
||||
@@ -118,15 +115,10 @@ create_page2 (GtkWidget *assistant)
|
||||
{
|
||||
GtkWidget *box, *checkbutton;
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
|
||||
gtk_widget_set_margin_start (box, 12);
|
||||
gtk_widget_set_margin_end (box, 12);
|
||||
gtk_widget_set_margin_top (box, 12);
|
||||
gtk_widget_set_margin_bottom (box, 12);
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
||||
|
||||
checkbutton = gtk_check_button_new_with_label ("This is optional data, you may continue "
|
||||
"even if you do not check this");
|
||||
gtk_widget_set_valign (checkbutton, GTK_ALIGN_CENTER);
|
||||
gtk_container_add (GTK_CONTAINER (box), checkbutton);
|
||||
|
||||
gtk_assistant_append_page (GTK_ASSISTANT (assistant), box);
|
||||
@@ -172,8 +164,6 @@ create_page4 (GtkWidget *assistant)
|
||||
GtkWidget*
|
||||
do_assistant (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *assistant;
|
||||
|
||||
if (!assistant)
|
||||
{
|
||||
assistant = gtk_assistant_new ();
|
||||
|
247
demos/gtk-demo/award.c
Normal file
247
demos/gtk-demo/award.c
Normal file
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Copyright © 2018 Benjamin Otte
|
||||
*
|
||||
* 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: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "award.h"
|
||||
|
||||
struct _GtkAward
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
char *explanation;
|
||||
char *name;
|
||||
char *title;
|
||||
GDateTime *granted; /* or NULL if not granted */
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_EXPLANATION,
|
||||
PROP_NAME,
|
||||
PROP_TITLE,
|
||||
PROP_GRANTED,
|
||||
|
||||
N_PROPS,
|
||||
};
|
||||
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
G_DEFINE_TYPE (GtkAward, gtk_award, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gtk_award_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
|
||||
{
|
||||
GtkAward *self = GTK_AWARD (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_EXPLANATION:
|
||||
self->explanation = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
self->name = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_TITLE:
|
||||
self->title = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_award_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkAward *self = GTK_AWARD (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_EXPLANATION:
|
||||
g_value_set_string (value, self->explanation);
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, self->name);
|
||||
break;
|
||||
|
||||
case PROP_TITLE:
|
||||
g_value_set_string (value, self->title);
|
||||
break;
|
||||
|
||||
case PROP_GRANTED:
|
||||
g_value_set_boxed (value, self->granted);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_award_dispose (GObject *object)
|
||||
{
|
||||
GtkAward *self = GTK_AWARD (object);
|
||||
|
||||
g_clear_pointer (&self->name, g_free);
|
||||
g_clear_pointer (&self->title, g_free);
|
||||
g_clear_pointer (&self->granted, g_date_time_unref);
|
||||
|
||||
G_OBJECT_CLASS (gtk_award_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_award_class_init (GtkAwardClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
||||
|
||||
gobject_class->set_property = gtk_award_set_property;
|
||||
gobject_class->get_property = gtk_award_get_property;
|
||||
gobject_class->dispose = gtk_award_dispose;
|
||||
|
||||
properties[PROP_EXPLANATION] =
|
||||
g_param_spec_string ("explanation",
|
||||
"Explanation",
|
||||
"How to get the title",
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_NAME] =
|
||||
g_param_spec_string ("name",
|
||||
"Name",
|
||||
"internal name of the award",
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_TITLE] =
|
||||
g_param_spec_string ("title",
|
||||
"Title",
|
||||
"user-visible title",
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_GRANTED] =
|
||||
g_param_spec_boxed ("granted",
|
||||
"Granted",
|
||||
"Timestamp the award was granted or NULL if not granted yet",
|
||||
G_TYPE_DATE_TIME,
|
||||
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_award_init (GtkAward *self)
|
||||
{
|
||||
}
|
||||
|
||||
GListModel *
|
||||
gtk_award_get_list (void)
|
||||
{
|
||||
static GListModel *list = NULL;
|
||||
|
||||
if (list == NULL)
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
|
||||
g_type_ensure (GTK_TYPE_AWARD);
|
||||
builder = gtk_builder_new_from_resource ("/awards.ui");
|
||||
list = G_LIST_MODEL (gtk_builder_get_object (builder, "list"));
|
||||
g_object_ref (list);
|
||||
g_object_unref (builder);
|
||||
}
|
||||
|
||||
return g_object_ref (list);
|
||||
}
|
||||
|
||||
const char *
|
||||
gtk_award_get_name (GtkAward *award)
|
||||
{
|
||||
return award->name;
|
||||
}
|
||||
|
||||
const char *
|
||||
gtk_award_get_title (GtkAward *award)
|
||||
{
|
||||
return award->title;
|
||||
}
|
||||
|
||||
GDateTime *
|
||||
gtk_award_get_granted (GtkAward *award)
|
||||
{
|
||||
return award->granted;
|
||||
}
|
||||
|
||||
GtkAward *
|
||||
award_find (const char *name)
|
||||
{
|
||||
GListModel *list;
|
||||
GtkAward *self;
|
||||
guint i;
|
||||
|
||||
list = gtk_award_get_list ();
|
||||
g_object_unref (list);
|
||||
|
||||
for (i = 0; i < g_list_model_get_n_items (list); i++)
|
||||
{
|
||||
self = g_list_model_get_item (list, i);
|
||||
g_object_unref (self);
|
||||
|
||||
if (g_ascii_strcasecmp (name, self->name) == 0)
|
||||
return self;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
award (const char *name)
|
||||
{
|
||||
GtkAward *self;
|
||||
GNotification *notification;
|
||||
|
||||
self = award_find (name);
|
||||
if (self == NULL)
|
||||
{
|
||||
g_warning ("Did not find award \"%s\"", name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->granted)
|
||||
return;
|
||||
|
||||
self->granted = g_date_time_new_now_utc ();
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_GRANTED]);
|
||||
|
||||
notification = g_notification_new ("You won an award!");
|
||||
g_notification_set_body (notification, self->title);
|
||||
g_application_send_notification (g_application_get_default (), NULL, notification);
|
||||
g_object_unref (notification);
|
||||
}
|
||||
|
18
demos/gtk-demo/award.h
Normal file
18
demos/gtk-demo/award.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef __AWARD_H__
|
||||
#define __AWARD_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#define GTK_TYPE_AWARD (gtk_award_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GtkAward, gtk_award, GTK, AWARD, GObject)
|
||||
|
||||
GListModel * gtk_award_get_list (void);
|
||||
|
||||
const char * gtk_award_get_name (GtkAward *award);
|
||||
const char * gtk_award_get_title (GtkAward *award);
|
||||
GDateTime * gtk_award_get_granted (GtkAward *award);
|
||||
|
||||
void award (const char *name);
|
||||
|
||||
#endif /* __AWARD_H__ */
|
11
demos/gtk-demo/awardlistitem.ui
Normal file
11
demos/gtk-demo/awardlistitem.ui
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface domain="gtk40">
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="label" bind-source="GtkListItem" bind-property="position"></property>
|
||||
<property name="margin">6</property>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
89
demos/gtk-demo/awards.ui
Normal file
89
demos/gtk-demo/awards.ui
Normal file
@@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<object class="GListStore" id="list">
|
||||
<property name="item-type">GtkAward</property>
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">demo-inspector</property>
|
||||
<!-- Transformers -->
|
||||
<property name="title" translatable="yes">You got a high-rise double-pump carburetor.</property>
|
||||
<property name="explanation" translatable="yes">Launch the inspector</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">demo-start</property>
|
||||
<!-- The Matrix -->
|
||||
<property name="title" translatable="yes">After this, there is no turning back.</property>
|
||||
<property name="explanation" translatable="yes">Start gtk-demo</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">listbox-reshare</property>
|
||||
<!-- Mean Girls -->
|
||||
<property name="title" translatable="yes">Trying to make fetch happen</property>
|
||||
<property name="explanation" translatable="yes">Reshare a tweet</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">listbox-100th-row</property>
|
||||
<!-- Aladdin -->
|
||||
<property name="title" translatable="yes">The ever impressive, long contained, often imitated, but never duplicated Genie of the lamp.</property>
|
||||
<property name="explanation" translatable="yes">Select a 100th row in a list</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">password-best</property>
|
||||
<!-- Spaceballs -->
|
||||
<property name="title" translatable="yes">I've got the same combination on my luggage!</property>
|
||||
<property name="explanation" translatable="yes">Use "12345" as the password</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">password-correct</property>
|
||||
<!-- Stanley Parable -->
|
||||
<property name="title" translatable="yes">Night Shark 1-1-5</property>
|
||||
<property name="explanation" translatable="yes">Correctly enter a password</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">puzzle-give-up</property>
|
||||
<!-- Pretty Woman -->
|
||||
<property name="title" translatable="yes">Big Mistake. Big. Huge!</property>
|
||||
<property name="explanation" translatable="yes">Close the puzzle without finishing it</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">puzzle-solve</property>
|
||||
<!-- The Incredibles -->
|
||||
<property name="title" translatable="yes">That was totally wicked!</property>
|
||||
<property name="explanation" translatable="yes">Solve a puzzle</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">puzzle-solve-animated</property>
|
||||
<!-- The Phantom Menace -->
|
||||
<property name="title" translatable="yes">A surprise to be sure but a welcome one.</property>
|
||||
<property name="explanation" translatable="yes">Solve an animated puzzle</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">puzzle-solve-large</property>
|
||||
<!-- Portal -->
|
||||
<property name="title" translatable="yes">Science isn't about WHY. It's about WHY NOT?!</property>
|
||||
<property name="explanation" translatable="yes">Solve a puzzle with at least 20 pieces</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
49
demos/gtk-demo/awardview.c
Normal file
49
demos/gtk-demo/awardview.c
Normal file
@@ -0,0 +1,49 @@
|
||||
/* Awards
|
||||
*
|
||||
* This demo demonstrates how to use lists to show the awards you have collected
|
||||
* while exploring this demo.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/* Include the header for accessing the awards */
|
||||
#include "award.h"
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
GtkWidget *
|
||||
do_awardview (GtkWidget *do_widget)
|
||||
{
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *sw, *listview;
|
||||
GListModel *list;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Awards");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
sw = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), sw);
|
||||
|
||||
listview = gtk_list_view_new_with_factory (
|
||||
gtk_builder_list_item_factory_new_from_resource (NULL, "/awardview/awardlistitem.ui"));
|
||||
list = gtk_award_get_list ();
|
||||
gtk_list_view_set_model (GTK_LIST_VIEW (listview), list);
|
||||
g_object_unref (list);
|
||||
gtk_list_view_set_show_separators (GTK_LIST_VIEW (listview), TRUE);
|
||||
gtk_container_add (GTK_CONTAINER (sw), listview);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
@@ -38,22 +38,7 @@ help_activate (GSimpleAction *action,
|
||||
g_print ("Help not available\n");
|
||||
}
|
||||
|
||||
static void
|
||||
not_implemented (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_print ("Action “%s” not implemented\n", g_action_get_name (G_ACTION (action)));
|
||||
}
|
||||
|
||||
static GActionEntry win_entries[] = {
|
||||
{ "new", not_implemented, NULL, NULL, NULL },
|
||||
{ "open", not_implemented, NULL, NULL, NULL },
|
||||
{ "save", not_implemented, NULL, NULL, NULL },
|
||||
{ "save-as", not_implemented, NULL, NULL, NULL },
|
||||
{ "copy", not_implemented, NULL, NULL, NULL },
|
||||
{ "cut", not_implemented, NULL, NULL, NULL },
|
||||
{ "paste", not_implemented, NULL, NULL, NULL },
|
||||
{ "quit", quit_activate, NULL, NULL, NULL },
|
||||
{ "about", about_activate, NULL, NULL, NULL },
|
||||
{ "help", help_activate, NULL, NULL, NULL }
|
||||
@@ -63,7 +48,10 @@ GtkWidget *
|
||||
do_builder (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
GtkWidget *toolbar;
|
||||
GActionGroup *actions;
|
||||
GtkAccelGroup *accel_group;
|
||||
GtkWidget *item;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
@@ -76,11 +64,52 @@ do_builder (GtkWidget *do_widget)
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
toolbar = GTK_WIDGET (gtk_builder_get_object (builder, "toolbar1"));
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (toolbar),
|
||||
"primary-toolbar");
|
||||
actions = (GActionGroup*)g_simple_action_group_new ();
|
||||
g_action_map_add_action_entries (G_ACTION_MAP (actions),
|
||||
win_entries, G_N_ELEMENTS (win_entries),
|
||||
window);
|
||||
gtk_widget_insert_action_group (window, "win", actions);
|
||||
accel_group = gtk_accel_group_new ();
|
||||
gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
|
||||
|
||||
item = (GtkWidget*)gtk_builder_get_object (builder, "new_item");
|
||||
gtk_widget_add_accelerator (item, "activate", accel_group,
|
||||
GDK_KEY_n, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
|
||||
|
||||
item = (GtkWidget*)gtk_builder_get_object (builder, "open_item");
|
||||
gtk_widget_add_accelerator (item, "activate", accel_group,
|
||||
GDK_KEY_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
|
||||
|
||||
item = (GtkWidget*)gtk_builder_get_object (builder, "save_item");
|
||||
gtk_widget_add_accelerator (item, "activate", accel_group,
|
||||
GDK_KEY_s, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
|
||||
|
||||
item = (GtkWidget*)gtk_builder_get_object (builder, "quit_item");
|
||||
gtk_widget_add_accelerator (item, "activate", accel_group,
|
||||
GDK_KEY_q, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
|
||||
|
||||
item = (GtkWidget*)gtk_builder_get_object (builder, "copy_item");
|
||||
gtk_widget_add_accelerator (item, "activate", accel_group,
|
||||
GDK_KEY_c, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
|
||||
|
||||
item = (GtkWidget*)gtk_builder_get_object (builder, "cut_item");
|
||||
gtk_widget_add_accelerator (item, "activate", accel_group,
|
||||
GDK_KEY_x, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
|
||||
|
||||
item = (GtkWidget*)gtk_builder_get_object (builder, "paste_item");
|
||||
gtk_widget_add_accelerator (item, "activate", accel_group,
|
||||
GDK_KEY_v, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
|
||||
|
||||
item = (GtkWidget*)gtk_builder_get_object (builder, "help_item");
|
||||
gtk_widget_add_accelerator (item, "activate", accel_group,
|
||||
GDK_KEY_F1, 0, GTK_ACCEL_VISIBLE);
|
||||
|
||||
item = (GtkWidget*)gtk_builder_get_object (builder, "about_item");
|
||||
gtk_widget_add_accelerator (item, "activate", accel_group,
|
||||
GDK_KEY_F7, 0, GTK_ACCEL_VISIBLE);
|
||||
|
||||
g_object_set_data_full (G_OBJECT(window), "builder", builder, g_object_unref);
|
||||
}
|
||||
|
551
demos/gtk-demo/changedisplay.c
Normal file
551
demos/gtk-demo/changedisplay.c
Normal file
@@ -0,0 +1,551 @@
|
||||
/* Change Display
|
||||
*
|
||||
* Demonstrates migrating a window between different displays.
|
||||
* A display is a mouse and keyboard with some number of
|
||||
* associated monitors. The neat thing about having multiple
|
||||
* displays is that they can be on a completely separate
|
||||
* computers, as long as there is a network connection to the
|
||||
* computer where the application is running.
|
||||
*
|
||||
* Only some of the windowing systems where GTK runs have the
|
||||
* concept of multiple displays. (The X Window System is the
|
||||
* main example.) Other windowing systems can only handle one
|
||||
* keyboard and mouse, and combine all monitors into
|
||||
* a single display.
|
||||
*
|
||||
* This is a moderately complex example, and demonstrates:
|
||||
*
|
||||
* - Tracking the currently open displays
|
||||
*
|
||||
* - Changing the display for a window
|
||||
*
|
||||
* - Letting the user choose a window by clicking on it
|
||||
*
|
||||
* - Using GtkListStore and GtkTreeView
|
||||
*
|
||||
* - Using GtkDialog
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/* The ChangeDisplayInfo structure corresponds to a toplevel window and
|
||||
* holds pointers to widgets inside the toplevel window along with other
|
||||
* information about the contents of the window.
|
||||
* This is a common organizational structure in real applications.
|
||||
*/
|
||||
typedef struct _ChangeDisplayInfo ChangeDisplayInfo;
|
||||
|
||||
struct _ChangeDisplayInfo
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkSizeGroup *size_group;
|
||||
|
||||
GtkTreeModel *display_model;
|
||||
|
||||
GdkDisplay *current_display;
|
||||
};
|
||||
|
||||
/* These enumerations provide symbolic names for the columns
|
||||
* in the two GtkListStore models.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
DISPLAY_COLUMN_NAME,
|
||||
DISPLAY_COLUMN_DISPLAY,
|
||||
DISPLAY_NUM_COLUMNS
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SCREEN_COLUMN_NUMBER,
|
||||
SCREEN_COLUMN_SCREEN,
|
||||
SCREEN_NUM_COLUMNS
|
||||
};
|
||||
|
||||
/* Finds the toplevel window under the mouse pointer, if any.
|
||||
*/
|
||||
static GtkWidget *
|
||||
find_toplevel_at_pointer (GdkDisplay *display)
|
||||
{
|
||||
GdkSurface *pointer_window;
|
||||
GtkWidget *widget = NULL;
|
||||
|
||||
pointer_window = gdk_device_get_surface_at_position (gtk_get_current_event_device (), NULL, NULL);
|
||||
|
||||
if (pointer_window)
|
||||
widget = GTK_WIDGET (gtk_native_get_for_surface (pointer_window));
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
static void
|
||||
released_cb (GtkGestureClick *gesture,
|
||||
guint n_press,
|
||||
gdouble x,
|
||||
gdouble y,
|
||||
gboolean *clicked)
|
||||
{
|
||||
*clicked = TRUE;
|
||||
}
|
||||
|
||||
/* Asks the user to click on a window, then waits for them click
|
||||
* the mouse. When the mouse is released, returns the toplevel
|
||||
* window under the pointer, or NULL, if there is none.
|
||||
*/
|
||||
static GtkWidget *
|
||||
query_for_toplevel (GdkDisplay *display,
|
||||
const char *prompt)
|
||||
{
|
||||
GtkWidget *popup, *label, *frame;
|
||||
GdkCursor *cursor;
|
||||
GtkWidget *toplevel = NULL;
|
||||
GdkDevice *device;
|
||||
|
||||
popup = gtk_window_new (GTK_WINDOW_POPUP);
|
||||
gtk_window_set_display (GTK_WINDOW (popup), display);
|
||||
gtk_window_set_modal (GTK_WINDOW (popup), TRUE);
|
||||
|
||||
frame = gtk_frame_new (NULL);
|
||||
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
|
||||
gtk_container_add (GTK_CONTAINER (popup), frame);
|
||||
|
||||
label = gtk_label_new (prompt);
|
||||
g_object_set (label, "margin", 10, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (frame), label);
|
||||
|
||||
gtk_widget_show (popup);
|
||||
cursor = gdk_cursor_new_from_name ("crosshair", NULL);
|
||||
device = gtk_get_current_event_device ();
|
||||
|
||||
if (gdk_seat_grab (gdk_device_get_seat (device),
|
||||
gtk_native_get_surface (GTK_NATIVE (popup)),
|
||||
GDK_SEAT_CAPABILITY_ALL_POINTING,
|
||||
FALSE, cursor, NULL, NULL, NULL) == GDK_GRAB_SUCCESS)
|
||||
{
|
||||
GtkGesture *gesture = gtk_gesture_click_new ();
|
||||
gboolean clicked = FALSE;
|
||||
|
||||
g_signal_connect (gesture, "released",
|
||||
G_CALLBACK (released_cb), &clicked);
|
||||
gtk_widget_add_controller (popup, GTK_EVENT_CONTROLLER (gesture));
|
||||
|
||||
/* Process events until clicked is set by our button release event handler.
|
||||
* We pass in may_block=TRUE since we want to wait if there
|
||||
* are no events currently.
|
||||
*/
|
||||
while (!clicked)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
|
||||
gdk_seat_ungrab (gdk_device_get_seat (device));
|
||||
|
||||
toplevel = find_toplevel_at_pointer (display);
|
||||
if (toplevel == popup)
|
||||
toplevel = NULL;
|
||||
}
|
||||
|
||||
g_object_unref (cursor);
|
||||
gtk_widget_destroy (popup);
|
||||
|
||||
return toplevel;
|
||||
}
|
||||
|
||||
/* Prompts the user for a toplevel window to move, and then moves
|
||||
* that window to the currently selected display
|
||||
*/
|
||||
static void
|
||||
query_change_display (ChangeDisplayInfo *info)
|
||||
{
|
||||
GdkDisplay *display = gtk_widget_get_display (info->window);
|
||||
GtkWidget *toplevel;
|
||||
|
||||
toplevel = query_for_toplevel (display,
|
||||
"Please select the toplevel\n"
|
||||
"to move to the new display");
|
||||
|
||||
if (toplevel)
|
||||
gtk_window_set_display (GTK_WINDOW (toplevel), info->current_display);
|
||||
else
|
||||
gdk_display_beep (display);
|
||||
}
|
||||
|
||||
/* Called when the user clicks on a button in our dialog or
|
||||
* closes the dialog through the window manager. Unless the
|
||||
* "Change" button was clicked, we destroy the dialog.
|
||||
*/
|
||||
static void
|
||||
response_cb (GtkDialog *dialog,
|
||||
gint response_id,
|
||||
ChangeDisplayInfo *info)
|
||||
{
|
||||
if (response_id == GTK_RESPONSE_OK)
|
||||
query_change_display (info);
|
||||
else
|
||||
gtk_widget_destroy (GTK_WIDGET (dialog));
|
||||
}
|
||||
|
||||
/* Called when the user clicks on "Open..." in the display
|
||||
* frame. Prompts for a new display, and then opens a connection
|
||||
* to that display.
|
||||
*/
|
||||
static void
|
||||
open_display_cb (GtkWidget *button,
|
||||
ChangeDisplayInfo *info)
|
||||
{
|
||||
GtkWidget *content_area;
|
||||
GtkWidget *dialog;
|
||||
GtkWidget *display_entry;
|
||||
GtkWidget *dialog_label;
|
||||
gchar *new_screen_name = NULL;
|
||||
GdkDisplay *result = NULL;
|
||||
|
||||
dialog = gtk_dialog_new_with_buttons ("Open Display",
|
||||
GTK_WINDOW (info->window),
|
||||
GTK_DIALOG_MODAL,
|
||||
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
||||
_("_OK"), GTK_RESPONSE_OK,
|
||||
NULL);
|
||||
|
||||
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
|
||||
display_entry = gtk_entry_new ();
|
||||
gtk_entry_set_activates_default (GTK_ENTRY (display_entry), TRUE);
|
||||
dialog_label =
|
||||
gtk_label_new ("Please enter the name of\nthe new display\n");
|
||||
|
||||
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (content_area), dialog_label);
|
||||
gtk_container_add (GTK_CONTAINER (content_area), display_entry);
|
||||
|
||||
gtk_widget_grab_focus (display_entry);
|
||||
|
||||
while (!result)
|
||||
{
|
||||
gint response_id = gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
if (response_id != GTK_RESPONSE_OK)
|
||||
break;
|
||||
|
||||
new_screen_name = gtk_editable_get_chars (GTK_EDITABLE (display_entry),
|
||||
0, -1);
|
||||
|
||||
if (strcmp (new_screen_name, "") != 0)
|
||||
{
|
||||
result = gdk_display_open (new_screen_name);
|
||||
if (!result)
|
||||
{
|
||||
gchar *error_msg =
|
||||
g_strdup_printf ("Can't open display:\n\t%s\nplease try another one\n",
|
||||
new_screen_name);
|
||||
gtk_label_set_text (GTK_LABEL (dialog_label), error_msg);
|
||||
g_free (error_msg);
|
||||
}
|
||||
|
||||
g_free (new_screen_name);
|
||||
}
|
||||
}
|
||||
|
||||
gtk_widget_destroy (dialog);
|
||||
}
|
||||
|
||||
/* Called when the user clicks on the "Close" button in the
|
||||
* "Display" frame. Closes the selected display.
|
||||
*/
|
||||
static void
|
||||
close_display_cb (GtkWidget *button,
|
||||
ChangeDisplayInfo *info)
|
||||
{
|
||||
if (info->current_display)
|
||||
gdk_display_close (info->current_display);
|
||||
}
|
||||
|
||||
/* Called when the selected row in the display list changes.
|
||||
* Updates info->current_display, then refills the list of
|
||||
* screens.
|
||||
*/
|
||||
static void
|
||||
display_changed_cb (GtkTreeSelection *selection,
|
||||
ChangeDisplayInfo *info)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (info->current_display)
|
||||
g_object_unref (info->current_display);
|
||||
if (gtk_tree_selection_get_selected (selection, &model, &iter))
|
||||
gtk_tree_model_get (model, &iter,
|
||||
DISPLAY_COLUMN_DISPLAY, &info->current_display,
|
||||
-1);
|
||||
else
|
||||
info->current_display = NULL;
|
||||
}
|
||||
|
||||
/* This function is used both for creating the "Display" and
|
||||
* "Screen" frames, since they have a similar structure. The
|
||||
* caller hooks up the right context for the value returned
|
||||
* in tree_view, and packs any relevant buttons into button_vbox.
|
||||
*/
|
||||
static void
|
||||
create_frame (ChangeDisplayInfo *info,
|
||||
const char *title,
|
||||
GtkWidget **frame,
|
||||
GtkWidget **tree_view,
|
||||
GtkWidget **button_vbox)
|
||||
{
|
||||
GtkTreeSelection *selection;
|
||||
GtkWidget *scrollwin;
|
||||
GtkWidget *hbox;
|
||||
|
||||
*frame = gtk_frame_new (title);
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
|
||||
g_object_set (hbox, "margin", 8, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (*frame), hbox);
|
||||
|
||||
scrollwin = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollwin),
|
||||
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
|
||||
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollwin),
|
||||
GTK_SHADOW_IN);
|
||||
gtk_container_add (GTK_CONTAINER (hbox), scrollwin);
|
||||
|
||||
*tree_view = gtk_tree_view_new ();
|
||||
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (*tree_view), FALSE);
|
||||
gtk_container_add (GTK_CONTAINER (scrollwin), *tree_view);
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (*tree_view));
|
||||
gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
|
||||
|
||||
*button_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
|
||||
gtk_container_add (GTK_CONTAINER (hbox), *button_vbox);
|
||||
|
||||
if (!info->size_group)
|
||||
info->size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
|
||||
|
||||
gtk_size_group_add_widget (GTK_SIZE_GROUP (info->size_group), *button_vbox);
|
||||
}
|
||||
|
||||
/* If we have a stack of buttons, it often looks better if their contents
|
||||
* are left-aligned, rather than centered. This function creates a button
|
||||
* and left-aligns it contents.
|
||||
*/
|
||||
GtkWidget *
|
||||
left_align_button_new (const char *label)
|
||||
{
|
||||
GtkWidget *button = gtk_button_new_with_mnemonic (label);
|
||||
GtkWidget *child = gtk_bin_get_child (GTK_BIN (button));
|
||||
|
||||
gtk_widget_set_halign (child, GTK_ALIGN_START);
|
||||
gtk_widget_set_valign (child, GTK_ALIGN_CENTER);
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
/* Creates the "Display" frame in the main window.
|
||||
*/
|
||||
GtkWidget *
|
||||
create_display_frame (ChangeDisplayInfo *info)
|
||||
{
|
||||
GtkWidget *frame;
|
||||
GtkWidget *tree_view;
|
||||
GtkWidget *button_vbox;
|
||||
GtkTreeViewColumn *column;
|
||||
GtkTreeSelection *selection;
|
||||
GtkWidget *button;
|
||||
|
||||
create_frame (info, "Display", &frame, &tree_view, &button_vbox);
|
||||
|
||||
button = left_align_button_new ("_Open...");
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (open_display_cb), info);
|
||||
gtk_container_add (GTK_CONTAINER (button_vbox), button);
|
||||
|
||||
button = left_align_button_new ("_Close");
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (close_display_cb), info);
|
||||
gtk_container_add (GTK_CONTAINER (button_vbox), button);
|
||||
|
||||
info->display_model = (GtkTreeModel *)gtk_list_store_new (DISPLAY_NUM_COLUMNS,
|
||||
G_TYPE_STRING,
|
||||
GDK_TYPE_DISPLAY);
|
||||
|
||||
gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), info->display_model);
|
||||
|
||||
column = gtk_tree_view_column_new_with_attributes ("Name",
|
||||
gtk_cell_renderer_text_new (),
|
||||
"text", DISPLAY_COLUMN_NAME,
|
||||
NULL);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
|
||||
g_signal_connect (selection, "changed",
|
||||
G_CALLBACK (display_changed_cb), info);
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
/* Called when one of the currently open displays is closed.
|
||||
* Remove it from our list of displays.
|
||||
*/
|
||||
static void
|
||||
display_closed_cb (GdkDisplay *display,
|
||||
gboolean is_error,
|
||||
ChangeDisplayInfo *info)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
gboolean valid;
|
||||
|
||||
for (valid = gtk_tree_model_get_iter_first (info->display_model, &iter);
|
||||
valid;
|
||||
valid = gtk_tree_model_iter_next (info->display_model, &iter))
|
||||
{
|
||||
GdkDisplay *tmp_display;
|
||||
|
||||
gtk_tree_model_get (info->display_model, &iter,
|
||||
DISPLAY_COLUMN_DISPLAY, &tmp_display,
|
||||
-1);
|
||||
if (tmp_display == display)
|
||||
{
|
||||
gtk_list_store_remove (GTK_LIST_STORE (info->display_model), &iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Adds a new display to our list of displays, and connects
|
||||
* to the "closed" signal so that we can remove it from the
|
||||
* list of displays again.
|
||||
*/
|
||||
static void
|
||||
add_display (ChangeDisplayInfo *info,
|
||||
GdkDisplay *display)
|
||||
{
|
||||
const gchar *name = gdk_display_get_name (display);
|
||||
GtkTreeIter iter;
|
||||
|
||||
gtk_list_store_append (GTK_LIST_STORE (info->display_model), &iter);
|
||||
gtk_list_store_set (GTK_LIST_STORE (info->display_model), &iter,
|
||||
DISPLAY_COLUMN_NAME, name,
|
||||
DISPLAY_COLUMN_DISPLAY, display,
|
||||
-1);
|
||||
|
||||
g_signal_connect (display, "closed",
|
||||
G_CALLBACK (display_closed_cb), info);
|
||||
}
|
||||
|
||||
/* Called when a new display is opened
|
||||
*/
|
||||
static void
|
||||
display_opened_cb (GdkDisplayManager *manager,
|
||||
GdkDisplay *display,
|
||||
ChangeDisplayInfo *info)
|
||||
{
|
||||
add_display (info, display);
|
||||
}
|
||||
|
||||
/* Adds all currently open displays to our list of displays,
|
||||
* and set up a signal connection so that we'll be notified
|
||||
* when displays are opened in the future as well.
|
||||
*/
|
||||
static void
|
||||
initialize_displays (ChangeDisplayInfo *info)
|
||||
{
|
||||
GdkDisplayManager *manager = gdk_display_manager_get ();
|
||||
GSList *displays = gdk_display_manager_list_displays (manager);
|
||||
GSList *tmp_list;
|
||||
|
||||
for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
|
||||
add_display (info, tmp_list->data);
|
||||
|
||||
g_slist_free (tmp_list);
|
||||
|
||||
g_signal_connect (manager, "display-opened",
|
||||
G_CALLBACK (display_opened_cb), info);
|
||||
}
|
||||
|
||||
/* Cleans up when the toplevel is destroyed; we remove the
|
||||
* connections we use to track currently open displays, then
|
||||
* free the ChangeDisplayInfo structure.
|
||||
*/
|
||||
static void
|
||||
destroy_info (ChangeDisplayInfo *info)
|
||||
{
|
||||
GdkDisplayManager *manager = gdk_display_manager_get ();
|
||||
GSList *displays = gdk_display_manager_list_displays (manager);
|
||||
GSList *tmp_list;
|
||||
|
||||
g_signal_handlers_disconnect_by_func (manager,
|
||||
display_opened_cb,
|
||||
info);
|
||||
|
||||
for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
|
||||
g_signal_handlers_disconnect_by_func (tmp_list->data,
|
||||
display_closed_cb,
|
||||
info);
|
||||
|
||||
g_slist_free (tmp_list);
|
||||
|
||||
g_object_unref (info->size_group);
|
||||
g_object_unref (info->display_model);
|
||||
|
||||
if (info->current_display)
|
||||
g_object_unref (info->current_display);
|
||||
|
||||
g_free (info);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_cb (GObject *object,
|
||||
ChangeDisplayInfo **info)
|
||||
{
|
||||
destroy_info (*info);
|
||||
*info = NULL;
|
||||
}
|
||||
|
||||
/* Main entry point. If the dialog for this demo doesn't yet exist, creates
|
||||
* it. Otherwise, destroys it.
|
||||
*/
|
||||
GtkWidget *
|
||||
do_changedisplay (GtkWidget *do_widget)
|
||||
{
|
||||
static ChangeDisplayInfo *info = NULL;
|
||||
|
||||
if (!info)
|
||||
{
|
||||
GtkWidget *content_area;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *frame;
|
||||
|
||||
info = g_new0 (ChangeDisplayInfo, 1);
|
||||
|
||||
info->window = gtk_dialog_new_with_buttons ("Change Display",
|
||||
GTK_WINDOW (do_widget),
|
||||
0,
|
||||
"Close", GTK_RESPONSE_CLOSE,
|
||||
"Change", GTK_RESPONSE_OK,
|
||||
NULL);
|
||||
|
||||
gtk_window_set_default_size (GTK_WINDOW (info->window), 300, 400);
|
||||
|
||||
g_signal_connect (info->window, "response",
|
||||
G_CALLBACK (response_cb), info);
|
||||
g_signal_connect (info->window, "destroy",
|
||||
G_CALLBACK (destroy_cb), &info);
|
||||
|
||||
content_area = gtk_dialog_get_content_area (GTK_DIALOG (info->window));
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
|
||||
g_object_set (vbox, "margin", 8, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (content_area), vbox);
|
||||
|
||||
frame = create_display_frame (info);
|
||||
gtk_container_add (GTK_CONTAINER (vbox), frame);
|
||||
|
||||
initialize_displays (info);
|
||||
|
||||
gtk_widget_show (info->window);
|
||||
return info->window;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_destroy (info->window);
|
||||
return NULL;
|
||||
}
|
||||
}
|
@@ -15,7 +15,7 @@
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
static void
|
||||
void
|
||||
copy_button_clicked (GtkWidget *button,
|
||||
gpointer user_data)
|
||||
{
|
||||
@@ -31,7 +31,7 @@ copy_button_clicked (GtkWidget *button,
|
||||
gdk_clipboard_set_text (clipboard, gtk_editable_get_text (GTK_EDITABLE (entry)));
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
paste_received (GObject *source_object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
@@ -75,7 +75,7 @@ paste_received (GObject *source_object,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
paste_button_clicked (GtkWidget *button,
|
||||
gpointer user_data)
|
||||
{
|
||||
@@ -98,7 +98,7 @@ get_image_paintable (GtkImage *image)
|
||||
{
|
||||
const gchar *icon_name;
|
||||
GtkIconTheme *icon_theme;
|
||||
GtkIconPaintable *icon;
|
||||
GtkIconInfo *icon_info;
|
||||
|
||||
switch (gtk_image_get_storage_type (image))
|
||||
{
|
||||
@@ -107,18 +107,10 @@ get_image_paintable (GtkImage *image)
|
||||
case GTK_IMAGE_ICON_NAME:
|
||||
icon_name = gtk_image_get_icon_name (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,
|
||||
48, 1,
|
||||
gtk_widget_get_direction (GTK_WIDGET (image)),
|
||||
0);
|
||||
if (icon == NULL)
|
||||
icon_info = gtk_icon_theme_lookup_icon (icon_theme, icon_name, 48, GTK_ICON_LOOKUP_GENERIC_FALLBACK);
|
||||
if (icon_info == NULL)
|
||||
return NULL;
|
||||
return GDK_PAINTABLE (icon);
|
||||
|
||||
case GTK_IMAGE_EMPTY:
|
||||
case GTK_IMAGE_GICON:
|
||||
return gtk_icon_info_load_icon (icon_info, NULL);
|
||||
default:
|
||||
g_warning ("Image storage type %d not handled",
|
||||
gtk_image_get_storage_type (image));
|
||||
@@ -127,54 +119,59 @@ get_image_paintable (GtkImage *image)
|
||||
}
|
||||
|
||||
static void
|
||||
drag_begin (GtkDragSource *source,
|
||||
GdkDrag *drag,
|
||||
GtkWidget *widget)
|
||||
drag_begin (GtkWidget *widget,
|
||||
GdkDrag *drag,
|
||||
gpointer data)
|
||||
{
|
||||
GdkPaintable *paintable;
|
||||
|
||||
paintable = get_image_paintable (GTK_IMAGE (widget));
|
||||
if (paintable)
|
||||
{
|
||||
gtk_drag_source_set_icon (source, paintable, -2, -2);
|
||||
gtk_drag_set_icon_paintable (drag, paintable, -2, -2);
|
||||
g_object_unref (paintable);
|
||||
}
|
||||
}
|
||||
|
||||
static GdkContentProvider *
|
||||
prepare_drag (GtkDragSource *source,
|
||||
double x,
|
||||
double y,
|
||||
GtkWidget *image)
|
||||
void
|
||||
drag_data_get (GtkWidget *widget,
|
||||
GdkDrag *drag,
|
||||
GtkSelectionData *selection_data,
|
||||
guint info,
|
||||
gpointer data)
|
||||
{
|
||||
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (image));
|
||||
GdkPaintable *paintable;
|
||||
|
||||
if (!GDK_IS_TEXTURE (paintable))
|
||||
return NULL;
|
||||
|
||||
return gdk_content_provider_new_typed (GDK_TYPE_TEXTURE, paintable);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
drag_drop (GtkDropTarget *dest,
|
||||
const GValue *value,
|
||||
double x,
|
||||
double y,
|
||||
GtkImage *image)
|
||||
{
|
||||
GdkTexture *texture = g_value_get_object (value);
|
||||
gtk_image_set_from_paintable (GTK_IMAGE (image), GDK_PAINTABLE (texture));
|
||||
|
||||
return TRUE;
|
||||
paintable = get_image_paintable (GTK_IMAGE (widget));
|
||||
if (GDK_IS_TEXTURE (paintable))
|
||||
gtk_selection_data_set_texture (selection_data, GDK_TEXTURE (paintable));
|
||||
}
|
||||
|
||||
static void
|
||||
copy_image (GSimpleAction *action,
|
||||
GVariant *value,
|
||||
gpointer data)
|
||||
drag_data_received (GtkWidget *widget,
|
||||
GdkDrop *drop,
|
||||
GtkSelectionData *selection_data,
|
||||
gpointer data)
|
||||
{
|
||||
GdkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (data));
|
||||
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (data));
|
||||
if (gtk_selection_data_get_length (selection_data) > 0)
|
||||
{
|
||||
GdkTexture *texture;
|
||||
|
||||
texture = gtk_selection_data_get_texture (selection_data);
|
||||
gtk_image_set_from_paintable (GTK_IMAGE (data), GDK_PAINTABLE (texture));
|
||||
g_object_unref (texture);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
copy_image (GtkMenuItem *item,
|
||||
gpointer data)
|
||||
{
|
||||
GdkClipboard *clipboard;
|
||||
GdkPaintable *paintable;
|
||||
|
||||
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (data));
|
||||
paintable = get_image_paintable (GTK_IMAGE (data));
|
||||
|
||||
if (GDK_IS_TEXTURE (paintable))
|
||||
gdk_clipboard_set_texture (clipboard, GDK_TEXTURE (paintable));
|
||||
@@ -199,12 +196,16 @@ paste_image_received (GObject *source,
|
||||
}
|
||||
|
||||
static void
|
||||
paste_image (GSimpleAction *action,
|
||||
GVariant *value,
|
||||
gpointer data)
|
||||
paste_image (GtkMenuItem *item,
|
||||
gpointer data)
|
||||
{
|
||||
GdkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (data));
|
||||
gdk_clipboard_read_texture_async (clipboard, NULL, paste_image_received, data);
|
||||
GdkClipboard *clipboard;
|
||||
|
||||
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (data));
|
||||
gdk_clipboard_read_texture_async (clipboard,
|
||||
NULL,
|
||||
paste_image_received,
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -214,24 +215,22 @@ pressed_cb (GtkGesture *gesture,
|
||||
double y,
|
||||
GtkWidget *image)
|
||||
{
|
||||
GtkWidget *popover;
|
||||
GMenu *menu;
|
||||
GMenuItem *item;
|
||||
GtkWidget *menu;
|
||||
GtkWidget *item;
|
||||
|
||||
menu = g_menu_new ();
|
||||
item = g_menu_item_new (_("_Copy"), "clipboard.copy");
|
||||
g_menu_append_item (menu, item);
|
||||
menu = gtk_menu_new ();
|
||||
|
||||
item = g_menu_item_new (_("_Paste"), "clipboard.paste");
|
||||
g_menu_append_item (menu, item);
|
||||
item = gtk_menu_item_new_with_mnemonic (_("_Copy"));
|
||||
g_signal_connect (item, "activate", G_CALLBACK (copy_image), image);
|
||||
gtk_widget_show (item);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
||||
|
||||
popover = gtk_popover_menu_new_from_model (G_MENU_MODEL (menu));
|
||||
gtk_widget_set_parent (popover, image);
|
||||
item = gtk_menu_item_new_with_mnemonic (_("_Paste"));
|
||||
g_signal_connect (item, "activate", G_CALLBACK (paste_image), image);
|
||||
gtk_widget_show (item);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
||||
|
||||
gtk_popover_set_pointing_to (GTK_POPOVER (popover), &(GdkRectangle) { x, y, 1, 1});
|
||||
gtk_popover_popup (GTK_POPOVER (popover));
|
||||
|
||||
g_object_unref (menu);
|
||||
gtk_menu_popup_at_pointer (GTK_MENU (menu), NULL);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
@@ -244,15 +243,8 @@ do_clipboard (GtkWidget *do_widget)
|
||||
GtkWidget *entry, *button;
|
||||
GtkWidget *image;
|
||||
GtkGesture *gesture;
|
||||
GActionEntry entries[] = {
|
||||
{ "copy", copy_image, NULL, NULL, NULL },
|
||||
{ "paste", paste_image, NULL, NULL, NULL },
|
||||
};
|
||||
GActionGroup *actions;
|
||||
GtkDragSource *source;
|
||||
GtkDropTarget *dest;
|
||||
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Clipboard");
|
||||
@@ -261,10 +253,7 @@ do_clipboard (GtkWidget *do_widget)
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_widget_set_margin_start (vbox, 8);
|
||||
gtk_widget_set_margin_end (vbox, 8);
|
||||
gtk_widget_set_margin_top (vbox, 8);
|
||||
gtk_widget_set_margin_bottom (vbox, 8);
|
||||
g_object_set (vbox, "margin", 8, NULL);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (window), vbox);
|
||||
|
||||
@@ -273,10 +262,7 @@ do_clipboard (GtkWidget *do_widget)
|
||||
gtk_container_add (GTK_CONTAINER (vbox), label);
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
|
||||
gtk_widget_set_margin_start (hbox, 8);
|
||||
gtk_widget_set_margin_end (hbox, 8);
|
||||
gtk_widget_set_margin_top (hbox, 8);
|
||||
gtk_widget_set_margin_bottom (hbox, 8);
|
||||
g_object_set (hbox, "margin", 8, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (vbox), hbox);
|
||||
|
||||
/* Create the first entry */
|
||||
@@ -293,10 +279,7 @@ do_clipboard (GtkWidget *do_widget)
|
||||
gtk_container_add (GTK_CONTAINER (vbox), label);
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
|
||||
gtk_widget_set_margin_start (hbox, 8);
|
||||
gtk_widget_set_margin_end (hbox, 8);
|
||||
gtk_widget_set_margin_top (hbox, 8);
|
||||
gtk_widget_set_margin_bottom (hbox, 8);
|
||||
g_object_set (hbox, "margin", 8, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (vbox), hbox);
|
||||
|
||||
/* Create the second entry */
|
||||
@@ -313,27 +296,27 @@ do_clipboard (GtkWidget *do_widget)
|
||||
gtk_container_add (GTK_CONTAINER (vbox), label);
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
|
||||
gtk_widget_set_margin_start (hbox, 8);
|
||||
gtk_widget_set_margin_end (hbox, 8);
|
||||
gtk_widget_set_margin_top (hbox, 8);
|
||||
gtk_widget_set_margin_bottom (hbox, 8);
|
||||
g_object_set (hbox, "margin", 8, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (vbox), hbox);
|
||||
|
||||
/* Create the first image */
|
||||
image = gtk_image_new_from_icon_name ("dialog-warning");
|
||||
gtk_image_set_pixel_size (GTK_IMAGE (image), 48);
|
||||
gtk_container_add (GTK_CONTAINER (hbox), image);
|
||||
|
||||
/* make image a drag source */
|
||||
source = gtk_drag_source_new ();
|
||||
g_signal_connect (source, "prepare", G_CALLBACK (prepare_drag), NULL);
|
||||
g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image);
|
||||
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (source));
|
||||
gtk_drag_source_set (image, GDK_BUTTON1_MASK, NULL, GDK_ACTION_COPY);
|
||||
gtk_drag_source_add_image_targets (image);
|
||||
g_signal_connect (image, "drag-begin",
|
||||
G_CALLBACK (drag_begin), image);
|
||||
g_signal_connect (image, "drag-data-get",
|
||||
G_CALLBACK (drag_data_get), image);
|
||||
|
||||
/* accept drops on image */
|
||||
dest = gtk_drop_target_new (GDK_TYPE_TEXTURE, GDK_ACTION_COPY);
|
||||
g_signal_connect (dest, "drop", G_CALLBACK (drag_drop), image);
|
||||
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (dest));
|
||||
gtk_drag_dest_set (image, GTK_DEST_DEFAULT_ALL,
|
||||
NULL, GDK_ACTION_COPY);
|
||||
gtk_drag_dest_add_image_targets (image);
|
||||
g_signal_connect (image, "drag-data-received",
|
||||
G_CALLBACK (drag_data_received), image);
|
||||
|
||||
/* context menu on image */
|
||||
gesture = gtk_gesture_click_new ();
|
||||
@@ -341,41 +324,30 @@ do_clipboard (GtkWidget *do_widget)
|
||||
g_signal_connect (gesture, "pressed", G_CALLBACK (pressed_cb), image);
|
||||
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (gesture));
|
||||
|
||||
actions = G_ACTION_GROUP (g_simple_action_group_new ());
|
||||
g_action_map_add_action_entries (G_ACTION_MAP (actions), entries, G_N_ELEMENTS (entries), image);
|
||||
|
||||
gtk_widget_insert_action_group (image, "clipboard", actions);
|
||||
|
||||
g_object_unref (actions);
|
||||
|
||||
/* Create the second image */
|
||||
image = gtk_image_new_from_icon_name ("process-stop");
|
||||
gtk_image_set_pixel_size (GTK_IMAGE (image), 48);
|
||||
gtk_container_add (GTK_CONTAINER (hbox), image);
|
||||
|
||||
/* make image a drag source */
|
||||
source = gtk_drag_source_new ();
|
||||
g_signal_connect (source, "prepare", G_CALLBACK (prepare_drag), NULL);
|
||||
g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image);
|
||||
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (source));
|
||||
gtk_drag_source_set (image, GDK_BUTTON1_MASK, NULL, GDK_ACTION_COPY);
|
||||
gtk_drag_source_add_image_targets (image);
|
||||
g_signal_connect (image, "drag-begin",
|
||||
G_CALLBACK (drag_begin), image);
|
||||
g_signal_connect (image, "drag-data-get",
|
||||
G_CALLBACK (drag_data_get), image);
|
||||
|
||||
/* accept drops on image */
|
||||
dest = gtk_drop_target_new (GDK_TYPE_TEXTURE, GDK_ACTION_COPY);
|
||||
g_signal_connect (dest, "drop", G_CALLBACK (drag_drop), image);
|
||||
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (dest));
|
||||
gtk_drag_dest_set (image, GTK_DEST_DEFAULT_ALL,
|
||||
NULL, GDK_ACTION_COPY);
|
||||
gtk_drag_dest_add_image_targets (image);
|
||||
g_signal_connect (image, "drag-data-received",
|
||||
G_CALLBACK (drag_data_received), image);
|
||||
|
||||
/* context menu on image */
|
||||
gesture = gtk_gesture_click_new ();
|
||||
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), GDK_BUTTON_SECONDARY);
|
||||
g_signal_connect (gesture, "pressed", G_CALLBACK (pressed_cb), image);
|
||||
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (gesture));
|
||||
|
||||
actions = G_ACTION_GROUP (g_simple_action_group_new ());
|
||||
g_action_map_add_action_entries (G_ACTION_MAP (actions), entries, G_N_ELEMENTS (entries), image);
|
||||
|
||||
gtk_widget_insert_action_group (image, "clipboard", actions);
|
||||
|
||||
g_object_unref (actions);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
@@ -16,7 +16,7 @@ static GtkWidget *frame;
|
||||
/* draw callback for the drawing area
|
||||
*/
|
||||
static void
|
||||
draw_function (GtkDrawingArea *drawing_area,
|
||||
draw_function (GtkDrawingArea *da,
|
||||
cairo_t *cr,
|
||||
int width,
|
||||
int height,
|
||||
@@ -69,7 +69,7 @@ do_colorsel (GtkWidget *do_widget)
|
||||
color.green = 0;
|
||||
color.alpha = 1;
|
||||
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Color Chooser");
|
||||
@@ -79,10 +79,7 @@ do_colorsel (GtkWidget *do_widget)
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8);
|
||||
gtk_widget_set_margin_start (vbox, 12);
|
||||
gtk_widget_set_margin_end (vbox, 12);
|
||||
gtk_widget_set_margin_top (vbox, 12);
|
||||
gtk_widget_set_margin_bottom (vbox, 12);
|
||||
g_object_set (vbox, "margin", 12, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), vbox);
|
||||
|
||||
/*
|
||||
|
@@ -19,7 +19,7 @@ enum
|
||||
static GtkTreeModel *
|
||||
create_icon_store (void)
|
||||
{
|
||||
const char *icon_names[6] = {
|
||||
const gchar *icon_names[6] = {
|
||||
"dialog-warning",
|
||||
"process-stop",
|
||||
"document-new",
|
||||
@@ -27,7 +27,7 @@ create_icon_store (void)
|
||||
NULL,
|
||||
"document-open"
|
||||
};
|
||||
const char *labels[6] = {
|
||||
const gchar *labels[6] = {
|
||||
N_("Warning"),
|
||||
N_("Stop"),
|
||||
N_("New"),
|
||||
@@ -111,8 +111,8 @@ static GtkTreeModel *
|
||||
create_capital_store (void)
|
||||
{
|
||||
struct {
|
||||
const char *group;
|
||||
const char *capital;
|
||||
gchar *group;
|
||||
gchar *capital;
|
||||
} capitals[] = {
|
||||
{ "A - B", NULL },
|
||||
{ NULL, "Albany" },
|
||||
@@ -234,7 +234,7 @@ typedef struct _MaskEntry MaskEntry;
|
||||
struct _MaskEntry
|
||||
{
|
||||
GtkEntry entry;
|
||||
const char *mask;
|
||||
gchar *mask;
|
||||
};
|
||||
|
||||
typedef struct _MaskEntryClass MaskEntryClass;
|
||||
@@ -246,7 +246,6 @@ struct _MaskEntryClass
|
||||
|
||||
static void mask_entry_editable_init (GtkEditableInterface *iface);
|
||||
|
||||
static GType mask_entry_get_type (void);
|
||||
G_DEFINE_TYPE_WITH_CODE (MaskEntry, mask_entry, GTK_TYPE_ENTRY,
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
|
||||
mask_entry_editable_init));
|
||||
@@ -311,7 +310,7 @@ do_combobox (GtkWidget *do_widget)
|
||||
|
||||
if (!window)
|
||||
{
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Combo Boxes");
|
||||
@@ -320,10 +319,7 @@ do_combobox (GtkWidget *do_widget)
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
|
||||
gtk_widget_set_margin_start (vbox, 10);
|
||||
gtk_widget_set_margin_end (vbox, 10);
|
||||
gtk_widget_set_margin_top (vbox, 10);
|
||||
gtk_widget_set_margin_bottom (vbox, 10);
|
||||
g_object_set (vbox, "margin", 10, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), vbox);
|
||||
|
||||
/* A combobox demonstrating cell renderers, separators and
|
||||
@@ -333,10 +329,7 @@ do_combobox (GtkWidget *do_widget)
|
||||
gtk_container_add (GTK_CONTAINER (vbox), frame);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_widget_set_margin_start (box, 5);
|
||||
gtk_widget_set_margin_end (box, 5);
|
||||
gtk_widget_set_margin_top (box, 5);
|
||||
gtk_widget_set_margin_bottom (box, 5);
|
||||
g_object_set (box, "margin", 5, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (frame), box);
|
||||
|
||||
model = create_icon_store ();
|
||||
@@ -377,10 +370,7 @@ do_combobox (GtkWidget *do_widget)
|
||||
gtk_container_add (GTK_CONTAINER (vbox), frame);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_widget_set_margin_start (box, 5);
|
||||
gtk_widget_set_margin_end (box, 5);
|
||||
gtk_widget_set_margin_top (box, 5);
|
||||
gtk_widget_set_margin_bottom (box, 5);
|
||||
g_object_set (box, "margin", 5, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (frame), box);
|
||||
|
||||
model = create_capital_store ();
|
||||
@@ -408,10 +398,7 @@ do_combobox (GtkWidget *do_widget)
|
||||
gtk_container_add (GTK_CONTAINER (vbox), frame);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_widget_set_margin_start (box, 5);
|
||||
gtk_widget_set_margin_end (box, 5);
|
||||
gtk_widget_set_margin_top (box, 5);
|
||||
gtk_widget_set_margin_bottom (box, 5);
|
||||
g_object_set (box, "margin", 5, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (frame), box);
|
||||
|
||||
combo = gtk_combo_box_text_new_with_entry ();
|
||||
@@ -429,10 +416,7 @@ do_combobox (GtkWidget *do_widget)
|
||||
gtk_container_add (GTK_CONTAINER (vbox), frame);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_widget_set_margin_start (box, 5);
|
||||
gtk_widget_set_margin_end (box, 5);
|
||||
gtk_widget_set_margin_top (box, 5);
|
||||
gtk_widget_set_margin_bottom (box, 5);
|
||||
g_object_set (box, "margin", 5, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (frame), box);
|
||||
|
||||
combo = gtk_combo_box_text_new ();
|
||||
|
@@ -255,7 +255,7 @@ do_constraints (GtkWidget *do_widget)
|
||||
{
|
||||
GtkWidget *header, *box, *grid, *button;
|
||||
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
|
@@ -211,7 +211,7 @@ do_constraints2 (GtkWidget *do_widget)
|
||||
{
|
||||
GtkWidget *header, *box, *grid, *button;
|
||||
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
|
@@ -131,7 +131,7 @@ do_constraints3 (GtkWidget *do_widget)
|
||||
{
|
||||
GtkWidget *header, *box, *grid, *button;
|
||||
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
|
@@ -24,7 +24,7 @@ do_css_accordion (GtkWidget *do_widget)
|
||||
GtkWidget *container, *child;
|
||||
GtkStyleProvider *provider;
|
||||
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_title (GTK_WINDOW (window), "CSS Accordion");
|
||||
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (do_widget));
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 600, 300);
|
||||
|
@@ -72,7 +72,7 @@ do_css_basics (GtkWidget *do_widget)
|
||||
GtkTextBuffer *text;
|
||||
GBytes *bytes;
|
||||
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_title (GTK_WINDOW (window), "CSS Basics");
|
||||
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (do_widget));
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
|
||||
|
@@ -11,8 +11,8 @@
|
||||
* These are the available blend modes.
|
||||
*/
|
||||
struct {
|
||||
const char *name;
|
||||
const char *id;
|
||||
gchar *name;
|
||||
gchar *id;
|
||||
} blend_modes[] =
|
||||
{
|
||||
{ "Color", "color" },
|
||||
|
@@ -86,7 +86,7 @@ do_css_multiplebgs (GtkWidget *do_widget)
|
||||
GtkTextBuffer *text;
|
||||
GBytes *bytes;
|
||||
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Multiple Backgrounds");
|
||||
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (do_widget));
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
|
||||
|
@@ -72,7 +72,7 @@ do_css_pixbufs (GtkWidget *do_widget)
|
||||
GtkTextBuffer *text;
|
||||
GBytes *bytes;
|
||||
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Animated Backgrounds");
|
||||
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (do_widget));
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
|
||||
|
@@ -58,23 +58,26 @@ apply_css (GtkWidget *widget, GtkStyleProvider *provider)
|
||||
gtk_container_forall (GTK_CONTAINER (widget), (GtkCallback) apply_css, provider);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
GtkWidget *
|
||||
create_toolbar (void)
|
||||
{
|
||||
GtkWidget *toolbar;
|
||||
GtkWidget *item;
|
||||
GtkToolItem *item;
|
||||
|
||||
toolbar = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
toolbar = gtk_toolbar_new ();
|
||||
gtk_widget_set_valign (toolbar, GTK_ALIGN_CENTER);
|
||||
|
||||
item = gtk_button_new_from_icon_name ("go-next");
|
||||
gtk_container_add (GTK_CONTAINER (toolbar), item);
|
||||
item = gtk_tool_button_new (NULL, NULL);
|
||||
gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (item), "go-next");
|
||||
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
|
||||
|
||||
item = gtk_button_new_from_icon_name ("go-previous");
|
||||
gtk_container_add (GTK_CONTAINER (toolbar), item);
|
||||
item = gtk_tool_button_new (NULL, NULL);
|
||||
gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (item), "go-previous");
|
||||
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
|
||||
|
||||
item = gtk_button_new_with_label ("Hello World");
|
||||
gtk_container_add (GTK_CONTAINER (toolbar), item);
|
||||
item = gtk_tool_button_new (NULL, "Hello World");
|
||||
gtk_tool_item_set_is_important (item, TRUE);
|
||||
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
|
||||
|
||||
return toolbar;
|
||||
}
|
||||
@@ -91,7 +94,7 @@ do_css_shadows (GtkWidget *do_widget)
|
||||
GtkTextBuffer *text;
|
||||
GBytes *bytes;
|
||||
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Shadows");
|
||||
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (do_widget));
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
|
||||
|
@@ -656,10 +656,7 @@
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="margin-start">60</property>
|
||||
<property name="margin-end">60</property>
|
||||
<property name="margin-top">60</property>
|
||||
<property name="margin-bottom">60</property>
|
||||
<property name="margin">60</property>
|
||||
<property name="spacing">10</property>
|
||||
<property name="halign">center</property>
|
||||
<child>
|
||||
@@ -675,10 +672,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -735,10 +729,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -795,10 +786,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -868,10 +856,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -928,10 +913,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -988,10 +970,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -1048,10 +1027,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -1108,10 +1084,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -1181,10 +1154,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -1241,10 +1211,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -1301,10 +1268,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -1361,10 +1325,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -1434,10 +1395,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -1494,10 +1452,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -1554,10 +1509,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -1614,10 +1566,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -1674,10 +1623,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -1734,10 +1680,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -1794,10 +1737,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -1867,10 +1807,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -1927,10 +1864,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -1987,10 +1921,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -2047,10 +1978,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -2107,10 +2035,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -2167,10 +2092,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -2227,10 +2149,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -2287,10 +2206,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -2347,10 +2263,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -2407,10 +2320,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -2467,10 +2377,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -2527,10 +2434,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -2587,10 +2491,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -2647,10 +2548,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -2707,10 +2605,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -2780,10 +2675,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
@@ -2840,10 +2732,7 @@
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
|
@@ -1,7 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/">
|
||||
<file>awards.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/ui">
|
||||
<file preprocess="xml-stripblanks">main.ui</file>
|
||||
<file preprocess="xml-stripblanks">main-listitem.ui</file>
|
||||
<file preprocess="xml-stripblanks">appmenu.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/application_demo">
|
||||
@@ -9,6 +13,9 @@
|
||||
<file>application.ui</file>
|
||||
<file>menus.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/awardview">
|
||||
<file>awardlistitem.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/builder">
|
||||
<file>demo.ui</file>
|
||||
</gresource>
|
||||
@@ -111,6 +118,19 @@
|
||||
<file>gnome-fs-directory.png</file>
|
||||
<file>gnome-fs-regular.png</file>
|
||||
</gresource>
|
||||
<gresource prefix="/listview_filebrowser">
|
||||
<file>listview_filebrowser.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/listview_minesweeper">
|
||||
<file>listview_minesweeper.ui</file>
|
||||
<file>listview_minesweeper_cell.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/listview_settings">
|
||||
<file>listview_settings.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/listview_weather">
|
||||
<file compressed="true">listview_weather.txt</file>
|
||||
</gresource>
|
||||
<gresource prefix="/shortcuts">
|
||||
<file>shortcuts.ui</file>
|
||||
<file>shortcuts-builder.ui</file>
|
||||
@@ -147,8 +167,10 @@
|
||||
</gresource>
|
||||
<gresource prefix="/sources">
|
||||
<file>application_demo.c</file>
|
||||
<file>awardview.c</file>
|
||||
<file>assistant.c</file>
|
||||
<file>builder.c</file>
|
||||
<file>changedisplay.c</file>
|
||||
<file>clipboard.c</file>
|
||||
<file>colorsel.c</file>
|
||||
<file>combobox.c</file>
|
||||
@@ -173,6 +195,7 @@
|
||||
<file>fishbowl.c</file>
|
||||
<file>fixed.c</file>
|
||||
<file>flowbox.c</file>
|
||||
<file>foreigndrawing.c</file>
|
||||
<file>font_features.c</file>
|
||||
<file>fontplane.c</file>
|
||||
<file>fontrendering.c</file>
|
||||
@@ -187,8 +210,15 @@
|
||||
<file>infobar.c</file>
|
||||
<file>links.c</file>
|
||||
<file>listbox.c</file>
|
||||
<file>listview_applauncher.c</file>
|
||||
<file>listview_clocks.c</file>
|
||||
<file>listview_filebrowser.c</file>
|
||||
<file>listview_minesweeper.c</file>
|
||||
<file>listview_settings.c</file>
|
||||
<file>listview_weather.c</file>
|
||||
<file>list_store.c</file>
|
||||
<file>markup.c</file>
|
||||
<file>menus.c</file>
|
||||
<file>modelbutton.c</file>
|
||||
<file>overlay.c</file>
|
||||
<file>overlay2.c</file>
|
||||
@@ -199,7 +229,6 @@
|
||||
<file>paintable_mediastream.c</file>
|
||||
<file>panes.c</file>
|
||||
<file>password_entry.c</file>
|
||||
<file>peg_solitaire.c</file>
|
||||
<file>pickers.c</file>
|
||||
<file>pixbufs.c</file>
|
||||
<file>popover.c</file>
|
||||
@@ -210,7 +239,6 @@
|
||||
<file>search_entry.c</file>
|
||||
<file>search_entry2.c</file>
|
||||
<file>shortcuts.c</file>
|
||||
<file>shortcut_triggers.c</file>
|
||||
<file>sizegroup.c</file>
|
||||
<file>sidebar.c</file>
|
||||
<file>sliding_puzzle.c</file>
|
||||
|
@@ -22,75 +22,6 @@
|
||||
</row>
|
||||
</data>
|
||||
</object>
|
||||
<menu id="menubar">
|
||||
<submenu>
|
||||
<attribute name="label" translatable="yes">_File</attribute>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_New</attribute>
|
||||
<attribute name="action">win.new</attribute>
|
||||
<attribute name="accel"><Primary>n</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Open</attribute>
|
||||
<attribute name="action">win.open</attribute>
|
||||
<attribute name="accel"><Primary>o</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Save</attribute>
|
||||
<attribute name="action">win.save</attribute>
|
||||
<attribute name="accel"><Primary>s</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Save _As</attribute>
|
||||
<attribute name="action">win.save-as</attribute>
|
||||
<attribute name="accel"><Primary>q</attribute>
|
||||
</item>
|
||||
</section>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Quit</attribute>
|
||||
<attribute name="action">win.quit</attribute>
|
||||
<attribute name="accel"><Primary><Shift>s</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</submenu>
|
||||
<submenu>
|
||||
<attribute name="label" translatable="yes">_Edit</attribute>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Copy</attribute>
|
||||
<attribute name="action">win.copy</attribute>
|
||||
<attribute name="accel"><Primary>c</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Cut</attribute>
|
||||
<attribute name="action">win.cut</attribute>
|
||||
<attribute name="accel"><Primary>x</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Paste</attribute>
|
||||
<attribute name="action">win.paste</attribute>
|
||||
<attribute name="accel"><Primary>v</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</submenu>
|
||||
<submenu>
|
||||
<attribute name="label" translatable="yes">_Help</attribute>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Help</attribute>
|
||||
<attribute name="action">win.help</attribute>
|
||||
<attribute name="accel">F1</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_About</attribute>
|
||||
<attribute name="action">win.about</attribute>
|
||||
<attribute name="accel">F7</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</submenu>
|
||||
</menu>
|
||||
<object class="GtkAboutDialog" id="aboutdialog1">
|
||||
<property name="program-name" translatable="yes">Builder demo</property>
|
||||
<property name="logo-icon-name" translatable="yes">gtk3-demo</property>
|
||||
@@ -106,57 +37,159 @@
|
||||
<object class="GtkBox" id="vbox1">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkPopoverMenuBar" id="menubar1">
|
||||
<property name="menu-model">menubar</property>
|
||||
<object class="GtkMenuBar" id="menubar1">
|
||||
<child internal-child="accessible">
|
||||
<object class="AtkObject" id="a11y-menubar">
|
||||
<property name="AtkObject::accessible-name">The menubar</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem">
|
||||
<property name="label" translatable="yes">_File</property>
|
||||
<property name="use-underline">1</property>
|
||||
<child type="submenu">
|
||||
<object class="GtkMenu">
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="new_item">
|
||||
<property name="label" translatable="yes">_New</property>
|
||||
<property name="use-underline">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="open_item">
|
||||
<property name="label" translatable="yes">_Open</property>
|
||||
<property name="use-underline">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="save_item">
|
||||
<property name="label" translatable="yes">_Save</property>
|
||||
<property name="use-underline">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="save_as_item">
|
||||
<property name="label" translatable="yes">Save _As</property>
|
||||
<property name="use-underline">1</property>
|
||||
<accelerator key="s" modifiers="primary | shift-mask" signal="activate"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparatorMenuItem"/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="quit_item">
|
||||
<property name="label" translatable="yes">_Quit</property>
|
||||
<property name="use-underline">1</property>
|
||||
<property name="action-name">win.quit</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem">
|
||||
<property name="label" translatable="yes">_Edit</property>
|
||||
<property name="use-underline">1</property>
|
||||
<child type="submenu">
|
||||
<object class="GtkMenu">
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="copy_item">
|
||||
<property name="label" translatable="yes">_Copy</property>
|
||||
<property name="use-underline">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="cut_item">
|
||||
<property name="label" translatable="yes">_Cut</property>
|
||||
<property name="use-underline">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="paste_item">
|
||||
<property name="label" translatable="yes">_Paste</property>
|
||||
<property name="use-underline">1</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem">
|
||||
<property name="label" translatable="yes">_Help</property>
|
||||
<property name="use-underline">1</property>
|
||||
<child type="submenu">
|
||||
<object class="GtkMenu">
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="help_item">
|
||||
<property name="label" translatable="yes">_Help</property>
|
||||
<property name="use-underline">1</property>
|
||||
<property name="action-name">win.help</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="about_item">
|
||||
<property name="label" translatable="yes">_About</property>
|
||||
<property name="use-underline">1</property>
|
||||
<property name="action-name">win.about</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="toolbar1">
|
||||
<object class="GtkToolbar" id="toolbar1">
|
||||
<child internal-child="accessible">
|
||||
<object class="AtkObject" id="a11y-toolbar">
|
||||
<property name="AtkObject::accessible-name">The toolbar</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<object class="GtkToolButton">
|
||||
<property name="label" translatable="yes">New</property>
|
||||
<property name="tooltip-text" translatable="yes">Create a new file</property>
|
||||
<property name="icon-name">document-new</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<object class="GtkToolButton">
|
||||
<property name="label" translatable="yes">Open</property>
|
||||
<property name="tooltip-text" translatable="yes">Open a file</property>
|
||||
<property name="icon-name">document-open</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<object class="GtkToolButton">
|
||||
<property name="label" translatable="yes">Save</property>
|
||||
<property name="tooltip-text" translatable="yes">Save a file</property>
|
||||
<property name="icon-name">document-save</property>
|
||||
<property name="is-important">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator"/>
|
||||
<object class="GtkSeparatorToolItem"/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<object class="GtkToolButton">
|
||||
<property name="label" translatable="yes">Copy</property>
|
||||
<property name="tooltip-text" translatable="yes">Copy selected object into the clipboard</property>
|
||||
<property name="icon-name">edit-copy</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<object class="GtkToolButton">
|
||||
<property name="label" translatable="yes">Cut</property>
|
||||
<property name="tooltip-text" translatable="yes">Cut selected object into the clipboard</property>
|
||||
<property name="icon-name">edit-cut</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<object class="GtkToolButton">
|
||||
<property name="label" translatable="yes">Paste</property>
|
||||
<property name="tooltip-text" translatable="yes">Paste object from the clipboard</property>
|
||||
<property name="icon-name">edit-paste</property>
|
||||
@@ -167,8 +200,7 @@
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="scrolledwindow1">
|
||||
<property name="shadow-type">in</property>
|
||||
<property name="hexpand">1</property>
|
||||
<property name="vexpand">1</property>
|
||||
<property name="expand">1</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="treeview1">
|
||||
<property name="model">liststore1</property>
|
||||
|
@@ -105,7 +105,7 @@ do_dialog (GtkWidget *do_widget)
|
||||
|
||||
if (!window)
|
||||
{
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Dialogs and Message Boxes");
|
||||
@@ -114,17 +114,11 @@ do_dialog (GtkWidget *do_widget)
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
frame = gtk_frame_new ("Dialogs");
|
||||
gtk_widget_set_margin_start (frame, 8);
|
||||
gtk_widget_set_margin_end (frame, 8);
|
||||
gtk_widget_set_margin_top (frame, 8);
|
||||
gtk_widget_set_margin_bottom (frame, 8);
|
||||
g_object_set (frame, "margin", 8, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), frame);
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8);
|
||||
gtk_widget_set_margin_start (vbox, 8);
|
||||
gtk_widget_set_margin_end (vbox, 8);
|
||||
gtk_widget_set_margin_top (vbox, 8);
|
||||
gtk_widget_set_margin_bottom (vbox, 8);
|
||||
g_object_set (vbox, "margin", 8, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (frame), vbox);
|
||||
|
||||
/* Standard message dialog */
|
||||
|
@@ -1,8 +1,6 @@
|
||||
/* Drag-and-Drop
|
||||
*
|
||||
* I can't believe its not glade!
|
||||
*
|
||||
* Try right-clicking in the window.
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
@@ -42,7 +40,7 @@ free_demo_widget (gpointer data)
|
||||
}
|
||||
|
||||
#define GTK_TYPE_DEMO_WIDGET (gtk_demo_widget_get_type ())
|
||||
static GType gtk_demo_widget_get_type (void);
|
||||
|
||||
G_DEFINE_BOXED_TYPE (GtkDemoWidget, gtk_demo_widget, copy_demo_widget, free_demo_widget)
|
||||
|
||||
static GtkDemoWidget *
|
||||
@@ -59,7 +57,7 @@ serialize_widget (GtkWidget *widget)
|
||||
}
|
||||
else if (GTK_IS_SPINNER (widget))
|
||||
{
|
||||
g_object_get (widget, "spinning", &demo->active, NULL);
|
||||
g_object_get (widget, "active", &demo->active, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -80,7 +78,7 @@ deserialize_widget (GtkDemoWidget *demo)
|
||||
}
|
||||
else if (demo->type == GTK_TYPE_SPINNER)
|
||||
{
|
||||
widget = g_object_new (demo->type, "spinning", demo->active, NULL);
|
||||
widget = g_object_new (demo->type, "active", demo->active, NULL);
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (widget), "demo");
|
||||
}
|
||||
else
|
||||
@@ -94,7 +92,7 @@ deserialize_widget (GtkDemoWidget *demo)
|
||||
static double pos_x, pos_y;
|
||||
|
||||
static void
|
||||
new_label_cb (GtkWidget *button,
|
||||
new_label_cb (GtkMenuItem *item,
|
||||
gpointer data)
|
||||
{
|
||||
GtkFixed *fixed = data;
|
||||
@@ -102,12 +100,10 @@ new_label_cb (GtkWidget *button,
|
||||
|
||||
widget = gtk_label_new ("Label");
|
||||
gtk_fixed_put (fixed, widget, pos_x, pos_y);
|
||||
|
||||
gtk_popover_popdown (GTK_POPOVER (gtk_widget_get_ancestor (button, GTK_TYPE_POPOVER)));
|
||||
}
|
||||
|
||||
static void
|
||||
new_spinner_cb (GtkWidget *button,
|
||||
new_spinner_cb (GtkMenuItem *item,
|
||||
gpointer data)
|
||||
{
|
||||
GtkFixed *fixed = data;
|
||||
@@ -117,39 +113,33 @@ new_spinner_cb (GtkWidget *button,
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (widget), "demo");
|
||||
gtk_spinner_start (GTK_SPINNER (widget));
|
||||
gtk_fixed_put (fixed, widget, pos_x, pos_y);
|
||||
|
||||
gtk_popover_popdown (GTK_POPOVER (gtk_widget_get_ancestor (button, GTK_TYPE_POPOVER)));
|
||||
}
|
||||
|
||||
static void
|
||||
copy_cb (GtkWidget *button, GtkWidget *child)
|
||||
copy_cb (GtkWidget *child)
|
||||
{
|
||||
GdkClipboard *clipboard;
|
||||
GtkDemoWidget *demo;
|
||||
|
||||
g_print ("Copy %s\n", G_OBJECT_TYPE_NAME (child));
|
||||
|
||||
demo = serialize_widget (child);
|
||||
|
||||
clipboard = gdk_display_get_clipboard (gdk_display_get_default ());
|
||||
gdk_clipboard_set (clipboard, GTK_TYPE_DEMO_WIDGET, demo);
|
||||
|
||||
gtk_popover_popdown (GTK_POPOVER (gtk_widget_get_ancestor (button, GTK_TYPE_POPOVER)));
|
||||
}
|
||||
|
||||
static void
|
||||
delete_cb (GtkWidget *button, GtkWidget *child)
|
||||
delete_cb (GtkWidget *child)
|
||||
{
|
||||
gtk_widget_destroy (child);
|
||||
|
||||
gtk_popover_popdown (GTK_POPOVER (gtk_widget_get_ancestor (button, GTK_TYPE_POPOVER)));
|
||||
}
|
||||
|
||||
static void
|
||||
cut_cb (GtkWidget *button, GtkWidget *child)
|
||||
cut_cb (GtkWidget *child)
|
||||
{
|
||||
copy_cb (button, child);
|
||||
delete_cb (button, child);
|
||||
|
||||
gtk_popover_popdown (GTK_POPOVER (gtk_widget_get_ancestor (button, GTK_TYPE_POPOVER)));
|
||||
copy_cb (child);
|
||||
delete_cb (child);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -185,7 +175,7 @@ value_read (GObject *source,
|
||||
}
|
||||
|
||||
static void
|
||||
paste_cb (GtkWidget *button, GtkWidget *fixed)
|
||||
paste_cb (GtkWidget *fixed)
|
||||
{
|
||||
GdkClipboard *clipboard;
|
||||
|
||||
@@ -197,8 +187,6 @@ paste_cb (GtkWidget *button, GtkWidget *fixed)
|
||||
}
|
||||
else
|
||||
g_print ("Don't know how to handle clipboard contents\n");
|
||||
|
||||
gtk_popover_popdown (GTK_POPOVER (gtk_widget_get_ancestor (button, GTK_TYPE_POPOVER)));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -217,7 +205,7 @@ edit_label_done (GtkWidget *entry, gpointer data)
|
||||
}
|
||||
|
||||
static void
|
||||
edit_cb (GtkWidget *button, GtkWidget *child)
|
||||
edit_cb (GtkWidget *child)
|
||||
{
|
||||
GtkWidget *fixed = gtk_widget_get_parent (child);
|
||||
int x, y;
|
||||
@@ -231,7 +219,6 @@ edit_cb (GtkWidget *button, GtkWidget *child)
|
||||
g_object_set_data (G_OBJECT (entry), "label", child);
|
||||
|
||||
gtk_editable_set_text (GTK_EDITABLE (entry), gtk_label_get_text (GTK_LABEL (child)));
|
||||
gtk_editable_set_width_chars (GTK_EDITABLE (entry), 12);
|
||||
g_signal_connect (entry, "activate", G_CALLBACK (edit_label_done), NULL);
|
||||
gtk_fixed_put (GTK_FIXED (fixed), entry, x, y);
|
||||
gtk_widget_grab_focus (entry);
|
||||
@@ -240,12 +227,9 @@ edit_cb (GtkWidget *button, GtkWidget *child)
|
||||
{
|
||||
gboolean active;
|
||||
|
||||
g_object_get (child, "spinning", &active, NULL);
|
||||
g_object_set (child, "spinning", !active, NULL);
|
||||
g_object_get (child, "active", &active, NULL);
|
||||
g_object_set (child, "active", !active, NULL);
|
||||
}
|
||||
|
||||
if (button)
|
||||
gtk_popover_popdown (GTK_POPOVER (gtk_widget_get_ancestor (button, GTK_TYPE_POPOVER)));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -263,66 +247,65 @@ pressed_cb (GtkGesture *gesture,
|
||||
|
||||
if (gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture)) == GDK_BUTTON_SECONDARY)
|
||||
{
|
||||
GdkRectangle rect;
|
||||
GtkWidget *menu;
|
||||
GtkWidget *box;
|
||||
GtkWidget *item;
|
||||
GdkClipboard *clipboard;
|
||||
|
||||
pos_x = x;
|
||||
pos_y = y;
|
||||
|
||||
menu = gtk_popover_new ();
|
||||
gtk_widget_set_parent (menu, widget);
|
||||
gtk_popover_set_has_arrow (GTK_POPOVER (menu), FALSE);
|
||||
gtk_popover_set_pointing_to (GTK_POPOVER (menu), &(GdkRectangle){ x, y, 1, 1});
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_container_add (GTK_CONTAINER (menu), box);
|
||||
menu = gtk_menu_new ();
|
||||
item = gtk_menu_item_new_with_label ("New Label");
|
||||
g_signal_connect (item, "activate", G_CALLBACK (new_label_cb), widget);
|
||||
gtk_container_add (GTK_CONTAINER (menu), item);
|
||||
item = gtk_menu_item_new_with_label ("New Spinner");
|
||||
g_signal_connect (item, "activate", G_CALLBACK (new_spinner_cb), widget);
|
||||
gtk_container_add (GTK_CONTAINER (menu), item);
|
||||
|
||||
item = gtk_button_new_with_label ("New Label");
|
||||
gtk_button_set_relief (GTK_BUTTON (item), GTK_RELIEF_NONE);
|
||||
g_signal_connect (item, "clicked", G_CALLBACK (new_label_cb), widget);
|
||||
gtk_container_add (GTK_CONTAINER (box), item);
|
||||
item = gtk_button_new_with_label ("New Spinner");
|
||||
gtk_button_set_relief (GTK_BUTTON (item), GTK_RELIEF_NONE);
|
||||
g_signal_connect (item, "clicked", G_CALLBACK (new_spinner_cb), widget);
|
||||
gtk_container_add (GTK_CONTAINER (box), item);
|
||||
item = gtk_separator_menu_item_new ();
|
||||
gtk_container_add (GTK_CONTAINER (menu), item);
|
||||
|
||||
item = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
|
||||
gtk_container_add (GTK_CONTAINER (box), item);
|
||||
|
||||
item = gtk_button_new_with_label ("Edit");
|
||||
gtk_button_set_relief (GTK_BUTTON (item), GTK_RELIEF_NONE);
|
||||
item = gtk_menu_item_new_with_label ("Edit");
|
||||
gtk_widget_set_sensitive (item, child != NULL && child != widget);
|
||||
g_signal_connect (item, "clicked", G_CALLBACK (edit_cb), child);
|
||||
gtk_container_add (GTK_CONTAINER (box), item);
|
||||
g_signal_connect_swapped (item, "activate", G_CALLBACK (edit_cb), child);
|
||||
gtk_container_add (GTK_CONTAINER (menu), item);
|
||||
|
||||
item = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
|
||||
gtk_container_add (GTK_CONTAINER (box), item);
|
||||
item = gtk_separator_menu_item_new ();
|
||||
gtk_container_add (GTK_CONTAINER (menu), item);
|
||||
|
||||
item = gtk_button_new_with_label ("Cut");
|
||||
gtk_button_set_relief (GTK_BUTTON (item), GTK_RELIEF_NONE);
|
||||
item = gtk_menu_item_new_with_label ("Cut");
|
||||
gtk_widget_set_sensitive (item, child != NULL && child != widget);
|
||||
g_signal_connect (item, "clicked", G_CALLBACK (cut_cb), child);
|
||||
gtk_container_add (GTK_CONTAINER (box), item);
|
||||
item = gtk_button_new_with_label ("Copy");
|
||||
gtk_button_set_relief (GTK_BUTTON (item), GTK_RELIEF_NONE);
|
||||
g_signal_connect_swapped (item, "activate", G_CALLBACK (cut_cb), child);
|
||||
gtk_container_add (GTK_CONTAINER (menu), item);
|
||||
item = gtk_menu_item_new_with_label ("Copy");
|
||||
gtk_widget_set_sensitive (item, child != NULL && child != widget);
|
||||
g_signal_connect (item, "clicked", G_CALLBACK (copy_cb), child);
|
||||
gtk_container_add (GTK_CONTAINER (box), item);
|
||||
item = gtk_button_new_with_label ("Paste");
|
||||
gtk_button_set_relief (GTK_BUTTON (item), GTK_RELIEF_NONE);
|
||||
g_signal_connect_swapped (item, "activate", G_CALLBACK (copy_cb), child);
|
||||
gtk_container_add (GTK_CONTAINER (menu), item);
|
||||
item = gtk_menu_item_new_with_label ("Paste");
|
||||
clipboard = gdk_display_get_clipboard (gdk_display_get_default ());
|
||||
gtk_widget_set_sensitive (item,
|
||||
gdk_content_formats_contain_gtype (gdk_clipboard_get_formats (clipboard), GTK_TYPE_DEMO_WIDGET));
|
||||
g_signal_connect (item, "clicked", G_CALLBACK (paste_cb), widget);
|
||||
gtk_container_add (GTK_CONTAINER (box), item);
|
||||
item = gtk_button_new_with_label ("Delete");
|
||||
gtk_button_set_relief (GTK_BUTTON (item), GTK_RELIEF_NONE);
|
||||
g_signal_connect_swapped (item, "activate", G_CALLBACK (paste_cb), widget);
|
||||
gtk_container_add (GTK_CONTAINER (menu), item);
|
||||
item = gtk_menu_item_new_with_label ("Delete");
|
||||
gtk_widget_set_sensitive (item, child != NULL && child != widget);
|
||||
g_signal_connect (item, "clicked", G_CALLBACK (delete_cb), child);
|
||||
gtk_container_add (GTK_CONTAINER (box), item);
|
||||
g_signal_connect_swapped (item, "activate", G_CALLBACK (delete_cb), child);
|
||||
gtk_container_add (GTK_CONTAINER (menu), item);
|
||||
|
||||
gtk_popover_popup (GTK_POPOVER (menu));
|
||||
rect.x = x;
|
||||
rect.y = y;
|
||||
rect.width = 0;
|
||||
rect.height = 0;
|
||||
|
||||
gtk_menu_popup_at_rect (GTK_MENU (menu),
|
||||
gtk_native_get_surface (gtk_widget_get_native (widget)),
|
||||
&rect,
|
||||
GDK_GRAVITY_NORTH_WEST,
|
||||
GDK_GRAVITY_NORTH_WEST,
|
||||
NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,7 +325,7 @@ released_cb (GtkGesture *gesture,
|
||||
if (gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture)) == GDK_BUTTON_PRIMARY)
|
||||
{
|
||||
if (child != NULL && child != widget)
|
||||
edit_cb (NULL, child);
|
||||
edit_cb (child);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,7 +340,7 @@ do_dnd (GtkWidget *do_widget)
|
||||
GtkGesture *multipress;
|
||||
GtkCssProvider *provider;
|
||||
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Drag-and-drop");
|
||||
|
@@ -189,7 +189,7 @@ do_drawingarea (GtkWidget *do_widget)
|
||||
|
||||
if (!window)
|
||||
{
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Drawing Area");
|
||||
@@ -198,10 +198,7 @@ do_drawingarea (GtkWidget *do_widget)
|
||||
G_CALLBACK (close_window), NULL);
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8);
|
||||
gtk_widget_set_margin_start (vbox, 16);
|
||||
gtk_widget_set_margin_end (vbox, 16);
|
||||
gtk_widget_set_margin_top (vbox, 16);
|
||||
gtk_widget_set_margin_bottom (vbox, 16);
|
||||
g_object_set (vbox, "margin", 16, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), vbox);
|
||||
|
||||
/*
|
||||
|
@@ -275,9 +275,6 @@ cell_edited (GtkCellRendererText *cell,
|
||||
g_array_index (articles, Item, i).product, -1);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
gtk_tree_path_free (path);
|
||||
@@ -348,7 +345,7 @@ do_editable_cells (GtkWidget *do_widget)
|
||||
GtkTreeModel *items_model;
|
||||
GtkTreeModel *numbers_model;
|
||||
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Editable Cells");
|
||||
@@ -356,10 +353,7 @@ do_editable_cells (GtkWidget *do_widget)
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
|
||||
gtk_widget_set_margin_start (vbox, 5);
|
||||
gtk_widget_set_margin_end (vbox, 5);
|
||||
gtk_widget_set_margin_top (vbox, 5);
|
||||
gtk_widget_set_margin_bottom (vbox, 5);
|
||||
g_object_set (vbox, "margin", 5, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), vbox);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (vbox),
|
||||
|
@@ -9,7 +9,7 @@
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/* Creates a tree model containing the completions */
|
||||
static GtkTreeModel *
|
||||
GtkTreeModel *
|
||||
create_completion_model (void)
|
||||
{
|
||||
GtkListStore *store;
|
||||
@@ -45,7 +45,7 @@ do_entry_completion (GtkWidget *do_widget)
|
||||
|
||||
if (!window)
|
||||
{
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Entry Completion");
|
||||
@@ -55,10 +55,7 @@ do_entry_completion (GtkWidget *do_widget)
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
|
||||
gtk_widget_set_margin_start (vbox, 5);
|
||||
gtk_widget_set_margin_end (vbox, 5);
|
||||
gtk_widget_set_margin_top (vbox, 5);
|
||||
gtk_widget_set_margin_bottom (vbox, 5);
|
||||
g_object_set (vbox, "margin", 5, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), vbox);
|
||||
|
||||
label = gtk_label_new (NULL);
|
||||
|
@@ -20,7 +20,7 @@ do_entry_undo (GtkWidget *do_widget)
|
||||
|
||||
if (!window)
|
||||
{
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Entry Undo");
|
||||
@@ -29,10 +29,7 @@ do_entry_undo (GtkWidget *do_widget)
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
|
||||
gtk_widget_set_margin_start (vbox, 5);
|
||||
gtk_widget_set_margin_end (vbox, 5);
|
||||
gtk_widget_set_margin_top (vbox, 5);
|
||||
gtk_widget_set_margin_bottom (vbox, 5);
|
||||
g_object_set (vbox, "margin", 5, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), vbox);
|
||||
|
||||
label = gtk_label_new (NULL);
|
||||
|
@@ -31,10 +31,7 @@
|
||||
<property name="title" translatable="yes">Filter Model</property>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid1">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="row-spacing">10</property>
|
||||
<property name="column-spacing">10</property>
|
||||
<property name="column-homogeneous">1</property>
|
||||
|
@@ -22,11 +22,29 @@ gsize n_icon_names = 0;
|
||||
static void
|
||||
init_icon_names (GtkIconTheme *theme)
|
||||
{
|
||||
GPtrArray *icons;
|
||||
GList *l, *icon_list;
|
||||
|
||||
if (icon_names)
|
||||
return;
|
||||
|
||||
icon_names = gtk_icon_theme_get_icon_names (theme);
|
||||
n_icon_names = g_strv_length (icon_names);
|
||||
icon_list = gtk_icon_theme_list_icons (theme, NULL);
|
||||
icons = g_ptr_array_new ();
|
||||
|
||||
for (l = icon_list; l; l = l->next)
|
||||
{
|
||||
if (g_str_has_suffix (l->data, "symbolic"))
|
||||
continue;
|
||||
|
||||
g_ptr_array_add (icons, g_strdup (l->data));
|
||||
}
|
||||
|
||||
n_icon_names = icons->len;
|
||||
g_ptr_array_add (icons, NULL); /* NULL-terminate the array */
|
||||
icon_names = (char **) g_ptr_array_free (icons, FALSE);
|
||||
|
||||
/* don't free strings, we assigned them to the array */
|
||||
g_list_free_full (icon_list, g_free);
|
||||
}
|
||||
|
||||
static const char *
|
||||
@@ -37,16 +55,13 @@ get_random_icon_name (GtkIconTheme *theme)
|
||||
return icon_names[g_random_int_range(0, n_icon_names)];
|
||||
}
|
||||
|
||||
/* Can't be static because it's also used in iconscroll.c */
|
||||
GtkWidget *
|
||||
create_icon (void)
|
||||
{
|
||||
GtkWidget *image;
|
||||
|
||||
image = gtk_image_new ();
|
||||
image = gtk_image_new_from_icon_name (get_random_icon_name (gtk_icon_theme_get_default ()));
|
||||
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (image),
|
||||
get_random_icon_name (gtk_icon_theme_get_for_display (gtk_widget_get_display (image))));
|
||||
|
||||
return image;
|
||||
}
|
||||
@@ -159,7 +174,7 @@ static GtkWidget *
|
||||
create_menu_button (void)
|
||||
{
|
||||
GtkWidget *w = gtk_menu_button_new ();
|
||||
GtkWidget *popover = gtk_popover_new ();
|
||||
GtkWidget *popover = gtk_popover_new (NULL);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (popover), gtk_button_new_with_label ("Hey!"));
|
||||
gtk_popover_set_autohide (GTK_POPOVER (popover), FALSE);
|
||||
@@ -250,6 +265,14 @@ fishbowl_changes_toggled_cb (GtkToggleButton *button,
|
||||
gtk_button_set_icon_name (GTK_BUTTON (button), "changes-allow");
|
||||
}
|
||||
|
||||
char *
|
||||
format_header_cb (GObject *object,
|
||||
guint count,
|
||||
double fps)
|
||||
{
|
||||
return g_strdup_printf ("%u Icons, %.2f fps", count, fps);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_fishbowl (GtkWidget *do_widget)
|
||||
{
|
||||
|
@@ -28,22 +28,12 @@
|
||||
</child>
|
||||
<child type="end">
|
||||
<object class="GtkLabel">
|
||||
<property name="label">fps</property>
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
<object class="GtkLabel">
|
||||
<property name="label" bind-source="bowl" bind-property="framerate-string"/>
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Icons, </property>
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
<object class="GtkLabel">
|
||||
<property name="label" bind-source="bowl" bind-property="count"/>
|
||||
<binding name="label">
|
||||
<closure type="gchararray" function="format_header_cb">
|
||||
<lookup name="count">bowl</lookup>
|
||||
<lookup name="framerate">bowl</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
|
@@ -124,7 +124,7 @@ create_demo_window (GtkWidget *do_widget)
|
||||
{
|
||||
GtkWidget *window, *sw, *fixed, *cube;
|
||||
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Fixed layout");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
|
||||
|
@@ -719,7 +719,7 @@ do_flowbox (GtkWidget *do_widget)
|
||||
|
||||
if (!window)
|
||||
{
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Flow Box");
|
||||
|
@@ -33,10 +33,7 @@
|
||||
<object class="GtkViewport">
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
@@ -112,10 +109,7 @@
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="hexpand">1</property>
|
||||
<property name="vexpand">1</property>
|
||||
<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="margin">20</property>
|
||||
<property name="spacing">20</property>
|
||||
<child>
|
||||
<object class="GtkStack" id="stack">
|
||||
|
@@ -25,14 +25,14 @@
|
||||
|
||||
#define MAKE_TAG(a,b,c,d) (unsigned int)(((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
|
||||
|
||||
static GtkWidget *the_label;
|
||||
static GtkWidget *label;
|
||||
static GtkWidget *settings;
|
||||
static GtkWidget *description;
|
||||
static GtkWidget *font;
|
||||
static GtkWidget *script_lang;
|
||||
static GtkWidget *resetbutton;
|
||||
static GtkWidget *stack;
|
||||
static GtkWidget *the_entry;
|
||||
static GtkWidget *entry;
|
||||
static GtkWidget *variations_heading;
|
||||
static GtkWidget *variations_grid;
|
||||
static GtkWidget *instance_combo;
|
||||
@@ -301,9 +301,9 @@ update_display (void)
|
||||
char *font_desc;
|
||||
char *features;
|
||||
|
||||
text = gtk_editable_get_text (GTK_EDITABLE (the_entry));
|
||||
text = gtk_editable_get_text (GTK_EDITABLE (entry));
|
||||
|
||||
if (gtk_label_get_selection_bounds (GTK_LABEL (the_label), &ins, &bound))
|
||||
if (gtk_label_get_selection_bounds (GTK_LABEL (label), &ins, &bound))
|
||||
{
|
||||
start = g_utf8_offset_to_pointer (text, ins) - text;
|
||||
end = g_utf8_offset_to_pointer (text, bound) - text;
|
||||
@@ -409,8 +409,8 @@ update_display (void)
|
||||
|
||||
gtk_label_set_text (GTK_LABEL (description), font_desc);
|
||||
gtk_label_set_text (GTK_LABEL (settings), features);
|
||||
gtk_label_set_text (GTK_LABEL (the_label), text);
|
||||
gtk_label_set_attributes (GTK_LABEL (the_label), attrs);
|
||||
gtk_label_set_text (GTK_LABEL (label), text);
|
||||
gtk_label_set_attributes (GTK_LABEL (label), attrs);
|
||||
|
||||
g_free (font_desc);
|
||||
pango_font_description_free (desc);
|
||||
@@ -548,7 +548,7 @@ update_script_combo (void)
|
||||
{
|
||||
const char *langname;
|
||||
char langbuf[5];
|
||||
GtkTreeIter tree_iter;
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (pair->lang_tag == HB_OT_TAG_DEFAULT_LANGUAGE)
|
||||
langname = NC_("Language", "Default");
|
||||
@@ -563,7 +563,7 @@ update_script_combo (void)
|
||||
}
|
||||
}
|
||||
|
||||
gtk_list_store_insert_with_values (store, &tree_iter, -1,
|
||||
gtk_list_store_insert_with_values (store, &iter, -1,
|
||||
0, langname,
|
||||
1, pair->script_index,
|
||||
2, pair->lang_index,
|
||||
@@ -572,7 +572,7 @@ update_script_combo (void)
|
||||
if (pair->lang_tag == active)
|
||||
{
|
||||
have_active = TRUE;
|
||||
active_iter = tree_iter;
|
||||
active_iter = iter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -751,7 +751,7 @@ add_font_variations (GString *s)
|
||||
GHashTableIter iter;
|
||||
Axis *axis;
|
||||
char buf[G_ASCII_DTOSTR_BUF_SIZE];
|
||||
const char *sep = "";
|
||||
char *sep = "";
|
||||
|
||||
g_hash_table_iter_init (&iter, axes);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *)NULL, (gpointer *)&axis))
|
||||
@@ -1129,7 +1129,7 @@ font_features_reset_features (void)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
gtk_label_select_region (GTK_LABEL (the_label), 0, 0);
|
||||
gtk_label_select_region (GTK_LABEL (label), 0, 0);
|
||||
|
||||
g_list_free_full (ranges, free_range);
|
||||
ranges = NULL;
|
||||
@@ -1156,9 +1156,9 @@ static char *text;
|
||||
static void
|
||||
switch_to_entry (void)
|
||||
{
|
||||
text = g_strdup (gtk_editable_get_text (GTK_EDITABLE (the_entry)));
|
||||
text = g_strdup (gtk_editable_get_text (GTK_EDITABLE (entry)));
|
||||
gtk_stack_set_visible_child_name (GTK_STACK (stack), "entry");
|
||||
gtk_widget_grab_focus (the_entry);
|
||||
gtk_widget_grab_focus (entry);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1217,20 +1217,20 @@ do_font_features (GtkWidget *do_widget)
|
||||
|
||||
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
|
||||
feature_list = GTK_WIDGET (gtk_builder_get_object (builder, "feature_list"));
|
||||
the_label = GTK_WIDGET (gtk_builder_get_object (builder, "label"));
|
||||
label = GTK_WIDGET (gtk_builder_get_object (builder, "label"));
|
||||
settings = GTK_WIDGET (gtk_builder_get_object (builder, "settings"));
|
||||
description = GTK_WIDGET (gtk_builder_get_object (builder, "description"));
|
||||
resetbutton = GTK_WIDGET (gtk_builder_get_object (builder, "reset"));
|
||||
font = GTK_WIDGET (gtk_builder_get_object (builder, "font"));
|
||||
script_lang = GTK_WIDGET (gtk_builder_get_object (builder, "script_lang"));
|
||||
stack = GTK_WIDGET (gtk_builder_get_object (builder, "stack"));
|
||||
the_entry = GTK_WIDGET (gtk_builder_get_object (builder, "entry"));
|
||||
entry = GTK_WIDGET (gtk_builder_get_object (builder, "entry"));
|
||||
edit_toggle = GTK_WIDGET (gtk_builder_get_object (builder, "edit_toggle"));
|
||||
|
||||
controller = gtk_event_controller_key_new ();
|
||||
g_object_set_data_full (G_OBJECT (the_entry), "controller", g_object_ref (controller), g_object_unref);
|
||||
g_signal_connect (controller, "key-pressed", G_CALLBACK (entry_key_press), the_entry);
|
||||
gtk_widget_add_controller (the_entry, controller);
|
||||
g_object_set_data_full (G_OBJECT (entry), "controller", controller, g_object_unref);
|
||||
g_signal_connect (controller, "key-pressed", G_CALLBACK (entry_key_press), entry);
|
||||
gtk_widget_add_controller (entry, controller);
|
||||
|
||||
add_check_group (feature_list, _("Kerning"), (const char *[]){ "kern", NULL });
|
||||
add_check_group (feature_list, _("Ligatures"), (const char *[]){ "liga",
|
||||
@@ -1337,8 +1337,6 @@ do_font_features (GtkWidget *do_widget)
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
g_object_unref (builder);
|
||||
|
||||
update_display ();
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
@@ -140,6 +140,17 @@ update_value (GtkFontPlane *plane,
|
||||
gtk_widget_queue_draw (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
hold_action (GtkGestureLongPress *gesture,
|
||||
gdouble x,
|
||||
gdouble y,
|
||||
GtkFontPlane *plane)
|
||||
{
|
||||
gboolean handled;
|
||||
|
||||
g_signal_emit_by_name (plane, "popup-menu", &handled);
|
||||
}
|
||||
|
||||
static void
|
||||
plane_drag_gesture_begin (GtkGestureDrag *gesture,
|
||||
gdouble start_x,
|
||||
@@ -150,6 +161,13 @@ plane_drag_gesture_begin (GtkGestureDrag *gesture,
|
||||
|
||||
button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
|
||||
|
||||
if (button == GDK_BUTTON_SECONDARY)
|
||||
{
|
||||
gboolean handled;
|
||||
|
||||
g_signal_emit_by_name (plane, "popup-menu", &handled);
|
||||
}
|
||||
|
||||
if (button != GDK_BUTTON_PRIMARY)
|
||||
{
|
||||
gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
|
||||
@@ -200,6 +218,13 @@ gtk_font_plane_init (GtkFontPlane *plane)
|
||||
G_CALLBACK (plane_drag_gesture_end), plane);
|
||||
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), 0);
|
||||
gtk_widget_add_controller (GTK_WIDGET (plane), GTK_EVENT_CONTROLLER (gesture));
|
||||
|
||||
gesture = gtk_gesture_long_press_new ();
|
||||
g_signal_connect (gesture, "pressed",
|
||||
G_CALLBACK (hold_action), plane);
|
||||
gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (gesture),
|
||||
TRUE);
|
||||
gtk_widget_add_controller (GTK_WIDGET (plane), GTK_EVENT_CONTROLLER (gesture));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -43,6 +43,7 @@ update_image (void)
|
||||
cairo_font_options_t *fopt;
|
||||
cairo_hint_style_t hintstyle;
|
||||
cairo_hint_metrics_t hintmetrics;
|
||||
int i;
|
||||
|
||||
if (!context)
|
||||
context = gtk_widget_create_pango_context (image);
|
||||
@@ -115,7 +116,6 @@ update_image (void)
|
||||
|
||||
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (show_grid)))
|
||||
{
|
||||
int i;
|
||||
cairo_set_source_rgba (cr, 0.2, 0, 0, 0.2);
|
||||
for (i = 1; i < ink.height + 20; i++)
|
||||
{
|
||||
|
@@ -165,11 +165,10 @@
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<style>
|
||||
<class name="linked"/>
|
||||
</style>
|
||||
<style><class name="linked"/></style>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="text_radio">
|
||||
<property name="draw-indicator">0</property>
|
||||
@@ -184,7 +183,7 @@
|
||||
</object>
|
||||
</child>
|
||||
<layout>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">3</property>
|
||||
<property name="column-span">7</property>
|
||||
</layout>
|
||||
|
984
demos/gtk-demo/foreigndrawing.c
Normal file
984
demos/gtk-demo/foreigndrawing.c
Normal file
@@ -0,0 +1,984 @@
|
||||
/* Foreign drawing
|
||||
*
|
||||
* Many applications can't use GTK widgets, for a variety of reasons,
|
||||
* but still want their user interface to appear integrated with the
|
||||
* rest of the desktop, and follow GTK themes. This demo shows how to
|
||||
* use GtkStyleContext and the gtk_render_ APIs to achieve this.
|
||||
*
|
||||
* Note that this is a very simple, non-interactive example.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <string.h>
|
||||
|
||||
static void
|
||||
append_element (GtkWidgetPath *path,
|
||||
const char *selector)
|
||||
{
|
||||
static const struct {
|
||||
const char *name;
|
||||
GtkStateFlags state_flag;
|
||||
} pseudo_classes[] = {
|
||||
{ "active", GTK_STATE_FLAG_ACTIVE },
|
||||
{ "hover", GTK_STATE_FLAG_PRELIGHT },
|
||||
{ "selected", GTK_STATE_FLAG_SELECTED },
|
||||
{ "disabled", GTK_STATE_FLAG_INSENSITIVE },
|
||||
{ "indeterminate", GTK_STATE_FLAG_INCONSISTENT },
|
||||
{ "focus", GTK_STATE_FLAG_FOCUSED },
|
||||
{ "backdrop", GTK_STATE_FLAG_BACKDROP },
|
||||
{ "dir(ltr)", GTK_STATE_FLAG_DIR_LTR },
|
||||
{ "dir(rtl)", GTK_STATE_FLAG_DIR_RTL },
|
||||
{ "link", GTK_STATE_FLAG_LINK },
|
||||
{ "visited", GTK_STATE_FLAG_VISITED },
|
||||
{ "checked", GTK_STATE_FLAG_CHECKED },
|
||||
{ "drop(active)", GTK_STATE_FLAG_DROP_ACTIVE }
|
||||
};
|
||||
const char *next;
|
||||
char *name;
|
||||
char type;
|
||||
guint i;
|
||||
|
||||
next = strpbrk (selector, "#.:");
|
||||
if (next == NULL)
|
||||
next = selector + strlen (selector);
|
||||
|
||||
name = g_strndup (selector, next - selector);
|
||||
if (g_ascii_isupper (selector[0]))
|
||||
{
|
||||
GType gtype;
|
||||
gtype = g_type_from_name (name);
|
||||
if (gtype == G_TYPE_INVALID)
|
||||
{
|
||||
g_critical ("Unknown type name `%s'", name);
|
||||
g_free (name);
|
||||
return;
|
||||
}
|
||||
gtk_widget_path_append_type (path, gtype);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Omit type, we're using name */
|
||||
gtk_widget_path_append_type (path, G_TYPE_NONE);
|
||||
gtk_widget_path_iter_set_object_name (path, -1, name);
|
||||
}
|
||||
g_free (name);
|
||||
|
||||
while (*next != '\0')
|
||||
{
|
||||
type = *next;
|
||||
selector = next + 1;
|
||||
next = strpbrk (selector, "#.:");
|
||||
if (next == NULL)
|
||||
next = selector + strlen (selector);
|
||||
name = g_strndup (selector, next - selector);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case '#':
|
||||
gtk_widget_path_iter_set_name (path, -1, name);
|
||||
break;
|
||||
|
||||
case '.':
|
||||
gtk_widget_path_iter_add_class (path, -1, name);
|
||||
break;
|
||||
|
||||
case ':':
|
||||
for (i = 0; i < G_N_ELEMENTS (pseudo_classes); i++)
|
||||
{
|
||||
if (g_str_equal (pseudo_classes[i].name, name))
|
||||
{
|
||||
gtk_widget_path_iter_set_state (path,
|
||||
-1,
|
||||
gtk_widget_path_iter_get_state (path, -1)
|
||||
| pseudo_classes[i].state_flag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == G_N_ELEMENTS (pseudo_classes))
|
||||
g_critical ("Unknown pseudo-class :%s", name);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (name);
|
||||
}
|
||||
}
|
||||
|
||||
static GtkStyleContext *
|
||||
create_context_for_path (GtkWidgetPath *path,
|
||||
GtkStyleContext *parent)
|
||||
{
|
||||
GtkStyleContext *context;
|
||||
|
||||
context = gtk_style_context_new ();
|
||||
gtk_style_context_set_path (context, path);
|
||||
gtk_style_context_set_parent (context, parent);
|
||||
/* Unfortunately, we have to explicitly set the state again here
|
||||
* for it to take effect
|
||||
*/
|
||||
gtk_style_context_set_state (context, gtk_widget_path_iter_get_state (path, -1));
|
||||
gtk_widget_path_unref (path);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
static GtkStyleContext *
|
||||
get_style (GtkStyleContext *parent,
|
||||
const char *selector)
|
||||
{
|
||||
GtkWidgetPath *path;
|
||||
|
||||
if (parent)
|
||||
path = gtk_widget_path_copy (gtk_style_context_get_path (parent));
|
||||
else
|
||||
path = gtk_widget_path_new ();
|
||||
|
||||
append_element (path, selector);
|
||||
|
||||
return create_context_for_path (path, parent);
|
||||
}
|
||||
|
||||
static GtkStyleContext *
|
||||
get_style_with_siblings (GtkStyleContext *parent,
|
||||
const char *selector,
|
||||
const char **siblings,
|
||||
gint position)
|
||||
{
|
||||
GtkWidgetPath *path, *siblings_path;
|
||||
guint i;
|
||||
|
||||
if (parent)
|
||||
path = gtk_widget_path_copy (gtk_style_context_get_path (parent));
|
||||
else
|
||||
path = gtk_widget_path_new ();
|
||||
|
||||
siblings_path = gtk_widget_path_new ();
|
||||
for (i = 0; siblings[i]; i++)
|
||||
append_element (siblings_path, siblings[i]);
|
||||
|
||||
gtk_widget_path_append_with_siblings (path, siblings_path, position);
|
||||
gtk_widget_path_unref (siblings_path);
|
||||
|
||||
return create_context_for_path (path, parent);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_style_common (GtkStyleContext *context,
|
||||
cairo_t *cr,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height,
|
||||
gint *contents_x,
|
||||
gint *contents_y,
|
||||
gint *contents_width,
|
||||
gint *contents_height)
|
||||
{
|
||||
GtkBorder margin, border, padding;
|
||||
int min_width, min_height;
|
||||
|
||||
gtk_style_context_get_margin (context, &margin);
|
||||
gtk_style_context_get_border (context, &border);
|
||||
gtk_style_context_get_padding (context, &padding);
|
||||
|
||||
gtk_style_context_get (context,
|
||||
"min-width", &min_width,
|
||||
"min-height", &min_height,
|
||||
NULL);
|
||||
x += margin.left;
|
||||
y += margin.top;
|
||||
width -= margin.left + margin.right;
|
||||
height -= margin.top + margin.bottom;
|
||||
|
||||
width = MAX (width, min_width);
|
||||
height = MAX (height, min_height);
|
||||
|
||||
gtk_render_background (context, cr, x, y, width, height);
|
||||
gtk_render_frame (context, cr, x, y, width, height);
|
||||
|
||||
if (contents_x)
|
||||
*contents_x = x + border.left + padding.left;
|
||||
if (contents_y)
|
||||
*contents_y = y + border.top + padding.top;
|
||||
if (contents_width)
|
||||
*contents_width = width - border.left - border.right - padding.left - padding.right;
|
||||
if (contents_height)
|
||||
*contents_height = height - border.top - border.bottom - padding.top - padding.bottom;
|
||||
}
|
||||
|
||||
static void
|
||||
query_size (GtkStyleContext *context,
|
||||
gint *width,
|
||||
gint *height)
|
||||
{
|
||||
GtkBorder margin, border, padding;
|
||||
int min_width, min_height;
|
||||
|
||||
gtk_style_context_get_margin (context, &margin);
|
||||
gtk_style_context_get_border (context, &border);
|
||||
gtk_style_context_get_padding (context, &padding);
|
||||
|
||||
gtk_style_context_get (context,
|
||||
"min-width", &min_width,
|
||||
"min-height", &min_height,
|
||||
NULL);
|
||||
|
||||
min_width += margin.left + margin.right + border.left + border.right + padding.left + padding.right;
|
||||
min_height += margin.top + margin.bottom + border.top + border.bottom + padding.top + padding.bottom;
|
||||
|
||||
if (width)
|
||||
*width = MAX (*width, min_width);
|
||||
if (height)
|
||||
*height = MAX (*height, min_height);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_menu (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint *height)
|
||||
{
|
||||
GtkStyleContext *menu_context;
|
||||
GtkStyleContext *menuitem_context;
|
||||
GtkStyleContext *hovermenuitem_context;
|
||||
GtkStyleContext *hoveredarrowmenuitem_context;
|
||||
GtkStyleContext *arrowmenuitem_context;
|
||||
GtkStyleContext *checkmenuitem_context;
|
||||
GtkStyleContext *disabledarrowmenuitem_context;
|
||||
GtkStyleContext *disabledcheckmenuitem_context;
|
||||
GtkStyleContext *radiomenuitem_context;
|
||||
GtkStyleContext *disablemenuitem_context;
|
||||
GtkStyleContext *disabledradiomenuitem_context;
|
||||
GtkStyleContext *separatormenuitem_context;
|
||||
gint menuitem1_height, menuitem2_height, menuitem3_height, menuitem4_height, menuitem5_height;
|
||||
gint contents_x, contents_y, contents_width, contents_height;
|
||||
gint menu_x, menu_y, menu_width, menu_height;
|
||||
gint arrow_width, arrow_height, arrow_size;
|
||||
gint toggle_x, toggle_y, toggle_width, toggle_height;
|
||||
|
||||
/* This information is taken from the GtkMenu docs, see "CSS nodes" */
|
||||
menu_context = get_style (gtk_widget_get_style_context(widget), "menu");
|
||||
hovermenuitem_context = get_style (menu_context, "menuitem:hover");
|
||||
hoveredarrowmenuitem_context = get_style (hovermenuitem_context, "arrow.right:dir(ltr)");
|
||||
menuitem_context = get_style (menu_context, "menuitem");
|
||||
arrowmenuitem_context = get_style (menuitem_context, "arrow:dir(rtl)");
|
||||
disablemenuitem_context = get_style (menu_context, "menuitem:disabled");
|
||||
disabledarrowmenuitem_context = get_style (disablemenuitem_context, "arrow:dir(rtl)");
|
||||
checkmenuitem_context = get_style (menuitem_context, "check:checked");
|
||||
disabledcheckmenuitem_context = get_style (disablemenuitem_context, "check");
|
||||
separatormenuitem_context = get_style (menu_context, "separator:disabled");
|
||||
radiomenuitem_context = get_style (menuitem_context, "radio:checked");
|
||||
disabledradiomenuitem_context = get_style (disablemenuitem_context, "radio");
|
||||
|
||||
*height = 0;
|
||||
query_size (menu_context, NULL, height);
|
||||
menuitem1_height = 0;
|
||||
query_size (hovermenuitem_context, NULL, &menuitem1_height);
|
||||
query_size (hoveredarrowmenuitem_context, NULL, &menuitem1_height);
|
||||
*height += menuitem1_height;
|
||||
menuitem2_height = 0;
|
||||
query_size (menu_context, NULL, &menuitem5_height);
|
||||
query_size (menuitem_context, NULL, &menuitem2_height);
|
||||
query_size (arrowmenuitem_context, NULL, &menuitem2_height);
|
||||
query_size (disabledarrowmenuitem_context, NULL, &menuitem2_height);
|
||||
*height += menuitem2_height;
|
||||
menuitem3_height = 0;
|
||||
query_size (menu_context, NULL, &menuitem5_height);
|
||||
query_size (menuitem_context, NULL, &menuitem3_height);
|
||||
query_size (checkmenuitem_context, NULL, &menuitem3_height);
|
||||
query_size (disabledcheckmenuitem_context, NULL, &menuitem3_height);
|
||||
*height += menuitem3_height;
|
||||
menuitem4_height = 0;
|
||||
query_size (menu_context, NULL, &menuitem5_height);
|
||||
query_size (separatormenuitem_context, NULL, &menuitem4_height);
|
||||
*height += menuitem4_height;
|
||||
menuitem5_height = 0;
|
||||
query_size (menu_context, NULL, &menuitem5_height);
|
||||
query_size (menuitem_context, NULL, &menuitem5_height);
|
||||
query_size (radiomenuitem_context, NULL, &menuitem5_height);
|
||||
query_size (disabledradiomenuitem_context, NULL, &menuitem5_height);
|
||||
*height += menuitem5_height;
|
||||
|
||||
draw_style_common (menu_context, cr, x, y, width, *height,
|
||||
&menu_x, &menu_y, &menu_width, &menu_height);
|
||||
|
||||
/* Hovered with right arrow */
|
||||
gtk_style_context_get (hoveredarrowmenuitem_context,
|
||||
"min-width", &arrow_width, "min-height", &arrow_height, NULL);
|
||||
arrow_size = MIN (arrow_width, arrow_height);
|
||||
draw_style_common (hovermenuitem_context, cr, menu_x, menu_y, menu_width, menuitem1_height,
|
||||
&contents_x, &contents_y, &contents_width, &contents_height);
|
||||
gtk_render_arrow (hoveredarrowmenuitem_context, cr, G_PI / 2,
|
||||
contents_x + contents_width - arrow_size,
|
||||
contents_y + (contents_height - arrow_size) / 2, arrow_size);
|
||||
|
||||
/* Left arrow sensitive, and right arrow insensitive */
|
||||
draw_style_common (menuitem_context, cr, menu_x, menu_y + menuitem1_height, menu_width, menuitem2_height,
|
||||
&contents_x, &contents_y, &contents_width, &contents_height);
|
||||
gtk_style_context_get (arrowmenuitem_context,
|
||||
"min-width", &arrow_width, "min-height", &arrow_height, NULL);
|
||||
arrow_size = MIN (arrow_width, arrow_height);
|
||||
gtk_render_arrow (arrowmenuitem_context, cr, G_PI / 2,
|
||||
contents_x,
|
||||
contents_y + (contents_height - arrow_size) / 2, arrow_size);
|
||||
gtk_style_context_get (disabledarrowmenuitem_context,
|
||||
"min-width", &arrow_width, "min-height", &arrow_height, NULL);
|
||||
arrow_size = MIN (arrow_width, arrow_height);
|
||||
gtk_render_arrow (disabledarrowmenuitem_context, cr, G_PI / 2,
|
||||
contents_x + contents_width - arrow_size,
|
||||
contents_y + (contents_height - arrow_size) / 2, arrow_size);
|
||||
|
||||
|
||||
/* Left check enabled, sensitive, and right check unchecked, insensitive */
|
||||
draw_style_common (menuitem_context, cr, menu_x, menu_y + menuitem1_height + menuitem2_height, menu_width, menuitem3_height,
|
||||
&contents_x, &contents_y, &contents_width, &contents_height);
|
||||
gtk_style_context_get (checkmenuitem_context,
|
||||
"min-width", &toggle_width, "min-height", &toggle_height, NULL);
|
||||
draw_style_common (checkmenuitem_context, cr,
|
||||
contents_x,
|
||||
contents_y,
|
||||
toggle_width, toggle_height,
|
||||
&toggle_x, &toggle_y, &toggle_width, &toggle_height);
|
||||
gtk_render_check (checkmenuitem_context, cr, toggle_x, toggle_y, toggle_width, toggle_height);
|
||||
gtk_style_context_get (disabledcheckmenuitem_context,
|
||||
"min-width", &toggle_width, "min-height", &toggle_height, NULL);
|
||||
draw_style_common (disabledcheckmenuitem_context, cr,
|
||||
contents_x + contents_width - toggle_width,
|
||||
contents_y,
|
||||
toggle_width, toggle_height,
|
||||
&toggle_x, &toggle_y, &toggle_width, &toggle_height);
|
||||
gtk_render_check (disabledcheckmenuitem_context, cr, toggle_x, toggle_y, toggle_width, toggle_height);
|
||||
|
||||
/* Separator */
|
||||
draw_style_common (separatormenuitem_context, cr, menu_x, menu_y + menuitem1_height + menuitem2_height + menuitem3_height,
|
||||
menu_width, menuitem4_height,
|
||||
NULL, NULL, NULL, NULL);
|
||||
|
||||
/* Left check enabled, sensitive, and right check unchecked, insensitive */
|
||||
draw_style_common (menuitem_context, cr, menu_x, menu_y + menuitem1_height + menuitem2_height + menuitem3_height + menuitem4_height,
|
||||
menu_width, menuitem5_height,
|
||||
&contents_x, &contents_y, &contents_width, &contents_height);
|
||||
gtk_style_context_get (radiomenuitem_context,
|
||||
"min-width", &toggle_width, "min-height", &toggle_height, NULL);
|
||||
draw_style_common (radiomenuitem_context, cr,
|
||||
contents_x,
|
||||
contents_y,
|
||||
toggle_width, toggle_height,
|
||||
&toggle_x, &toggle_y, &toggle_width, &toggle_height);
|
||||
gtk_render_check (radiomenuitem_context, cr, toggle_x, toggle_y, toggle_width, toggle_height);
|
||||
gtk_style_context_get (disabledradiomenuitem_context,
|
||||
"min-width", &toggle_width, "min-height", &toggle_height, NULL);
|
||||
draw_style_common (disabledradiomenuitem_context, cr,
|
||||
contents_x + contents_width - toggle_width,
|
||||
contents_y,
|
||||
toggle_width, toggle_height,
|
||||
&toggle_x, &toggle_y, &toggle_width, &toggle_height);
|
||||
gtk_render_check (disabledradiomenuitem_context, cr, toggle_x, toggle_y, toggle_width, toggle_height);
|
||||
|
||||
g_object_unref (menu_context);
|
||||
g_object_unref (menuitem_context);
|
||||
g_object_unref (hovermenuitem_context);
|
||||
g_object_unref (hoveredarrowmenuitem_context);
|
||||
g_object_unref (arrowmenuitem_context);
|
||||
g_object_unref (checkmenuitem_context);
|
||||
g_object_unref (disabledarrowmenuitem_context);
|
||||
g_object_unref (disabledcheckmenuitem_context);
|
||||
g_object_unref (radiomenuitem_context);
|
||||
g_object_unref (disablemenuitem_context);
|
||||
g_object_unref (disabledradiomenuitem_context);
|
||||
g_object_unref (separatormenuitem_context);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_menubar (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint *height)
|
||||
{
|
||||
GtkStyleContext *frame_context;
|
||||
GtkStyleContext *border_context;
|
||||
GtkStyleContext *menubar_context;
|
||||
GtkStyleContext *hovered_menuitem_context;
|
||||
GtkStyleContext *menuitem_context;
|
||||
gint contents_x, contents_y, contents_width, contents_height;
|
||||
gint item_width;
|
||||
|
||||
/* Menubar background is the same color as our base background, so use a frame */
|
||||
frame_context = get_style (NULL, "frame");
|
||||
border_context = get_style (frame_context, "border");
|
||||
|
||||
/* This information is taken from the GtkMenuBar docs, see "CSS nodes" */
|
||||
menubar_context = get_style (NULL, "menubar");
|
||||
hovered_menuitem_context = get_style (menubar_context, "menuitem:hover");
|
||||
menuitem_context = get_style (menubar_context, "menuitem");
|
||||
|
||||
*height = 0;
|
||||
query_size (frame_context, NULL, height);
|
||||
query_size (border_context, NULL, height);
|
||||
query_size (menubar_context, NULL, height);
|
||||
query_size (hovered_menuitem_context, NULL, height);
|
||||
query_size (menuitem_context, NULL, height);
|
||||
|
||||
draw_style_common (frame_context, cr, x, y, width, *height,
|
||||
NULL, NULL, NULL, NULL);
|
||||
draw_style_common (border_context, cr, x, y, width, *height,
|
||||
&contents_x, &contents_y, &contents_width, &contents_height);
|
||||
draw_style_common (menubar_context, cr, contents_x, contents_y, contents_width, contents_height,
|
||||
NULL, NULL, NULL, NULL);
|
||||
item_width = contents_width / 3;
|
||||
draw_style_common (hovered_menuitem_context, cr, contents_x, contents_y, item_width, contents_height,
|
||||
NULL, NULL, NULL, NULL);
|
||||
draw_style_common (menuitem_context, cr, contents_x + item_width * 2, contents_y, item_width, contents_height,
|
||||
NULL, NULL, NULL, NULL);
|
||||
|
||||
g_object_unref (menuitem_context);
|
||||
g_object_unref (hovered_menuitem_context);
|
||||
g_object_unref (menubar_context);
|
||||
g_object_unref (border_context);
|
||||
g_object_unref (frame_context);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_notebook (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
GtkStyleContext *notebook_context;
|
||||
GtkStyleContext *header_context;
|
||||
GtkStyleContext *tabs_context;
|
||||
GtkStyleContext *tab1_context, *tab2_context;
|
||||
GtkStyleContext *stack_context;
|
||||
gint header_height;
|
||||
gint contents_x, contents_y, contents_width, contents_height;
|
||||
|
||||
/* This information is taken from the GtkNotebook docs, see "CSS nodes" */
|
||||
notebook_context = get_style (NULL, "notebook.frame");
|
||||
header_context = get_style (notebook_context, "header.top");
|
||||
tabs_context = get_style (header_context, "tabs");
|
||||
tab1_context = get_style (tabs_context, "tab:checked");
|
||||
tab2_context = get_style (tabs_context, "tab:hover");
|
||||
stack_context = get_style (notebook_context, "stack");
|
||||
|
||||
header_height = 0;
|
||||
query_size (notebook_context, NULL, &header_height);
|
||||
query_size (header_context, NULL, &header_height);
|
||||
query_size (tabs_context, NULL, &header_height);
|
||||
query_size (tab1_context, NULL, &header_height);
|
||||
query_size (tab2_context, NULL, &header_height);
|
||||
|
||||
draw_style_common (notebook_context, cr, x, y, width, height, NULL, NULL, NULL, NULL);
|
||||
draw_style_common (header_context, cr, x, y, width, header_height, NULL, NULL, NULL, NULL);
|
||||
draw_style_common (tabs_context, cr, x, y, width, header_height, NULL, NULL, NULL, NULL);
|
||||
draw_style_common (tab1_context, cr, x, y, width / 2, header_height,
|
||||
&contents_x, &contents_y, &contents_width, &contents_height);
|
||||
draw_style_common (tab2_context, cr, x + width / 2, y, width / 2, header_height,
|
||||
NULL, NULL, NULL, NULL);
|
||||
draw_style_common (stack_context, cr, x, y + header_height, width,height - header_height,
|
||||
NULL, NULL, NULL, NULL);
|
||||
|
||||
g_object_unref (stack_context);
|
||||
g_object_unref (tabs_context);
|
||||
g_object_unref (tab1_context);
|
||||
g_object_unref (tab2_context);
|
||||
g_object_unref (header_context);
|
||||
g_object_unref (notebook_context);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_horizontal_scrollbar (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint position,
|
||||
GtkStateFlags state,
|
||||
gint *height)
|
||||
{
|
||||
GtkStyleContext *scrollbar_context;
|
||||
GtkStyleContext *contents_context;
|
||||
GtkStyleContext *trough_context;
|
||||
GtkStyleContext *slider_context;
|
||||
gint slider_width;
|
||||
|
||||
/* This information is taken from the GtkScrollbar docs, see "CSS nodes" */
|
||||
scrollbar_context = get_style (NULL, "scrollbar.horizontal.bottom");
|
||||
contents_context = get_style (scrollbar_context, "contents");
|
||||
trough_context = get_style (contents_context, "trough");
|
||||
slider_context = get_style (trough_context, "slider");
|
||||
|
||||
gtk_style_context_set_state (scrollbar_context, state);
|
||||
gtk_style_context_set_state (contents_context, state);
|
||||
gtk_style_context_set_state (trough_context, state);
|
||||
gtk_style_context_set_state (slider_context, state);
|
||||
|
||||
*height = 0;
|
||||
query_size (scrollbar_context, NULL, height);
|
||||
query_size (contents_context, NULL, height);
|
||||
query_size (trough_context, NULL, height);
|
||||
query_size (slider_context, NULL, height);
|
||||
|
||||
gtk_style_context_get (slider_context,
|
||||
"min-width", &slider_width, NULL);
|
||||
|
||||
draw_style_common (scrollbar_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
|
||||
draw_style_common (contents_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
|
||||
draw_style_common (trough_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
|
||||
draw_style_common (slider_context, cr, x + position, y, slider_width, *height, NULL, NULL, NULL, NULL);
|
||||
|
||||
g_object_unref (slider_context);
|
||||
g_object_unref (trough_context);
|
||||
g_object_unref (contents_context);
|
||||
g_object_unref (scrollbar_context);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_text (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height,
|
||||
const gchar *text,
|
||||
GtkStateFlags state)
|
||||
{
|
||||
GtkStyleContext *label_context;
|
||||
GtkStyleContext *selection_context;
|
||||
GtkStyleContext *context;
|
||||
PangoLayout *layout;
|
||||
|
||||
/* This information is taken from the GtkLabel docs, see "CSS nodes" */
|
||||
label_context = get_style (NULL, "label.view");
|
||||
selection_context = get_style (label_context, "selection");
|
||||
|
||||
gtk_style_context_set_state (label_context, state);
|
||||
|
||||
if (state & GTK_STATE_FLAG_SELECTED)
|
||||
context = selection_context;
|
||||
else
|
||||
context = label_context;
|
||||
|
||||
layout = gtk_widget_create_pango_layout (widget, text);
|
||||
|
||||
gtk_render_background (context, cr, x, y, width, height);
|
||||
gtk_render_frame (context, cr, x, y, width, height);
|
||||
gtk_render_layout (context, cr, x, y, layout);
|
||||
|
||||
g_object_unref (layout);
|
||||
|
||||
g_object_unref (selection_context);
|
||||
g_object_unref (label_context);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_check (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
gint x,
|
||||
gint y,
|
||||
GtkStateFlags state,
|
||||
gint *width,
|
||||
gint *height)
|
||||
{
|
||||
GtkStyleContext *button_context;
|
||||
GtkStyleContext *check_context;
|
||||
gint contents_x, contents_y, contents_width, contents_height;
|
||||
|
||||
/* This information is taken from the GtkCheckButton docs, see "CSS nodes" */
|
||||
button_context = get_style (NULL, "checkbutton");
|
||||
check_context = get_style (button_context, "check");
|
||||
|
||||
gtk_style_context_set_state (check_context, state);
|
||||
|
||||
*width = *height = 0;
|
||||
query_size (button_context, width, height);
|
||||
query_size (check_context, width, height);
|
||||
|
||||
draw_style_common (button_context, cr, x, y, *width, *height, NULL, NULL, NULL, NULL);
|
||||
draw_style_common (check_context, cr, x, y, *width, *height,
|
||||
&contents_x, &contents_y, &contents_width, &contents_height);
|
||||
gtk_render_check (check_context, cr, contents_x, contents_y, contents_width, contents_height);
|
||||
|
||||
g_object_unref (check_context);
|
||||
g_object_unref (button_context);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
draw_radio (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
gint x,
|
||||
gint y,
|
||||
GtkStateFlags state,
|
||||
gint *width,
|
||||
gint *height)
|
||||
{
|
||||
GtkStyleContext *button_context;
|
||||
GtkStyleContext *check_context;
|
||||
gint contents_x, contents_y, contents_width, contents_height;
|
||||
|
||||
/* This information is taken from the GtkRadioButton docs, see "CSS nodes" */
|
||||
button_context = get_style (NULL, "radiobutton");
|
||||
check_context = get_style (button_context, "radio");
|
||||
|
||||
gtk_style_context_set_state (check_context, state);
|
||||
|
||||
*width = *height = 0;
|
||||
query_size (button_context, width, height);
|
||||
query_size (check_context, width, height);
|
||||
|
||||
draw_style_common (button_context, cr, x, y, *width, *height, NULL, NULL, NULL, NULL);
|
||||
draw_style_common (check_context, cr, x, y, *width, *height,
|
||||
&contents_x, &contents_y, &contents_width, &contents_height);
|
||||
gtk_render_check (check_context, cr, contents_x, contents_y, contents_width, contents_height);
|
||||
|
||||
g_object_unref (check_context);
|
||||
g_object_unref (button_context);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
draw_progress (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint position,
|
||||
gint *height)
|
||||
{
|
||||
GtkStyleContext *bar_context;
|
||||
GtkStyleContext *trough_context;
|
||||
GtkStyleContext *progress_context;
|
||||
|
||||
/* This information is taken from the GtkProgressBar docs, see "CSS nodes" */
|
||||
bar_context = get_style (NULL, "progressbar.horizontal");
|
||||
trough_context = get_style (bar_context, "trough");
|
||||
progress_context = get_style (trough_context, "progress.left");
|
||||
|
||||
*height = 0;
|
||||
query_size (bar_context, NULL, height);
|
||||
query_size (trough_context, NULL, height);
|
||||
query_size (progress_context, NULL, height);
|
||||
|
||||
draw_style_common (bar_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
|
||||
draw_style_common (trough_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
|
||||
draw_style_common (progress_context, cr, x, y, position, *height, NULL, NULL, NULL, NULL);
|
||||
|
||||
g_object_unref (progress_context);
|
||||
g_object_unref (trough_context);
|
||||
g_object_unref (bar_context);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_scale (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint position,
|
||||
gint *height)
|
||||
{
|
||||
GtkStyleContext *scale_context;
|
||||
GtkStyleContext *contents_context;
|
||||
GtkStyleContext *trough_context;
|
||||
GtkStyleContext *slider_context;
|
||||
GtkStyleContext *highlight_context;
|
||||
gint contents_x, contents_y, contents_width, contents_height;
|
||||
gint trough_height, slider_height;
|
||||
|
||||
scale_context = get_style (NULL, "scale.horizontal");
|
||||
contents_context = get_style (scale_context, "contents");
|
||||
trough_context = get_style (contents_context, "trough");
|
||||
slider_context = get_style (trough_context, "slider");
|
||||
highlight_context = get_style (trough_context, "highlight.top");
|
||||
|
||||
*height = 0;
|
||||
query_size (scale_context, NULL, height);
|
||||
query_size (contents_context, NULL, height);
|
||||
query_size (trough_context, NULL, height);
|
||||
query_size (slider_context, NULL, height);
|
||||
query_size (highlight_context, NULL, height);
|
||||
|
||||
draw_style_common (scale_context, cr, x, y, width, *height,
|
||||
&contents_x, &contents_y, &contents_width, &contents_height);
|
||||
draw_style_common (contents_context, cr, contents_x, contents_y, contents_width, contents_height,
|
||||
&contents_x, &contents_y, &contents_width, &contents_height);
|
||||
/* Scale trough defines its size querying slider and highlight */
|
||||
trough_height = 0;
|
||||
query_size (trough_context, NULL, &trough_height);
|
||||
slider_height = 0;
|
||||
query_size (slider_context, NULL, &slider_height);
|
||||
query_size (highlight_context, NULL, &slider_height);
|
||||
trough_height += slider_height;
|
||||
draw_style_common (trough_context, cr, contents_x, contents_y, contents_width, trough_height,
|
||||
&contents_x, &contents_y, &contents_width, &contents_height);
|
||||
draw_style_common (highlight_context, cr, contents_x, contents_y,
|
||||
contents_width / 2, contents_height,
|
||||
NULL, NULL, NULL, NULL);
|
||||
draw_style_common (slider_context, cr, contents_x + position, contents_y, contents_height, contents_height,
|
||||
NULL, NULL, NULL, NULL);
|
||||
|
||||
g_object_unref (scale_context);
|
||||
g_object_unref (contents_context);
|
||||
g_object_unref (trough_context);
|
||||
g_object_unref (slider_context);
|
||||
g_object_unref (highlight_context);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_combobox (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gboolean has_entry,
|
||||
gint *height)
|
||||
{
|
||||
GtkStyleContext *combo_context;
|
||||
GtkStyleContext *box_context;
|
||||
GtkStyleContext *button_context;
|
||||
GtkStyleContext *button_box_context;
|
||||
GtkStyleContext *entry_context;
|
||||
GtkStyleContext *arrow_context;
|
||||
gint contents_x, contents_y, contents_width, contents_height;
|
||||
gint button_width;
|
||||
gint arrow_width, arrow_height, arrow_size;
|
||||
|
||||
/* This information is taken from the GtkComboBox docs, see "CSS nodes" */
|
||||
combo_context = get_style (NULL, "combobox:focus");
|
||||
box_context = get_style (combo_context, "box.horizontal.linked");
|
||||
if (has_entry)
|
||||
{
|
||||
const char *siblings[3] = { "entry.combo:focus", "button.combo" , NULL };
|
||||
|
||||
entry_context = get_style_with_siblings (box_context, "entry.combo:focus", siblings, 0);
|
||||
button_context = get_style_with_siblings (box_context, "button.combo", siblings, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *siblings[2] = { "button.combo" , NULL };
|
||||
|
||||
button_context = get_style_with_siblings (box_context, "button.combo", siblings, 0);
|
||||
}
|
||||
button_box_context = get_style (button_context, "box.horizontal");
|
||||
arrow_context = get_style (button_box_context, "arrow");
|
||||
|
||||
*height = 0;
|
||||
query_size (combo_context, NULL, height);
|
||||
query_size (box_context, NULL, height);
|
||||
if (has_entry)
|
||||
query_size (entry_context, NULL, height);
|
||||
query_size (button_context, NULL, height);
|
||||
query_size (button_box_context, NULL, height);
|
||||
query_size (arrow_context, NULL, height);
|
||||
|
||||
gtk_style_context_get (arrow_context,
|
||||
"min-width", &arrow_width, "min-height", &arrow_height, NULL);
|
||||
arrow_size = MIN (arrow_width, arrow_height);
|
||||
|
||||
draw_style_common (combo_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
|
||||
draw_style_common (box_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
|
||||
if (has_entry)
|
||||
{
|
||||
button_width = *height;
|
||||
draw_style_common (entry_context, cr, x, y, width - button_width, *height, NULL, NULL, NULL, NULL);
|
||||
draw_style_common (button_context, cr, x + width - button_width, y, button_width, *height,
|
||||
&contents_x, &contents_y, &contents_width, &contents_height);
|
||||
}
|
||||
else
|
||||
{
|
||||
button_width = width;
|
||||
draw_style_common (button_context, cr, x, y, width, *height,
|
||||
&contents_x, &contents_y, &contents_width, &contents_height);
|
||||
}
|
||||
|
||||
draw_style_common (button_box_context, cr, contents_x, contents_y, contents_width, contents_height,
|
||||
NULL, NULL, NULL, NULL);
|
||||
draw_style_common (arrow_context, cr, contents_x, contents_y, contents_width, contents_height,
|
||||
NULL, NULL, NULL, NULL);
|
||||
gtk_render_arrow (arrow_context, cr, G_PI / 2,
|
||||
contents_x + contents_width - arrow_size,
|
||||
contents_y + (contents_height - arrow_size) / 2, arrow_size);
|
||||
|
||||
g_object_unref (arrow_context);
|
||||
if (has_entry)
|
||||
g_object_unref (entry_context);
|
||||
g_object_unref (button_context);
|
||||
g_object_unref (combo_context);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_spinbutton (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint *height)
|
||||
{
|
||||
GtkStyleContext *spin_context;
|
||||
GtkStyleContext *entry_context;
|
||||
GtkStyleContext *up_context;
|
||||
GtkStyleContext *down_context;
|
||||
GtkIconTheme *icon_theme;
|
||||
GtkIconInfo *icon_info;
|
||||
GdkTexture *texture;
|
||||
gint icon_width, icon_height, icon_size;
|
||||
gint button_width;
|
||||
gint contents_x, contents_y, contents_width, contents_height;
|
||||
|
||||
/* This information is taken from the GtkSpinButton docs, see "CSS nodes" */
|
||||
spin_context = get_style (NULL, "spinbutton.horizontal:focus");
|
||||
entry_context = get_style (spin_context, "entry:focus");
|
||||
up_context = get_style (spin_context, "button.up:focus:active");
|
||||
down_context = get_style (spin_context, "button.down:focus");
|
||||
|
||||
*height = 0;
|
||||
query_size (spin_context, NULL, height);
|
||||
query_size (entry_context, NULL, height);
|
||||
query_size (up_context, NULL, height);
|
||||
query_size (down_context, NULL, height);
|
||||
button_width = *height;
|
||||
|
||||
draw_style_common (spin_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
|
||||
draw_style_common (entry_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
|
||||
|
||||
icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (widget));
|
||||
|
||||
gtk_style_context_get (up_context,
|
||||
"min-width", &icon_width, "min-height", &icon_height, NULL);
|
||||
icon_size = MIN (icon_width, icon_height);
|
||||
icon_info = gtk_icon_theme_lookup_icon (icon_theme, "list-add-symbolic", icon_size, 0);
|
||||
texture = GDK_TEXTURE (gtk_icon_info_load_symbolic_for_context (icon_info, up_context, NULL, NULL));
|
||||
g_object_unref (icon_info);
|
||||
draw_style_common (up_context, cr, x + width - button_width, y, button_width, *height,
|
||||
&contents_x, &contents_y, &contents_width, &contents_height);
|
||||
gtk_render_icon (up_context, cr, texture, contents_x, contents_y + (contents_height - icon_size) / 2);
|
||||
g_object_unref (texture);
|
||||
|
||||
gtk_style_context_get (down_context,
|
||||
"min-width", &icon_width, "min-height", &icon_height, NULL);
|
||||
icon_size = MIN (icon_width, icon_height);
|
||||
icon_info = gtk_icon_theme_lookup_icon (icon_theme, "list-remove-symbolic", icon_size, 0);
|
||||
texture = GDK_TEXTURE (gtk_icon_info_load_symbolic_for_context (icon_info, down_context, NULL, NULL));
|
||||
g_object_unref (icon_info);
|
||||
draw_style_common (down_context, cr, x + width - 2 * button_width, y, button_width, *height,
|
||||
&contents_x, &contents_y, &contents_width, &contents_height);
|
||||
gtk_render_icon (down_context, cr, texture, contents_x, contents_y + (contents_height - icon_size) / 2);
|
||||
g_object_unref (texture);
|
||||
|
||||
g_object_unref (down_context);
|
||||
g_object_unref (up_context);
|
||||
g_object_unref (entry_context);
|
||||
g_object_unref (spin_context);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_func (GtkDrawingArea *da,
|
||||
cairo_t *cr,
|
||||
int width,
|
||||
int height,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (da);
|
||||
gint panewidth;
|
||||
gint x, y;
|
||||
|
||||
panewidth = width / 2;
|
||||
|
||||
cairo_rectangle (cr, 0, 0, width, height);
|
||||
cairo_set_source_rgb (cr, 0.9, 0.9, 0.9);
|
||||
cairo_fill (cr);
|
||||
|
||||
x = y = 10;
|
||||
draw_horizontal_scrollbar (widget, cr, x, y, panewidth - 20, 30, GTK_STATE_FLAG_NORMAL, &height);
|
||||
y += height + 8;
|
||||
draw_horizontal_scrollbar (widget, cr, x, y, panewidth - 20, 40, GTK_STATE_FLAG_PRELIGHT, &height);
|
||||
y += height + 8;
|
||||
draw_horizontal_scrollbar (widget, cr, x, y, panewidth - 20, 50, GTK_STATE_FLAG_ACTIVE|GTK_STATE_FLAG_PRELIGHT, &height);
|
||||
|
||||
y += height + 8;
|
||||
draw_text (widget, cr, x, y, panewidth - 20, 20, "Not selected", GTK_STATE_FLAG_NORMAL);
|
||||
y += 20 + 10;
|
||||
draw_text (widget, cr, x, y, panewidth - 20, 20, "Selected", GTK_STATE_FLAG_SELECTED);
|
||||
|
||||
x = 10;
|
||||
y += 20 + 10;
|
||||
draw_check (widget, cr, x, y, GTK_STATE_FLAG_NORMAL, &width, &height);
|
||||
x += width + 10;
|
||||
draw_check (widget, cr, x, y, GTK_STATE_FLAG_CHECKED, &width, &height);
|
||||
x += width + 10;
|
||||
draw_radio (widget, cr, x, y, GTK_STATE_FLAG_NORMAL, &width, &height);
|
||||
x += width + 10;
|
||||
draw_radio (widget, cr, x, y, GTK_STATE_FLAG_CHECKED, &width, &height);
|
||||
x = 10;
|
||||
|
||||
y += height + 10;
|
||||
draw_progress (widget, cr, x, y, panewidth - 20, 50, &height);
|
||||
|
||||
y += height + 10;
|
||||
draw_scale (widget, cr, x, y, panewidth - 20, 75, &height);
|
||||
|
||||
y += height + 20;
|
||||
draw_notebook (widget, cr, x, y, panewidth - 20, 160);
|
||||
|
||||
/* Second column */
|
||||
x += panewidth;
|
||||
y = 10;
|
||||
draw_menu (widget, cr, x, y, panewidth - 20, &height);
|
||||
|
||||
y += height + 10;
|
||||
draw_menubar (widget, cr, x, y, panewidth - 20, &height);
|
||||
|
||||
y += height + 20;
|
||||
draw_spinbutton (widget, cr, x, y, panewidth - 20, &height);
|
||||
|
||||
y += height + 30;
|
||||
draw_combobox (widget, cr, x, y, panewidth - 20, FALSE, &height);
|
||||
|
||||
y += height + 10;
|
||||
draw_combobox (widget, cr, 10 + panewidth, y, panewidth - 20, TRUE, &height);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_foreigndrawing (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *box;
|
||||
GtkWidget *da;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Foreign drawing");
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
|
||||
gtk_container_add (GTK_CONTAINER (window), box);
|
||||
da = gtk_drawing_area_new ();
|
||||
gtk_drawing_area_set_content_width (GTK_DRAWING_AREA (da), 400);
|
||||
gtk_drawing_area_set_content_height (GTK_DRAWING_AREA (da), 400);
|
||||
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (da), draw_func, NULL, NULL);
|
||||
gtk_widget_set_hexpand (da, TRUE);
|
||||
gtk_widget_set_vexpand (da, TRUE);
|
||||
gtk_container_add (GTK_CONTAINER (box), da);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
@@ -13,17 +13,16 @@ in_files = sys.argv[2:]
|
||||
file_output = """
|
||||
typedef GtkWidget *(*GDoDemoFunc) (GtkWidget *do_widget);
|
||||
|
||||
typedef struct _Demo Demo;
|
||||
typedef struct _DemoData DemoData;
|
||||
|
||||
struct _Demo
|
||||
struct _DemoData
|
||||
{
|
||||
const char *name;
|
||||
const char *title;
|
||||
const char *filename;
|
||||
char *name;
|
||||
char *title;
|
||||
char *filename;
|
||||
GDoDemoFunc func;
|
||||
Demo *children;
|
||||
DemoData *children;
|
||||
};
|
||||
|
||||
"""
|
||||
|
||||
# Demo = namedtuple('Demo', ['name', 'title', 'file', 'func'])
|
||||
@@ -67,7 +66,7 @@ for demo in demos:
|
||||
i = 0
|
||||
for parent in parents:
|
||||
id = parent_ids[i]
|
||||
file_output += "\nDemo child" + str(id) + "[] = {\n"
|
||||
file_output += "\nDemoData child" + str(id) + "[] = {\n"
|
||||
# iterate over all demos and check if the name starts with the given parent name
|
||||
for child in demos:
|
||||
if child[1].startswith(parent + "/"):
|
||||
@@ -82,7 +81,7 @@ for parent in parents:
|
||||
# Sort demos by title
|
||||
demos = sorted(demos, key=lambda x: x[1])
|
||||
|
||||
file_output += "\nDemo gtk_demos[] = {\n"
|
||||
file_output += "\nDemoData gtk_demos[] = {\n"
|
||||
for demo in demos:
|
||||
# Do not generate one of these for demos with a parent demo
|
||||
if "/" not in demo[1]:
|
||||
|
@@ -94,12 +94,9 @@ drawing_area_draw (GtkDrawingArea *area,
|
||||
cairo_pattern_t *pat;
|
||||
cairo_matrix_t matrix;
|
||||
gdouble angle, scale;
|
||||
gdouble x_center, y_center;
|
||||
|
||||
gtk_gesture_get_bounding_box_center (GTK_GESTURE (zoom), &x_center, &y_center);
|
||||
|
||||
cairo_get_matrix (cr, &matrix);
|
||||
cairo_matrix_translate (&matrix, x_center, y_center);
|
||||
cairo_matrix_translate (&matrix, width / 2, height / 2);
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
@@ -146,7 +143,7 @@ do_gestures (GtkWidget *do_widget)
|
||||
|
||||
if (!window)
|
||||
{
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 400, 400);
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Gestures");
|
||||
g_signal_connect (window, "destroy",
|
||||
|
@@ -383,23 +383,20 @@ close_window (GtkWidget *widget)
|
||||
rotation_angles[Z_AXIS] = 0.0;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
GtkWidget *
|
||||
create_glarea_window (GtkWidget *do_widget)
|
||||
{
|
||||
GtkWidget *window, *box, *button, *controls;
|
||||
int i;
|
||||
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "OpenGL Area");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 400, 600);
|
||||
g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE);
|
||||
gtk_widget_set_margin_start (box, 12);
|
||||
gtk_widget_set_margin_end (box, 12);
|
||||
gtk_widget_set_margin_top (box, 12);
|
||||
gtk_widget_set_margin_bottom (box, 12);
|
||||
g_object_set (box, "margin", 12, NULL);
|
||||
gtk_box_set_spacing (GTK_BOX (box), 6);
|
||||
gtk_container_add (GTK_CONTAINER (window), box);
|
||||
|
||||
|
@@ -53,7 +53,6 @@ enum {
|
||||
PROP_BENCHMARK,
|
||||
PROP_COUNT,
|
||||
PROP_FRAMERATE,
|
||||
PROP_FRAMERATE_STRING,
|
||||
PROP_UPDATE_DELAY,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
@@ -289,14 +288,6 @@ gtk_fishbowl_get_property (GObject *object,
|
||||
g_value_set_double (value, gtk_fishbowl_get_framerate (fishbowl));
|
||||
break;
|
||||
|
||||
case PROP_FRAMERATE_STRING:
|
||||
{
|
||||
char *s = g_strdup_printf ("%.2f", gtk_fishbowl_get_framerate (fishbowl));
|
||||
g_value_set_string (value, s);
|
||||
g_free (s);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_UPDATE_DELAY:
|
||||
g_value_set_int64 (value, gtk_fishbowl_get_update_delay (fishbowl));
|
||||
break;
|
||||
@@ -350,13 +341,6 @@ gtk_fishbowl_class_init (GtkFishbowlClass *klass)
|
||||
0,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
props[PROP_FRAMERATE_STRING] =
|
||||
g_param_spec_string ("framerate-string",
|
||||
"Framerate as string",
|
||||
"Framerate as string, with 2 decimals",
|
||||
NULL,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
props[PROP_UPDATE_DELAY] =
|
||||
g_param_spec_int64 ("update-delay",
|
||||
"Update delay",
|
||||
@@ -508,7 +492,6 @@ gtk_fishbowl_do_update (GtkFishbowl *fishbowl)
|
||||
priv->framerate = ((int)(priv->framerate * 100))/100.0;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_FRAMERATE]);
|
||||
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_FRAMERATE_STRING]);
|
||||
|
||||
if (!priv->benchmark)
|
||||
return;
|
||||
|
@@ -23,7 +23,7 @@ do_headerbar (GtkWidget *do_widget)
|
||||
|
||||
if (!window)
|
||||
{
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
@@ -17,7 +17,7 @@
|
||||
static void
|
||||
insert_link (GtkTextBuffer *buffer,
|
||||
GtkTextIter *iter,
|
||||
const char *text,
|
||||
gchar *text,
|
||||
gint page)
|
||||
{
|
||||
GtkTextTag *tag;
|
||||
@@ -232,7 +232,7 @@ do_hypertext (GtkWidget *do_widget)
|
||||
GtkTextBuffer *buffer;
|
||||
GtkEventController *controller;
|
||||
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Hypertext");
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
|
@@ -52,10 +52,7 @@ populate_icons (void)
|
||||
|
||||
grid = gtk_grid_new ();
|
||||
gtk_widget_set_halign (grid, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_margin_start (grid, 10);
|
||||
gtk_widget_set_margin_end (grid, 10);
|
||||
gtk_widget_set_margin_top (grid, 10);
|
||||
gtk_widget_set_margin_bottom (grid, 10);
|
||||
g_object_set (grid, "margin", 10, NULL);
|
||||
gtk_grid_set_row_spacing (GTK_GRID (grid), 10);
|
||||
gtk_grid_set_column_spacing (GTK_GRID (grid), 10);
|
||||
|
||||
|
@@ -31,12 +31,9 @@
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="scrolledwindow">
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="hadjustment">
|
||||
<object class="GtkAdjustment" id="hadjustment"/>
|
||||
</property>
|
||||
<property name="vadjustment">
|
||||
<object class="GtkAdjustment" id="vadjustment"/>
|
||||
</property>
|
||||
<property name="vscrollbar-policy">automatic</property>
|
||||
<property name="hadjustment"><object class="GtkAdjustment" id="hadjustment"/></property>
|
||||
<property name="vadjustment"><object class="GtkAdjustment" id="vadjustment"/></property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
@@ -26,7 +26,7 @@ enum
|
||||
|
||||
static GdkPixbuf *file_pixbuf, *folder_pixbuf;
|
||||
gchar *parent;
|
||||
GtkWidget *up_button;
|
||||
GtkToolItem *up_button;
|
||||
|
||||
/* Loads the images for the demo and returns whether the operation succeeded */
|
||||
static void
|
||||
@@ -188,8 +188,8 @@ item_activated (GtkIconView *icon_view,
|
||||
}
|
||||
|
||||
static void
|
||||
up_clicked (GtkButton *item,
|
||||
gpointer user_data)
|
||||
up_clicked (GtkToolItem *item,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkListStore *store;
|
||||
gchar *dir_name;
|
||||
@@ -209,8 +209,8 @@ up_clicked (GtkButton *item,
|
||||
}
|
||||
|
||||
static void
|
||||
home_clicked (GtkButton *item,
|
||||
gpointer user_data)
|
||||
home_clicked (GtkToolItem *item,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkListStore *store;
|
||||
|
||||
@@ -248,9 +248,9 @@ do_iconview (GtkWidget *do_widget)
|
||||
GtkListStore *store;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *tool_bar;
|
||||
GtkWidget *home_button;
|
||||
GtkToolItem *home_button;
|
||||
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 650, 400);
|
||||
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
@@ -265,15 +265,23 @@ do_iconview (GtkWidget *do_widget)
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_container_add (GTK_CONTAINER (window), vbox);
|
||||
|
||||
tool_bar = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
tool_bar = gtk_toolbar_new ();
|
||||
gtk_container_add (GTK_CONTAINER (vbox), tool_bar);
|
||||
|
||||
up_button = gtk_button_new_with_mnemonic ("_Up");
|
||||
up_button = gtk_tool_button_new (NULL, NULL);
|
||||
gtk_tool_button_set_label (GTK_TOOL_BUTTON (up_button), _("_Up"));
|
||||
gtk_tool_button_set_use_underline (GTK_TOOL_BUTTON (up_button), TRUE);
|
||||
gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (up_button), "go-up");
|
||||
gtk_tool_item_set_is_important (up_button, TRUE);
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (up_button), FALSE);
|
||||
gtk_container_add (GTK_CONTAINER (tool_bar), up_button);
|
||||
gtk_toolbar_insert (GTK_TOOLBAR (tool_bar), up_button, -1);
|
||||
|
||||
home_button = gtk_button_new_with_mnemonic ("_Home");
|
||||
gtk_container_add (GTK_CONTAINER (tool_bar), home_button);
|
||||
home_button = gtk_tool_button_new (NULL, NULL);
|
||||
gtk_tool_button_set_label (GTK_TOOL_BUTTON (home_button), _("_Home"));
|
||||
gtk_tool_button_set_use_underline (GTK_TOOL_BUTTON (home_button), TRUE);
|
||||
gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (home_button), "go-home");
|
||||
gtk_tool_item_set_is_important (home_button, TRUE);
|
||||
gtk_toolbar_insert (GTK_TOOLBAR (tool_bar), home_button, -1);
|
||||
|
||||
|
||||
sw = gtk_scrolled_window_new (NULL, NULL);
|
||||
|
@@ -106,7 +106,7 @@ do_iconview_edit (GtkWidget *do_widget)
|
||||
GtkListStore *store;
|
||||
GtkCellRenderer *renderer;
|
||||
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
|
@@ -331,7 +331,7 @@ do_images (GtkWidget *do_widget)
|
||||
|
||||
if (!window)
|
||||
{
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Images");
|
||||
@@ -342,10 +342,7 @@ do_images (GtkWidget *do_widget)
|
||||
G_CALLBACK (cleanup_callback), NULL);
|
||||
|
||||
base_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8);
|
||||
gtk_widget_set_margin_start (base_vbox, 16);
|
||||
gtk_widget_set_margin_end (base_vbox, 16);
|
||||
gtk_widget_set_margin_top (base_vbox, 16);
|
||||
gtk_widget_set_margin_bottom (base_vbox, 16);
|
||||
g_object_set (base_vbox, "margin", 16, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), base_vbox);
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 16);
|
||||
|
@@ -53,7 +53,7 @@ do_infobar (GtkWidget *do_widget)
|
||||
{
|
||||
actions = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Info Bars");
|
||||
@@ -61,10 +61,7 @@ do_infobar (GtkWidget *do_widget)
|
||||
g_signal_connect (window, "destroy", G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_widget_set_margin_start (vbox, 8);
|
||||
gtk_widget_set_margin_end (vbox, 8);
|
||||
gtk_widget_set_margin_top (vbox, 8);
|
||||
gtk_widget_set_margin_bottom (vbox, 8);
|
||||
g_object_set (vbox, "margin", 8, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), vbox);
|
||||
|
||||
bar = gtk_info_bar_new ();
|
||||
@@ -73,7 +70,7 @@ do_infobar (GtkWidget *do_widget)
|
||||
label = gtk_label_new ("This is an info bar with message type GTK_MESSAGE_INFO");
|
||||
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0);
|
||||
gtk_container_add (GTK_CONTAINER (bar), label);
|
||||
gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (bar))), label);
|
||||
|
||||
button = gtk_toggle_button_new_with_label ("Message");
|
||||
g_object_bind_property (bar, "revealed", button, "active", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
|
||||
@@ -85,7 +82,7 @@ do_infobar (GtkWidget *do_widget)
|
||||
label = gtk_label_new ("This is an info bar with message type GTK_MESSAGE_WARNING");
|
||||
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0);
|
||||
gtk_container_add (GTK_CONTAINER (bar), label);
|
||||
gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (bar))), label);
|
||||
|
||||
button = gtk_toggle_button_new_with_label ("Warning");
|
||||
g_object_bind_property (bar, "revealed", button, "active", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
|
||||
@@ -99,8 +96,7 @@ do_infobar (GtkWidget *do_widget)
|
||||
label = gtk_label_new ("This is an info bar with message type GTK_MESSAGE_QUESTION");
|
||||
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0);
|
||||
gtk_container_add (GTK_CONTAINER (bar), label);
|
||||
gtk_info_bar_set_default_response (GTK_INFO_BAR (bar), GTK_RESPONSE_OK);
|
||||
gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (bar))), label);
|
||||
|
||||
button = gtk_toggle_button_new_with_label ("Question");
|
||||
g_object_bind_property (bar, "revealed", button, "active", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
|
||||
@@ -112,7 +108,7 @@ do_infobar (GtkWidget *do_widget)
|
||||
label = gtk_label_new ("This is an info bar with message type GTK_MESSAGE_ERROR");
|
||||
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0);
|
||||
gtk_container_add (GTK_CONTAINER (bar), label);
|
||||
gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (bar))), label);
|
||||
|
||||
button = gtk_toggle_button_new_with_label ("Error");
|
||||
g_object_bind_property (bar, "revealed", button, "active", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
|
||||
@@ -125,7 +121,7 @@ do_infobar (GtkWidget *do_widget)
|
||||
label = gtk_label_new ("This is an info bar with message type GTK_MESSAGE_OTHER");
|
||||
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0);
|
||||
gtk_container_add (GTK_CONTAINER (bar), label);
|
||||
gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (bar))), label);
|
||||
|
||||
button = gtk_toggle_button_new_with_label ("Other");
|
||||
g_object_bind_property (bar, "revealed", button, "active", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
|
||||
@@ -137,10 +133,7 @@ do_infobar (GtkWidget *do_widget)
|
||||
gtk_container_add (GTK_CONTAINER (vbox), frame);
|
||||
|
||||
vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8);
|
||||
gtk_widget_set_margin_start (vbox2, 8);
|
||||
gtk_widget_set_margin_end (vbox2, 8);
|
||||
gtk_widget_set_margin_top (vbox2, 8);
|
||||
gtk_widget_set_margin_bottom (vbox2, 8);
|
||||
g_object_set (vbox2, "margin", 8, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (frame), vbox2);
|
||||
|
||||
/* Standard message dialog */
|
||||
|
@@ -52,7 +52,7 @@ do_links (GtkWidget *do_widget)
|
||||
|
||||
if (!window)
|
||||
{
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Links");
|
||||
|
@@ -16,9 +16,10 @@ typedef struct
|
||||
{
|
||||
const gboolean fixed;
|
||||
const guint number;
|
||||
const char *severity;
|
||||
const char *description;
|
||||
} Bug;
|
||||
const gchar *severity;
|
||||
const gchar *description;
|
||||
}
|
||||
Bug;
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -33,7 +34,7 @@ enum
|
||||
NUM_COLUMNS
|
||||
};
|
||||
|
||||
static Bug bugs[] =
|
||||
static Bug data[] =
|
||||
{
|
||||
{ FALSE, 60482, "Normal", "scrollable notebooks and hidden tabs" },
|
||||
{ FALSE, 60620, "Critical", "gdk_surface_clear_area (gdksurface-win32.c) is not thread-safe" },
|
||||
@@ -97,9 +98,9 @@ create_model (void)
|
||||
G_TYPE_BOOLEAN);
|
||||
|
||||
/* add data to the list store */
|
||||
for (i = 0; i < G_N_ELEMENTS (bugs); i++)
|
||||
for (i = 0; i < G_N_ELEMENTS (data); i++)
|
||||
{
|
||||
const char *icon_name;
|
||||
gchar *icon_name;
|
||||
gboolean sensitive;
|
||||
|
||||
if (i == 1 || i == 3)
|
||||
@@ -112,10 +113,10 @@ create_model (void)
|
||||
sensitive = TRUE;
|
||||
gtk_list_store_append (store, &iter);
|
||||
gtk_list_store_set (store, &iter,
|
||||
COLUMN_FIXED, bugs[i].fixed,
|
||||
COLUMN_NUMBER, bugs[i].number,
|
||||
COLUMN_SEVERITY, bugs[i].severity,
|
||||
COLUMN_DESCRIPTION, bugs[i].description,
|
||||
COLUMN_FIXED, data[i].fixed,
|
||||
COLUMN_NUMBER, data[i].number,
|
||||
COLUMN_SEVERITY, data[i].severity,
|
||||
COLUMN_DESCRIPTION, data[i].description,
|
||||
COLUMN_PULSE, 0,
|
||||
COLUMN_ICON, icon_name,
|
||||
COLUMN_ACTIVE, FALSE,
|
||||
@@ -128,23 +129,23 @@ create_model (void)
|
||||
|
||||
static void
|
||||
fixed_toggled (GtkCellRendererToggle *cell,
|
||||
char *path_str,
|
||||
gchar *path_str,
|
||||
gpointer data)
|
||||
{
|
||||
GtkTreeModel *tree_model = (GtkTreeModel *)data;
|
||||
GtkTreeModel *model = (GtkTreeModel *)data;
|
||||
GtkTreeIter iter;
|
||||
GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
|
||||
gboolean fixed;
|
||||
|
||||
/* get toggled iter */
|
||||
gtk_tree_model_get_iter (tree_model, &iter, path);
|
||||
gtk_tree_model_get (tree_model, &iter, COLUMN_FIXED, &fixed, -1);
|
||||
gtk_tree_model_get_iter (model, &iter, path);
|
||||
gtk_tree_model_get (model, &iter, COLUMN_FIXED, &fixed, -1);
|
||||
|
||||
/* do something with the value */
|
||||
fixed ^= 1;
|
||||
|
||||
/* set new value */
|
||||
gtk_list_store_set (GTK_LIST_STORE (tree_model), &iter, COLUMN_FIXED, fixed, -1);
|
||||
gtk_list_store_set (GTK_LIST_STORE (model), &iter, COLUMN_FIXED, fixed, -1);
|
||||
|
||||
/* clean up */
|
||||
gtk_tree_path_free (path);
|
||||
@@ -155,6 +156,7 @@ add_columns (GtkTreeView *treeview)
|
||||
{
|
||||
GtkCellRenderer *renderer;
|
||||
GtkTreeViewColumn *column;
|
||||
GtkTreeModel *model = gtk_tree_view_get_model (treeview);
|
||||
|
||||
/* column for fixed toggles */
|
||||
renderer = gtk_cell_renderer_toggle_new ();
|
||||
@@ -253,7 +255,7 @@ do_list_store (GtkWidget *do_widget)
|
||||
GtkWidget *treeview;
|
||||
|
||||
/* create window, etc */
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "List Store");
|
||||
@@ -262,10 +264,7 @@ do_list_store (GtkWidget *do_widget)
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8);
|
||||
gtk_widget_set_margin_start (vbox, 8);
|
||||
gtk_widget_set_margin_end (vbox, 8);
|
||||
gtk_widget_set_margin_top (vbox, 8);
|
||||
gtk_widget_set_margin_bottom (vbox, 8);
|
||||
g_object_set (vbox, "margin", 8, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), vbox);
|
||||
|
||||
label = gtk_label_new ("This is the bug list (note: not based on real data, it would be nice to have a nice ODBC interface to bugzilla or so, though).");
|
||||
|
@@ -8,6 +8,7 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "award.h"
|
||||
|
||||
static GdkPixbuf *avatar_pixbuf_other;
|
||||
static GtkWidget *window = NULL;
|
||||
@@ -234,9 +235,9 @@ reshare_clicked (GtkMessageRow *row,
|
||||
{
|
||||
GtkMessageRowPrivate *priv = row->priv;
|
||||
|
||||
award ("listbox-reshare");
|
||||
priv->message->n_reshares++;
|
||||
gtk_message_row_update (row);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -255,11 +256,14 @@ gtk_message_row_state_flags_changed (GtkWidget *widget,
|
||||
{
|
||||
GtkMessageRowPrivate *priv = GTK_MESSAGE_ROW (widget)->priv;
|
||||
GtkStateFlags flags;
|
||||
gboolean visible;
|
||||
|
||||
flags = gtk_widget_get_state_flags (widget);
|
||||
|
||||
gtk_widget_set_visible (priv->extra_buttons_box,
|
||||
flags & (GTK_STATE_FLAG_PRELIGHT | GTK_STATE_FLAG_SELECTED));
|
||||
visible = flags & (GTK_STATE_FLAG_PRELIGHT | GTK_STATE_FLAG_SELECTED) ? TRUE : FALSE;
|
||||
gtk_widget_set_visible (priv->extra_buttons_box, visible);
|
||||
if (visible && gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (widget)) % 100 == 99)
|
||||
award ("listbox-100th-row");
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_message_row_parent_class)->state_flags_changed (widget, previous_state_flags);
|
||||
}
|
||||
@@ -347,7 +351,7 @@ do_listbox (GtkWidget *do_widget)
|
||||
{
|
||||
avatar_pixbuf_other = gdk_pixbuf_new_from_resource_at_scale ("/listbox/apple-red.png", 32, 32, FALSE, NULL);
|
||||
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "List Box");
|
||||
|
@@ -1,15 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface domain="gtk40">
|
||||
<menu id="menu1">
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Email message</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Embed message</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</menu>
|
||||
<object class="GtkMenu" id="menu1">
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="menuitem1">
|
||||
<property name="label" translatable="yes">Email message</property>
|
||||
<property name="use-underline">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="menuitem2">
|
||||
<property name="label" translatable="yes">Embed message</property>
|
||||
<property name="use-underline">1</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<template class="GtkMessageRow" parent="GtkListBoxRow">
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid1">
|
||||
@@ -167,7 +171,7 @@
|
||||
<object class="GtkMenuButton" id="more-button">
|
||||
<property name="can-focus">1</property>
|
||||
<property name="receives-default">1</property>
|
||||
<property name="menu-model">menu1</property>
|
||||
<property name="popup">menu1</property>
|
||||
<property name="relief">none</property>
|
||||
<property name="label" translatable="yes">More...</property>
|
||||
</object>
|
||||
|
199
demos/gtk-demo/listview_applauncher.c
Normal file
199
demos/gtk-demo/listview_applauncher.c
Normal file
@@ -0,0 +1,199 @@
|
||||
/* Lists/Application launcher
|
||||
*
|
||||
* This demo uses the GtkCoverFlow widget as a fancy application launcher.
|
||||
*
|
||||
* It is also a very small introduction to listviews.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/* This is the function that creates the #GListModel that we need.
|
||||
* GTK list widgets need a #GListModel to display, as it support change
|
||||
* notifications, but various older APIs do not support one.
|
||||
*/
|
||||
static GListModel *
|
||||
create_application_list (void)
|
||||
{
|
||||
GListStore *store;
|
||||
GList *apps, *l;
|
||||
|
||||
/* We use a #GListStore here, which is a simple array-like list implementation
|
||||
* for manual management.
|
||||
* List models need to know what type of data they provide, so we need to
|
||||
* provide the type here. As we want to do a list of applications, #GAppInfo
|
||||
* is the object we provide.
|
||||
*/
|
||||
store = g_list_store_new (G_TYPE_APP_INFO);
|
||||
|
||||
apps = g_app_info_get_all ();
|
||||
|
||||
for (l = apps; l; l = l->next)
|
||||
{
|
||||
g_list_store_append (store, l->data);
|
||||
}
|
||||
|
||||
g_list_free_full (apps, g_object_unref);
|
||||
|
||||
return G_LIST_MODEL (store);
|
||||
}
|
||||
|
||||
/* This is the function we use for setting up new listitems to display.
|
||||
* We add just a #GtkImage here to display the application's icon as this is just
|
||||
* a simple demo.
|
||||
*/
|
||||
static void
|
||||
setup_listitem_cb (GtkListItemFactory *factory,
|
||||
GtkListItem *list_item)
|
||||
{
|
||||
GtkWidget *image;
|
||||
|
||||
image = gtk_image_new ();
|
||||
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
|
||||
|
||||
gtk_list_item_set_child (list_item, image);
|
||||
}
|
||||
|
||||
/* Here we need to prepare the listitem for displaying its item. We get the
|
||||
* listitem already set up from the previous function, so we can reuse the
|
||||
* #GtkImage widget we set up above.
|
||||
* We get the item - which we know is a #GAppInfo because it comes out of
|
||||
* the model we set up above, grab its icon and display it.
|
||||
*/
|
||||
static void
|
||||
bind_listitem_cb (GtkListItemFactory *factory,
|
||||
GtkListItem *list_item)
|
||||
{
|
||||
GtkWidget *image;
|
||||
GAppInfo *app_info;
|
||||
|
||||
image = gtk_list_item_get_child (list_item);
|
||||
app_info = gtk_list_item_get_item (list_item);
|
||||
|
||||
gtk_image_set_from_gicon (GTK_IMAGE (image), g_app_info_get_icon (app_info));
|
||||
}
|
||||
|
||||
/* In more complex code, we would also need functions to unbind and teardown
|
||||
* the listitem, but this is simple code, so the default implemntations are
|
||||
* enough. If we had connected signals, this step would have been necessary.
|
||||
*
|
||||
* The #GtkSignalListItemFactory documentation contains more information about
|
||||
* this step.
|
||||
*/
|
||||
|
||||
/* This function is called whenever an item in the list is activated. This is
|
||||
* the simple way to allow reacting to the Enter key or double-clicking on a
|
||||
* listitem.
|
||||
* Of course, it is possible to use far more complex interactions by turning
|
||||
* off activation and adding buttons or other widgets in the setup function
|
||||
* above, but this is a simple demo, so we'll use the simple way.
|
||||
*/
|
||||
static void
|
||||
activate_cb (GtkCoverFlow *coverflow,
|
||||
guint position,
|
||||
gpointer unused)
|
||||
{
|
||||
GAppInfo *app_info;
|
||||
GdkAppLaunchContext *context;
|
||||
GError *error = NULL;
|
||||
|
||||
app_info = g_list_model_get_item (gtk_cover_flow_get_model (coverflow), position);
|
||||
|
||||
/* Prepare the context for launching the application and launch it. This
|
||||
* code is explained in detail in the documentation for #GdkAppLaunchContext
|
||||
* and #GAppInfo.
|
||||
*/
|
||||
context = gdk_display_get_app_launch_context (gtk_widget_get_display (GTK_WIDGET (coverflow)));
|
||||
if (!g_app_info_launch (app_info,
|
||||
NULL,
|
||||
G_APP_LAUNCH_CONTEXT (context),
|
||||
&error))
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
|
||||
/* And because error handling is important, even a simple demo has it:
|
||||
* We display an error dialog that something went wrong.
|
||||
*/
|
||||
dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (coverflow))),
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
|
||||
GTK_MESSAGE_ERROR,
|
||||
GTK_BUTTONS_CLOSE,
|
||||
"Could not launch %s", g_app_info_get_display_name (app_info));
|
||||
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
|
||||
g_clear_error (&error);
|
||||
gtk_widget_show (dialog);
|
||||
}
|
||||
|
||||
g_object_unref (context);
|
||||
g_object_unref (app_info);
|
||||
}
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
GtkWidget *
|
||||
do_listview_applauncher (GtkWidget *do_widget)
|
||||
{
|
||||
if (window == NULL)
|
||||
{
|
||||
GtkWidget *coverflow, *sw;;
|
||||
GListModel *model;
|
||||
GtkListItemFactory *factory;
|
||||
|
||||
/* Create a window and set a few defaults */
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 640, 320);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Application Launcher");
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK(gtk_widget_destroyed), &window);
|
||||
|
||||
/* The #GtkListitemFactory is what is used to create #GtkListItems
|
||||
* to display the data from the model. So it is absolutely necessary
|
||||
* to create one.
|
||||
* We will use a #GtkSignalListitemFactory because it is the simplest
|
||||
* one to use. Different ones are available for different use cases.
|
||||
* The most powerful one being the #GtkBuilderListItemFactory which
|
||||
* will to everything without requiring any code and just using a
|
||||
* #GtkBuilder .ui file.
|
||||
*/
|
||||
factory = gtk_signal_list_item_factory_new ();
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (setup_listitem_cb), NULL);
|
||||
g_signal_connect (factory, "bind", G_CALLBACK (bind_listitem_cb), NULL);
|
||||
|
||||
/* Create the list widget here: We use a coverflow widgets, because it's
|
||||
* the coolest one. We could just as well use other list widgets such
|
||||
* as a #GtkListView or a #GtkGridView and the code would look quite
|
||||
* the same.
|
||||
*/
|
||||
coverflow = gtk_cover_flow_new_with_factory (factory);
|
||||
/* We connect the activate signal here. It's the function you remember
|
||||
* from above for launching the selected application.
|
||||
*/
|
||||
g_signal_connect (coverflow, "activate", G_CALLBACK (activate_cb), NULL);
|
||||
|
||||
/* And of course we need to set the data model. Here we call the function
|
||||
* we wrote above that gives us the list of applications and then we set
|
||||
* it on the coverflow list widget.
|
||||
* The coverflow will now take items from the model and use the factory
|
||||
* to create as many listitems as it needs to show itself to the user.
|
||||
*/
|
||||
model = create_application_list ();
|
||||
gtk_cover_flow_set_model (GTK_COVER_FLOW (coverflow), model);
|
||||
g_object_unref (model);
|
||||
|
||||
/* List widgets should always be contained in a #GtkScrolledWindow,
|
||||
* because otherwise they might get too large or they might not
|
||||
* be scrollable.
|
||||
*/
|
||||
sw = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), sw);
|
||||
gtk_container_add (GTK_CONTAINER (sw), coverflow);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
488
demos/gtk-demo/listview_clocks.c
Normal file
488
demos/gtk-demo/listview_clocks.c
Normal file
@@ -0,0 +1,488 @@
|
||||
/* Lists/Clocks
|
||||
*
|
||||
* This demo displays the time in different timezones.
|
||||
*
|
||||
* The goal is to show how to set up expressions that track changes
|
||||
* in objects and make them update widgets.
|
||||
*
|
||||
* For that, we create a GtkClock object that updates its time every
|
||||
* second and then use various ways to display that time.
|
||||
*
|
||||
* Typically, this will be done using GtkBuilder .ui files with the
|
||||
* help of the <binding> tag, but this demo shows the code that runs
|
||||
* behind that.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#define GTK_TYPE_CLOCK (gtk_clock_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (GtkClock, gtk_clock, GTK, CLOCK, GObject)
|
||||
|
||||
/* This is our object. It's just a timezone */
|
||||
typedef struct _GtkClock GtkClock;
|
||||
struct _GtkClock
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
/* We allow this to be NULL for the local timezone */
|
||||
GTimeZone *timezone;
|
||||
/* Name of the location we're displaying time for */
|
||||
char *location;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_LOCATION,
|
||||
PROP_TIME,
|
||||
PROP_TIMEZONE,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
/* This function returns the current time in the clock's timezone.
|
||||
* Note that this returns a new object every time, so we need to
|
||||
* remember to unref it after use. */
|
||||
static GDateTime *
|
||||
gtk_clock_get_time (GtkClock *clock)
|
||||
{
|
||||
if (clock->timezone)
|
||||
return g_date_time_new_now (clock->timezone);
|
||||
else
|
||||
return g_date_time_new_now_local ();
|
||||
}
|
||||
|
||||
/* Here, we implement the functionality required by the GdkPaintable interface.
|
||||
* This way we have a trivial way to display an analog clock.
|
||||
* It also allows demonstrating how to directly use objects in the listview
|
||||
* later by making this object do something interesting. */
|
||||
static void
|
||||
gtk_clock_snapshot (GdkPaintable *paintable,
|
||||
GdkSnapshot *snapshot,
|
||||
double width,
|
||||
double height)
|
||||
{
|
||||
GtkClock *self = GTK_CLOCK (paintable);
|
||||
GDateTime *time;
|
||||
GskRoundedRect outline;
|
||||
|
||||
#define BLACK ((GdkRGBA) { 0, 0, 0, 1 })
|
||||
|
||||
/* save/restore() is necessary so we can undo the transforms we start
|
||||
* out with. */
|
||||
gtk_snapshot_save (snapshot);
|
||||
|
||||
/* First, we move the (0, 0) point to the center of the area so
|
||||
* we can draw everything relative to it. */
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (width / 2, height / 2));
|
||||
/* Next we scale it, so that we can pretend that the clock is
|
||||
* 100px in size. That way, we don't need to do any complicated
|
||||
* math later.
|
||||
* We use MIN() here so that we use the smaller dimension for sizing.
|
||||
* That way we don't overdraw but keep the aspect ratio. */
|
||||
gtk_snapshot_scale (snapshot, MIN (width, height) / 100.0, MIN (width, height) / 100.0);
|
||||
/* Now we have a circle with diameter 100px (and radius 50px) that
|
||||
* has its (0, 0) point at the center.
|
||||
* Let's draw a simple clock into it. */
|
||||
|
||||
time = gtk_clock_get_time (self);
|
||||
|
||||
/* First, draw a circle. This is a neat little trick to draw a circle
|
||||
* without requiring Cairo. */
|
||||
gsk_rounded_rect_init_from_rect (&outline, &GRAPHENE_RECT_INIT(-50, -50, 100, 100), 50);
|
||||
gtk_snapshot_append_border (snapshot,
|
||||
&outline,
|
||||
(float[4]) { 4, 4, 4, 4 },
|
||||
(GdkRGBA [4]) { BLACK, BLACK, BLACK, BLACK });
|
||||
|
||||
/* Next, draw the hour hand.
|
||||
* We do this using tranforms again: Instead of computing where the angle points
|
||||
* to, we just rotate everything and then draw the hand as if if was :00.
|
||||
* We don't even need to care about am/pm here because rotations just work. */
|
||||
gtk_snapshot_save (snapshot);
|
||||
gtk_snapshot_rotate (snapshot, 30 * g_date_time_get_hour (time) + 0.5 * g_date_time_get_minute (time));
|
||||
gsk_rounded_rect_init_from_rect (&outline, &GRAPHENE_RECT_INIT(-2, -23, 4, 25), 2);
|
||||
gtk_snapshot_push_rounded_clip (snapshot, &outline);
|
||||
gtk_snapshot_append_color (snapshot, &BLACK, &outline.bounds);
|
||||
gtk_snapshot_pop (snapshot);
|
||||
gtk_snapshot_restore (snapshot);
|
||||
|
||||
/* And the same as above for the minute hand. Just make this one longer
|
||||
* so people can tell the hands apart. */
|
||||
gtk_snapshot_save (snapshot);
|
||||
gtk_snapshot_rotate (snapshot, 6 * g_date_time_get_minute (time));
|
||||
gsk_rounded_rect_init_from_rect (&outline, &GRAPHENE_RECT_INIT(-2, -43, 4, 45), 2);
|
||||
gtk_snapshot_push_rounded_clip (snapshot, &outline);
|
||||
gtk_snapshot_append_color (snapshot, &BLACK, &outline.bounds);
|
||||
gtk_snapshot_pop (snapshot);
|
||||
gtk_snapshot_restore (snapshot);
|
||||
|
||||
/* and finally, the second indicator. */
|
||||
gtk_snapshot_save (snapshot);
|
||||
gtk_snapshot_rotate (snapshot, 6 * g_date_time_get_second (time));
|
||||
gsk_rounded_rect_init_from_rect (&outline, &GRAPHENE_RECT_INIT(-2, -43, 4, 10), 2);
|
||||
gtk_snapshot_push_rounded_clip (snapshot, &outline);
|
||||
gtk_snapshot_append_color (snapshot, &BLACK, &outline.bounds);
|
||||
gtk_snapshot_pop (snapshot);
|
||||
gtk_snapshot_restore (snapshot);
|
||||
|
||||
/* And finally, don't forget to restore the initial save() that we did for
|
||||
* the initial transformations. */
|
||||
gtk_snapshot_restore (snapshot);
|
||||
|
||||
g_date_time_unref (time);
|
||||
}
|
||||
|
||||
/* Our desired size is 100px. That sounds okay for an analog clock */
|
||||
static int
|
||||
gtk_clock_get_intrinsic_width (GdkPaintable *paintable)
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
static int
|
||||
gtk_clock_get_intrinsic_height (GdkPaintable *paintable)
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
/* Initialize the paintable interface. This way we turn our clock objects
|
||||
* into objects that can be drawn.
|
||||
* There are more functions to this interface to define desired size,
|
||||
* but this is enough.
|
||||
*/
|
||||
static void
|
||||
gtk_clock_paintable_init (GdkPaintableInterface *iface)
|
||||
{
|
||||
iface->snapshot = gtk_clock_snapshot;
|
||||
iface->get_intrinsic_width = gtk_clock_get_intrinsic_width;
|
||||
iface->get_intrinsic_height = gtk_clock_get_intrinsic_height;
|
||||
}
|
||||
|
||||
/* Finally, we define the type. The important part is adding the paintable
|
||||
* interface, so GTK knows that this object can indeed be drawm.
|
||||
*/
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkClock, gtk_clock, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
|
||||
gtk_clock_paintable_init))
|
||||
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
gtk_clock_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkClock *self = GTK_CLOCK (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_LOCATION:
|
||||
g_value_set_string (value, self->location);
|
||||
break;
|
||||
|
||||
case PROP_TIME:
|
||||
g_value_take_boxed (value, gtk_clock_get_time (self));
|
||||
break;
|
||||
|
||||
case PROP_TIMEZONE:
|
||||
g_value_set_boxed (value, self->timezone);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_clock_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkClock *self = GTK_CLOCK (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_LOCATION:
|
||||
self->location = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_TIMEZONE:
|
||||
self->timezone = g_value_dup_boxed (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* This is the list of all the ticking clocks */
|
||||
static GSList *ticking_clocks = NULL;
|
||||
/* This is the id of the timeout source that is updating all ticking clocks */
|
||||
static guint ticking_clock_id = 0;
|
||||
|
||||
/* Every second, this function is called to tell everybody that the
|
||||
* clocks are ticking.
|
||||
*/
|
||||
static gboolean
|
||||
gtk_clock_tick (gpointer unused)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
for (l = ticking_clocks; l; l = l->next)
|
||||
{
|
||||
GtkClock *clock = l->data;
|
||||
|
||||
/* We will now return a different value for the time porperty,
|
||||
* so notify about that.
|
||||
*/
|
||||
g_object_notify_by_pspec (G_OBJECT (clock), properties[PROP_TIME]);
|
||||
/* We will also draw the hands of the clock differently.
|
||||
* So notify about that, too.
|
||||
*/
|
||||
gdk_paintable_invalidate_contents (GDK_PAINTABLE (clock));
|
||||
}
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_clock_stop_ticking (GtkClock *self)
|
||||
{
|
||||
ticking_clocks = g_slist_remove (ticking_clocks, self);
|
||||
|
||||
/* If no clock is remaining, stop running the tick updates */
|
||||
if (ticking_clocks == NULL && ticking_clock_id != 0)
|
||||
g_clear_handle_id (&ticking_clock_id, g_source_remove);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_clock_start_ticking (GtkClock *self)
|
||||
{
|
||||
/* if no clock is ticking yet, start */
|
||||
if (ticking_clock_id == 0)
|
||||
ticking_clock_id = g_timeout_add_seconds (1, gtk_clock_tick, NULL);
|
||||
|
||||
ticking_clocks = g_slist_prepend (ticking_clocks, self);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_clock_finalize (GObject *object)
|
||||
{
|
||||
GtkClock *self = GTK_CLOCK (object);
|
||||
|
||||
gtk_clock_stop_ticking (self);
|
||||
|
||||
g_free (self->location);
|
||||
g_clear_pointer (&self->timezone, g_time_zone_unref);
|
||||
|
||||
G_OBJECT_CLASS (gtk_clock_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_clock_class_init (GtkClockClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->get_property = gtk_clock_get_property;
|
||||
gobject_class->set_property = gtk_clock_set_property;
|
||||
gobject_class->finalize = gtk_clock_finalize;
|
||||
|
||||
properties[PROP_LOCATION] =
|
||||
g_param_spec_string ("location", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
properties[PROP_TIME] =
|
||||
g_param_spec_boxed ("time", NULL, NULL, G_TYPE_DATE_TIME, G_PARAM_READABLE);
|
||||
properties[PROP_TIMEZONE] =
|
||||
g_param_spec_boxed ("timezone", NULL, NULL, G_TYPE_TIME_ZONE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_clock_init (GtkClock *self)
|
||||
{
|
||||
gtk_clock_start_ticking (self);
|
||||
}
|
||||
|
||||
static GtkClock *
|
||||
gtk_clock_new (const char *location,
|
||||
GTimeZone *timezone)
|
||||
{
|
||||
GtkClock *result;
|
||||
|
||||
result = g_object_new (GTK_TYPE_CLOCK,
|
||||
"location", location,
|
||||
"timezone", timezone,
|
||||
NULL);
|
||||
|
||||
g_clear_pointer (&timezone, g_time_zone_unref);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static GListModel *
|
||||
create_clocks_model (void)
|
||||
{
|
||||
GListStore *result;
|
||||
GtkClock *clock;
|
||||
|
||||
result = g_list_store_new (GTK_TYPE_CLOCK);
|
||||
|
||||
/* local time */
|
||||
clock = gtk_clock_new ("local", NULL);
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
/* UTC time */
|
||||
clock = gtk_clock_new ("UTC", g_time_zone_new_utc ());
|
||||
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 ("America/Los_Angeles"));
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
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 ("Europe/London"));
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
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 ("Europe/Moscow"));
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
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 ("Asia/Shanghai"));
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
|
||||
return G_LIST_MODEL (result);
|
||||
}
|
||||
|
||||
static char *
|
||||
convert_time_to_string (GObject *image,
|
||||
GDateTime *time,
|
||||
gpointer unused)
|
||||
{
|
||||
return g_date_time_format (time, "%x\n%X");
|
||||
}
|
||||
|
||||
/* And this function is the crux for this whole demo.
|
||||
* It shows how to use expressions to set up bindings.
|
||||
*/
|
||||
static void
|
||||
setup_listitem_cb (GtkListItemFactory *factory,
|
||||
GtkListItem *list_item)
|
||||
{
|
||||
GtkWidget *box, *picture, *location_label, *time_label;
|
||||
GtkExpression *clock_expression, *expression;
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_list_item_set_child (list_item, box);
|
||||
|
||||
/* First, we create an expression that gets us the clock from the listitem:
|
||||
* 1. Create an expression that gets the list item.
|
||||
* 2. Use that expression's "item" property to get the clock
|
||||
*/
|
||||
expression = gtk_constant_expression_new (GTK_TYPE_LIST_ITEM, list_item);
|
||||
clock_expression = gtk_property_expression_new (GTK_TYPE_LIST_ITEM, expression, "item");
|
||||
|
||||
/* Bind the clock's location to a label.
|
||||
* This is easy: We just get the "location" property of the clock.
|
||||
*/
|
||||
expression = gtk_property_expression_new (GTK_TYPE_CLOCK,
|
||||
gtk_expression_ref (clock_expression),
|
||||
"location");
|
||||
/* Now create the label and bind the expression to it. */
|
||||
location_label = gtk_label_new (NULL);
|
||||
gtk_expression_bind (expression, location_label, location_label, "label");
|
||||
gtk_container_add (GTK_CONTAINER (box), location_label);
|
||||
|
||||
|
||||
/* Here we bind the item itself to a GdkPicture.
|
||||
* This is simply done by using the clock expression itself.
|
||||
*/
|
||||
expression = gtk_expression_ref (clock_expression);
|
||||
/* Now create the widget and bind the expression to it. */
|
||||
picture = gtk_picture_new ();
|
||||
gtk_expression_bind (expression, picture, picture, "paintable");
|
||||
gtk_container_add (GTK_CONTAINER (box), picture);
|
||||
|
||||
|
||||
/* And finally, everything comes together.
|
||||
* We create a label for displaying the time as text.
|
||||
* For that, we need to transform the "GDateTime" of the
|
||||
* time property into a string so that the label can display it.
|
||||
*/
|
||||
expression = gtk_property_expression_new (GTK_TYPE_CLOCK,
|
||||
gtk_expression_ref (clock_expression),
|
||||
"time");
|
||||
expression = gtk_cclosure_expression_new (G_TYPE_STRING,
|
||||
NULL,
|
||||
1, (GtkExpression *[1]) { expression },
|
||||
G_CALLBACK (convert_time_to_string),
|
||||
NULL, NULL);
|
||||
/* Now create the label and bind the expression to it. */
|
||||
time_label = gtk_label_new (NULL);
|
||||
gtk_expression_bind (expression, time_label, time_label, "label");
|
||||
gtk_container_add (GTK_CONTAINER (box), time_label);
|
||||
|
||||
gtk_expression_unref (clock_expression);
|
||||
}
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
GtkWidget *
|
||||
do_listview_clocks (GtkWidget *do_widget)
|
||||
{
|
||||
if (window == NULL)
|
||||
{
|
||||
GtkWidget *gridview, *sw;
|
||||
GtkListItemFactory *factory;
|
||||
GListModel *model;
|
||||
GtkNoSelection *selection;
|
||||
|
||||
/* This is the normal window setup code every demo does */
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
/* List widgets go into a scrolled window. Always. */
|
||||
sw = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), sw);
|
||||
|
||||
/* Create the factory that creates the listitems. Because we
|
||||
* used bindings above during setup, we only need to connect
|
||||
* to the setup signal.
|
||||
* The bindings take care of the bind step.
|
||||
*/
|
||||
factory = gtk_signal_list_item_factory_new ();
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (setup_listitem_cb), NULL);
|
||||
|
||||
gridview = gtk_grid_view_new_with_factory (factory);
|
||||
gtk_scrollable_set_hscroll_policy (GTK_SCROLLABLE (gridview), GTK_SCROLL_NATURAL);
|
||||
gtk_scrollable_set_vscroll_policy (GTK_SCROLLABLE (gridview), GTK_SCROLL_NATURAL);
|
||||
|
||||
model = create_clocks_model ();
|
||||
selection = gtk_no_selection_new (model);
|
||||
gtk_grid_view_set_model (GTK_GRID_VIEW (gridview), G_LIST_MODEL (selection));
|
||||
gtk_container_add (GTK_CONTAINER (sw), gridview);
|
||||
g_object_unref (selection);
|
||||
g_object_unref (model);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
255
demos/gtk-demo/listview_filebrowser.c
Normal file
255
demos/gtk-demo/listview_filebrowser.c
Normal file
@@ -0,0 +1,255 @@
|
||||
/* Lists/File browser
|
||||
*
|
||||
* This demo shows off the different layouts that are quickly achievable
|
||||
* with GtkGridView by implementing a file browser with different views.
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
/* Create a simple object that holds the data for the different views */
|
||||
typedef struct _FileBrowserView FileBrowserView;
|
||||
struct _FileBrowserView
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GtkListItemFactory *factory;
|
||||
char *icon_name;
|
||||
GtkOrientation orientation;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_FACTORY,
|
||||
PROP_ICON_NAME,
|
||||
PROP_ORIENTATION,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
#define FILE_BROWSER_TYPE_VIEW (file_browser_view_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (FileBrowserView, file_browser_view, FILE_BROWSER, VIEW, GObject);
|
||||
|
||||
G_DEFINE_TYPE (FileBrowserView, file_browser_view, G_TYPE_OBJECT);
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
file_browser_view_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
FileBrowserView *self = FILE_BROWSER_VIEW (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_FACTORY:
|
||||
g_value_set_object (value, self->factory);
|
||||
break;
|
||||
|
||||
case PROP_ICON_NAME:
|
||||
g_value_set_string (value, self->icon_name);
|
||||
break;
|
||||
|
||||
case PROP_ORIENTATION:
|
||||
g_value_set_enum (value, self->orientation);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
file_browser_view_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
FileBrowserView *self = FILE_BROWSER_VIEW (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_FACTORY:
|
||||
g_set_object (&self->factory, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_ICON_NAME:
|
||||
g_free (self->icon_name);
|
||||
self->icon_name = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_ORIENTATION:
|
||||
self->orientation = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
file_browser_view_finalize (GObject *object)
|
||||
{
|
||||
FileBrowserView *self = FILE_BROWSER_VIEW (object);
|
||||
|
||||
g_object_unref (self->factory);
|
||||
g_free (self->icon_name);
|
||||
|
||||
G_OBJECT_CLASS (file_browser_view_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
file_browser_view_class_init (FileBrowserViewClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->get_property = file_browser_view_get_property;
|
||||
gobject_class->set_property = file_browser_view_set_property;
|
||||
gobject_class->finalize = file_browser_view_finalize;
|
||||
|
||||
properties[PROP_FACTORY] =
|
||||
g_param_spec_object ("factory",
|
||||
"factory",
|
||||
"factory to use in the main view",
|
||||
GTK_TYPE_LIST_ITEM_FACTORY,
|
||||
G_PARAM_READWRITE);
|
||||
properties[PROP_ICON_NAME] =
|
||||
g_param_spec_string ("icon-name",
|
||||
"icon name",
|
||||
"icon to display for selecting this view",
|
||||
NULL,
|
||||
G_PARAM_READWRITE);
|
||||
properties[PROP_ORIENTATION] =
|
||||
g_param_spec_enum ("orientation",
|
||||
"orientation",
|
||||
"orientation of the view",
|
||||
GTK_TYPE_ORIENTATION,
|
||||
GTK_ORIENTATION_VERTICAL,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void file_browser_view_init (FileBrowserView *self)
|
||||
{
|
||||
}
|
||||
|
||||
char *
|
||||
filebrowser_get_display_name (GObject *object,
|
||||
GFileInfo *info)
|
||||
{
|
||||
if (!info)
|
||||
return NULL;
|
||||
|
||||
return g_strdup (g_file_info_get_attribute_string (info, "standard::display-name"));
|
||||
}
|
||||
|
||||
char *
|
||||
filebrowser_get_content_type (GObject *object,
|
||||
GFileInfo *info)
|
||||
{
|
||||
if (!info)
|
||||
return NULL;
|
||||
|
||||
return g_strdup (g_file_info_get_attribute_string (info, "standard::content-type"));
|
||||
}
|
||||
|
||||
char *
|
||||
filebrowser_get_size (GObject *object,
|
||||
GFileInfo *info)
|
||||
{
|
||||
if (!info)
|
||||
return NULL;
|
||||
|
||||
return g_format_size (g_file_info_get_attribute_uint64 (info, "standard::size"));
|
||||
}
|
||||
|
||||
GIcon *
|
||||
filebrowser_get_icon (GObject *object,
|
||||
GFileInfo *info)
|
||||
{
|
||||
GIcon *icon;
|
||||
|
||||
if (info)
|
||||
icon = G_ICON (g_file_info_get_attribute_object (info, "standard::icon"));
|
||||
else
|
||||
icon = NULL;
|
||||
|
||||
if (icon)
|
||||
g_object_ref (icon);
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
void
|
||||
filebrowser_up_clicked_cb (GtkButton *button,
|
||||
GtkDirectoryList *list)
|
||||
{
|
||||
GFile *file;
|
||||
|
||||
file = g_file_get_parent (gtk_directory_list_get_file (list));
|
||||
if (file == NULL)
|
||||
return;
|
||||
|
||||
gtk_directory_list_set_file (list, file);
|
||||
}
|
||||
|
||||
void
|
||||
filebrowser_view_activated_cb (GtkGridView *view,
|
||||
guint pos,
|
||||
GtkDirectoryList *list)
|
||||
{
|
||||
GFileInfo *info;
|
||||
|
||||
info = g_list_model_get_item (gtk_grid_view_get_model (view), pos);
|
||||
if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
|
||||
gtk_directory_list_set_file (list, G_FILE (g_file_info_get_attribute_object (info, "standard::file")));
|
||||
|
||||
g_object_unref (info);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_listview_filebrowser (GtkWidget *do_widget)
|
||||
{
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *view;
|
||||
GtkBuilder *builder;
|
||||
GtkDirectoryList *dirlist;
|
||||
GFile *file;
|
||||
char *cwd;
|
||||
|
||||
builder = gtk_builder_new_from_resource ("/listview_filebrowser/listview_filebrowser.ui");
|
||||
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
/* Create the model and fill it with the contents of the current directory */
|
||||
cwd = g_get_current_dir ();
|
||||
file = g_file_new_for_path (cwd);
|
||||
g_free (cwd);
|
||||
dirlist = GTK_DIRECTORY_LIST (gtk_builder_get_object (builder, "dirlist"));
|
||||
gtk_directory_list_set_file (dirlist, file);
|
||||
g_object_unref (file);
|
||||
|
||||
/* grab focus in the view */
|
||||
view = GTK_WIDGET (gtk_builder_get_object (builder, "view"));
|
||||
gtk_widget_grab_focus (view);
|
||||
|
||||
g_object_unref (builder);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
240
demos/gtk-demo/listview_filebrowser.ui
Normal file
240
demos/gtk-demo/listview_filebrowser.ui
Normal file
@@ -0,0 +1,240 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<object class="GListStore" id="viewlist">
|
||||
<property name="item-type">FileBrowserView</property>
|
||||
<child>
|
||||
<object class="FileBrowserView">
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<binding name="gicon">
|
||||
<closure type="GIcon" function="filebrowser_get_icon">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">start</property>
|
||||
<binding name="label">
|
||||
<closure type="gchararray" function="filebrowser_get_display_name">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
<property name="icon-name">view-list-symbolic</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="FileBrowserView">
|
||||
<property name="icon-name">view-grid-symbolic</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="icon-size">large</property>
|
||||
<binding name="gicon">
|
||||
<closure type="GIcon" function="filebrowser_get_icon">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="wrap">1</property>
|
||||
<property name="wrap-mode">word-char</property>
|
||||
<property name="lines">2</property>
|
||||
<property name="ellipsize">end</property>
|
||||
<property name="width-chars">10</property>
|
||||
<property name="max-width-chars">30</property>
|
||||
<binding name="label">
|
||||
<closure type="gchararray" function="filebrowser_get_display_name">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
<property name="orientation">vertical</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="FileBrowserView">
|
||||
<property name="icon-name">view-paged-symbolic</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="icon-size">large</property>
|
||||
<binding name="gicon">
|
||||
<closure type="GIcon" function="filebrowser_get_icon">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">start</property>
|
||||
<binding name="label">
|
||||
<closure type="gchararray" function="filebrowser_get_display_name">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">start</property>
|
||||
<binding name="label">
|
||||
<closure type="gchararray" function="filebrowser_get_size">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">start</property>
|
||||
<binding name="label">
|
||||
<closure type="gchararray" function="filebrowser_get_content_type">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkDirectoryList" id="dirlist">
|
||||
<property name="attributes">standard::name,standard::display-name,standard::icon,standard::size,standard::content-type</property>
|
||||
</object>
|
||||
<object class="GtkWindow" id="window">
|
||||
<property name="title" translatable="yes">File browser</property>
|
||||
<property name="default-width">600</property>
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="icon-name">go-up</property>
|
||||
<signal name="clicked" handler="filebrowser_up_clicked_cb" object="dirlist" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
<object class="GtkListView">
|
||||
<property name="valign">center</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
<style>
|
||||
<class name="linked"/>
|
||||
</style>
|
||||
<property name="model">
|
||||
<object class="GtkSingleSelection" id="selected-view">
|
||||
<property name="model">viewlist</property>
|
||||
</object>
|
||||
</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkImage">
|
||||
<binding name="icon-name">
|
||||
<lookup type="FileBrowserView" name="icon-name">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="can-focus">1</property>
|
||||
<child>
|
||||
<object class="GtkGridView" id="view">
|
||||
<property name="model">dirlist</property>
|
||||
<property name="max-columns">15</property>
|
||||
<binding name="factory">
|
||||
<lookup name="factory" type="FileBrowserView">
|
||||
<lookup name="selected-item">selected-view</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
<binding name="orientation">
|
||||
<lookup name="orientation" type="FileBrowserView">
|
||||
<lookup name="selected-item">selected-view</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
<signal name="activate" handler="filebrowser_view_activated_cb" object="dirlist" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
473
demos/gtk-demo/listview_minesweeper.c
Normal file
473
demos/gtk-demo/listview_minesweeper.c
Normal file
@@ -0,0 +1,473 @@
|
||||
/* Lists/Minesweeper
|
||||
*
|
||||
* This demo shows how to develop a user interface for small game using a
|
||||
* gridview.
|
||||
*
|
||||
* It demonstrates how to use the activate signal and single-press behavior
|
||||
* to implement rather different interaction behavior to a typical list.
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/*** The cell object ***/
|
||||
|
||||
/* Create an object that holds the data for a cell in the game */
|
||||
typedef struct _SweeperCell SweeperCell;
|
||||
struct _SweeperCell
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
gboolean is_mine;
|
||||
gboolean is_visible;
|
||||
guint neighbor_mines;
|
||||
};
|
||||
|
||||
enum {
|
||||
CELL_PROP_0,
|
||||
CELL_PROP_LABEL,
|
||||
|
||||
N_CELL_PROPS
|
||||
};
|
||||
|
||||
#define SWEEPER_TYPE_CELL (sweeper_cell_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (SweeperCell, sweeper_cell, SWEEPER, CELL, GObject);
|
||||
|
||||
G_DEFINE_TYPE (SweeperCell, sweeper_cell, G_TYPE_OBJECT);
|
||||
static GParamSpec *cell_properties[N_CELL_PROPS] = { NULL, };
|
||||
|
||||
static const char *
|
||||
sweeper_cell_get_label (SweeperCell *self)
|
||||
{
|
||||
static const char *minecount_labels[10] = { "", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
|
||||
|
||||
if (!self->is_visible)
|
||||
return "?";
|
||||
|
||||
if (self->is_mine)
|
||||
return "💣";
|
||||
|
||||
return minecount_labels[self->neighbor_mines];
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_cell_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SweeperCell *self = SWEEPER_CELL (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case CELL_PROP_LABEL:
|
||||
g_value_set_string (value, sweeper_cell_get_label (self));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_cell_class_init (SweeperCellClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->get_property = sweeper_cell_get_property;
|
||||
|
||||
cell_properties[CELL_PROP_LABEL] =
|
||||
g_param_spec_string ("label",
|
||||
"label",
|
||||
"label to display for this row",
|
||||
NULL,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_CELL_PROPS, cell_properties);
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_cell_init (SweeperCell *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_cell_reveal (SweeperCell *self)
|
||||
{
|
||||
if (self->is_visible)
|
||||
return;
|
||||
|
||||
self->is_visible = TRUE;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), cell_properties[CELL_PROP_LABEL]);
|
||||
}
|
||||
|
||||
static SweeperCell *
|
||||
sweeper_cell_new ()
|
||||
{
|
||||
return g_object_new (SWEEPER_TYPE_CELL, NULL);
|
||||
}
|
||||
|
||||
/*** The board object ***/
|
||||
|
||||
/* Create an object that holds the data for the game */
|
||||
typedef struct _SweeperGame SweeperGame;
|
||||
struct _SweeperGame
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GPtrArray *cells;
|
||||
guint width;
|
||||
guint height;
|
||||
gboolean playing;
|
||||
gboolean win;
|
||||
};
|
||||
|
||||
enum {
|
||||
GAME_PROP_0,
|
||||
GAME_PROP_HEIGHT,
|
||||
GAME_PROP_PLAYING,
|
||||
GAME_PROP_WIDTH,
|
||||
GAME_PROP_WIN,
|
||||
|
||||
N_GAME_PROPS
|
||||
};
|
||||
|
||||
#define SWEEPER_TYPE_GAME (sweeper_game_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (SweeperGame, sweeper_game, SWEEPER, GAME, GObject);
|
||||
|
||||
static GType
|
||||
sweeper_game_list_model_get_item_type (GListModel *model)
|
||||
{
|
||||
return SWEEPER_TYPE_GAME;
|
||||
}
|
||||
|
||||
static guint
|
||||
sweeper_game_list_model_get_n_items (GListModel *model)
|
||||
{
|
||||
SweeperGame *self = SWEEPER_GAME (model);
|
||||
|
||||
return self->width * self->height;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
sweeper_game_list_model_get_item (GListModel *model,
|
||||
guint position)
|
||||
{
|
||||
SweeperGame *self = SWEEPER_GAME (model);
|
||||
|
||||
return g_object_ref (g_ptr_array_index (self->cells, position));
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_game_list_model_init (GListModelInterface *iface)
|
||||
{
|
||||
iface->get_item_type = sweeper_game_list_model_get_item_type;
|
||||
iface->get_n_items = sweeper_game_list_model_get_n_items;
|
||||
iface->get_item = sweeper_game_list_model_get_item;
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (SweeperGame, sweeper_game, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, sweeper_game_list_model_init))
|
||||
|
||||
static GParamSpec *game_properties[N_GAME_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
sweeper_game_dispose (GObject *object)
|
||||
{
|
||||
SweeperGame *self = SWEEPER_GAME (object);
|
||||
|
||||
g_clear_pointer (&self->cells, g_ptr_array_unref);
|
||||
|
||||
G_OBJECT_CLASS (sweeper_game_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_game_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SweeperGame *self = SWEEPER_GAME (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case GAME_PROP_HEIGHT:
|
||||
g_value_set_uint (value, self->height);
|
||||
break;
|
||||
|
||||
case GAME_PROP_PLAYING:
|
||||
g_value_set_boolean (value, self->playing);
|
||||
break;
|
||||
|
||||
case GAME_PROP_WIDTH:
|
||||
g_value_set_uint (value, self->width);
|
||||
break;
|
||||
|
||||
case GAME_PROP_WIN:
|
||||
g_value_set_boolean (value, self->win);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_game_class_init (SweeperGameClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->dispose = sweeper_game_dispose;
|
||||
gobject_class->get_property = sweeper_game_get_property;
|
||||
|
||||
game_properties[GAME_PROP_HEIGHT] =
|
||||
g_param_spec_uint ("height",
|
||||
"height",
|
||||
"height of the game grid",
|
||||
1, G_MAXUINT, 8,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
game_properties[GAME_PROP_PLAYING] =
|
||||
g_param_spec_boolean ("playing",
|
||||
"playing",
|
||||
"if the game is still going on",
|
||||
FALSE,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
game_properties[GAME_PROP_WIDTH] =
|
||||
g_param_spec_uint ("width",
|
||||
"width",
|
||||
"width of the game grid",
|
||||
1, G_MAXUINT, 8,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
game_properties[GAME_PROP_WIN] =
|
||||
g_param_spec_boolean ("win",
|
||||
"win",
|
||||
"if the game was won",
|
||||
FALSE,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_GAME_PROPS, game_properties);
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_game_reset_board (SweeperGame *self,
|
||||
guint width,
|
||||
guint height)
|
||||
{
|
||||
guint i;
|
||||
|
||||
g_ptr_array_set_size (self->cells, 0);
|
||||
|
||||
for (i = 0; i < width * height; i++)
|
||||
{
|
||||
g_ptr_array_add (self->cells, sweeper_cell_new ());
|
||||
}
|
||||
|
||||
if (self->width != width)
|
||||
{
|
||||
self->width = width;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), game_properties[GAME_PROP_WIDTH]);
|
||||
}
|
||||
if (self->height != height)
|
||||
{
|
||||
self->height = height;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), game_properties[GAME_PROP_HEIGHT]);
|
||||
}
|
||||
if (!self->playing)
|
||||
{
|
||||
self->playing = TRUE;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), game_properties[GAME_PROP_PLAYING]);
|
||||
}
|
||||
if (self->win)
|
||||
{
|
||||
self->win = FALSE;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), game_properties[GAME_PROP_WIN]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_game_place_mines (SweeperGame *self,
|
||||
guint n_mines)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < n_mines; i++)
|
||||
{
|
||||
SweeperCell *cell;
|
||||
|
||||
do {
|
||||
cell = g_ptr_array_index (self->cells, g_random_int_range (0, self->cells->len));
|
||||
} while (cell->is_mine);
|
||||
|
||||
cell->is_mine = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static SweeperCell *
|
||||
get_cell (SweeperGame *self,
|
||||
guint x,
|
||||
guint y)
|
||||
{
|
||||
return g_ptr_array_index (self->cells, y * self->width + x);
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_game_count_neighbor_mines (SweeperGame *self,
|
||||
guint width,
|
||||
guint height)
|
||||
{
|
||||
guint x, y, x2, y2;
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
SweeperCell *cell = get_cell (self, x, y);
|
||||
|
||||
for (y2 = MAX (1, y) - 1; y2 < MIN (height, y + 2); y2++)
|
||||
{
|
||||
for (x2 = MAX (1, x) - 1; x2 < MIN (width, x + 2); x2++)
|
||||
{
|
||||
SweeperCell *other = get_cell (self, x2, y2);
|
||||
|
||||
if (other->is_mine)
|
||||
cell->neighbor_mines++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_game_new_game (SweeperGame *self,
|
||||
guint width,
|
||||
guint height,
|
||||
guint n_mines)
|
||||
{
|
||||
guint n_items_before;
|
||||
|
||||
g_return_if_fail (n_mines <= width * height);
|
||||
|
||||
n_items_before = self->width * self->height;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
|
||||
sweeper_game_reset_board (self, width, height);
|
||||
sweeper_game_place_mines (self, n_mines);
|
||||
sweeper_game_count_neighbor_mines (self, width, height);
|
||||
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), 0, n_items_before, width * height);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_game_init (SweeperGame *self)
|
||||
{
|
||||
self->cells = g_ptr_array_new_with_free_func (g_object_unref);
|
||||
|
||||
sweeper_game_new_game (self, 8, 8, 10);
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_game_end (SweeperGame *self,
|
||||
gboolean win)
|
||||
{
|
||||
if (self->playing)
|
||||
{
|
||||
self->playing = FALSE;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), game_properties[GAME_PROP_PLAYING]);
|
||||
}
|
||||
if (self->win != win)
|
||||
{
|
||||
self->win = win;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), game_properties[GAME_PROP_WIN]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_game_check_finished (SweeperGame *self)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (!self->playing)
|
||||
return;
|
||||
|
||||
for (i = 0; i < self->cells->len; i++)
|
||||
{
|
||||
SweeperCell *cell = g_ptr_array_index (self->cells, i);
|
||||
|
||||
/* There's still a non-revealed cell that isn't a mine */
|
||||
if (!cell->is_visible && !cell->is_mine)
|
||||
return;
|
||||
}
|
||||
|
||||
sweeper_game_end (self, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_game_reveal_cell (SweeperGame *self,
|
||||
guint position)
|
||||
{
|
||||
SweeperCell *cell;
|
||||
|
||||
if (!self->playing)
|
||||
return;
|
||||
|
||||
cell = g_ptr_array_index (self->cells, position);
|
||||
sweeper_cell_reveal (cell);
|
||||
|
||||
if (cell->is_mine)
|
||||
sweeper_game_end (self, FALSE);
|
||||
|
||||
sweeper_game_check_finished (self);
|
||||
}
|
||||
|
||||
void
|
||||
minesweeper_cell_clicked_cb (GtkGridView *gridview,
|
||||
guint pos,
|
||||
SweeperGame *game)
|
||||
{
|
||||
sweeper_game_reveal_cell (game, pos);
|
||||
}
|
||||
|
||||
void
|
||||
minesweeper_new_game_cb (GtkButton *button,
|
||||
SweeperGame *game)
|
||||
{
|
||||
sweeper_game_new_game (game, 8, 8, 10);
|
||||
}
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
GtkWidget *
|
||||
do_listview_minesweeper (GtkWidget *do_widget)
|
||||
{
|
||||
if (window == NULL)
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
|
||||
g_type_ensure (SWEEPER_TYPE_GAME);
|
||||
|
||||
builder = gtk_builder_new_from_resource ("/listview_minesweeper/listview_minesweeper.ui");
|
||||
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
g_object_unref (builder);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
48
demos/gtk-demo/listview_minesweeper.ui
Normal file
48
demos/gtk-demo/listview_minesweeper.ui
Normal file
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<object class="SweeperGame" id="game">
|
||||
</object>
|
||||
<object class="GtkWindow" id="window">
|
||||
<property name="title" translatable="yes">Minesweeper</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label">New Game</property>
|
||||
<signal name="clicked" handler="minesweeper_new_game_cb" object="game" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child type="title">
|
||||
<object class="GtkImage">
|
||||
<property name="icon-name">trophy-gold</property>
|
||||
<binding name="visible">
|
||||
<lookup name="win">game</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGridView" id="view">
|
||||
<property name="model">
|
||||
<object class="GtkNoSelection">
|
||||
<property name="model">game</property>
|
||||
</object>
|
||||
</property>
|
||||
<binding name="max-columns">
|
||||
<lookup name="width">game</lookup>
|
||||
</binding>
|
||||
<binding name="min-columns">
|
||||
<lookup name="width">game</lookup>
|
||||
</binding>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="resource">/listview_minesweeper/listview_minesweeper_cell.ui</property>
|
||||
</object>
|
||||
</property>
|
||||
<signal name="activate" handler="minesweeper_cell_clicked_cb" object="game" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
16
demos/gtk-demo/listview_minesweeper_cell.ui
Normal file
16
demos/gtk-demo/listview_minesweeper_cell.ui
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<binding name="label">
|
||||
<lookup name="label" type="SweeperCell">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
256
demos/gtk-demo/listview_settings.c
Normal file
256
demos/gtk-demo/listview_settings.c
Normal file
@@ -0,0 +1,256 @@
|
||||
/* Lists/Settings
|
||||
*
|
||||
* This demo shows a settings viewer for GSettings.
|
||||
*
|
||||
* It demonstrates how to implement support for trees with listview.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/* Create an object that wraps GSettingsSchemaKey because that's a boxed type */
|
||||
typedef struct _SettingsKey SettingsKey;
|
||||
struct _SettingsKey
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GSettings *settings;
|
||||
GSettingsSchemaKey *key;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_NAME,
|
||||
PROP_SUMMARY,
|
||||
PROP_DESCRIPTION,
|
||||
PROP_VALUE,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
#define SETTINGS_TYPE_KEY (settings_key_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (SettingsKey, settings_key, SETTINGS, KEY, GObject);
|
||||
|
||||
G_DEFINE_TYPE (SettingsKey, settings_key, G_TYPE_OBJECT);
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
settings_key_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SettingsKey *self = SETTINGS_KEY (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_DESCRIPTION:
|
||||
g_value_set_string (value, g_settings_schema_key_get_description (self->key));
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, g_settings_schema_key_get_name (self->key));
|
||||
break;
|
||||
|
||||
case PROP_SUMMARY:
|
||||
g_value_set_string (value, g_settings_schema_key_get_summary (self->key));
|
||||
break;
|
||||
|
||||
case PROP_VALUE:
|
||||
{
|
||||
GVariant *variant = g_settings_get_value (self->settings, g_settings_schema_key_get_name (self->key));
|
||||
g_value_take_string (value, g_variant_print (variant, FALSE));
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
settings_key_class_init (SettingsKeyClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->get_property = settings_key_get_property;
|
||||
|
||||
properties[PROP_DESCRIPTION] =
|
||||
g_param_spec_string ("description", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
properties[PROP_NAME] =
|
||||
g_param_spec_string ("name", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
properties[PROP_SUMMARY] =
|
||||
g_param_spec_string ("summary", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
properties[PROP_VALUE] =
|
||||
g_param_spec_string ("value", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
settings_key_init (SettingsKey *self)
|
||||
{
|
||||
}
|
||||
|
||||
static SettingsKey *
|
||||
settings_key_new (GSettings *settings,
|
||||
GSettingsSchemaKey *key)
|
||||
{
|
||||
SettingsKey *result = g_object_new (SETTINGS_TYPE_KEY, NULL);
|
||||
|
||||
result->settings = g_object_ref (settings);
|
||||
result->key = g_settings_schema_key_ref (key);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
strvcmp (gconstpointer p1,
|
||||
gconstpointer p2)
|
||||
{
|
||||
const char * const *s1 = p1;
|
||||
const char * const *s2 = p2;
|
||||
|
||||
return strcmp (*s1, *s2);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
transform_settings_to_keys (GBinding *binding,
|
||||
const GValue *from_value,
|
||||
GValue *to_value,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkTreeListRow *treelistrow;
|
||||
GSettings *settings;
|
||||
GSettingsSchema *schema;
|
||||
GListStore *store;
|
||||
char **keys;
|
||||
guint i;
|
||||
|
||||
treelistrow = g_value_get_object (from_value);
|
||||
if (treelistrow == NULL)
|
||||
return TRUE;
|
||||
settings = gtk_tree_list_row_get_item (treelistrow);
|
||||
g_object_get (settings, "settings-schema", &schema, NULL);
|
||||
|
||||
store = g_list_store_new (SETTINGS_TYPE_KEY);
|
||||
|
||||
keys = g_settings_schema_list_keys (schema);
|
||||
qsort (keys, g_strv_length (keys), sizeof (char *), strvcmp);
|
||||
|
||||
for (i = 0; keys[i] != NULL; i++)
|
||||
{
|
||||
GSettingsSchemaKey *almost_there = g_settings_schema_get_key (schema, keys[i]);
|
||||
SettingsKey *finally = settings_key_new (settings, almost_there);
|
||||
g_list_store_append (store, finally);
|
||||
g_object_unref (finally);
|
||||
g_settings_schema_key_unref (almost_there);
|
||||
}
|
||||
|
||||
g_strfreev (keys);
|
||||
g_settings_schema_unref (schema);
|
||||
g_object_unref (settings);
|
||||
|
||||
g_value_take_object (to_value, store);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GListModel *
|
||||
create_settings_model (gpointer item,
|
||||
gpointer unused)
|
||||
{
|
||||
GSettings *settings = item;
|
||||
char **schemas;
|
||||
GListStore *result;
|
||||
guint i;
|
||||
|
||||
if (settings == NULL)
|
||||
{
|
||||
g_settings_schema_source_list_schemas (g_settings_schema_source_get_default (),
|
||||
TRUE,
|
||||
&schemas,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
schemas = g_settings_list_children (settings);
|
||||
}
|
||||
|
||||
if (schemas == NULL || schemas[0] == NULL)
|
||||
{
|
||||
g_free (schemas);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qsort (schemas, g_strv_length (schemas), sizeof (char *), strvcmp);
|
||||
|
||||
result = g_list_store_new (G_TYPE_SETTINGS);
|
||||
for (i = 0; schemas[i] != NULL; i++)
|
||||
{
|
||||
GSettings *child;
|
||||
|
||||
if (settings == NULL)
|
||||
child = g_settings_new (schemas[i]);
|
||||
else
|
||||
child = g_settings_get_child (settings, schemas[i]);
|
||||
|
||||
g_list_store_append (result, child);
|
||||
g_object_unref (child);
|
||||
}
|
||||
|
||||
return G_LIST_MODEL (result);
|
||||
}
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
GtkWidget *
|
||||
do_listview_settings (GtkWidget *do_widget)
|
||||
{
|
||||
if (window == NULL)
|
||||
{
|
||||
GtkWidget *listview, *columnview;
|
||||
GListModel *model;
|
||||
GtkTreeListModel *treemodel;
|
||||
GtkSingleSelection *selection;
|
||||
GtkBuilder *builder;
|
||||
|
||||
g_type_ensure (SETTINGS_TYPE_KEY);
|
||||
|
||||
builder = gtk_builder_new_from_resource ("/listview_settings/listview_settings.ui");
|
||||
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
listview = GTK_WIDGET (gtk_builder_get_object (builder, "listview"));
|
||||
columnview = GTK_WIDGET (gtk_builder_get_object (builder, "columnview"));
|
||||
model = create_settings_model (NULL, NULL);
|
||||
treemodel = gtk_tree_list_model_new (FALSE,
|
||||
model,
|
||||
TRUE,
|
||||
create_settings_model,
|
||||
NULL,
|
||||
NULL);
|
||||
selection = gtk_single_selection_new (G_LIST_MODEL (treemodel));
|
||||
g_object_bind_property_full (selection, "selected-item",
|
||||
columnview, "model",
|
||||
G_BINDING_SYNC_CREATE,
|
||||
transform_settings_to_keys,
|
||||
NULL,
|
||||
NULL, NULL);
|
||||
gtk_list_view_set_model (GTK_LIST_VIEW (listview), G_LIST_MODEL (selection));
|
||||
g_object_unref (selection);
|
||||
g_object_unref (treemodel);
|
||||
g_object_unref (model);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
108
demos/gtk-demo/listview_settings.ui
Normal file
108
demos/gtk-demo/listview_settings.ui
Normal file
@@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<object class="GtkWindow" id="window">
|
||||
<property name="title" translatable="yes">Settings</property>
|
||||
<property name="default-width">600</property>
|
||||
<property name="default-height">400</property>
|
||||
<child>
|
||||
<object class="GtkPaned">
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<child>
|
||||
<object class="GtkListView" id="listview">
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkTreeExpander" id="expander">
|
||||
<binding name="list-row">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</binding>
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<binding name="label">
|
||||
<lookup name="schema" type="GSettings">
|
||||
<lookup name="item">expander</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<child>
|
||||
<object class="GtkColumnView" id="columnview">
|
||||
<child>
|
||||
<object class="GtkColumnViewColumn">
|
||||
<property name="title">Name</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<binding name="label">
|
||||
<lookup name="name" type="SettingsKey">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColumnViewColumn">
|
||||
<property name="title">Value</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<binding name="label">
|
||||
<lookup name="value" type="SettingsKey">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
316
demos/gtk-demo/listview_weather.c
Normal file
316
demos/gtk-demo/listview_weather.c
Normal file
@@ -0,0 +1,316 @@
|
||||
/* Lists/Weather
|
||||
*
|
||||
* This demo shows a few of the rarer features of GtkListView and
|
||||
* how they can be used to display weather information.
|
||||
*
|
||||
* The hourly weather info uses a horizontal listview. This is easy
|
||||
* to achieve because GtkListView implements the GtkOrientable interface.
|
||||
*
|
||||
* To make the items in the list stand out more, the listview uses
|
||||
* separators.
|
||||
*
|
||||
* A GtkNoSelectionModel is used to make sure no item in the list can be
|
||||
* selected. All other interactions with the items is still possible.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#define GTK_TYPE_WEATHER_INFO (gtk_weather_info_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GtkWeatherInfo, gtk_weather_info, GTK, WEATHER_INFO, GObject)
|
||||
|
||||
typedef enum {
|
||||
GTK_WEATHER_CLEAR,
|
||||
GTK_WEATHER_FEW_CLOUDS,
|
||||
GTK_WEATHER_FOG,
|
||||
GTK_WEATHER_OVERCAST,
|
||||
GTK_WEATHER_SCATTERED_SHOWERS,
|
||||
GTK_WEATHER_SHOWERS,
|
||||
GTK_WEATHER_SNOW,
|
||||
GTK_WEATHER_STORM
|
||||
} GtkWeatherType;
|
||||
|
||||
struct _GtkWeatherInfo
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
gint64 timestamp;
|
||||
int temperature;
|
||||
GtkWeatherType weather_type;
|
||||
};
|
||||
|
||||
struct _GtkWeatherInfoClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
static void
|
||||
gtk_weather_info_class_init (GtkWeatherInfoClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_weather_info_init (GtkWeatherInfo *self)
|
||||
{
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE (GtkWeatherInfo, gtk_weather_info, G_TYPE_OBJECT);
|
||||
|
||||
static GtkWeatherInfo *
|
||||
gtk_weather_info_new (GDateTime *timestamp,
|
||||
GtkWeatherInfo *copy_from)
|
||||
{
|
||||
GtkWeatherInfo *result;
|
||||
|
||||
result = g_object_new (GTK_TYPE_WEATHER_INFO, NULL);
|
||||
|
||||
result->timestamp = g_date_time_to_unix (timestamp);
|
||||
if (copy_from)
|
||||
{
|
||||
result->temperature = copy_from->temperature;
|
||||
result->weather_type = copy_from->weather_type;
|
||||
g_object_unref (copy_from);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static GDateTime *
|
||||
parse_timestamp (const char *string,
|
||||
GTimeZone *timezone)
|
||||
{
|
||||
char *with_seconds;
|
||||
GDateTime *result;
|
||||
|
||||
with_seconds = g_strconcat (string, ":00", NULL);
|
||||
result = g_date_time_new_from_iso8601 (with_seconds, timezone);
|
||||
g_free (with_seconds);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static GtkWeatherType
|
||||
parse_weather_type (const char *clouds,
|
||||
const char *precip,
|
||||
GtkWeatherType fallback)
|
||||
{
|
||||
if (strstr (precip, "SN"))
|
||||
return GTK_WEATHER_SNOW;
|
||||
|
||||
if (strstr (precip, "TS"))
|
||||
return GTK_WEATHER_STORM;
|
||||
|
||||
if (strstr (precip, "DZ"))
|
||||
return GTK_WEATHER_SCATTERED_SHOWERS;
|
||||
|
||||
if (strstr (precip, "SH") || strstr (precip, "RA"))
|
||||
return GTK_WEATHER_SHOWERS;
|
||||
|
||||
if (strstr (precip, "FG"))
|
||||
return GTK_WEATHER_FOG;
|
||||
|
||||
if (g_str_equal (clouds, "M") ||
|
||||
g_str_equal (clouds, ""))
|
||||
return fallback;
|
||||
|
||||
if (strstr (clouds, "OVC") ||
|
||||
strstr (clouds, "BKN"))
|
||||
return GTK_WEATHER_OVERCAST;
|
||||
|
||||
if (strstr (clouds, "BKN") ||
|
||||
strstr (clouds, "SCT"))
|
||||
return GTK_WEATHER_FEW_CLOUDS;
|
||||
|
||||
if (strstr (clouds, "VV"))
|
||||
return GTK_WEATHER_FOG;
|
||||
|
||||
return GTK_WEATHER_CLEAR;
|
||||
}
|
||||
|
||||
static double
|
||||
parse_temperature (const char *s,
|
||||
double fallback)
|
||||
{
|
||||
char *endptr;
|
||||
double d;
|
||||
|
||||
d = g_ascii_strtod (s, &endptr);
|
||||
if (*endptr != '\0')
|
||||
return fallback;
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
static GListModel *
|
||||
create_weather_model (void)
|
||||
{
|
||||
GListStore *store;
|
||||
GTimeZone *utc;
|
||||
GDateTime *timestamp;
|
||||
GtkWeatherInfo *info;
|
||||
GBytes *data;
|
||||
char **lines;
|
||||
guint i;
|
||||
|
||||
store = g_list_store_new (GTK_TYPE_WEATHER_INFO);
|
||||
data = g_resources_lookup_data ("/listview_weather/listview_weather.txt", 0, NULL);
|
||||
lines = g_strsplit (g_bytes_get_data (data, NULL), "\n", 0);
|
||||
|
||||
utc = g_time_zone_new_utc ();
|
||||
timestamp = g_date_time_new (utc, 2011, 1, 1, 0, 0, 0);
|
||||
info = gtk_weather_info_new (timestamp, NULL);
|
||||
g_list_store_append (store, info);
|
||||
|
||||
for (i = 0; lines[i] != NULL && *lines[i]; i++)
|
||||
{
|
||||
char **fields;
|
||||
GDateTime *date;
|
||||
|
||||
fields = g_strsplit (lines[i], ",", 0);
|
||||
date = parse_timestamp (fields[0], utc);
|
||||
while (g_date_time_difference (date, timestamp) > 30 * G_TIME_SPAN_MINUTE)
|
||||
{
|
||||
GDateTime *new_timestamp = g_date_time_add_hours (timestamp, 1);
|
||||
g_date_time_unref (timestamp);
|
||||
timestamp = new_timestamp;
|
||||
info = gtk_weather_info_new (timestamp, info);
|
||||
g_list_store_append (store, info);
|
||||
}
|
||||
|
||||
info->temperature = parse_temperature (fields[1], info->temperature);
|
||||
info->weather_type = parse_weather_type (fields[2], fields[3], info->weather_type);
|
||||
g_date_time_unref (date);
|
||||
g_strfreev (fields);
|
||||
}
|
||||
|
||||
g_strfreev (lines);
|
||||
g_bytes_unref (data);
|
||||
g_time_zone_unref (utc);
|
||||
|
||||
return G_LIST_MODEL (store);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_widget (GtkListItem *list_item,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkWidget *box, *child;
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_list_item_set_child (list_item, box);
|
||||
|
||||
child = gtk_label_new (NULL);
|
||||
gtk_label_set_width_chars (GTK_LABEL (child), 5);
|
||||
gtk_container_add (GTK_CONTAINER (box), child);
|
||||
|
||||
child = gtk_image_new ();
|
||||
gtk_image_set_icon_size (GTK_IMAGE (child), GTK_ICON_SIZE_LARGE);
|
||||
gtk_container_add (GTK_CONTAINER (box), child);
|
||||
|
||||
child = gtk_label_new (NULL);
|
||||
gtk_widget_set_vexpand (child, TRUE);
|
||||
gtk_widget_set_valign (child, GTK_ALIGN_END);
|
||||
gtk_label_set_width_chars (GTK_LABEL (child), 4);
|
||||
gtk_container_add (GTK_CONTAINER (box), child);
|
||||
}
|
||||
|
||||
static void
|
||||
bind_widget (GtkListItem *list_item,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkWidget *box, *child;
|
||||
GtkWeatherInfo *info;
|
||||
GDateTime *timestamp;
|
||||
char *s;
|
||||
|
||||
box = gtk_list_item_get_child (list_item);
|
||||
info = gtk_list_item_get_item (list_item);
|
||||
|
||||
child = gtk_widget_get_first_child (box);
|
||||
timestamp = g_date_time_new_from_unix_utc (info->timestamp);
|
||||
s = g_date_time_format (timestamp, "%R");
|
||||
gtk_label_set_text (GTK_LABEL (child), s);
|
||||
g_free (s);
|
||||
g_date_time_unref (timestamp);
|
||||
|
||||
child = gtk_widget_get_next_sibling (child);
|
||||
switch (info->weather_type)
|
||||
{
|
||||
case GTK_WEATHER_CLEAR:
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-clear-symbolic");
|
||||
break;
|
||||
case GTK_WEATHER_FEW_CLOUDS:
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-few-clouds-symbolic");
|
||||
break;
|
||||
case GTK_WEATHER_FOG:
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-fog-symbolic");
|
||||
break;
|
||||
case GTK_WEATHER_OVERCAST:
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-overcast-symbolic");
|
||||
break;
|
||||
case GTK_WEATHER_SCATTERED_SHOWERS:
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-showers-scattered-symbolic");
|
||||
break;
|
||||
case GTK_WEATHER_SHOWERS:
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-showers-symbolic");
|
||||
break;
|
||||
case GTK_WEATHER_SNOW:
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-snow-symbolic");
|
||||
break;
|
||||
case GTK_WEATHER_STORM:
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-storm-symbolic");
|
||||
break;
|
||||
default:
|
||||
gtk_image_clear (GTK_IMAGE (child));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
child = gtk_widget_get_next_sibling (child);
|
||||
s = g_strdup_printf ("%d°", info->temperature);
|
||||
gtk_label_set_text (GTK_LABEL (child), s);
|
||||
g_free (s);
|
||||
}
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
GtkWidget *
|
||||
do_listview_weather (GtkWidget *do_widget)
|
||||
{
|
||||
if (window == NULL)
|
||||
{
|
||||
GtkWidget *listview, *sw;;
|
||||
GListModel *model, *selection;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Weather");
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK(gtk_widget_destroyed), &window);
|
||||
|
||||
sw = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), sw);
|
||||
|
||||
listview = gtk_list_view_new_with_factory (
|
||||
gtk_functions_list_item_factory_new (setup_widget,
|
||||
bind_widget,
|
||||
NULL, NULL));
|
||||
gtk_orientable_set_orientation (GTK_ORIENTABLE (listview), GTK_ORIENTATION_HORIZONTAL);
|
||||
gtk_list_view_set_show_separators (GTK_LIST_VIEW (listview), TRUE);
|
||||
model = create_weather_model ();
|
||||
selection = G_LIST_MODEL (gtk_no_selection_new (model));
|
||||
gtk_list_view_set_model (GTK_LIST_VIEW (listview), selection);
|
||||
g_object_unref (selection);
|
||||
g_object_unref (model);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (sw), listview);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
70116
demos/gtk-demo/listview_weather.txt
Normal file
70116
demos/gtk-demo/listview_weather.txt
Normal file
File diff suppressed because it is too large
Load Diff
22
demos/gtk-demo/main-listitem.ui
Normal file
22
demos/gtk-demo/main-listitem.ui
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkTreeExpander" id="expander">
|
||||
<binding name="list-row">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</binding>
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">start</property>
|
||||
<binding name="label">
|
||||
<lookup name="title" type="GtkDemo">
|
||||
<lookup name="item">expander</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
@@ -8,6 +8,7 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#include "award.h"
|
||||
#include "demos.h"
|
||||
|
||||
static GtkWidget *info_view;
|
||||
@@ -15,19 +16,99 @@ static GtkWidget *source_view;
|
||||
|
||||
static gchar *current_file = NULL;
|
||||
|
||||
static GtkWidget *window;
|
||||
static GtkWidget *notebook;
|
||||
static GtkWidget *treeview;
|
||||
static GtkWidget *listview;
|
||||
static GtkSingleSelection *selection;
|
||||
static GtkWidget *headerbar;
|
||||
|
||||
enum {
|
||||
NAME_COLUMN,
|
||||
TITLE_COLUMN,
|
||||
FILENAME_COLUMN,
|
||||
FUNC_COLUMN,
|
||||
STYLE_COLUMN,
|
||||
NUM_COLUMNS
|
||||
typedef struct _GtkDemo GtkDemo;
|
||||
struct _GtkDemo
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
const char *name;
|
||||
const char *title;
|
||||
const char *filename;
|
||||
GDoDemoFunc func;
|
||||
GListModel *children_model;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_FILENAME,
|
||||
PROP_NAME,
|
||||
PROP_TITLE,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
# define GTK_TYPE_DEMO (gtk_demo_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (GtkDemo, gtk_demo, GTK, DEMO, GObject);
|
||||
|
||||
G_DEFINE_TYPE (GtkDemo, gtk_demo, G_TYPE_OBJECT);
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
gtk_demo_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkDemo *self = GTK_DEMO (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_FILENAME:
|
||||
g_value_set_string (value, self->filename);
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, self->name);
|
||||
break;
|
||||
|
||||
case PROP_TITLE:
|
||||
g_value_set_string (value, self->title);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void gtk_demo_class_init (GtkDemoClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->get_property = gtk_demo_get_property;
|
||||
|
||||
properties[PROP_FILENAME] =
|
||||
g_param_spec_string ("filename",
|
||||
"filename",
|
||||
"filename",
|
||||
NULL,
|
||||
G_PARAM_READABLE);
|
||||
properties[PROP_NAME] =
|
||||
g_param_spec_string ("name",
|
||||
"name",
|
||||
"name",
|
||||
NULL,
|
||||
G_PARAM_READABLE);
|
||||
properties[PROP_TITLE] =
|
||||
g_param_spec_string ("title",
|
||||
"title",
|
||||
"title",
|
||||
NULL,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void gtk_demo_init (GtkDemo *self)
|
||||
{
|
||||
}
|
||||
|
||||
typedef struct _CallbackData CallbackData;
|
||||
struct _CallbackData
|
||||
{
|
||||
@@ -35,6 +116,27 @@ struct _CallbackData
|
||||
GtkTreePath *path;
|
||||
};
|
||||
|
||||
static gboolean
|
||||
gtk_demo_run (GtkDemo *self,
|
||||
GtkWidget *window)
|
||||
{
|
||||
GtkWidget *result;
|
||||
|
||||
if (!self->func)
|
||||
return FALSE;
|
||||
|
||||
result = self->func (window);
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
activate_about (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
@@ -111,69 +213,7 @@ activate_inspector (GSimpleAction *action,
|
||||
gpointer user_data)
|
||||
{
|
||||
gtk_window_set_interactive_debugging (TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
window_closed_cb (GtkWidget *window, gpointer data)
|
||||
{
|
||||
CallbackData *cbdata = data;
|
||||
GtkTreeIter iter;
|
||||
PangoStyle style;
|
||||
|
||||
gtk_tree_model_get_iter (cbdata->model, &iter, cbdata->path);
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (cbdata->model), &iter,
|
||||
STYLE_COLUMN, &style,
|
||||
-1);
|
||||
if (style == PANGO_STYLE_ITALIC)
|
||||
gtk_tree_store_set (GTK_TREE_STORE (cbdata->model), &iter,
|
||||
STYLE_COLUMN, PANGO_STYLE_NORMAL,
|
||||
-1);
|
||||
|
||||
gtk_tree_path_free (cbdata->path);
|
||||
g_free (cbdata);
|
||||
}
|
||||
|
||||
static void
|
||||
run_example_for_row (GtkWidget *window,
|
||||
GtkTreeModel *model,
|
||||
GtkTreeIter *iter)
|
||||
{
|
||||
PangoStyle style;
|
||||
GDoDemoFunc func;
|
||||
GtkWidget *demo;
|
||||
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (model),
|
||||
iter,
|
||||
FUNC_COLUMN, &func,
|
||||
STYLE_COLUMN, &style,
|
||||
-1);
|
||||
|
||||
if (func)
|
||||
{
|
||||
gtk_tree_store_set (GTK_TREE_STORE (model),
|
||||
iter,
|
||||
STYLE_COLUMN, (style == PANGO_STYLE_ITALIC ? PANGO_STYLE_NORMAL : PANGO_STYLE_ITALIC),
|
||||
-1);
|
||||
demo = (func) (window);
|
||||
|
||||
if (demo != NULL)
|
||||
{
|
||||
CallbackData *cbdata;
|
||||
|
||||
cbdata = g_new (CallbackData, 1);
|
||||
cbdata->model = model;
|
||||
cbdata->path = gtk_tree_model_get_path (model, iter);
|
||||
|
||||
if (GTK_IS_WINDOW (demo))
|
||||
{
|
||||
gtk_window_set_transient_for (GTK_WINDOW (demo), GTK_WINDOW (window));
|
||||
gtk_window_set_modal (GTK_WINDOW (demo), TRUE);
|
||||
}
|
||||
|
||||
g_signal_connect (demo, "destroy",
|
||||
G_CALLBACK (window_closed_cb), cbdata);
|
||||
}
|
||||
}
|
||||
award ("demo-inspector");
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -181,14 +221,10 @@ activate_run (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkWidget *window = user_data;
|
||||
GtkTreeSelection *selection;
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
GtkTreeListRow *row = gtk_single_selection_get_selected_item (selection);
|
||||
GtkDemo *demo = gtk_tree_list_row_get_item (row);
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
|
||||
if (gtk_tree_selection_get_selected (selection, &model, &iter))
|
||||
run_example_for_row (window, model, &iter);
|
||||
gtk_demo_run (demo, window);
|
||||
}
|
||||
|
||||
/* Stupid syntax highlighting.
|
||||
@@ -205,14 +241,14 @@ enum {
|
||||
STATE_IN_COMMENT
|
||||
};
|
||||
|
||||
static const char *tokens[] =
|
||||
static gchar *tokens[] =
|
||||
{
|
||||
"/*",
|
||||
"\"",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *types[] =
|
||||
static gchar *types[] =
|
||||
{
|
||||
"static",
|
||||
"const ",
|
||||
@@ -310,6 +346,7 @@ static const char *types[] =
|
||||
"GtkIconView ",
|
||||
"GtkCellRendererText ",
|
||||
"GtkContainer ",
|
||||
"GtkAccelGroup ",
|
||||
"GtkPaned ",
|
||||
"GtkPrintOperation ",
|
||||
"GtkPrintContext ",
|
||||
@@ -336,7 +373,7 @@ static const char *types[] =
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *control[] =
|
||||
static gchar *control[] =
|
||||
{
|
||||
" if ",
|
||||
" while ",
|
||||
@@ -350,11 +387,11 @@ static const char *control[] =
|
||||
NULL
|
||||
};
|
||||
void
|
||||
parse_chars (gchar *text,
|
||||
gchar **end_ptr,
|
||||
gint *state,
|
||||
const char **tag,
|
||||
gboolean start)
|
||||
parse_chars (gchar *text,
|
||||
gchar **end_ptr,
|
||||
gint *state,
|
||||
gchar **tag,
|
||||
gboolean start)
|
||||
{
|
||||
gint i;
|
||||
gchar *next_token;
|
||||
@@ -493,7 +530,7 @@ fontify (GtkTextBuffer *source_buffer)
|
||||
gint state;
|
||||
gchar *text;
|
||||
gchar *start_ptr, *end_ptr;
|
||||
const char *tag;
|
||||
gchar *tag;
|
||||
|
||||
gtk_text_buffer_create_tag (source_buffer, "source",
|
||||
"font", "monospace",
|
||||
@@ -867,7 +904,7 @@ load_file (const gchar *demoname,
|
||||
|
||||
p = lines[i];
|
||||
state++;
|
||||
G_GNUC_FALLTHROUGH;
|
||||
/* Fall through */
|
||||
|
||||
case 3:
|
||||
/* Reading program body */
|
||||
@@ -875,9 +912,6 @@ load_file (const gchar *demoname,
|
||||
if (lines[i+1] != NULL)
|
||||
gtk_text_buffer_insert (source_buffer, &start, "\n", 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -895,81 +929,72 @@ load_file (const gchar *demoname,
|
||||
}
|
||||
|
||||
static void
|
||||
selection_cb (GtkTreeSelection *selection,
|
||||
GtkTreeModel *model)
|
||||
|
||||
selection_cb (GtkSingleSelection *selection,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
char *name;
|
||||
char *filename;
|
||||
char *title;
|
||||
GtkTreeListRow *row = gtk_single_selection_get_selected_item (selection);
|
||||
GtkDemo *demo = gtk_tree_list_row_get_item (row);
|
||||
|
||||
if (! gtk_tree_selection_get_selected (selection, NULL, &iter))
|
||||
return;
|
||||
if (demo->filename)
|
||||
load_file (demo->name, demo->filename);
|
||||
|
||||
gtk_tree_model_get (model, &iter,
|
||||
NAME_COLUMN, &name,
|
||||
TITLE_COLUMN, &title,
|
||||
FILENAME_COLUMN, &filename,
|
||||
-1);
|
||||
|
||||
if (filename)
|
||||
load_file (name, filename);
|
||||
|
||||
gtk_header_bar_set_title (GTK_HEADER_BAR (headerbar), title);
|
||||
|
||||
g_free (name);
|
||||
g_free (title);
|
||||
g_free (filename);
|
||||
gtk_header_bar_set_title (GTK_HEADER_BAR (headerbar), demo->title);
|
||||
}
|
||||
|
||||
static void
|
||||
populate_model (GtkTreeModel *model)
|
||||
static GListModel *
|
||||
create_demo_model (void)
|
||||
{
|
||||
Demo *d = gtk_demos;
|
||||
GListStore *store = g_list_store_new (GTK_TYPE_DEMO);
|
||||
DemoData *demo = gtk_demos;
|
||||
|
||||
/* this code only supports 1 level of children. If we
|
||||
* want more we probably have to use a recursing function.
|
||||
*/
|
||||
while (d->title)
|
||||
while (demo->title)
|
||||
{
|
||||
Demo *children = d->children;
|
||||
GtkTreeIter iter;
|
||||
GtkDemo *d = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
|
||||
DemoData *children = demo->children;
|
||||
|
||||
gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
|
||||
d->name = demo->name;
|
||||
d->title = demo->title;
|
||||
d->filename = demo->filename;
|
||||
d->func = demo->func;
|
||||
|
||||
gtk_tree_store_set (GTK_TREE_STORE (model),
|
||||
&iter,
|
||||
NAME_COLUMN, d->name,
|
||||
TITLE_COLUMN, d->title,
|
||||
FILENAME_COLUMN, d->filename,
|
||||
FUNC_COLUMN, d->func,
|
||||
STYLE_COLUMN, PANGO_STYLE_NORMAL,
|
||||
-1);
|
||||
g_list_store_append (store, d);
|
||||
|
||||
d++;
|
||||
|
||||
if (!children)
|
||||
continue;
|
||||
|
||||
while (children->title)
|
||||
if (children)
|
||||
{
|
||||
GtkTreeIter child_iter;
|
||||
d->children_model = G_LIST_MODEL (g_list_store_new (GTK_TYPE_DEMO));
|
||||
|
||||
gtk_tree_store_append (GTK_TREE_STORE (model), &child_iter, &iter);
|
||||
while (children->title)
|
||||
{
|
||||
GtkDemo *child = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
|
||||
|
||||
gtk_tree_store_set (GTK_TREE_STORE (model),
|
||||
&child_iter,
|
||||
NAME_COLUMN, children->name,
|
||||
TITLE_COLUMN, children->title,
|
||||
FILENAME_COLUMN, children->filename,
|
||||
FUNC_COLUMN, children->func,
|
||||
STYLE_COLUMN, PANGO_STYLE_NORMAL,
|
||||
-1);
|
||||
child->name = children->name;
|
||||
child->title = children->title;
|
||||
child->filename = children->filename;
|
||||
child->func = children->func;
|
||||
|
||||
children++;
|
||||
g_list_store_append (G_LIST_STORE (d->children_model), child);
|
||||
children++;
|
||||
}
|
||||
}
|
||||
|
||||
demo++;
|
||||
}
|
||||
|
||||
return G_LIST_MODEL (store);
|
||||
}
|
||||
|
||||
static GListModel *
|
||||
get_child_model (gpointer item,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkDemo *demo = item;
|
||||
|
||||
if (demo->children_model)
|
||||
return g_object_ref (G_LIST_MODEL (demo->children_model));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -977,7 +1002,7 @@ startup (GApplication *app)
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
GMenuModel *appmenu;
|
||||
const char *ids[] = { "appmenu", NULL };
|
||||
gchar *ids[] = { "appmenu", NULL };
|
||||
|
||||
builder = gtk_builder_new ();
|
||||
gtk_builder_add_objects_from_resource (builder, "/ui/appmenu.ui", ids, NULL);
|
||||
@@ -990,29 +1015,52 @@ startup (GApplication *app)
|
||||
}
|
||||
|
||||
static void
|
||||
row_activated_cb (GtkWidget *tree_view,
|
||||
GtkTreePath *path,
|
||||
GtkTreeViewColumn *column)
|
||||
start_cb (GtkMenuItem *item, GtkWidget *scrollbar)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
GtkWidget *window;
|
||||
GtkTreeModel *model;
|
||||
GtkAdjustment *adj;
|
||||
|
||||
window = GTK_WIDGET (gtk_widget_get_root (tree_view));
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
|
||||
gtk_tree_model_get_iter (model, &iter, path);
|
||||
adj = gtk_scrollbar_get_adjustment (GTK_SCROLLBAR (scrollbar));
|
||||
gtk_adjustment_set_value (adj, gtk_adjustment_get_lower (adj));
|
||||
}
|
||||
|
||||
run_example_for_row (window, model, &iter);
|
||||
static void
|
||||
end_cb (GtkMenuItem *item, GtkWidget *scrollbar)
|
||||
{
|
||||
GtkAdjustment *adj;
|
||||
|
||||
adj = gtk_scrollbar_get_adjustment (GTK_SCROLLBAR (scrollbar));
|
||||
gtk_adjustment_set_value (adj, gtk_adjustment_get_upper (adj) - gtk_adjustment_get_page_size (adj));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
scrollbar_popup (GtkWidget *scrollbar, GtkWidget *menu)
|
||||
{
|
||||
gtk_menu_popup_at_pointer (GTK_MENU (menu), NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
main_activate_cb (GtkListView *listview,
|
||||
guint position,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkTreeListRow *row = g_list_model_get_item (gtk_list_view_get_model (listview), position);
|
||||
GtkDemo *demo = gtk_tree_list_row_get_item (row);
|
||||
|
||||
gtk_demo_run (demo, window);
|
||||
}
|
||||
|
||||
static void
|
||||
activate (GApplication *app)
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
GtkWindow *window;
|
||||
GtkWidget *widget;
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
GtkWidget *sw;
|
||||
GtkWidget *scrollbar;
|
||||
GtkWidget *menu;
|
||||
GtkWidget *item;
|
||||
GListModel *listmodel;
|
||||
GtkTreeListModel *treemodel;
|
||||
|
||||
static GActionEntry win_entries[] = {
|
||||
{ "run", activate_run, NULL, NULL, NULL }
|
||||
@@ -1020,8 +1068,8 @@ activate (GApplication *app)
|
||||
|
||||
builder = gtk_builder_new_from_resource ("/ui/main.ui");
|
||||
|
||||
window = (GtkWindow *)gtk_builder_get_object (builder, "window");
|
||||
gtk_application_add_window (GTK_APPLICATION (app), window);
|
||||
window = (GtkWidget *)gtk_builder_get_object (builder, "window");
|
||||
gtk_application_add_window (GTK_APPLICATION (app), GTK_WINDOW (window));
|
||||
g_action_map_add_action_entries (G_ACTION_MAP (window),
|
||||
win_entries, G_N_ELEMENTS (win_entries),
|
||||
window);
|
||||
@@ -1031,22 +1079,38 @@ activate (GApplication *app)
|
||||
info_view = (GtkWidget *)gtk_builder_get_object (builder, "info-textview");
|
||||
source_view = (GtkWidget *)gtk_builder_get_object (builder, "source-textview");
|
||||
headerbar = (GtkWidget *)gtk_builder_get_object (builder, "headerbar");
|
||||
treeview = (GtkWidget *)gtk_builder_get_object (builder, "treeview");
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
|
||||
listview = (GtkWidget *)gtk_builder_get_object (builder, "listview");
|
||||
|
||||
sw = (GtkWidget *)gtk_builder_get_object (builder, "source-scrolledwindow");
|
||||
scrollbar = gtk_scrolled_window_get_vscrollbar (GTK_SCROLLED_WINDOW (sw));
|
||||
|
||||
menu = gtk_menu_new ();
|
||||
|
||||
item = gtk_menu_item_new_with_label ("Start");
|
||||
g_signal_connect (item, "activate", G_CALLBACK (start_cb), scrollbar);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
||||
|
||||
item = gtk_menu_item_new_with_label ("End");
|
||||
g_signal_connect (item, "activate", G_CALLBACK (end_cb), scrollbar);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
||||
|
||||
g_signal_connect (scrollbar, "popup-menu", G_CALLBACK (scrollbar_popup), menu);
|
||||
|
||||
load_file (gtk_demos[0].name, gtk_demos[0].filename);
|
||||
|
||||
populate_model (model);
|
||||
listmodel = create_demo_model ();
|
||||
treemodel = gtk_tree_list_model_new (FALSE,
|
||||
G_LIST_MODEL (listmodel),
|
||||
FALSE,
|
||||
get_child_model,
|
||||
NULL,
|
||||
NULL);
|
||||
selection = gtk_single_selection_new (G_LIST_MODEL (treemodel));
|
||||
g_signal_connect (selection, "notify::selected-item", G_CALLBACK (selection_cb), NULL);
|
||||
gtk_list_view_set_model (GTK_LIST_VIEW (listview),
|
||||
G_LIST_MODEL (selection));
|
||||
|
||||
g_signal_connect (treeview, "row-activated", G_CALLBACK (row_activated_cb), model);
|
||||
|
||||
widget = (GtkWidget *)gtk_builder_get_object (builder, "treeview-selection");
|
||||
g_signal_connect (widget, "changed", G_CALLBACK (selection_cb), model);
|
||||
|
||||
gtk_tree_model_get_iter_first (gtk_tree_view_get_model (GTK_TREE_VIEW (treeview)), &iter);
|
||||
gtk_tree_selection_select_iter (GTK_TREE_SELECTION (widget), &iter);
|
||||
|
||||
gtk_tree_view_collapse_all (GTK_TREE_VIEW (treeview));
|
||||
award ("demo-start");
|
||||
|
||||
gtk_widget_show (GTK_WIDGET (window));
|
||||
|
||||
@@ -1063,7 +1127,7 @@ auto_quit (gpointer data)
|
||||
static void
|
||||
list_demos (void)
|
||||
{
|
||||
Demo *d, *c;
|
||||
DemoData *d, *c;
|
||||
|
||||
d = gtk_demos;
|
||||
|
||||
@@ -1090,7 +1154,7 @@ command_line (GApplication *app,
|
||||
const gchar *name = NULL;
|
||||
gboolean autoquit = FALSE;
|
||||
gboolean list = FALSE;
|
||||
Demo *d, *c;
|
||||
DemoData *d, *c;
|
||||
GDoDemoFunc func = 0;
|
||||
GtkWidget *window, *demo;
|
||||
|
||||
|
@@ -65,32 +65,15 @@
|
||||
<property name="can-focus">1</property>
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="min-content-width">150</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkTreeView" id="treeview">
|
||||
<property name="can-focus">1</property>
|
||||
<property name="model">treestore</property>
|
||||
<property name="headers-visible">0</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection" id="treeview-selection">
|
||||
<property name="mode">browse</property>
|
||||
<object class="GtkListView" id="listview">
|
||||
<signal name="activate" handler="main_activate_cb" swapped="no" />
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="resource">/ui/main-listitem.ui</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<child>
|
||||
<object class="GtkCellRendererText"/>
|
||||
<attributes>
|
||||
<attribute name="style">4</attribute>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="text"> </property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@@ -103,8 +86,7 @@
|
||||
<property name="scrollable">1</property>
|
||||
<property name="enable-popup">1</property>
|
||||
<property name="show-border">0</property>
|
||||
<property name="hexpand">1</property>
|
||||
<property name="vexpand">1</property>
|
||||
<property name="expand">1</property>
|
||||
<child>
|
||||
<object class="GtkNotebookPage">
|
||||
<property name="tab-expand">1</property>
|
||||
|
@@ -54,7 +54,7 @@ do_markup (GtkWidget *do_widget)
|
||||
GtkWidget *header;
|
||||
GtkWidget *show_source;
|
||||
|
||||
window = gtk_window_new ();
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 450, 450);
|
||||
@@ -78,7 +78,7 @@ do_markup (GtkWidget *do_widget)
|
||||
|
||||
view = gtk_text_view_new ();
|
||||
gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE);
|
||||
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD_CHAR);
|
||||
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD);
|
||||
gtk_text_view_set_left_margin (GTK_TEXT_VIEW (view), 10);
|
||||
gtk_text_view_set_right_margin (GTK_TEXT_VIEW (view), 10);
|
||||
|
||||
|
@@ -14,7 +14,3 @@ Superscripts and subscripts: 𝜀<span rise="-6000" size="x-small" font_desc="it
|
||||
OpenType font features: <span font_desc="sans regular" font_features="dlig=0">feast</span> versus <span font_desc="sans regular" font_features="dlig=1">feast</span>
|
||||
|
||||
Shortcuts: <tt>Monospace</tt> – <b>Bold</b> – <i>Italic</i> – <big>Big</big> – <small>Small</small> – <u>Underlined</u> – <s>Strikethrough</s> – Super<sup>script</sup> – Sub<sub>script</sub>
|
||||
|
||||
<span allow_breaks="false">A</span> hyphenation algorithm is a set of rules, especially one codified for implementation in a computer program, that decides at which points a word can be broken over two lines with a hyphen. For example, a hyphenation algorithm might decide that impeachment can be broken as <span allow_breaks="false">impeach‧ment</span> or <span allow_breaks="false">im‧peachment</span> but not <span allow_breaks="false">impe‧achment.</span>
|
||||
|
||||
<span insert_hyphens="false">one/two three/four five/six seven/eight nine/ten</span>
|
||||
|
147
demos/gtk-demo/menus.c
Normal file
147
demos/gtk-demo/menus.c
Normal file
@@ -0,0 +1,147 @@
|
||||
/* Menus
|
||||
*
|
||||
* There are several widgets involved in displaying menus. The
|
||||
* GtkMenuBar widget is a menu bar, which normally appears horizontally
|
||||
* at the top of an application, but can also be layed out vertically.
|
||||
* The GtkMenu widget is the actual menu that pops up. Both GtkMenuBar
|
||||
* and GtkMenu are subclasses of GtkMenuShell; a GtkMenuShell contains
|
||||
* menu items (GtkMenuItem). Each menu item contains text and/or images
|
||||
* and can be selected by the user.
|
||||
*
|
||||
* There are several kinds of menu item, including plain GtkMenuItem,
|
||||
* GtkCheckMenuItem which can be checked/unchecked, GtkRadioMenuItem
|
||||
* which is a check menu item that's in a mutually exclusive group,
|
||||
* GtkSeparatorMenuItem which is a separator bar, GtkTearoffMenuItem
|
||||
* which allows a GtkMenu to be torn off, and GtkImageMenuItem which
|
||||
* can place a GtkImage or other widget next to the menu text.
|
||||
*
|
||||
* A GtkMenuItem can have a submenu, which is simply a GtkMenu to pop
|
||||
* up when the menu item is selected. Typically, all menu items in a menu bar
|
||||
* have submenus.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
static GtkWidget *
|
||||
create_menu (gint depth)
|
||||
{
|
||||
GtkWidget *menu;
|
||||
GtkRadioMenuItem *last_item;
|
||||
char buf[32];
|
||||
int i, j;
|
||||
|
||||
if (depth < 1)
|
||||
return NULL;
|
||||
|
||||
menu = gtk_menu_new ();
|
||||
last_item = NULL;
|
||||
|
||||
for (i = 0, j = 1; i < 5; i++, j++)
|
||||
{
|
||||
GtkWidget *menu_item;
|
||||
|
||||
sprintf (buf, "item %2d - %d", depth, j);
|
||||
|
||||
menu_item = gtk_radio_menu_item_new_with_label_from_widget (NULL, buf);
|
||||
gtk_radio_menu_item_join_group (GTK_RADIO_MENU_ITEM (menu_item), last_item);
|
||||
last_item = GTK_RADIO_MENU_ITEM (menu_item);
|
||||
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
|
||||
gtk_widget_show (menu_item);
|
||||
if (i == 3)
|
||||
gtk_widget_set_sensitive (menu_item, FALSE);
|
||||
|
||||
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), create_menu (depth - 1));
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
static void
|
||||
change_orientation (GtkWidget *button,
|
||||
GtkWidget *menubar)
|
||||
{
|
||||
GtkWidget *parent;
|
||||
GtkOrientation orientation;
|
||||
|
||||
parent = gtk_widget_get_parent (menubar);
|
||||
orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (parent));
|
||||
gtk_orientable_set_orientation (GTK_ORIENTABLE (parent), 1 - orientation);
|
||||
}
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
GtkWidget *
|
||||
do_menus (GtkWidget *do_widget)
|
||||
{
|
||||
GtkWidget *box;
|
||||
GtkWidget *box1;
|
||||
GtkWidget *box2;
|
||||
GtkWidget *button;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *menubar;
|
||||
GtkWidget *menu;
|
||||
GtkWidget *menuitem;
|
||||
GtkAccelGroup *accel_group;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Menus");
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK(gtk_widget_destroyed), &window);
|
||||
|
||||
accel_group = gtk_accel_group_new ();
|
||||
gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_container_add (GTK_CONTAINER (window), box);
|
||||
|
||||
box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_container_add (GTK_CONTAINER (box), box1);
|
||||
|
||||
menubar = gtk_menu_bar_new ();
|
||||
gtk_widget_set_hexpand (menubar, TRUE);
|
||||
gtk_container_add (GTK_CONTAINER (box1), menubar);
|
||||
|
||||
menu = create_menu (2);
|
||||
|
||||
menuitem = gtk_menu_item_new_with_label ("test\nline2");
|
||||
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
|
||||
|
||||
menuitem = gtk_menu_item_new_with_label ("foo");
|
||||
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (3));
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
|
||||
|
||||
menuitem = gtk_menu_item_new_with_label ("bar");
|
||||
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (4));
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
|
||||
|
||||
box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
|
||||
gtk_container_add (GTK_CONTAINER (box1), box2);
|
||||
|
||||
button = gtk_button_new_with_label ("Flip");
|
||||
g_signal_connect (button, "clicked",
|
||||
G_CALLBACK (change_orientation), menubar);
|
||||
gtk_container_add (GTK_CONTAINER (box2), button);
|
||||
|
||||
button = gtk_button_new_with_label ("Close");
|
||||
g_signal_connect_swapped (button, "clicked",
|
||||
G_CALLBACK(gtk_widget_destroy), window);
|
||||
gtk_container_add (GTK_CONTAINER (box2), button);
|
||||
gtk_window_set_default_widget (GTK_WINDOW (window), button);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
@@ -3,7 +3,9 @@
|
||||
demos = files([
|
||||
'application_demo.c',
|
||||
'assistant.c',
|
||||
'awardview.c',
|
||||
'builder.c',
|
||||
'changedisplay.c',
|
||||
'clipboard.c',
|
||||
'colorsel.c',
|
||||
'combobox.c',
|
||||
@@ -28,6 +30,7 @@ demos = files([
|
||||
'fishbowl.c',
|
||||
'fixed.c',
|
||||
'fontrendering.c',
|
||||
'foreigndrawing.c',
|
||||
'gestures.c',
|
||||
'glarea.c',
|
||||
'headerbar.c',
|
||||
@@ -41,7 +44,14 @@ demos = files([
|
||||
'listbox.c',
|
||||
'flowbox.c',
|
||||
'list_store.c',
|
||||
'listview_applauncher.c',
|
||||
'listview_clocks.c',
|
||||
'listview_filebrowser.c',
|
||||
'listview_minesweeper.c',
|
||||
'listview_settings.c',
|
||||
'listview_weather.c',
|
||||
'markup.c',
|
||||
'menus.c',
|
||||
'modelbutton.c',
|
||||
'overlay.c',
|
||||
'overlay2.c',
|
||||
@@ -51,7 +61,6 @@ demos = files([
|
||||
'paintable_mediastream.c',
|
||||
'panes.c',
|
||||
'password_entry.c',
|
||||
'peg_solitaire.c',
|
||||
'pickers.c',
|
||||
'pixbufs.c',
|
||||
'popover.c',
|
||||
@@ -62,7 +71,6 @@ demos = files([
|
||||
'search_entry.c',
|
||||
'search_entry2.c',
|
||||
'shortcuts.c',
|
||||
'shortcut_triggers.c',
|
||||
'sidebar.c',
|
||||
'sizegroup.c',
|
||||
'sliding_puzzle.c',
|
||||
@@ -85,6 +93,7 @@ demos = files([
|
||||
gtkdemo_deps = [ libgtk_dep, ]
|
||||
|
||||
extra_demo_sources = files(['main.c',
|
||||
'award.c',
|
||||
'gtkfishbowl.c',
|
||||
'fontplane.c',
|
||||
'gtkgears.c',
|
||||
@@ -95,7 +104,7 @@ extra_demo_sources = files(['main.c',
|
||||
if harfbuzz_dep.found() and pangoft_dep.found()
|
||||
demos += files('font_features.c')
|
||||
extra_demo_sources += files(['script-names.c', 'language-names.c'])
|
||||
gtkdemo_deps += [ harfbuzz_dep, ]
|
||||
gtkdemo_deps += [ harfbuzz_dep, epoxy_dep ]
|
||||
endif
|
||||
|
||||
if os_unix
|
||||
@@ -113,16 +122,9 @@ gtkdemo_resources = gnome.compile_resources('gtkdemo_resources',
|
||||
'demo.gresource.xml',
|
||||
source_dir: '.')
|
||||
|
||||
demo_cflags = []
|
||||
foreach flag: common_cflags
|
||||
if flag not in ['-Werror=missing-prototypes', '-Werror=missing-declarations', '-fvisibility=hidden']
|
||||
demo_cflags += flag
|
||||
endif
|
||||
endforeach
|
||||
|
||||
executable('gtk4-demo',
|
||||
demos, demos_h, extra_demo_sources, gtkdemo_resources,
|
||||
c_args: gtkdemo_args + demo_cflags,
|
||||
c_args: gtkdemo_args,
|
||||
dependencies: gtkdemo_deps,
|
||||
include_directories: confinc,
|
||||
gui_app: true,
|
||||
@@ -131,7 +133,7 @@ executable('gtk4-demo',
|
||||
|
||||
executable('gtk4-demo-application',
|
||||
'application.c', gtkdemo_resources,
|
||||
c_args: gtkdemo_args + common_cflags,
|
||||
c_args: gtkdemo_args,
|
||||
dependencies: gtkdemo_deps,
|
||||
include_directories: confinc,
|
||||
gui_app: true,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user