Compare commits

..

157 Commits

Author SHA1 Message Date
Matthias Clasen 025e4721ba spin button: Drop keybinding signals 2019-06-24 22:44:31 +00:00
Matthias Clasen ab24a46310 label: Drop keybinding signals
They are no longer used.
2019-06-24 22:44:31 +00:00
Matthias Clasen c7b5e75377 label: Port bindings from signal to action 2019-06-24 22:44:31 +00:00
Matthias Clasen 130c8b1b7b label: Add a move-cursor action 2019-06-24 22:44:31 +00:00
Matthias Clasen 2a76337c82 label: Document actions 2019-06-24 22:44:31 +00:00
Matthias Clasen b38f0f67c8 label: Cosmetics
Move actions before keybindings in class init.
2019-06-24 22:44:31 +00:00
Matthias Clasen 9aebb66755 label: Stop using copy-clipboard signal
No need for a signal emission here, we can
just call the function.
2019-06-24 22:44:31 +00:00
Matthias Clasen da36d0502f window: Actually listen for focus change
Same as the previous commit: We need a bubble
phase key controller to receive focus change
events.
2019-06-24 22:44:31 +00:00
Matthias Clasen bf56f1a8c5 popovermenu: Actually listen to focus change
As it turns out, capture phase controllers
don't see any crossing events, so we need to
use separate controllers for key presses and
focus change.
2019-06-24 22:44:31 +00:00
Matthias Clasen 8cf231c3b7 window: No need to keep the key controller
We don't need access to it after creating it.
2019-06-24 22:44:31 +00:00
Matthias Clasen 2cd739ae23 popover: Actually install tab bindings 2019-06-24 22:44:31 +00:00
Matthias Clasen 5b39a06032 Drop the move-focus signal 2019-06-24 22:44:31 +00:00
Matthias Clasen 532a1c6d0d Replace move-focus signal by focus.move action 2019-06-24 22:44:31 +00:00
Matthias Clasen d1691c5a48 window: Replace enable-debugging by an action 2019-06-24 22:44:31 +00:00
Matthias Clasen 2002d49871 window: Convert activate-focus to an action 2019-06-24 22:44:31 +00:00
Matthias Clasen 14fd2ccca5 window: Document default.activate 2019-06-24 22:44:31 +00:00
Matthias Clasen 1c34d79a53 window: Drop the activate-default signal
It has been replaced by an action.
2019-06-24 22:44:31 +00:00
Matthias Clasen 3a139453c4 Remove popup-menu signal
We decided not to have generic context menu api,
so this binding is a bit out of place too. Replace
it by bindings in the individual widgets that
have context menus.
2019-06-24 22:44:31 +00:00
Matthias Clasen 3fcfcf51f6 treeview: Avoid popup-menu 2019-06-24 22:44:31 +00:00
Matthias Clasen aa04678239 scrollbar: Avoid popup-menu 2019-06-24 22:44:31 +00:00
Matthias Clasen 0dccb3de40 placesview: Avoid the use of popup-menu 2019-06-24 22:44:31 +00:00
Matthias Clasen f9c670b7c6 mountoperation: Avoid use of popup-menu 2019-06-24 22:40:29 +00:00
Matthias Clasen e40758ec26 file chooser: Avoid use of popup-menu 2019-06-24 22:40:29 +00:00
Matthias Clasen ce19f5a282 color editor: Avoid popup-menu use 2019-06-24 22:40:29 +00:00
Matthias Clasen b050572918 popover: Switch activate-default to an action
This matches what we already did for GtkWindow.
2019-06-24 22:40:29 +00:00
Matthias Clasen f6f8f4b742 shortcutaction: Just use gtk_widget_activate_action
We can just rely on this, no need to do manual
action group juggling here.
2019-06-24 22:40:29 +00:00
Matthias Clasen 318ac2f823 shortcut action: Fix a wrong cast 2019-06-24 22:40:29 +00:00
Matthias Clasen af689a2a5c tests: Skip GtkShortcutsController::model
The defaultvalue test can't handle object-valued
properties with non-NULL initial value.
2019-06-24 22:40:29 +00:00
Matthias Clasen caf73e7211 text: Documentation for actions
Add doc comments to all GtkText actions.

gtk-doc will need to learn to extract action
documentation. This is using a CLASS|action
format to differentiate actions from properties
and signals. For actions with parameters, we
use the normal gtk-doc syntax for arguments.
2019-06-24 22:40:29 +00:00
Matthias Clasen fca13bd00c introspection test: Update
GtkText has some new actions.
2019-06-24 22:40:29 +00:00
Matthias Clasen 6d4fcd9633 widget: Quiet a compiler warning 2019-06-24 22:40:29 +00:00
Matthias Clasen dfd20e037b shortcut trigger: Silence gtk-doc warnings 2019-06-24 22:40:29 +00:00
Matthias Clasen d9b771aa7f shortcut controller: Silence gtk-doc warnings 2019-06-24 22:40:29 +00:00
Matthias Clasen 7873f5c4eb shortcut action: Silence gtk-doc warnings 2019-06-24 22:40:29 +00:00
Matthias Clasen 60479bedae password entry: Silence gtk-doc warnings 2019-06-24 22:40:29 +00:00
Matthias Clasen 6b632ca139 entry: Silence gtk-doc warnings 2019-06-24 22:40:29 +00:00
Matthias Clasen a92ab66024 docs: Make the shooter build again 2019-06-24 22:40:29 +00:00
Matthias Clasen 8ab76574cd Redo default activation in entries
Remove the activates-default property in GtkText
and move this functionality to the entry wrapper
classes instead. Add an activate action and
bindings where necessary.

With this, GtkText is completely converted from
keybinding signals to actions.
2019-06-24 22:40:29 +00:00
Matthias Clasen 21e9fc054e text: Drop keybinding signals
These are not used anymore.
2019-06-24 22:40:29 +00:00
Matthias Clasen 1cbb2099a2 text: Stop using keybinding signals internally
We can just call the class handlers.
2019-06-24 22:40:29 +00:00
Matthias Clasen 7ed27ef574 text: Convert bindings to actions 2019-06-24 22:40:29 +00:00
Matthias Clasen 9039d0b0c1 text: Add more actions
These will let us port more bindings to actions.
2019-06-24 22:40:29 +00:00
Matthias Clasen 00e68fcae2 widget: Unset propagation limits for shortcut managers
These controllers are meant to be global and
thus should be able to react to events that are
getting routed to open popovers. This makes
shortcuts in open popover menus work.
2019-06-24 22:40:29 +00:00
Matthias Clasen 9038b7a8c5 widget_factory: Stop using GtkApplication for accels
We want to replace the accels APIs in GtkApplication
with shortcut controllers.
2019-06-24 22:40:29 +00:00
Matthias Clasen 0a7f5f1be1 text: Convert bindings from signals to actions
With this change, the context menu picks up the
accels for the actions. The conversion is not
complete, since we don't have actions for all
bindings yet.
2019-06-24 22:40:29 +00:00
Matthias Clasen 70597de0a5 widget: Pass shortcuts to the action muxer
Send the shortcuts used by shortcut managers
and the per-class shortcuts to the action muxer
for associating accels with actions. The
action muxer has existing machinery for propagating
accels to the UI.
2019-06-24 22:40:29 +00:00
Matthias Clasen 75b19169cf action muxer: Support injecting shortcuts
Give the action muxer an api to add list models
of shortcuts to draw accels from.
2019-06-24 22:40:29 +00:00
Matthias Clasen 390ba974df model button: Drop accel lookup hack
We were just cutting through to the application
at map time in a last-ditch effort to find
an accel to display. Drop that and just rely on
the menu tracker to give us the right thing.
2019-06-24 22:40:29 +00:00
Matthias Clasen d9167fc8d6 model button: Stop parsing accels
The new shortcuts machinery gives us formatted
strings, so just use them as-is without parsing
and reformatting.
2019-06-24 22:40:29 +00:00
Matthias Clasen d000bed15f popover menu: Make mnemonics visible
For menus, mnemonics trigger without pressing Alt,
and the expectation is that we show them whenever
keynav is happening. Reinstate this behavior for
popover menus.
2019-06-24 22:40:29 +00:00
Matthias Clasen b1ac7b667c popover menu: Implement shortcut manager
And make mnemonics trigger without Alt,
like we already do for GtkMenu.
2019-06-24 22:40:29 +00:00
Matthias Clasen b89dee2f56 shortcut controller: Factor out a helper
No need to have the same code in multiple places.
2019-06-24 22:40:29 +00:00
Matthias Clasen 0f75f33857 Implement group cycling
When more than one shortcut can trigger,
activate them non-exclusively, round-robin.
2019-06-24 22:40:29 +00:00
Matthias Clasen f41931f527 label: Remove mnemonics when unmapped
We never want mnemonics to trigger when the user
can't see them, so remove them from the shortcuts
manager.
2019-06-24 22:40:29 +00:00
Matthias Clasen fa8ffa6d6c Set names on shortcut controllers 2019-06-24 22:40:29 +00:00
Matthias Clasen b2be6db1ed inspector: Show owners for shortcuts
This is somewhat preliminary, but it helps
debugging shortcuts. It suffers from not having
the right list model apis to do this.

Eventually, this should become a link to the
object details.
2019-06-24 22:40:29 +00:00
Matthias Clasen 949afa598a inspector: Add a quick shortcuts page
This shows the shortcuts for a GtkShortcutController
object.
2019-06-24 22:40:29 +00:00
Matthias Clasen 56bc921586 inspector: Show shortcut actions and triggers
Show these in the property details for
GtkShortcut objects.
2019-06-24 22:40:29 +00:00
Matthias Clasen d0509d5afc shortcut controller: Make model readable
We want to show the shortcuts in the inspector,
so we need to be able to get at the model.
2019-06-24 22:40:29 +00:00
Matthias Clasen a9c0548179 window: Use gtk_widget_class_bind_action
Use gtk_widget_class_bind_action for default.activate.
2019-06-24 22:40:29 +00:00
Matthias Clasen 79c5398690 Add gtk_widget_class_bind_action
Similar to gtk_widget_class_add_binding_signal,
but triggers an action.
2019-06-24 22:40:29 +00:00
Georges Basile Stavracas Neto 26d310fb07 shortcutcontroller: Unref shortcut proper
g_list_model_get_item() is transfer full, so we need to
unref everything that is acquired through it.
2019-06-24 22:40:29 +00:00
Georges Basile Stavracas Neto 1787bf5471 shortcuttrigger: Filter a few modifiers out
Copying the code from GtkKeyHash, filter out X11 modifiers and
Caps Lock from events. Unfortunately, legacy X11 modifiers can
be present even when running full Wayland, due to XKB.
2019-06-24 22:40:29 +00:00
Benjamin Otte 2ace9aef5f filechooser: Trigger the location popup via bindings
Simplifies code quite a bit.
2019-06-24 22:40:29 +00:00
Benjamin Otte b46e7f1108 filechooser: Remove outdated hack
In GTK2, the filechooser was using a Paned, so switching between sidebar
and files list with the arrow keys didn't work (the slider would be
selected instead). So in
https://bugzilla.gnome.org/show_bug.cgi?id=161489 a crude hack was added
to make this possible.

Over the years the filechooser code has changed so that it now would do
this by default, yet the hack had been retained.
2019-06-24 22:40:29 +00:00
Benjamin Otte cedb413600 accels: Remove GtkAccelGroup 2019-06-24 22:40:29 +00:00
Benjamin Otte f0b41b181d testmenubutton: Don't create a GtkAccelGroup
It's unused.
2019-06-24 22:40:29 +00:00
Benjamin Otte 9c46eb4398 testsuite: Remove GtkAccelGroup usage 2019-06-24 22:40:29 +00:00
Benjamin Otte 2aa9c0ddc1 doc tools: Create AccelLabel image without using GtkAccelGroup 2019-06-24 22:40:29 +00:00
Benjamin Otte ba9fc7aead widget: Remove gtk_widget_add_accelerator()
People should use shortcut controllers instead (global, capture).

A side effect of this is that GtkMenuItem (or rather: GtkAccelLabel) now
lost its method to magically look up accelerators to display. Somebody
needs to add that back later.
2019-06-24 22:40:29 +00:00
Benjamin Otte 0a77a4a264 testgtk: Port keyval example to shortcut controllers 2019-06-24 22:40:29 +00:00
Benjamin Otte 0b21d6a01c gtk-demo: Redo builder example to use shortcuts
Now that shortcuts and controllers are supported by GtkBuilder, demo
how all of that works.
2019-06-24 22:40:29 +00:00
Benjamin Otte 21e4f5353b shortcutcontroller: Implement GtkBuildable
Use it to allow adding shortcuts to the controller via the usual <child>
method.
2019-06-24 22:40:29 +00:00
Benjamin Otte 16583da221 shortcutaction: Integrate with GtkBuilder property parsing
<property name="action">action(win.quit)</property> style action
specifications now work for GtkShortcutAction properties.
2019-06-24 22:40:29 +00:00
Benjamin Otte ee88c6863e shortcuttrigger: Add gtk_shortcut_triger_new_parse_string()
And hook it up into the GtkBuilder infrastructure.
2019-06-24 22:40:29 +00:00
Benjamin Otte 112a8d1037 application: Replace accelerator handling with shortcuts
API remains the same, but activation is now done via a
shortcutcontroller.

The code uses a controller with global scope so that the shortcuts are
managed with all the other global shortcuts.
2019-06-24 22:40:29 +00:00
Benjamin Otte 28a1e44833 accel: Add display arg to gtk_accelerator_parse_with_keycode()
It was using the default display unconditionally.
2019-06-24 22:40:29 +00:00
Benjamin Otte d273fb63ec accelerators: Make gtk_accelerator_parse() return TRUE/FALSE
A parse function should return success or not. So do that.
2019-06-24 22:40:29 +00:00
Benjamin Otte 4ac2f95688 shortcuttrigger: Add hash(), equal(), and compare() functions
Those are useful for putting triggers in hash tables or getting sorted
output.
2019-06-24 22:40:28 +00:00
Benjamin Otte d38791473a shortcuts: Mananage managed shortcuts with a custom model
Reduce the amount of special casing by using a ListModel for global and
managed shortcuts, too.

This way, the ListModel API will work for the ShortcutController in the
GtkShortcutManager and GtkRoot.

The only special case remaining is shortcut activation, which needs to
pass the right widget to the controller in the global/managed case.
2019-06-24 22:40:28 +00:00
Benjamin Otte c5b2bb06be gdk: Make gdk_keyval_name() return a const char
The string is const, so return it like that.
2019-06-24 22:40:28 +00:00
Benjamin Otte 6a75fdf732 shortcutaction: Add gtk_shortcut_action_to_string()
For all but the callback action, we can print something useful.
2019-06-24 22:40:28 +00:00
Benjamin Otte dd1b65d522 widget: Keep keybindings as a GListStore
This way, we can use shortcut_controller_new_for_model() and avoid all
the special casing about run_class.
2019-06-24 22:40:28 +00:00
Benjamin Otte 40264629f7 shortcutcontroller: Add gtk_shortcut_controller_new_for_model()
This is mainly for internal use, but I can't see a reason to not have it
public for people who want to maintain their own lists.

I'm sure gnome-builder will never ever find a way to misuse it.
2019-06-24 22:40:28 +00:00
Benjamin Otte 740fe4f7ce shortcutcontroller: Implement GListModel
After all, this controller is a list of shortcuts.
2019-06-24 22:40:28 +00:00
Benjamin Otte 7fffbccbde gtk-demo: Port the sliding puzzle demo to shortcuts 2019-06-24 22:40:28 +00:00
Benjamin Otte 10ff0bc959 shortcut: Change the API for creating shortcuts
When creating shortcuts, there almost always are a trigger and an action
available for use. So make gtk_shortcut_new() take those as arguments.

Also add gtk_shortcut_new_with_arguments() so people can easily pass
those in, too.
2019-06-24 22:40:28 +00:00
Benjamin Otte c336ebdaae shortcut: Add GtkShortcutAction
Similar to GtkShortcutTrigger, GtkShortCutAction provides all the
different ways to activate a shortcut.

So far, these different ways are supported:
- do nothing
- Call a user-provided callback
- Call gtk_widget_activate()
- Call gtk_widget_mnemonic_activate()
- Emit an action signal
- Activate an action from the widget's action muxer
- Activate a GAction
2019-06-24 22:40:28 +00:00
Benjamin Otte 4d6d5d3fe5 accelgroup: Remove unneeded APIs
After the removal of GtkAccelMap, these things are no longer necessary.
2019-06-24 22:40:28 +00:00
Benjamin Otte edf1023f5c gtk: Remove GtkAccelMap
Now that accel paths are gone, the object managing them isn't needed
anymore either.
2019-06-24 22:40:28 +00:00
Benjamin Otte 41a9786b51 gtk: Remove accel paths
It's an outdated technology now that everybody is using GActionGroups.

If somebody wanted to support changeable shortcuts, they'd need to
reintroduce it in another way.
2019-06-24 22:40:28 +00:00
Benjamin Otte 97cdd92233 menushell: Remove old mnemonic handling
It's not used anymore.

This was also the last user of GtkMnemonicHash, so delete that one, too.
2019-06-24 22:40:28 +00:00
Benjamin Otte ba70b22ab1 window: Remove all old mnemonic handling API 2019-06-24 22:40:28 +00:00
Benjamin Otte 500bee4a25 menu: Implement GtkShortcutManager
And make sure to activate mnemonics without Alt
2019-06-24 22:40:28 +00:00
Benjamin Otte c551279ec7 shortcutmanager: Add
This adds an interface for taking care of shortcut controllers with
managed scope.

GtkRoot requires this interface, where it's also used for global
controllers and to ensure that managed scope always finds a parent that
is a shortcut manager.

No widget that isn't a root implements the interface yet.
2019-06-24 22:40:28 +00:00
Benjamin Otte 6b4b1a0ba3 label: Implement mnemonics using shortcuts 2019-06-24 22:40:28 +00:00
Benjamin Otte 635299fff1 shortcut: Add gtk_shortcut_set_mnemonic_activate()
Makes the shortcut call gtk_widget_mnemonic_activate() upon activation.
2019-06-24 22:40:28 +00:00
Benjamin Otte 46179898cf shortcuttrigger: Add support for mnemonics
Mnemonics need to be triggered with help from the controllers (who
determine the modifiers). Support for that has been added, too.

Mnemonics do not use this yet though.
2019-06-24 22:40:28 +00:00
Benjamin Otte d977797d87 window: Put F10 accelerator into its own shortcut controller
So instead of relying on gtk_window_activate_key(), it's now using
proper infrastructure.
2019-06-24 22:40:28 +00:00
Benjamin Otte d9320b923d window: Get rid of public APIs that shouldn't be
Event controllers should have replaced all of them. And if they haven't,
apps need to fix their code (I'm looking at you Gimp).
2019-06-24 22:40:28 +00:00
Benjamin Otte bd2dc9f299 gdk: Remove GDK_RELEASE_MASK
It was only ever supported by keybindings and those are gone now.
2019-06-24 22:40:28 +00:00
Benjamin Otte d1711f4953 gtk-demo: Add a dumb demo for shortcut triggers 2019-06-24 22:40:28 +00:00
Benjamin Otte 8462b4f322 shortcutcontroller: Add GtkShortcutScope
Allow setting the scope for a controller. The scope determines at what
point in event propagation the shortcuts will be activated.

Local scope is the usual activation, global scope means that the root
widget activates the shortcuts - ie they are activated at the very
start of event propagation (for global capture events) or the very end
(for global bubble events).
Managed scope so far is unimplemented.

This is supposed to be used to replace accelerators and mnemonics.
2019-06-24 22:40:28 +00:00
Benjamin Otte cee07a218d shortcuttrigger: Add gtk_shortcut_trigger_to_label()
Provide a user-presentable string.
2019-06-24 22:40:28 +00:00
Benjamin Otte 8270a0c751 accelgroup: Add gtk_accel_group_print_label() 2019-06-24 22:40:28 +00:00
Benjamin Otte 4bbeb36afe accellabel: Move gtk_accelerator_get_label() code
The function lives in gtkaccelgroup.c, so there's no need to have that
call a private function in another source file. Instead, make that
other source file call gtk_accelerator_get_label() instead.
2019-06-24 22:40:28 +00:00
Benjamin Otte 9acfc58fc4 accellabel: Get rid of class variables
We can just look them up as-needed, no need to cache them.
2019-06-24 22:40:28 +00:00
Matthias Clasen 757ccb65df model button: Use simpler api for accels 2019-06-24 22:40:28 +00:00
Benjamin Otte fd0a0c0da6 gtk: Remove bindings
The whole binding functionality is now handled by shortcuts.
2019-06-24 22:40:28 +00:00
Matthias Clasen 7685d8fdd8 popovermenu: Port away from GtkBindings 2019-06-24 22:40:28 +00:00
Georges Basile Stavracas Neto 8a0607bc4e eventcontrollerkey: Remove binding handling 2019-06-24 22:40:28 +00:00
Georges Basile Stavracas Neto 0aa6898e54 passwordentry: Remove unused header 2019-06-24 22:40:28 +00:00
Benjamin Otte b0f971b45a accelgroup: Actually have a default mod mask
Don't just use a value without initializing it.
2019-06-24 22:40:28 +00:00
Benjamin Otte b902beaf42 treeview: Redo event forwarding hack
Reorder the event controllers so that key forwarding to the search
entries really happens after shortcut triggering.
2019-06-24 22:40:28 +00:00
Benjamin Otte 6f57b1fb5f combobox: Redo key event forwarding hack
Instead of manualling invoking bindings, we now reorder event
controllers inside the treemenu, so that shortcuts run before the event
forwarding.
2019-06-24 22:40:28 +00:00
Benjamin Otte 0a1b472b40 iconview: Port bindings to use shortcuts 2019-06-24 22:40:28 +00:00
Benjamin Otte 5172ccaf64 infobar: Port bindings to use shortcuts 2019-06-24 22:40:28 +00:00
Benjamin Otte e623561d94 label: Port bindings to use shortcuts 2019-06-24 22:40:28 +00:00
Benjamin Otte 5a1719c719 listbox: Port bindings to use shortcuts 2019-06-24 22:40:28 +00:00
Benjamin Otte 58c3be5dfb menubar: Port bindings to use shortcuts 2019-06-24 22:40:28 +00:00
Benjamin Otte a3cb40832e menu: Port bindings to use shortcuts 2019-06-24 22:40:28 +00:00
Benjamin Otte 603da7b432 menushell: Port bindings to use shortcuts 2019-06-24 22:40:28 +00:00
Benjamin Otte 95c7669a96 notebook: Port bindings to use shortcuts 2019-06-24 22:40:28 +00:00
Benjamin Otte 2774f9ab9f scale: Port bindings to use shortcuts 2019-06-24 22:40:28 +00:00
Benjamin Otte 0e875859aa scalebutton: Port bindings to use shortcuts 2019-06-24 22:40:28 +00:00
Benjamin Otte 042ad688eb scrolledwindow: Port bindings to use shortcuts 2019-06-24 22:40:28 +00:00
Benjamin Otte 25519ae3fa searchentry: Port bindings to use shortcuts 2019-06-24 22:40:28 +00:00
Benjamin Otte 484a20709e shortcutssection: Port bindings to use shortcuts 2019-06-24 22:40:27 +00:00
Benjamin Otte c1f6dd6f0a shortcutswindow: Port bindings to use shortcuts 2019-06-24 22:40:27 +00:00
Benjamin Otte b10e31985a flowbox: Port bindings to use shortcuts 2019-06-24 22:40:27 +00:00
Benjamin Otte a55af731f0 paned: Port bindings to use shortcuts 2019-06-24 22:40:27 +00:00
Benjamin Otte 52ff060527 spinbutton: Port bindings to use shortcuts 2019-06-24 22:40:27 +00:00
Benjamin Otte 11e132d8e0 textview: Port bindings to use shortcuts 2019-06-24 22:40:27 +00:00
Benjamin Otte da0465ec27 filechooserwidget: Port bindings to use shortcuts 2019-06-24 22:40:27 +00:00
Benjamin Otte 27a60f76fc toolbar: Port bindings to use shortcuts 2019-06-24 22:40:27 +00:00
Benjamin Otte 232f4a8503 shortcutcontroller: Add gtk_shortcut_controller_add_shortcut()
... and gtk_shortcut_controller_remove_shortcut().
2019-06-24 22:40:27 +00:00
Benjamin Otte bb0343ecc8 shortcutcontroller: Add private API for running class shortcuts
We don't want regular users to be able to run class shortcuts in their
controllers, so we have to special case that.
2019-06-24 22:40:27 +00:00
Benjamin Otte f8638c7fc9 treeview: Port bindings to use shortcuts 2019-06-24 22:40:27 +00:00
Benjamin Otte 571320a198 widget: Port bindings to use shortcuts 2019-06-24 22:40:27 +00:00
Benjamin Otte 8c256ab36a dialog: Port binding to use shortcuts 2019-06-24 22:40:27 +00:00
Benjamin Otte dfba621d80 text: Port bindings to use shortcuts 2019-06-24 22:40:27 +00:00
Benjamin Otte 80ecccf6ba shortcut: Add gtk_shortcut_set_callback()
... and gtk_widget_class_add_binding() to go with it.

This allows shortcuts to invoke manually added callbacks.
2019-06-24 22:40:27 +00:00
Benjamin Otte 47d348a6de combobox: Port bindings to use shortcuts 2019-06-24 22:40:27 +00:00
Benjamin Otte 778a60fa2c assistant: Port bindings to use shortcuts 2019-06-24 22:40:27 +00:00
Benjamin Otte fbaba0026a trigger: Add an alternative trigger
And use it.

I just added it to GtkWidget just to show that I can.
The real reason I want it is for gamepad/joystick triggers in games,
so that it becomes possible to select 2 different triggers (gamepad and
keyboard) for the same shortcut.
2019-06-24 22:40:27 +00:00
Benjamin Otte e8aba7d8b9 shortcut: Add GtkShortcutTrigger
Triggers are meant to describe how to trigger a shortcut. So far only a
keyval + modifiers trigger exists.
2019-06-24 22:40:27 +00:00
Benjamin Otte fc9ff92096 window: Port bindings to use shortcuts 2019-06-24 22:40:27 +00:00
Benjamin Otte f80d664c0d bindings: Add more variant types
Also marshal types that the code in gtkbindings.c doesn't use. These
will be used by gtk_widget_class_add_binding_signal().
2019-06-24 22:40:27 +00:00
Benjamin Otte ec641ebcab widget: Add gtk_widget_class_add_shortcut()
This allows adding shortcuts as a replacement for keybindings.
2019-06-24 22:40:27 +00:00
Benjamin Otte 8b96ce4e8b gtk: Add GtkShortcut
This is the base class for what is about to take over all sorts of
keyboard shortcuts. The initial version barely deals with keybindings.
2019-06-24 22:40:27 +00:00
Benjamin Otte 504e203a1d bindings: Split out function to invoke an action signal
We want to use that in shortcuts later.
2019-06-24 22:40:27 +00:00
Benjamin Otte 435ff1012f shortcutcontroller: Introduce
This is a very barebones controller that currently does nothing but
activate the binding signals. Yay.

And because we have bindings on every widget (Yes, a GtkGrid has a
keybinding - 2 in fact), we need that controller everywhere.
2019-06-24 22:40:27 +00:00
Benjamin Otte 83bfc8d9f2 bindings: Make gtk_binding_parse_signal() use GVariantBuilder
And because it's the last user of GtkBindingArg and
gtk_binding_entry_add_signall(), also remove those two.
2019-06-24 22:40:27 +00:00
Benjamin Otte 0e4bbb18f3 bindings: Parse into GVariantBuilder directly
Avoids the indirection via GtkBindingArg
2019-06-24 22:40:27 +00:00
Benjamin Otte 935c03c8a0 bindings: Add gtk_binding_entry_add_signal_variant()
This function is the replacement for
gtk_binding_entry_add_signall().

The GVariant will be demarshalled and passed to the action signal upon
binding activation. The same rules apply as used to apply for
GtkBindingArg, in that long, double and string args are now replaced by
"x", "d" and "s" variant types.
2019-06-24 22:40:27 +00:00
Benjamin Otte 77ef644c7c bindings: Replace GtkBindingArg arguments with GVariant
This only replaces invocation, not yet parsing.
2019-06-24 22:40:27 +00:00
Georges Basile Stavracas Neto fd9d7c67d5 widget: Bring back _gtk_widget_list_controllers()
Will be used by shourtcuts.
2019-06-24 22:40:27 +00:00
3630 changed files with 506127 additions and 638530 deletions
-11
View File
@@ -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
+39 -202
View File
@@ -1,11 +1,5 @@
include:
- project: 'gnome/citemplates'
file: 'flatpak/flatpak_ci_initiative.yml'
stages:
- build
- analysis
- docs
- flatpak
- deploy
@@ -18,264 +12,107 @@ stages:
- subprojects/libepoxy/
- subprojects/pango/
# Common variables
variables:
COMMON_MESON_FLAGS: "-Dwerror=true -Dglib:werror=false -Dpango:werror=false -Dgtk-doc:werror=false -Dwayland-protocols:werror=false -Dsysprof:werror=false"
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true"
FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled"
MESON_TEST_TIMEOUT_MULTIPLIER: 3
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v25"
FLATPAK_IMAGE: "registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master"
DOCS_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora-docs:v25"
.only-default:
only:
- branches
except:
- tags
style-check-diff:
extends: .only-default
image: $FEDORA_IMAGE
stage: .pre
allow_failure: true
fedora-x86_64:
image: registry.gitlab.gnome.org/gnome/gtk/master:v6
stage: build
script:
- .gitlab-ci/run-style-check-diff.sh
.build-fedora-default:
image: $FEDORA_IMAGE
- bash -x ./.gitlab-ci/test-docker.sh
artifacts:
when: always
reports:
junit:
- "${CI_PROJECT_DIR}/_build/report-x11.xml"
- "${CI_PROJECT_DIR}/_build/report-wayland.xml"
- "${CI_PROJECT_DIR}/_build/report-broadway.xml"
- "${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"
- "${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"
cache:
key: "$CI_JOB_NAME"
paths:
- _ccache/
- subprojects/gdk-pixbuf/
- subprojects/glib/
- subprojects/graphene/
- subprojects/libepoxy/
- subprojects/pango/
<<: *cache-paths
fedora-x86_64:
extends: .build-fedora-default
stage: build
needs: []
variables:
EXTRA_MESON_FLAGS: "--buildtype=debug --default-library=both"
script:
- meson subprojects update
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} ${BACKEND_FLAGS} ${FEATURE_FLAGS}
_build
- ninja -C _build
- .gitlab-ci/run-tests.sh _build x11
- .gitlab-ci/run-tests.sh _build wayland
- .gitlab-ci/run-tests.sh _build broadway
release-build:
extends: .build-fedora-default
stage: build
needs: []
variables:
EXTRA_MESON_FLAGS: "--buildtype=release"
script:
- meson subprojects update
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} ${BACKEND_FLAGS} ${FEATURE_FLAGS}
_build
- ninja -C _build
- .gitlab-ci/run-tests.sh _build x11
installed-tests:
extends: .build-fedora-default
stage: build
needs: []
variables:
EXTRA_MESON_FLAGS: "--prefix=/usr --libdir=/usr/lib64 -Dinstall-tests=true"
G_TEST_ACCESSIBLE: 1
script:
- meson subprojects update
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} ${BACKEND_FLAGS} ${FEATURE_FLAGS}
_build
- ninja -C _build
- sudo ninja -C _build install
- dbus-run-session xvfb-run -a -s "-screen 0 1024x768x24"
gnome-desktop-testing-runner
--report-directory=_build/installed-tests-report/failed/
--parallel=0
gtk-4.0
artifacts:
paths:
- "_build/installed-tests-report/"
.mingw-defaults:
.mingw-defaults: &mingw-defaults
stage: build
tags:
- win32-ps
- win32
script:
- C:\msys64\usr\bin\pacman --noconfirm -Syyuu
- C:\msys64\usr\bin\bash -lc "bash -x ./.gitlab-ci/test-msys2.sh"
cache:
key: "$CI_JOB_NAME"
paths:
- _ccache/
- subprojects/gdk-pixbuf/
- subprojects/glib/
- subprojects/graphene/
- subprojects/libepoxy/
- subprojects/pango/
key: "%CI_JOB_NAME%"
<<: *cache-paths
msys2-mingw64:
extends: .mingw-defaults
needs: []
msys2-mingw32:
variables:
MSYSTEM: "MINGW64"
MSYSTEM: "MINGW32"
CHERE_INVOKING: "yes"
<<: *mingw-defaults
.flatpak-defaults:
image: $FLATPAK_IMAGE
.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"
- 'repo.tar'
expire_in: 1 day
script:
- bash -x ./.gitlab-ci/flatpak-build.sh "${APPID}"
# Manual jobs, for branches and MRs
.flatpak-manual:
extends: .flatpak-defaults
.flatpak-manual: &flatpak-manual
<<: *flatpak-defaults
when: manual
# Only build Flatpak bundles automatically on master
.flatpak-master:
extends: .flatpak-defaults
.flatpak-master: &flatpak-master
<<: *flatpak-defaults
only:
- master
flatpak-manual:demo:
extends: .flatpak-manual
needs: []
variables:
APPID: org.gtk.Demo4
<<: *flatpak-manual
flatpak-master:demo:
extends: .flatpak-master
needs: []
variables:
APPID: org.gtk.Demo4
<<: *flatpak-master
flatpak-manual:widget-factory:
extends: .flatpak-manual
needs: []
variables:
APPID: org.gtk.WidgetFactory4
<<: *flatpak-manual
flatpak-master:widget-factory:
extends: .flatpak-master
needs: []
variables:
APPID: org.gtk.WidgetFactory4
<<: *flatpak-master
flatpak-manual:icon-browser:
extends: .flatpak-manual
needs: []
variables:
APPID: org.gtk.IconBrowser4
<<: *flatpak-manual
flatpak-master:icon-browser:
extends: .flatpak-master
needs: []
variables:
APPID: org.gtk.IconBrowser4
# Publish the demo apps to the GNOME Nightly repo
# https://wiki.gnome.org/Apps/Nightly
# https://gitlab.gnome.org/GNOME/Initiatives/-/wikis/DevOps-with-Flatpak
nightly demo:
extends: '.publish_nightly'
dependencies: ['flatpak-master:demo']
needs: ['flatpak-master:demo']
nightly factory:
extends: '.publish_nightly'
dependencies: ['flatpak-master:widget-factory']
needs: ['flatpak-master:widget-factory']
nightly icon-browser:
extends: '.publish_nightly'
dependencies: ['flatpak-master:icon-browser']
needs: ['flatpak-master:icon-browser']
static-scan:
image: $FEDORA_IMAGE
stage: analysis
needs: []
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
# Run tests with the address sanitizer. We need to turn off introspection,
# since it is incompatible with asan
asan-build:
image: $FEDORA_IMAGE
tags: [ asan ]
stage: analysis
needs: []
variables:
script:
- CC=clang meson --buildtype=debugoptimized -Db_sanitize=address -Db_lundef=false -Dintrospection=disabled _build
- ninja -C _build
- .gitlab-ci/run-tests.sh _build wayland
artifacts:
paths:
- _build/meson-logs
allow_failure: true
reference:
image: $DOCS_IMAGE
stage: docs
needs: []
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
<<: *flatpak-master
pages:
stage: deploy
needs: ['reference']
image: registry.gitlab.gnome.org/gnome/gtk/master:v6
stage: deploy
script:
- mv _reference/ public/
- meson -Ddocumentation=true _build .
- ninja -C _build
- ninja -C _build gdk4-doc gsk4-doc gtk4-doc
- mkdir -p public/
- mv _build/docs/reference/gtk/html/ public/gtk/
- mv _build/docs/reference/gdk/html/ public/gdk/
- mv _build/docs/reference/gsk/html/ public/gsk/
artifacts:
paths:
- public
View File
@@ -1,6 +1,7 @@
FROM fedora:31
FROM fedora:30
RUN dnf -y install \
hicolor-icon-theme \
adwaita-icon-theme \
atk-devel \
at-spi2-atk-devel \
@@ -8,15 +9,11 @@ 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 \
elfutils-libelf-devel \
fribidi-devel \
gcc \
@@ -26,10 +23,8 @@ RUN dnf -y install \
gettext \
git \
glib2-devel \
glib2-static \
glibc-devel \
glibc-headers \
gnome-desktop-testing \
gobject-introspection-devel \
graphene-devel \
gstreamer1-devel \
@@ -37,20 +32,16 @@ RUN dnf -y install \
gstreamer1-plugins-bad-free-devel \
gstreamer1-plugins-base-devel \
gtk-doc \
hicolor-icon-theme \
iso-codes \
itstool \
json-glib-devel \
lcov \
libasan \
libattr-devel \
libcloudproviders-devel \
libepoxy-devel \
libffi-devel \
libmount-devel \
librsvg2 \
libselinux-devel \
libubsan \
libXcomposite-devel \
libXcursor-devel \
libXcursor-devel \
@@ -61,7 +52,6 @@ RUN dnf -y install \
libxkbcommon-devel \
libXrandr-devel \
libXrender-devel \
libXtst-devel \
libxslt \
mesa-dri-drivers \
mesa-libEGL-devel \
@@ -69,11 +59,9 @@ 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 \
@@ -81,11 +69,17 @@ RUN dnf -y install \
vulkan-devel \
wayland-devel \
wayland-protocols-devel \
weston \
weston-libs \
which \
xorg-x11-server-Xvfb \
&& dnf clean all
RUN pip3 install meson==0.55.3
RUN pip3 install meson==0.50.1
ARG HOST_USER_ID=5555
ENV HOST_USER_ID ${HOST_USER_ID}
RUN useradd -u $HOST_USER_ID -ms /bin/bash user
USER user
WORKDIR /home/user
ENV LANG C.UTF-8
-47
View File
@@ -1,47 +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
### Checklist for Adding a new dependency to a CI image
Our images are layered, and the base (called fedora-base) contains
all the rpm payload. Therefore, adding a new dependency is a 2-step
process:
1. [ ] Build and upload fedora-base:$version+1
1. [ ] Build and upload fedora:$version+1 based on fedora-base:version+1
[registry]: https://gitlab.gnome.org/GNOME/gtk/container_registry
-133
View File
@@ -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()
-12
View File
@@ -1,12 +0,0 @@
FROM registry.gitlab.gnome.org/gnome/gtk/fedora-base:v25
RUN dnf -y install pandoc
ARG HOST_USER_ID=5555
ENV HOST_USER_ID ${HOST_USER_ID}
RUN useradd -u $HOST_USER_ID -ms /bin/bash user
USER user
WORKDIR /home/user
ENV LANG C.UTF-8
-13
View File
@@ -1,13 +0,0 @@
FROM registry.gitlab.gnome.org/gnome/gtk/fedora-base:v25
# Enable sudo for wheel users
RUN sed -i -e 's/# %wheel/%wheel/' -e '0,/%wheel/{s/%wheel/# %wheel/}' /etc/sudoers
ARG HOST_USER_ID=5555
ENV HOST_USER_ID ${HOST_USER_ID}
RUN useradd -u $HOST_USER_ID -G wheel -ms /bin/bash user
USER user
WORKDIR /home/user
ENV LANG C.UTF-8
+14 -17
View File
@@ -4,32 +4,34 @@ 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 \
-Dbuild-tests=false \
-Dbuild-examples=false \
-Dintrospection=disabled \
-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,10 +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}
# to be consumed by the nightly publish jobs
if [[ $CI_COMMIT_BRANCH == master ]]; then
tar cf repo.tar ${repodir}
fi
+57 -65
View File
@@ -138,26 +138,22 @@ ul.images li {
</head>
<body>
<header>
<h1>{{ report.project_name }}/{{ report.backend }}/{{ 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>Backend:</strong> {{ report.backend }}</p>
<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>
<h3>Summary</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>Failed:</strong> {{ report.total_failures }}</li>
</ul>
</div>
</section>
@@ -165,18 +161,58 @@ ul.images li {
{% for suite_result in report.results_list %}
<section>
<div class="result">
<h3><a name="results">Suite: {{ suite_result.suite_name }}</a></h3>
<h3>Suite: {{ suite_result.suite_name }}</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="successes">
<h4>Passed</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>
{% else %}
<li>None</li>
{% endfor %}
</ul>
<h4>Skipped</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>Expected failures</h4>
<ul>
{% for success in suite_result.successes if success.result == 'EXPECTEDFAIL' %}
<li>{{ success.name }} - result: <span class="result xfail">{{ success.result }}</span><br/>
{% if success.stdout %}
Output: <pre>{{ success.stdout }}</pre>
{% endif %}
{% if success.image_data is defined %}
<ul class="images">
<li><img alt="ref" src="{{ success.image_data.ref }}" /></li>
<li><img alt="out" src="{{ success.image_data.out }}" /></li>
<li><img alt="diff" src="{{ success.image_data.diff }}" /></li>
</ul>
{% endif %}
</li>
{% else %}
<li>None</li>
{% endfor %}
</ul>
</div>
<div class="failures">
<h4><a name="{{ suite_result.suite_name }}-failed">Failures</a></h4>
<h4>Failed</h4>
<ul class="failed">
{% for failure in suite_result.failures if failure.result in [ 'ERROR', 'FAIL', 'UNEXPECTEDPASS' ] %}
<li><a name="{{ failure.name }}">{{ failure.name }}</a> - result: <span class="result fail">{{ failure.result }}</span><br/>
{% for failure in suite_result.failures if failure.result == 'FAIL' %}
<li>{{ failure.name }} - result: <span class="result fail">{{ failure.result }}</span><br/>
{% if failure.stdout %}
Output: <pre>{{ failure.stdout }}</pre>
{% endif %}
@@ -193,10 +229,10 @@ ul.images li {
{% endfor %}
</ul>
<h4><a name="{{ suite_result.suite_name }}-timed-out">Timed out</a></h4>
<h4>Timed out</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/>
<li>{{ failure.name }} - result: <span class="result fail">{{ failure.result }}</span><br/>
{% if failure.stdout %}
Output: <pre>{{ failure.stdout }}</pre>
{% endif %}
@@ -207,46 +243,6 @@ ul.images li {
</ul>
</div>
<div class="successes">
<h4><a name="{{ suite_result.suite_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/>
{% if success.stdout %}
Output: <pre>{{ success.stdout }}</pre>
{% endif %}
{% if success.image_data is defined %}
<ul class="images">
<li><img alt="ref" src="{{ success.image_data.ref }}" /></li>
<li><img alt="out" src="{{ success.image_data.out }}" /></li>
<li><img alt="diff" src="{{ success.image_data.diff }}" /></li>
</ul>
{% endif %}
</li>
{% else %}
<li>None</li>
{% endfor %}
</ul>
<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>
<ul class="passed">
{% for success in suite_result.successes if success.result == 'OK' %}
<li>{{ success.name }} - result: <span class="result pass">{{ success.result }}</li>
{% else %}
<li>None</li>
{% endfor %}
</ul>
</div>
</div>
</section>
{% endfor %}
@@ -260,9 +256,6 @@ aparser = argparse.ArgumentParser(description='Turns a Meson test log into an HT
aparser.add_argument('--project-name', metavar='NAME',
help='The project name',
default='Unknown')
aparser.add_argument('--backend', metavar='NAME',
help='The used backend',
default='unknown')
aparser.add_argument('--job-id', metavar='ID',
help='The job ID for the report',
default=None)
@@ -323,7 +316,6 @@ report = {}
report['date'] = datetime.datetime.utcnow()
report['locale_date'] = report['date'].strftime("%c")
report['project_name'] = args.project_name
report['backend'] = args.backend
report['job_id'] = args.job_id
report['branch_name'] = args.branch
report['total_successes'] = 0
@@ -336,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', 'ERROR',]:
if unit['result'] in ['FAIL', 'TIMEOUT']:
return True
return False
+5 -10
View File
@@ -19,9 +19,6 @@ aparser = argparse.ArgumentParser(description='Turns a Meson test log into a JUn
aparser.add_argument('--project-name', metavar='NAME',
help='The project name',
default='unknown')
aparser.add_argument('--backend', metavar='NAME',
help='The used backend',
default='unknown')
aparser.add_argument('--job-id', metavar='ID',
help='The job ID for the report',
default='Unknown')
@@ -54,7 +51,6 @@ for line in args.infile:
duration = data['duration']
return_code = data['returncode']
result = data['result']
log = data['stdout']
unit = {
@@ -62,7 +58,6 @@ for line in args.infile:
'name': unit_name,
'duration': duration,
'returncode': return_code,
'result': result,
'stdout': log,
}
@@ -73,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 ['ERROR', '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
@@ -95,18 +90,18 @@ for name, units in suites.items():
for unit in successes:
testcase = ET.SubElement(testsuite, 'testcase')
testcase.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
testcase.set('name', '{}/{}'.format(args.backend, unit['name']))
testcase.set('name', unit['name'])
testcase.set('time', str(unit['duration']))
for unit in failures:
testcase = ET.SubElement(testsuite, 'testcase')
testcase.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
testcase.set('name', '{}/{}'.format(args.backend, unit['name']))
testcase.set('name', unit['name'])
testcase.set('time', str(unit['duration']))
failure = ET.SubElement(testcase, 'failure')
failure.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
testcase.set('name', '{}/{}'.format(args.backend, unit['name']))
failure.set('name', unit['name'])
failure.set('type', 'error')
failure.text = unit['stdout']
+6 -130
View File
@@ -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:v6"
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"
elif [ $base_version != "latest" ]; then
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 docker"
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
-44
View File
@@ -1,44 +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.
if [ "${CI_PROJECT_NAMESPACE}" != "GNOME" ]; then
echo "Retrieving the current upstream repository from ${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME}..."
git remote add upstream https://gitlab.gnome.org/GNOME/gtk.git
git fetch upstream
ORIGIN="upstream"
else
echo "Reusing the existing repository on ${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME}"
ORIGIN="origin"
fi
# 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 were 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 "${ORIGIN}/${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 GTKs 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. Thats why this CI check is OK
# to fail: the idea is that people can look through the output and ignore it if
# its wrong. (That situation can also happen if someone touches pre-existing
# badly formatted code and it doesnt make sense to tidy up the wider coding
# style with the changes theyre 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}
-82
View File
@@ -1,82 +0,0 @@
#!/bin/bash
set +x
set +e
srcdir=$( pwd )
builddir=$1
backend=$2
# Ignore memory leaks lower in dependencies
export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp
case "${backend}" in
x11)
xvfb-run -a -s "-screen 0 1024x768x24 -noreset" \
meson test -C ${builddir} \
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
--print-errorlogs \
--setup=${backend} \
--suite=gtk \
--no-suite=gsk-compare-broadway
# Store the exit code for the CI run, but always
# generate the reports
exit_code=$?
;;
wayland)
export XDG_RUNTIME_DIR="$(mktemp -p $(pwd) -d xdg-runtime-XXXXXX)"
weston --backend=headless-backend.so --socket=wayland-5 --idle-time=0 &
compositor=$!
export WAYLAND_DISPLAY=wayland-5
meson test -C ${builddir} \
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
--print-errorlogs \
--setup=${backend} \
--suite=gtk \
--no-suite=gsk-compare-broadway
exit_code=$?
kill ${compositor}
;;
broadway)
export XDG_RUNTIME_DIR="$(mktemp -p $(pwd) -d xdg-runtime-XXXXXX)"
${builddir}/gdk/broadway/gtk4-broadwayd :5 &
server=$!
export BROADWAY_DISPLAY=:5
meson test -C ${builddir} \
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
--print-errorlogs \
--setup=${backend} \
--suite=gtk \
--no-suite=gsk-compare-opengl
# don't let Broadway failures fail the run, for now
exit_code=0
kill ${server}
;;
esac
cd ${builddir}
$srcdir/.gitlab-ci/meson-junit-report.py \
--project-name=gtk \
--backend=${backend} \
--job-id="${CI_JOB_NAME}" \
--output=report-${backend}.xml \
meson-logs/testlog-${backend}.json
$srcdir/.gitlab-ci/meson-html-report.py \
--project-name=gtk \
--backend=${backend} \
--job-id="${CI_JOB_NAME}" \
--reftest-output-dir="testsuite/reftests/output/${backend}" \
--output=report-${backend}.html \
meson-logs/testlog-${backend}.json
exit $exit_code
-2
View File
@@ -16,9 +16,7 @@ meson \
-Dwayland-backend=true \
-Dbroadway-backend=true \
-Dvulkan=yes \
-Dprofiler=true \
--werror \
${EXTRA_MESON_FLAGS:-} \
_build $srcdir
unset CCACHE_DISABLE
+2 -22
View File
@@ -37,25 +37,6 @@ mkdir -p _ccache
export CCACHE_BASEDIR="$(pwd)"
export CCACHE_DIR="${CCACHE_BASEDIR}/_ccache"
# https://gitlab.gnome.org/GNOME/gtk/-/issues/2243
# https://gitlab.gnome.org/GNOME/gtk/-/issues/3002
if ! pkg-config --atleast-version=2.65.0 glib-2.0; then
git clone https://gitlab.gnome.org/GNOME/glib.git _glib
meson setup _glib_build _glib
meson compile -C _glib_build
meson install -C _glib_build
fi
pkg-config --modversion glib-2.0
if ! pkg-config --atleast-version=1.47.0 pango; then
git clone https://gitlab.gnome.org/GNOME/pango.git _pango
meson setup _pango_build _pango
meson compile -C _pango_build
meson install -C _pango_build
fi
pkg-config --modversion pango
# Build
ccache --zero-stats
ccache --show-stats
@@ -64,9 +45,8 @@ meson \
-Dx11-backend=false \
-Dwayland-backend=false \
-Dwin32-backend=true \
-Dvulkan=disabled \
-Dintrospection=enabled \
-Dgtk:werror=true \
-Dvulkan=no \
--werror \
_build
unset CCACHE_DISABLE
+6 -24
View File
@@ -1,5 +1,5 @@
Please do not mail any of the authors listed here
asking questions about this version of GTK.
Please do not mail any of the authors listed here
asking questions about this version of GTK+.
Original Authors
----------------
@@ -7,8 +7,8 @@ Peter Mattis <petm@xcf.berkeley.edu>
Spencer Kimball <spencer@xcf.berkeley.edu>
Josh MacDonald <jmacd@xcf.berkeley.edu>
The Team that build GTK 2 (in alphabetical order)
-------------------------------------------------
The GTK+ Team (in alphabetical order)
-------------------------------------
Shawn T. Amundson <amundson@gtk.org>
Jerome Bolliet <bolliet@gtk.org>
Damon Chaplin <damon@gtk.org>
@@ -28,24 +28,11 @@ Jay Painter <jpaint@gtk.org>
Manish Singh <manish@gtk.org>
Owen Taylor <otaylor@gtk.org>
The current team (GTK 3 and 4)
------------------------------
Jonas Ådahl <jadahl@gmail.com>
Tim Bäder <mail@baedert.org>
Emmanuele Bassi <ebassi@gnome.org>
Chun-wei Fan <fanchunwei@src.gnome.org>
Matthias Clasen <mclasen@redhat.com>
Carlos Garnacho <mrgarnacho@gmail.com>
Alexander Larsson <alexl@redhat.com>
Benjamin Otte <otte@gnome.org>
There are many others who have contributed patches; we thank them,
GTK is much better because of them.
GTK+ is much better because of them.
Over time, GTK has incorporated some pieces of software which
Over time, GTK+ has incorporated some pieces of software which
started as independent projects. We list the original authors here:
@@ -76,8 +63,3 @@ DirectFB backend
Denis Oliver Kropp
Sven Neumann
Mike Emmel
gtkparasite
-----------
Christian Hammond
+7 -2
View File
@@ -22,7 +22,12 @@ Please, do not use the issue tracker for support questions. If you have
questions on how to use GTK effectively, you can use:
- the `#gtk` IRC channel on irc.gnome.org
- the [gtk tag on the GNOME Discourse instance](https://discourse.gnome.org/tag/gtk)
- the [gtk](https://mail.gnome.org/mailman/listinfo/gtk-list) mailing list,
for general questions on GTK
- the [gtk-app-devel](https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list)
mailing list, for questions on application development with GTK
- the [gtk-devel](https://mail.gnome.org/mailman/listinfo/gtk-devel-list)
mailing list, for questions on developing GTK itself
You can also look at the GTK tag on [Stack
Overflow](https://stackoverflow.com/questions/tagged/gtk).
@@ -169,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.
+1 -922
View File
@@ -1,924 +1,3 @@
Overview of Changes in 3.99.4
=============================
* GtkColumnView:
- Improve column resizing
- Make double-click reset column widths
- Move header outside of scrollbars
* GtkSearchEntry:
- Add an icon
* GtkDropDown:
- Polish the appearance
* GtkColorChooser:
- Accessibility improvements
* GtkPopoverMenu:
- Add accessibility support
- Allow custom items. This adds new API:
gtk_popover_menu_add/remove_child
gtk_popover_menu_bar_add/remove_child
* GtkTextView:
- Fix rendering and positioning of anchored children
- Fix positioning of touch handles
* Constraints:
- Fix loading constraints from ui files
* Media support:
- Use cubic instead of linear volume
* Accessibility:
- Implement Component for all widgets
- Implement Text and EditableText for all editables
- Rework accessible name/description computation
- Add documentation for app and widget developers
- Handle HIDDEN state changes by adding/removing elements
- Support setting accessibility attributes in ui files
- Make window controls accessible
* Introspection:
- Add some missing annotations
* gdk:
- Deliver events on flush
- Drop the unused GdkPoint struct from the API
- Improve popup autohide behavior
* Demos:
- Add another constraints demo
- Tweak various demos to improve consistency
- Small accessibility improvements
* Tools:
- Improve gtk4-builder-tool handling of various
widgets when converting ui files from GTK 3
* Documentation:
- Use GtkApplication in all examples
- Improve and expand the widget gallery
* Testsuite:
- Improve coverage of GDK
- Improve coverage of gtk4-builder-tool
* Build:
- Fix the build with cups 2.2.12
- Make cloudprint support build without warnings
* Broadway:
- Support modifiers for scroll events
* Windows:
- Improve IME support
* OS X:
- Fix various input issues
- Make GtkGLArea work (with the cairo backend)
* Translation updates:
German
Polish
Overview of Changes in 3.99.3
=============================
* Accessibility:
- Add an initial AT-SPI backend
* GtkEmojiChooser:
- Allow inserting multiple Emoji by pressing Control
- Update Emoji data to Unicode 13 / CLDR 37
- Use translations
- The recent-emoji setting type changed. Call
gsettings reset org.gtk.gtk4.Settings.EmojiChooser recent-emoji
* GtkTextBuffer:
- Add boolean returns to some get_iter functions
* GtkScale:
- Change the default value of the :draw-value property
* GtkPopover:
- Avoid losing focus when popovers are close
* GtkColorChooser:
- Add color names back for accessibility
* Input methods:
- Add a 'private' input hint
* GL Renderer:
- Fix issues with texture caching
- Fix texture flipping problems
* Build:
- Use meson yield feature for some options
- Require gtk-doc 1.33
- Require sysprof 3.38
* Wayland:
- Clean up Wayland backend api, add annotations
- Generate introspection for Wayland backend api
* Windows:
- Fix modal window handling and window stacking
* MacOS:
- Fix the build
- Define GDK_WINDOWING_MACOS
- Fix various event handling issues
* Demos:
- Add another column view demo
- Add an svg paintable demo
* Translation updates
Czech
Lithuanian
Polish
Overview of Changes in GTK 3.99.2
=================================
* GtkButton:
- Check coordinates for button releases
* GtkColorChooser:
- Update the default palette
* GtkEntry:
- Fix issues with Emoji insertion
- Fix issues with dnd
- Set correct hotspot for dnd icon
* GtkFileChooser:
- Fix a crash
- Fix setting unlisted filters
* GtkFontChooser:
- Determine sample text based on font coverage (requires fontconfig)
- Allow filtering by language (requires fontconfig)
- Don't center the list
* GtkMenuButton:
- Always use the direction property for the arrow
* GtkPasswordEntry:
- Use non-pageable memory
- Add an ::activate signal
* GtkRevealer:
- Fix clipping issues in the swing transitions
* GtkScrolledWindow:
- Fix kinetic scrolling in X11
* GtkSearchEntry:
- Don't handle forwarded events twice
* GtkStack:
- Add gtk_stack_add_child
* GtkTextView:
- Fix dnd
- Improve undo state tracking
- Speed rendering in the presence of selections
- Make clickable links work again
- Fix handling of anchored children
* GtkVideo:
- Make autoplay work
* CSS:
- Allow more than 64 selectors per rule
- Avoid some allocation overhead
* Adwaita:
- Improve gesture graphics
- Tweak DND highlight color
- Add spacing to .navigation-sidebar
* GDK:
- Add gdk_frame_clock_get_fps
- GLES: Fix color channel mixup in textures
- GL: Reduce image copying for texture uploads
* GSK:
- Add radial gradient nodes
- Add GskGLShader and shader nodes
* GL renderer:
- Fix clipping with projective transforms
- Use linear interpolation for offscreen rendering
with non-axis-aligned transforms
- Fix texture caching to avoid size mismatches
- Avoid downloading GL textures when possible,
improving GtkGLArea performance
* Vulkan renderer:
- Fix swapchain creation
* Windows:
- Fix display of CSD windows
* Wayland
- Always ack configure to avoid jumping windows
- Use the primary-selection-unstable-v1 protocol
* API cleanups:
- Make filter and sorter constructors return exact types
- Rename GdkSurfaceState to GdkToplevelState
- Remove GdkWaylandSurface::committed
- Make Wayland backend api take GdkToplevel
- Drop gtk_widget_new
- Drop cairo_surface_upload_to_gl
- Drop gtk_scrolled_window_set_capture_button_press
- Drop gtk_column_view_column_new_with_factory
- Rename gtk_buildable_set_name to gtk_buildable_set_buildable_id
- Drop other GtkBuildable api
* Demos:
- Bug and crash fixes
- Cosmetic improvements for several demos
- Improve search in the sidebar
- Add a Shadertoy demo
- Add a OpenGL transitions demo
- Add an Emblem demo
- Add a demo for input validation and error states
- Add a demo for context menus
- Make gtk-demo demo itself
* Build:
- Fix Vulkan dependency checking
- Make sysprof truly optional
* Translation updates:
Basque
British English
Catalan
Croatian
Czech
Danish
French
Galician
German
Hebrew
Hungarian
Indonesian
Italian
Kazakh
Latvian
Lithuanian
Persian
Polish
Slovak
Slovenian
Spanish
Turkish
Ukrainian
Overview of Changes in GTK 3.99.1
=================================
* GtkGridLayout: Rename left-/top-attach to column/row
* Drop GtkAccelLabel - it is no longer used
* GtkTextView:
- Fix redraw issues with selections
- Make insert-emoji replace the selection
* GtkTreeView:
- Fix selection handling in cell editables
* GtkPopover:
- Allow setting popup offset
* GtkPlacesSidebar:
- Fix DND
* GtkTextview:
- Speed up gtk_text_buffer_insert_markup
* GtkFrame:
- Set GTK_OVERFLOW_HIDDEN
* GtkSpinButton:
- Fix spinning
* GtkFontChooser:
- Populate the list incrementally
* GtkButton: Simplify the button hierarchy; GtkRadioButton
is gone, GtkCheckButton and GtkToggleButton can be grouped
* list widgets:
- Change apis to make models explicitly GtkSelectionModel
- Simplify constructors
* CSS:
- Hexadecimal colors can now specify alpha
- Fix parsing of numbers in scientific notation
* Themes:
- Add and document highlevel list styles
- Drop the style class defines. Just use string literals
- Round the corners of frames
- Make circular buttons square
* GL renderer:
- Fix clipping with projective transforms
* Documentation:
- Refresh the widget gallery
- Add images for new widgets to the gallery
- Fix many cross-references
- Make sure tutorial examples are buildable
* Demos:
- Numerous crash- and bug fixes
- Improve about dialogs
- gtk4-demo: Modernize source highlighting
- gtk4-demo: Improve sidebar filtering
- gtk4-demo: Drop some outdated demos
- gtk4-demo: Polish a number of existing demos
- gtk4-demo: Add several new demos
- widget-factory: Show error states
* Tools:
- Make gtk4-builder-tool rewrite GtkBox
- Make gtk4-builder-tool rewrite radio buttons
- Rewrite the profiling support, drop support
for D-Bus profiler activation, use SYSPROF_TRACE_FD
* Printing:
- Fix build with cups < 2.3
* win32:
- Default to the GL renderer when we can
* Broadway:
- Fix handling of opaque colors
- Fix handling of debug nodes
- Prune clipped render nodes
* Wayland:
- Support newer schemas for settings
- Fix DND hotspot handling
- Disconnect on display close
* Translation updates:
Basque
Brazilian Portuguese
British English
Catalan
Chinese (China)
Croatian
Galician
German
Greek
Indonesian
Japanese
Kazakh
Korean
Lithuanian
Polish
Romanian
Slovenian
Spanish
Turkish
Ukrainian
Overview of Changes in GTK 3.99.0
=================================
* Remove the old accessibility implementation and
add the foundations for a new one that is based
on ARIA. The relevant widget api is GtkAccessible,
the backend implementations will use GtkATContext.
Currently, there is just a nascent test backend.
* Update the GTK headers to use char *, int, float and
double instead of the corresponding GLib types.
* Add GtkEditableLabel, a label that can be edited
* Add GtkBookmarkList, a list model for bookmarks
* Add GtkStringList, a list model for strings
* Add GtkBitset, and use it for representing selections
* GtkTreeView:
- Make cell editing work again
* GtkSpinButton:
- Make autosizing work again
* Printing:
- Use GtkDropDown in the print dialog
* GtkApplication
- Support opening files on OS X
* GtkFileChooser:
- Fix libcloudproviders support
- Turn GtkFileFilter into a GtkFilter
- Simplify the api
* GtkGridView, GtkListView:
- Improve scrolling behavior
- Autoscroll and autoexpand during DND
* GtkScrolledWindow:
- Make autoscrolling work again
* GtkFilterListModel:
- Add incremental filtering
- Add a boolean filter, GtkBoolFilter
* GtkSortListModel:
- Use timsort
- Add various tweaks that massively speed up sorting
- Add incremental sorting
* GtkWidget:
- Massively speed up action handling
* GtkEntry:
- Make entry completion work again
- Drop action support from GtkEntryCompletion
* Inspector:
- Improve list model support
- Add direct navigation between objects
- Show accessibility information
* GDK:
- Compress scroll events
- Keep a scroll history
- Clean up GdkDevice api
- Drop the master/slave device split
- Move axes to GdkDeviceTool
- Change monitor workarea to be per-backend API
- Improve frame clock accuracy
- Add a new macOS backend
- Add an ANGLE-based GLES renderer for Windows
* GSK:
- Use GL_ARB_framebuffer_object
* gtk-demo:
- Add incremental refill to the color grid
- Improve performance of the color grid
- Add an incrementally filtering word list
- Improve the sidebar
* Install print-editor as another demo
* Translation updates
Basque
Catalan
Chinese
Japanese
Kazakh
Lithuanian
Polish
Romanian
Spanish
Turkish
Ukrainian
Overview of Changes in GTK 3.98.5
=================================
* Introduce new list widgets and supporting infrastructure.
The main APIs are:
- GtkListView
- GtkGridView
- GtkColumnView and GtkColumnViewColumn
- GtkDropDown
- GtkListItemFactory and implementations
- GtkExpression
- GtkFilter and subclasses, and GtkFilterListModel
- GtkSorter and subclasses, and GtkSortListModel
- GtkSelectionModel and subclasses
- GtkTreeListModel, GtkTreeExpander and GtkTreeListRowSorter
* GtkFileChooser:
- Add a tracker3-based search engine implementation
- Rate-limit updates from the trash monitor
* GtkWindow:
- Redo the css node setup. There is now a single 'window' node
- Fix rounded corners on tiled windows
* GtkApplication:
- Drop app menu support. Menubar support is still there
* GtkFixed:
- Change coordinate APIs to take doubles
* GtkOverlay:
- Make GtkOverlayLayout public
* GtkTooltips:
- Fix line wrapping of tooltips
* Shortcuts:
- Fix mnemonic cycling
- Fix using '0' as a mnemonic
* Menus:
- Differentiate keypad keys in accelerators
* GtkIMContext:
- Add gtk_im_context_filter_key to allow event reinjection
* Themes:
- Adwaita: Limit the scope of backdrop
* Accessibility:
- Clean up and reorganize the code to prepare for the
dropping of ATK
* GDK:
- Drop unused enum and struct definitions from headers
- Make keymap translation API public again. Still needed
- Frameclock: Always use compositor refresh rate info
- Frameclock: Use quadratic correction for frame time jitter
- Frameclock: Ensure monotonicity
- Frameclock: Track resason for paint
- X11: Improve sync when the Nvidia driver is used
* GSK:
- GL renderer: Fix blurred outset shadows
- GL renderer: handle nested transform nodes properly
- GL renderer: Optimize clip handling
* gtk-demo:
- Improve the Drag-and-Drop demo with proper drag icons
- Don't show the main window if --run is given
- Add demos for list widgets and GtkDropDrown
* Documentation:
- Convert freestanding sections to markdown
- Drop the glossary
- Expand and improve the migration guide
* Build:
- We require pandoc now, for building the documentation
- Require Pango 1.45
* Translation updates:
Polish
Romanian
Slovenian
Turkish
Ukrainian
Overview of Changes in GTK 3.98.4
=================================
* Themes
- Refine menu styling
- Tweak visible focus behavior
- HighConstrast: Add public colors
- HighContrast: Fix scale borders
* CSS:
- Drop the nonstandard -gtk-icon-theme property
- Add a system_setting_changed vfunc to propagate global changes
* Untangle titlebars from windows:
- Add a GtkWindowControls widget
- Add a GtkWindowHandle widget
- Add actions for window menu items
- Remove app menu fallback from GtkHeaderBar
- Remove title and subtitle properties from GtkHeaderBar,
rename custom-title to title-widget
* GtkWidget
- Add a focusable property
* GtkPopover:
- Fix (re-)positioning issues
* GtkStack:
- Drop the homogeneous property
- Add a use-underline property to stack pages
* GtkScale:
- Make area around the trough clickable
* GtkScrolledWindow:
- Fix kinetic scrolling
* GtkTreeView:
- Break reference cycles in unroot
* Drop GtkBin and GtkContainer. All existing GtkBin subclasses
have grown a child property with setter and getter. All
existing GtkContainer subclasses have grown widget-specific
remove (and in some cases, add) functions. <child> in ui
files continues to work as before
* Replace gtk_widget_destroy by gtk_window_destroy
* Drop the ::size-allocate signal. Use a GtkWidgetPaintable
if you need to be informed about changes to a widgets
content or size
* Remove gtk_dialog_run
* GDK:
- Wayland: Provide a builtin cursor of last resort
- Change the monitor api to use a GListModel
* GSK:
- Don't include renderer-specific headers automatically
- GL: Fix nested rounded clips
* Introspection:
- Assorted annotation fixes
* Inspector:
- Preview media resources
- Show media backend information
* gtk4-widget-factory:
- Add GtkVideo
- Add text styles
- Add a print dialog
- Add a password entry
- Improve toolbar styling
- Revamp transition effects
* gtk4-demo:
- Replace some demos
* Translation updates:
Chinese (Taiwan)
Esperanto
Japanese
Romanian
Spanish
Ukrainian
Overview of Changes in GTK 3.98.3
=================================
* GtkEntry:
- Support setting attributes in ui files
* GtkScaleButton:
- Don't derive from GtkButton
* GtkAboutDialog:
- Support more common licenses
* GtkEmojiChooser:
- Improve keyboard navigation
* GtkLabel:
- Remove pattern API
* GtkAspectFrame:
- Modernize and simplify
* Chooser buttons:
- Make dialogs modal by default
* Various widgets:
- Replace shadow-type and relief properties by
a simpler has-frame
* CSS:
- Use :focus-visible instead of :focus(visible)
- Add support for :focus-within
* Focus handling
- Fix crossing event generation
- Fix focus handling in various widgets
- Change :can-focus to be recursive
- Fix GtkWindow:is-active setting
* Scrolling
- gtk_container_set_focus_[hv]adjustment has been removed
- gtk_viewport_set_scroll_to_focus has been added
* Accessibility:
- Add a cursor-aspect-ratio setting
- Set focus-related states properly
* Themes:
- Use blue focus outlines more
- Numerous minor improvements
* Wayland:
- Fix .Compose file loading
- Support popup repositioning
- Fix problems with autohide popovers
* GDK:
- Remove GdkKeymap from public API, replaced by
GdkDevice properties
- Add full keyboard translation state to key events
- Simplify modifier support, drop GdkModifierIntent
- Move key event matching to GDK
- Add GdkSurface::enter/leave-monitor signals
- Turn GskEvent into a derivable type, and make
it introspectable
* GSK:
- Turn GskRenderNode into a derivable type, and make
it introspectable
- Fall back to cairo if compiling shaders fails
* Translation updates:
- Japanese
- Lithuanian
- Turkish
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
==================================
@@ -1281,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
+7 -15
View File
@@ -1,7 +1,7 @@
GTK — The GTK toolkit
=====================
[![Build status](https://gitlab.gnome.org/GNOME/gtk/badges/master/pipeline.svg)](https://gitlab.gnome.org/GNOME/gtk/-/commits/master)
[![Build Status](https://gitlab.gnome.org/GNOME/gtk/badges/master/build.svg)](https://gitlab.gnome.org/GNOME/gtk/pipelines)
General information
-------------------
@@ -27,9 +27,9 @@ The official developers blog
- https://blog.gtk.org
Discussion forum
Information about mailing lists can be found at
- https://discourse.gnome.org/c/platform/core/
- http://www.gtk.org/mailing-lists.php
Nightly documentation can be found at
- Gtk: https://gnome.pages.gitlab.gnome.org/gtk/gtk/
@@ -56,6 +56,7 @@ building for:
- [Pango](https://download.gnome.org/sources/pango)
- [Epoxy](https://github.com/anholt/libepoxy)
- [Graphene](https://github.com/ebassi/graphene)
- [ATK](https://download.gnome.org/sources/atk)
- [Xkb-common](https://github.com/xkbcommon/libxkbcommon)
If you are building the X11 backend, you will also need:
@@ -69,6 +70,7 @@ If you are building the X11 backend, you will also need:
- xcursor
- xdamage
- xcomposite
- [atk-bridge-2.0](https://download.gnome.org/sources/at-spi2-atk)
If you are building the Wayland backend, you will also need:
@@ -98,7 +100,7 @@ And, finally, you can install GTK using:
$ sudo ninja install
```
Complete information about installing GTK and related libraries
Complete information about installing GTK+ and related libraries
can be found in the file:
```
@@ -138,12 +140,6 @@ In the bug report please include:
* Further information such as stack traces may be useful, but
is not necessary.
Contributing to GTK
-------------------
Please, follow the [contribution guide](./CONTRIBUTING.md) to know how to
start contributing to GTK.
Release notes
-------------
@@ -160,8 +156,4 @@ GTK is released under the terms of the GNU Lesser General Public License,
version 2.1 or, at your option, any later version, as published by the Free
Software Foundation.
Please, see the [`COPYING`](./COPYING) file for further information.
GTK includes a small number of source files under the Apache license:
- A fork of the roaring bitmaps implementation in [gtk/roaring](./gtk/roaring)
- An adaptation of timsort from python in [gtk/timsort](./gtk/timsort)
Please, see the `COPYING` file for further information.
+29 -75
View File
@@ -1,38 +1,29 @@
{
"app-id" : "org.gtk.Demo4",
"runtime" : "org.gnome.Platform",
"runtime-version" : "master",
"sdk" : "org.gnome.Sdk",
"command" : "gtk4-demo",
"tags" : [
"devel",
"development",
"nightly"
],
"desktop-file-name-prefix" : "(Development) ",
"finish-args" : [
"app-id": "org.gtk.Demo4",
"runtime": "org.gnome.Platform",
"runtime-version": "master",
"sdk": "org.gnome.Sdk",
"command": "gtk4-demo",
"tags": ["devel", "development", "nightly"],
"desktop-file-name-prefix": "(Development) ",
"finish-args": [
"--device=dri",
"--share=ipc",
"--socket=fallback-x11",
"--socket=wayland",
"--talk-name=org.gtk.vfs",
"--talk-name=org.gtk.vfs.*"
"--talk-name=org.gtk.vfs", "--talk-name=org.gtk.vfs.*"
],
"cleanup" : [
"cleanup": [
"/include",
"/lib/pkgconfig",
"/share/pkgconfig",
"/lib/pkgconfig", "/share/pkgconfig",
"/share/aclocal",
"/man",
"/share/man",
"/share/gtk-doc",
"*.la",
".a",
"/man", "/share/man", "/share/gtk-doc",
"*.la", ".a",
"/lib/girepository-1.0",
"/share/gir-1.0",
"/share/doc"
],
"modules" : [
"modules": [
{
"name" : "wayland",
"buildsystem" : "autotools",
@@ -48,71 +39,34 @@
]
},
{
"name" : "graphene",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"name": "graphene",
"buildsystem": "meson",
"builddir": true,
"config-opts": [
"--libdir=/app/lib",
"-Dtests=false",
"-Dbenchmarks=false"
],
"sources" : [
"sources": [
{
"type" : "git",
"url" : "https://github.com/ebassi/graphene.git"
"type": "git",
"url": "https://github.com/ebassi/graphene.git"
}
]
},
{
"name" : "libsass",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"name": "gtk",
"buildsystem": "meson",
"builddir": true,
"config-opts": [
"--libdir=/app/lib"
],
"sources" : [
"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",
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib",
"-Denable_vulkan=no",
"-Dbuildtype=debugoptimized"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/gtk.git"
"type": "git",
"url": "https://gitlab.gnome.org/GNOME/gtk.git"
}
]
}
],
"build-options" : {
"env" : {
"GSK_RENDERER" : "opengl"
}
}
]
}
+29 -74
View File
@@ -1,38 +1,29 @@
{
"app-id" : "org.gtk.IconBrowser4",
"runtime" : "org.gnome.Platform",
"runtime-version" : "master",
"sdk" : "org.gnome.Sdk",
"command" : "gtk4-icon-browser",
"tags" : [
"devel",
"development",
"nightly"
],
"desktop-file-name-prefix" : "(Development) ",
"finish-args" : [
"app-id": "org.gtk.IconBrowser4",
"runtime": "org.gnome.Platform",
"runtime-version": "master",
"sdk": "org.gnome.Sdk",
"command": "gtk4-icon-browser",
"tags": ["devel", "development", "nightly"],
"desktop-file-name-prefix": "(Development) ",
"finish-args": [
"--device=dri",
"--share=ipc",
"--socket=fallback-x11",
"--socket=wayland",
"--talk-name=org.gtk.vfs",
"--talk-name=org.gtk.vfs.*"
"--talk-name=org.gtk.vfs", "--talk-name=org.gtk.vfs.*"
],
"cleanup" : [
"cleanup": [
"/include",
"/lib/pkgconfig",
"/share/pkgconfig",
"/lib/pkgconfig", "/share/pkgconfig",
"/share/aclocal",
"/man",
"/share/man",
"/share/gtk-doc",
"*.la",
".a",
"/man", "/share/man", "/share/gtk-doc",
"*.la", ".a",
"/lib/girepository-1.0",
"/share/gir-1.0",
"/share/doc"
],
"modules" : [
"modules": [
{
"name" : "wayland",
"buildsystem" : "autotools",
@@ -48,70 +39,34 @@
]
},
{
"name" : "graphene",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"name": "graphene",
"buildsystem": "meson",
"builddir": true,
"config-opts": [
"--libdir=/app/lib",
"-Dtests=false",
"-Dbenchmarks=false"
],
"sources" : [
"sources": [
{
"type" : "git",
"url" : "https://github.com/ebassi/graphene.git"
"type": "git",
"url": "https://github.com/ebassi/graphene.git"
}
]
},
{
"name" : "libsass",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"name": "gtk",
"buildsystem": "meson",
"builddir": true,
"config-opts": [
"--libdir=/app/lib"
],
"sources" : [
"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",
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib",
"-Denable_vulkan=no",
"-Dbuildtype=debugoptimized"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/gtk.git"
"type": "git",
"url": "https://gitlab.gnome.org/GNOME/gtk.git"
}
]
}
],
"build-options" : {
"env" : {
}
}
]
}
+29 -78
View File
@@ -1,38 +1,29 @@
{
"app-id" : "org.gtk.WidgetFactory4",
"runtime" : "org.gnome.Platform",
"runtime-version" : "master",
"sdk" : "org.gnome.Sdk",
"command" : "gtk4-widget-factory",
"tags" : [
"devel",
"development",
"nightly"
],
"desktop-file-name-prefix" : "(Development) ",
"finish-args" : [
"app-id": "org.gtk.WidgetFactory4",
"runtime": "org.gnome.Platform",
"runtime-version": "master",
"sdk": "org.gnome.Sdk",
"command": "gtk4-widget-factory",
"tags": ["devel", "development", "nightly"],
"desktop-file-name-prefix": "(Development) ",
"finish-args": [
"--device=dri",
"--share=ipc",
"--socket=fallback-x11",
"--socket=wayland",
"--talk-name=org.gtk.vfs",
"--talk-name=org.gtk.vfs.*"
"--talk-name=org.gtk.vfs", "--talk-name=org.gtk.vfs.*"
],
"cleanup" : [
"cleanup": [
"/include",
"/lib/pkgconfig",
"/share/pkgconfig",
"/lib/pkgconfig", "/share/pkgconfig",
"/share/aclocal",
"/man",
"/share/man",
"/share/gtk-doc",
"*.la",
".a",
"/man", "/share/man", "/share/gtk-doc",
"*.la", ".a",
"/lib/girepository-1.0",
"/share/gir-1.0",
"/share/doc"
],
"modules" : [
"modules": [
{
"name" : "wayland",
"buildsystem" : "autotools",
@@ -48,74 +39,34 @@
]
},
{
"name" : "graphene",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"name": "graphene",
"buildsystem": "meson",
"builddir": true,
"config-opts": [
"--libdir=/app/lib",
"-Dtests=false",
"-Dbenchmarks=false"
],
"sources" : [
"sources": [
{
"type" : "git",
"url" : "https://github.com/ebassi/graphene.git"
"type": "git",
"url": "https://github.com/ebassi/graphene.git"
}
]
},
{
"name" : "libsass",
"buildsystem" : "meson",
"builddir" : true,
"config-opts" : [
"name": "gtk",
"buildsystem": "meson",
"builddir": true,
"config-opts": [
"--libdir=/app/lib"
],
"sources" : [
"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",
"builddir" : true,
"config-opts" : [
"--libdir=/app/lib",
"-Denable_vulkan=no",
"-Dbuildtype=debugoptimized"
],
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/gtk.git"
"type": "git",
"url": "https://gitlab.gnome.org/GNOME/gtk.git"
}
]
}
],
"build-options" : {
"env" : {
"DBUS_SESSION_BUS_ADDRESS" : "''",
"GSK_RENDERER" : "opengl",
"GDK_DEBUG" : "vulkan-disable",
"G_ENABLE_DEBUG" : "true"
}
}
]
}
+3 -15
View File
@@ -15,13 +15,7 @@ if 'DESTDIR' not in os.environ:
gtk_immodule_dir = os.path.join(gtk_moduledir, 'immodules')
print('Compiling GSettings schemas...')
glib_compile_schemas = subprocess.check_output(['pkg-config',
'--variable=glib_compile_schemas',
'gio-2.0']).strip()
if not os.path.exists(glib_compile_schemas):
# pkg-config variables only available since GLib 2.62.0.
glib_compile_schemas = 'glib-compile-schemas'
subprocess.call([glib_compile_schemas,
subprocess.call(['glib-compile-schemas',
os.path.join(gtk_datadir, 'glib-2.0', 'schemas')])
print('Updating icon cache...')
@@ -30,14 +24,8 @@ if 'DESTDIR' not in os.environ:
print('Updating module cache for print backends...')
os.makedirs(gtk_printmodule_dir, exist_ok=True)
gio_querymodules = subprocess.check_output(['pkg-config',
'--variable=gio_querymodules',
'gio-2.0']).strip()
if not os.path.exists(gio_querymodules):
# pkg-config variables only available since GLib 2.62.0.
gio_querymodules = 'gio-querymodules'
subprocess.call([gio_querymodules, gtk_printmodule_dir])
subprocess.call(['gio-querymodules', gtk_printmodule_dir])
print('Updating module cache for input methods...')
os.makedirs(gtk_immodule_dir, exist_ok=True)
subprocess.call([gio_querymodules, gtk_immodule_dir])
subprocess.call(['gio-querymodules', gtk_immodule_dir])
+35 -10
View File
@@ -1,9 +1,8 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* always defined to indicate that i18n is enabled */
#define ENABLE_NLS 1
/* Use structured logging */
#define G_LOG_STRUCTURED 1
/* The prefix for our gettext translation domains. */
#mesondefine GETTEXT_PACKAGE
@@ -28,6 +27,14 @@
/* Define to 1 if you have the `dcgettext' function. */
#mesondefine HAVE_DCGETTEXT
/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't.
*/
#mesondefine HAVE_DECL_ISINF
/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't.
*/
#mesondefine HAVE_DECL_ISNAN
/* Define to 1 if you have the <dlfcn.h> header file. */
#mesondefine HAVE_DLFCN_H
@@ -49,6 +56,12 @@
/* Define if GStreamer support is available */
#mesondefine HAVE_GSTREAMER
/* Define to 1 if you have the `httpGetAuthString' function. */
#mesondefine HAVE_HTTPGETAUTHSTRING
/* Define if cups http_t authstring field is accessible */
#mesondefine HAVE_HTTP_AUTHSTRING
/* Define to 1 if you have the <inttypes.h> header file. */
#mesondefine HAVE_INTTYPES_H
@@ -70,12 +83,12 @@
/* Define to 1 if you have the `mkstemp' function. */
#mesondefine HAVE_MKSTEMP
/* Define to 1 if you have the `mlock` function. */
#mesondefine HAVE_MLOCK
/* Define to 1 if you have a working `mmap' system call. */
#mesondefine HAVE_MMAP
/* Define to 1 if you have the `nearbyint' function. */
#mesondefine HAVE_NEARBYINT
/* Define to 1 if you have the `posix_fallocate' function. */
#mesondefine HAVE_POSIX_FALLOCATE
@@ -85,9 +98,21 @@
/* Have the Xrandr 1.5 extension library */
#mesondefine HAVE_RANDR15
/* Define to 1 if you have the `rint' function. */
#mesondefine HAVE_RINT
/* Define to 1 if you have the `round' function. */
#mesondefine HAVE_ROUND
/* Define to 1 if you have the `sincos' function. */
#mesondefine HAVE_SINCOS
/* Define to 1 if you have the `log2` function */
#mesondefine HAVE_LOG2
/* Define to 1 if you ahve the `exp2` function */
#mesondefine HAVE_EXP2
/* Define to 1 if you have the <stdint.h> header file. */
#mesondefine HAVE_STDINT_H
@@ -107,7 +132,7 @@
#mesondefine HAVE_SYS_PARAM_H
/* Have the sysprof-capture library */
#mesondefine HAVE_SYSPROF
#mesondefine HAVE_SYSPROF_CAPTURE
/* Define to 1 if you have the <sys/stat.h> header file. */
#mesondefine HAVE_SYS_STAT_H
@@ -166,6 +191,9 @@
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#mesondefine LT_OBJDIR
/* Define if <X11/extensions/XIproto.h> needed for xReply */
#mesondefine NEED_XIPROTO_H_FOR_XREPLY
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
#mesondefine NO_MINUS_C_MINUS_O
@@ -276,6 +304,3 @@
#mesondefine HAVE_PANGOFT
#mesondefine ISO_CODES_PREFIX
/* Define if tracker3 is available */
#mesondefine HAVE_TRACKER3
@@ -1,115 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#include "config.h"
#include "constraint-editor-application.h"
#include "constraint-editor-window.h"
struct _ConstraintEditorApplication
{
GtkApplication parent_instance;
};
G_DEFINE_TYPE(ConstraintEditorApplication, constraint_editor_application, GTK_TYPE_APPLICATION);
static void
constraint_editor_application_init (ConstraintEditorApplication *app)
{
}
static void
quit_activated (GSimpleAction *action,
GVariant *parameter,
gpointer data)
{
g_application_quit (G_APPLICATION (data));
}
static GActionEntry app_entries[] =
{
{ "quit", quit_activated, NULL, NULL, NULL }
};
static void
constraint_editor_application_startup (GApplication *app)
{
const char *quit_accels[2] = { "<Ctrl>Q", NULL };
const char *open_accels[2] = { "<Ctrl>O", NULL };
GtkCssProvider *provider;
G_APPLICATION_CLASS (constraint_editor_application_parent_class)->startup (app);
g_action_map_add_action_entries (G_ACTION_MAP (app),
app_entries, G_N_ELEMENTS (app_entries),
app);
gtk_application_set_accels_for_action (GTK_APPLICATION (app), "app.quit", quit_accels);
gtk_application_set_accels_for_action (GTK_APPLICATION (app), "win.open", open_accels);
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider, "/org/gtk/gtk4/constraint-editor/constraint-editor.css");
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
static void
constraint_editor_application_activate (GApplication *app)
{
ConstraintEditorWindow *win;
win = constraint_editor_window_new (CONSTRAINT_EDITOR_APPLICATION (app));
gtk_window_present (GTK_WINDOW (win));
}
static void
constraint_editor_application_open (GApplication *app,
GFile **files,
int n_files,
const char *hint)
{
ConstraintEditorWindow *win;
int i;
for (i = 0; i < n_files; i++)
{
win = constraint_editor_window_new (CONSTRAINT_EDITOR_APPLICATION (app));
constraint_editor_window_load (win, files[i]);
gtk_window_present (GTK_WINDOW (win));
}
}
static void
constraint_editor_application_class_init (ConstraintEditorApplicationClass *class)
{
GApplicationClass *application_class = G_APPLICATION_CLASS (class);
application_class->startup = constraint_editor_application_startup;
application_class->activate = constraint_editor_application_activate;
application_class->open = constraint_editor_application_open;
}
ConstraintEditorApplication *
constraint_editor_application_new (void)
{
return g_object_new (CONSTRAINT_EDITOR_APPLICATION_TYPE,
"application-id", "org.gtk.gtk4.ConstraintEditor",
"flags", G_APPLICATION_HANDLES_OPEN,
NULL);
}
@@ -1,28 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#pragma once
#include <gtk/gtk.h>
#define CONSTRAINT_EDITOR_APPLICATION_TYPE (constraint_editor_application_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintEditorApplication, constraint_editor_application, CONSTRAINT, EDITOR_APPLICATION, GtkApplication)
ConstraintEditorApplication *constraint_editor_application_new (void);
@@ -1,664 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#include "config.h"
#include "constraint-editor-window.h"
#include "constraint-view.h"
#include "constraint-editor.h"
#include "guide-editor.h"
struct _ConstraintEditorWindow
{
GtkApplicationWindow parent_instance;
GtkWidget *paned;
GtkWidget *view;
GtkWidget *list;
};
G_DEFINE_TYPE(ConstraintEditorWindow, constraint_editor_window, GTK_TYPE_APPLICATION_WINDOW);
static GtkConstraintTarget *
find_target (GListModel *model,
GtkConstraintTarget *orig)
{
const char *name;
const char *model_name;
gpointer item;
int i;
if (orig == NULL)
return NULL;
if (GTK_IS_LABEL (orig))
name = gtk_label_get_label (GTK_LABEL (orig));
else if (GTK_IS_CONSTRAINT_GUIDE (orig))
name = gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (orig));
else
{
g_warning ("Don't know how to handle %s targets", G_OBJECT_TYPE_NAME (orig));
return NULL;
}
for (i = 0; i < g_list_model_get_n_items (model); i++)
{
item = g_list_model_get_item (model, i);
g_object_unref (item);
if (GTK_IS_WIDGET (item))
model_name = gtk_widget_get_name (GTK_WIDGET (item));
else
model_name = gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (item));
if (strcmp (name, model_name) == 0)
return GTK_CONSTRAINT_TARGET (item);
}
g_warning ("Failed to find target '%s'", name);
return NULL;
}
gboolean
constraint_editor_window_load (ConstraintEditorWindow *self,
GFile *file)
{
char *path;
GtkBuilder *builder;
GError *error = NULL;
GtkWidget *view;
GtkLayoutManager *layout;
GtkWidget *child;
const char *name;
gpointer item;
int i;
GListModel *list;
path = g_file_get_path (file);
builder = gtk_builder_new ();
if (!gtk_builder_add_from_file (builder, path, &error))
{
g_print ("Could not load %s: %s", path, error->message);
g_error_free (error);
g_free (path);
g_object_unref (builder);
return FALSE;
}
view = GTK_WIDGET (gtk_builder_get_object (builder, "view"));
if (!GTK_IS_BOX (view))
{
g_print ("Could not load %s: No GtkBox named 'view'", path);
g_free (path);
g_object_unref (builder);
return FALSE;
}
layout = gtk_widget_get_layout_manager (view);
if (!GTK_IS_CONSTRAINT_LAYOUT (layout))
{
g_print ("Could not load %s: Widget 'view' does not use GtkConstraintLayout", path);
g_free (path);
g_object_unref (builder);
return FALSE;
}
for (child = gtk_widget_get_first_child (view);
child;
child = gtk_widget_get_next_sibling (child))
{
if (!GTK_IS_LABEL (child))
{
g_print ("Skipping non-GtkLabel child\n");
continue;
}
name = gtk_label_get_label (GTK_LABEL (child));
constraint_view_add_child (CONSTRAINT_VIEW (self->view), name);
}
list = gtk_constraint_layout_observe_guides (GTK_CONSTRAINT_LAYOUT (layout));
for (i = 0; i < g_list_model_get_n_items (list); i++)
{
GtkConstraintGuide *guide, *clone;
int w, h;
item = g_list_model_get_item (list, i);
guide = GTK_CONSTRAINT_GUIDE (item);
/* need to clone here, to attach to the right targets */
clone = gtk_constraint_guide_new ();
gtk_constraint_guide_set_name (clone, gtk_constraint_guide_get_name (guide));
gtk_constraint_guide_set_strength (clone, gtk_constraint_guide_get_strength (guide));
gtk_constraint_guide_get_min_size (guide, &w, &h);
gtk_constraint_guide_set_min_size (clone, w, h);
gtk_constraint_guide_get_nat_size (guide, &w, &h);
gtk_constraint_guide_set_nat_size (clone, w, h);
gtk_constraint_guide_get_max_size (guide, &w, &h);
gtk_constraint_guide_set_max_size (clone, w, h);
constraint_view_add_guide (CONSTRAINT_VIEW (self->view), clone);
g_object_unref (guide);
g_object_unref (clone);
}
g_object_unref (list);
list = gtk_constraint_layout_observe_constraints (GTK_CONSTRAINT_LAYOUT (layout));
for (i = 0; i < g_list_model_get_n_items (list); i++)
{
GtkConstraint *constraint;
GtkConstraint *clone;
GtkConstraintTarget *target;
GtkConstraintTarget *source;
GtkConstraintAttribute source_attr;
item = g_list_model_get_item (list, i);
constraint = GTK_CONSTRAINT (item);
target = gtk_constraint_get_target (constraint);
source = gtk_constraint_get_source (constraint);
source_attr = gtk_constraint_get_source_attribute (constraint);
if (source == NULL && source_attr == GTK_CONSTRAINT_ATTRIBUTE_NONE)
clone = gtk_constraint_new_constant (find_target (constraint_view_get_model (CONSTRAINT_VIEW (self->view)), target),
gtk_constraint_get_target_attribute (constraint),
gtk_constraint_get_relation (constraint),
gtk_constraint_get_constant (constraint),
gtk_constraint_get_strength (constraint));
else
clone = gtk_constraint_new (find_target (constraint_view_get_model (CONSTRAINT_VIEW (self->view)), target),
gtk_constraint_get_target_attribute (constraint),
gtk_constraint_get_relation (constraint),
find_target (constraint_view_get_model (CONSTRAINT_VIEW (self->view)), source),
source_attr,
gtk_constraint_get_multiplier (constraint),
gtk_constraint_get_constant (constraint),
gtk_constraint_get_strength (constraint));
constraint_view_add_constraint (CONSTRAINT_VIEW (self->view), clone);
g_object_unref (constraint);
g_object_unref (clone);
}
g_object_unref (list);
g_free (path);
g_object_unref (builder);
return TRUE;
}
static void
open_response_cb (GtkNativeDialog *dialog,
int response,
ConstraintEditorWindow *self)
{
gtk_native_dialog_hide (dialog);
if (response == GTK_RESPONSE_ACCEPT)
{
GFile *file;
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
constraint_editor_window_load (self, file);
g_object_unref (file);
}
gtk_native_dialog_destroy (dialog);
}
static void
open_cb (GtkWidget *button,
ConstraintEditorWindow *self)
{
GtkFileChooserNative *dialog;
dialog = gtk_file_chooser_native_new ("Open file",
GTK_WINDOW (self),
GTK_FILE_CHOOSER_ACTION_OPEN,
"_Load",
"_Cancel");
gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (dialog), TRUE);
GFile *cwd = g_file_new_for_path (".");
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), cwd, NULL);
g_object_unref (cwd);
g_signal_connect (dialog, "response", G_CALLBACK (open_response_cb), self);
gtk_native_dialog_show (GTK_NATIVE_DIALOG (dialog));
}
static void
serialize_child (GString *str,
int indent,
GtkWidget *child)
{
const char *name;
name = gtk_widget_get_name (child);
g_string_append_printf (str, "%*s<child>\n", indent, "");
g_string_append_printf (str, "%*s <object class=\"GtkLabel\" id=\"%s\">\n", indent, "", name);
g_string_append_printf (str, "%*s <property name=\"label\">%s</property>\n", indent, "", name);
g_string_append_printf (str, "%*s </object>\n", indent, "");
g_string_append_printf (str, "%*s</child>\n", indent, "");
}
static char *
serialize_model (GListModel *list)
{
GString *str = g_string_new ("");
int i;
g_string_append (str, "<interface>\n");
g_string_append (str, " <object class=\"GtkBox\" id=\"view\">\n");
g_string_append (str, " <property name=\"layout-manager\">\n");
g_string_append (str, " <object class=\"GtkConstraintLayout\">\n");
g_string_append (str, " <constraints>\n");
for (i = 0; i < g_list_model_get_n_items (list); i++)
{
gpointer item = g_list_model_get_item (list, i);
g_object_unref (item);
if (GTK_IS_CONSTRAINT (item))
constraint_editor_serialize_constraint (str, 10, GTK_CONSTRAINT (item));
else if (GTK_IS_CONSTRAINT_GUIDE (item))
guide_editor_serialize_guide (str, 10, GTK_CONSTRAINT_GUIDE (item));
}
g_string_append (str, " </constraints>\n");
g_string_append (str, " </object>\n");
g_string_append (str, " </property>\n");
for (i = 0; i < g_list_model_get_n_items (list); i++)
{
gpointer item = g_list_model_get_item (list, i);
g_object_unref (item);
if (GTK_IS_WIDGET (item))
serialize_child (str, 4, GTK_WIDGET (item));
}
g_string_append (str, " </object>\n");
g_string_append (str, "</interface>\n");
return g_string_free (str, FALSE);
}
static void
save_response_cb (GtkNativeDialog *dialog,
int response,
ConstraintEditorWindow *self)
{
gtk_native_dialog_hide (dialog);
if (response == GTK_RESPONSE_ACCEPT)
{
GListModel *model;
GFile *file;
char *text;
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, strlen (text),
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),
"%s", error->message);
g_signal_connect (message_dialog, "response", G_CALLBACK (gtk_window_destroy), NULL);
gtk_widget_show (message_dialog);
g_error_free (error);
}
g_free (text);
g_object_unref (file);
}
gtk_native_dialog_destroy (dialog);
}
static void
save_cb (GtkWidget *button,
ConstraintEditorWindow *self)
{
GtkFileChooserNative *dialog;
dialog = gtk_file_chooser_native_new ("Save constraints",
GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (button))),
GTK_FILE_CHOOSER_ACTION_SAVE,
"_Save",
"_Cancel");
gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (dialog), TRUE);
GFile *cwd = g_file_new_for_path (".");
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), cwd, NULL);
g_object_unref (cwd);
g_signal_connect (dialog, "response", G_CALLBACK (save_response_cb), self);
gtk_native_dialog_show (GTK_NATIVE_DIALOG (dialog));
}
static void
constraint_editor_window_finalize (GObject *object)
{
//ConstraintEditorWindow *self = (ConstraintEditorWindow *)object;
G_OBJECT_CLASS (constraint_editor_window_parent_class)->finalize (object);
}
static int child_counter;
static int guide_counter;
static void
add_child (ConstraintEditorWindow *win)
{
char *name;
child_counter++;
name = g_strdup_printf ("Child %d", child_counter);
constraint_view_add_child (CONSTRAINT_VIEW (win->view), name);
g_free (name);
}
static void
add_guide (ConstraintEditorWindow *win)
{
char *name;
GtkConstraintGuide *guide;
guide_counter++;
name = g_strdup_printf ("Guide %d", guide_counter);
guide = gtk_constraint_guide_new ();
gtk_constraint_guide_set_name (guide, name);
g_free (name);
constraint_view_add_guide (CONSTRAINT_VIEW (win->view), guide);
}
static void
constraint_editor_done (ConstraintEditor *editor,
GtkConstraint *constraint,
ConstraintEditorWindow *win)
{
GtkConstraint *old_constraint;
g_object_get (editor, "constraint", &old_constraint, NULL);
if (old_constraint)
constraint_view_remove_constraint (CONSTRAINT_VIEW (win->view), old_constraint);
constraint_view_add_constraint (CONSTRAINT_VIEW (win->view), constraint);
g_clear_object (&old_constraint);
gtk_window_destroy (GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (editor), GTK_TYPE_WINDOW)));
}
static void
edit_constraint (ConstraintEditorWindow *win,
GtkConstraint *constraint)
{
GtkWidget *window;
ConstraintEditor *editor;
GListModel *model;
window = gtk_window_new ();
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (win));
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
if (constraint)
gtk_window_set_title (GTK_WINDOW (window), "Edit Constraint");
else
gtk_window_set_title (GTK_WINDOW (window), "Create Constraint");
model = constraint_view_get_model (CONSTRAINT_VIEW (win->view));
editor = constraint_editor_new (model, constraint);
gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (editor));
g_signal_connect (editor, "done", G_CALLBACK (constraint_editor_done), win);
gtk_widget_show (window);
}
static void
add_constraint (ConstraintEditorWindow *win)
{
edit_constraint (win, NULL);
}
static void
guide_editor_done (GuideEditor *editor,
GtkConstraintGuide *guide,
ConstraintEditorWindow *win)
{
gtk_window_destroy (GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (editor), GTK_TYPE_WINDOW)));
}
static void
edit_guide (ConstraintEditorWindow *win,
GtkConstraintGuide *guide)
{
GtkWidget *window;
GuideEditor *editor;
window = gtk_window_new ();
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (win));
gtk_window_set_title (GTK_WINDOW (window), "Edit Guide");
editor = guide_editor_new (guide);
gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (editor));
g_signal_connect (editor, "done", G_CALLBACK (guide_editor_done), win);
gtk_widget_show (window);
}
static void
row_activated (GtkListBox *list,
GtkListBoxRow *row,
ConstraintEditorWindow *win)
{
GObject *item;
item = G_OBJECT (g_object_get_data (G_OBJECT (row), "item"));
if (GTK_IS_CONSTRAINT (item))
edit_constraint (win, GTK_CONSTRAINT (item));
else if (GTK_IS_CONSTRAINT_GUIDE (item))
edit_guide (win, GTK_CONSTRAINT_GUIDE (item));
}
static void
constraint_editor_window_class_init (ConstraintEditorWindowClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->finalize = constraint_editor_window_finalize;
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gtk/gtk4/constraint-editor/constraint-editor-window.ui");
gtk_widget_class_bind_template_child (widget_class, ConstraintEditorWindow, paned);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditorWindow, view);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditorWindow, list);
gtk_widget_class_bind_template_callback (widget_class, open_cb);
gtk_widget_class_bind_template_callback (widget_class, save_cb);
gtk_widget_class_bind_template_callback (widget_class, add_child);
gtk_widget_class_bind_template_callback (widget_class, add_guide);
gtk_widget_class_bind_template_callback (widget_class, add_constraint);
gtk_widget_class_bind_template_callback (widget_class, row_activated);
}
static void
row_edit (GtkButton *button,
ConstraintEditorWindow *win)
{
GtkWidget *row;
GObject *item;
row = gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_LIST_BOX_ROW);
item = (GObject *)g_object_get_data (G_OBJECT (row), "item");
if (GTK_IS_CONSTRAINT (item))
edit_constraint (win, GTK_CONSTRAINT (item));
else if (GTK_IS_CONSTRAINT_GUIDE (item))
edit_guide (win, GTK_CONSTRAINT_GUIDE (item));
}
static void
mark_constraints_invalid (ConstraintEditorWindow *win,
gpointer removed)
{
GtkWidget *child;
GObject *item;
for (child = gtk_widget_get_first_child (win->list);
child;
child = gtk_widget_get_next_sibling (child))
{
item = (GObject *)g_object_get_data (G_OBJECT (child), "item");
if (GTK_IS_CONSTRAINT (item))
{
GtkConstraint *constraint = GTK_CONSTRAINT (item);
if (gtk_constraint_get_target (constraint) == (GtkConstraintTarget *)removed ||
gtk_constraint_get_source (constraint) == (GtkConstraintTarget *)removed)
{
GtkWidget *button;
button = (GtkWidget *)g_object_get_data (G_OBJECT (child), "edit");
gtk_button_set_icon_name (GTK_BUTTON (button), "dialog-warning-symbolic");
gtk_widget_set_tooltip_text (button, "Constraint is invalid");
}
}
}
}
static void
row_delete (GtkButton *button,
ConstraintEditorWindow *win)
{
GtkWidget *row;
GObject *item;
row = gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_LIST_BOX_ROW);
item = (GObject *)g_object_get_data (G_OBJECT (row), "item");
if (GTK_IS_CONSTRAINT (item))
constraint_view_remove_constraint (CONSTRAINT_VIEW (win->view),
GTK_CONSTRAINT (item));
else if (GTK_IS_CONSTRAINT_GUIDE (item))
{
mark_constraints_invalid (win, item);
constraint_view_remove_guide (CONSTRAINT_VIEW (win->view),
GTK_CONSTRAINT_GUIDE (item));
}
else if (GTK_IS_WIDGET (item))
{
mark_constraints_invalid (win, item);
constraint_view_remove_child (CONSTRAINT_VIEW (win->view),
GTK_WIDGET (item));
}
}
static GtkWidget *
create_widget_func (gpointer item,
gpointer user_data)
{
ConstraintEditorWindow *win = user_data;
const char *name;
char *freeme = NULL;
GtkWidget *row, *box, *label, *button;
if (GTK_IS_WIDGET (item))
name = gtk_widget_get_name (GTK_WIDGET (item));
else if (GTK_IS_CONSTRAINT_GUIDE (item))
name = gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (item));
else if (GTK_IS_CONSTRAINT (item))
name = freeme = constraint_editor_constraint_to_string (GTK_CONSTRAINT (item));
else
name = "";
row = gtk_list_box_row_new ();
g_object_set_data_full (G_OBJECT (row), "item", g_object_ref (item), g_object_unref);
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
label = gtk_label_new (name);
if (GTK_IS_WIDGET (item) || GTK_IS_CONSTRAINT_GUIDE (item))
g_object_bind_property (item, "name",
label, "label",
G_BINDING_DEFAULT);
gtk_widget_set_margin_start (label, 10);
gtk_widget_set_margin_end (label, 10);
gtk_widget_set_margin_top (label, 10);
gtk_widget_set_margin_bottom (label, 10);
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
gtk_widget_set_hexpand (label, TRUE);
gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), box);
gtk_box_append (GTK_BOX (box), label);
if (GTK_IS_CONSTRAINT (item) || GTK_IS_CONSTRAINT_GUIDE (item))
{
button = gtk_button_new_from_icon_name ("document-edit-symbolic");
gtk_button_set_has_frame (GTK_BUTTON (button), FALSE);
g_signal_connect (button, "clicked", G_CALLBACK (row_edit), win);
g_object_set_data (G_OBJECT (row), "edit", button);
gtk_box_append (GTK_BOX (box), button);
button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
gtk_button_set_has_frame (GTK_BUTTON (button), FALSE);
g_signal_connect (button, "clicked", G_CALLBACK (row_delete), win);
gtk_box_append (GTK_BOX (box), button);
}
else if (GTK_IS_WIDGET (item))
{
button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
gtk_button_set_has_frame (GTK_BUTTON (button), FALSE);
g_signal_connect (button, "clicked", G_CALLBACK (row_delete), win);
gtk_box_append (GTK_BOX (box), button);
}
g_free (freeme);
return row;
}
static void
constraint_editor_window_init (ConstraintEditorWindow *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
gtk_list_box_bind_model (GTK_LIST_BOX (self->list),
constraint_view_get_model (CONSTRAINT_VIEW (self->view)),
create_widget_func,
self,
NULL);
}
ConstraintEditorWindow *
constraint_editor_window_new (ConstraintEditorApplication *application)
{
return g_object_new (CONSTRAINT_EDITOR_WINDOW_TYPE,
"application", application,
NULL);
}
@@ -1,34 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#pragma once
#include <gtk/gtk.h>
#include "constraint-editor-application.h"
#define CONSTRAINT_EDITOR_WINDOW_TYPE (constraint_editor_window_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintEditorWindow, constraint_editor_window, CONSTRAINT, EDITOR_WINDOW, GtkApplicationWindow)
ConstraintEditorWindow * constraint_editor_window_new (ConstraintEditorApplication *application);
gboolean constraint_editor_window_load (ConstraintEditorWindow *self,
GFile *file);
@@ -1,80 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ConstraintEditorWindow" parent="GtkApplicationWindow">
<style>
<class name="devel"/>
</style>
<property name="title" translatable="yes">GTK Constraint Editor</property>
<property name="default-width">1024</property>
<property name="default-height">768</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="header">
<child type="start">
<object class="GtkButton">
<property name="icon-name">document-open-symbolic</property>
<property name="tooltip-text">Open ui file</property>
<signal name="clicked" handler="open_cb"/>
</object>
</child>
<child type="start">
<object class="GtkButton">
<property name="icon-name">document-save-symbolic</property>
<property name="tooltip-text">Save to ui file</property>
<signal name="clicked" handler="save_cb"/>
</object>
</child>
</object>
</child>
<child>
<object class="GtkPaned" id="paned">
<property name="orientation">horizontal</property>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="orientation">horizontal</property>
<child>
<object class="GtkButton">
<property name="label">Add Child</property>
<signal name="clicked" handler="add_child" swapped="yes"/>
</object>
</child>
<child>
<object class="GtkButton">
<property name="label">Add Guide</property>
<signal name="clicked" handler="add_guide" swapped="yes"/>
</object>
</child>
<child>
<object class="GtkButton">
<property name="label">Add Constraint</property>
<signal name="clicked" handler="add_constraint" swapped="yes"/>
</object>
</child>
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="vscrollbar-policy">automatic</property>
<property name="vexpand">1</property>
<child>
<object class="GtkListBox" id="list">
<property name="show-separators">1</property>
<property name="selection-mode">none</property>
<signal name="row-activated" handler="row_activated"/>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="ConstraintView" id="view">
</object>
</child>
</object>
</child>
</template>
</interface>
-680
View File
@@ -1,680 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#include "config.h"
#include "constraint-editor.h"
struct _ConstraintEditor
{
GtkWidget parent_instance;
GtkWidget *grid;
GtkWidget *target;
GtkWidget *target_attr;
GtkWidget *relation;
GtkWidget *source;
GtkWidget *source_attr;
GtkWidget *multiplier;
GtkWidget *constant;
GtkWidget *strength;
GtkWidget *preview;
GtkWidget *button;
GtkConstraint *constraint;
GListModel *model;
gboolean constructed;
};
enum {
PROP_MODEL = 1,
PROP_CONSTRAINT,
LAST_PROP
};
static GParamSpec *pspecs[LAST_PROP];
enum {
DONE,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
G_DEFINE_TYPE(ConstraintEditor, constraint_editor, GTK_TYPE_WIDGET);
static const char *
get_target_name (GtkConstraintTarget *target)
{
if (target == NULL)
return "super";
else if (GTK_IS_WIDGET (target))
return gtk_widget_get_name (GTK_WIDGET (target));
else if (GTK_IS_CONSTRAINT_GUIDE (target))
return gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (target));
else
return "";
}
static void
constraint_target_combo (GListModel *model,
GtkWidget *combo,
gboolean is_source)
{
int i;
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "super", "Super");
if (model)
{
for (i = 0; i < g_list_model_get_n_items (model); i++)
{
GObject *item = g_list_model_get_object (model, i);
const char *name;
if (GTK_IS_CONSTRAINT (item))
continue;
name = get_target_name (GTK_CONSTRAINT_TARGET (item));
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), name, name);
g_object_unref (item);
}
}
}
static void
constraint_attribute_combo (GtkWidget *combo,
gboolean is_source)
{
if (is_source)
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "none", "None");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "left", "Left");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "right", "Right");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "top", "Top");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "bottom", "Bottom");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "start", "Start");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "end", "End");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "width", "Width");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "height", "Height");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "center-x", "Center X");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "center-y", "Center Y");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "baseline", "Baseline");
}
static void
constraint_relation_combo (GtkWidget *combo)
{
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "le", "");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "eq", "=");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "ge", "");
}
static void
constraint_strength_combo (GtkWidget *combo)
{
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "weak", "Weak");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "medium", "Medium");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "strong", "Strong");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "required", "Required");
}
static gpointer
get_target (GListModel *model,
const char *id)
{
int i;
if (id == NULL)
return NULL;
if (strcmp ("super", id) == 0)
return NULL;
for (i = 0; i < g_list_model_get_n_items (model); i++)
{
GObject *item = g_list_model_get_object (model, i);
g_object_unref (item);
if (GTK_IS_CONSTRAINT (item))
continue;
else if (GTK_IS_WIDGET (item))
{
if (strcmp (id, gtk_widget_get_name (GTK_WIDGET (item))) == 0)
return item;
}
else if (GTK_IS_CONSTRAINT_GUIDE (item))
{
if (strcmp (id, gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (item))) == 0)
return item;
}
}
return NULL;
}
static GtkConstraintAttribute
get_target_attr (const char *id)
{
GtkConstraintAttribute attr;
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_ATTRIBUTE);
GEnumValue *value = g_enum_get_value_by_nick (class, id);
attr = value->value;
g_type_class_unref (class);
return attr;
}
static const char *
get_attr_nick (GtkConstraintAttribute attr)
{
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_ATTRIBUTE);
GEnumValue *value = g_enum_get_value (class, attr);
const char *nick = value->value_nick;
g_type_class_unref (class);
return nick;
}
static GtkConstraintRelation
get_relation (const char *id)
{
GtkConstraintRelation relation;
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_RELATION);
GEnumValue *value = g_enum_get_value_by_nick (class, id);
relation = value->value;
g_type_class_unref (class);
return relation;
}
static const char *
get_relation_nick (GtkConstraintRelation relation)
{
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_RELATION);
GEnumValue *value = g_enum_get_value (class, relation);
const char *nick = value->value_nick;
g_type_class_unref (class);
return nick;
}
static const char *
get_relation_display_name (GtkConstraintRelation relation)
{
switch (relation)
{
case GTK_CONSTRAINT_RELATION_LE:
return "";
case GTK_CONSTRAINT_RELATION_EQ:
return "=";
case GTK_CONSTRAINT_RELATION_GE:
return "";
default:
return "?";
}
}
static GtkConstraintStrength
get_strength (const char *id)
{
GtkConstraintStrength strength;
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_STRENGTH);
GEnumValue *value = g_enum_get_value_by_nick (class, id);
strength = value->value;
g_type_class_unref (class);
return strength;
}
static const char *
get_strength_nick (GtkConstraintStrength strength)
{
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_STRENGTH);
GEnumValue *value = g_enum_get_value (class, strength);
const char *nick = value->value_nick;
g_type_class_unref (class);
return nick;
}
void
constraint_editor_serialize_constraint (GString *str,
int indent,
GtkConstraint *constraint)
{
const char *target;
const char *target_attr;
const char *relation;
const char *source;
const char *source_attr;
double multiplier;
double constant;
const char *strength;
target = get_target_name (gtk_constraint_get_target (constraint));
target_attr = get_attr_nick (gtk_constraint_get_target_attribute (constraint));
relation = get_relation_nick (gtk_constraint_get_relation (constraint));
source = get_target_name (gtk_constraint_get_source (constraint));
source_attr = get_attr_nick (gtk_constraint_get_source_attribute (constraint));
multiplier = gtk_constraint_get_multiplier (constraint);
constant = gtk_constraint_get_constant (constraint);
strength = get_strength_nick (gtk_constraint_get_strength (constraint));
g_string_append_printf (str, "%*s<constraint target=\"%s\" target-attribute=\"%s\"\n", indent, "", target, target_attr);
g_string_append_printf (str, "%*s relation=\"%s\"\n", indent, "", relation);
if (strcmp (source_attr, "none") != 0)
{
g_string_append_printf (str, "%*s source=\"%s\" source-attribute=\"%s\"\n", indent, "", source, source_attr);
g_string_append_printf (str, "%*s multiplier=\"%g\"\n", indent, "", multiplier);
}
g_string_append_printf (str, "%*s constant=\"%g\"\n", indent, "", constant);
g_string_append_printf (str, "%*s strength=\"%s\" />\n", indent, "", strength);
}
static void
create_constraint (GtkButton *button,
ConstraintEditor *editor)
{
const char *id;
gpointer target;
GtkConstraintAttribute target_attr;
gpointer source;
GtkConstraintAttribute source_attr;
GtkConstraintRelation relation;
double multiplier;
double constant;
int strength;
GtkConstraint *constraint;
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->target));
target = get_target (editor->model, id);
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->target_attr));
target_attr = get_target_attr (id);
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source));
source = get_target (editor->model, id);
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source_attr));
source_attr = get_target_attr (id);
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->relation));
relation = get_relation (id);
multiplier = g_ascii_strtod (gtk_editable_get_text (GTK_EDITABLE (editor->multiplier)), NULL);
constant = g_ascii_strtod (gtk_editable_get_text (GTK_EDITABLE (editor->constant)), NULL);
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->strength));
strength = get_strength (id);
constraint = gtk_constraint_new (target, target_attr,
relation,
source, source_attr,
multiplier,
constant,
strength);
g_signal_emit (editor, signals[DONE], 0, constraint);
g_object_unref (constraint);
}
static void
source_attr_changed (ConstraintEditor *editor)
{
const char *id;
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source_attr));
if (strcmp (id, "none") == 0)
{
gtk_combo_box_set_active (GTK_COMBO_BOX (editor->source), -1);
gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), "");
gtk_widget_set_sensitive (editor->source, FALSE);
gtk_widget_set_sensitive (editor->multiplier, FALSE);
}
else
{
gtk_widget_set_sensitive (editor->source, TRUE);
gtk_widget_set_sensitive (editor->multiplier, TRUE);
gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), "1");
}
}
char *
constraint_editor_constraint_to_string (GtkConstraint *constraint)
{
GString *str;
const char *name;
const char *attr;
const char *relation;
double c, m;
str = g_string_new ("");
name = get_target_name (gtk_constraint_get_target (constraint));
attr = get_attr_nick (gtk_constraint_get_target_attribute (constraint));
relation = get_relation_display_name (gtk_constraint_get_relation (constraint));
if (name == NULL)
name = "[ ]";
g_string_append_printf (str, "%s.%s %s ", name, attr, relation);
c = gtk_constraint_get_constant (constraint);
attr = get_attr_nick (gtk_constraint_get_source_attribute (constraint));
if (strcmp (attr, "none") != 0)
{
name = get_target_name (gtk_constraint_get_source (constraint));
m = gtk_constraint_get_multiplier (constraint);
if (name == NULL)
name = "[ ]";
g_string_append_printf (str, "%s.%s", name, attr);
if (m != 1.0)
g_string_append_printf (str, " × %g", m);
if (c > 0.0)
g_string_append_printf (str, " + %g", c);
else if (c < 0.0)
g_string_append_printf (str, " - %g", -c);
}
else
g_string_append_printf (str, "%g", c);
return g_string_free (str, FALSE);
}
static void
update_preview (ConstraintEditor *editor)
{
GString *str;
const char *name;
const char *attr;
char *relation;
const char *multiplier;
const char *constant;
double c, m;
if (!editor->constructed)
return;
str = g_string_new ("");
name = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->target));
attr = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->target_attr));
relation = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (editor->relation));
if (name == NULL)
name = "[ ]";
g_string_append_printf (str, "%s.%s %s ", name, attr, relation);
g_free (relation);
constant = gtk_editable_get_text (GTK_EDITABLE (editor->constant));
c = g_ascii_strtod (constant, NULL);
attr = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source_attr));
if (strcmp (attr, "none") != 0)
{
name = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source));
multiplier = gtk_editable_get_text (GTK_EDITABLE (editor->multiplier));
m = g_ascii_strtod (multiplier, NULL);
if (name == NULL)
name = "[ ]";
g_string_append_printf (str, "%s.%s", name, attr);
if (m != 1.0)
g_string_append_printf (str, " × %g", m);
if (c > 0.0)
g_string_append_printf (str, " + %g", c);
else if (c < 0.0)
g_string_append_printf (str, " - %g", -c);
}
else
g_string_append_printf (str, "%g", c);
gtk_label_set_label (GTK_LABEL (editor->preview), str->str);
g_string_free (str, TRUE);
}
static void
update_button (ConstraintEditor *editor)
{
const char *target = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->target));
const char *source = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source));
const char *source_attr = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->source_attr));
if (target &&
(source || (source_attr && get_target_attr (source_attr) == GTK_CONSTRAINT_ATTRIBUTE_NONE)))
gtk_widget_set_sensitive (editor->button, TRUE);
else
gtk_widget_set_sensitive (editor->button, FALSE);
}
static void
constraint_editor_init (ConstraintEditor *editor)
{
gtk_widget_init_template (GTK_WIDGET (editor));
}
static void
constraint_editor_constructed (GObject *object)
{
ConstraintEditor *editor = CONSTRAINT_EDITOR (object);
constraint_target_combo (editor->model, editor->target, FALSE);
constraint_attribute_combo (editor->target_attr, FALSE);
constraint_relation_combo (editor->relation);
constraint_target_combo (editor->model, editor->source, TRUE);
constraint_attribute_combo (editor->source_attr, TRUE);
constraint_strength_combo (editor->strength);
if (editor->constraint)
{
GtkConstraintTarget *target;
GtkConstraintAttribute attr;
GtkConstraintRelation relation;
GtkConstraintStrength strength;
const char *nick;
char *val;
double multiplier;
double constant;
target = gtk_constraint_get_target (editor->constraint);
nick = get_target_name (target);
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->target), nick);
attr = gtk_constraint_get_target_attribute (editor->constraint);
nick = get_attr_nick (attr);
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->target_attr), nick);
target = gtk_constraint_get_source (editor->constraint);
nick = get_target_name (target);
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->source), nick);
attr = gtk_constraint_get_source_attribute (editor->constraint);
nick = get_attr_nick (attr);
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->source_attr), nick);
relation = gtk_constraint_get_relation (editor->constraint);
nick = get_relation_nick (relation);
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->relation), nick);
multiplier = gtk_constraint_get_multiplier (editor->constraint);
val = g_strdup_printf ("%g", multiplier);
gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), val);
g_free (val);
constant = gtk_constraint_get_constant (editor->constraint);
val = g_strdup_printf ("%g", constant);
gtk_editable_set_text (GTK_EDITABLE (editor->constant), val);
g_free (val);
strength = gtk_constraint_get_strength (editor->constraint);
nick = get_strength_nick (strength);
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->strength), nick);
gtk_button_set_label (GTK_BUTTON (editor->button), "Apply");
}
else
{
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->target_attr), "left");
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->source_attr), "left");
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->relation), "eq");
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->strength), "required");
gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), "1.0");
gtk_editable_set_text (GTK_EDITABLE (editor->constant), "0.0");
gtk_button_set_label (GTK_BUTTON (editor->button), "Create");
}
editor->constructed = TRUE;
update_preview (editor);
update_button (editor);
}
static void
constraint_editor_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
ConstraintEditor *self = CONSTRAINT_EDITOR (object);
switch (property_id)
{
case PROP_MODEL:
self->model = g_value_dup_object (value);
break;
case PROP_CONSTRAINT:
self->constraint = g_value_dup_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
constraint_editor_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
ConstraintEditor *self = CONSTRAINT_EDITOR (object);
switch (property_id)
{
case PROP_MODEL:
g_value_set_object (value, self->model);
break;
case PROP_CONSTRAINT:
g_value_set_object (value, self->constraint);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
constraint_editor_dispose (GObject *object)
{
ConstraintEditor *self = (ConstraintEditor *)object;
g_clear_pointer (&self->grid, gtk_widget_unparent);
g_clear_object (&self->model);
g_clear_object (&self->constraint);
G_OBJECT_CLASS (constraint_editor_parent_class)->dispose (object);
}
static void
constraint_editor_class_init (ConstraintEditorClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->constructed = constraint_editor_constructed;
object_class->dispose = constraint_editor_dispose;
object_class->set_property = constraint_editor_set_property;
object_class->get_property = constraint_editor_get_property;
pspecs[PROP_CONSTRAINT] =
g_param_spec_object ("constraint", "constraint", "constraint",
GTK_TYPE_CONSTRAINT,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);
pspecs[PROP_MODEL] =
g_param_spec_object ("model", "model", "model",
G_TYPE_LIST_MODEL,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_properties (object_class, LAST_PROP, pspecs);
signals[DONE] =
g_signal_new ("done",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
NULL,
G_TYPE_NONE, 1, GTK_TYPE_CONSTRAINT);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gtk/gtk4/constraint-editor/constraint-editor.ui");
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, grid);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, target);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, target_attr);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, relation);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, source);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, source_attr);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, multiplier);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, constant);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, strength);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, preview);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, button);
gtk_widget_class_bind_template_callback (widget_class, update_preview);
gtk_widget_class_bind_template_callback (widget_class, update_button);
gtk_widget_class_bind_template_callback (widget_class, create_constraint);
gtk_widget_class_bind_template_callback (widget_class, source_attr_changed);
}
ConstraintEditor *
constraint_editor_new (GListModel *model,
GtkConstraint *constraint)
{
return g_object_new (CONSTRAINT_EDITOR_TYPE,
"model", model,
"constraint", constraint,
NULL);
}
@@ -1,12 +0,0 @@
constraintview {
background: black;
color: white;
}
constraintview .child {
background: red;
}
constraintview .guide {
background: blue;
}
@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gtk/gtk4/constraint-editor">
<file preprocess="xml-stripblanks">constraint-editor-window.ui</file>
<file preprocess="xml-stripblanks">constraint-editor.ui</file>
<file preprocess="xml-stripblanks">guide-editor.ui</file>
<file>constraint-editor.css</file>
</gresource>
</gresources>
@@ -1,34 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#pragma once
#include <gtk/gtk.h>
#define CONSTRAINT_EDITOR_TYPE (constraint_editor_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintEditor, constraint_editor, CONSTRAINT, EDITOR, GtkWidget)
ConstraintEditor * constraint_editor_new (GListModel *model,
GtkConstraint *constraint);
void constraint_editor_serialize_constraint (GString *str,
int indent,
GtkConstraint *constraint);
char *constraint_editor_constraint_to_string (GtkConstraint *constraint);
@@ -1,167 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ConstraintEditor" parent="GtkWidget">
<child>
<object class="GtkGrid" id="grid">
<property name="margin-start">20</property>
<property name="margin-end">20</property>
<property name="margin-top">20</property>
<property name="margin-bottom">20</property>
<property name="row-spacing">10</property>
<property name="column-spacing">10</property>
<child>
<object class="GtkLabel">
<property name="label">Target</property>
<layout>
<property name="column">0</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkComboBoxText" id="target">
<signal name="changed" handler="update_preview" swapped="yes"/>
<signal name="changed" handler="update_button" swapped="yes"/>
<layout>
<property name="column">1</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkComboBoxText" id="target_attr">
<signal name="changed" handler="update_preview" swapped="yes"/>
<layout>
<property name="column">2</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Relation</property>
<layout>
<property name="column">0</property>
<property name="row">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkComboBoxText" id="relation">
<signal name="changed" handler="update_preview" swapped="yes"/>
<layout>
<property name="column">1</property>
<property name="row">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Source</property>
<layout>
<property name="column">0</property>
<property name="row">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkComboBoxText" id="source">
<signal name="changed" handler="update_preview" swapped="yes"/>
<signal name="changed" handler="update_button" swapped="yes"/>
<layout>
<property name="column">1</property>
<property name="row">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkComboBoxText" id="source_attr">
<signal name="changed" handler="update_preview" swapped="yes"/>
<signal name="changed" handler="source_attr_changed" swapped="yes"/>
<signal name="changed" handler="update_button" swapped="yes"/>
<layout>
<property name="column">2</property>
<property name="row">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Multiplier</property>
<layout>
<property name="column">0</property>
<property name="row">4</property>
</layout>
</object>
</child>
<child>
<object class="GtkEntry" id="multiplier">
<signal name="changed" handler="update_preview" swapped="yes"/>
<layout>
<property name="column">1</property>
<property name="row">4</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Constant</property>
<layout>
<property name="column">0</property>
<property name="row">5</property>
</layout>
</object>
</child>
<child>
<object class="GtkEntry" id="constant">
<signal name="changed" handler="update_preview" swapped="yes"/>
<layout>
<property name="column">1</property>
<property name="row">5</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Strength</property>
<layout>
<property name="column">0</property>
<property name="row">6</property>
</layout>
</object>
</child>
<child>
<object class="GtkComboBoxText" id="strength">
<layout>
<property name="column">1</property>
<property name="row">6</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel" id="preview">
<property name="xalign">0</property>
<layout>
<property name="column">1</property>
<property name="row">7</property>
<property name="column-span">2</property>
</layout>
<attributes>
<attribute name="scale" value="1.44"/>
</attributes>
</object>
</child>
<child>
<object class="GtkButton" id="button">
<property name="label">Create</property>
<signal name="clicked" handler="create_constraint"/>
<layout>
<property name="column">2</property>
<property name="row">8</property>
</layout>
</object>
</child>
</object>
</child>
</template>
</interface>
@@ -1,93 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#include "constraint-view-child.h"
struct _ConstraintViewChild
{
GObject parent_instance;
char *name;
};
enum {
PROP_NAME = 1,
LAST_PROP
};
static GParamSpec props[LAST_PROP];
G_DEFINE_TYPE (ConstraintViewChild, constraint_view_child, G_TYPE_OBJECT)
static void
constraint_view_child_init (ConstraintViewChild *child)
{
}
static void
constraint_view_child_finalize (GObject *object)
{
ConstraintViewChild *child = CONSTRAINT_VIEW_CHILD (object);
g_free (child->name);
G_OBJECT_CLASS (constraint_view_child_parent_class)->finalize (object);
}
static void
constraint_view_child_set_property (GObject *object,
static void
constraint_view_child_class_init (ConstraintViewChildClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->finalize = constraint_view_child_finalize;
object_class->get_property = constraint_view_child_get_property;
object_class->set_property = constraint_view_child_set_property;
props[PROP_NAME] =
g_param_spec_string ("name", "name", "name",
NULL,
G_PARAM_READWRITE);
g_object_class_install_properties (object_class, LAST_PROP, props);
}
#define CONSTRAINT_VIEW_CHILD_TYPE (constraint_view_get_type ())
G_DECLARE_TYPE (ConstraintViewChild, constraint_view_child, CONSTRAINT, VIEW_CHILD, GObject)
#define CONSTRAINT_VIEW_WIDGET_TYPE (constraint_view_widget_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewWidget, constraint_view_widget, CONSTRAINT, VIEW_WIDGET, ConstraintViewChild)
ConstraintViewWidget * constraint_view_widget_new (void);
#define CONSTRAINT_VIEW_GUIDE_TYPE (constraint_view_guide_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewGuide, constraint_view_guide, CONSTRAINT, VIEW_GUIDE, ConstraintViewChild)
ConstraintViewGuide * constraint_view_guide_new (void);
#define CONSTRAINT_VIEW_CONSTRAINT_TYPE (constraint_view_constraint_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewConstraint, constraint_view_constraint, CONSTRAINT, VIEW_CONSTRAINT, ConstraintViewChild)
ConstraintViewGuide * constraint_view_constraint_new (void);
@@ -1,44 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#pragma once
#include <gtk/gtk.h>
#define CONSTRAINT_VIEW_CHILD_TYPE (constraint_view_get_type ())
G_DECLARE_TYPE (ConstraintViewChild, constraint_view_child, CONSTRAINT, VIEW_CHILD, GObject)
#define CONSTRAINT_VIEW_WIDGET_TYPE (constraint_view_widget_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewWidget, constraint_view_widget, CONSTRAINT, VIEW_WIDGET, ConstraintViewChild)
ConstraintViewWidget * constraint_view_widget_new (void);
#define CONSTRAINT_VIEW_GUIDE_TYPE (constraint_view_guide_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewGuide, constraint_view_guide, CONSTRAINT, VIEW_GUIDE, ConstraintViewChild)
ConstraintViewGuide * constraint_view_guide_new (void);
#define CONSTRAINT_VIEW_CONSTRAINT_TYPE (constraint_view_constraint_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewConstraint, constraint_view_constraint, CONSTRAINT, VIEW_CONSTRAINT, ConstraintViewChild)
ConstraintViewGuide * constraint_view_constraint_new (void);
-345
View File
@@ -1,345 +0,0 @@
/* Copyright (C) 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <gtk/gtk.h>
#include "constraint-view.h"
struct _ConstraintView
{
GtkWidget parent;
GListModel *model;
GtkWidget *drag_widget;
};
G_DEFINE_TYPE (ConstraintView, constraint_view, GTK_TYPE_WIDGET);
static void
constraint_view_dispose (GObject *object)
{
ConstraintView *view = CONSTRAINT_VIEW (object);
GtkWidget *child;
while ((child = gtk_widget_get_first_child (GTK_WIDGET (view))) != NULL)
gtk_widget_unparent (child);
g_clear_object (&view->model);
G_OBJECT_CLASS (constraint_view_parent_class)->dispose (object);
}
static void
constraint_view_class_init (ConstraintViewClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = constraint_view_dispose;
gtk_widget_class_set_css_name (widget_class, "constraintview");
}
static void
update_weak_position (ConstraintView *self,
GtkWidget *child,
double x,
double y)
{
GtkLayoutManager *manager;
GtkConstraint *constraint;
manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
constraint = (GtkConstraint *)g_object_get_data (G_OBJECT (child), "x-constraint");
if (constraint)
{
gtk_constraint_layout_remove_constraint (GTK_CONSTRAINT_LAYOUT (manager),
constraint);
g_object_set_data (G_OBJECT (child), "x-constraint", NULL);
}
if (x != -100)
{
constraint = gtk_constraint_new_constant (child,
GTK_CONSTRAINT_ATTRIBUTE_CENTER_X,
GTK_CONSTRAINT_RELATION_EQ,
x,
GTK_CONSTRAINT_STRENGTH_WEAK);
g_object_set_data (G_OBJECT (constraint), "internal", (char *)"yes");
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (manager),
constraint);
g_object_set_data (G_OBJECT (child), "x-constraint", constraint);
}
constraint = (GtkConstraint *)g_object_get_data (G_OBJECT (child), "y-constraint");
if (constraint)
{
gtk_constraint_layout_remove_constraint (GTK_CONSTRAINT_LAYOUT (manager),
constraint);
g_object_set_data (G_OBJECT (child), "y-constraint", NULL);
}
if (y != -100)
{
constraint = gtk_constraint_new_constant (child,
GTK_CONSTRAINT_ATTRIBUTE_CENTER_Y,
GTK_CONSTRAINT_RELATION_EQ,
y,
GTK_CONSTRAINT_STRENGTH_WEAK);
g_object_set_data (G_OBJECT (constraint), "internal", (char *)"yes");
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (manager),
constraint);
g_object_set_data (G_OBJECT (child), "y-constraint", constraint);
}
}
static void
drag_begin (GtkGestureDrag *drag,
double start_x,
double start_y,
ConstraintView *self)
{
GtkWidget *widget;
widget = gtk_widget_pick (GTK_WIDGET (self), start_x, start_y, GTK_PICK_DEFAULT);
if (GTK_IS_LABEL (widget))
{
widget = gtk_widget_get_ancestor (widget, GTK_TYPE_FRAME);
if (widget &&
gtk_widget_get_parent (widget) == (GtkWidget *)self)
{
self->drag_widget = widget;
}
}
}
static void
drag_update (GtkGestureDrag *drag,
double offset_x,
double offset_y,
ConstraintView *self)
{
double x, y;
if (!self->drag_widget)
return;
gtk_gesture_drag_get_start_point (drag, &x, &y);
update_weak_position (self, self->drag_widget, x + offset_x, y + offset_y);
}
static void
drag_end (GtkGestureDrag *drag,
double offset_x,
double offset_y,
ConstraintView *self)
{
self->drag_widget = NULL;
}
static gboolean
omit_internal (gpointer item, gpointer user_data)
{
if (g_object_get_data (G_OBJECT (item), "internal"))
return FALSE;
return TRUE;
}
static void
constraint_view_init (ConstraintView *self)
{
GtkLayoutManager *manager;
GtkEventController *controller;
GListStore *list;
GListModel *all_children;
GListModel *all_constraints;
GListModel *guides;
GListModel *children;
GListModel *constraints;
GtkFilter *filter;
manager = gtk_constraint_layout_new ();
gtk_widget_set_layout_manager (GTK_WIDGET (self), manager);
guides = gtk_constraint_layout_observe_guides (GTK_CONSTRAINT_LAYOUT (manager));
all_constraints = gtk_constraint_layout_observe_constraints (GTK_CONSTRAINT_LAYOUT (manager));
filter = GTK_FILTER (gtk_custom_filter_new (omit_internal, NULL, NULL));
constraints = (GListModel *)gtk_filter_list_model_new (all_constraints, filter);
all_children = gtk_widget_observe_children (GTK_WIDGET (self));
filter = GTK_FILTER (gtk_custom_filter_new (omit_internal, NULL, NULL));
children = (GListModel *)gtk_filter_list_model_new (all_children, filter);
list = g_list_store_new (G_TYPE_LIST_MODEL);
g_list_store_append (list, children);
g_list_store_append (list, guides);
g_list_store_append (list, constraints);
g_object_unref (children);
g_object_unref (guides);
g_object_unref (constraints);
self->model = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (list)));
controller = (GtkEventController *)gtk_gesture_drag_new ();
g_signal_connect (controller, "drag-begin", G_CALLBACK (drag_begin), self);
g_signal_connect (controller, "drag-update", G_CALLBACK (drag_update), self);
g_signal_connect (controller, "drag-end", G_CALLBACK (drag_end), self);
gtk_widget_add_controller (GTK_WIDGET (self), controller);
}
ConstraintView *
constraint_view_new (void)
{
return g_object_new (CONSTRAINT_VIEW_TYPE, NULL);
}
void
constraint_view_add_child (ConstraintView *view,
const char *name)
{
GtkWidget *frame;
GtkWidget *label;
label = gtk_label_new (name);
frame = gtk_frame_new (NULL);
gtk_widget_add_css_class (frame, "child");
gtk_widget_set_name (frame, name);
gtk_frame_set_child (GTK_FRAME (frame), label);
gtk_widget_set_parent (frame, GTK_WIDGET (view));
update_weak_position (view, frame, 100, 100);
}
void
constraint_view_remove_child (ConstraintView *view,
GtkWidget *child)
{
update_weak_position (view, child, -100, -100);
gtk_widget_unparent (child);
}
void
constraint_view_add_guide (ConstraintView *view,
GtkConstraintGuide *guide)
{
GtkConstraintLayout *layout;
GtkWidget *frame;
GtkWidget *label;
const char *name;
GtkConstraint *constraint;
struct {
const char *name;
GtkConstraintAttribute attr;
} names[] = {
{ "left-constraint", GTK_CONSTRAINT_ATTRIBUTE_LEFT },
{ "top-constraint", GTK_CONSTRAINT_ATTRIBUTE_TOP },
{ "width-constraint", GTK_CONSTRAINT_ATTRIBUTE_WIDTH },
{ "height-constraint", GTK_CONSTRAINT_ATTRIBUTE_HEIGHT },
};
int i;
name = gtk_constraint_guide_get_name (guide);
label = gtk_label_new (name);
g_object_bind_property (guide, "name",
label, "label",
G_BINDING_DEFAULT);
frame = gtk_frame_new (NULL);
gtk_widget_add_css_class (frame, "guide");
g_object_set_data (G_OBJECT (frame), "internal", (char *)"yes");
gtk_frame_set_child (GTK_FRAME (frame), label);
gtk_widget_insert_after (frame, GTK_WIDGET (view), NULL);
g_object_set_data (G_OBJECT (guide), "frame", frame);
layout = GTK_CONSTRAINT_LAYOUT (gtk_widget_get_layout_manager (GTK_WIDGET (view)));
gtk_constraint_layout_add_guide (layout, g_object_ref (guide));
for (i = 0; i < G_N_ELEMENTS (names); i++)
{
constraint = gtk_constraint_new (frame,
names[i].attr,
GTK_CONSTRAINT_RELATION_EQ,
guide,
names[i].attr,
1.0, 0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
g_object_set_data (G_OBJECT (constraint), "internal", (char *)"yes");
gtk_constraint_layout_add_constraint (layout, constraint);
g_object_set_data (G_OBJECT (guide), names[i].name, constraint);
}
update_weak_position (view, frame, 150, 150);
}
void
constraint_view_remove_guide (ConstraintView *view,
GtkConstraintGuide *guide)
{
GtkConstraintLayout *layout;
GtkWidget *frame;
GtkConstraint *constraint;
const char *names[] = {
"left-constraint",
"top-constraint",
"width-constraint",
"height-constraint"
};
int i;
layout = GTK_CONSTRAINT_LAYOUT (gtk_widget_get_layout_manager (GTK_WIDGET (view)));
for (i = 0; i < G_N_ELEMENTS (names); i++)
{
constraint = (GtkConstraint*)g_object_get_data (G_OBJECT (guide), names[i]);
gtk_constraint_layout_remove_constraint (layout, constraint);
}
frame = (GtkWidget *)g_object_get_data (G_OBJECT (guide), "frame");
update_weak_position (view, frame, -100, -100);
gtk_widget_unparent (frame);
gtk_constraint_layout_remove_guide (layout, guide);
}
void
constraint_view_add_constraint (ConstraintView *view,
GtkConstraint *constraint)
{
GtkLayoutManager *manager;
manager = gtk_widget_get_layout_manager (GTK_WIDGET (view));
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (manager),
g_object_ref (constraint));
}
void
constraint_view_remove_constraint (ConstraintView *view,
GtkConstraint *constraint)
{
GtkLayoutManager *manager;
manager = gtk_widget_get_layout_manager (GTK_WIDGET (view));
gtk_constraint_layout_remove_constraint (GTK_CONSTRAINT_LAYOUT (manager),
constraint);
}
GListModel *
constraint_view_get_model (ConstraintView *view)
{
return view->model;
}
-45
View File
@@ -1,45 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#pragma once
#include <gtk/gtk.h>
#define CONSTRAINT_VIEW_TYPE (constraint_view_get_type ())
G_MODULE_EXPORT
G_DECLARE_FINAL_TYPE (ConstraintView, constraint_view, CONSTRAINT, VIEW, GtkWidget)
ConstraintView * constraint_view_new (void);
void constraint_view_add_child (ConstraintView *view,
const char *name);
void constraint_view_remove_child (ConstraintView *view,
GtkWidget *child);
void constraint_view_add_guide (ConstraintView *view,
GtkConstraintGuide *guide);
void constraint_view_remove_guide (ConstraintView *view,
GtkConstraintGuide *guide);
void constraint_view_guide_changed (ConstraintView *view,
GtkConstraintGuide *guide);
void constraint_view_add_constraint (ConstraintView *view,
GtkConstraint *constraint);
void constraint_view_remove_constraint (ConstraintView *view,
GtkConstraint *constraint);
GListModel * constraint_view_get_model (ConstraintView *view);
-355
View File
@@ -1,355 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#include "config.h"
#include "guide-editor.h"
struct _GuideEditor
{
GtkWidget parent_instance;
GtkWidget *grid;
GtkWidget *name;
GtkWidget *min_width;
GtkWidget *min_height;
GtkWidget *nat_width;
GtkWidget *nat_height;
GtkWidget *max_width;
GtkWidget *max_height;
GtkWidget *strength;
GtkWidget *button;
GtkConstraintGuide *guide;
gboolean constructed;
};
enum {
PROP_GUIDE = 1,
LAST_PROP
};
static GParamSpec *pspecs[LAST_PROP];
enum {
DONE,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
G_DEFINE_TYPE(GuideEditor, guide_editor, GTK_TYPE_WIDGET);
static void
guide_strength_combo (GtkWidget *combo)
{
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "weak", "Weak");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "medium", "Medium");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "strong", "Strong");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "required", "Required");
}
static GtkConstraintStrength
get_strength (const char *id)
{
GtkConstraintStrength strength;
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_STRENGTH);
GEnumValue *value = g_enum_get_value_by_nick (class, id);
strength = value->value;
g_type_class_unref (class);
return strength;
}
static const char *
get_strength_nick (GtkConstraintStrength strength)
{
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_STRENGTH);
GEnumValue *value = g_enum_get_value (class, strength);
const char *nick = value->value_nick;
g_type_class_unref (class);
return nick;
}
void
guide_editor_serialize_guide (GString *str,
int indent,
GtkConstraintGuide *guide)
{
int min_width, min_height;
int nat_width, nat_height;
int max_width, max_height;
const char *name;
const char *strength;
gtk_constraint_guide_get_min_size (guide, &min_width, &min_height);
gtk_constraint_guide_get_nat_size (guide, &nat_width, &nat_height);
gtk_constraint_guide_get_max_size (guide, &max_width, &max_height);
name = gtk_constraint_guide_get_name (guide);
strength = get_strength_nick (gtk_constraint_guide_get_strength (guide));
g_string_append_printf (str, "%*s<guide min-width=\"%d\" min-height=\"%d\"\n", indent, "", min_width, min_height);
g_string_append_printf (str, "%*s nat-width=\"%d\" nat-height=\"%d\"\n", indent, "", nat_width, nat_height);
g_string_append_printf (str, "%*s max-width=\"%d\" max-height=\"%d\"\n", indent, "", max_width, max_height);
g_string_append_printf (str, "%*s name=\"%s\" strength=\"%s\" />\n", indent, "", name, strength);
}
static void
create_guide (GtkButton *button,
GuideEditor *editor)
{
const char *id;
int strength;
const char *name;
int w, h;
GtkConstraintGuide *guide;
if (editor->guide)
guide = g_object_ref (editor->guide);
else
guide = gtk_constraint_guide_new ();
name = gtk_editable_get_text (GTK_EDITABLE (editor->name));
gtk_constraint_guide_set_name (guide, name);
w = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->min_width));
h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->min_height));
gtk_constraint_guide_set_min_size (guide, w, h);
w = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->nat_width));
h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->nat_height));
gtk_constraint_guide_set_nat_size (guide, w, h);
w = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->max_width));
h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->max_height));
gtk_constraint_guide_set_max_size (guide, w, h);
id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (editor->strength));
strength = get_strength (id);
gtk_constraint_guide_set_strength (guide, strength);
g_signal_emit (editor, signals[DONE], 0, guide);
g_object_unref (guide);
}
static void
guide_editor_init (GuideEditor *editor)
{
gtk_widget_init_template (GTK_WIDGET (editor));
}
static int guide_counter;
static int
min_input (GtkSpinButton *spin_button,
double *new_val)
{
if (strcmp (gtk_editable_get_text (GTK_EDITABLE (spin_button)), "") == 0)
{
*new_val = 0.0;
return TRUE;
}
return FALSE;
}
static int
max_input (GtkSpinButton *spin_button,
double *new_val)
{
if (strcmp (gtk_editable_get_text (GTK_EDITABLE (spin_button)), "") == 0)
{
*new_val = G_MAXINT;
return TRUE;
}
return FALSE;
}
static void
guide_editor_constructed (GObject *object)
{
GuideEditor *editor = GUIDE_EDITOR (object);
guide_strength_combo (editor->strength);
g_signal_connect (editor->min_width, "input", G_CALLBACK (min_input), NULL);
g_signal_connect (editor->min_height, "input", G_CALLBACK (min_input), NULL);
g_signal_connect (editor->max_width, "input", G_CALLBACK (max_input), NULL);
g_signal_connect (editor->max_height, "input", G_CALLBACK (max_input), NULL);
if (editor->guide)
{
GtkConstraintStrength strength;
const char *nick;
int w, h;
nick = gtk_constraint_guide_get_name (editor->guide);
if (nick)
gtk_editable_set_text (GTK_EDITABLE (editor->name), nick);
gtk_constraint_guide_get_min_size (editor->guide, &w, &h);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->min_width), w);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->min_height), h);
gtk_constraint_guide_get_nat_size (editor->guide, &w, &h);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->nat_width), w);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->nat_height), h);
gtk_constraint_guide_get_max_size (editor->guide, &w, &h);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_width), w);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_height), h);
strength = gtk_constraint_guide_get_strength (editor->guide);
nick = get_strength_nick (strength);
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->strength), nick);
gtk_button_set_label (GTK_BUTTON (editor->button), "Apply");
}
else
{
char *name;
guide_counter++;
name = g_strdup_printf ("Guide %d", guide_counter);
gtk_editable_set_text (GTK_EDITABLE (editor->name), name);
g_free (name);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->min_width), 0.0);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->min_height), 0.0);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->nat_width), 0.0);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->nat_height), 0.0);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_width), G_MAXINT);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_height), G_MAXINT);
gtk_combo_box_set_active_id (GTK_COMBO_BOX (editor->strength), "medium");
gtk_button_set_label (GTK_BUTTON (editor->button), "Create");
}
editor->constructed = TRUE;
}
static void
guide_editor_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GuideEditor *self = GUIDE_EDITOR (object);
switch (property_id)
{
case PROP_GUIDE:
self->guide = g_value_dup_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
guide_editor_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GuideEditor *self = GUIDE_EDITOR (object);
switch (property_id)
{
case PROP_GUIDE:
g_value_set_object (value, self->guide);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
guide_editor_dispose (GObject *object)
{
GuideEditor *self = (GuideEditor *)object;
g_clear_pointer (&self->grid, gtk_widget_unparent);
g_clear_object (&self->guide);
G_OBJECT_CLASS (guide_editor_parent_class)->dispose (object);
}
static void
guide_editor_class_init (GuideEditorClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->constructed = guide_editor_constructed;
object_class->dispose = guide_editor_dispose;
object_class->set_property = guide_editor_set_property;
object_class->get_property = guide_editor_get_property;
pspecs[PROP_GUIDE] =
g_param_spec_object ("guide", "guide", "guide",
GTK_TYPE_CONSTRAINT_GUIDE,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_properties (object_class, LAST_PROP, pspecs);
signals[DONE] =
g_signal_new ("done",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
NULL,
G_TYPE_NONE, 1, GTK_TYPE_CONSTRAINT_GUIDE);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gtk/gtk4/constraint-editor/guide-editor.ui");
gtk_widget_class_bind_template_child (widget_class, GuideEditor, grid);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, name);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, min_width);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, min_height);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, nat_width);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, nat_height);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, max_width);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, max_height);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, strength);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, button);
gtk_widget_class_bind_template_callback (widget_class, create_guide);
}
GuideEditor *
guide_editor_new (GtkConstraintGuide *guide)
{
return g_object_new (GUIDE_EDITOR_TYPE,
"guide", guide,
NULL);
}
-32
View File
@@ -1,32 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#pragma once
#include <gtk/gtk.h>
#define GUIDE_EDITOR_TYPE (guide_editor_get_type ())
G_DECLARE_FINAL_TYPE (GuideEditor, guide_editor, GUIDE, EDITOR, GtkWidget)
GuideEditor * guide_editor_new (GtkConstraintGuide *guide);
void guide_editor_serialize_guide (GString *str,
int indent,
GtkConstraintGuide *guide);
-191
View File
@@ -1,191 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkAdjustment" id="min_width_adj">
<property name="lower">0</property>
<property name="upper">2147483647</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
<property name="page-size">0</property>
</object>
<object class="GtkAdjustment" id="min_height_adj">
<property name="lower">0</property>
<property name="upper">2147483647</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
<property name="page-size">0</property>
</object>
<object class="GtkAdjustment" id="nat_width_adj">
<property name="lower">0</property>
<property name="upper">2147483647</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
<property name="page-size">0</property>
</object>
<object class="GtkAdjustment" id="nat_height_adj">
<property name="lower">0</property>
<property name="upper">2147483647</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
<property name="page-size">0</property>
</object>
<object class="GtkAdjustment" id="max_width_adj">
<property name="lower">0</property>
<property name="upper">2147483647</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
<property name="page-size">0</property>
</object>
<object class="GtkAdjustment" id="max_height_adj">
<property name="lower">0</property>
<property name="upper">2147483647</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
<property name="page-size">0</property>
</object>
<template class="GuideEditor" parent="GtkWidget">
<child>
<object class="GtkGrid" id="grid">
<property name="margin-start">20</property>
<property name="margin-end">20</property>
<property name="margin-top">20</property>
<property name="margin-bottom">20</property>
<property name="row-spacing">10</property>
<property name="column-spacing">10</property>
<child>
<object class="GtkLabel">
<property name="label">Name</property>
<layout>
<property name="column">0</property>
<property name="row">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkEntry" id="name">
<property name="max-width-chars">20</property>
<layout>
<property name="column">1</property>
<property name="row">0</property>
<property name="column-span">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Min Size</property>
<layout>
<property name="column">0</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkSpinButton" id="min_width">
<property name="adjustment">min_width_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">1</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkSpinButton" id="min_height">
<property name="adjustment">min_height_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">2</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Nat Size</property>
<layout>
<property name="column">0</property>
<property name="row">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkSpinButton" id="nat_width">
<property name="adjustment">nat_width_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">1</property>
<property name="row">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkSpinButton" id="nat_height">
<property name="adjustment">nat_height_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">2</property>
<property name="row">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Max Size</property>
<layout>
<property name="column">0</property>
<property name="row">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkSpinButton" id="max_width">
<property name="adjustment">max_width_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">1</property>
<property name="row">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkSpinButton" id="max_height">
<property name="adjustment">max_height_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">2</property>
<property name="row">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Strength</property>
<layout>
<property name="column">0</property>
<property name="row">4</property>
</layout>
</object>
</child>
<child>
<object class="GtkComboBoxText" id="strength">
<layout>
<property name="column">1</property>
<property name="row">4</property>
<property name="column-span">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkButton" id="button">
<property name="label">Create</property>
<signal name="clicked" handler="create_guide"/>
<layout>
<property name="column">2</property>
<property name="row">5</property>
</layout>
</object>
</child>
</object>
</child>
</template>
</interface>
-28
View File
@@ -1,28 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen <mclasen@redhat.com>
*/
#include "config.h"
#include <constraint-editor-application.h>
int
main (int argc, char *argv[])
{
return g_application_run (G_APPLICATION (constraint_editor_application_new ()), argc, argv);
}
-21
View File
@@ -1,21 +0,0 @@
constraint_editor_sources = [
'main.c',
'constraint-editor-application.c',
'constraint-editor-window.c',
'constraint-view.c',
'constraint-editor.c',
'guide-editor.c',
]
constraint_editor_resources = gnome.compile_resources('constraint_editor_resources',
'constraint-editor.gresource.xml',
source_dir: '.')
executable('gtk4-constraint-editor',
constraint_editor_sources, constraint_editor_resources,
c_args: common_cflags,
dependencies: libgtk_dep,
include_directories: confinc,
gui_app: true,
link_args: extra_demo_ldflags,
install: false)
-345
View File
@@ -1,345 +0,0 @@
// Originally from: https://www.shadertoy.com/view/wsjBD3
// License CC0: A battered alien planet
// Been experimenting with space inspired shaders
#define PI 3.141592654
#define TAU (2.0*PI)
#define TOLERANCE 0.00001
#define MAX_ITER 65
#define MIN_DISTANCE 0.01
#define MAX_DISTANCE 9.0
const vec3 skyCol1 = vec3(0.35, 0.45, 0.6);
const vec3 skyCol2 = vec3(0.4, 0.7, 1.0);
const vec3 skyCol3 = pow(skyCol1, vec3(0.25));
const vec3 sunCol1 = vec3(1.0,0.6,0.4);
const vec3 sunCol2 = vec3(1.0,0.9,0.7);
const vec3 smallSunCol1 = vec3(1.0,0.5,0.25)*0.5;
const vec3 smallSunCol2 = vec3(1.0,0.5,0.25)*0.5;
const vec3 mountainColor = 1.0*sqrt(vec3(0.95, 0.65, 0.45));
const float cellWidth = 1.0;
const vec4 planet = vec4(80.0, -20.0, 100.0, 50.0)*1000.0;
void rot(inout vec2 p, float a) {
float c = cos(a);
float s = sin(a);
p = vec2(p.x*c + p.y*s, -p.x*s + p.y*c);
}
vec2 mod2(inout vec2 p, vec2 size) {
vec2 c = floor((p + size*0.5)/size);
p = mod(p + size*0.5,size) - size*0.5;
return c;
}
float circle(vec2 p, float r) {
return length(p) - r;
}
float egg(vec2 p, float ra, float rb) {
const float k = sqrt(3.0);
p.x = abs(p.x);
float r = ra - rb;
return ((p.y<0.0) ? length(vec2(p.x, p.y )) - r :
(k*(p.x+r)<p.y) ? length(vec2(p.x, p.y-k*r)) :
length(vec2(p.x+r,p.y )) - 2.0*r) - rb;
}
vec2 hash(vec2 p) {
p = vec2(dot (p, vec2 (127.1, 311.7)), dot (p, vec2 (269.5, 183.3)));
return -1. + 2.*fract (sin (p)*43758.5453123);
}
vec2 raySphere(vec3 ro, vec3 rd, vec4 sphere) {
vec3 center = sphere.xyz;
float radius = sphere.w;
vec3 m = ro - center.xyz;
float b = dot(m, rd);
float c = dot(m, m) - radius*radius;
if(c > 0.0 && b > 0.0) return vec2(-1.0, -1.0);
float discr = b * b - c;
if(discr < 0.0) return vec2(-1.0);
float normalMultiplier = 1.0;
float s = sqrt(discr);
float t0 = -b - s;
float t1 = -b + s;;
return vec2(t0, t1);
}
float noise1(vec2 p) {
vec2 n = mod2(p, vec2(cellWidth));
vec2 hh = hash(sqrt(2.0)*(n+1000.0));
hh.x *= hh.y;
float r = 0.225*cellWidth;
float d = circle(p, 2.0*r);
float h = hh.x*smoothstep(0.0, r, -d);
return h*0.25;
}
float noise2(vec2 p) {
vec2 n = mod2(p, vec2(cellWidth));
vec2 hh = hash(sqrt(2.0)*(n+1000.0));
hh.x *= hh.y;
rot(p, TAU*hh.y);
float r = 0.45*cellWidth;
// float d = circle(p, 1.0*r);
float d = egg(p, 0.75*r, 0.5*r*abs(hh.y));
float h = (hh.x)*smoothstep(0.0, r, -2.0*d);
return h*0.275;
}
float height(vec2 p, float dd, int mx) {
const float aa = 0.45;
const float ff = 2.03;
const float tt = 1.2;
const float oo = 3.93;
const float near = 0.25;
const float far = 0.65;
float a = 1.0;
float o = 0.2;
float s = 0.0;
float d = 0.0;
int i = 0;
for (; i < 4;++i) {
float nn = a*noise2(p);
s += nn;
d += abs(a);
p += o;
a *= aa;
p *= ff;
o *= oo;
rot(p, tt);
}
float lod = s/d;
float rdd = dd/MAX_DISTANCE;
mx = int(mix(float(4), float(mx), step(rdd, far)));
for (; i < mx; ++i) {
float nn = a*noise1(p);
s += nn;
d += abs(a);
p += o;
a *= aa;
p *= ff;
o *= oo;
rot(p, tt);
}
float hid = (s/d);
return mix(hid, lod, smoothstep(near, far, rdd));
}
float loheight(vec2 p, float d) {
return height(p, d, 0);
}
float height(vec2 p, float d) {
return height(p, d, 6);
}
float hiheight(vec2 p, float d) {
return height(p, d, 8);
}
vec3 normal(vec2 p, float d) {
vec2 eps = vec2(0.00125, 0.0);
vec3 n;
n.x = (hiheight(p - eps.xy, d) - hiheight(p + eps.xy, d));
n.y = 2.0*eps.x;
n.z = (hiheight(p - eps.yx, d) - hiheight(p + eps.yx, d));
return normalize(n);
}
const float stepLength[] = float[](0.9, 0.25);
float march(vec3 ro, vec3 rd, out int max_iter) {
float dt = 0.1;
float d = MIN_DISTANCE;
int currentStep = 0;
float lastd = d;
for (int i = 0; i < MAX_ITER; ++i)
{
vec3 p = ro + d*rd;
float h = height(p.xz, d);
if (d > MAX_DISTANCE) {
max_iter = i;
return MAX_DISTANCE;
}
float hd = p.y - h;
if (hd < TOLERANCE) {
++currentStep;
if (currentStep >= stepLength.length()) {
max_iter = i;
return d;
}
d = lastd;
continue;
}
float sl = stepLength[currentStep];
dt = max(hd, TOLERANCE)*sl + 0.0025*d;
lastd = d;
d += dt;
}
max_iter = MAX_ITER;
return MAX_DISTANCE;
}
vec3 sunDirection() {
return normalize(vec3(-0.5, 0.085, 1.0));
}
vec3 smallSunDirection() {
return normalize(vec3(-0.2, -0.05, 1.0));
}
float psin(float f) {
return 0.5 + 0.5*sin(f);
}
vec3 skyColor(vec3 ro, vec3 rd) {
vec3 sunDir = sunDirection();
vec3 smallSunDir = smallSunDirection();
float sunDot = max(dot(rd, sunDir), 0.0);
float smallSunDot = max(dot(rd, smallSunDir), 0.0);
float angle = atan(rd.y, length(rd.xz))*2.0/PI;
vec3 skyCol = mix(mix(skyCol1, skyCol2, max(0.0, angle)), skyCol3, clamp(-angle*2.0, 0.0, 1.0));
vec3 sunCol = 0.5*sunCol1*pow(sunDot, 20.0) + 8.0*sunCol2*pow(sunDot, 2000.0);
vec3 smallSunCol = 0.5*smallSunCol1*pow(smallSunDot, 200.0) + 8.0*smallSunCol2*pow(smallSunDot, 20000.0);
vec3 dust = pow(sunCol2*mountainColor, vec3(1.75))*smoothstep(0.05, -0.1, rd.y)*0.5;
vec2 si = raySphere(ro, rd, planet);
vec3 planetSurface = ro + si.x*rd;
vec3 planetNormal = normalize(planetSurface - planet.xyz);
float planetDiff = max(dot(planetNormal, sunDir), 0.0);
float planetBorder = max(dot(planetNormal, -rd), 0.0);
float planetLat = (planetSurface.x+planetSurface.y)*0.0005;
vec3 planetCol = mix(1.3*vec3(0.9, 0.8, 0.7), 0.3*vec3(0.9, 0.8, 0.7), pow(psin(planetLat+1.0)*psin(sqrt(2.0)*planetLat+2.0)*psin(sqrt(3.5)*planetLat+3.0), 0.5));
vec3 final = vec3(0.0);
final += step(0.0, si.x)*pow(planetDiff, 0.75)*planetCol*smoothstep(-0.075, 0.0, rd.y)*smoothstep(0.0, 0.1, planetBorder);
final += skyCol + sunCol + smallSunCol + dust;
return final;
}
vec3 getColor(vec3 ro, vec3 rd) {
int max_iter = 0;
vec3 skyCol = skyColor(ro, rd);
vec3 col = vec3(0);
float d = march(ro, rd, max_iter);
if (d < MAX_DISTANCE) {
vec3 sunDir = sunDirection();
vec3 osunDir = sunDir*vec3(-1.0, .0, -1.0);
vec3 p = ro + d*rd;
vec3 normal = normal(p.xz, d);
float amb = 0.2;
float dif1 = max(0.0, dot(sunDir, normal));
vec3 shd1 = sunCol2*mix(amb, 1.0, pow(dif1, 0.75));
float dif2 = max(0.0, dot(osunDir, normal));
vec3 shd2 = sunCol1*mix(amb, 1.0, pow(dif2, 0.75));
vec3 ref = reflect(rd, normal);
vec3 rcol = skyColor(p, ref);
col = mountainColor*amb*skyCol3;
col += mix(shd1, shd2, -0.5)*mountainColor;
float fre = max(dot(normal, -rd), 0.0);
fre = pow(1.0 - fre, 5.0);
col += rcol*fre*0.5;
col += (1.0*p.y);
col = tanh(col);
col = mix(col, skyCol, smoothstep(0.5*MAX_DISTANCE, 1.0*MAX_DISTANCE, d));
} else {
col = skyCol;
}
// col += vec3(1.1, 0.0, 0.0)* smoothstep(0.25, 1.0,(float(max_iter)/float(MAX_ITER)));
return col;
}
vec3 getSample1(vec2 p, float time) {
float off = 0.5*iTime;
vec3 ro = vec3(0.5, 1.0-0.25, -2.0 + off);
vec3 la = ro + vec3(0.0, -0.30, 2.0);
vec3 ww = normalize(la - ro);
vec3 uu = normalize(cross(vec3(0.0,1.0,0.0), ww));
vec3 vv = normalize(cross(ww, uu));
vec3 rd = normalize(p.x*uu + p.y*vv + 2.0*ww);
vec3 col = getColor(ro, rd) ;
return col;
}
vec3 getSample2(vec2 p, float time) {
p.y-=time*0.25;
float h = height(p, 0.0);
vec3 n = normal(p, 0.0);
vec3 lp = vec3(10.0, -1.2, 0.0);
vec3 ld = normalize(vec3(p.x, h, p.y)- lp);
float d = max(dot(ld, n), 0.0);
vec3 col = vec3(0.0);
col = vec3(1.0)*(h+0.1);
col += vec3(1.5)*pow(d, 0.75);
return col;
}
void mainImage(out vec4 fragColor, vec2 fragCoord) {
vec2 q = fragCoord.xy/iResolution.xy;
vec2 p = -1.0 + 2.0*q;
p.x *= iResolution.x/iResolution.y;
vec3 col = getSample1(p, iTime);
fragColor = vec4(col, 1.0);
}
+34 -31
View File
@@ -1,3 +1,4 @@
#include "config.h"
#include <gtk/gtk.h>
@@ -5,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 {
@@ -14,7 +14,7 @@ typedef struct {
GtkWidget *message;
GtkWidget *infobar;
GtkWidget *status;
GtkWidget *menubutton;
GtkWidget *menutool;
GMenuModel *toolmenu;
GtkTextBuffer *buffer;
@@ -25,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);
@@ -33,7 +32,7 @@ static void create_window (GApplication *app, const char *contents);
static void
show_action_dialog (GSimpleAction *action)
{
const char *name;
const gchar *name;
GtkWidget *dialog;
name = g_action_get_name (G_ACTION (action));
@@ -46,7 +45,7 @@ show_action_dialog (GSimpleAction *action)
name);
g_signal_connect (dialog, "response",
G_CALLBACK (gtk_window_destroy), NULL);
G_CALLBACK (gtk_widget_destroy), NULL);
gtk_widget_show (dialog);
}
@@ -57,9 +56,9 @@ show_action_infobar (GSimpleAction *action,
gpointer data)
{
DemoApplicationWindow *window = data;
char *text;
const char *name;
const char *value;
gchar *text;
const gchar *name;
const gchar *value;
name = g_action_get_name (G_ACTION (action));
value = g_variant_get_string (parameter, NULL);
@@ -91,7 +90,7 @@ activate_new (GSimpleAction *action,
static void
open_response_cb (GtkNativeDialog *dialog,
int response_id,
gint response_id,
gpointer user_data)
{
GtkFileChooserNative *native = user_data;
@@ -119,7 +118,7 @@ open_response_cb (GtkNativeDialog *dialog,
"Error loading file: \"%s\"",
error->message);
g_signal_connect (message_dialog, "response",
G_CALLBACK (gtk_window_destroy), NULL);
G_CALLBACK (gtk_widget_destroy), NULL);
gtk_widget_show (message_dialog);
g_error_free (error);
}
@@ -184,7 +183,7 @@ activate_about (GSimpleAction *action,
{
GtkWidget *window = user_data;
const char *authors[] = {
const gchar *authors[] = {
"Peter Mattis",
"Spencer Kimball",
"Josh MacDonald",
@@ -192,7 +191,7 @@ activate_about (GSimpleAction *action,
NULL
};
const char *documentors[] = {
const gchar *documentors[] = {
"Owen Taylor",
"Tony Gale",
"Matthias Clasen <mclasen@redhat.com>",
@@ -233,7 +232,7 @@ activate_quit (GSimpleAction *action,
win = list->data;
next = list->next;
gtk_window_destroy (GTK_WINDOW (win));
gtk_widget_destroy (GTK_WIDGET (win));
list = next;
}
@@ -243,9 +242,9 @@ static void
update_statusbar (GtkTextBuffer *buffer,
DemoApplicationWindow *window)
{
char *msg;
int row, col;
int count;
gchar *msg;
gint row, col;
gint count;
GtkTextIter iter;
/* clear any previous message, underflow is allowed */
@@ -327,14 +326,19 @@ static void
startup (GApplication *app)
{
GtkBuilder *builder;
GMenuModel *appmenu;
GMenuModel *menubar;
G_APPLICATION_CLASS (demo_application_parent_class)->startup (app);
builder = gtk_builder_new ();
gtk_builder_add_from_resource (builder, "/application_demo/menus.ui", NULL);
gtk_application_set_menubar (GTK_APPLICATION (app),
G_MENU_MODEL (gtk_builder_get_object (builder, "menubar")));
appmenu = (GMenuModel *)gtk_builder_get_object (builder, "appmenu");
menubar = (GMenuModel *)gtk_builder_get_object (builder, "menubar");
gtk_application_set_app_menu (GTK_APPLICATION (app), appmenu);
gtk_application_set_menubar (GTK_APPLICATION (app), menubar);
g_object_unref (builder);
}
@@ -347,7 +351,6 @@ create_window (GApplication *app,
window = (DemoApplicationWindow *)g_object_new (demo_application_window_get_type (),
"application", app,
"show-menubar", TRUE,
NULL);
if (content)
gtk_text_buffer_set_text (window->buffer, content, -1);
@@ -416,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;
@@ -425,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),
@@ -472,11 +475,11 @@ static void
surface_state_changed (GtkWidget *widget)
{
DemoApplicationWindow *window = (DemoApplicationWindow *)widget;
GdkToplevelState new_state;
GdkSurfaceState new_state;
new_state = gdk_toplevel_get_state (GDK_TOPLEVEL (gtk_native_get_surface (GTK_NATIVE (widget))));
window->maximized = (new_state & GDK_TOPLEVEL_STATE_MAXIMIZED) != 0;
window->fullscreen = (new_state & GDK_TOPLEVEL_STATE_FULLSCREEN) != 0;
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;
}
static void
@@ -498,13 +501,13 @@ demo_application_window_unrealize (GtkWidget *widget)
}
static void
demo_application_window_dispose (GObject *object)
demo_application_window_destroy (GtkWidget *widget)
{
DemoApplicationWindow *window = (DemoApplicationWindow *)object;
DemoApplicationWindow *window = (DemoApplicationWindow *)widget;
demo_application_window_store_state (window);
G_OBJECT_CLASS (demo_application_window_parent_class)->dispose (object);
GTK_WIDGET_CLASS (demo_application_window_parent_class)->destroy (widget);
}
static void
@@ -514,18 +517,18 @@ demo_application_window_class_init (DemoApplicationWindowClass *class)
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->constructed = demo_application_window_constructed;
object_class->dispose = demo_application_window_dispose;
widget_class->size_allocate = demo_application_window_size_allocate;
widget_class->realize = demo_application_window_realize;
widget_class->unrealize = demo_application_window_unrealize;
widget_class->destroy = demo_application_window_destroy;
gtk_widget_class_set_template_from_resource (widget_class, "/application_demo/application.ui");
gtk_widget_class_bind_template_child (widget_class, DemoApplicationWindow, message);
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);
+34 -23
View File
@@ -8,31 +8,34 @@
<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>
</child>
<layout>
<property name="column">0</property>
<property name="row">0</property>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</layout>
</object>
</child>
@@ -40,28 +43,36 @@
<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>
<property name="column">0</property>
<property name="row">1</property>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="has-frame">1</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkTextView">
<property name="hexpand">1</property>
@@ -70,8 +81,8 @@
</object>
</child>
<layout>
<property name="column">0</property>
<property name="row">2</property>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</layout>
</object>
</child>
@@ -79,8 +90,8 @@
<object class="GtkStatusbar" id="status">
<property name="hexpand">1</property>
<layout>
<property name="column">0</property>
<property name="row">3</property>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
</layout>
</object>
</child>
+10 -5
View File
@@ -16,8 +16,8 @@ static GtkWidget *placeholder;
static void
on_name_appeared (GDBusConnection *connection,
const char *name,
const char *name_owner,
const gchar *name,
const gchar *name_owner,
gpointer user_data)
{
name_seen = TRUE;
@@ -25,13 +25,18 @@ on_name_appeared (GDBusConnection *connection,
static void
on_name_vanished (GDBusConnection *connection,
const char *name,
const gchar *name,
gpointer user_data)
{
if (!name_seen)
return;
g_clear_object (&placeholder);
if (placeholder)
{
gtk_widget_destroy (placeholder);
g_object_unref (placeholder);
placeholder = NULL;
}
}
#ifdef G_OS_WIN32
@@ -55,7 +60,7 @@ do_application_demo (GtkWidget *toplevel)
if (placeholder == NULL)
{
const char *command;
const gchar *command;
GError *error = NULL;
if (g_file_test ("./gtk4-demo-application" APP_EXTENSION, G_FILE_TEST_IS_EXECUTABLE))
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<menu id="appmenu">
<section>
<item>
<attribute name="label" translatable="yes">About</attribute>
<attribute name="action">app.about</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">_Quit</attribute>
<attribute name="action">app.quit</attribute>
<attribute name="accel">&lt;Primary&gt;q</attribute>
</item>
</section>
</menu>
</interface>
+26 -30
View File
@@ -1,18 +1,19 @@
/* Assistant
*
* Demonstrates a sample multi-step assistant with GtkAssistant. Assistants
* are used to divide an operation into several simpler sequential steps,
* and to guide the user through these steps.
* Demonstrates a sample multi-step assistant. Assistants are used to divide
* an operation into several simpler sequential steps, and to guide the user
* through these steps.
*/
#include <gtk/gtk.h>
static GtkWidget *assistant = NULL;
static GtkWidget *progress_bar = NULL;
static gboolean
apply_changes_gradually (gpointer data)
{
double fraction;
gdouble fraction;
/* Work, work, work... */
fraction = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (progress_bar));
@@ -26,7 +27,8 @@ apply_changes_gradually (gpointer data)
else
{
/* Close automatically once changes are fully applied. */
gtk_window_destroy (GTK_WINDOW (data));
gtk_widget_destroy (assistant);
assistant = NULL;
return G_SOURCE_REMOVE;
}
}
@@ -35,20 +37,23 @@ 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
on_assistant_close_cancel (GtkWidget *widget, gpointer data)
{
gtk_window_destroy (GTK_WINDOW (widget));
GtkWidget **assistant = (GtkWidget **) data;
gtk_widget_destroy (*assistant);
*assistant = NULL;
}
static void
on_assistant_prepare (GtkWidget *widget, GtkWidget *page, gpointer data)
{
int current_page, n_pages;
char *title;
gint current_page, n_pages;
gchar *title;
current_page = gtk_assistant_get_current_page (GTK_ASSISTANT (widget));
n_pages = gtk_assistant_get_n_pages (GTK_ASSISTANT (widget));
@@ -70,8 +75,8 @@ on_entry_changed (GtkWidget *widget, gpointer data)
{
GtkAssistant *assistant = GTK_ASSISTANT (data);
GtkWidget *current_page;
int page_number;
const char *text;
gint page_number;
const gchar *text;
page_number = gtk_assistant_get_current_page (assistant);
current_page = gtk_assistant_get_nth_page (assistant, page_number);
@@ -89,18 +94,14 @@ 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_box_append (GTK_BOX (box), label);
gtk_container_add (GTK_CONTAINER (box), label);
entry = gtk_entry_new ();
gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
gtk_widget_set_valign (entry, GTK_ALIGN_CENTER);
gtk_box_append (GTK_BOX (box), entry);
gtk_container_add (GTK_CONTAINER (box), entry);
g_signal_connect (G_OBJECT (entry), "changed",
G_CALLBACK (on_entry_changed), assistant);
@@ -114,16 +115,11 @@ 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_box_append (GTK_BOX (box), checkbutton);
gtk_container_add (GTK_CONTAINER (box), checkbutton);
gtk_assistant_append_page (GTK_ASSISTANT (assistant), box);
gtk_assistant_set_page_complete (GTK_ASSISTANT (assistant), box, TRUE);
@@ -168,8 +164,6 @@ create_page4 (GtkWidget *assistant)
GtkWidget*
do_assistant (GtkWidget *do_widget)
{
static GtkWidget *assistant;
if (!assistant)
{
assistant = gtk_assistant_new ();
@@ -178,7 +172,6 @@ do_assistant (GtkWidget *do_widget)
gtk_window_set_display (GTK_WINDOW (assistant),
gtk_widget_get_display (do_widget));
g_object_add_weak_pointer (G_OBJECT (assistant), (gpointer *)&assistant);
create_page1 (assistant);
create_page2 (assistant);
@@ -186,9 +179,9 @@ do_assistant (GtkWidget *do_widget)
create_page4 (assistant);
g_signal_connect (G_OBJECT (assistant), "cancel",
G_CALLBACK (on_assistant_close_cancel), NULL);
G_CALLBACK (on_assistant_close_cancel), &assistant);
g_signal_connect (G_OBJECT (assistant), "close",
G_CALLBACK (on_assistant_close_cancel), NULL);
G_CALLBACK (on_assistant_close_cancel), &assistant);
g_signal_connect (G_OBJECT (assistant), "apply",
G_CALLBACK (on_assistant_apply), NULL);
g_signal_connect (G_OBJECT (assistant), "prepare",
@@ -198,7 +191,10 @@ do_assistant (GtkWidget *do_widget)
if (!gtk_widget_get_visible (assistant))
gtk_widget_show (assistant);
else
gtk_window_destroy (GTK_WINDOW (assistant));
{
gtk_widget_destroy (assistant);
assistant = NULL;
}
return assistant;
}
-26
View File
@@ -1,26 +0,0 @@
uniform float u_time;
void
mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv)
{
vec2 pos = (fragCoord.xy * 2.0 - resolution.xy)/ min (resolution.x, resolution.y) ;
float t0 = sin ((u_time + 0.00)*1.0);
float t1 = sin ((u_time + 0.30)*0.4);
float t2 = cos ((u_time + 0.23)*0.9);
float t3 = cos ((u_time + 0.41)*0.6);
float t4 = cos ((u_time + 0.11)*0.3);
vec2 p0 = vec2 (t1, t0) ;
vec2 p1 = vec2 (t2, t3) ;
vec2 p2 = vec2 (t4, t3) ;
float r = 1.0/distance (pos, p0);
float g = 1.0/distance (pos, p1);
float b = 1.0/distance (pos, p2);
float sum = r + g + b;
float alpha = 1.0 - pow (1.0/(sum), 40)*pow (10.0, 40*0.7);
fragColor = vec4 (r*0.5, g*0.5, b*0.5, 1.0) * alpha;
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

+51 -53
View File
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkWindow" id="window">
<property name="resizable">0</property>
<property name="title">CSS Blend Modes</property>
@@ -7,10 +8,6 @@
<property name="default-height">300</property>
<child>
<object class="GtkGrid">
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="margin-top">12</property>
<property name="margin-bottom">12</property>
<property name="row-spacing">12</property>
<property name="column-spacing">12</property>
<child>
@@ -21,19 +18,20 @@
<class name="dim-label"/>
</style>
<layout>
<property name="column">0</property>
<property name="row">0</property>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow">
<property name="can-focus">1</property>
<property name="vexpand">1</property>
<property name="has-frame">1</property>
<property name="shadow-type">in</property>
<property name="min-content-width">150</property>
<layout>
<property name="column">0</property>
<property name="row">1</property>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
@@ -43,8 +41,8 @@
<property name="hexpand">1</property>
<property name="stack">stack</property>
<layout>
<property name="column">1</property>
<property name="row">0</property>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</layout>
</object>
</child>
@@ -70,8 +68,8 @@
<object class="GtkLabel">
<property name="label" translatable="yes">Duck</property>
<layout>
<property name="column">0</property>
<property name="row">0</property>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</layout>
</object>
</child>
@@ -79,8 +77,8 @@
<object class="GtkLabel">
<property name="label" translatable="yes">Background</property>
<layout>
<property name="column">1</property>
<property name="row">0</property>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</layout>
</object>
</child>
@@ -90,8 +88,8 @@
<class name="duck"/>
</style>
<layout>
<property name="column">0</property>
<property name="row">1</property>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
@@ -101,8 +99,8 @@
<class name="gradient"/>
</style>
<layout>
<property name="column">1</property>
<property name="row">1</property>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
@@ -111,8 +109,8 @@
<property name="label" translatable="yes">
Blended picture</property>
<layout>
<property name="column">0</property>
<property name="row">2</property>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
<property name="column-span">2</property>
</layout>
</object>
@@ -124,8 +122,8 @@ Blended picture</property>
<class name="blend0"/>
</style>
<layout>
<property name="column">0</property>
<property name="row">3</property>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
<property name="column-span">2</property>
</layout>
</object>
@@ -149,8 +147,8 @@ Blended picture</property>
<object class="GtkLabel">
<property name="label" translatable="yes">Red</property>
<layout>
<property name="column">0</property>
<property name="row">0</property>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</layout>
</object>
</child>
@@ -158,8 +156,8 @@ Blended picture</property>
<object class="GtkLabel">
<property name="label" translatable="yes">Blue</property>
<layout>
<property name="column">1</property>
<property name="row">0</property>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</layout>
</object>
</child>
@@ -169,8 +167,8 @@ Blended picture</property>
<class name="red"/>
</style>
<layout>
<property name="column">0</property>
<property name="row">1</property>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
@@ -180,8 +178,8 @@ Blended picture</property>
<class name="blue"/>
</style>
<layout>
<property name="column">1</property>
<property name="row">1</property>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
@@ -190,8 +188,8 @@ Blended picture</property>
<property name="label" translatable="yes">
Blended picture</property>
<layout>
<property name="column">0</property>
<property name="row">2</property>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
<property name="column-span">2</property>
</layout>
</object>
@@ -203,8 +201,8 @@ Blended picture</property>
<class name="blend1"/>
</style>
<layout>
<property name="column">0</property>
<property name="row">3</property>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
<property name="column-span">2</property>
</layout>
</object>
@@ -231,8 +229,8 @@ Blended picture</property>
<class name="cyan"/>
</style>
<layout>
<property name="column">0</property>
<property name="row">1</property>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
@@ -242,8 +240,8 @@ Blended picture</property>
<class name="magenta"/>
</style>
<layout>
<property name="column">1</property>
<property name="row">1</property>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
@@ -253,8 +251,8 @@ Blended picture</property>
<class name="yellow"/>
</style>
<layout>
<property name="column">0</property>
<property name="row">3</property>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
</layout>
</object>
</child>
@@ -265,8 +263,8 @@ Blended picture</property>
<class name="blend2"/>
</style>
<layout>
<property name="column">1</property>
<property name="row">3</property>
<property name="left-attach">1</property>
<property name="top-attach">3</property>
</layout>
</object>
</child>
@@ -278,8 +276,8 @@ Blended picture</property>
<class name="dim-label"/>
</style>
<layout>
<property name="column">0</property>
<property name="row">0</property>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</layout>
</object>
</child>
@@ -291,8 +289,8 @@ Blended picture</property>
<class name="dim-label"/>
</style>
<layout>
<property name="column">1</property>
<property name="row">0</property>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</layout>
</object>
</child>
@@ -304,8 +302,8 @@ Blended picture</property>
<class name="dim-label"/>
</style>
<layout>
<property name="column">0</property>
<property name="row">2</property>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</layout>
</object>
</child>
@@ -317,8 +315,8 @@ Blended picture</property>
<attribute name="weight" value="bold"></attribute>
</attributes>
<layout>
<property name="column">1</property>
<property name="row">2</property>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
</layout>
</object>
</child>
@@ -327,8 +325,8 @@ Blended picture</property>
</object>
</child>
<layout>
<property name="column">1</property>
<property name="row">1</property>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
+58 -38
View File
@@ -39,7 +39,7 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 };
static GQuark child_data_quark = 0;
G_DEFINE_TYPE (BlurOverlay, blur_overlay, GTK_TYPE_WIDGET)
G_DEFINE_TYPE (BlurOverlay, blur_overlay, GTK_TYPE_BIN)
static void
blur_overlay_set_overlay_child (GtkWidget *widget,
@@ -131,11 +131,13 @@ blur_overlay_child_update_style_classes (BlurOverlay *overlay,
GtkAlign valign, halign;
gboolean is_left, is_right, is_top, is_bottom;
gboolean has_left, has_right, has_top, has_bottom;
GtkStyleContext *context;
has_left = gtk_widget_has_css_class (child, "left");
has_right = gtk_widget_has_css_class (child, "right");
has_top = gtk_widget_has_css_class (child, "top");
has_bottom = gtk_widget_has_css_class (child, "bottom");
context = gtk_widget_get_style_context (child);
has_left = gtk_style_context_has_class (context, GTK_STYLE_CLASS_LEFT);
has_right = gtk_style_context_has_class (context, GTK_STYLE_CLASS_RIGHT);
has_top = gtk_style_context_has_class (context, GTK_STYLE_CLASS_TOP);
has_bottom = gtk_style_context_has_class (context, GTK_STYLE_CLASS_BOTTOM);
is_left = is_right = is_top = is_bottom = FALSE;
@@ -158,24 +160,24 @@ blur_overlay_child_update_style_classes (BlurOverlay *overlay,
is_bottom = (child_allocation->y + child_allocation->height == height);
if (has_left && !is_left)
gtk_widget_remove_css_class (child, "left");
gtk_style_context_remove_class (context, GTK_STYLE_CLASS_LEFT);
else if (!has_left && is_left)
gtk_widget_add_css_class (child, "left");
gtk_style_context_add_class (context, GTK_STYLE_CLASS_LEFT);
if (has_right && !is_right)
gtk_widget_remove_css_class (child, "right");
gtk_style_context_remove_class (context, GTK_STYLE_CLASS_RIGHT);
else if (!has_right && is_right)
gtk_widget_add_css_class (child, "right");
gtk_style_context_add_class (context, GTK_STYLE_CLASS_RIGHT);
if (has_top && !is_top)
gtk_widget_remove_css_class (child, "top");
gtk_style_context_remove_class (context, GTK_STYLE_CLASS_TOP);
else if (!has_top && is_top)
gtk_widget_add_css_class (child, "top");
gtk_style_context_add_class (context, GTK_STYLE_CLASS_TOP);
if (has_bottom && !is_bottom)
gtk_widget_remove_css_class (child, "bottom");
gtk_style_context_remove_class (context, GTK_STYLE_CLASS_BOTTOM);
else if (!has_bottom && is_bottom)
gtk_widget_add_css_class (child, "bottom");
gtk_style_context_add_class (context, GTK_STYLE_CLASS_BOTTOM);
}
static void
@@ -204,7 +206,7 @@ blur_overlay_size_allocate (GtkWidget *widget,
GtkWidget *child;
GtkWidget *main_widget;
main_widget = overlay->main_widget;
main_widget = gtk_bin_get_child (GTK_BIN (overlay));
if (main_widget && gtk_widget_get_visible (main_widget))
gtk_widget_size_allocate (main_widget,
&(GtkAllocation) {
@@ -290,6 +292,43 @@ blur_overlay_get_child_position (BlurOverlay *overlay,
return TRUE;
}
static void
blur_overlay_add (GtkContainer *container,
GtkWidget *widget)
{
BlurOverlay *overlay = BLUR_OVERLAY (container);
gtk_widget_insert_after (widget, GTK_WIDGET (container), NULL);
overlay->main_widget = widget;
}
static void
blur_overlay_remove (GtkContainer *container,
GtkWidget *widget)
{
BlurOverlay *overlay = BLUR_OVERLAY (container);
gtk_widget_unparent (widget);
if (overlay->main_widget == widget)
overlay->main_widget = NULL;
}
static void
blur_overlay_forall (GtkContainer *overlay,
GtkCallback callback,
gpointer callback_data)
{
GtkWidget *child;
child = gtk_widget_get_first_child (GTK_WIDGET (overlay));
while (child != NULL)
{
GtkWidget *next = gtk_widget_get_next_sibling (child);
(* callback) (child, callback_data);
child = next;
}
}
static void
blur_overlay_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
@@ -383,32 +422,21 @@ blur_overlay_snapshot (GtkWidget *widget,
gsk_render_node_unref (main_widget_node);
}
static void
blur_overlay_dispose (GObject *object)
{
BlurOverlay *overlay = BLUR_OVERLAY (object);
GtkWidget *child;
g_clear_pointer (&overlay->main_widget, gtk_widget_unparent);
while ((child = gtk_widget_get_first_child (GTK_WIDGET (overlay))))
gtk_widget_unparent (child);
G_OBJECT_CLASS (blur_overlay_parent_class)->dispose (object);
}
static void
blur_overlay_class_init (BlurOverlayClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = blur_overlay_dispose;
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
widget_class->measure = blur_overlay_measure;
widget_class->size_allocate = blur_overlay_size_allocate;
widget_class->snapshot = blur_overlay_snapshot;
container_class->add = blur_overlay_add;
container_class->remove = blur_overlay_remove;
container_class->forall = blur_overlay_forall;
klass->get_child_position = blur_overlay_get_child_position;
signals[GET_CHILD_POSITION] =
@@ -451,11 +479,3 @@ blur_overlay_add_overlay (BlurOverlay *overlay,
blur_overlay_set_overlay_child (widget, child);
}
void
blur_overlay_set_child (BlurOverlay *overlay,
GtkWidget *widget)
{
gtk_widget_insert_after (widget, GTK_WIDGET (overlay), NULL);
overlay->main_widget = widget;
}
+2 -5
View File
@@ -37,14 +37,14 @@ typedef struct _BlurOverlayClass BlurOverlayClass;
struct _BlurOverlay
{
GtkWidget parent_instance;
GtkBin parent_instance;
GtkWidget *main_widget;
};
struct _BlurOverlayClass
{
GtkWidgetClass parent_class;
GtkBinClass parent_class;
gboolean (*get_child_position) (BlurOverlay *overlay,
GtkWidget *widget,
@@ -59,9 +59,6 @@ GDK_AVAILABLE_IN_ALL
void blur_overlay_add_overlay (BlurOverlay *overlay,
GtkWidget *widget,
double blur);
GDK_AVAILABLE_IN_ALL
void blur_overlay_set_child (BlurOverlay *overlay,
GtkWidget *widget);
G_END_DECLS
+34 -111
View File
@@ -1,8 +1,6 @@
/* Builder
* #Keywords: GMenu, GtkPopoverMenuBar, GtkBuilder, GtkStatusBar, GtkShortcutController, toolbar
*
* Demonstrates a traditional interface, loaded from a XML description,
* and shows how to connect actions to the menu items and toolbar buttons.
* Demonstrates an interface loaded from a XML description.
*/
#include <gtk/gtk.h>
@@ -14,7 +12,7 @@ quit_activate (GSimpleAction *action,
{
GtkWidget *window = user_data;
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
}
static void
@@ -23,154 +21,79 @@ about_activate (GSimpleAction *action,
gpointer user_data)
{
GtkWidget *window = user_data;
GtkBuilder *builder;
GtkWidget *about_dlg;
about_dlg = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "about"));
gtk_window_present (GTK_WINDOW (about_dlg));
builder = g_object_get_data (G_OBJECT (window), "builder");
about_dlg = GTK_WIDGET (gtk_builder_get_object (builder, "aboutdialog1"));
gtk_dialog_run (GTK_DIALOG (about_dlg));
gtk_widget_hide (about_dlg);
}
static void
remove_timeout (gpointer data)
{
guint id = GPOINTER_TO_UINT (data);
g_source_remove (id);
}
static gboolean
pop_status (gpointer data)
{
gtk_statusbar_pop (GTK_STATUSBAR (data), 0);
g_object_set_data (G_OBJECT (data), "timeout", NULL);
return G_SOURCE_REMOVE;
}
static void
status_message (GtkStatusbar *status,
const char *text)
{
guint id;
gtk_statusbar_push (GTK_STATUSBAR (status), 0, text);
id = g_timeout_add (5000, pop_status, status);
g_object_set_data_full (G_OBJECT (status), "timeout", GUINT_TO_POINTER (id), remove_timeout);
}
static void
help_activate (GSimpleAction *action,
menu_activate (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
GtkWidget *status;
status = GTK_WIDGET (g_object_get_data (G_OBJECT (user_data), "status"));
status_message (GTK_STATUSBAR (status), "Help not available");
}
static void
not_implemented (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
GtkWidget *status;
char *text;
text = g_strdup_printf ("Action “%s” not implemented", g_action_get_name (G_ACTION (action)));
status = GTK_WIDGET (g_object_get_data (G_OBJECT (user_data), "status"));
status_message (GTK_STATUSBAR (status), text);
g_free (text);
g_print ("%s action not available\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 }
{ "help", menu_activate, NULL, NULL, NULL }
};
static GActionEntry menu_entries[] = {
{ "new", menu_activate, NULL, NULL, NULL },
{ "open", menu_activate, NULL, NULL, NULL },
{ "save", menu_activate, NULL, NULL, NULL },
{ "save_as", menu_activate, NULL, NULL, NULL },
{ "copy", menu_activate, NULL, NULL, NULL },
{ "cut", menu_activate, NULL, NULL, NULL },
{ "paste", menu_activate, NULL, NULL, NULL },
};
GtkWidget *
do_builder (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
GtkWidget *toolbar;
GActionGroup *actions;
if (!window)
{
GtkBuilder *builder;
GtkWidget *about;
GtkWidget *status;
GtkEventController *controller;
builder = gtk_builder_new_from_resource ("/builder/demo.ui");
gtk_builder_connect_signals (builder, NULL);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window1"));
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
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);
actions = (GActionGroup*)g_simple_action_group_new ();
g_action_map_add_action_entries (G_ACTION_MAP (actions),
menu_entries, G_N_ELEMENTS (menu_entries),
window);
gtk_widget_insert_action_group (window, "menu", actions);
controller = gtk_shortcut_controller_new ();
gtk_shortcut_controller_set_scope (GTK_SHORTCUT_CONTROLLER (controller),
GTK_SHORTCUT_SCOPE_GLOBAL);
gtk_widget_add_controller (window, controller);
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller),
gtk_shortcut_new (gtk_keyval_trigger_new (GDK_KEY_n, GDK_CONTROL_MASK),
gtk_named_action_new ("win.new")));
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller),
gtk_shortcut_new (gtk_keyval_trigger_new (GDK_KEY_o, GDK_CONTROL_MASK),
gtk_named_action_new ("win.open")));
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller),
gtk_shortcut_new (gtk_keyval_trigger_new (GDK_KEY_s, GDK_CONTROL_MASK),
gtk_named_action_new ("win.save")));
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller),
gtk_shortcut_new (gtk_keyval_trigger_new (GDK_KEY_s, GDK_CONTROL_MASK|GDK_SHIFT_MASK),
gtk_named_action_new ("win.save-as")));
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller),
gtk_shortcut_new (gtk_keyval_trigger_new (GDK_KEY_q, GDK_CONTROL_MASK),
gtk_named_action_new ("win.quit")));
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller),
gtk_shortcut_new (gtk_keyval_trigger_new (GDK_KEY_c, GDK_CONTROL_MASK),
gtk_named_action_new ("win.copy")));
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller),
gtk_shortcut_new (gtk_keyval_trigger_new (GDK_KEY_x, GDK_CONTROL_MASK),
gtk_named_action_new ("win.cut")));
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller),
gtk_shortcut_new (gtk_keyval_trigger_new (GDK_KEY_v, GDK_CONTROL_MASK),
gtk_named_action_new ("win.paste")));
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller),
gtk_shortcut_new (gtk_keyval_trigger_new (GDK_KEY_F1, 0),
gtk_named_action_new ("win.help")));
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller),
gtk_shortcut_new (gtk_keyval_trigger_new (GDK_KEY_F7, 0),
gtk_named_action_new ("win.about")));
about = GTK_WIDGET (gtk_builder_get_object (builder, "aboutdialog1"));
gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (window));
gtk_window_set_hide_on_close (GTK_WINDOW (about), TRUE);
g_object_set_data_full (G_OBJECT (window), "about",
about, (GDestroyNotify)gtk_window_destroy);
status = GTK_WIDGET (gtk_builder_get_object (builder, "statusbar1"));
g_object_set_data (G_OBJECT (window), "status", status);
g_object_unref (builder);
g_object_set_data_full (G_OBJECT(window), "builder", builder, g_object_unref);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
return window;
}
+551
View 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;
}
}
+210 -42
View File
@@ -12,11 +12,10 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <string.h>
#include "demoimage.h"
static GtkWidget *window = NULL;
static void
void
copy_button_clicked (GtkWidget *button,
gpointer user_data)
{
@@ -32,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)
@@ -69,14 +68,14 @@ paste_received (GObject *source_object,
"Could not paste text: %s",
error->message);
g_signal_connect (dialog, "response",
G_CALLBACK (gtk_window_destroy), NULL);
G_CALLBACK (gtk_widget_destroy), NULL);
gtk_widget_show (dialog);
g_error_free (error);
}
}
static void
void
paste_button_clicked (GtkWidget *button,
gpointer user_data)
{
@@ -94,6 +93,146 @@ paste_button_clicked (GtkWidget *button,
gdk_clipboard_read_text_async (clipboard, NULL, paste_received, entry);
}
static GdkPaintable *
get_image_paintable (GtkImage *image)
{
const gchar *icon_name;
GtkIconTheme *icon_theme;
GtkIconInfo *icon_info;
switch (gtk_image_get_storage_type (image))
{
case GTK_IMAGE_PAINTABLE:
return g_object_ref (gtk_image_get_paintable (image));
case GTK_IMAGE_ICON_NAME:
icon_name = gtk_image_get_icon_name (image);
icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (image)));
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 (gtk_icon_info_load_texture (icon_info));
default:
g_warning ("Image storage type %d not handled",
gtk_image_get_storage_type (image));
return NULL;
}
}
static void
drag_begin (GtkWidget *widget,
GdkDrag *drag,
gpointer data)
{
GdkPaintable *paintable;
paintable = get_image_paintable (GTK_IMAGE (widget));
if (paintable)
{
gtk_drag_set_icon_paintable (drag, paintable, -2, -2);
g_object_unref (paintable);
}
}
void
drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GtkSelectionData *selection_data,
guint info,
gpointer data)
{
GdkPaintable *paintable;
paintable = get_image_paintable (GTK_IMAGE (widget));
if (GDK_IS_TEXTURE (paintable))
gtk_selection_data_set_texture (selection_data, GDK_TEXTURE (paintable));
}
static void
drag_data_received (GtkWidget *widget,
GdkDrop *drop,
GtkSelectionData *selection_data,
gpointer 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));
if (paintable)
g_object_unref (paintable);
}
static void
paste_image_received (GObject *source,
GAsyncResult *result,
gpointer data)
{
GdkTexture *texture;
texture = gdk_clipboard_read_texture_finish (GDK_CLIPBOARD (source), result, NULL);
if (texture == NULL)
return;
gtk_image_set_from_paintable (GTK_IMAGE (data), GDK_PAINTABLE (texture));
g_object_unref (texture);
}
static void
paste_image (GtkMenuItem *item,
gpointer data)
{
GdkClipboard *clipboard;
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (data));
gdk_clipboard_read_texture_async (clipboard,
NULL,
paste_image_received,
data);
}
static void
pressed_cb (GtkGesture *gesture,
int n_press,
double x,
double y,
GtkWidget *image)
{
GtkWidget *menu;
GtkWidget *item;
menu = gtk_menu_new ();
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);
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_menu_popup_at_pointer (GTK_MENU (menu), NULL);
}
GtkWidget *
do_clipboard (GtkWidget *do_widget)
{
@@ -103,89 +242,118 @@ do_clipboard (GtkWidget *do_widget)
GtkWidget *label;
GtkWidget *entry, *button;
GtkWidget *image;
GtkGesture *gesture;
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");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
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_window_set_child (GTK_WINDOW (window), vbox);
gtk_container_add (GTK_CONTAINER (window), vbox);
label = gtk_label_new ("\"Copy\" will copy the text\nin the entry to the clipboard");
gtk_box_append (GTK_BOX (vbox), label);
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);
gtk_box_append (GTK_BOX (vbox), hbox);
g_object_set (hbox, "margin", 8, NULL);
gtk_container_add (GTK_CONTAINER (vbox), hbox);
/* Create the first entry */
entry = gtk_entry_new ();
gtk_box_append (GTK_BOX (hbox), entry);
gtk_container_add (GTK_CONTAINER (hbox), entry);
/* Create the button */
button = gtk_button_new_with_mnemonic (_("_Copy"));
gtk_box_append (GTK_BOX (hbox), button);
gtk_container_add (GTK_CONTAINER (hbox), button);
g_signal_connect (button, "clicked",
G_CALLBACK (copy_button_clicked), entry);
label = gtk_label_new ("\"Paste\" will paste the text from the clipboard to the entry");
gtk_box_append (GTK_BOX (vbox), label);
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);
gtk_box_append (GTK_BOX (vbox), hbox);
g_object_set (hbox, "margin", 8, NULL);
gtk_container_add (GTK_CONTAINER (vbox), hbox);
/* Create the second entry */
entry = gtk_entry_new ();
gtk_box_append (GTK_BOX (hbox), entry);
gtk_container_add (GTK_CONTAINER (hbox), entry);
/* Create the button */
button = gtk_button_new_with_mnemonic (_("_Paste"));
gtk_box_append (GTK_BOX (hbox), button);
gtk_container_add (GTK_CONTAINER (hbox), button);
g_signal_connect (button, "clicked",
G_CALLBACK (paste_button_clicked), entry);
label = gtk_label_new ("Images can be transferred via the clipboard, too");
gtk_box_append (GTK_BOX (vbox), label);
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);
gtk_box_append (GTK_BOX (vbox), hbox);
g_object_set (hbox, "margin", 8, NULL);
gtk_container_add (GTK_CONTAINER (vbox), hbox);
/* Create the first image */
image = demo_image_new ("dialog-warning");
gtk_box_append (GTK_BOX (hbox), image);
image = gtk_image_new_from_icon_name ("dialog-warning");
gtk_container_add (GTK_CONTAINER (hbox), image);
/* make image a drag 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 */
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));
/* Create the second image */
image = demo_image_new ("process-stop");
gtk_box_append (GTK_BOX (hbox), image);
image = gtk_image_new_from_icon_name ("process-stop");
gtk_container_add (GTK_CONTAINER (hbox), image);
/* Create the third image */
image = demo_image_new ("weather-clear");
gtk_box_append (GTK_BOX (hbox), image);
/* make image a drag 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 */
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));
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
return window;
}
-224
View File
@@ -1,224 +0,0 @@
// Originally from: https://www.shadertoy.com/view/3ljyDD
// License CC0: Hexagonal tiling + cog wheels
// Nothing fancy, just hexagonal tiling + cog wheels
#define PI 3.141592654
#define TAU (2.0*PI)
#define MROT(a) mat2(cos(a), sin(a), -sin(a), cos(a))
float hash(in vec2 co) {
return fract(sin(dot(co.xy ,vec2(12.9898,58.233))) * 13758.5453);
}
float pcos(float a) {
return 0.5 + 0.5*cos(a);
}
void rot(inout vec2 p, float a) {
float c = cos(a);
float s = sin(a);
p = vec2(c*p.x + s*p.y, -s*p.x + c*p.y);
}
float modPolar(inout vec2 p, float repetitions) {
float angle = 2.0*PI/repetitions;
float a = atan(p.y, p.x) + angle/2.;
float r = length(p);
float c = floor(a/angle);
a = mod(a,angle) - angle/2.;
p = vec2(cos(a), sin(a))*r;
// For an odd number of repetitions, fix cell index of the cell in -x direction
// (cell index would be e.g. -5 and 5 in the two halves of the cell):
if (abs(c) >= (repetitions/2.0)) c = abs(c);
return c;
}
float pmin(float a, float b, float k) {
float h = clamp( 0.5+0.5*(b-a)/k, 0.0, 1.0 );
return mix( b, a, h ) - k*h*(1.0-h);
}
const vec2 sz = vec2(1.0, sqrt(3.0));
const vec2 hsz = 0.5*sz;
const float smallCount = 16.0;
vec2 hextile(inout vec2 p) {
// See Art of Code: Hexagonal Tiling Explained!
// https://www.youtube.com/watch?v=VmrIDyYiJBA
vec2 p1 = mod(p, sz)-hsz;
vec2 p2 = mod(p - hsz*1.0, sz)-hsz;
vec2 p3 = mix(p2, p1, vec2(length(p1) < length(p2)));
vec2 n = p3 - p;
p = p3;
return n;
}
float circle(vec2 p, float r) {
return length(p) - r;
}
float box(vec2 p, vec2 b) {
vec2 d = abs(p)-b;
return length(max(d,0.0)) + min(max(d.x,d.y),0.0);
}
float unevenCapsule(vec2 p, float r1, float r2, float h) {
p.x = abs(p.x);
float b = (r1-r2)/h;
float a = sqrt(1.0-b*b);
float k = dot(p,vec2(-b,a));
if( k < 0.0 ) return length(p) - r1;
if( k > a*h ) return length(p-vec2(0.0,h)) - r2;
return dot(p, vec2(a,b) ) - r1;
}
float cogwheel(vec2 p, float innerRadius, float outerRadius, float cogs, float holes) {
float cogWidth = 0.25*innerRadius*TAU/cogs;
float d0 = circle(p, innerRadius);
vec2 icp = p;
modPolar(icp, holes);
icp -= vec2(innerRadius*0.55, 0.0);
float d1 = circle(icp, innerRadius*0.25);
vec2 cp = p;
modPolar(cp, cogs);
cp -= vec2(innerRadius, 0.0);
float d2 = unevenCapsule(cp.yx, cogWidth, cogWidth*0.75, (outerRadius-innerRadius));
float d3 = circle(p, innerRadius*0.20);
float d = 1E6;
d = min(d, d0);
d = pmin(d, d2, 0.5*cogWidth);
d = min(d, d2);
d = max(d, -d1);
d = max(d, -d3);
return d;
}
float ccell1(vec2 p, float r) {
float d = 1E6;
const float bigCount = 60.0;
vec2 cp0 = p;
rot(cp0, -iTime*TAU/bigCount);
float d0 = cogwheel(cp0, 0.36, 0.38, bigCount, 5.0);
vec2 cp1 = p;
float nm = modPolar(cp1, 6.0);
cp1 -= vec2(0.5, 0.0);
rot(cp1, 0.2+TAU*nm/2.0 + iTime*TAU/smallCount);
float d1 = cogwheel(cp1, 0.11, 0.125, smallCount, 5.0);
d = min(d, d0);
d = min(d, d1);
return d;
}
float ccell2(vec2 p, float r) {
float d = 1E6;
vec2 cp0 = p;
float nm = modPolar(cp0, 6.0);
vec2 cp1 = cp0;
const float off = 0.275;
const float count = smallCount + 2.0;
cp0 -= vec2(off, 0.0);
rot(cp0, 0.+TAU*nm/2.0 - iTime*TAU/count);
float d0 = cogwheel(cp0, 0.09, 0.105, count, 5.0);
cp1 -= vec2(0.5, 0.0);
rot(cp1, 0.2+TAU*nm/2.0 + iTime*TAU/smallCount);
float d1 = cogwheel(cp1, 0.11, 0.125, smallCount, 5.0);
float l = length(p);
float d2 = l - (off+0.055);
float d3 = d2 + 0.020;;
vec2 tp0 = p;
modPolar(tp0, 60.0);
tp0.x -= off;
float d4 = box(tp0, vec2(0.0125, 0.005));
float ctime = -(iTime*0.05 + r)*TAU;
vec2 tp1 = p;
rot(tp1, ctime*12.0);
tp1.x -= 0.13;
float d5 = box(tp1, vec2(0.125, 0.005));
vec2 tp2 = p;
rot(tp2, ctime);
tp2.x -= 0.13*0.5;
float d6 = box(tp2, vec2(0.125*0.5, 0.0075));
float d7 = l - 0.025;
float d8 = l - 0.0125;
d = min(d, d0);
d = min(d, d1);
d = min(d, d2);
d = max(d, -d3);
d = min(d, d4);
d = min(d, d5);
d = min(d, d6);
d = min(d, d7);
d = max(d, -d8);
return d;
}
float df(vec2 p, float scale, inout vec2 nn) {
p /= scale;
nn = hextile(p);
nn = round(nn);
float r = hash(nn);
float d;;
if (r < 0.5) {
d = ccell1(p, r);
} else {
d = ccell2(p, r);
}
return d*scale;
}
vec3 postProcess(vec3 col, vec2 q) {
//col = saturate(col);
col=pow(clamp(col,0.0,1.0),vec3(0.75));
col=col*0.6+0.4*col*col*(3.0-2.0*col); // contrast
col=mix(col, vec3(dot(col, vec3(0.33))), -0.4); // satuation
col*=0.5+0.5*pow(19.0*q.x*q.y*(1.0-q.x)*(1.0-q.y),0.7); // vigneting
return col;
}
void mainImage(out vec4 fragColor, vec2 fragCoord) {
vec2 q = fragCoord/iResolution.xy;
vec2 p = -1.0 + 2.0*q;
p.x *= iResolution.x/iResolution.y;
float tm = iTime*0.1;
p += vec2(cos(tm), sin(tm*sqrt(0.5)));
float z = mix(0.5, 1.0, pcos(tm*sqrt(0.3)));
float aa = 4.0 / iResolution.y;
vec2 nn = vec2(0.0);
float d = df(p, z, nn);
vec3 col = vec3(160.0)/vec3(255.0);
vec3 baseCol = vec3(0.3);
vec4 logoCol = vec4(baseCol, 1.0)*smoothstep(-aa, 0.0, -d);
col = mix(col, logoCol.xyz, pow(logoCol.w, 8.0));
col += 0.4*pow(abs(sin(20.0*d)), 0.6);
col = postProcess(col, q);
fragColor = vec4(col, 1.0);
}
-226
View File
@@ -1,226 +0,0 @@
uniform float iTime;
// Originally from: https://www.shadertoy.com/view/3ljyDD
// License CC0: Hexagonal tiling + cog wheels
// Nothing fancy, just hexagonal tiling + cog wheels
#define PI 3.141592654
#define TAU (2.0*PI)
#define MROT(a) mat2(cos(a), sin(a), -sin(a), cos(a))
float hash(in vec2 co) {
return fract(sin(dot(co.xy ,vec2(12.9898,58.233))) * 13758.5453);
}
float pcos(float a) {
return 0.5 + 0.5*cos(a);
}
void rot(inout vec2 p, float a) {
float c = cos(a);
float s = sin(a);
p = vec2(c*p.x + s*p.y, -s*p.x + c*p.y);
}
float modPolar(inout vec2 p, float repetitions) {
float angle = 2.0*PI/repetitions;
float a = atan(p.y, p.x) + angle/2.;
float r = length(p);
float c = floor(a/angle);
a = mod(a,angle) - angle/2.;
p = vec2(cos(a), sin(a))*r;
// For an odd number of repetitions, fix cell index of the cell in -x direction
// (cell index would be e.g. -5 and 5 in the two halves of the cell):
if (abs(c) >= (repetitions/2.0)) c = abs(c);
return c;
}
float pmin(float a, float b, float k) {
float h = clamp( 0.5+0.5*(b-a)/k, 0.0, 1.0 );
return mix( b, a, h ) - k*h*(1.0-h);
}
const vec2 sz = vec2(1.0, sqrt(3.0));
const vec2 hsz = 0.5*sz;
const float smallCount = 16.0;
vec2 hextile(inout vec2 p) {
// See Art of Code: Hexagonal Tiling Explained!
// https://www.youtube.com/watch?v=VmrIDyYiJBA
vec2 p1 = mod(p, sz)-hsz;
vec2 p2 = mod(p - hsz*1.0, sz)-hsz;
vec2 p3 = mix(p2, p1, vec2(length(p1) < length(p2)));
vec2 n = p3 - p;
p = p3;
return n;
}
float circle(vec2 p, float r) {
return length(p) - r;
}
float box(vec2 p, vec2 b) {
vec2 d = abs(p)-b;
return length(max(d,0.0)) + min(max(d.x,d.y),0.0);
}
float unevenCapsule(vec2 p, float r1, float r2, float h) {
p.x = abs(p.x);
float b = (r1-r2)/h;
float a = sqrt(1.0-b*b);
float k = dot(p,vec2(-b,a));
if( k < 0.0 ) return length(p) - r1;
if( k > a*h ) return length(p-vec2(0.0,h)) - r2;
return dot(p, vec2(a,b) ) - r1;
}
float cogwheel(vec2 p, float innerRadius, float outerRadius, float cogs, float holes) {
float cogWidth = 0.25*innerRadius*TAU/cogs;
float d0 = circle(p, innerRadius);
vec2 icp = p;
modPolar(icp, holes);
icp -= vec2(innerRadius*0.55, 0.0);
float d1 = circle(icp, innerRadius*0.25);
vec2 cp = p;
modPolar(cp, cogs);
cp -= vec2(innerRadius, 0.0);
float d2 = unevenCapsule(cp.yx, cogWidth, cogWidth*0.75, (outerRadius-innerRadius));
float d3 = circle(p, innerRadius*0.20);
float d = 1E6;
d = min(d, d0);
d = pmin(d, d2, 0.5*cogWidth);
d = min(d, d2);
d = max(d, -d1);
d = max(d, -d3);
return d;
}
float ccell1(vec2 p, float r) {
float d = 1E6;
const float bigCount = 60.0;
vec2 cp0 = p;
rot(cp0, -iTime*TAU/bigCount);
float d0 = cogwheel(cp0, 0.36, 0.38, bigCount, 5.0);
vec2 cp1 = p;
float nm = modPolar(cp1, 6.0);
cp1 -= vec2(0.5, 0.0);
rot(cp1, 0.2+TAU*nm/2.0 + iTime*TAU/smallCount);
float d1 = cogwheel(cp1, 0.11, 0.125, smallCount, 5.0);
d = min(d, d0);
d = min(d, d1);
return d;
}
float ccell2(vec2 p, float r) {
float d = 1E6;
vec2 cp0 = p;
float nm = modPolar(cp0, 6.0);
vec2 cp1 = cp0;
const float off = 0.275;
const float count = smallCount + 2.0;
cp0 -= vec2(off, 0.0);
rot(cp0, 0.+TAU*nm/2.0 - iTime*TAU/count);
float d0 = cogwheel(cp0, 0.09, 0.105, count, 5.0);
cp1 -= vec2(0.5, 0.0);
rot(cp1, 0.2+TAU*nm/2.0 + iTime*TAU/smallCount);
float d1 = cogwheel(cp1, 0.11, 0.125, smallCount, 5.0);
float l = length(p);
float d2 = l - (off+0.055);
float d3 = d2 + 0.020;;
vec2 tp0 = p;
modPolar(tp0, 60.0);
tp0.x -= off;
float d4 = box(tp0, vec2(0.0125, 0.005));
float ctime = -(iTime*0.05 + r)*TAU;
vec2 tp1 = p;
rot(tp1, ctime*12.0);
tp1.x -= 0.13;
float d5 = box(tp1, vec2(0.125, 0.005));
vec2 tp2 = p;
rot(tp2, ctime);
tp2.x -= 0.13*0.5;
float d6 = box(tp2, vec2(0.125*0.5, 0.0075));
float d7 = l - 0.025;
float d8 = l - 0.0125;
d = min(d, d0);
d = min(d, d1);
d = min(d, d2);
d = max(d, -d3);
d = min(d, d4);
d = min(d, d5);
d = min(d, d6);
d = min(d, d7);
d = max(d, -d8);
return d;
}
float df(vec2 p, float scale, inout vec2 nn) {
p /= scale;
nn = hextile(p);
nn = round(nn);
float r = hash(nn);
float d;;
if (r < 0.5) {
d = ccell1(p, r);
} else {
d = ccell2(p, r);
}
return d*scale;
}
vec3 postProcess(vec3 col, vec2 q) {
//col = saturate(col);
col=pow(clamp(col,0.0,1.0),vec3(0.75));
col=col*0.6+0.4*col*col*(3.0-2.0*col); // contrast
col=mix(col, vec3(dot(col, vec3(0.33))), -0.4); // satuation
col*=0.5+0.5*pow(19.0*q.x*q.y*(1.0-q.x)*(1.0-q.y),0.7); // vigneting
return col;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv) {
vec2 q = fragCoord/resolution.xy;
vec2 p = -1.0 + 2.0*q;
p.x *= resolution.x/resolution.y;
float tm = iTime*0.1;
p += vec2(cos(tm), sin(tm*sqrt(0.5)));
float z = mix(0.5, 1.0, pcos(tm*sqrt(0.3)));
float aa = 4.0 / resolution.y;
vec2 nn = vec2(0.0);
float d = df(p, z, nn);
vec3 col = vec3(160.0)/vec3(255.0);
vec3 baseCol = vec3(0.3);
vec4 logoCol = vec4(baseCol, 1.0)*smoothstep(-aa, 0.0, -d);
col = mix(col, logoCol.xyz, pow(logoCol.w, 8.0));
col += 0.4*pow(abs(sin(20.0*d)), 0.6);
col = postProcess(col, q);
fragColor = vec4(col, 1.0);
}
File diff suppressed because it is too large Load Diff
+116
View File
@@ -0,0 +1,116 @@
/* Color Chooser
*
* A GtkColorChooser lets the user choose a color. There are several
* implementations of the GtkColorChooser interface in GTK. The
* GtkColorChooserDialog is a prebuilt dialog containing a
* GtkColorChooserWidget.
*/
#include <gtk/gtk.h>
static GtkWidget *window = NULL;
static GtkWidget *da;
static GdkRGBA color;
static GtkWidget *frame;
/* draw callback for the drawing area
*/
static void
draw_function (GtkDrawingArea *da,
cairo_t *cr,
int width,
int height,
gpointer data)
{
gdk_cairo_set_source_rgba (cr, &color);
cairo_paint (cr);
}
static void
response_cb (GtkDialog *dialog,
gint response_id,
gpointer user_data)
{
if (response_id == GTK_RESPONSE_OK)
{
gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (dialog), &color);
gtk_widget_queue_draw (da);
}
gtk_widget_destroy (GTK_WIDGET (dialog));
}
static void
change_color_callback (GtkWidget *button,
gpointer data)
{
GtkWidget *dialog;
dialog = gtk_color_chooser_dialog_new ("Changing color", GTK_WINDOW (window));
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (dialog), &color);
g_signal_connect (dialog, "response",
G_CALLBACK (response_cb), NULL);
gtk_widget_show (dialog);
}
GtkWidget *
do_colorsel (GtkWidget *do_widget)
{
GtkWidget *vbox;
GtkWidget *button;
if (!window)
{
color.red = 0;
color.blue = 1;
color.green = 0;
color.alpha = 1;
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");
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8);
g_object_set (vbox, "margin", 12, NULL);
gtk_container_add (GTK_CONTAINER (window), vbox);
/*
* Create the color swatch area
*/
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
gtk_container_add (GTK_CONTAINER (vbox), frame);
da = gtk_drawing_area_new ();
gtk_drawing_area_set_content_width (GTK_DRAWING_AREA (da), 200);
gtk_drawing_area_set_content_height (GTK_DRAWING_AREA (da), 200);
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (da), draw_function, NULL, NULL);
gtk_container_add (GTK_CONTAINER (frame), da);
button = gtk_button_new_with_mnemonic ("_Change the above color");
gtk_widget_set_halign (button, GTK_ALIGN_END);
gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
gtk_container_add (GTK_CONTAINER (vbox), button);
g_signal_connect (button, "clicked",
G_CALLBACK (change_color_callback), NULL);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_widget_destroy (window);
return window;
}
+34 -48
View File
@@ -1,5 +1,4 @@
/* Combo Boxes
* #Keywords: GtkCellRenderer
*
* The GtkComboBox widget allows to select one option out of a list.
* The GtkComboBoxEntry additionally allows the user to enter a value
@@ -20,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",
@@ -28,7 +27,7 @@ create_icon_store (void)
NULL,
"document-open"
};
const char *labels[6] = {
const gchar *labels[6] = {
N_("Warning"),
N_("Stop"),
N_("New"),
@@ -39,7 +38,7 @@ create_icon_store (void)
GtkTreeIter iter;
GtkListStore *store;
int i;
gint i;
store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
@@ -78,7 +77,7 @@ set_sensitive (GtkCellLayout *cell_layout,
gpointer data)
{
GtkTreePath *path;
int *indices;
gint *indices;
gboolean sensitive;
path = gtk_tree_model_get_path (tree_model, iter);
@@ -112,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" },
@@ -176,7 +175,7 @@ create_capital_store (void)
GtkTreeIter iter, iter2;
GtkTreeStore *store;
int i;
gint i;
store = gtk_tree_store_new (1, G_TYPE_STRING);
@@ -235,7 +234,7 @@ typedef struct _MaskEntry MaskEntry;
struct _MaskEntry
{
GtkEntry entry;
const char *mask;
gchar *mask;
};
typedef struct _MaskEntryClass MaskEntryClass;
@@ -247,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));
@@ -312,36 +310,32 @@ 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");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
g_signal_connect (window, "destroy",
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);
gtk_window_set_child (GTK_WINDOW (window), vbox);
g_object_set (vbox, "margin", 10, NULL);
gtk_container_add (GTK_CONTAINER (window), vbox);
/* A combobox demonstrating cell renderers, separators and
* insensitive rows
*/
frame = gtk_frame_new ("Items with icons");
gtk_box_append (GTK_BOX (vbox), frame);
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);
gtk_frame_set_child (GTK_FRAME (frame), box);
g_object_set (box, "margin", 5, NULL);
gtk_container_add (GTK_CONTAINER (frame), box);
model = create_icon_store ();
combo = gtk_combo_box_new_with_model (model);
g_object_unref (model);
gtk_box_append (GTK_BOX (box), combo);
gtk_container_add (GTK_CONTAINER (box), combo);
renderer = gtk_cell_renderer_pixbuf_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, FALSE);
@@ -373,19 +367,16 @@ do_combobox (GtkWidget *do_widget)
/* A combobox demonstrating trees.
*/
frame = gtk_frame_new ("Where are we ?");
gtk_box_append (GTK_BOX (vbox), frame);
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);
gtk_frame_set_child (GTK_FRAME (frame), box);
g_object_set (box, "margin", 5, NULL);
gtk_container_add (GTK_CONTAINER (frame), box);
model = create_capital_store ();
combo = gtk_combo_box_new_with_model (model);
g_object_unref (model);
gtk_box_append (GTK_BOX (box), combo);
gtk_container_add (GTK_CONTAINER (box), combo);
renderer = gtk_cell_renderer_text_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
@@ -404,52 +395,47 @@ do_combobox (GtkWidget *do_widget)
/* A GtkComboBoxEntry with validation */
frame = gtk_frame_new ("Editable");
gtk_box_append (GTK_BOX (vbox), frame);
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);
gtk_frame_set_child (GTK_FRAME (frame), box);
g_object_set (box, "margin", 5, NULL);
gtk_container_add (GTK_CONTAINER (frame), box);
combo = gtk_combo_box_text_new_with_entry ();
fill_combo_entry (combo);
gtk_box_append (GTK_BOX (box), combo);
gtk_container_add (GTK_CONTAINER (box), combo);
entry = g_object_new (TYPE_MASK_ENTRY, NULL);
MASK_ENTRY (entry)->mask = "^([0-9]*|One|Two|2\302\275|Three)$";
gtk_combo_box_set_child (GTK_COMBO_BOX (combo), entry);
gtk_container_remove (GTK_CONTAINER (combo), gtk_bin_get_child (GTK_BIN (combo)));
gtk_container_add (GTK_CONTAINER (combo), entry);
/* A combobox with string IDs */
frame = gtk_frame_new ("String IDs");
gtk_box_append (GTK_BOX (vbox), frame);
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);
gtk_frame_set_child (GTK_FRAME (frame), box);
g_object_set (box, "margin", 5, NULL);
gtk_container_add (GTK_CONTAINER (frame), box);
combo = gtk_combo_box_text_new ();
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "never", "Not visible");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "when-active", "Visible when active");
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), "always", "Always visible");
gtk_box_append (GTK_BOX (box), combo);
gtk_container_add (GTK_CONTAINER (box), combo);
entry = gtk_entry_new ();
g_object_bind_property (combo, "active-id",
entry, "text",
G_BINDING_BIDIRECTIONAL);
gtk_box_append (GTK_BOX (box), entry);
gtk_container_add (GTK_CONTAINER (box), entry);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
return window;
}
-285
View File
@@ -1,285 +0,0 @@
/* Constraints/Simple Constraints
* #Keywords: GtkLayoutManager
*
* GtkConstraintLayout provides a layout manager that uses relations
* between widgets (also known as “constraints”) to compute the position
* and size of each child.
*
* In addition to child widgets, the constraints can involve spacer
* objects (also known as “guides”). This example has a guide between
* the two buttons in the top row.
*
* Try resizing the window to see how the constraints react to update
* the layout.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
G_DECLARE_FINAL_TYPE (SimpleGrid, simple_grid, SIMPLE, GRID, GtkWidget)
struct _SimpleGrid
{
GtkWidget parent_instance;
GtkWidget *button1, *button2;
GtkWidget *button3;
};
G_DEFINE_TYPE (SimpleGrid, simple_grid, GTK_TYPE_WIDGET)
static void
simple_grid_dispose (GObject *object)
{
SimpleGrid *self = SIMPLE_GRID (object);
g_clear_pointer (&self->button1, gtk_widget_unparent);
g_clear_pointer (&self->button2, gtk_widget_unparent);
g_clear_pointer (&self->button3, gtk_widget_unparent);
G_OBJECT_CLASS (simple_grid_parent_class)->dispose (object);
}
static void
simple_grid_class_init (SimpleGridClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = simple_grid_dispose;
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
}
/* Layout:
*
* +-------------------------------------+
* | +-----------++-------++-----------+ |
* | | Child 1 || Space || Child 2 | |
* | +-----------++-------++-----------+ |
* | +---------------------------------+ |
* | | Child 3 | |
* | +---------------------------------+ |
* +-------------------------------------+
*
* Constraints:
*
* super.start = child1.start - 8
* child1.width = child2.width
* child1.end = space.start
* space.end = child2.start
* child2.end = super.end - 8
* super.start = child3.start - 8
* child3.end = super.end - 8
* super.top = child1.top - 8
* super.top = child2.top - 8
* child1.bottom = child3.top - 12
* child2.bottom = child3.top - 12
* child3.height = child1.height
* child3.height = child2.height
* child3.bottom = super.bottom - 8
*
* To add some flexibility, we make the space
* stretchable:
*
* space.width >= 10
* space.width = 100
* space.width <= 200
*/
static void
build_constraints (SimpleGrid *self,
GtkConstraintLayout *manager)
{
GtkConstraintGuide *guide;
guide = gtk_constraint_guide_new ();
gtk_constraint_guide_set_name (guide, "space");
gtk_constraint_guide_set_min_size (guide, 10, 10);
gtk_constraint_guide_set_nat_size (guide, 100, 10);
gtk_constraint_guide_set_max_size (guide, 200, 20);
gtk_constraint_guide_set_strength (guide, GTK_CONSTRAINT_STRENGTH_STRONG);
gtk_constraint_layout_add_guide (manager, guide);
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new_constant (GTK_CONSTRAINT_TARGET (self->button1),
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
GTK_CONSTRAINT_RELATION_LE,
200.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_START,
GTK_CONSTRAINT_RELATION_EQ,
self->button1,
GTK_CONSTRAINT_ATTRIBUTE_START,
1.0,
-8.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (self->button1,
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
GTK_CONSTRAINT_RELATION_EQ,
self->button2,
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (self->button1,
GTK_CONSTRAINT_ATTRIBUTE_END,
GTK_CONSTRAINT_RELATION_EQ,
guide,
GTK_CONSTRAINT_ATTRIBUTE_START,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (guide,
GTK_CONSTRAINT_ATTRIBUTE_END,
GTK_CONSTRAINT_RELATION_EQ,
self->button2,
GTK_CONSTRAINT_ATTRIBUTE_START,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (self->button2,
GTK_CONSTRAINT_ATTRIBUTE_END,
GTK_CONSTRAINT_RELATION_EQ,
NULL,
GTK_CONSTRAINT_ATTRIBUTE_END,
1.0,
-8.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_START,
GTK_CONSTRAINT_RELATION_EQ,
self->button3,
GTK_CONSTRAINT_ATTRIBUTE_START,
1.0,
-8.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (self->button3,
GTK_CONSTRAINT_ATTRIBUTE_END,
GTK_CONSTRAINT_RELATION_EQ,
NULL,
GTK_CONSTRAINT_ATTRIBUTE_END,
1.0,
-8.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_TOP,
GTK_CONSTRAINT_RELATION_EQ,
self->button1,
GTK_CONSTRAINT_ATTRIBUTE_TOP,
1.0,
-8.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_TOP,
GTK_CONSTRAINT_RELATION_EQ,
self->button2,
GTK_CONSTRAINT_ATTRIBUTE_TOP,
1.0,
-8.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (self->button1,
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
GTK_CONSTRAINT_RELATION_EQ,
self->button3,
GTK_CONSTRAINT_ATTRIBUTE_TOP,
1.0,
-12.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (self->button2,
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
GTK_CONSTRAINT_RELATION_EQ,
self->button3,
GTK_CONSTRAINT_ATTRIBUTE_TOP,
1.0,
-12.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (self->button3,
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
GTK_CONSTRAINT_RELATION_EQ,
self->button1,
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (self->button3,
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
GTK_CONSTRAINT_RELATION_EQ,
self->button2,
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (self->button3,
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
GTK_CONSTRAINT_RELATION_EQ,
NULL,
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
1.0,
-8.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
}
static void
simple_grid_init (SimpleGrid *self)
{
GtkWidget *widget = GTK_WIDGET (self);
self->button1 = gtk_button_new_with_label ("Child 1");
gtk_widget_set_parent (self->button1, widget);
self->button2 = gtk_button_new_with_label ("Child 2");
gtk_widget_set_parent (self->button2, widget);
self->button3 = gtk_button_new_with_label ("Child 3");
gtk_widget_set_parent (self->button3, widget);
GtkLayoutManager *manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
build_constraints (self, GTK_CONSTRAINT_LAYOUT (manager));
}
GtkWidget *
do_constraints (GtkWidget *do_widget)
{
static GtkWidget *window;
if (!window)
{
GtkWidget *box, *grid;
window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Simple Constraints");
gtk_window_set_default_size (GTK_WINDOW (window), 260, -1);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
gtk_window_set_child (GTK_WINDOW (window), box);
grid = g_object_new (simple_grid_get_type (), NULL);
gtk_widget_set_hexpand (grid, TRUE);
gtk_widget_set_vexpand (grid, TRUE);
gtk_box_append (GTK_BOX (box), grid);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}
-74
View File
@@ -1,74 +0,0 @@
/* Constraints/Builder
*
* GtkConstraintLayouts can be created in .ui files, and constraints can
* be set up at that time as well, as this example demonstrates. It shows
* various ways to do spacing and sizing with constraints.
*
* Make the window wider to see the rows react differently
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
G_DECLARE_FINAL_TYPE (ConstraintsGrid, constraints_grid, CONSTRAINTS, GRID, GtkWidget)
struct _ConstraintsGrid
{
GtkWidget parent_instance;
};
G_DEFINE_TYPE (ConstraintsGrid, constraints_grid, GTK_TYPE_WIDGET)
static void
constraints_grid_init (ConstraintsGrid *grid)
{
}
static void
constraints_grid_dispose (GObject *object)
{
GtkWidget *widget = GTK_WIDGET (object);
GtkWidget *child;
while ((child = gtk_widget_get_first_child (widget)))
gtk_widget_unparent (child);
G_OBJECT_CLASS (constraints_grid_parent_class)->dispose (object);
}
static void
constraints_grid_class_init (ConstraintsGridClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = constraints_grid_dispose;
}
GtkWidget *
do_constraints_builder (GtkWidget *do_widget)
{
static GtkWidget *window;
if (!window)
{
GtkBuilder *builder;
g_type_ensure (constraints_grid_get_type ());
builder = gtk_builder_new_from_resource ("/constraints_builder/constraints_builder.ui");
window = GTK_WIDGET (gtk_builder_get_object (builder, "window1"));
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
g_object_unref (builder);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}
-460
View File
@@ -1,460 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow" id="window1">
<property name="title" translatable="yes">Constraints — Builder</property>
<property name="default-width">260</property>
<child>
<object class="ConstraintsGrid">
<property name="halign">fill</property>
<property name="valign">fill</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="layout-manager">
<object class="GtkConstraintLayout">
<constraints>
<guide name="guide1" min-width="10" nat-width="200" strength="weak"/>
<guide name="guide2" min-width="10" nat-width="200" strength="weak"/>
<guide name="guide3" min-width="10" nat-width="200" strength="weak"/>
<guide name="guide4" min-width="10" nat-width="200" strength="weak"/>
<guide name="guide5" min-width="10" nat-width="200" strength="weak"/>
<guide name="guide6" min-width="10" nat-width="200" strength="weak"/>
<guide name="guide7" min-width="10" nat-width="200" strength="weak"/>
<guide name="guide8" min-width="10" nat-width="200" strength="weak"/>
<guide name="guide9" min-width="0" nat-width="200" strength="weak"/>
<guide name="guide10" min-width="0" nat-width="200" strength="weak"/>
<guide name="barrier1" min-height="10"/>
<guide name="barrier2" min-height="10"/>
<guide name="barrier3" min-height="10"/>
<guide name="barrier4" min-height="10"/>
<!-- Spread Chain -->
<constraint target="super" target-attribute="top"
relation="eq"
source="button1" source-attribute="top"
strength="required"/>
<constraint target="super" target-attribute="top"
relation="eq"
source="button2" source-attribute="top"
strength="required"/>
<constraint target="super" target-attribute="top"
relation="eq"
source="button3" source-attribute="top"
strength="required"/>
<constraint target="super" target-attribute="left"
relation="eq"
source="guide1" source-attribute="left"
strength="required"/>
<constraint target="button1" target-attribute="left"
relation="eq"
source="guide1" source-attribute="right"
strength="required"/>
<constraint target="guide2" target-attribute="left"
relation="eq"
source="button1" source-attribute="right"
strength="required"/>
<constraint target="button2" target-attribute="left"
relation="eq"
source="guide2" source-attribute="right"
strength="required"/>
<constraint target="guide3" target-attribute="left"
relation="eq"
source="button2" source-attribute="right"
strength="required"/>
<constraint target="button3" target-attribute="left"
relation="eq"
source="guide3" source-attribute="right"
strength="required"/>
<constraint target="guide4" target-attribute="left"
relation="eq"
source="button3" source-attribute="right"
strength="required"/>
<constraint target="super" target-attribute="right"
relation="eq"
source="guide4" source-attribute="right"
strength="required"/>
<constraint target="guide1" target-attribute="width"
relation="eq"
source="guide2" source-attribute="width"
strength="required"/>
<constraint target="guide2" target-attribute="width"
relation="eq"
source="guide3" source-attribute="width"
strength="required"/>
<constraint target="guide3" target-attribute="width"
relation="eq"
source="guide4" source-attribute="width"
strength="required"/>
<constraint target="button1" target-attribute="width"
relation="eq"
source="button2" source-attribute="width"
strength="required"/>
<constraint target="button2" target-attribute="width"
relation="eq"
source="button3" source-attribute="width"
strength="required"/>
<constraint target="button1" target-attribute="bottom"
relation="eq"
source="barrier1" source-attribute="top"
strength="required"/>
<constraint target="button2" target-attribute="bottom"
relation="eq"
source="barrier1" source-attribute="top"
strength="required"/>
<constraint target="button3" target-attribute="bottom"
relation="eq"
source="barrier1" source-attribute="top"
strength="required"/>
<!-- Spread Inside Chain -->
<constraint target="super" target-attribute="left"
relation="eq"
source="button4" source-attribute="left"
strength="required"/>
<constraint target="guide5" target-attribute="left"
relation="eq"
source="button4" source-attribute="right"
strength="required"/>
<constraint target="button5" target-attribute="left"
relation="eq"
source="guide5" source-attribute="right"
strength="required"/>
<constraint target="guide6" target-attribute="left"
relation="eq"
source="button5" source-attribute="right"
strength="required"/>
<constraint target="button6" target-attribute="left"
relation="eq"
source="guide6" source-attribute="right"
strength="required"/>
<constraint target="super" target-attribute="right"
relation="eq"
source="button6" source-attribute="right"
strength="required"/>
<constraint target="guide5" target-attribute="width"
relation="eq"
source="guide6" source-attribute="width"
strength="required"/>
<constraint target="button4" target-attribute="width"
relation="eq"
source="button5" source-attribute="width"
strength="required"/>
<constraint target="button5" target-attribute="width"
relation="eq"
source="button6" source-attribute="width"
strength="required"/>
<constraint target="button4" target-attribute="top"
relation="eq"
source="barrier1" source-attribute="bottom"
strength="required"/>
<constraint target="button5" target-attribute="top"
relation="eq"
source="barrier1" source-attribute="bottom"
strength="required"/>
<constraint target="button6" target-attribute="top"
relation="eq"
source="barrier1" source-attribute="bottom"
strength="required"/>
<constraint target="button4" target-attribute="bottom"
relation="eq"
source="barrier2" source-attribute="top"
strength="required"/>
<constraint target="button5" target-attribute="bottom"
relation="eq"
source="barrier2" source-attribute="top"
strength="required"/>
<constraint target="button6" target-attribute="bottom"
relation="eq"
source="barrier2" source-attribute="top"
strength="required"/>
<!-- Weighted Chain -->
<constraint target="super" target-attribute="left"
relation="eq"
source="button7" source-attribute="left"
strength="required"/>
<constraint target="button8" target-attribute="left"
relation="eq"
source="button7" source-attribute="right"
constant="10"
strength="required"/>
<constraint target="button9" target-attribute="left"
relation="eq"
source="button8" source-attribute="right"
constant="10"
strength="required"/>
<constraint target="super" target-attribute="right"
relation="eq"
source="button9" source-attribute="right"
strength="required"/>
<constraint target="button8" target-attribute="width"
relation="eq"
source="button7" source-attribute="width"
multiplier="2"
strength="required"/>
<constraint target="button9" target-attribute="width"
relation="eq"
source="button7" source-attribute="width"
multiplier="3"
strength="required"/>
<constraint target="button7" target-attribute="top"
relation="eq"
source="barrier2" source-attribute="bottom"
strength="required"/>
<constraint target="button8" target-attribute="top"
relation="eq"
source="barrier2" source-attribute="bottom"
strength="required"/>
<constraint target="button9" target-attribute="top"
relation="eq"
source="barrier2" source-attribute="bottom"
strength="required"/>
<constraint target="button7" target-attribute="bottom"
relation="eq"
source="barrier3" source-attribute="top"
strength="required"/>
<constraint target="button8" target-attribute="bottom"
relation="eq"
source="barrier3" source-attribute="top"
strength="required"/>
<constraint target="button9" target-attribute="bottom"
relation="eq"
source="barrier3" source-attribute="top"
strength="required"/>
<!-- Packed Chain -->
<constraint target="super" target-attribute="left"
relation="eq"
source="guide7" source-attribute="left"
strength="required"/>
<constraint target="button10" target-attribute="left"
relation="eq"
source="guide7" source-attribute="right"
strength="required"/>
<constraint target="button11" target-attribute="left"
relation="eq"
source="button10" source-attribute="right"
constant="10"
strength="required"/>
<constraint target="button12" target-attribute="left"
relation="eq"
source="button11" source-attribute="right"
constant="10"
strength="required"/>
<constraint target="guide8" target-attribute="left"
relation="eq"
source="button12" source-attribute="right"
strength="required"/>
<constraint target="super" target-attribute="right"
relation="eq"
source="guide8" source-attribute="right"
strength="required"/>
<constraint target="guide7" target-attribute="width"
relation="eq"
source="guide8" source-attribute="width"
strength="required"/>
<constraint target="button10" target-attribute="width"
relation="eq"
source="button11" source-attribute="width"
strength="required"/>
<constraint target="button11" target-attribute="width"
relation="eq"
source="button12" source-attribute="width"
strength="required"/>
<constraint target="button10" target-attribute="top"
relation="eq"
source="barrier3" source-attribute="bottom"
strength="required"/>
<constraint target="button11" target-attribute="top"
relation="eq"
source="barrier3" source-attribute="bottom"
strength="required"/>
<constraint target="button12" target-attribute="top"
relation="eq"
source="barrier3" source-attribute="bottom"
strength="required"/>
<constraint target="button10" target-attribute="bottom"
relation="eq"
source="barrier4" source-attribute="top"
strength="required"/>
<constraint target="button11" target-attribute="bottom"
relation="eq"
source="barrier4" source-attribute="top"
strength="required"/>
<constraint target="button12" target-attribute="bottom"
relation="eq"
source="barrier4" source-attribute="top"
strength="required"/>
<!-- Packed Chain with Bias -->
<constraint target="super" target-attribute="left"
relation="eq"
source="guide9" source-attribute="left"
strength="required"/>
<constraint target="button13" target-attribute="left"
relation="eq"
source="guide9" source-attribute="right"
constant="10"
strength="required"/>
<constraint target="button14" target-attribute="left"
relation="eq"
source="button13" source-attribute="right"
constant="10"
strength="required"/>
<constraint target="button15" target-attribute="left"
relation="eq"
source="button14" source-attribute="right"
constant="10"
strength="required"/>
<constraint target="guide10" target-attribute="left"
relation="eq"
source="button15" source-attribute="right"
constant="10"
strength="required"/>
<constraint target="super" target-attribute="right"
relation="eq"
source="guide10" source-attribute="right"
strength="required"/>
<constraint target="guide9" target-attribute="width"
relation="eq"
source="guide10" source-attribute="width"
multiplier="4"
strength="required"/>
<constraint target="button13" target-attribute="width"
relation="eq"
source="button14" source-attribute="width"
strength="required"/>
<constraint target="button14" target-attribute="width"
relation="eq"
source="button15" source-attribute="width"
strength="required"/>
<constraint target="button13" target-attribute="top"
relation="eq"
source="barrier4" source-attribute="bottom"
strength="required"/>
<constraint target="button14" target-attribute="top"
relation="eq"
source="barrier4" source-attribute="bottom"
strength="required"/>
<constraint target="button15" target-attribute="top"
relation="eq"
source="barrier4" source-attribute="bottom"
strength="required"/>
<constraint target="super" target-attribute="bottom"
relation="ge"
source="button13" source-attribute="bottom"
strength="required"/>
<constraint target="super" target-attribute="bottom"
relation="ge"
source="button14" source-attribute="bottom"
strength="required"/>
<constraint target="super" target-attribute="bottom"
relation="ge"
source="button15" source-attribute="bottom"
strength="required"/>
</constraints>
</object>
</property>
<child>
<object class="GtkButton" id="button1">
<property name="label">A</property>
</object>
</child>
<child>
<object class="GtkButton" id="button2">
<property name="label">B</property>
</object>
</child>
<child>
<object class="GtkButton" id="button3">
<property name="label">C</property>
</object>
</child>
<child>
<object class="GtkButton" id="button4">
<property name="label">A</property>
</object>
</child>
<child>
<object class="GtkButton" id="button5">
<property name="label">B</property>
</object>
</child>
<child>
<object class="GtkButton" id="button6">
<property name="label">C</property>
</object>
</child>
<child>
<object class="GtkButton" id="button7">
<property name="label">A</property>
</object>
</child>
<child>
<object class="GtkButton" id="button8">
<property name="label">B</property>
</object>
</child>
<child>
<object class="GtkButton" id="button9">
<property name="label">C</property>
</object>
</child>
<child>
<object class="GtkButton" id="button10">
<property name="label">A</property>
</object>
</child>
<child>
<object class="GtkButton" id="button11">
<property name="label">B</property>
</object>
</child>
<child>
<object class="GtkButton" id="button12">
<property name="label">C</property>
</object>
</child>
<child>
<object class="GtkButton" id="button13">
<property name="label">A</property>
</object>
</child>
<child>
<object class="GtkButton" id="button14">
<property name="label">B</property>
</object>
</child>
<child>
<object class="GtkButton" id="button15">
<property name="label">C</property>
</object>
</child>
</object>
</child>
</object>
</interface>
-237
View File
@@ -1,237 +0,0 @@
/* Constraints/Interactive Constraints
* #Keywords: GtkConstraintLayout
*
* This example shows how constraints can be updated during user interaction.
* The vertical edge between the buttons can be dragged with the mouse.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
G_DECLARE_FINAL_TYPE (InteractiveGrid, interactive_grid, INTERACTIVE, GRID, GtkWidget)
struct _InteractiveGrid
{
GtkWidget parent_instance;
GtkWidget *button1, *button2;
GtkWidget *button3;
GtkConstraintGuide *guide;
GtkConstraint *constraint;
};
G_DEFINE_TYPE (InteractiveGrid, interactive_grid, GTK_TYPE_WIDGET)
static void
interactive_grid_dispose (GObject *object)
{
InteractiveGrid *self = INTERACTIVE_GRID (object);
g_clear_pointer (&self->button1, gtk_widget_unparent);
g_clear_pointer (&self->button2, gtk_widget_unparent);
g_clear_pointer (&self->button3, gtk_widget_unparent);
G_OBJECT_CLASS (interactive_grid_parent_class)->dispose (object);
}
static void
interactive_grid_class_init (InteractiveGridClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = interactive_grid_dispose;
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
}
static void
build_constraints (InteractiveGrid *self,
GtkConstraintLayout *manager)
{
self->guide = g_object_new (GTK_TYPE_CONSTRAINT_GUIDE, NULL);
gtk_constraint_layout_add_guide (manager, self->guide);
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new_constant (GTK_CONSTRAINT_TARGET (self->guide),
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
GTK_CONSTRAINT_RELATION_EQ,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_START,
GTK_CONSTRAINT_RELATION_EQ,
GTK_CONSTRAINT_TARGET (self->button1),
GTK_CONSTRAINT_ATTRIBUTE_START,
1.0,
-8.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button1),
GTK_CONSTRAINT_ATTRIBUTE_END,
GTK_CONSTRAINT_RELATION_EQ,
GTK_CONSTRAINT_TARGET (self->guide),
GTK_CONSTRAINT_ATTRIBUTE_START,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button2),
GTK_CONSTRAINT_ATTRIBUTE_START,
GTK_CONSTRAINT_RELATION_EQ,
GTK_CONSTRAINT_TARGET (self->guide),
GTK_CONSTRAINT_ATTRIBUTE_END,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button2),
GTK_CONSTRAINT_ATTRIBUTE_END,
GTK_CONSTRAINT_RELATION_EQ,
NULL,
GTK_CONSTRAINT_ATTRIBUTE_END,
1.0,
-8.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_START,
GTK_CONSTRAINT_RELATION_EQ,
GTK_CONSTRAINT_TARGET (self->button3),
GTK_CONSTRAINT_ATTRIBUTE_START,
1.0,
-8.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button3),
GTK_CONSTRAINT_ATTRIBUTE_END,
GTK_CONSTRAINT_RELATION_EQ,
GTK_CONSTRAINT_TARGET (self->guide),
GTK_CONSTRAINT_ATTRIBUTE_START,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (NULL,
GTK_CONSTRAINT_ATTRIBUTE_TOP,
GTK_CONSTRAINT_RELATION_EQ,
GTK_CONSTRAINT_TARGET (self->button1),
GTK_CONSTRAINT_ATTRIBUTE_TOP,
1.0,
-8.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button2),
GTK_CONSTRAINT_ATTRIBUTE_TOP,
GTK_CONSTRAINT_RELATION_EQ,
GTK_CONSTRAINT_TARGET (self->button1),
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button3),
GTK_CONSTRAINT_ATTRIBUTE_TOP,
GTK_CONSTRAINT_RELATION_EQ,
GTK_CONSTRAINT_TARGET (self->button2),
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
1.0,
0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_constraint_layout_add_constraint (manager,
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button3),
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
GTK_CONSTRAINT_RELATION_EQ,
NULL,
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
1.0,
-8.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED));
}
static void
drag_cb (GtkGestureDrag *drag,
double offset_x,
double offset_y,
InteractiveGrid *self)
{
GtkConstraintLayout *layout = GTK_CONSTRAINT_LAYOUT (gtk_widget_get_layout_manager (GTK_WIDGET (self)));
double x, y;
if (self->constraint)
{
gtk_constraint_layout_remove_constraint (layout, self->constraint);
g_clear_object (&self->constraint);
}
gtk_gesture_drag_get_start_point (drag, &x, &y);
self->constraint = gtk_constraint_new_constant (GTK_CONSTRAINT_TARGET (self->guide),
GTK_CONSTRAINT_ATTRIBUTE_LEFT,
GTK_CONSTRAINT_RELATION_EQ,
x + offset_x,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
gtk_constraint_layout_add_constraint (layout, g_object_ref (self->constraint));
gtk_widget_queue_allocate (GTK_WIDGET (self));
}
static void
interactive_grid_init (InteractiveGrid *self)
{
GtkWidget *widget = GTK_WIDGET (self);
GtkGesture *drag;
self->button1 = gtk_button_new_with_label ("Child 1");
gtk_widget_set_parent (self->button1, widget);
gtk_widget_set_name (self->button1, "button1");
self->button2 = gtk_button_new_with_label ("Child 2");
gtk_widget_set_parent (self->button2, widget);
gtk_widget_set_name (self->button2, "button2");
self->button3 = gtk_button_new_with_label ("Child 3");
gtk_widget_set_parent (self->button3, widget);
gtk_widget_set_name (self->button3, "button3");
GtkLayoutManager *manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
build_constraints (self, GTK_CONSTRAINT_LAYOUT (manager));
drag = gtk_gesture_drag_new ();
g_signal_connect (drag, "drag-update", G_CALLBACK (drag_cb), self);
gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (drag));
}
GtkWidget *
do_constraints_interactive (GtkWidget *do_widget)
{
static GtkWidget *window;
if (!window)
{
GtkWidget *box, *grid;
window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Interactive Constraints");
gtk_window_set_default_size (GTK_WINDOW (window), 260, -1);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
gtk_window_set_child (GTK_WINDOW (window), box);
grid = g_object_new (interactive_grid_get_type (), NULL);
gtk_widget_set_hexpand (grid, TRUE);
gtk_widget_set_vexpand (grid, TRUE);
gtk_box_append (GTK_BOX (box), grid);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}
-160
View File
@@ -1,160 +0,0 @@
/* Constraints/VFL
*
* GtkConstraintLayout allows defining constraints using a
* compact syntax called Visual Format Language, or VFL.
*
* A typical example of a VFL specification looks like this:
*
* H:|-[button1(==button2)]-12-[button2]-|
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
G_DECLARE_FINAL_TYPE (VflGrid, vfl_grid, VFL, GRID, GtkWidget)
struct _VflGrid
{
GtkWidget parent_instance;
GtkWidget *button1, *button2;
GtkWidget *button3;
};
G_DEFINE_TYPE (VflGrid, vfl_grid, GTK_TYPE_WIDGET)
static void
vfl_grid_dispose (GObject *object)
{
VflGrid *self = VFL_GRID (object);
g_clear_pointer (&self->button1, gtk_widget_unparent);
g_clear_pointer (&self->button2, gtk_widget_unparent);
g_clear_pointer (&self->button3, gtk_widget_unparent);
G_OBJECT_CLASS (vfl_grid_parent_class)->dispose (object);
}
static void
vfl_grid_class_init (VflGridClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = vfl_grid_dispose;
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
}
/* Layout:
*
* +-----------------------------+
* | +-----------+ +-----------+ |
* | | Child 1 | | Child 2 | |
* | +-----------+ +-----------+ |
* | +-------------------------+ |
* | | Child 3 | |
* | +-------------------------+ |
* +-----------------------------+
*
* Constraints:
*
* super.start = child1.start - 8
* child1.width = child2.width
* child1.end = child2.start - 12
* child2.end = super.end - 8
* super.start = child3.start - 8
* child3.end = super.end - 8
* super.top = child1.top - 8
* super.top = child2.top - 8
* child1.bottom = child3.top - 12
* child2.bottom = child3.top - 12
* child3.height = child1.height
* child3.height = child2.height
* child3.bottom = super.bottom - 8
*
* Visual format:
*
* H:|-8-[view1(==view2)-12-[view2]-8-|
* H:|-8-[view3]-8-|
* V:|-8-[view1]-12-[view3(==view1)]-8-|
* V:|-8-[view2]-12-[view3(==view2)]-8-|
*/
static void
build_constraints (VflGrid *self,
GtkConstraintLayout *manager)
{
const char * const vfl[] = {
"H:|-[button1(==button2)]-12-[button2]-|",
"H:|-[button3]-|",
"V:|-[button1]-12-[button3(==button1)]-|",
"V:|-[button2]-12-[button3(==button2)]-|",
};
GError *error = NULL;
gtk_constraint_layout_add_constraints_from_description (manager, vfl, G_N_ELEMENTS (vfl),
8, 8,
&error,
"button1", self->button1,
"button2", self->button2,
"button3", self->button3,
NULL);
if (error != NULL)
{
g_printerr ("VFL parsing error:\n%s", error->message);
g_error_free (error);
}
}
static void
vfl_grid_init (VflGrid *self)
{
GtkWidget *widget = GTK_WIDGET (self);
self->button1 = gtk_button_new_with_label ("Child 1");
gtk_widget_set_parent (self->button1, widget);
gtk_widget_set_name (self->button1, "button1");
self->button2 = gtk_button_new_with_label ("Child 2");
gtk_widget_set_parent (self->button2, widget);
gtk_widget_set_name (self->button2, "button2");
self->button3 = gtk_button_new_with_label ("Child 3");
gtk_widget_set_parent (self->button3, widget);
gtk_widget_set_name (self->button3, "button3");
GtkLayoutManager *manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
build_constraints (self, GTK_CONSTRAINT_LAYOUT (manager));
}
GtkWidget *
do_constraints_vfl (GtkWidget *do_widget)
{
static GtkWidget *window;
if (!window)
{
GtkWidget *box, *grid;
window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Constraints — VFL");
gtk_window_set_default_size (GTK_WINDOW (window), 260, -1);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
gtk_window_set_child (GTK_WINDOW (window), box);
grid = g_object_new (vfl_grid_get_type (), NULL);
gtk_widget_set_hexpand (grid, TRUE);
gtk_widget_set_vexpand (grid, TRUE);
gtk_box_append (GTK_BOX (box), grid);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}
-27
View File
@@ -1,27 +0,0 @@
uniform float progress;
uniform sampler2D u_texture1;
uniform sampler2D u_texture2;
vec4 getFromColor (vec2 uv) {
return GskTexture(u_texture1, uv);
}
vec4 getToColor (vec2 uv) {
return GskTexture(u_texture2, uv);
}
// Source: https://gl-transitions.com/editor/crosswarp
// Author: Eke Péter <peterekepeter@gmail.com>
// License: MIT
vec4 transition(vec2 p) {
float x = progress;
x=smoothstep(.0,1.0,(x*2.0+p.x-1.0));
return mix(getFromColor((p-.5)*(1.-x)+.5), getToColor((p-.5)*x+.5), x);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv)
{
fragColor = transition(uv);
}
+14 -16
View File
@@ -1,6 +1,7 @@
/* Theming/CSS Accordion
*
* A simple accordion demo written using CSS transitions and multiple backgrounds
*
*/
#include <gtk/gtk.h>
@@ -8,13 +9,9 @@
static void
apply_css (GtkWidget *widget, GtkStyleProvider *provider)
{
GtkWidget *child;
gtk_style_context_add_provider (gtk_widget_get_style_context (widget), provider, G_MAXUINT);
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
apply_css (child, provider);
if (GTK_IS_CONTAINER (widget))
gtk_container_forall (GTK_CONTAINER (widget), (GtkCallback) apply_css, provider);
}
GtkWidget *
@@ -27,34 +24,35 @@ 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);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
container = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_set_halign (container, GTK_ALIGN_CENTER);
gtk_widget_set_valign (container, GTK_ALIGN_CENTER);
gtk_window_set_child (GTK_WINDOW (window), container);
gtk_container_add (GTK_CONTAINER (window), container);
child = gtk_button_new_with_label ("This");
gtk_box_append (GTK_BOX (container), child);
gtk_container_add (GTK_CONTAINER (container), child);
child = gtk_button_new_with_label ("Is");
gtk_box_append (GTK_BOX (container), child);
gtk_container_add (GTK_CONTAINER (container), child);
child = gtk_button_new_with_label ("A");
gtk_box_append (GTK_BOX (container), child);
gtk_container_add (GTK_CONTAINER (container), child);
child = gtk_button_new_with_label ("CSS");
gtk_box_append (GTK_BOX (container), child);
gtk_container_add (GTK_CONTAINER (container), child);
child = gtk_button_new_with_label ("Accordion");
gtk_box_append (GTK_BOX (container), child);
gtk_container_add (GTK_CONTAINER (container), child);
child = gtk_button_new_with_label (":-)");
gtk_box_append (GTK_BOX (container), child);
gtk_container_add (GTK_CONTAINER (container), child);
provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
gtk_css_provider_load_from_resource (GTK_CSS_PROVIDER (provider), "/css_accordion/css_accordion.css");
@@ -65,7 +63,7 @@ do_css_accordion (GtkWidget *do_widget)
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
return window;
}
+11 -13
View File
@@ -1,7 +1,8 @@
/* Theming/CSS Basics
*
* GTK themes are written using CSS. Every widget is build of multiple items
* Gtk themes are written using CSS. Every widget is build of multiple items
* that you can style very similarly to a regular website.
*
*/
#include <gtk/gtk.h>
@@ -54,13 +55,9 @@ css_text_changed (GtkTextBuffer *buffer,
static void
apply_css (GtkWidget *widget, GtkStyleProvider *provider)
{
GtkWidget *child;
gtk_style_context_add_provider (gtk_widget_get_style_context (widget), provider, G_MAXUINT);
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
apply_css (child, provider);
if (GTK_IS_CONTAINER (widget))
gtk_container_forall (GTK_CONTAINER (widget), (GtkCallback) apply_css, provider);
}
GtkWidget *
@@ -75,11 +72,12 @@ 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);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
text = gtk_text_buffer_new (NULL);
gtk_text_buffer_create_tag (text,
@@ -93,10 +91,10 @@ do_css_basics (GtkWidget *do_widget)
provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
container = gtk_scrolled_window_new ();
gtk_window_set_child (GTK_WINDOW (window), container);
container = gtk_scrolled_window_new (NULL, NULL);
gtk_container_add (GTK_CONTAINER (window), container);
child = gtk_text_view_new_with_buffer (text);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (container), child);
gtk_container_add (GTK_CONTAINER (container), child);
g_signal_connect (text, "changed",
G_CALLBACK (css_text_changed), provider);
@@ -115,7 +113,7 @@ do_css_basics (GtkWidget *do_widget)
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
return window;
}
-4
View File
@@ -15,10 +15,6 @@
border: 1px solid;
}
window {
background-color: white;
}
/* Make sure selections are visible */
selection {
background-color: darkGreen;
+13 -14
View File
@@ -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" },
@@ -38,14 +38,14 @@ struct {
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
static void
update_css_for_blend_mode (GtkCssProvider *provider,
const char *blend_mode)
const gchar *blend_mode)
{
GBytes *bytes;
char *css;
gchar *css;
bytes = g_resources_lookup_data ("/css_blendmodes/css_blendmodes.css", 0, NULL);
css = g_strdup_printf ((char *) g_bytes_get_data (bytes, NULL),
css = g_strdup_printf ((gchar*) g_bytes_get_data (bytes, NULL),
blend_mode,
blend_mode,
blend_mode);
@@ -62,7 +62,7 @@ row_activated (GtkListBox *listbox,
GtkListBoxRow *row,
GtkCssProvider *provider)
{
const char *blend_mode;
const gchar *blend_mode;
blend_mode = blend_modes[gtk_list_box_row_get_index (row)].id;
@@ -75,11 +75,11 @@ setup_listbox (GtkBuilder *builder,
{
GtkWidget *normal_row;
GtkWidget *listbox;
int i;
gint i;
normal_row = NULL;
listbox = gtk_list_box_new ();
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (WID ("scrolledwindow")), listbox);
gtk_container_add (GTK_CONTAINER (WID ("scrolledwindow")), listbox);
g_signal_connect (listbox, "row-activated", G_CALLBACK (row_activated), provider);
@@ -95,8 +95,9 @@ setup_listbox (GtkBuilder *builder,
"xalign", 0.0,
NULL);
gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), label);
gtk_list_box_insert (GTK_LIST_BOX (listbox), row, -1);
gtk_container_add (GTK_CONTAINER (row), label);
gtk_container_add (GTK_CONTAINER (listbox), row);
/* The first selected row is "normal" */
if (g_strcmp0 (blend_modes[i].id, "normal") == 0)
@@ -124,7 +125,7 @@ do_css_blendmodes (GtkWidget *do_widget)
window = WID ("window");
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (do_widget));
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
g_signal_connect (window, "destroy", G_CALLBACK (gtk_widget_destroyed), &window);
/* Setup the CSS provider for window */
provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
@@ -134,14 +135,12 @@ do_css_blendmodes (GtkWidget *do_widget)
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
setup_listbox (builder, provider);
g_object_unref (builder);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
return window;
}
+18 -20
View File
@@ -1,7 +1,8 @@
/* Theming/Multiple Backgrounds
*
* GTK themes are written using CSS. Every widget is build of multiple items
* Gtk themes are written using CSS. Every widget is build of multiple items
* that you can style very similarly to a regular website.
*
*/
#include <gtk/gtk.h>
@@ -68,13 +69,9 @@ drawing_area_draw (GtkDrawingArea *da,
static void
apply_css (GtkWidget *widget, GtkStyleProvider *provider)
{
GtkWidget *child;
gtk_style_context_add_provider (gtk_widget_get_style_context (widget), provider, G_MAXUINT);
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
apply_css (child, provider);
if (GTK_IS_CONTAINER (widget))
gtk_container_forall (GTK_CONTAINER (widget), (GtkCallback) apply_css, provider);
}
GtkWidget *
@@ -84,40 +81,41 @@ do_css_multiplebgs (GtkWidget *do_widget)
if (!window)
{
GtkWidget *paned, *overlay, *child, *sw;
GtkWidget *paned, *container, *child;
GtkStyleProvider *provider;
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);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
overlay = gtk_overlay_new ();
gtk_window_set_child (GTK_WINDOW (window), overlay);
container = gtk_overlay_new ();
gtk_container_add (GTK_CONTAINER (window), container);
child = gtk_drawing_area_new ();
gtk_widget_set_name (child, "canvas");
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (child),
drawing_area_draw,
NULL, NULL);
gtk_overlay_set_child (GTK_OVERLAY (overlay), child);
gtk_container_add (GTK_CONTAINER (container), child);
child = gtk_button_new ();
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), child);
gtk_overlay_add_overlay (GTK_OVERLAY (container), child);
gtk_widget_set_name (child, "bricks-button");
gtk_widget_set_halign (child, GTK_ALIGN_CENTER);
gtk_widget_set_valign (child, GTK_ALIGN_CENTER);
gtk_widget_set_size_request (child, 250, 84);
paned = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), paned);
gtk_overlay_add_overlay (GTK_OVERLAY (container), paned);
/* Need a filler so we get a handle */
child = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_paned_set_start_child (GTK_PANED (paned), child);
gtk_container_add (GTK_CONTAINER (paned), child);
text = gtk_text_buffer_new (NULL);
gtk_text_buffer_create_tag (text,
@@ -131,10 +129,10 @@ do_css_multiplebgs (GtkWidget *do_widget)
provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
sw = gtk_scrolled_window_new ();
gtk_paned_set_end_child (GTK_PANED (paned), sw);
container = gtk_scrolled_window_new (NULL, NULL);
gtk_container_add (GTK_CONTAINER (paned), container);
child = gtk_text_view_new_with_buffer (text);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), child);
gtk_container_add (GTK_CONTAINER (container), child);
g_signal_connect (text,
"changed",
G_CALLBACK (css_text_changed),
@@ -155,7 +153,7 @@ do_css_multiplebgs (GtkWidget *do_widget)
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
return window;
}
+12 -16
View File
@@ -1,7 +1,6 @@
/* Theming/Animated Backgrounds
*
* This demo is in honour of a classic Pixbufs demo.
*
* This demo is done in honour of the Pixbufs demo further down.
* It is done exclusively with CSS as the background of the window.
*/
@@ -56,13 +55,9 @@ css_text_changed (GtkTextBuffer *buffer,
static void
apply_css (GtkWidget *widget, GtkStyleProvider *provider)
{
GtkWidget *child;
gtk_style_context_add_provider (gtk_widget_get_style_context (widget), provider, G_MAXUINT);
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
apply_css (child, provider);
if (GTK_IS_CONTAINER (widget))
gtk_container_forall (GTK_CONTAINER (widget), (GtkCallback) apply_css, provider);
}
GtkWidget *
@@ -77,18 +72,19 @@ 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);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
paned = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
gtk_window_set_child (GTK_WINDOW (window), paned);
gtk_container_add (GTK_CONTAINER (window), paned);
/* Need a filler so we get a handle */
child = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_paned_set_start_child (GTK_PANED (paned), child);
gtk_container_add (GTK_CONTAINER (paned), child);
text = gtk_text_buffer_new (NULL);
gtk_text_buffer_create_tag (text,
@@ -102,10 +98,10 @@ do_css_pixbufs (GtkWidget *do_widget)
provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
container = gtk_scrolled_window_new ();
gtk_paned_set_end_child (GTK_PANED (paned), container);
container = gtk_scrolled_window_new (NULL, NULL);
gtk_container_add (GTK_CONTAINER (paned), container);
child = gtk_text_view_new_with_buffer (text);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (container), child);
gtk_container_add (GTK_CONTAINER (container), child);
g_signal_connect (text, "changed",
G_CALLBACK (css_text_changed), provider);
@@ -124,7 +120,7 @@ do_css_pixbufs (GtkWidget *do_widget)
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
return window;
}
+10 -10
View File
@@ -46,19 +46,19 @@
}
@keyframes size-the-image {
0% { background-size: 96px, 12px, 96px, 12px, 96px, 12px, 96px, 12px, auto; }
100% { background-size: 12px, 96px, 12px, 96px, 12px, 96px, 12px, 96px, auto; }
0% { background-size: 96px, 12px, 96px, 12px, 96px, 12px, 96px, 12px, auto }
100% { background-size: 12px, 96px, 12px, 96px, 12px, 96px, 12px, 96px, auto }
}
window {
background-image: url("resource://css_pixbufs/images/apple-red.png"),
url("resource://css_pixbufs/images/gnome-applets.png"),
url("resource://css_pixbufs/images/gnome-calendar.png"),
url("resource://css_pixbufs/images/gnome-foot.png"),
url("resource://css_pixbufs/images/gnome-gmush.png"),
url("resource://css_pixbufs/images/gnome-gimp.png"),
url("resource://css_pixbufs/images/gnome-gsame.png"),
url("resource://css_pixbufs/images/gnu-keys.png"),
background-image: url("resource://css_pixbufs/apple-red.png"),
url("resource://css_pixbufs/gnome-applets.png"),
url("resource://css_pixbufs/gnome-calendar.png"),
url("resource://css_pixbufs/gnome-foot.png"),
url("resource://css_pixbufs/gnome-gmush.png"),
url("resource://css_pixbufs/gnome-gimp.png"),
url("resource://css_pixbufs/gnome-gsame.png"),
url("resource://css_pixbufs/gnu-keys.png"),
url("resource://css_pixbufs/background.jpg");
background-position: 50.00% 75.00%, 67.68% 67.68%, 75.00% 50.00%, 67.68% 32.32%, 50.00% 25.00%, 32.32% 32.32%, 25.00% 50.00%, 32.32% 67.68%, 0% 0%;
background-repeat: no-repeat, no-repeat, no-repeat, no-repeat, no-repeat, no-repeat, no-repeat, no-repeat, repeat;
+23 -24
View File
@@ -53,32 +53,31 @@ css_text_changed (GtkTextBuffer *buffer,
static void
apply_css (GtkWidget *widget, GtkStyleProvider *provider)
{
GtkWidget *child;
gtk_style_context_add_provider (gtk_widget_get_style_context (widget), provider, G_MAXUINT);
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
apply_css (child, provider);
if (GTK_IS_CONTAINER (widget))
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_box_append (GTK_BOX (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_box_append (GTK_BOX (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_box_append (GTK_BOX (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;
}
@@ -95,18 +94,18 @@ 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);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
paned = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
gtk_window_set_child (GTK_WINDOW (window), paned);
gtk_container_add (GTK_CONTAINER (window), paned);
child = create_toolbar ();
gtk_paned_set_start_child (GTK_PANED (paned), child);
gtk_paned_set_resize_start_child (GTK_PANED (paned), FALSE);
gtk_container_add (GTK_CONTAINER (paned), child);
text = gtk_text_buffer_new (NULL);
gtk_text_buffer_create_tag (text,
@@ -120,10 +119,10 @@ do_css_shadows (GtkWidget *do_widget)
provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
container = gtk_scrolled_window_new ();
gtk_paned_set_end_child (GTK_PANED (paned), container);
container = gtk_scrolled_window_new (NULL, NULL);
gtk_container_add (GTK_CONTAINER (paned), container);
child = gtk_text_view_new_with_buffer (text);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (container), child);
gtk_container_add (GTK_CONTAINER (container), child);
g_signal_connect (text, "changed",
G_CALLBACK (css_text_changed), provider);
@@ -142,7 +141,7 @@ do_css_shadows (GtkWidget *do_widget)
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
return window;
}
+7 -5
View File
@@ -1,8 +1,9 @@
/* Cursors
*
* Demonstrates a useful set of available cursors. The cursors shown here are the
* ones defined by CSS, which we assume to be available. The example shows creating
* cursors by name or from an image, with or without a fallback.
* Demonstrates a useful set of available cursors. The cursors shown here are the ones
* defined by CSS, which we assume to be available.
*
* The example shows creating cursors by name or from an image, with or without a fallback.
*/
#include <gtk/gtk.h>
@@ -23,19 +24,20 @@ do_cursors (GtkWidget *do_widget)
GtkBuilder *builder;
builder = gtk_builder_new_from_resource ("/cursors/cursors.ui");
gtk_builder_connect_signals (builder, NULL);
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 (on_destroy), NULL);
g_object_unref (builder);
g_object_set_data_full (G_OBJECT (window), "builder", builder, g_object_unref);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
{
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
}
return window;
+145 -256
View File
File diff suppressed because it is too large Load Diff
+28 -155
View File
@@ -1,10 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/">
</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">
<file>application.c</file>
@@ -14,13 +12,6 @@
<gresource prefix="/builder">
<file>demo.ui</file>
</gresource>
<gresource prefix="/clipboard">
<file>demoimage.c</file>
<file>demoimage.h</file>
</gresource>
<gresource prefix="/constraints_builder">
<file>constraints_builder.ui</file>
</gresource>
<gresource prefix="/css_accordion">
<file>css_accordion.css</file>
<file>reset.css</file>
@@ -43,11 +34,6 @@
<file>cssview.css</file>
<file>reset.css</file>
</gresource>
<gresource prefix="/dropdown">
<file>suggestionentry.h</file>
<file>suggestionentry.c</file>
<file>suggestionentry.css</file>
</gresource>
<gresource prefix="/theming_style_classes">
<file>theming.ui</file>
</gresource>
@@ -59,8 +45,6 @@
<file>cssview.css</file>
<file>reset.css</file>
<file>background.jpg</file>
</gresource>
<gresource prefix="/css_pixbufs/images">
<file>apple-red.png</file>
<file>gnome-applets.png</file>
<file>gnome-calendar.png</file>
@@ -77,8 +61,6 @@
</gresource>
<gresource prefix="/cursors">
<file>cursors.ui</file>
</gresource>
<gresource prefix="/cursors/images">
<file>alias_cursor.png</file>
<file>all_scroll_cursor.png</file>
<file>cell_cursor.png</file>
@@ -117,106 +99,15 @@
<file>zoom_in_cursor.png</file>
<file>zoom_out_cursor.png</file>
</gresource>
<gresource prefix="/dnd">
<file>dnd.css</file>
</gresource>
<gresource prefix="/errorstates">
<file>errorstates.ui</file>
</gresource>
<gresource prefix="/fishbowl">
<file>fishbowl.ui</file>
<file>gtkfishbowl.c</file>
<file>gtkfishbowl.h</file>
</gresource>
<gresource prefix="/gears">
<file>gtkgears.c</file>
<file>gtkgears.h</file>
</gresource>
<gresource prefix="/shadertoy">
<file>gtkshadertoy.c</file>
<file>gtkshadertoy.h</file>
<file>alienplanet.glsl</file>
<file>mandelbrot.glsl</file>
<file>neon.glsl</file>
<file>cogs.glsl</file>
<file>glowingstars.glsl</file>
</gresource>
<gresource prefix="/gltransition">
<file>gtkshaderstack.c</file>
<file>gtkshaderstack.h</file>
<file>gtkshaderbin.h</file>
<file>gtkshaderbin.c</file>
<file>gskshaderpaintable.h</file>
<file>gskshaderpaintable.c</file>
<file>wind.glsl</file>
<file>radial.glsl</file>
<file>crosswarp.glsl</file>
<file>kaleidoscope.glsl</file>
<file>cogs2.glsl</file>
<file>ripple.glsl</file>
<file>background.glsl</file>
</gresource>
<gresource prefix="/iconscroll">
<file>iconscroll.ui</file>
</gresource>
<gresource prefix="/iconview">
<file>gnome-fs-directory.png</file>
<file>gnome-fs-regular.png</file>
</gresource>
<gresource prefix="/layoutmanager">
<file>demolayout.h</file>
<file>demolayout.c</file>
<file>demowidget.h</file>
<file>demowidget.c</file>
<file>demochild.h</file>
<file>demochild.c</file>
</gresource>
<gresource prefix="/layoutmanager2">
<file>demo2layout.h</file>
<file>demo2layout.c</file>
<file>demo2widget.h</file>
<file>demo2widget.c</file>
<file>four_point_transform.h</file>
<file>four_point_transform.c</file>
<file>singular_value_decomposition.h</file>
<file>singular_value_decomposition.c</file>
</gresource>
<gresource prefix="/listview_filebrowser">
<file>listview_filebrowser.ui</file>
<file>listview_filebrowser.css</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_ucd_data/">
<file>ucdnames.data</file>
</gresource>
<gresource prefix="/listview_weather">
<file compressed="true">listview_weather.txt</file>
</gresource>
<gresource prefix="/listview_colors">
<file compressed="true">color.names.txt</file>
<file>listview_colors.css</file>
</gresource>
<gresource prefix="/main">
<file>fontify.c</file>
<file>fontify.h</file>
<file>main.ui</file>
</gresource>
<gresource prefix="/menu">
<file>demo3widget.c</file>
<file>demo3widget.h</file>
<file>demo3widget.ui</file>
</gresource>
<gresource prefix="/paintable_svg">
<file>svgpaintable.h</file>
<file>svgpaintable.c</file>
<file>org.gtk.gtk4.NodeEditor.Devel.svg</file>
</gresource>
<gresource prefix="/shortcuts">
<file>shortcuts.ui</file>
<file>shortcuts-builder.ui</file>
@@ -236,26 +127,29 @@
<file>revealer.ui</file>
</gresource>
<gresource prefix="/images">
<file>pixbufpaintable.h</file>
<file>pixbufpaintable.c</file>
<file>alphatest.png</file>
<file>floppybuddy.gif</file>
<file>gtk-logo.webm</file>
<file alias="org.gtk.Demo4.svg">data/scalable/apps/org.gtk.Demo4.svg</file>
</gresource>
<gresource prefix="/video-player">
<file>bbb.png</file>
<gresource prefix="/pixbufs">
<file>apple-red.png</file>
<file>background.jpg</file>
<file>gnome-applets.png</file>
<file>gnome-calendar.png</file>
<file>gnome-foot.png</file>
<file>gnome-gmush.png</file>
<file>gnome-gimp.png</file>
<file>gnome-gsame.png</file>
<file>gnu-keys.png</file>
</gresource>
<gresource prefix="/sources">
<file>application_demo.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>
<file>constraints.c</file>
<file>constraints_interactive.c</file>
<file>constraints_vfl.c</file>
<file>constraints_builder.c</file>
<file>css_accordion.c</file>
<file>css_basics.c</file>
<file>css_blendmodes.c</file>
@@ -265,69 +159,50 @@
<file>cursors.c</file>
<file>dialog.c</file>
<file>drawingarea.c</file>
<file>dropdown.c</file>
<file>dnd.c</file>
<file>editable_cells.c</file>
<file>entry_buffer.c</file>
<file>entry_completion.c</file>
<file>entry_undo.c</file>
<file>errorstates.c</file>
<file>expander.c</file>
<file>filtermodel.c</file>
<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>
<file>gears.c</file>
<file>gestures.c</file>
<file>glarea.c</file>
<file>gltransition.c</file>
<file>headerbar.c</file>
<file>hypertext.c</file>
<file>iconscroll.c</file>
<file>iconview.c</file>
<file>iconview_edit.c</file>
<file>images.c</file>
<file>infobar.c</file>
<file>layoutmanager.c</file>
<file>layoutmanager2.c</file>
<file>links.c</file>
<file>listbox.c</file>
<file>listbox_controls.c</file>
<file>listview_applauncher.c</file>
<file>listview_colors.c</file>
<file>listview_clocks.c</file>
<file>listview_filebrowser.c</file>
<file>listview_minesweeper.c</file>
<file>listview_settings.c</file>
<file>listview_ucd.c</file>
<file>listview_weather.c</file>
<file>listview_words.c</file>
<file>list_store.c</file>
<file>main.c</file>
<file>markup.c</file>
<file>menu.c</file>
<file>menus.c</file>
<file>modelbutton.c</file>
<file>overlay.c</file>
<file>overlay_decorative.c</file>
<file>overlay2.c</file>
<file>paint.c</file>
<file>pagesetup.c</file>
<file>paintable.c</file>
<file>paintable_animated.c</file>
<file>paintable_emblem.c</file>
<file>paintable_mediastream.c</file>
<file>paintable_svg.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>
<file>printing.c</file>
<file>revealer.c</file>
<file>rotated_text.c</file>
<file>scale.c</file>
<file>search_entry.c</file>
<file>search_entry2.c</file>
<file>shadertoy.c</file>
<file>shortcuts.c</file>
<file>shortcut_triggers.c</file>
<file>sizegroup.c</file>
@@ -338,7 +213,6 @@
<file>spinner.c</file>
<file>tabs.c</file>
<file>tagged_entry.c</file>
<file>textundo.c</file>
<file>textview.c</file>
<file>textscroll.c</file>
<file>theming_style_classes.c</file>
@@ -359,8 +233,8 @@
<file>messages.txt</file>
<file>apple-red.png</file>
</gresource>
<gresource prefix="/listbox_controls">
<file>listbox_controls.ui</file>
<gresource prefix="/popover">
<file>popover.ui</file>
</gresource>
<gresource prefix="/glarea">
<file>glarea-gl.fs.glsl</file>
@@ -384,7 +258,6 @@
</gresource>
<gresource prefix="/transparent">
<file>portland-rose.jpg</file>
<file>bluroverlay.h</file>
<file>bluroverlay.c</file>
</gresource>
<gresource prefix="/markup">
@@ -393,6 +266,12 @@
<gresource prefix="/scale">
<file>scale.ui</file>
</gresource>
<gresource prefix="/modelbutton">
<file>modelbutton.ui</file>
</gresource>
<gresource prefix="/dnd">
<file>dnd.css</file>
</gresource>
<gresource prefix="/tagged_entry">
<file>demotaggedentry.c</file>
<file>demotaggedentry.h</file>
@@ -400,9 +279,6 @@
<gresource prefix="/fixed">
<file>fixed.css</file>
</gresource>
<gresource prefix="/fontrendering">
<file>fontrendering.ui</file>
</gresource>
<gresource prefix="/org/gtk/Demo4">
<file>icons/16x16/actions/application-exit.png</file>
<file>icons/16x16/actions/document-new.png</file>
@@ -422,7 +298,4 @@
<file>icons/16x16/status/battery-caution-charging-symbolic.symbolic.png</file>
<file>icons/16x16/categories/applications-other.png</file>
</gresource>
<gresource prefix="/org/gtk/Demo4/gtk">
<file preprocess="xml-stripblanks">help-overlay.ui</file>
</gresource>
</gresources>
+205 -90
View File
@@ -22,154 +22,269 @@
</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>
</item>
<item>
<attribute name="label" translatable="yes">_Open</attribute>
<attribute name="action">win.open</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Save</attribute>
<attribute name="action">win.save</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Save _As</attribute>
<attribute name="action">win.save-as</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">_Quit</attribute>
<attribute name="action">win.quit</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>
</item>
<item>
<attribute name="label" translatable="yes">_Cut</attribute>
<attribute name="action">win.cut</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Paste</attribute>
<attribute name="action">win.paste</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>
</item>
<item>
<attribute name="label" translatable="yes">_About</attribute>
<attribute name="action">win.about</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">org.gtk.Demo4</property>
<property name="modal">True</property>
<property name="logo-icon-name" translatable="yes">gtk3-demo</property>
<accessibility>
<relation target="window1" type="subwindow-of"/>
</accessibility>
</object>
<object class="GtkWindow" id="window1">
<property name="default-height">250</property>
<property name="default-width">440</property>
<property name="title" translatable="yes">Builder</property>
<child>
<object class="GtkBox" id="vbox1">
<property name="orientation">vertical</property>
<object class="GtkShortcutController" id="controller1">
<property name="scope">global</property>
<property name="propagation-phase">capture</property>
<child>
<object class="GtkPopoverMenuBar" id="menubar1">
<property name="menu-model">menubar</property>
<accessibility>
<property name="label">Main Menu</property>
</accessibility>
<object class="GtkShortcut">
<property name="trigger">&lt;Primary&gt;n</property>
<property name="action">action(menu.new)</property>
</object>
</child>
<child>
<object class="GtkBox" id="toolbar1">
<property name="accessible-role">toolbar</property>
<property name="css-classes">toolbar</property>
<accessibility>
<property name="label">Toolbar</property>
</accessibility>
<object class="GtkShortcut">
<property name="trigger">&lt;Primary&gt;o</property>
<property name="action">action(menu.open)</property>
</object>
</child>
<child>
<object class="GtkShortcut">
<property name="trigger">&lt;Primary&gt;s</property>
<property name="action">action(menu.save)</property>
</object>
</child>
<child>
<object class="GtkShortcut">
<property name="trigger">&lt;Primary&gt;&lt;Shift&gt;s</property>
<property name="action">action(menu.save_as)</property>
</object>
</child>
<child>
<object class="GtkShortcut">
<property name="trigger">&lt;Primary&gt;q</property>
<property name="action">action(win.quit)</property>
</object>
</child>
<child>
<object class="GtkShortcut">
<property name="trigger">&lt;Primary&gt;c</property>
<property name="action">action(menu.copy)</property>
</object>
</child>
<child>
<object class="GtkShortcut">
<property name="trigger">&lt;Primary&gt;x</property>
<property name="action">action(menu.cut)</property>
</object>
</child>
<child>
<object class="GtkShortcut">
<property name="trigger">&lt;Primary&gt;v</property>
<property name="action">action(menu.paste)</property>
</object>
</child>
<child>
<object class="GtkShortcut">
<property name="trigger">F1</property>
<property name="action">action(win.help)</property>
</object>
</child>
<child>
<object class="GtkShortcut">
<property name="trigger">F7</property>
<property name="action">action(win.about)</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="vbox1">
<property name="orientation">vertical</property>
<child>
<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="GtkButton">
<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>
<property name="action-name">menu.new</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="open_item">
<property name="label" translatable="yes">_Open</property>
<property name="use-underline">1</property>
<property name="action-name">menu.open</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="save_item">
<property name="label" translatable="yes">_Save</property>
<property name="use-underline">1</property>
<property name="action-name">menu.save</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>
<property name="action-name">menu.save_as</property>
</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>
<property name="action-name">menu.copy</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="cut_item">
<property name="label" translatable="yes">_Cut</property>
<property name="use-underline">1</property>
<property name="action-name">menu.cut</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="paste_item">
<property name="label" translatable="yes">_Paste</property>
<property name="use-underline">1</property>
<property name="action-name">menu.paste</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="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="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>
<property name="action-name">win.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>
<property name="action-name">win.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="action-name">win.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>
<property name="action-name">win.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>
<property name="action-name">win.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>
<property name="action-name">win.paste</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="has-frame">1</property>
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<property name="shadow-type">in</property>
<property name="expand">1</property>
<child>
<object class="GtkTreeView" id="treeview1">
<property name="model">liststore1</property>
<property name="tooltip-column">3</property>
<child internal-child="accessible">
<object class="AtkObject" id="a11y-treeview">
<property name="AtkObject::accessible-name">Name list</property>
<property name="AtkObject::accessible-description">
A list of person with name, surname and age columns
</property>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="column1">
<property name="title">Name</property>
-204
View File
@@ -1,204 +0,0 @@
#include "demo2layout.h"
#include "four_point_transform.h"
struct _Demo2Layout
{
GtkLayoutManager parent_instance;
float position;
float offset;
};
struct _Demo2LayoutClass
{
GtkLayoutManagerClass parent_class;
};
G_DEFINE_TYPE (Demo2Layout, demo2_layout, GTK_TYPE_LAYOUT_MANAGER)
static void
demo2_layout_measure (GtkLayoutManager *layout_manager,
GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
GtkWidget *child;
int minimum_size = 0;
int natural_size = 0;
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
{
int child_min = 0, child_nat = 0;
if (!gtk_widget_should_layout (child))
continue;
gtk_widget_measure (child, orientation, -1,
&child_min, &child_nat,
NULL, NULL);
minimum_size = MAX (minimum_size, child_min);
natural_size = MAX (natural_size, child_nat);
}
*minimum = minimum_size;
*natural = 3 * natural_size;
}
#define RADIANS(angle) ((angle)*M_PI/180.0);
/* Spherical coordinates */
#define SX(r,t,p) ((r) * sin (t) * cos (p))
#define SZ(r,t,p) ((r) * sin (t) * sin (p))
#define SY(r,t,p) ((r) * cos (t))
static double
map_offset (double x)
{
x = fmod (x, 180.0);
if (x < 0.0)
x += 180.0;
return x;
}
static void
demo2_layout_allocate (GtkLayoutManager *layout_manager,
GtkWidget *widget,
int width,
int height,
int baseline)
{
GtkWidget *child;
GtkRequisition child_req;
int i, j, k;
float x0, y0;
float w, h;
graphene_point3d_t p1, p2, p3, p4;
graphene_point3d_t q1, q2, q3, q4;
double t_1, t_2, p_1, p_2;
double r;
graphene_matrix_t m;
GskTransform *transform;
double position = DEMO2_LAYOUT (layout_manager)->position;
double offset = DEMO2_LAYOUT (layout_manager)->offset;
/* for simplicity, assume all children are the same size */
gtk_widget_get_preferred_size (gtk_widget_get_first_child (widget), &child_req, NULL);
w = child_req.width;
h = child_req.height;
r = 300;
x0 = y0 = 300;
for (child = gtk_widget_get_first_child (widget), i = 0;
child != NULL;
child = gtk_widget_get_next_sibling (child), i++)
{
j = i / 36;
k = i % 36;
gtk_widget_set_child_visible (child, FALSE);
graphene_point3d_init (&p1, w, h, 1.);
graphene_point3d_init (&p2, w, 0., 1.);
graphene_point3d_init (&p3, 0., 0., 1.);
graphene_point3d_init (&p4, 0., h, 1.);
t_1 = RADIANS (map_offset (offset + 10 * j));
t_2 = RADIANS (map_offset (offset + 10 * (j + 1)));
p_1 = RADIANS (position + 10 * k);
p_2 = RADIANS (position + 10 * (k + 1));
if (t_2 < t_1)
continue;
if (SZ (r, t_1, p_1) > 0 ||
SZ (r, t_2, p_1) > 0 ||
SZ (r, t_1, p_2) > 0 ||
SZ (r, t_2, p_2) > 0)
continue;
gtk_widget_set_child_visible (child, TRUE);
graphene_point3d_init (&q1, x0 + SX (r, t_1, p_1), y0 + SY (r, t_1, p_1), SZ (r, t_1, p_1));
graphene_point3d_init (&q2, x0 + SX (r, t_2, p_1), y0 + SY (r, t_2, p_1), SZ (r, t_2, p_1));
graphene_point3d_init (&q3, x0 + SX (r, t_2, p_2), y0 + SY (r, t_2, p_2), SZ (r, t_2, p_2));
graphene_point3d_init (&q4, x0 + SX (r, t_1, p_2), y0 + SY (r, t_1, p_2), SZ (r, t_1, p_2));
/* Get a matrix that moves p1 -> q1, p2 -> q2, ... */
perspective_3d (&p1, &p2, &p3, &p4,
&q1, &q2, &q3, &q4,
&m);
transform = gsk_transform_matrix (NULL, &m);
/* Since our matrix was built for transforming points with z = 1,
* prepend a translation to the z = 1 plane.
*/
transform = gsk_transform_translate_3d (transform,
&GRAPHENE_POINT3D_INIT (0, 0, 1));
gtk_widget_allocate (child, w, h, -1, transform);
}
}
static GtkSizeRequestMode
demo2_layout_get_request_mode (GtkLayoutManager *layout_manager,
GtkWidget *widget)
{
return GTK_SIZE_REQUEST_CONSTANT_SIZE;
}
static void
demo2_layout_class_init (Demo2LayoutClass *klass)
{
GtkLayoutManagerClass *layout_class = GTK_LAYOUT_MANAGER_CLASS (klass);
layout_class->get_request_mode = demo2_layout_get_request_mode;
layout_class->measure = demo2_layout_measure;
layout_class->allocate = demo2_layout_allocate;
}
static void
demo2_layout_init (Demo2Layout *self)
{
}
GtkLayoutManager *
demo2_layout_new (void)
{
return g_object_new (DEMO2_TYPE_LAYOUT, NULL);
}
void
demo2_layout_set_position (Demo2Layout *layout,
float position)
{
layout->position = position;
}
float
demo2_layout_get_position (Demo2Layout *layout)
{
return layout->position;
}
void
demo2_layout_set_offset (Demo2Layout *layout,
float offset)
{
layout->offset = offset;
}
float
demo2_layout_get_offset (Demo2Layout *layout)
{
return layout->offset;
}
-16
View File
@@ -1,16 +0,0 @@
#pragma once
#include <gtk/gtk.h>
#define DEMO2_TYPE_LAYOUT (demo2_layout_get_type ())
G_DECLARE_FINAL_TYPE (Demo2Layout, demo2_layout, DEMO2, LAYOUT, GtkLayoutManager)
GtkLayoutManager * demo2_layout_new (void);
void demo2_layout_set_position (Demo2Layout *layout,
float position);
float demo2_layout_get_position (Demo2Layout *layout);
void demo2_layout_set_offset (Demo2Layout *layout,
float offset);
float demo2_layout_get_offset (Demo2Layout *layout);
-172
View File
@@ -1,172 +0,0 @@
#include "demo2widget.h"
#include "demo2layout.h"
struct _Demo2Widget
{
GtkWidget parent_instance;
gint64 start_time;
gint64 end_time;
float start_position;
float end_position;
float start_offset;
float end_offset;
gboolean animating;
};
struct _Demo2WidgetClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE (Demo2Widget, demo2_widget, GTK_TYPE_WIDGET)
static void
demo2_widget_init (Demo2Widget *self)
{
gtk_widget_set_focusable (GTK_WIDGET (self), TRUE);
}
static void
demo2_widget_dispose (GObject *object)
{
GtkWidget *child;
while ((child = gtk_widget_get_first_child (GTK_WIDGET (object))))
gtk_widget_unparent (child);
G_OBJECT_CLASS (demo2_widget_parent_class)->dispose (object);
}
/* From clutter-easing.c, based on Robert Penner's
* infamous easing equations, MIT license.
*/
static double
ease_out_cubic (double t)
{
double p = t - 1;
return p * p * p + 1;
}
static gboolean
update_position (GtkWidget *widget,
GdkFrameClock *clock,
gpointer data)
{
Demo2Widget *self = DEMO2_WIDGET (widget);
Demo2Layout *layout = DEMO2_LAYOUT (gtk_widget_get_layout_manager (widget));
gint64 now;
double t;
now = gdk_frame_clock_get_frame_time (clock);
if (now >= self->end_time)
{
self->animating = FALSE;
return G_SOURCE_REMOVE;
}
t = (now - self->start_time) / (double) (self->end_time - self->start_time);
t = ease_out_cubic (t);
demo2_layout_set_position (layout, self->start_position + t * (self->end_position - self->start_position));
demo2_layout_set_offset (layout, self->start_offset + t * (self->end_offset - self->start_offset));
gtk_widget_queue_allocate (widget);
return G_SOURCE_CONTINUE;
}
static void
rotate_sphere (GtkWidget *widget,
const char *action,
GVariant *parameters)
{
Demo2Widget *self = DEMO2_WIDGET (widget);
Demo2Layout *layout = DEMO2_LAYOUT (gtk_widget_get_layout_manager (widget));
GtkOrientation orientation;
int direction;
g_variant_get (parameters, "(ii)", &orientation, &direction);
self->end_position = self->start_position = demo2_layout_get_position (layout);
self->end_offset = self->start_offset = demo2_layout_get_offset (layout);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
self->end_position += 10 * direction;
else
self->end_offset += 10 * direction;
self->start_time = g_get_monotonic_time ();
self->end_time = self->start_time + 0.5 * G_TIME_SPAN_SECOND;
if (!self->animating)
{
gtk_widget_add_tick_callback (widget, update_position, NULL, NULL);
self->animating = TRUE;
}
}
static void
demo2_widget_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
GtkWidget *child;
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
{
/* our layout manager sets this for children that are out of view */
if (!gtk_widget_get_child_visible (child))
continue;
gtk_widget_snapshot_child (widget, child, snapshot);
}
}
static void
demo2_widget_class_init (Demo2WidgetClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->dispose = demo2_widget_dispose;
widget_class->snapshot = demo2_widget_snapshot;
gtk_widget_class_install_action (widget_class, "rotate", "(ii)", rotate_sphere);
gtk_widget_class_add_binding_action (widget_class,
GDK_KEY_Left, 0,
"rotate",
"(ii)", GTK_ORIENTATION_HORIZONTAL, -1);
gtk_widget_class_add_binding_action (widget_class,
GDK_KEY_Right, 0,
"rotate",
"(ii)", GTK_ORIENTATION_HORIZONTAL, 1);
gtk_widget_class_add_binding_action (widget_class,
GDK_KEY_Up, 0,
"rotate",
"(ii)", GTK_ORIENTATION_VERTICAL, 1);
gtk_widget_class_add_binding_action (widget_class,
GDK_KEY_Down, 0,
"rotate",
"(ii)", GTK_ORIENTATION_VERTICAL, -1);
/* here is where we use our custom layout manager */
gtk_widget_class_set_layout_manager_type (widget_class, DEMO2_TYPE_LAYOUT);
}
GtkWidget *
demo2_widget_new (void)
{
return g_object_new (DEMO2_TYPE_WIDGET, NULL);
}
void
demo2_widget_add_child (Demo2Widget *self,
GtkWidget *child)
{
gtk_widget_set_parent (child, GTK_WIDGET (self));
}
-11
View File
@@ -1,11 +0,0 @@
#pragma once
#include <gtk/gtk.h>
#define DEMO2_TYPE_WIDGET (demo2_widget_get_type ())
G_DECLARE_FINAL_TYPE (Demo2Widget, demo2_widget, DEMO2, WIDGET, GtkWidget)
GtkWidget * demo2_widget_new (void);
void demo2_widget_add_child (Demo2Widget *self,
GtkWidget *child);
-243
View File
@@ -1,243 +0,0 @@
#include <math.h>
#include "demo3widget.h"
enum
{
PROP_PAINTABLE = 1,
PROP_SCALE
};
struct _Demo3Widget
{
GtkWidget parent_instance;
GdkPaintable *paintable;
float scale;
GtkWidget *menu;
};
struct _Demo3WidgetClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE (Demo3Widget, demo3_widget, GTK_TYPE_WIDGET)
static void
demo3_widget_init (Demo3Widget *self)
{
self->scale = 1.f;
gtk_widget_init_template (GTK_WIDGET (self));
}
static void
demo3_widget_dispose (GObject *object)
{
Demo3Widget *self = DEMO3_WIDGET (object);
g_clear_object (&self->paintable);
g_clear_pointer (&self->menu, gtk_widget_unparent);
G_OBJECT_CLASS (demo3_widget_parent_class)->dispose (object);
}
static void
demo3_widget_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
Demo3Widget *self = DEMO3_WIDGET (widget);
int x, y, width, height;
double w, h;
width = gtk_widget_get_width (widget);
height = gtk_widget_get_height (widget);
w = self->scale * gdk_paintable_get_intrinsic_width (self->paintable);
h = self->scale * gdk_paintable_get_intrinsic_height (self->paintable);
x = MAX (0, (width - ceil (w)) / 2);
y = MAX (0, (height - ceil (h)) / 2);
gtk_snapshot_push_clip (snapshot, &GRAPHENE_RECT_INIT (0, 0, width, height));
gtk_snapshot_save (snapshot);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
gdk_paintable_snapshot (self->paintable, snapshot, w, h);
gtk_snapshot_restore (snapshot);
gtk_snapshot_pop (snapshot);
}
static void
demo3_widget_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
Demo3Widget *self = DEMO3_WIDGET (widget);
int size;
if (orientation == GTK_ORIENTATION_HORIZONTAL)
size = gdk_paintable_get_intrinsic_width (self->paintable);
else
size = gdk_paintable_get_intrinsic_height (self->paintable);
*minimum = *natural = self->scale * size;
}
static void
demo3_widget_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
Demo3Widget *self = DEMO3_WIDGET (widget);
/* Since we are not using a layout manager (who would do this
* for us), we need to allocate a size for our menu by calling
* gtk_native_check_resize().
*/
gtk_native_check_resize (GTK_NATIVE (self->menu));
}
static void
demo3_widget_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
Demo3Widget *self = DEMO3_WIDGET (object);
switch (prop_id)
{
case PROP_PAINTABLE:
g_clear_object (&self->paintable);
self->paintable = g_value_dup_object (value);
gtk_widget_queue_resize (GTK_WIDGET (object));
break;
case PROP_SCALE:
self->scale = g_value_get_float (value);
gtk_widget_queue_resize (GTK_WIDGET (object));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
demo3_widget_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
Demo3Widget *self = DEMO3_WIDGET (object);
switch (prop_id)
{
case PROP_PAINTABLE:
g_value_set_object (value, self->paintable);
break;
case PROP_SCALE:
g_value_set_float (value, self->scale);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
pressed_cb (GtkGestureClick *gesture,
guint n_press,
double x,
double y,
Demo3Widget *self)
{
/* We are placing our menu at the point where
* the click happened, before popping it up.
*/
gtk_popover_set_pointing_to (GTK_POPOVER (self->menu),
&(const GdkRectangle){ x, y, 1, 1 });
gtk_popover_popup (GTK_POPOVER (self->menu));
}
static void
zoom_cb (GtkWidget *widget,
const char *action_name,
GVariant *parameter)
{
Demo3Widget *self = DEMO3_WIDGET (widget);
float scale;
if (g_str_equal (action_name, "zoom.in"))
scale = MIN (10, self->scale * M_SQRT2);
else if (g_str_equal (action_name, "zoom.out"))
scale = MAX (0.01, self->scale / M_SQRT2);
else
scale = 1.0;
gtk_widget_action_set_enabled (widget, "zoom.in", scale < 10);
gtk_widget_action_set_enabled (widget, "zoom.out", scale > 0.01);
gtk_widget_action_set_enabled (widget, "zoom.reset", scale != 1);
g_object_set (widget, "scale", scale, NULL);
}
static void
demo3_widget_class_init (Demo3WidgetClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->dispose = demo3_widget_dispose;
object_class->set_property = demo3_widget_set_property;
object_class->get_property = demo3_widget_get_property;
widget_class->snapshot = demo3_widget_snapshot;
widget_class->measure = demo3_widget_measure;
widget_class->size_allocate = demo3_widget_size_allocate;
g_object_class_install_property (object_class, PROP_PAINTABLE,
g_param_spec_object ("paintable", "Paintable", "Paintable",
GDK_TYPE_PAINTABLE,
G_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_SCALE,
g_param_spec_float ("scale", "Scale", "Scale",
0.0, 10.0, 1.0,
G_PARAM_READWRITE));
/* These are the actions that we are using in the menu */
gtk_widget_class_install_action (widget_class, "zoom.in", NULL, zoom_cb);
gtk_widget_class_install_action (widget_class, "zoom.out", NULL, zoom_cb);
gtk_widget_class_install_action (widget_class, "zoom.reset", NULL, zoom_cb);
gtk_widget_class_set_template_from_resource (widget_class, "/menu/demo3widget.ui");
gtk_widget_class_bind_template_child (widget_class, Demo3Widget, menu);
gtk_widget_class_bind_template_callback (widget_class, pressed_cb);
}
GtkWidget *
demo3_widget_new (const char *resource)
{
Demo3Widget *self;
GdkPixbuf *pixbuf;
GdkPaintable *paintable;
pixbuf = gdk_pixbuf_new_from_resource (resource, NULL);
paintable = GDK_PAINTABLE (gdk_texture_new_for_pixbuf (pixbuf));
self = g_object_new (DEMO3_TYPE_WIDGET, "paintable", paintable, NULL);
g_object_unref (pixbuf);
g_object_unref (paintable);
return GTK_WIDGET (self);
}
-8
View File
@@ -1,8 +0,0 @@
#pragma once
#include <gtk/gtk.h>
#define DEMO3_TYPE_WIDGET (demo3_widget_get_type ())
G_DECLARE_FINAL_TYPE (Demo3Widget, demo3_widget, DEMO3, WIDGET, GtkWidget)
GtkWidget * demo3_widget_new (const char *resource);
-30
View File
@@ -1,30 +0,0 @@
<interface>
<menu id="model">
<item>
<attribute name="label">Zoom Out</attribute>
<attribute name="action">zoom.out</attribute>
</item>
<item>
<attribute name="label">Zoom In</attribute>
<attribute name="action">zoom.in</attribute>
</item>
<item>
<attribute name="label">11</attribute>
<attribute name="action">zoom.reset</attribute>
</item>
</menu>
<template class="Demo3Widget">
<child>
<object class="GtkPopoverMenu" id="menu">
<property name="has-arrow">0</property>
<property name="menu-model">model</property>
</object>
</child>
<child>
<object class="GtkGestureClick">
<property name="button">3</property>
<signal name="pressed" handler="pressed_cb"/>
</object>
</child>
</template>
</interface>
-72
View File
@@ -1,72 +0,0 @@
#include "demochild.h"
/* This is a trivial child widget just for demo purposes.
* It draws a 32x32 square in fixed color.
*/
struct _DemoChild
{
GtkWidget parent_instance;
GdkRGBA color;
};
struct _DemoChildClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE (DemoChild, demo_child, GTK_TYPE_WIDGET)
static void
demo_child_init (DemoChild *self)
{
}
static void
demo_child_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
DemoChild *self = DEMO_CHILD (widget);
int width, height;
width = gtk_widget_get_width (widget);
height = gtk_widget_get_height (widget);
gtk_snapshot_append_color (snapshot, &self->color,
&GRAPHENE_RECT_INIT(0, 0, width, height));
}
static void
demo_child_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
*minimum = *natural = 32;
}
static void
demo_child_class_init (DemoChildClass *class)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
widget_class->snapshot = demo_child_snapshot;
widget_class->measure = demo_child_measure;
}
GtkWidget *
demo_child_new (const char *color)
{
DemoChild *self;
self = g_object_new (DEMO_TYPE_CHILD,
"tooltip-text", color,
NULL);
gdk_rgba_parse (&self->color, color);
return GTK_WIDGET (self);
}
-8
View File
@@ -1,8 +0,0 @@
#pragma once
#include <gtk/gtk.h>
#define DEMO_TYPE_CHILD (demo_child_get_type ())
G_DECLARE_FINAL_TYPE (DemoChild, demo_child, DEMO, CHILD, GtkWidget)
GtkWidget * demo_child_new (const char *color);
-285
View File
@@ -1,285 +0,0 @@
#include "demoimage.h"
#include <glib/gi18n.h>
struct _DemoImage {
GtkWidget parent_instance;
GtkWidget *image;
GtkWidget *popover;
};
enum {
PROP_ICON_NAME = 1
};
G_DEFINE_TYPE(DemoImage, demo_image, GTK_TYPE_WIDGET)
static GdkPaintable *
get_image_paintable (GtkImage *image)
{
const char *icon_name;
GtkIconTheme *icon_theme;
GtkIconPaintable *icon;
switch (gtk_image_get_storage_type (image))
{
case GTK_IMAGE_PAINTABLE:
return g_object_ref (gtk_image_get_paintable (image));
case GTK_IMAGE_ICON_NAME:
icon_name = gtk_image_get_icon_name (image);
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)
return NULL;
return GDK_PAINTABLE (icon);
case GTK_IMAGE_EMPTY:
case GTK_IMAGE_GICON:
default:
g_warning ("Image storage type %d not handled",
gtk_image_get_storage_type (image));
return NULL;
}
}
static void
update_drag_icon (DemoImage *demo,
GtkDragIcon *icon)
{
const char *icon_name;
GdkPaintable *paintable;
GtkWidget *image;
switch (gtk_image_get_storage_type (GTK_IMAGE (demo->image)))
{
case GTK_IMAGE_PAINTABLE:
paintable = gtk_image_get_paintable (GTK_IMAGE (demo->image));
image = gtk_image_new_from_paintable (paintable);
break;
case GTK_IMAGE_ICON_NAME:
icon_name = gtk_image_get_icon_name (GTK_IMAGE (demo->image));
image = gtk_image_new_from_icon_name (icon_name);
break;
case GTK_IMAGE_EMPTY:
case GTK_IMAGE_GICON:
default:
g_warning ("Image storage type %d not handled",
gtk_image_get_storage_type (GTK_IMAGE (demo->image)));
return;
}
gtk_image_set_pixel_size (GTK_IMAGE (image),
gtk_image_get_pixel_size (GTK_IMAGE (demo->image)));
gtk_drag_icon_set_child (icon, image);
}
static void
drag_begin (GtkDragSource *source,
GdkDrag *drag,
gpointer data)
{
GtkWidget *widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (source));
DemoImage *demo = DEMO_IMAGE (widget);
update_drag_icon (demo, GTK_DRAG_ICON (gtk_drag_icon_get_for_drag (drag)));
}
static GdkContentProvider *
prepare_drag (GtkDragSource *source,
double x,
double y,
gpointer data)
{
GtkWidget *widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (source));
DemoImage *demo = DEMO_IMAGE (widget);
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (demo->image));
return gdk_content_provider_new_typed (GDK_TYPE_PAINTABLE, paintable);
}
static gboolean
drag_drop (GtkDropTarget *dest,
const GValue *value,
double x,
double y,
gpointer data)
{
GtkWidget *widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest));
DemoImage *demo = DEMO_IMAGE (widget);
GdkPaintable *paintable = g_value_get_object (value);
gtk_image_set_from_paintable (GTK_IMAGE (demo->image), paintable);
return TRUE;
}
static void
copy_image (GtkWidget *widget,
const char *action_name,
GVariant *parameter)
{
GdkClipboard *clipboard = gtk_widget_get_clipboard (widget);
DemoImage *demo = DEMO_IMAGE (widget);
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (demo->image));
GValue value = G_VALUE_INIT;
g_value_init (&value, GDK_TYPE_PAINTABLE);
g_value_set_object (&value, paintable);
gdk_clipboard_set_value (clipboard, &value);
g_value_unset (&value);
if (paintable)
g_object_unref (paintable);
}
static void
paste_image (GtkWidget *widget,
const char *action_name,
GVariant *parameter)
{
GdkClipboard *clipboard = gtk_widget_get_clipboard (widget);
DemoImage *demo = DEMO_IMAGE (widget);
GdkContentProvider *content = gdk_clipboard_get_content (clipboard);
GValue value = G_VALUE_INIT;
GdkPaintable *paintable;
g_value_init (&value, GDK_TYPE_PAINTABLE);
if (!gdk_content_provider_get_value (content, &value, NULL))
return;
paintable = GDK_PAINTABLE (g_value_get_object (&value));
gtk_image_set_from_paintable (GTK_IMAGE (demo->image), paintable);
g_value_unset (&value);
}
static void
pressed_cb (GtkGesture *gesture,
int n_press,
double x,
double y,
gpointer data)
{
DemoImage *demo = DEMO_IMAGE (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture)));
gtk_popover_popup (GTK_POPOVER (demo->popover));
}
static void
demo_image_init (DemoImage *demo)
{
GMenu *menu;
GMenuItem *item;
GtkDragSource *source;
GtkDropTarget *dest;
GtkGesture *gesture;
demo->image = gtk_image_new ();
gtk_image_set_pixel_size (GTK_IMAGE (demo->image), 48);
gtk_widget_set_parent (demo->image, GTK_WIDGET (demo));
menu = g_menu_new ();
item = g_menu_item_new (_("_Copy"), "clipboard.copy");
g_menu_append_item (menu, item);
item = g_menu_item_new (_("_Paste"), "clipboard.paste");
g_menu_append_item (menu, item);
demo->popover = gtk_popover_menu_new_from_model (G_MENU_MODEL (menu));
gtk_widget_set_parent (demo->popover, GTK_WIDGET (demo));
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), NULL);
gtk_widget_add_controller (GTK_WIDGET (demo), GTK_EVENT_CONTROLLER (source));
dest = gtk_drop_target_new (GDK_TYPE_PAINTABLE, GDK_ACTION_COPY);
g_signal_connect (dest, "drop", G_CALLBACK (drag_drop), NULL);
gtk_widget_add_controller (GTK_WIDGET (demo), GTK_EVENT_CONTROLLER (dest));
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), NULL);
gtk_widget_add_controller (GTK_WIDGET (demo), GTK_EVENT_CONTROLLER (gesture));
}
static void
demo_image_dispose (GObject *object)
{
DemoImage *demo = DEMO_IMAGE (object);
g_clear_pointer (&demo->image, gtk_widget_unparent);
g_clear_pointer (&demo->popover, gtk_widget_unparent);
G_OBJECT_CLASS (demo_image_parent_class)->dispose (object);
}
static void
demo_image_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
DemoImage *demo = DEMO_IMAGE (object);
switch (prop_id)
{
case PROP_ICON_NAME:
g_value_set_string (value, gtk_image_get_icon_name (GTK_IMAGE (demo->image)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
demo_image_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
DemoImage *demo = DEMO_IMAGE (object);
switch (prop_id)
{
case PROP_ICON_NAME:
gtk_image_set_from_icon_name (GTK_IMAGE (demo->image),
g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
demo_image_class_init (DemoImageClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->dispose = demo_image_dispose;
object_class->get_property = demo_image_get_property;
object_class->set_property = demo_image_set_property;
g_object_class_install_property (object_class, PROP_ICON_NAME,
g_param_spec_string ("icon-name", "Icon name", "Icon name",
NULL, G_PARAM_READWRITE));
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_install_action (widget_class, "clipboard.copy", NULL, copy_image);
gtk_widget_class_install_action (widget_class, "clipboard.paste", NULL, paste_image);
}
GtkWidget *
demo_image_new (const char *icon_name)
{
return g_object_new (DEMO_TYPE_IMAGE, "icon-name", icon_name, NULL);
}
-13
View File
@@ -1,13 +0,0 @@
#pragma once
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define DEMO_TYPE_IMAGE (demo_image_get_type ())
G_DECLARE_FINAL_TYPE(DemoImage, demo_image, DEMO, IMAGE, GtkWidget)
GtkWidget * demo_image_new (const char *icon_name);
G_END_DECLS
-189
View File
@@ -1,189 +0,0 @@
#include "demolayout.h"
struct _DemoLayout
{
GtkLayoutManager parent_instance;
float position;
int pos[16];
};
struct _DemoLayoutClass
{
GtkLayoutManagerClass parent_class;
};
G_DEFINE_TYPE (DemoLayout, demo_layout, GTK_TYPE_LAYOUT_MANAGER)
static void
demo_layout_measure (GtkLayoutManager *layout_manager,
GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
GtkWidget *child;
int minimum_size = 0;
int natural_size = 0;
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
{
int child_min = 0, child_nat = 0;
if (!gtk_widget_should_layout (child))
continue;
gtk_widget_measure (child, orientation, -1,
&child_min, &child_nat,
NULL, NULL);
minimum_size = MAX (minimum_size, child_min);
natural_size = MAX (natural_size, child_nat);
}
/* A back-of-a-napkin calculation to reserve enough
* space for arranging 16 children in a circle.
*/
*minimum = 16 * minimum_size / G_PI + minimum_size;
*natural = 16 * natural_size / G_PI + natural_size;
}
static void
demo_layout_allocate (GtkLayoutManager *layout_manager,
GtkWidget *widget,
int width,
int height,
int baseline)
{
DemoLayout *self = DEMO_LAYOUT (layout_manager);
GtkWidget *child;
int i;
int child_width = 0;
int child_height = 0;
int x0, y0;
float r;
float t;
t = self->position;
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
{
GtkRequisition child_req;
if (!gtk_widget_should_layout (child))
continue;
gtk_widget_get_preferred_size (child, &child_req, NULL);
child_width = MAX (child_width, child_req.width);
child_height = MAX (child_height, child_req.height);
}
/* the center of our layout */
x0 = (width / 2);
y0 = (height / 2);
/* the radius for our circle of children */
r = 8 * child_width / G_PI;
for (child = gtk_widget_get_first_child (widget), i = 0;
child != NULL;
child = gtk_widget_get_next_sibling (child), i++)
{
GtkRequisition child_req;
float a = self->pos[i] * G_PI / 8;
int gx, gy;
int cx, cy;
int x, y;
if (!gtk_widget_should_layout (child))
continue;
gtk_widget_get_preferred_size (child, &child_req, NULL);
/* The grid position of child. */
gx = x0 + (i % 4 - 2) * child_width;
gy = y0 + (i / 4 - 2) * child_height;
/* The circle position of child. Note that we
* are adjusting the position by half the child size
* to place the center of child on a centered circle.
* This assumes that the children don't use align flags
* or uneven margins that would shift the center.
*/
cx = x0 + sin (a) * r - child_req.width / 2;
cy = y0 + cos (a) * r - child_req.height / 2;
/* we interpolate between the two layouts according to
* the position value that has been set on the layout.
*/
x = t * cx + (1 - t) * gx;
y = t * cy + (1 - t) * gy;
gtk_widget_size_allocate (child,
&(const GtkAllocation){ x, y, child_width, child_height},
-1);
}
}
static GtkSizeRequestMode
demo_layout_get_request_mode (GtkLayoutManager *layout_manager,
GtkWidget *widget)
{
return GTK_SIZE_REQUEST_CONSTANT_SIZE;
}
static void
demo_layout_class_init (DemoLayoutClass *klass)
{
GtkLayoutManagerClass *layout_class = GTK_LAYOUT_MANAGER_CLASS (klass);
layout_class->get_request_mode = demo_layout_get_request_mode;
layout_class->measure = demo_layout_measure;
layout_class->allocate = demo_layout_allocate;
}
static void
demo_layout_init (DemoLayout *self)
{
int i;
for (i = 0; i < 16; i++)
self->pos[i] = i;
}
GtkLayoutManager *
demo_layout_new (void)
{
return g_object_new (DEMO_TYPE_LAYOUT, NULL);
}
void
demo_layout_set_position (DemoLayout *layout,
float position)
{
layout->position = position;
}
/* Shuffle the circle positions of the children.
* Should be called when we are in the grid layout.
*/
void
demo_layout_shuffle (DemoLayout *layout)
{
int i, j, tmp;
for (i = 0; i < 16; i++)
{
j = g_random_int_range (0, i + 1);
tmp = layout->pos[i];
layout->pos[i] = layout->pos[j];
layout->pos[j] = tmp;
}
}
-13
View File
@@ -1,13 +0,0 @@
#pragma once
#include <gtk/gtk.h>
#define DEMO_TYPE_LAYOUT (demo_layout_get_type ())
G_DECLARE_FINAL_TYPE (DemoLayout, demo_layout, DEMO, LAYOUT, GtkLayoutManager)
GtkLayoutManager * demo_layout_new (void);
void demo_layout_set_position (DemoLayout *layout,
float position);
void demo_layout_shuffle (DemoLayout *layout);
+99 -52
View File
@@ -23,63 +23,57 @@
#include "demotaggedentry.h"
#include <gtk/gtk.h>
#include <gtk/gtk-a11y.h>
struct _DemoTaggedEntry
{
GtkWidget parent_instance;
GtkWidget *text;
};
struct _DemoTaggedEntryClass
{
GtkWidgetClass parent_class;
};
typedef struct {
GtkWidget *box;
GtkWidget *entry;
} DemoTaggedEntryPrivate;
static void demo_tagged_entry_editable_init (GtkEditableInterface *iface);
G_DEFINE_TYPE_WITH_CODE (DemoTaggedEntry, demo_tagged_entry, GTK_TYPE_WIDGET,
G_ADD_PRIVATE (DemoTaggedEntry)
G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE, demo_tagged_entry_editable_init))
static void
demo_tagged_entry_init (DemoTaggedEntry *entry)
{
GtkCssProvider *provider;
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
entry->text = gtk_text_new ();
gtk_widget_set_hexpand (entry->text, TRUE);
gtk_widget_set_vexpand (entry->text, TRUE);
gtk_widget_set_parent (entry->text, GTK_WIDGET (entry));
priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_set_parent (priv->box, GTK_WIDGET (entry));
priv->entry = gtk_text_new ();
gtk_widget_set_hexpand (priv->entry, TRUE);
gtk_widget_set_vexpand (priv->entry, TRUE);
gtk_widget_set_hexpand (priv->box, FALSE);
gtk_widget_set_vexpand (priv->box, FALSE);
gtk_container_add (GTK_CONTAINER (priv->box), priv->entry);
gtk_editable_init_delegate (GTK_EDITABLE (entry));
gtk_editable_set_width_chars (GTK_EDITABLE (entry->text), 6);
gtk_editable_set_max_width_chars (GTK_EDITABLE (entry->text), 6);
gtk_widget_add_css_class (GTK_WIDGET (entry), "tagged");
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider, "/tagged_entry/tagstyle.css");
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
800);
g_object_unref (provider);
}
static void
demo_tagged_entry_dispose (GObject *object)
{
DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (object);
GtkWidget *child;
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
if (entry->text)
if (priv->entry)
gtk_editable_finish_delegate (GTK_EDITABLE (entry));
while ((child = gtk_widget_get_first_child (GTK_WIDGET (entry))))
gtk_widget_unparent (child);
entry->text = NULL;
g_clear_pointer (&priv->entry, gtk_widget_unparent);
g_clear_pointer (&priv->box, gtk_widget_unparent);
G_OBJECT_CLASS (demo_tagged_entry_parent_class)->dispose (object);
}
static void
demo_tagged_entry_finalize (GObject *object)
{
G_OBJECT_CLASS (demo_tagged_entry_parent_class)->finalize (object);
}
static void
demo_tagged_entry_set_property (GObject *object,
guint prop_id,
@@ -104,12 +98,44 @@ demo_tagged_entry_get_property (GObject *object,
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
static gboolean
static void
demo_tagged_entry_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (widget);
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
gtk_widget_measure (priv->box, orientation, for_size,
minimum, natural,
minimum_baseline, natural_baseline);
}
static void
demo_tagged_entry_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (widget);
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
gtk_widget_size_allocate (priv->box,
&(GtkAllocation) { 0, 0, width, height },
baseline);
}
static void
demo_tagged_entry_grab_focus (GtkWidget *widget)
{
DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (widget);
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
return gtk_widget_grab_focus (entry->text);
gtk_widget_grab_focus (priv->entry);
}
static void
@@ -119,22 +145,27 @@ demo_tagged_entry_class_init (DemoTaggedEntryClass *klass)
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = demo_tagged_entry_dispose;
object_class->finalize = demo_tagged_entry_finalize;
object_class->get_property = demo_tagged_entry_get_property;
object_class->set_property = demo_tagged_entry_set_property;
widget_class->measure = demo_tagged_entry_measure;
widget_class->size_allocate = demo_tagged_entry_size_allocate;
widget_class->grab_focus = demo_tagged_entry_grab_focus;
gtk_editable_install_properties (object_class, 1);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_ENTRY_ACCESSIBLE);
gtk_widget_class_set_css_name (widget_class, "entry");
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_TEXT_BOX);
}
static GtkEditable *
demo_tagged_entry_get_delegate (GtkEditable *editable)
{
return GTK_EDITABLE (DEMO_TAGGED_ENTRY (editable)->text);
DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (editable);
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
return GTK_EDITABLE (priv->entry);
}
static void
@@ -153,9 +184,11 @@ void
demo_tagged_entry_add_tag (DemoTaggedEntry *entry,
GtkWidget *tag)
{
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
g_return_if_fail (DEMO_IS_TAGGED_ENTRY (entry));
gtk_widget_set_parent (tag, GTK_WIDGET (entry));
gtk_container_add (GTK_CONTAINER (priv->box), tag);
}
void
@@ -163,24 +196,30 @@ demo_tagged_entry_insert_tag_after (DemoTaggedEntry *entry,
GtkWidget *tag,
GtkWidget *sibling)
{
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
g_return_if_fail (DEMO_IS_TAGGED_ENTRY (entry));
gtk_widget_insert_after (tag, GTK_WIDGET (entry), sibling);
if (sibling == NULL)
gtk_container_add (GTK_CONTAINER (priv->box), tag);
else
gtk_box_insert_child_after (GTK_BOX (priv->box), tag, sibling);
}
void
demo_tagged_entry_remove_tag (DemoTaggedEntry *entry,
GtkWidget *tag)
{
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
g_return_if_fail (DEMO_IS_TAGGED_ENTRY (entry));
gtk_widget_unparent (tag);
gtk_container_remove (GTK_CONTAINER (priv->box), tag);
}
struct _DemoTaggedEntryTag
{
GtkWidget parent;
GtkWidget *box;
GtkWidget *label;
GtkWidget *button;
@@ -211,11 +250,11 @@ static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE (DemoTaggedEntryTag, demo_tagged_entry_tag, GTK_TYPE_WIDGET)
static void
on_released (GtkGestureClick *gesture,
int n_press,
double x,
double y,
DemoTaggedEntryTag *tag)
on_released (GtkGestureClick *gesture,
int n_press,
double x,
double y,
DemoTaggedEntryTag *tag)
{
g_signal_emit (tag, signals[SIGNAL_CLICKED], 0);
}
@@ -224,15 +263,23 @@ static void
demo_tagged_entry_tag_init (DemoTaggedEntryTag *tag)
{
GtkGesture *gesture;
GtkCssProvider *provider;
tag->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_set_parent (tag->box, GTK_WIDGET (tag));
tag->label = gtk_label_new ("");
gtk_box_append (GTK_BOX (tag->box), tag->label);
gtk_container_add (GTK_CONTAINER (tag->box), tag->label);
gesture = gtk_gesture_click_new ();
g_signal_connect (gesture, "released", G_CALLBACK (on_released), tag);
gtk_widget_add_controller (GTK_WIDGET (tag), GTK_EVENT_CONTROLLER (gesture));
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider, "/tagged_entry/tagstyle.css");
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
800);
g_object_unref (provider);
}
static void
@@ -413,7 +460,7 @@ demo_tagged_entry_tag_set_has_close_button (DemoTaggedEntryTag *tag,
if (!has_close_button && tag->button)
{
gtk_box_remove (GTK_BOX (tag->box), tag->button);
gtk_container_remove (GTK_CONTAINER (tag->box), tag->button);
tag->button = NULL;
}
else if (has_close_button && tag->button == NULL)
@@ -422,11 +469,11 @@ demo_tagged_entry_tag_set_has_close_button (DemoTaggedEntryTag *tag,
image = gtk_image_new_from_icon_name ("window-close-symbolic");
tag->button = gtk_button_new ();
gtk_button_set_child (GTK_BUTTON (tag->button), image);
gtk_container_add (GTK_CONTAINER (tag->button), image);
gtk_widget_set_halign (tag->button, GTK_ALIGN_CENTER);
gtk_widget_set_valign (tag->button, GTK_ALIGN_CENTER);
gtk_button_set_has_frame (GTK_BUTTON (tag->button), FALSE);
gtk_box_append (GTK_BOX (tag->box), tag->button);
gtk_button_set_relief (GTK_BUTTON (tag->button), GTK_RELIEF_NONE);
gtk_container_add (GTK_CONTAINER (tag->box), tag->button);
g_signal_connect (tag->button, "clicked", G_CALLBACK (on_button_clicked), tag);
}
+32 -4
View File
@@ -25,11 +25,39 @@
G_BEGIN_DECLS
#define DEMO_TYPE_TAGGED_ENTRY (demo_tagged_entry_get_type ())
G_DECLARE_FINAL_TYPE (DemoTaggedEntry, demo_tagged_entry, DEMO, TAGGED_ENTRY, GtkWidget)
#define DEMO_TYPE_TAGGED_ENTRY (demo_tagged_entry_get_type ())
#define DEMO_TAGGED_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DEMO_TYPE_TAGGED_ENTRY, DemoTaggedEntry))
#define DEMO_TAGGED_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DEMO_TYPE_TAGGED_ENTRY, DemoTaggedEntryClass))
#define DEMO_IS_TAGGED_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DEMO_TYPE_TAGGED_ENTRY))
#define DEMO_IS_TAGGED_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DEMO_TYPE_TAGGED_ENTRY))
#define DEMO_TAGGED_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DEMO_TYPE_TAGGED_ENTRY, DemoTaggedEntryClass))
#define DEMO_TYPE_TAGGED_ENTRY_TAG (demo_tagged_entry_tag_get_type ())
G_DECLARE_FINAL_TYPE (DemoTaggedEntryTag, demo_tagged_entry_tag, DEMO, TAGGED_ENTRY_TAG, GtkWidget)
typedef struct _DemoTaggedEntry DemoTaggedEntry;
typedef struct _DemoTaggedEntryClass DemoTaggedEntryClass;
struct _DemoTaggedEntry
{
GtkWidget parent;
};
struct _DemoTaggedEntryClass
{
GtkWidgetClass parent_class;
};
#define DEMO_TYPE_TAGGED_ENTRY_TAG (demo_tagged_entry_tag_get_type ())
#define DEMO_TAGGED_ENTRY_TAG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DEMO_TYPE_TAGGED_ENTRY_TAG, DemoTaggedEntryTag))
#define DEMO_TAGGED_ENTRY_TAG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DEMO_TYPE_TAGGED_ENTRY_TAG, DemoTaggedEntryTag))
#define DEMO_IS_TAGGED_ENTRY_TAG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DEMO_TYPE_TAGGED_ENTRY_TAG))
#define DEMO_IS_TAGGED_ENTRY_TAG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DEMO_TYPE_TAGGED_ENTRY_TAG))
#define DEMO_TAGGED_ENTRY_TAG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DEMO_TYPE_TAGGED_ENTRY_TAG, DemoTaggedEntryTagClass))
typedef struct _DemoTaggedEntryTag DemoTaggedEntryTag;
typedef struct _DemoTaggedEntryTagClass DemoTaggedEntryTagClass;
GType demo_tagged_entry_get_type (void) G_GNUC_CONST;
GType demo_tagged_entry_tag_get_type (void) G_GNUC_CONST;
GtkWidget * demo_tagged_entry_new (void);
-121
View File
@@ -1,121 +0,0 @@
#include "demowidget.h"
#include "demolayout.h"
/* parent widget */
struct _DemoWidget
{
GtkWidget parent_instance;
gboolean backward; /* whether we go 0 -> 1 or 1 -> 0 */
gint64 start_time; /* time the transition started */
guint tick_id; /* our tick cb */
};
struct _DemoWidgetClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE (DemoWidget, demo_widget, GTK_TYPE_WIDGET)
/* The widget is controlling the transition by calling
* demo_layout_set_position() in a tick callback.
*
* We take half a second to go from one layout to the other.
*/
#define DURATION (0.5 * G_TIME_SPAN_SECOND)
static gboolean
transition (GtkWidget *widget,
GdkFrameClock *frame_clock,
gpointer data)
{
DemoWidget *self = DEMO_WIDGET (widget);
DemoLayout *demo_layout = DEMO_LAYOUT (gtk_widget_get_layout_manager (widget));
gint64 now = g_get_monotonic_time ();
gtk_widget_queue_allocate (widget);
if (self->backward)
demo_layout_set_position (demo_layout, 1.0 - (now - self->start_time) / DURATION);
else
demo_layout_set_position (demo_layout, (now - self->start_time) / DURATION);
if (now - self->start_time >= DURATION)
{
self->backward = !self->backward;
demo_layout_set_position (demo_layout, self->backward ? 1.0 : 0.0);
/* keep things interesting by shuffling the positions */
if (!self->backward)
demo_layout_shuffle (demo_layout);
self->tick_id = 0;
return G_SOURCE_REMOVE;
}
return G_SOURCE_CONTINUE;
}
static void
clicked (GtkGestureClick *gesture,
guint n_press,
double x,
double y,
gpointer data)
{
DemoWidget *self = data;
if (self->tick_id != 0)
return;
self->start_time = g_get_monotonic_time ();
self->tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (self), transition, NULL, NULL);
}
static void
demo_widget_init (DemoWidget *self)
{
GtkGesture *gesture;
gesture = gtk_gesture_click_new ();
g_signal_connect (gesture, "pressed", G_CALLBACK (clicked), self);
gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (gesture));
}
static void
demo_widget_dispose (GObject *object)
{
GtkWidget *child;
while ((child = gtk_widget_get_first_child (GTK_WIDGET (object))))
gtk_widget_unparent (child);
G_OBJECT_CLASS (demo_widget_parent_class)->dispose (object);
}
static void
demo_widget_class_init (DemoWidgetClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->dispose = demo_widget_dispose;
/* here is where we use our custom layout manager */
gtk_widget_class_set_layout_manager_type (widget_class, DEMO_TYPE_LAYOUT);
}
GtkWidget *
demo_widget_new (void)
{
return g_object_new (DEMO_TYPE_WIDGET, NULL);
}
void
demo_widget_add_child (DemoWidget *self,
GtkWidget *child)
{
gtk_widget_set_parent (child, GTK_WIDGET (self));
}
-11
View File
@@ -1,11 +0,0 @@
#pragma once
#include <gtk/gtk.h>
#define DEMO_TYPE_WIDGET (demo_widget_get_type ())
G_DECLARE_FINAL_TYPE (DemoWidget, demo_widget, DEMO, WIDGET, GtkWidget)
GtkWidget * demo_widget_new (void);
void demo_widget_add_child (DemoWidget *self,
GtkWidget *child);
+53 -75
View File
@@ -1,8 +1,6 @@
/* Dialogs
* #Keywords: GtkMessageDialog
/* Dialogs and Message Boxes
*
* Dialogs are used to pop up transient windows for information
* and user feedback.
* Dialog widgets are used to pop up a transient window for user feedback.
*/
#include <glib/gi18n.h>
@@ -17,77 +15,57 @@ message_dialog_clicked (GtkButton *button,
gpointer user_data)
{
GtkWidget *dialog;
static int i = 1;
static gint i = 1;
dialog = gtk_message_dialog_new (GTK_WINDOW (window),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK_CANCEL,
"Test message");
"This message box has been popped up the following\n"
"number of times:");
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
ngettext ("Has been shown once", "Has been shown %d times", i), i);
g_signal_connect (dialog, "response", G_CALLBACK (gtk_window_destroy), NULL);
gtk_widget_show (dialog);
"%d", i);
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
i++;
}
typedef struct {
GtkWidget *local_entry1;
GtkWidget *local_entry2;
GtkWidget *global_entry1;
GtkWidget *global_entry2;
} ResponseData;
static void
on_dialog_response (GtkDialog *dialog,
int response,
gpointer user_data)
{
ResponseData *data = user_data;
if (response == GTK_RESPONSE_OK)
{
gtk_editable_set_text (GTK_EDITABLE (data->global_entry1),
gtk_editable_get_text (GTK_EDITABLE (data->local_entry1)));
gtk_editable_set_text (GTK_EDITABLE (data->global_entry2),
gtk_editable_get_text (GTK_EDITABLE (data->local_entry2)));
}
gtk_window_destroy (GTK_WINDOW (dialog));
}
static void
interactive_dialog_clicked (GtkButton *button,
gpointer user_data)
{
GtkWidget *content_area;
GtkWidget *dialog;
GtkWidget *hbox;
GtkWidget *image;
GtkWidget *table;
GtkWidget *local_entry1;
GtkWidget *local_entry2;
GtkWidget *label;
ResponseData *data;
gint response;
dialog = gtk_dialog_new_with_buttons ("Interactive Dialog",
GTK_WINDOW (window),
GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT|GTK_DIALOG_USE_HEADER_BAR,
_("_OK"), GTK_RESPONSE_OK,
_("_Cancel"), GTK_RESPONSE_CANCEL,
GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT,
_("_OK"),
GTK_RESPONSE_OK,
"_Cancel",
GTK_RESPONSE_CANCEL,
NULL);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
table = gtk_grid_new ();
gtk_widget_set_hexpand (table, TRUE);
gtk_widget_set_vexpand (table, TRUE);
gtk_widget_set_halign (table, GTK_ALIGN_CENTER);
gtk_widget_set_valign (table, GTK_ALIGN_CENTER);
gtk_box_append (GTK_BOX (content_area), table);
gtk_grid_set_row_spacing (GTK_GRID (table), 6);
gtk_grid_set_column_spacing (GTK_GRID (table), 6);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
gtk_container_add (GTK_CONTAINER (content_area), hbox);
image = gtk_image_new_from_icon_name ("dialog-question");
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
gtk_container_add (GTK_CONTAINER (hbox), image);
table = gtk_grid_new ();
gtk_grid_set_row_spacing (GTK_GRID (table), 4);
gtk_grid_set_column_spacing (GTK_GRID (table), 4);
gtk_container_add (GTK_CONTAINER (hbox), table);
label = gtk_label_new_with_mnemonic ("_Entry 1");
gtk_grid_attach (GTK_GRID (table), label, 0, 0, 1, 1);
local_entry1 = gtk_entry_new ();
@@ -103,23 +81,21 @@ interactive_dialog_clicked (GtkButton *button,
gtk_grid_attach (GTK_GRID (table), local_entry2, 1, 1, 1, 1);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), local_entry2);
data = g_new (ResponseData, 1);
data->local_entry1 = local_entry1;
data->local_entry2 = local_entry2;
data->global_entry1 = entry1;
data->global_entry2 = entry2;
response = gtk_dialog_run (GTK_DIALOG (dialog));
g_signal_connect_data (dialog, "response",
G_CALLBACK (on_dialog_response),
data, (GClosureNotify) g_free,
0);
if (response == GTK_RESPONSE_OK)
{
gtk_editable_set_text (GTK_EDITABLE (entry1), gtk_editable_get_text (GTK_EDITABLE (local_entry1)));
gtk_editable_set_text (GTK_EDITABLE (entry2), gtk_editable_get_text (GTK_EDITABLE (local_entry2)));
}
gtk_widget_show (dialog);
gtk_widget_destroy (dialog);
}
GtkWidget *
do_dialog (GtkWidget *do_widget)
{
GtkWidget *frame;
GtkWidget *vbox;
GtkWidget *vbox2;
GtkWidget *hbox;
@@ -129,45 +105,47 @@ 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");
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
gtk_window_set_title (GTK_WINDOW (window), "Dialogs and Message Boxes");
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
frame = gtk_frame_new ("Dialogs");
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);
gtk_window_set_child (GTK_WINDOW (window), vbox);
g_object_set (vbox, "margin", 8, NULL);
gtk_container_add (GTK_CONTAINER (frame), vbox);
/* Standard message dialog */
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
gtk_box_append (GTK_BOX (vbox), hbox);
gtk_container_add (GTK_CONTAINER (vbox), hbox);
button = gtk_button_new_with_mnemonic ("_Message Dialog");
g_signal_connect (button, "clicked",
G_CALLBACK (message_dialog_clicked), NULL);
gtk_box_append (GTK_BOX (hbox), button);
gtk_container_add (GTK_CONTAINER (hbox), button);
gtk_box_append (GTK_BOX (vbox), gtk_separator_new (GTK_ORIENTATION_HORIZONTAL));
gtk_container_add (GTK_CONTAINER (vbox), gtk_separator_new (GTK_ORIENTATION_HORIZONTAL));
/* Interactive dialog*/
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
gtk_box_append (GTK_BOX (vbox), hbox);
gtk_container_add (GTK_CONTAINER (vbox), hbox);
vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
button = gtk_button_new_with_mnemonic ("_Interactive Dialog");
g_signal_connect (button, "clicked",
G_CALLBACK (interactive_dialog_clicked), NULL);
gtk_box_append (GTK_BOX (hbox), vbox2);
gtk_box_append (GTK_BOX (vbox2), button);
gtk_container_add (GTK_CONTAINER (hbox), vbox2);
gtk_container_add (GTK_CONTAINER (vbox2), button);
table = gtk_grid_new ();
gtk_grid_set_row_spacing (GTK_GRID (table), 4);
gtk_grid_set_column_spacing (GTK_GRID (table), 4);
gtk_box_append (GTK_BOX (hbox), table);
gtk_container_add (GTK_CONTAINER (hbox), table);
label = gtk_label_new_with_mnemonic ("_Entry 1");
gtk_grid_attach (GTK_GRID (table), label, 0, 0, 1, 1);
@@ -186,7 +164,7 @@ do_dialog (GtkWidget *do_widget)
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
return window;
}
+229 -644
View File
File diff suppressed because it is too large Load Diff

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