Compare commits

..

176 Commits

Author SHA1 Message Date
Matthias Clasen c1995384f2 wip: Add GtkMultiSelection
This is implemented using a private GtkSet helper.
2019-12-09 12:10:05 -05:00
Matthias Clasen 9b3f42c695 wip: Add GtkSelectionMonitor
This is a list model that turns a GtkSelectionModel
into a model containing just the selected items.
This is currently only implemented for GtkSingleSelection.
2019-12-09 12:09:19 -05:00
Matthias Clasen 2cee1686a0 wip: Add GtkDropDown
This is a simple drop down control using list models.
2019-12-09 12:02:41 -05:00
Matthias Clasen 3e95a7a09a inspector: Touch up list styling
This is just the minimal amount of work to make
headers recognizable.
2019-12-09 00:03:48 -05:00
Matthias Clasen e14c079b69 inspector: Use a column view for actions
A straight conversion from list box to column view.
2019-12-09 00:03:48 -05:00
Matthias Clasen 9645142e8c inspector: Make the resource list sortable
This is using a GtkTreeListRowSorter to keep expanded
state of the tree while changing the sorting.
2019-12-09 00:03:48 -05:00
Matthias Clasen 917b1e2d6e Add GtkTreeListRowSorter
This is a special-purpose sorter that can
apply the sorting of another sorter to the
levels of a GtkTreeListModel.
2019-12-09 00:03:48 -05:00
Matthias Clasen dee6f30fab inspector: Use a column view for the resource list
A conversion from tree view to column view.
2019-12-09 00:03:48 -05:00
Matthias Clasen 152c2b9d22 inspector: Use a column view for properties
Just a straight conversion from list box to column view.
2019-12-09 00:03:48 -05:00
Matthias Clasen 4bfc653311 column view: Add a sort-by api 2019-12-09 00:03:48 -05:00
Matthias Clasen 27f19ca2a7 column view title: Show sort indicators 2019-12-09 00:03:48 -05:00
Matthias Clasen 54ded2a284 column view column: Add a sorter property
This will be used to implement sort by header click.
2019-12-09 00:03:48 -05:00
Matthias Clasen fdcc452fd6 column view: Add a sorter property
The sorter is where the column view combines the sorters of
individual columns, as the user clicks on headers. To make
sorting take effect, the sorter needs to be associated with
a sort model underneath the model thats shown in the view.
2019-12-09 00:03:48 -05:00
Matthias Clasen 376bf3789b Add GtkColumnViewSorter
This is a special-purpose, private sorter implementation which sorts
according to multiple sorters, allowing each individual sorter to be
inverted. This will be used with clickable column view headers - whenever
a header is clicked, that columns sorter is prepended to the list of
sorters, unless it is already the first sorter, in which case we invert
its order. No column can be in the list more than once.
2019-12-09 00:03:48 -05:00
Matthias Clasen 0e59cc5e22 column view: Add some helpers
These functions will be used in updating sort indicators
in column headers.
2019-12-09 00:03:48 -05:00
Matthias Clasen 3f4b8d269e Redo sort list model with GtkSorter
Reshuffle the api to take full advantage
of GtkSorter. Update all callers.
2019-12-09 00:03:48 -05:00
Matthias Clasen 4471171a6a sorter: Add tests
Some basic tests for GtkSorter.
2019-12-09 00:03:48 -05:00
Matthias Clasen 93e2e5e171 Add GtkNumericSorter
This sorter compares numbers obtained from items
by evaluating an expression.
2019-12-09 00:03:48 -05:00
Matthias Clasen a55d300357 Add GtkMultiSorter
This is a sorter that tries multiple sorters in turn.
2019-12-09 00:03:48 -05:00
Matthias Clasen 3c409a61fd Add GtkSorter, GtkStringSorter, GtkCustomSorter
This is a helper object for sorting. Also add
two implementations, GtkStringSorter for collating
strings, and GtkCustomSorter, which uses a GCompareDataFunc.
2019-12-09 00:03:48 -05:00
Matthias Clasen 59a6a3e056 list item factory: Small correction
The vfuncs for signals in GtkSignalListItemFactory
had the wrong 'this' type.
2019-12-09 00:03:44 -05:00
Matthias Clasen e1ab8db88d filter: Add a missing precondition 2019-12-08 14:00:11 -05:00
Matthias Clasen 08beaa6448 filter: Small doc tweaks 2019-12-08 13:56:15 -05:00
Matthias Clasen 65ef4b6bc8 filter: Update tests 2019-12-08 13:56:15 -05:00
Matthias Clasen dea0397e63 Add missing listmodel and selection types to the docs 2019-12-08 13:56:15 -05:00
Benjamin Otte c246671634 xxx: WIP fontchooser conversion
It compiles, and no longer crashes insantly. But more work needed.

These changes depend on Pango 1.46's introduction of listmodels, so we
depend on that now.
2019-12-08 06:27:40 +01:00
Benjamin Otte 98c25a449d expression: Allow passing a this object to bind()
This gives a bit more control over the arguments passed to expressions.
2019-12-08 06:27:40 +01:00
Benjamin Otte 71fd74c88f widget: Do parent_class handling properly
The previous cosde did not actually query the parent class, it just did
a very complicated C cast.
2019-12-08 06:27:40 +01:00
Benjamin Otte 8efe92ec69 gtk-demo: Add a Clocks demo
This demo is meant to showcase expressions.

It also needs the fixes in glib 2.64 to work properly.
2019-12-08 06:27:40 +01:00
Benjamin Otte 2f10212e7d xxx: Add a hack to make paintables transform to/from objects
See also: https://gitlab.gnome.org/GNOME/glib/merge_requests/1251
2019-12-08 06:27:40 +01:00
Benjamin Otte 13eb49c525 inspector: Remove private struct for prop editor 2019-12-08 06:27:39 +01:00
Benjamin Otte 531dc407e3 inspector: Make Controller page a GtkWidget 2019-12-08 06:27:39 +01:00
Benjamin Otte fddd7c9fad inspector: Remove private struct from controllers 2019-12-08 06:27:39 +01:00
Benjamin Otte 1cbfdddb76 columnview: Add header
This uses a custom GtkColumnViewTitle widget. So far that widget is
pretty boring, but that will change once we added
resizing, reordering, dnd, sorting, hiding/showing of columns or
whatever UIs we want.
2019-12-08 06:27:39 +01:00
Benjamin Otte 24df6869a3 tests: Add testcolumnview 2019-12-08 06:27:39 +01:00
Benjamin Otte ffbc361c30 columnview: Add a custom LayoutManager
The ColumnView now allocates column widths first and then the individual
rows use the new layout manager which looks at the column allocations to
allocate their children.
2019-12-08 06:27:39 +01:00
Benjamin Otte 48f44e87ab constraint-editor: Don't poke around in widget internals 2019-12-08 06:27:39 +01:00
Benjamin Otte 6ed9df3058 columnview: Fix styling with Adwaita
- Use "treeview" as the node name
- Add .view style class
2019-12-08 06:27:39 +01:00
Benjamin Otte 47ee4bc223 inspector: Port object tree to GtkColumnView 2019-12-08 06:27:39 +01:00
Benjamin Otte 02096df981 columnview: Add GtkColumnViewCell
It's a GtkListItemWidget subclass that tracks the column it belongs to
and allows the column to track it.

We also use this subclass to implement sizing support so columns share
the same size and get resized in sync.
2019-12-08 06:27:39 +01:00
Benjamin Otte 63afc41eb8 widget: Add a hook for resizes
It's private, no APIs, we don't talk about it. But we will start using
it very soon, so we can do size request caching in columns and avoid
sizegroups...
2019-12-08 06:27:39 +01:00
Benjamin Otte 5822d13763 columnview: Implement GtkScrollable
Just forward it to the listview for now.
2019-12-08 06:27:39 +01:00
Benjamin Otte 55018bc21a columnview: Add listitems for the columns
They are not aligned in columns yet, but they do exist.
2019-12-08 06:27:39 +01:00
Benjamin Otte 78e055c080 listitemwidget: Lazily create listitems
We only create them in root/unroot (they should be created in
appear/disappear, but that vfunc doesn't exist yet), that way we can
avoid expensive work while the widget isn't used for anything.
2019-12-08 06:27:39 +01:00
Benjamin Otte 77b7c56de2 listitem: Move position/item/selected tracking to widget
This way, we can ensure it's always there when we need it (before the
item gets created) and gone when we don't (if some GC language holds on
to the item after we've destroyed the widget).
2019-12-08 06:27:39 +01:00
Benjamin Otte 804e253f80 listitemwidget: Add a private struct
I had to rename the item property to list_item anyway, so I could just
do the next step with it.
2019-12-08 06:27:39 +01:00
Benjamin Otte 534fda92fa listitemfactory: Simplify
Instead of 6 vfuncs, we now have 3 and rely on the factory keeping track
of what it needs to do.

We're doing lots of dancing from one object to another here, but this
will hopefully get simpler with further commits.
2019-12-08 06:27:39 +01:00
Benjamin Otte 0c1336f959 listitemfactory: Reorganize vfuncs
Instead of bind/rebind/update/unbind, we now just have update, and the
factories get to interpret that in the way they want.
2019-12-08 06:27:39 +01:00
Benjamin Otte 093c37a046 listitem: Make this a GObject
This splits GtkListItem into 2 parts:

1. GtkListItem
   This is purely a GObject with public API for developers who want to
   populate lists. There is no chance to cause conflict with GtkWidget
   properties that the list implementation assumed control over and
   defines a clear boundary.
2. GtkListItemWidget
   The widget part of the listitem. This is not only fully in control of
   the list machinery, the machinery can also use different widget
   implementations for different list widgets like I inted to for
   GtkColumnView.
2019-12-08 06:27:39 +01:00
Benjamin Otte 567548c11d builder: Make gtk_builder_extend_with_template() work with objects
This will be relevant later when we introduce GtkListItem which is not a
GtkWidget.
2019-12-08 06:27:39 +01:00
Benjamin Otte b4a6262b70 gtk-demo: Add a Coverflow application launcher
This is roughly the simplest demo I could come up with.

But I documented it, so there's your tutorial.

Related: #2214
2019-12-08 06:27:39 +01:00
Benjamin Otte 81264fa7ad Add GtkSignalListItemFactory
So the poor Rust users can actually use this.

I would totally not use this ever!
2019-12-08 06:27:39 +01:00
Benjamin Otte 002fafc160 columnview: Allow adding/removing columns
... and make that work in UI files via <child>, too.
2019-12-08 06:27:39 +01:00
Benjamin Otte 4c7d053db9 gtk-demo: Add a minesweeper demo
The demo shows creating ones own listmodel and using it to fill a grid.

I am totally getting the hang of React btw:
500 lines of logic with no UI code and 100 lines of GtkBuilder XML and
I get a sweet UI.
2019-12-08 06:27:39 +01:00
Benjamin Otte 2b3f716ec3 Add GtkColumnView skeleton
It's just a copy/paste of the listview code with all the internals
gutted. The code doesn't do anything.
2019-12-08 06:27:39 +01:00
Benjamin Otte a11c5e7741 wip: Add GtkCoverFlow
The widget mostly works out of the box, but some tweaking may be
necessary (in particular in the theme) and the gtk-demo changes might
require removing before this is production-ready.
2019-12-08 06:27:39 +01:00
Benjamin Otte 35c177bae9 listbase: Take over anchor handling
With that, pretty much all code but allocating the widgets is gone from
the gridview and listview.
2019-12-08 06:27:39 +01:00
Benjamin Otte c25dc91fab listbase: Add vfuncs to convert positions to/from coordinates
... and use that to implement PageUp/PageDown.

With that, all keyboard handling has been moved to GtkListBase.
2019-12-08 06:27:39 +01:00
Benjamin Otte 52194f94dd listbase: Move focus moving keybindings here
The focus tracker is not yet moved because that depends on scroll_to()
support and we don't have that yet.
Whoops.
So we use a hack.
2019-12-08 06:27:39 +01:00
Benjamin Otte 87ae1d94df Remove gtk_selection_model_user_select_item() again
This reverts commit 6a164ab306dad9096bde736c907494c71086d3c4.

The function was awkward and we now have only one caller again, so we
can fold it back into it.
2019-12-08 06:27:39 +01:00
Benjamin Otte 1717d30416 listbase: Move orientable implementation here 2019-12-08 06:27:39 +01:00
Benjamin Otte 0852f011de listbase: Move selection handling here 2019-12-08 06:27:39 +01:00
Benjamin Otte da5f3a2ca3 listbase: Move item manager here
Nothing really changes, because both ListView and GridView still keep
self->item_manager around, but it's set up to point at the base's item
manager.

This way we can slowly move things to GtkListBase that need the item
manager (like trackers).
2019-12-08 06:27:39 +01:00
Benjamin Otte b6d965af21 listbase: Move GtkScrollable implementation
Shared code between GtkGridView and GtkListView.
2019-12-08 06:27:39 +01:00
Benjamin Otte ec2600c0f0 Add GtkListBase
This is a base item for GTK's list widgets so they can share some (read:
hopefully a lot of) code.
2019-12-08 06:27:39 +01:00
Benjamin Otte f7f3a9bd61 gridview: Simplify allocation code
It doesn't fix the bug I'm after, but it looks a lot better.
2019-12-08 06:27:39 +01:00
Benjamin Otte c2102e5a1c listview: Port various gridview improvements
- Handle anchor as align + top/bottom
  This fixes behavior for cells that are higher than the view
- Add gtk_list_view_adjustment_is_flipped()
  This should fix RTL handling of horizontal lists
- Fix scrolling
  This should make scrolling more reliable, particularly on short lists
  that are only a few pages long.
2019-12-08 06:27:39 +01:00
Benjamin Otte ab470f0c25 demo: Add a file browser demo 2019-12-08 06:27:39 +01:00
Benjamin Otte 89d48be883 gridview: Add move keybindings 2019-12-08 06:27:39 +01:00
Benjamin Otte 30ee9b0ab9 gridview: Implement (un)select all
Adds listitem.select-all and listitem.unselect-all actions and installs
the same keybindings as the treeview for those actions.
2019-12-08 06:27:39 +01:00
Benjamin Otte 5954d8f52b gridview: Add a focus tracker
... and use that to properly update selections when moving around with
the arrow keys.
2019-12-08 06:27:39 +01:00
Benjamin Otte dfbc73e41a gridview: Implement list.scroll-to action 2019-12-08 06:27:39 +01:00
Benjamin Otte 38dac9e7e1 gridview: Add activation 2019-12-08 06:27:39 +01:00
Benjamin Otte a7947a3e6e gridview: Implement minimum row height
We only allocate a certain amount of widgets - and we don't want to run
out of them. So we make all widgets high enough for this to never
happen.
2019-12-08 06:27:39 +01:00
Benjamin Otte 9f258e9544 gridview: Implement the list.select-item action 2019-12-08 06:27:39 +01:00
Benjamin Otte 272078be16 selectionmodel: Add gtk_selection_model_user_select_item()
I'm not sure this should be public API because it's incredibly awkward.
But it should definitely be shared between list widget implementations.
2019-12-08 06:27:39 +01:00
Benjamin Otte 493cb48b5f gridview: Implement anchors and scrolling 2019-12-08 06:27:39 +01:00
Benjamin Otte 3cdb350769 widget: Add gtk_widget_get_size()
A little bit of convenience.
2019-12-08 06:27:39 +01:00
Benjamin Otte 2d380ca4d3 listitemmanager: Handle NULL factory
Just don't call it and create empty listitems.
2019-12-08 06:27:39 +01:00
Timm Bäder ec50a66897 demo: Use a listview as sidebar 2019-12-08 06:27:39 +01:00
Benjamin Otte d2efd6bb99 gtk-demo: Introduce awards
We need a way to get a useful listbox, so here we go!
2019-12-08 06:27:39 +01:00
Benjamin Otte 6bf147c651 builder: Autofill scope property of listitemfactory
I couldn't come up with a better way to automatically inherit the scope
in the builder list item factory that didn't involve a magic
incantation in the XML file. And I do not want developers to know magic
incantations to do a thing that should pretty much always be done.
2019-12-08 06:27:39 +01:00
Benjamin Otte 6daa313718 builderlistitemfactory: Add scope argument
This way, the scope used when creating builder instances can be
influenced. This way, callbacks can be passed into the factory.
2019-12-08 06:27:39 +01:00
Benjamin Otte dcab637dc1 listitemfactory: Make the builder factory properly buildable
Turn the construct arguments into construct properties so that they can
be set from ui files.
2019-12-08 06:27:39 +01:00
Benjamin Otte 4404f91685 listview: Add move keybindings
My god, these are a lot.

And my god, these are complicated to get right.
2019-12-08 06:27:39 +01:00
Benjamin Otte 8f1c09b963 listview: Add gtk_list_view_get_position_at_y() 2019-12-08 06:27:39 +01:00
Benjamin Otte 10296ccefe listitem: Add "listitem.select" action and keybindings for it
In fact, grab space with all modifiers to toggle selection of the
current item.
2019-12-08 06:27:39 +01:00
Benjamin Otte 2d3bcf5b33 listview: Add a focus tracker
This ensures that the row with the input focus always stays available,
even when scrolled out of view.
2019-12-08 06:27:39 +01:00
Benjamin Otte 9c089ec7d1 listview: Implement (un)select all
Adds listitem.select-all and listitem.unselect-all actions and installs
the same keybindings as the treeview for those actions.
2019-12-08 06:27:39 +01:00
Benjamin Otte 227d6977dd listview: Track focus movements and update selection
When focus moves via tab/arrow, we need to select the new item.
2019-12-08 06:27:39 +01:00
Benjamin Otte ac55bfb999 listview: Implement activation
- a GtkListview::activate signal
- a GtkListItem::activatable property
- activate list items on double clicks and <Enter> presses
2019-12-08 06:27:38 +01:00
Benjamin Otte be87b6b62d treeexpander: Implement input support
This implements all the keybindings from GtkTreeView that can be
supported.

It does not implement expand-all, because supporting that means
causing the TreeListModel to emit lots of create_model vfuncs which in
turn would cause many items-changed signal which in turn would cause
many signal handlers to run which in turn would make "expand-all" very
reentrant, and I'm uneasy about supporting that.

For the mouse, just add a click gesture to the expander icon that toggles
expanded state.
2019-12-08 06:27:38 +01:00
Benjamin Otte a28cec61b0 listitem: Change focus handling
Focus in the listitem now works like this:
1. If any child can take focus, do not ever attempt
   to take focus.
2. Otherwise, if this item is selectable or activatable,
   allow focusing this widget.

This makes sure every item in a list is focusable for
activation and selection handling, but no useless widgets
get focused and moving focus is as fast as possible.
2019-12-08 06:27:38 +01:00
Benjamin Otte 31c5a46537 popover: Remove unneeded vfunc
The vfunc is identical to the GtkWidget implementation it replaces. So
just keep using that one.
2019-12-08 06:27:38 +01:00
Benjamin Otte 95b68384be inspector: Make the recorder node list use a ListView
It's quite a bit faster now, but the code is also a bit more awkward.

Pain points:

- GtkTreeListModel cannot be created in UI files because it needs
  a CreateModelFunc.
  Using a signal for this doesn't work because autoexpand wants to
  expand the model before the signal handler is connected.

- The list item factory usage is still awkward. It's bearable here
  because the list items are very simple, but still.
2019-12-08 06:27:38 +01:00
Benjamin Otte 8d8152279e inspector: Use a GtkTreeExpander in the object tree 2019-12-08 06:27:38 +01:00
Benjamin Otte 0e84a9d47f inspector: Use a treeexpander in the recorder 2019-12-08 06:27:38 +01:00
Benjamin Otte 6fa7319498 demo: Add a GSettings tree demo
It is meant to look somewhat like dconf-editor when it is done.

So far, it's just a list.
2019-12-08 06:27:38 +01:00
Benjamin Otte 7acfb4d918 Add GtkTreeExpander
This is a container widget that takes over all the duties of tree
expanding and collapsing.
It has to be a container so it can capture keybindings while focus is
inside the listitem.

So far, this widget does not allow interacting with it, but it shows the
expander arrow in its correct state.

Also, testlistview uses this widget now instead of implementing
expanding itself.
2019-12-08 06:27:38 +01:00
Benjamin Otte 90aaab5db9 gridview: Actually do something
Implement measuring and allocating items - which makes the items appear
when drawing and allows interacting with the items.

However, the gridview still does not allow any user interaction
(including scrolling).
2019-12-08 06:27:38 +01:00
Benjamin Otte b9d08d8b23 listview: Pass the CSS name of listitems to the manager
... instead of hardcoding "row".
2019-12-08 06:27:38 +01:00
Benjamin Otte 33ff020d13 gridview: Implement GtkOrientable
Again, this is just the skeleton, because the Gridview does nothing yet.
2019-12-08 06:27:38 +01:00
Benjamin Otte 30f61d38d3 gridview: Add factory handling
Just copy the listview APIs.

Code still doesn't do anything with it.
2019-12-08 06:27:38 +01:00
Benjamin Otte 4ec6d15013 listview: Expose GtkListItemFactory APIs
Due to the many different ways to set factories, it makes sense to
expose them as custom objects.

This makes the actual APIs for the list widgets simpler, because they
can just have a regular "factory" property.

As a convenience function, gtk_list_view_new_with_factory() was added
to make this whole approach easy to use from C.
2019-12-08 06:27:38 +01:00
Benjamin Otte fcb4c8d19b textview: Make cursor work when blinking is disabled 2019-12-08 06:27:38 +01:00
Benjamin Otte e99b195c18 gtk-demo: Add a rough start at a Weather demo
This demos a horizontal listview.
2019-12-08 06:27:38 +01:00
Benjamin Otte 978119f268 listview: Implement GtkOrientable 2019-12-08 06:27:38 +01:00
Benjamin Otte b3d16b28fd tests: Add a rough form of multiselection
Just store a "filechooser::selected" attribute in the GFileInfo if
the file is meant to be selected.
2019-12-08 06:27:38 +01:00
Benjamin Otte 136457f60c listview: Implement extending selections
Shift-clicking to extend selections now also works, imitating the
behavior of normal clicking and Windows Explorer (but not treeview):

1. We track the last selected item (normally, not via extend-clicking).

2. When shift-selecting, we modify the range from the last selected item
   to this item the same way we modify the regular item when not using
   shift:

2a. If Ctrl is not pressed, we select the range and unselect everything
    else.

2b. If Ctrl is pressed, we make the range have the same selection state
    as the last selected item:
    - If the last selected item is selected, select the range.
    - If the last selected item is not selected, unselect the range.
2019-12-08 06:27:38 +01:00
Benjamin Otte 29d10ac5ea listview: Add list.scroll_to_item action
The action scrolls the given item into view.

Listitems activate this action when they gain focus.
2019-12-08 06:27:38 +01:00
Benjamin Otte b668ad09d9 testlistview: Load icons async
Speeds up loading by 4x, because out of view icons aren't loaded
anymore.
2019-12-08 06:27:38 +01:00
Benjamin Otte f4d0564074 testlistview: Port to directory list 2019-12-08 06:27:38 +01:00
Benjamin Otte 1b0d8b68d9 listitemfactory: Add a factory for ui files
Reuse <template> magic to initialize GtkListItems. This feels
amazingly hacky, but it also amazingly worked on the first try.
2019-12-08 06:27:38 +01:00
Benjamin Otte 734456d6e3 listitemfactory: Split implementation out
.. into gtkfunctionslistitemfactory.c

Now we can add a different implmenetation.
2019-12-08 06:27:38 +01:00
Benjamin Otte d2f4de1107 listitemfactory: vfuncify
No functional changes other than a new indirection.
2019-12-08 06:27:38 +01:00
Benjamin Otte e72c56d2e8 listitemfactory: Sanitize APIs
Make sure the APIs follow a predictable path:

setup
  bind
    rebind/update (0-N times)
  unbind
teardown

This is the first step towards providing multiple different factories.
2019-12-08 06:27:38 +01:00
Benjamin Otte 73712a9dca listview: Add gtk_list_view_set_show_separators()
Do the same thing that GtkListBox does in commit
0249bd4f8a
2019-12-08 06:27:38 +01:00
Benjamin Otte 2dbc847bab listitemmanager: Add trackers
... and replace the anchor tracking with a tracker.

Trackers track an item through the list across changes and ensure that
this item (and potentially siblings before/after it) are always backed
by a GtkListItem and that if the item gets removed a replacement gets
chosen.

This is now used for tracking the anchor but can also be used to add
trackers for the cursor later.
2019-12-08 06:27:38 +01:00
Benjamin Otte 08f6e3d4e1 listitemmanager: Simplify
Remove a bunch of API from the headers that isn't used anymore and then
refactor code to not call it anymore.

In particular, get rid of GtkListItemManagerChange and replace it with a
GHashTable.
2019-12-08 06:27:38 +01:00
Benjamin Otte be1ffea531 gridview: Implement GtkScrollable
We can now scroll all the nothing we display.

We also clip it properly.
2019-12-08 06:27:38 +01:00
Benjamin Otte 97fbc3b13d listitemmanager: Move list of listitems here
All the listview infrastructure moved with it, so the next step is
moving that back...
2019-12-08 06:27:38 +01:00
Benjamin Otte 5351a95900 wayland: Remove function declaration for nonexisting function 2019-12-08 06:27:38 +01:00
Benjamin Otte b5d937a497 gridview: Add API for setting number of columns
The API isn't used yet.
2019-12-08 06:27:38 +01:00
Benjamin Otte 7c1da37676 gtk: Add a GtkGridView skeleton 2019-12-08 06:27:38 +01:00
Benjamin Otte 25e896ec40 listitem: Add a press gesture to select the item
This is implemented by using actions, which are a neat trick to get to
allow the ListItem to call functions on the ListView without actually
needing to be aware of it.
2019-12-08 06:27:38 +01:00
Benjamin Otte 21f240e99a listview: Add initial support for displaying selections 2019-12-08 06:27:38 +01:00
Benjamin Otte 7b6a2f7b4d listview: Reset listitems' CSS animations when rebinding
This way, newly displayed rows don't play an unselect animation (text
fading in) when they are unselected, but the row was previously used for
a selected item.
2019-12-08 06:27:38 +01:00
Benjamin Otte 5b12a0fe1b listview: Add selection properties to ListItem
This just brings the infrastructure into place, we're not using the
properties yet.
2019-12-08 06:27:38 +01:00
Benjamin Otte eaefce91b2 listview: Try to keep the list items in order when scrolling
Instead of just destroying all items and then recreating them (or even
hide()ing and then show()ing them again (or even even repositioning
them in the widget tree)), just try to reust them in the order they are.

This works surprisingly well when scrolling and most/all widgets
just moved.
2019-12-08 06:27:38 +01:00
Benjamin Otte 382f543539 listlistmodel: Add gtk_list_list_model_item_moved()
Use it to fix a case that just said g_warning ("oops").

Apparently I had forgotten the case where a container moved a child
in the widget tree.
2019-12-08 06:27:38 +01:00
Benjamin Otte 3c5f040e06 listitemmanager: Switch from "insert_before" to "insert_after" argumnet
We reorder widgets start to end, so when reusing a list item, we
correctly know the previous sibling for that list item, but not the
next sibling yet. We just know the widget it should ultimately be in
front of.
So we can do a more correct guess of the list item's place in the widget
tree if we think about where to place an item like this.

Actually using this change will come in the next commit.
2019-12-08 06:27:38 +01:00
Benjamin Otte d58ba49d28 testlistview: Create widgets only once
Previously, we were recreating all widgets every time the list item was
rebound, which caused a lot of extra work every time we scrolled.

Now we keep the widgets around and only set their properties again when
the item changes.
2019-12-08 06:27:38 +01:00
Benjamin Otte 9435b7135d testlistview: Show the row number
Always show the current row. This is mostly useful for debugging, not
for beauty.
2019-12-08 06:27:38 +01:00
Benjamin Otte e802551369 listview: Only allocate necesary rows
This is the big one.

The listview only allocates 200 rows around the visible row now.
Everything else is kept in ListRow instances with row->widget == NULL.

For rows without a widget, we assign the median height of the child
widgets as the row's height and then do all calculations as if there
were widgets that had requested that height (like setting adjustment
values or reacting to adjustment value changes).

When the view is scrolled, we bind the 200 rows to the new visible area,
so that the part of the listview that can be seen is always allocated.
2019-12-08 06:27:38 +01:00
Benjamin Otte 522c1f2883 listview: Change anchor handling again
The anchor is now a tuple of { listitem, align }.

Using the actual list item allows keeping the anchor across changes
in position (ie when lists get resorted) while still being able to fall
back to positions (list items store their position) when an item gets
removed.

The align value is in the range [0..1] and defines where in the visible
area to do the alignment.
0.0 means to align the top of the row with the top of the visible area,
1.0 aligns the bottom of the widget with the visible area and 0.5 keeps
the center of the widget at the center of the visible area.
It works conceptually the same as percentages in CSS background-position
(where the background area and the background image's size are matched
the same way) or CSS transform-origin.
2019-12-08 06:27:38 +01:00
Benjamin Otte 11de7bf1a0 listview: Change how binding is done
We now don't let the functions create widgets for the item from the
listmodel, instead we hand out a GtkListItem for them to add a widget
to.

GtkListItems are created in advance and can only be filled in by the
binding code by gtk_container_add()ing a widget.
However, they are GObjects, so they can provide properties that the
binding code can make use of - either via notify signals or GBinding.
2019-12-08 06:27:38 +01:00
Benjamin Otte d01138c4d5 listitem: Add gtk_list_item_get_position()
Also refactor the whole list item management yet again.

Now, list item APIs doesn't have bind/unbind functions anymore, but only
property setters.

The item factory is the only one doing the binding.
As before, the item manager manages when items need to be bound.
2019-12-08 06:27:38 +01:00
Benjamin Otte 637ba7afd2 tests: Make animating listview do random resorts 2019-12-08 06:27:38 +01:00
Benjamin Otte 715e597107 listview: Change change management
Add a GtkListItemManagerChange object that tracks all removed list
rows during an item-changed signal so they can be added back later.
2019-12-08 06:27:38 +01:00
Benjamin Otte 9dc9092bac listview: Make the listitemmanager stricter
Require that items created with the manager get destroyed via the
manager.

To that purpose, renamed create_list_item() to acquire_list_item() and
add a matching release_list_item() function.

This way, the manager can in the future keep track of all items and
cache information about them.
2019-12-08 06:27:38 +01:00
Benjamin Otte 9ee0283ffa listview: Add GtkListItem
GtkListItem is a generic row widget that is supposed to replace
GtkListBoxRow and GtkFlowBoxChild.
2019-12-08 06:27:38 +01:00
Benjamin Otte 9672aa089a listview: Add GtkListItemManager
It's all stubs for now, but here's the basic ideas about what
this object is supposed to do:

(1) It's supposed to be handling all the child GtkWidgets that are
    used by the listview, so that the listview can concern
    itself with how many items it needs and where to put them.
(2) It's meant to do the caching of widgets that are not (currently)
    used.
(3) It's meant to track items that remain in the model across
    items-changed emissions and just change position.
(2) It's code that can be shared between listview and potential
    other widgets like a GridView.

It's also free to assume that the number of items it's supposed to
manage doesn't grow too much, so it's free to use O(N) algorithms.
2019-12-08 06:27:38 +01:00
Benjamin Otte a6dcfe7b58 listview: Implement an anchor
The anchor selection is very basic: just anchor the top row.

That's vastly better than any other widget already though.
2019-12-08 06:27:38 +01:00
Benjamin Otte 545398e819 tests: Add a test for a permanently changing listview
This is mostly for dealing with proper anchoring and can be used to
check that things don't scroll or that selection and focus handling
properly works.

For comparison purposes, a ListBox is provided next to it.
2019-12-08 06:27:38 +01:00
Benjamin Otte ccb13a4c92 listview: Implement GtkScrollable
Scrolling in a very basic form is also supported
2019-12-08 06:27:37 +01:00
Benjamin Otte 6e756d9ad0 listview: Make widget actually do something
The thing we're actually doing is create and maintain a widget for every
row. That's it.

Also add a testcase using this. The testcase quickly allocates too many
rows though and then becomes unresponsive though. You have been warned.
2019-12-08 06:27:37 +01:00
Benjamin Otte 34709bc815 listview: Introduce GtkListItemFactory
Thisis the abstraction I intend to use for creating widgets and binding
them to the item out of the listview.

For now this is a very dumb wrapper around the functions that exist in
the API.

But it leaves the freedom to turn this into public API, make an
interface out of it and most of all write different implementations, in
particular one that uses GtkBuilder.
2019-12-08 06:27:37 +01:00
Benjamin Otte 054299d45b gtk: Add a GtkListView skeleton 2019-12-08 06:27:37 +01:00
Benjamin Otte f4ad74de9d builder: Add <binding> tag
The tag contains an expression that it then gtk_expression_bind()s to
the object it is contained in.
2019-12-08 06:27:37 +01:00
Benjamin Otte b20105b7bc builder: Allow text content in <lookup>
<lookup>foo</lookup>
is now short for
  <lookup>
    <constant>foo</constant>
  </lookup>
ie it looks up the object with the given name so it can then do a
property lookup with it.

This is the most common operation, so it's a nice shortcut.
2019-12-08 06:27:37 +01:00
Benjamin Otte 6600776865 builder: Allow <constant> without a type
A constant without a type is assumed to be an object. This is the most
common case and allows
  <constant>foo</constant>
without requiring updates to the type whenever the foo object changes.
2019-12-08 06:27:37 +01:00
Benjamin Otte 3f23255e0f builder: Make <lookup> type optional
If no type is set, use the type of the expression.
2019-12-08 06:27:37 +01:00
Benjamin Otte 615a0ccae1 gtk-demo: Make fishbowl info text use bindings
It's a good demo for how bindings can format multiple properties into an
informative string with 1 line of code (and 5 lines of XML).
2019-12-08 06:27:37 +01:00
Matthias Clasen 6a098e451e More expression tests
Test type mismatches, and the this pointer
during evaluation.
2019-12-08 06:27:37 +01:00
Benjamin Otte a94d4648c8 expression: Invalidate bindings before destroying them
Use a weak ref to invalidate bindings. Make sure that this happens
before creating any watches, so that notifies from the
watched expression about changes will not trigger set_property() calls
during dispose()/finalize().

Invalidating also ensures that the watches aren't removed, which can
trigger warnings if the watches are watching the object itself, and the
weak refs cannot be removed anymore.
2019-12-08 06:27:37 +01:00
Benjamin Otte c3d67d3271 expression: Add gtk_expression_bind()
Add a simple way to bind expressions to object properties. This is
essentially the thing to replace g_object_bind_property().
2019-12-08 06:27:37 +01:00
Benjamin Otte b9b4e3ebe4 testsuite: Add expression tests 2019-12-08 06:27:37 +01:00
Benjamin Otte adab2ba0de expression: Add the ability to watch an expression 2019-12-08 06:27:37 +01:00
Benjamin Otte e6b82215d2 builder: Add support for parsing expressions 2019-12-08 06:27:37 +01:00
Benjamin Otte 02619e8a47 filter: Add GtkStringFilter
Users provide a search filter and an expression that evaluates the items
to a string and then the filter goes and matches those strings to the
search term.
2019-12-08 06:27:37 +01:00
Benjamin Otte 0956255b50 expression: Make property expression allow subexpressions 2019-12-08 06:27:37 +01:00
Benjamin Otte 4567c425ae expression: Add GtkObjectExpression
Weak refs break cycles...
2019-12-08 06:27:37 +01:00
Benjamin Otte 9371102bf9 Add GtkExpression
GtkExpressions allow looking up values from objects.

There are a few simple expressions, but the main one is the closure
expression that just calls a user-provided closure.
2019-12-08 06:27:37 +01:00
Benjamin Otte dbaec8756d filter: Add GtkAnyFilter 2019-12-08 06:27:37 +01:00
Benjamin Otte d3e75bcb3b filterlistmodel: Rewrite to use GtkFilter 2019-12-08 06:27:37 +01:00
Benjamin Otte 614a748d65 tests: Remove testtreemodel test
testlistview does everything this test does.
2019-12-08 06:27:37 +01:00
Benjamin Otte 1fd1f71abf filter: Add a custom filter 2019-12-08 06:27:37 +01:00
Benjamin Otte 8bf8bdb8ef Add GtkFilter 2019-12-08 06:27:37 +01:00
Benjamin Otte 94cb76788d Add GtkDirectoryList
Adds a new listmodel called GtkDirectoryList that lists the children of
a GFile as GFileInfos.

This is supposed to be used by the filechooser.
2019-12-08 06:27:37 +01:00
Benjamin Otte f16a9a5f5c builder: Turn last dlsym() function into a scope API
Looking up a get_type function by its name is now also part of
GtkBuilderScope.
2019-12-08 06:27:37 +01:00
Benjamin Otte dccef45600 builder: Add GtkBuilderScope
GtkBuilderScope is an interface that provides the scope that a builder
instance operates in.
It creates closures and resolves types. Language bindings are meant to
use this interface to customize the behavior of builder files, in
particular when instantiating templates.

A default implementation for C is provided via GtkBuilderCScope (to keep
with the awkward naming that glib uses for closures). It is derivable on
purpose so that languages or extensions that extend C can use it.

The reftest code in fact does derive GtkBuilderCScope for its own scope
implementation that implements looking up symbols in modules.

gtk-widget-factory was updated to use the new GtkBuilderCScope to add
its custom callback symbols.
So it does it different from gtk-demo, which uses the normal way of
exporting symbols for dlsym() and thereby makes the 2 demos test the 2
ways GtkBuilder uses for looking up symbols.
2019-12-08 06:27:37 +01:00
Benjamin Otte 2baa8b750c builder: Add gtk_builder_set_current_object()
Use it as the default object for expression binds and when connecting
signals. It is intended to work kind of as the "this" object while
parsing. In fact, the term "current object" was stolen from the Java
docs and various C++ tutorials for the this pointer.

Set the current object in gtk_widget_init_template() and
GtkListItemBuilder.

This more-or-less replaces the object passed to
gtk_builder_connect_signals() in GTK3.
2019-12-08 06:27:37 +01:00
Benjamin Otte 1420deb167 builder: Add gtk_builder_lookup_object()
... and use it. This function looks up an object like
gtk_builder_get_object() but generates an error on failure.

Unlike the evil function _gtk_builder_lookup_object() which also
generates an error but hides it for later lookup.

Use this to avoid continuing applying properties when an error was
encountered.
2019-12-08 06:27:37 +01:00
Benjamin Otte e3e8d72e72 a11y: We can peek here
Avoids instantiating a11y objects when we don't need to.
2019-12-08 06:27:37 +01:00
Benjamin Otte 2c48c1c9d9 treeview: Don't create a cyclic reference
TreeRowReference refs the proxy object, so don't use proxies.
2019-12-08 06:27:37 +01:00
Benjamin Otte 92a1683675 label: Compute label baselines correctly
When we were switching smallest and widest, we were not switching the
baselines.
2019-12-08 05:33:42 +01:00
2435 changed files with 246343 additions and 233525 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
+47 -132
View File
@@ -1,9 +1,7 @@
stages:
- build
- analysis
- docs
- flatpak
- deploy
# - deploy
.cache-paths: &cache-paths
paths:
@@ -14,114 +12,53 @@ stages:
- subprojects/libepoxy/
- subprojects/pango/
# Common variables
variables:
COMMON_MESON_FLAGS: "--fatal-meson-warnings --werror"
MESON_TEST_TIMEOUT_MULTIPLIER: 2
.only-default:
only:
- branches
except:
- tags
style-check-diff:
extends: .only-default
image: registry.gitlab.gnome.org/gnome/gtk/fedora:v17
stage: .pre
allow_failure: true
fedora-x86_64: &fedora-x86_64-defaults
image: registry.gitlab.gnome.org/gnome/gtk/master:v7
stage: build
script:
- .gitlab-ci/run-style-check-diff.sh
.build-fedora-default:
image: registry.gitlab.gnome.org/gnome/gtk/fedora:v17
- 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
fedora-x86_64-staticlibs:
variables:
EXTRA_MESON_FLAGS: "--buildtype=debug --default-library=both"
script:
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS}
-Dx11-backend=true
-Dwayland-backend=true
-Dbroadway-backend=true
-Dvulkan=yes
-Dprofiler=true
_build
- ninja -C _build
- .gitlab-ci/run-tests.sh _build x11
- .gitlab-ci/run-tests.sh _build wayland
- .gitlab-ci/run-tests.sh _build broadway
EXTRA_MESON_FLAGS: "-Ddefault_library=both"
<<: *fedora-x86_64-defaults
release-build:
extends: .build-fedora-default
stage: build
variables:
EXTRA_MESON_FLAGS: "--buildtype=release"
script:
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS}
-Dx11-backend=true
-Dwayland-backend=true
-Dbroadway-backend=true
-Dvulkan=yes
_build
- ninja -C _build
- .gitlab-ci/run-tests.sh _build x11
.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"
allow_failure: true
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-mingw32:
extends: .mingw-defaults
variables:
MSYSTEM: "MINGW32"
CHERE_INVOKING: "yes"
<<: *mingw-defaults
.flatpak-defaults:
.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"
@@ -130,81 +67,59 @@ msys2-mingw32:
- 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
variables:
APPID: org.gtk.Demo4
<<: *flatpak-manual
flatpak-master:demo:
extends: .flatpak-master
variables:
APPID: org.gtk.Demo4
<<: *flatpak-master
flatpak-manual:widget-factory:
extends: .flatpak-manual
variables:
APPID: org.gtk.WidgetFactory4
<<: *flatpak-manual
flatpak-master:widget-factory:
extends: .flatpak-master
variables:
APPID: org.gtk.WidgetFactory4
<<: *flatpak-master
flatpak-manual:icon-browser:
extends: .flatpak-manual
variables:
APPID: org.gtk.IconBrowser4
<<: *flatpak-manual
flatpak-master:icon-browser:
extends: .flatpak-master
variables:
APPID: org.gtk.IconBrowser4
<<: *flatpak-master
static-scan:
image: registry.gitlab.gnome.org/gnome/gtk/fedora:v16
stage: analysis
variables:
EXTRA_MESON_FLAGS: "--buildtype=debug"
script:
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} _scan_build
- ninja -C _scan_build scan-build
artifacts:
paths:
- _scan_build/meson-logs
allow_failure: true
reference:
image: registry.gitlab.gnome.org/gnome/gtk/fedora-docs:v19
stage: docs
variables:
EXTRA_MESON_FLAGS: "--buildtype=release"
script:
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} -Dgtk_doc=true _build
- ninja -C _build gdk4-doc gsk4-doc gtk4-doc
- mkdir -p _reference/
- mv _build/docs/reference/gdk/html/ _reference/gdk/
- mv _build/docs/reference/gsk/html/ _reference/gsk/
- mv _build/docs/reference/gtk/html/ _reference/gtk/
artifacts:
paths:
- _reference
pages:
stage: deploy
script:
- mv _reference/ public/
artifacts:
paths:
- public
only:
- master
#pages:
# image: registry.gitlab.gnome.org/gnome/gtk/master:v6
# stage: deploy
# script:
# - meson -Dgtk_doc=true _build .
# - ninja -C _build
# - ninja -C _build gdk4-doc gsk4-doc gtk4-doc
# - mkdir -p public/
# - mv _build/docs/reference/gtk/html/ public/gtk/
# - mv _build/docs/reference/gdk/html/ public/gdk/
# - mv _build/docs/reference/gsk/html/ public/gsk/
# artifacts:
# paths:
# - public
# only:
# - master
@@ -8,12 +8,9 @@ RUN dnf -y install \
cairo-devel \
cairo-gobject-devel \
ccache \
clang \
clang-analyzer \
colord-devel \
cups-devel \
dbus-daemon \
dbus-x11 \
dejavu-sans-mono-fonts \
desktop-file-utils \
diffutils \
@@ -26,7 +23,6 @@ RUN dnf -y install \
gettext \
git \
glib2-devel \
glib2-static \
glibc-devel \
glibc-headers \
gobject-introspection-devel \
@@ -57,7 +53,6 @@ RUN dnf -y install \
libxkbcommon-devel \
libXrandr-devel \
libXrender-devel \
libXtst-devel \
libxslt \
mesa-dri-drivers \
mesa-libEGL-devel \
@@ -65,24 +60,27 @@ RUN dnf -y install \
ninja-build \
pango-devel \
pcre-devel \
pcre-static \
python3 \
python3-jinja2 \
python3-pip \
python3-pygments \
python3-wheel \
redhat-rpm-config \
sassc \
sysprof-devel \
systemtap-sdt-devel \
vulkan-devel \
wayland-devel \
wayland-protocols-devel \
weston \
weston-libs \
which \
xorg-x11-server-Xvfb \
&& dnf clean all
RUN pip3 install meson==0.53.1
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
-38
View File
@@ -1,38 +0,0 @@
## GTK CI infrastructure
GTK uses different CI images depending on platform and jobs.
The CI images are Docker containers, generated either using `docker` or
`podman`, and pushed to the GitLab [container registry][registry].
Each Docker image has a tag composed of two parts:
- `${image}`: the base image for a given platform, like "fedora" or
"debian-stable"
- `${number}`: an incremental version number, or `latest`
See the [container registry][registry] for the available images for each
branch, as well as their available versions.
### Checklist for Updating a CI image
- [ ] Update the `${image}.Dockerfile` file with the dependencies
- [ ] Run `./run-docker.sh build --base ${image} --base-version ${number}`
- [ ] Run `./run-docker.sh push --base ${image} --base-version ${number}`
once the Docker image is built; you may need to log in by using
`docker login` or `podman login`
- [ ] Update the `image` keys in the `.gitlab-ci.yml` file with the new
image tag
- [ ] Open a merge request with your changes and let it run
### Checklist for Adding a new CI image
- [ ] Write a new `${image}.Dockerfile` with the instructions to set up
a build environment
- [ ] Add the `pip3 install meson` incantation
- [ ] Run `./run-docker.sh build --base ${image} --base-version ${number}`
- [ ] Run `./run-docker.sh push --base ${image} --base-version ${number}`
- [ ] Add the new job to `.gitlab-ci.yml` referencing the image
- [ ] Open a merge request with your changes and let it run
[registry]: https://gitlab.gnome.org/GNOME/gtk/container_registry
-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:v19
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
-10
View File
@@ -1,10 +0,0 @@
FROM registry.gitlab.gnome.org/gnome/gtk/fedora-base:v19
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 -11
View File
@@ -4,19 +4,20 @@ set -e
appid=$1
builddir=flatpak_app
builddir=app
repodir=repo
flatpak-builder \
--user --disable-rofiles-fuse \
--stop-at=gtk \
${builddir} \
build-aux/flatpak/${appid}.json
flatpak build ${builddir} meson \
--prefix=/app \
--libdir=/app/lib \
--buildtype=release \
flatpak-builder \
--run ${builddir} build-aux/flatpak/${appid}.json \
meson \
--prefix /app \
--libdir /app/lib \
--buildtype debug \
-Dx11-backend=true \
-Dwayland-backend=true \
-Dprint-backends=file \
@@ -24,12 +25,13 @@ flatpak build ${builddir} meson \
-Dbuild-examples=false \
-Dintrospection=false \
-Ddemos=true \
_flatpak_build
flatpak build ${builddir} ninja -C _flatpak_build install
_build .
flatpak-builder \
--run ${builddir} build-aux/flatpak/${appid}.json \
ninja -C _build install
flatpak-builder \
--user --disable-rofiles-fuse \
--finish-only \
--repo=${repodir} \
${builddir} \
@@ -38,5 +40,5 @@ flatpak-builder \
flatpak build-bundle \
${repodir} \
${appid}-dev.flatpak \
--runtime-repo=https://nightly.gnome.org/gnome-nightly.flatpakrepo \
--runtime-repo=https://flathub.org/repo/flathub.flatpakrepo \
${appid}
+55 -63
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>
<ul>
<li><strong>Total units:</strong> {{ report.total_units }}</li>
<li><strong>Failed:</strong> {{ report.total_failures }}</li>
<li><strong>Passed:</strong> {{ report.total_successes }}</li>
<li><strong>Passed:</strong> <a href="#passed">{{ report.total_successes }}</a></li>
<li><strong>Failed:</strong> <a href="#failures">{{ report.total_failures }}</a></li>
</ul>
</div>
</section>
@@ -168,47 +164,30 @@ ul.images li {
<h3><a name="results">Suite: {{ suite_result.suite_name }}</a></h3>
<ul>
<li><strong>Units:</strong> {{ suite_result.n_units }}</li>
<li><strong>Failed:</strong> <a href="#{{ suite_result.suite_name }}-failed">{{ suite_result.n_failures }}</a></li>
<li><strong>Passed:</strong> <a href="#{{ suite_result.suite_name }}-passed">{{ suite_result.n_successes }}</a></li>
<li><strong>Passed:</strong> {{ suite_result.n_successes }}</li>
<li><strong>Failed:</strong> {{ suite_result.n_failures }}</li>
</ul>
<div class="failures">
<h4><a name="{{ suite_result.suite_name }}-failed">Failures</a></h4>
<ul class="failed">
{% for failure in suite_result.failures if failure.result in [ 'ERROR', 'FAIL', 'UNEXPECTEDPASS' ] %}
<li><a name="{{ failure.name }}">{{ failure.name }}</a> - result: <span class="result fail">{{ failure.result }}</span><br/>
{% if failure.stdout %}
Output: <pre>{{ failure.stdout }}</pre>
{% endif %}
{% if failure.image_data is defined %}
<ul class="images">
<li><img alt="ref" src="{{ failure.image_data.ref }}" /></li>
<li><img alt="out" src="{{ failure.image_data.out }}" /></li>
<li><img alt="diff" src="{{ failure.image_data.diff }}" /></li>
</ul>
{% endif %}
</li>
{% else %}
<li>None</li>
{% endfor %}
</ul>
<h4><a name="{{ suite_result.suite_name }}-timed-out">Timed out</a></h4>
<ul class="failed">
{% for failure in suite_result.failures if failure.result == 'TIMEOUT' %}
<li><a name="{{ failure.name }}">{{ failure.name }}</a> - result: <span class="result fail">{{ failure.result }}</span><br/>
{% if failure.stdout %}
Output: <pre>{{ failure.stdout }}</pre>
{% endif %}
</li>
{% else %}
<li>None</li>
{% endfor %}
</ul>
</div>
<div class="successes">
<h4><a name="{{ suite_result.suite_name }}-expected-fail">Expected failures</a></h4>
<h4><a name="passed">Passed</a></h4>
<ul class="passed">
{% for success in suite_result.successes if success.result == 'OK' %}
<li>{{ success.name }} - result: <span class="result pass">{{ success.result }}</li>
{% else %}
<li>None</li>
{% endfor %}
</ul>
<h4><a name="skipped">Skipped</a></h4>
<ul>
{% for success in suite_result.successes if success.result == 'SKIP' %}
<li>{{ success.name }} - result: <span class="result skip">{{ success.result }}</li>
{% else %}
<li>None</li>
{% endfor %}
</ul>
<h4><a name="expected-fail">Expected failures</a></h4>
<ul>
{% for success in suite_result.successes if success.result == 'EXPECTEDFAIL' %}
<li><a name="{{ success.name }}">{{ success.name }}</a> - result: <span class="result xfail">{{ success.result }}</span><br/>
@@ -227,20 +206,37 @@ ul.images li {
<li>None</li>
{% endfor %}
</ul>
</div>
<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>
<div class="failures">
<h4><a name="failed">Failed</a></h4>
<ul class="failed">
{% for failure in suite_result.failures if failure.result == 'FAIL' %}
<li><a name="{{ failure.name }}">{{ failure.name }}</a> - result: <span class="result fail">{{ failure.result }}</span><br/>
{% if failure.stdout %}
Output: <pre>{{ failure.stdout }}</pre>
{% endif %}
{% if failure.image_data is defined %}
<ul class="images">
<li><img alt="ref" src="{{ failure.image_data.ref }}" /></li>
<li><img alt="out" src="{{ failure.image_data.out }}" /></li>
<li><img alt="diff" src="{{ failure.image_data.diff }}" /></li>
</ul>
{% endif %}
</li>
{% else %}
<li>None</li>
{% endfor %}
</ul>
<h4><a name="{{ 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>
<h4><a name="timed-out">Timed out</a></h4>
<ul class="failed">
{% for failure in suite_result.failures if failure.result == 'TIMEOUT' %}
<li><a name="{{ failure.name }}">{{ failure.name }}</a> - result: <span class="result fail">{{ failure.result }}</span><br/>
{% if failure.stdout %}
Output: <pre>{{ failure.stdout }}</pre>
{% endif %}
</li>
{% else %}
<li>None</li>
{% endfor %}
@@ -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:v7"
while (($# > 0)); do
case "${1%%=*}" in
build) build=1;;
run) run=1;;
push) push=1;;
list) list=1;;
help) print_help=1;;
--base|-b) read_arg base "$@" || shift;;
--base-version) read_arg base_version "$@" || shift;;
--no-login) no_login=1;;
*) echo -e "\e[1;31mERROR\e[0m: Unknown option '$1'"; exit 1;;
esac
shift
done
if [ $print_help == 1 ]; then
echo "$0 - Build and run Docker images"
echo ""
echo "Usage: $0 <command> [options] [basename]"
echo ""
echo "Available commands"
echo ""
echo " build --base=<BASENAME> - Build Docker image <BASENAME>.Dockerfile"
echo " run --base=<BASENAME> - Run Docker image <BASENAME>"
echo " push --base=<BASENAME> - Push Docker image <BASENAME> to the registry"
echo " list - List available images"
echo " help - This help message"
echo ""
exit 0
fi
cd "$(dirname "$0")"
if [ $list == 1 ]; then
echo "Available Docker images:"
for f in *.Dockerfile; do
filename=$( basename -- "$f" )
basename="${filename%.*}"
echo -e " \e[1;39m$basename\e[0m"
done
exit 0
fi
# All commands after this require --base to be set
if [ -z $base ]; then
echo "Usage: $0 <command>"
exit 1
fi
if [ ! -f "$base.Dockerfile" ]; then
echo -e "\e[1;31mERROR\e[0m: Dockerfile for '$base' not found"
exit 1
fi
if [ -z $base_version ]; then
base_version="latest"
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
-37
View File
@@ -1,37 +0,0 @@
#!/bin/bash
set -e
# We need to add a new remote for the upstream master, since this script could
# be running in a personal fork of the repository which has out of date branches.
git remote add upstream https://gitlab.gnome.org/GNOME/gtk.git
git fetch upstream
# Work out the newest common ancestor between the detached HEAD that this CI job
# has checked out, and the upstream target branch (which will typically be
# `upstream/master` or `upstream/gtk-3-24`).
#
# `${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}` is only defined if 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 "upstream/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-${CI_DEFAULT_BRANCH}}") <(git rev-list --first-parent HEAD) | head -1)
git diff -U0 --no-color "${newest_common_ancestor_sha}" | .gitlab-ci/clang-format-diff.py -binary "clang-format" -p1
exit_status=$?
# The style check is not infallible. The clang-format configuration cannot
# perfectly describe 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}
-79
View File
@@ -1,79 +0,0 @@
#!/bin/bash
set +x
set +e
srcdir=$( pwd )
builddir=$1
backend=$2
case "${backend}" in
x11)
xvfb-run -a -s "-screen 0 1024x768x24" \
meson test -C ${builddir} \
--print-errorlogs \
--setup=${backend} \
--suite=gtk \
--no-suite=gtk:a11y \
--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} \
--print-errorlogs \
--setup=${backend} \
--suite=gtk \
--no-suite=gtk:a11y \
--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} \
--print-errorlogs \
--setup=${backend} \
--suite=gtk \
--no-suite=gtk:a11y \
--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
-1
View File
@@ -16,7 +16,6 @@ meson \
-Dwayland-backend=true \
-Dbroadway-backend=true \
-Dvulkan=yes \
-Dprofiler=true \
--werror \
${EXTRA_MESON_FLAGS:-} \
_build $srcdir
-10
View File
@@ -33,13 +33,6 @@ pacman --noconfirm -S --needed \
mingw-w64-$MSYS2_ARCH-gst-plugins-bad \
mingw-w64-$MSYS2_ARCH-shared-mime-info
# https://gitlab.gnome.org/GNOME/gtk/issues/2243
wget "https://gitlab.gnome.org/creiter/gitlab-ci-win32-runner-v2/raw/master/pango/mingw-w64-$MSYS2_ARCH-pango-git-1.44.7.90.ge48ae523-1-any.pkg.tar.zst"
pacman --noconfirm -U "mingw-w64-$MSYS2_ARCH-pango-git-1.44.7.90.ge48ae523-1-any.pkg.tar.zst"
# https://github.com/msys2/MINGW-packages/pull/6465
pacman --noconfirm -S --needed mingw-w64-$MSYS2_ARCH-brotli
mkdir -p _ccache
export CCACHE_BASEDIR="$(pwd)"
export CCACHE_DIR="${CCACHE_BASEDIR}/_ccache"
@@ -48,14 +41,11 @@ export CCACHE_DIR="${CCACHE_BASEDIR}/_ccache"
ccache --zero-stats
ccache --show-stats
export CCACHE_DISABLE=true
# FIXME: introspection disabled for now because of
# https://gitlab.gnome.org/GNOME/gobject-introspection/-/issues/340
meson \
-Dx11-backend=false \
-Dwayland-backend=false \
-Dwin32-backend=true \
-Dvulkan=no \
-Dintrospection=false \
--werror \
_build
unset CCACHE_DISABLE
+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 -333
View File
@@ -1,335 +1,3 @@
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
==================================
@@ -692,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
+3 -9
View File
@@ -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/
@@ -140,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
-------------
@@ -162,4 +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.
Please, see the `COPYING` file for further information.
-30
View File
@@ -54,36 +54,6 @@
}
]
},
{
"name" : "libsass",
"buildsystem" : "meson",
"builddir" : true,
"config-opts": [
"--libdir=/app/lib"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/lazka/libsass.git",
"branch" : "meson"
}
]
},
{
"name" : "sassc",
"buildsystem" : "meson",
"builddir" : true,
"config-opts": [
"--libdir=/app/lib"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/lazka/sassc.git",
"branch" : "meson"
}
]
},
{
"name": "gtk",
"buildsystem": "meson",
@@ -54,36 +54,6 @@
}
]
},
{
"name" : "libsass",
"buildsystem" : "meson",
"builddir" : true,
"config-opts": [
"--libdir=/app/lib"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/lazka/libsass.git",
"branch" : "meson"
}
]
},
{
"name" : "sassc",
"buildsystem" : "meson",
"builddir" : true,
"config-opts": [
"--libdir=/app/lib"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/lazka/sassc.git",
"branch" : "meson"
}
]
},
{
"name": "gtk",
"buildsystem": "meson",
@@ -54,36 +54,6 @@
}
]
},
{
"name" : "libsass",
"buildsystem" : "meson",
"builddir" : true,
"config-opts": [
"--libdir=/app/lib"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/lazka/libsass.git",
"branch" : "meson"
}
]
},
{
"name" : "sassc",
"buildsystem" : "meson",
"builddir" : true,
"config-opts": [
"--libdir=/app/lib"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/lazka/sassc.git",
"branch" : "meson"
}
]
},
{
"name": "gtk",
"buildsystem": "meson",
+3 -7
View File
@@ -35,10 +35,6 @@
*/
#mesondefine HAVE_DECL_ISNAN
/* Define to 1 if you have the declaration of `isnanf', and to 0 if you don't.
*/
#mesondefine HAVE_DECL_ISNANF
/* Define to 1 if you have the <dlfcn.h> header file. */
#mesondefine HAVE_DLFCN_H
@@ -150,6 +146,9 @@
/* Have the Xcursor library */
#mesondefine HAVE_XCURSOR
/* Have the XDAMAGE X extension */
#mesondefine HAVE_XDAMAGE
/* Have the XFIXES X extension */
#mesondefine HAVE_XFIXES
@@ -296,6 +295,3 @@
#mesondefine HAVE_PANGOFT
#mesondefine ISO_CODES_PREFIX
/* Define if tracker3 is available */
#mesondefine HAVE_TRACKER3
@@ -221,12 +221,9 @@ open_cb (GtkWidget *button,
GTK_FILE_CHOOSER_ACTION_OPEN,
"_Load",
"_Cancel");
gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (dialog), TRUE);
GFile *cwd = g_file_new_for_path (".");
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), cwd, NULL);
g_object_unref (cwd);
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), ".");
g_signal_connect (dialog, "response", G_CALLBACK (open_response_cb), self);
gtk_native_dialog_show (GTK_NATIVE_DIALOG (dialog));
}
@@ -293,37 +290,29 @@ save_response_cb (GtkNativeDialog *dialog,
if (response == GTK_RESPONSE_ACCEPT)
{
GListModel *model;
GFile *file;
char *text;
char *text, *filename;
GError *error = NULL;
model = constraint_view_get_model (CONSTRAINT_VIEW (self->view));
text = serialize_model (model);
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
g_file_replace_contents (file, text, -1,
NULL, FALSE,
G_FILE_CREATE_NONE,
NULL,
NULL,
&error);
if (error != NULL)
{
GtkWidget *message_dialog;
message_dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self))),
GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
"Saving failed");
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message_dialog),
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
if (!g_file_set_contents (filename, text, -1, &error))
{
GtkWidget *dialog;
dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self))),
GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
"Saving failed");
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
"%s", error->message);
g_signal_connect (message_dialog, "response", G_CALLBACK (gtk_window_destroy), NULL);
gtk_widget_show (message_dialog);
g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
gtk_widget_show (dialog);
g_error_free (error);
}
g_free (text);
g_object_unref (file);
g_free (filename);
}
gtk_native_dialog_destroy (dialog);
@@ -340,12 +329,9 @@ save_cb (GtkWidget *button,
GTK_FILE_CHOOSER_ACTION_SAVE,
"_Save",
"_Cancel");
gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (dialog), TRUE);
GFile *cwd = g_file_new_for_path (".");
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), cwd, NULL);
g_object_unref (cwd);
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), ".");
g_signal_connect (dialog, "response", G_CALLBACK (save_response_cb), self);
gtk_native_dialog_show (GTK_NATIVE_DIALOG (dialog));
}
@@ -403,7 +389,7 @@ constraint_editor_done (ConstraintEditor *editor,
g_clear_object (&old_constraint);
gtk_window_destroy (GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (editor), GTK_TYPE_WINDOW)));
gtk_widget_destroy (gtk_widget_get_ancestor (GTK_WIDGET (editor), GTK_TYPE_WINDOW));
}
static void
@@ -414,7 +400,7 @@ edit_constraint (ConstraintEditorWindow *win,
ConstraintEditor *editor;
GListModel *model;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (win));
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
if (constraint)
@@ -426,7 +412,7 @@ edit_constraint (ConstraintEditorWindow *win,
editor = constraint_editor_new (model, constraint);
gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (editor));
gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (editor));
g_signal_connect (editor, "done", G_CALLBACK (constraint_editor_done), win);
@@ -444,7 +430,7 @@ guide_editor_done (GuideEditor *editor,
GtkConstraintGuide *guide,
ConstraintEditorWindow *win)
{
gtk_window_destroy (GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (editor), GTK_TYPE_WINDOW)));
gtk_widget_destroy (gtk_widget_get_ancestor (GTK_WIDGET (editor), GTK_TYPE_WINDOW));
}
static void
@@ -454,13 +440,13 @@ edit_guide (ConstraintEditorWindow *win,
GtkWidget *window;
GuideEditor *editor;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (win));
gtk_window_set_title (GTK_WINDOW (window), "Edit Guide");
editor = guide_editor_new (guide);
gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (editor));
gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (editor));
g_signal_connect (editor, "done", G_CALLBACK (guide_editor_done), win);
gtk_widget_show (window);
@@ -487,6 +473,8 @@ constraint_editor_window_class_init (ConstraintEditorWindowClass *class)
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
g_type_ensure (CONSTRAINT_VIEW_TYPE);
object_class->finalize = constraint_editor_window_finalize;
gtk_widget_class_set_template_from_resource (widget_class,
@@ -599,33 +587,30 @@ create_widget_func (gpointer item,
g_object_bind_property (item, "name",
label, "label",
G_BINDING_DEFAULT);
gtk_widget_set_margin_start (label, 10);
gtk_widget_set_margin_end (label, 10);
gtk_widget_set_margin_top (label, 10);
gtk_widget_set_margin_bottom (label, 10);
g_object_set (label, "margin", 10, NULL);
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
gtk_widget_set_hexpand (label, TRUE);
gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), box);
gtk_box_append (GTK_BOX (box), label);
gtk_container_add (GTK_CONTAINER (row), box);
gtk_container_add (GTK_CONTAINER (box), label);
if (GTK_IS_CONSTRAINT (item) || GTK_IS_CONSTRAINT_GUIDE (item))
{
button = gtk_button_new_from_icon_name ("document-edit-symbolic");
gtk_button_set_has_frame (GTK_BUTTON (button), FALSE);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
g_signal_connect (button, "clicked", G_CALLBACK (row_edit), win);
g_object_set_data (G_OBJECT (row), "edit", button);
gtk_box_append (GTK_BOX (box), button);
gtk_container_add (GTK_CONTAINER (box), button);
button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
gtk_button_set_has_frame (GTK_BUTTON (button), FALSE);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
g_signal_connect (button, "clicked", G_CALLBACK (row_delete), win);
gtk_box_append (GTK_BOX (box), button);
gtk_container_add (GTK_CONTAINER (box), button);
}
else if (GTK_IS_WIDGET (item))
{
button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
gtk_button_set_has_frame (GTK_BUTTON (button), FALSE);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
g_signal_connect (button, "clicked", G_CALLBACK (row_delete), win);
gtk_box_append (GTK_BOX (box), button);
gtk_container_add (GTK_CONTAINER (box), button);
}
g_free (freeme);
@@ -9,6 +9,7 @@
<property name="default-height">768</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="header">
<property name="title" translatable="yes">GTK Constraint Editor</property>
<property name="show-title-buttons">1</property>
<child type="start">
<object class="GtkButton">
+1 -4
View File
@@ -3,10 +3,7 @@
<template class="ConstraintEditor" parent="GtkWidget">
<child>
<object class="GtkGrid" id="grid">
<property name="margin-start">20</property>
<property name="margin-end">20</property>
<property name="margin-top">20</property>
<property name="margin-bottom">20</property>
<property name="margin">20</property>
<property name="row-spacing">10</property>
<property name="column-spacing">10</property>
<child>
+8 -8
View File
@@ -77,7 +77,7 @@ update_weak_position (ConstraintView *self,
GTK_CONSTRAINT_RELATION_EQ,
x,
GTK_CONSTRAINT_STRENGTH_WEAK);
g_object_set_data (G_OBJECT (constraint), "internal", (char *)"yes");
g_object_set_data (G_OBJECT (constraint), "internal", "yes");
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (manager),
constraint);
g_object_set_data (G_OBJECT (child), "x-constraint", constraint);
@@ -97,7 +97,7 @@ update_weak_position (ConstraintView *self,
GTK_CONSTRAINT_RELATION_EQ,
y,
GTK_CONSTRAINT_STRENGTH_WEAK);
g_object_set_data (G_OBJECT (constraint), "internal", (char *)"yes");
g_object_set_data (G_OBJECT (constraint), "internal", "yes");
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (manager),
constraint);
g_object_set_data (G_OBJECT (child), "y-constraint", constraint);
@@ -219,9 +219,9 @@ constraint_view_add_child (ConstraintView *view,
label = gtk_label_new (name);
frame = gtk_frame_new (NULL);
gtk_widget_add_css_class (frame, "child");
gtk_style_context_add_class (gtk_widget_get_style_context (frame), "child");
gtk_widget_set_name (frame, name);
gtk_frame_set_child (GTK_FRAME (frame), label);
gtk_container_add (GTK_CONTAINER (frame), label);
gtk_widget_set_parent (frame, GTK_WIDGET (view));
update_weak_position (view, frame, 100, 100);
@@ -262,9 +262,9 @@ constraint_view_add_guide (ConstraintView *view,
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_style_context_add_class (gtk_widget_get_style_context (frame), "guide");
g_object_set_data (G_OBJECT (frame), "internal", "yes");
gtk_container_add (GTK_CONTAINER (frame), label);
gtk_widget_insert_after (frame, GTK_WIDGET (view), NULL);
g_object_set_data (G_OBJECT (guide), "frame", frame);
@@ -281,7 +281,7 @@ constraint_view_add_guide (ConstraintView *view,
names[i].attr,
1.0, 0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
g_object_set_data (G_OBJECT (constraint), "internal", (char *)"yes");
g_object_set_data (G_OBJECT (constraint), "internal", "yes");
gtk_constraint_layout_add_constraint (layout, constraint);
g_object_set_data (G_OBJECT (guide), names[i].name, constraint);
}
@@ -23,7 +23,6 @@
#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);
+1 -1
View File
@@ -78,7 +78,7 @@ get_strength (const char *id)
return strength;
}
static const char *
const char *
get_strength_nick (GtkConstraintStrength strength)
{
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_STRENGTH);
+1 -4
View File
@@ -45,10 +45,7 @@
<template class="GuideEditor" parent="GtkWidget">
<child>
<object class="GtkGrid" id="grid">
<property name="margin-start">20</property>
<property name="margin-end">20</property>
<property name="margin-top">20</property>
<property name="margin-bottom">20</property>
<property name="margin">20</property>
<property name="row-spacing">10</property>
<property name="column-spacing">10</property>
<child>
-1
View File
@@ -13,7 +13,6 @@ constraint_editor_resources = gnome.compile_resources('constraint_editor_resourc
executable('gtk4-constraint-editor',
constraint_editor_sources, constraint_editor_resources,
c_args: common_cflags,
dependencies: libgtk_dep,
include_directories: confinc,
gui_app: true,
+20 -18
View File
@@ -6,7 +6,6 @@
typedef GtkApplication DemoApplication;
typedef GtkApplicationClass DemoApplicationClass;
static GType demo_application_get_type (void);
G_DEFINE_TYPE (DemoApplication, demo_application, GTK_TYPE_APPLICATION)
typedef struct {
@@ -15,7 +14,7 @@ typedef struct {
GtkWidget *message;
GtkWidget *infobar;
GtkWidget *status;
GtkWidget *menubutton;
GtkWidget *menutool;
GMenuModel *toolmenu;
GtkTextBuffer *buffer;
@@ -26,7 +25,6 @@ typedef struct {
} DemoApplicationWindow;
typedef GtkApplicationWindowClass DemoApplicationWindowClass;
static GType demo_application_window_get_type (void);
G_DEFINE_TYPE (DemoApplicationWindow, demo_application_window, GTK_TYPE_APPLICATION_WINDOW)
static void create_window (GApplication *app, const char *contents);
@@ -47,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);
}
@@ -120,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);
}
@@ -234,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;
}
@@ -328,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);
}
@@ -348,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);
@@ -417,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;
@@ -426,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),
@@ -475,7 +477,7 @@ surface_state_changed (GtkWidget *widget)
DemoApplicationWindow *window = (DemoApplicationWindow *)widget;
GdkSurfaceState new_state;
new_state = gdk_toplevel_get_state (GDK_TOPLEVEL (gtk_native_get_surface (GTK_NATIVE (widget))));
new_state = gdk_surface_get_state (gtk_native_get_surface (GTK_NATIVE (widget)));
window->maximized = (new_state & GDK_SURFACE_STATE_MAXIMIZED) != 0;
window->fullscreen = (new_state & GDK_SURFACE_STATE_FULLSCREEN) != 0;
}
@@ -499,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
@@ -515,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);
+26 -15
View File
@@ -8,24 +8,27 @@
<child>
<object class="GtkGrid">
<child>
<object class="GtkBox">
<object class="GtkToolbar">
<property name="hexpand">1</property>
<style>
<class name="primary-toolbar"/>
</style>
<child>
<object class="GtkMenuButton" id="menubutton">
<object class="GtkMenuToolButton" id="menutool">
<property name="icon-name">document-open</property>
</object>
</child>
<child>
<object class="GtkButton">
<object class="GtkToolButton">
<property name="icon-name">application-exit</property>
<property name="action-name">app.quit</property>
</object>
</child>
<child>
<object class="GtkSeparator"/>
<object class="GtkSeparatorToolItem"/>
</child>
<child>
<object class="GtkButton">
<object class="GtkToolButton">
<property name="icon-name">applications-other</property>
<property name="action-name">win.logo</property>
</object>
@@ -40,17 +43,25 @@
<object class="GtkInfoBar" id="infobar">
<property name="visible">0</property>
<property name="hexpand">1</property>
<child>
<object class="GtkLabel" id="message">
<property name="hexpand">1</property>
<child internal-child="content_area">
<object class="GtkBox" id="content_area">
<child>
<object class="GtkLabel" id="message">
<property name="hexpand">1</property>
</object>
</child>
</object>
</child>
<child type="action">
<object class="GtkButton">
<property name="valign">center</property>
<property name="label" translatable="yes">_OK</property>
<property name="use-underline">1</property>
<signal name="clicked" handler="clicked_cb"/>
<child internal-child="action_area">
<object class="GtkBox">
<child>
<object class="GtkButton">
<property name="valign">center</property>
<property name="label" translatable="yes">_OK</property>
<property name="use-underline">1</property>
<signal name="clicked" handler="clicked_cb"/>
</object>
</child>
</object>
</child>
<layout>
@@ -61,7 +72,7 @@
</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>
+6 -1
View File
@@ -31,7 +31,12 @@ on_name_vanished (GDBusConnection *connection,
if (!name_seen)
return;
g_clear_object (&placeholder);
if (placeholder)
{
gtk_widget_destroy (placeholder);
g_object_unref (placeholder);
placeholder = NULL;
}
}
#ifdef G_OS_WIN32
+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>
+18 -22
View File
@@ -7,6 +7,7 @@
#include <gtk/gtk.h>
static GtkWidget *assistant = NULL;
static GtkWidget *progress_bar = NULL;
static gboolean
@@ -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,13 +37,16 @@ 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
@@ -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;
}
+6 -5
View File
@@ -20,15 +20,16 @@ do_awardview (GtkWidget *do_widget)
GtkWidget *sw, *listview;
GListModel *list;
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), "Awards");
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);
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_window_set_child (GTK_WINDOW (window), sw);
gtk_container_add (GTK_CONTAINER (window), sw);
listview = gtk_list_view_new_with_factory (
gtk_builder_list_item_factory_new_from_resource (NULL, "/awardview/awardlistitem.ui"));
@@ -36,13 +37,13 @@ do_awardview (GtkWidget *do_widget)
gtk_list_view_set_model (GTK_LIST_VIEW (listview), list);
g_object_unref (list);
gtk_list_view_set_show_separators (GTK_LIST_VIEW (listview), TRUE);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), listview);
gtk_container_add (GTK_CONTAINER (sw), listview);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
return window;
}
+2 -1
View File
@@ -25,8 +25,9 @@
</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="left-attach">0</property>
+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, GTK_STYLE_CLASS_LEFT);
has_right = gtk_widget_has_css_class (child, GTK_STYLE_CLASS_RIGHT);
has_top = gtk_widget_has_css_class (child, GTK_STYLE_CLASS_TOP);
has_bottom = gtk_widget_has_css_class (child, GTK_STYLE_CLASS_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, GTK_STYLE_CLASS_LEFT);
gtk_style_context_remove_class (context, GTK_STYLE_CLASS_LEFT);
else if (!has_left && is_left)
gtk_widget_add_css_class (child, GTK_STYLE_CLASS_LEFT);
gtk_style_context_add_class (context, GTK_STYLE_CLASS_LEFT);
if (has_right && !is_right)
gtk_widget_remove_css_class (child, GTK_STYLE_CLASS_RIGHT);
gtk_style_context_remove_class (context, GTK_STYLE_CLASS_RIGHT);
else if (!has_right && is_right)
gtk_widget_add_css_class (child, GTK_STYLE_CLASS_RIGHT);
gtk_style_context_add_class (context, GTK_STYLE_CLASS_RIGHT);
if (has_top && !is_top)
gtk_widget_remove_css_class (child, GTK_STYLE_CLASS_TOP);
gtk_style_context_remove_class (context, GTK_STYLE_CLASS_TOP);
else if (!has_top && is_top)
gtk_widget_add_css_class (child, GTK_STYLE_CLASS_TOP);
gtk_style_context_add_class (context, GTK_STYLE_CLASS_TOP);
if (has_bottom && !is_bottom)
gtk_widget_remove_css_class (child, GTK_STYLE_CLASS_BOTTOM);
gtk_style_context_remove_class (context, GTK_STYLE_CLASS_BOTTOM);
else if (!has_bottom && is_bottom)
gtk_widget_add_css_class (child, GTK_STYLE_CLASS_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
+51 -23
View File
@@ -12,7 +12,7 @@ quit_activate (GSimpleAction *action,
{
GtkWidget *window = user_data;
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
}
static void
@@ -26,10 +26,8 @@ about_activate (GSimpleAction *action,
builder = g_object_get_data (G_OBJECT (window), "builder");
about_dlg = GTK_WIDGET (gtk_builder_get_object (builder, "aboutdialog1"));
gtk_window_set_transient_for (GTK_WINDOW (about_dlg), GTK_WINDOW (window));
gtk_window_set_hide_on_close (GTK_WINDOW (about_dlg), TRUE);
g_signal_connect (about_dlg, "response", G_CALLBACK (gtk_widget_hide), NULL);
gtk_widget_show (about_dlg);
gtk_dialog_run (GTK_DIALOG (about_dlg));
gtk_widget_hide (about_dlg);
}
static void
@@ -40,22 +38,7 @@ help_activate (GSimpleAction *action,
g_print ("Help not available\n");
}
static void
not_implemented (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
g_print ("Action “%s” not implemented\n", g_action_get_name (G_ACTION (action)));
}
static GActionEntry win_entries[] = {
{ "new", not_implemented, NULL, NULL, NULL },
{ "open", not_implemented, NULL, NULL, NULL },
{ "save", not_implemented, NULL, NULL, NULL },
{ "save-as", not_implemented, NULL, NULL, NULL },
{ "copy", not_implemented, NULL, NULL, NULL },
{ "cut", not_implemented, NULL, NULL, NULL },
{ "paste", not_implemented, NULL, NULL, NULL },
{ "quit", quit_activate, NULL, NULL, NULL },
{ "about", about_activate, NULL, NULL, NULL },
{ "help", help_activate, NULL, NULL, NULL }
@@ -65,7 +48,10 @@ GtkWidget *
do_builder (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
GtkWidget *toolbar;
GActionGroup *actions;
GtkAccelGroup *accel_group;
GtkWidget *item;
if (!window)
{
@@ -76,20 +62,62 @@ do_builder (GtkWidget *do_widget)
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);
accel_group = gtk_accel_group_new ();
gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
g_object_unref (builder);
item = (GtkWidget*)gtk_builder_get_object (builder, "new_item");
gtk_widget_add_accelerator (item, "activate", accel_group,
GDK_KEY_n, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
item = (GtkWidget*)gtk_builder_get_object (builder, "open_item");
gtk_widget_add_accelerator (item, "activate", accel_group,
GDK_KEY_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
item = (GtkWidget*)gtk_builder_get_object (builder, "save_item");
gtk_widget_add_accelerator (item, "activate", accel_group,
GDK_KEY_s, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
item = (GtkWidget*)gtk_builder_get_object (builder, "quit_item");
gtk_widget_add_accelerator (item, "activate", accel_group,
GDK_KEY_q, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
item = (GtkWidget*)gtk_builder_get_object (builder, "copy_item");
gtk_widget_add_accelerator (item, "activate", accel_group,
GDK_KEY_c, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
item = (GtkWidget*)gtk_builder_get_object (builder, "cut_item");
gtk_widget_add_accelerator (item, "activate", accel_group,
GDK_KEY_x, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
item = (GtkWidget*)gtk_builder_get_object (builder, "paste_item");
gtk_widget_add_accelerator (item, "activate", accel_group,
GDK_KEY_v, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
item = (GtkWidget*)gtk_builder_get_object (builder, "help_item");
gtk_widget_add_accelerator (item, "activate", accel_group,
GDK_KEY_F1, 0, GTK_ACCEL_VISIBLE);
item = (GtkWidget*)gtk_builder_get_object (builder, "about_item");
gtk_widget_add_accelerator (item, "activate", accel_group,
GDK_KEY_F7, 0, GTK_ACCEL_VISIBLE);
g_object_set_data_full (G_OBJECT(window), "builder", builder, g_object_unref);
}
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 gtk_icon_info_load_icon (icon_info, NULL);
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;
}
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;
}
+31 -44
View File
@@ -19,7 +19,7 @@ enum
static GtkTreeModel *
create_icon_store (void)
{
const char *icon_names[6] = {
const gchar *icon_names[6] = {
"dialog-warning",
"process-stop",
"document-new",
@@ -27,7 +27,7 @@ create_icon_store (void)
NULL,
"document-open"
};
const char *labels[6] = {
const gchar *labels[6] = {
N_("Warning"),
N_("Stop"),
N_("New"),
@@ -111,8 +111,8 @@ static GtkTreeModel *
create_capital_store (void)
{
struct {
const char *group;
const char *capital;
gchar *group;
gchar *capital;
} capitals[] = {
{ "A - B", NULL },
{ NULL, "Albany" },
@@ -234,7 +234,7 @@ typedef struct _MaskEntry MaskEntry;
struct _MaskEntry
{
GtkEntry entry;
const char *mask;
gchar *mask;
};
typedef struct _MaskEntryClass MaskEntryClass;
@@ -246,7 +246,6 @@ struct _MaskEntryClass
static void mask_entry_editable_init (GtkEditableInterface *iface);
static GType mask_entry_get_type (void);
G_DEFINE_TYPE_WITH_CODE (MaskEntry, mask_entry, GTK_TYPE_ENTRY,
G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
mask_entry_editable_init));
@@ -311,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);
@@ -372,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);
@@ -403,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;
}
+16 -16
View File
@@ -21,24 +21,23 @@ struct _SimpleGrid
G_DEFINE_TYPE (SimpleGrid, simple_grid, GTK_TYPE_WIDGET)
static void
simple_grid_dispose (GObject *object)
simple_grid_destroy (GtkWidget *widget)
{
SimpleGrid *self = SIMPLE_GRID (object);
SimpleGrid *self = SIMPLE_GRID (widget);
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_clear_pointer (&self->button1, gtk_widget_destroy);
g_clear_pointer (&self->button2, gtk_widget_destroy);
g_clear_pointer (&self->button3, gtk_widget_destroy);
G_OBJECT_CLASS (simple_grid_parent_class)->dispose (object);
GTK_WIDGET_CLASS (simple_grid_parent_class)->destroy (widget);
}
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;
widget_class->destroy = simple_grid_destroy;
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
}
@@ -256,34 +255,35 @@ do_constraints (GtkWidget *do_widget)
{
GtkWidget *header, *box, *grid, *button;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Constraints");
header = gtk_header_bar_new ();
gtk_header_bar_set_title (GTK_HEADER_BAR (header), "Constraints");
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
gtk_window_set_titlebar (GTK_WINDOW (window), header);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
gtk_window_set_child (GTK_WINDOW (window), box);
gtk_container_add (GTK_CONTAINER (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);
gtk_container_add (GTK_CONTAINER (box), grid);
button = gtk_button_new_with_label ("Close");
gtk_box_append (GTK_BOX (box), button);
gtk_container_add (GTK_CONTAINER (box), button);
gtk_widget_set_hexpand (grid, TRUE);
g_signal_connect_swapped (button, "clicked",
G_CALLBACK (gtk_window_destroy), window);
G_CALLBACK (gtk_widget_destroy), window);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
return window;
}
+16 -16
View File
@@ -22,24 +22,23 @@ struct _InteractiveGrid
G_DEFINE_TYPE (InteractiveGrid, interactive_grid, GTK_TYPE_WIDGET)
static void
interactive_grid_dispose (GObject *object)
interactive_grid_destroy (GtkWidget *widget)
{
InteractiveGrid *self = INTERACTIVE_GRID (object);
InteractiveGrid *self = INTERACTIVE_GRID (widget);
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_clear_pointer (&self->button1, gtk_widget_destroy);
g_clear_pointer (&self->button2, gtk_widget_destroy);
g_clear_pointer (&self->button3, gtk_widget_destroy);
G_OBJECT_CLASS (interactive_grid_parent_class)->dispose (object);
GTK_WIDGET_CLASS (interactive_grid_parent_class)->destroy (widget);
}
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;
widget_class->destroy = interactive_grid_destroy;
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
}
@@ -212,34 +211,35 @@ do_constraints2 (GtkWidget *do_widget)
{
GtkWidget *header, *box, *grid, *button;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Constraints");
header = gtk_header_bar_new ();
gtk_header_bar_set_title (GTK_HEADER_BAR (header), "Constraints");
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
gtk_window_set_titlebar (GTK_WINDOW (window), header);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
gtk_window_set_child (GTK_WINDOW (window), box);
gtk_container_add (GTK_CONTAINER (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);
gtk_container_add (GTK_CONTAINER (box), grid);
button = gtk_button_new_with_label ("Close");
gtk_box_append (GTK_BOX (box), button);
gtk_container_add (GTK_CONTAINER (box), button);
gtk_widget_set_hexpand (grid, TRUE);
g_signal_connect_swapped (button, "clicked",
G_CALLBACK (gtk_window_destroy), window);
G_CALLBACK (gtk_widget_destroy), window);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
return window;
}
+16 -16
View File
@@ -20,24 +20,23 @@ struct _VflGrid
G_DEFINE_TYPE (VflGrid, vfl_grid, GTK_TYPE_WIDGET)
static void
vfl_grid_dispose (GObject *object)
vfl_grid_destroy (GtkWidget *widget)
{
VflGrid *self = VFL_GRID (object);
VflGrid *self = VFL_GRID (widget);
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_clear_pointer (&self->button1, gtk_widget_destroy);
g_clear_pointer (&self->button2, gtk_widget_destroy);
g_clear_pointer (&self->button3, gtk_widget_destroy);
G_OBJECT_CLASS (vfl_grid_parent_class)->dispose (object);
GTK_WIDGET_CLASS (vfl_grid_parent_class)->destroy (widget);
}
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;
widget_class->destroy = vfl_grid_destroy;
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
}
@@ -132,34 +131,35 @@ do_constraints3 (GtkWidget *do_widget)
{
GtkWidget *header, *box, *grid, *button;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Constraints");
header = gtk_header_bar_new ();
gtk_header_bar_set_title (GTK_HEADER_BAR (header), "Constraints");
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
gtk_window_set_titlebar (GTK_WINDOW (window), header);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
gtk_window_set_child (GTK_WINDOW (window), box);
gtk_container_add (GTK_CONTAINER (window), box);
grid = g_object_new (vfl_grid_get_type (), NULL);
gtk_widget_set_hexpand (grid, TRUE);
gtk_widget_set_vexpand (grid, TRUE);
gtk_box_append (GTK_BOX (box), grid);
gtk_container_add (GTK_CONTAINER (box), grid);
button = gtk_button_new_with_label ("Close");
gtk_box_append (GTK_BOX (box), button);
gtk_container_add (GTK_CONTAINER (box), button);
gtk_widget_set_hexpand (grid, TRUE);
g_signal_connect_swapped (button, "clicked",
G_CALLBACK (gtk_window_destroy), window);
G_CALLBACK (gtk_widget_destroy), window);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
return window;
}
+13 -16
View File
@@ -9,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 *
@@ -28,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");
@@ -66,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;
}
+8 -11
View File
@@ -55,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 *
@@ -76,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,
@@ -95,9 +92,9 @@ do_css_basics (GtkWidget *do_widget)
provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
container = gtk_scrolled_window_new (NULL, NULL);
gtk_window_set_child (GTK_WINDOW (window), container);
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);
@@ -116,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;
}
+8 -9
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" },
@@ -79,7 +79,7 @@ setup_listbox (GtkBuilder *builder,
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;
}
+16 -19
View File
@@ -69,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 *
@@ -85,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,
@@ -132,10 +129,10 @@ do_css_multiplebgs (GtkWidget *do_widget)
provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
sw = gtk_scrolled_window_new (NULL, NULL);
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),
@@ -156,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;
}
+10 -13
View File
@@ -55,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 *
@@ -76,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,9 +99,9 @@ do_css_pixbufs (GtkWidget *do_widget)
provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
container = gtk_scrolled_window_new (NULL, NULL);
gtk_paned_set_end_child (GTK_PANED (paned), container);
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);
@@ -123,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;
}
+22 -22
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,17 +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_container_add (GTK_CONTAINER (paned), child);
text = gtk_text_buffer_new (NULL);
gtk_text_buffer_create_tag (text,
@@ -120,9 +120,9 @@ do_css_shadows (GtkWidget *do_widget)
provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
container = gtk_scrolled_window_new (NULL, NULL);
gtk_paned_set_end_child (GTK_PANED (paned), container);
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);
@@ -141,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;
}
+2 -2
View File
@@ -29,14 +29,14 @@ do_cursors (GtkWidget *do_widget)
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;
+37 -148
View File
@@ -656,10 +656,7 @@
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="margin-start">60</property>
<property name="margin-end">60</property>
<property name="margin-top">60</property>
<property name="margin-bottom">60</property>
<property name="margin">60</property>
<property name="spacing">10</property>
<property name="halign">center</property>
<child>
@@ -675,10 +672,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -735,10 +729,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -795,10 +786,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -868,10 +856,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -928,10 +913,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -988,10 +970,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -1048,10 +1027,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -1108,10 +1084,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -1181,10 +1154,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -1241,10 +1211,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -1301,10 +1268,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -1361,10 +1325,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -1434,10 +1395,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -1494,10 +1452,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -1554,10 +1509,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -1614,10 +1566,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -1674,10 +1623,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -1734,10 +1680,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -1794,10 +1737,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -1867,10 +1807,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -1927,10 +1864,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -1987,10 +1921,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -2047,10 +1978,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -2107,10 +2035,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -2167,10 +2092,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -2227,10 +2149,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -2287,10 +2206,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -2347,10 +2263,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -2407,10 +2320,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -2467,10 +2377,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -2527,10 +2434,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -2587,10 +2491,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -2647,10 +2548,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -2707,10 +2605,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -2780,10 +2675,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
@@ -2840,10 +2732,7 @@
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage">
+12 -18
View File
@@ -6,6 +6,7 @@
<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>
@@ -18,10 +19,6 @@
<gresource prefix="/builder">
<file>demo.ui</file>
</gresource>
<gresource prefix="/clipboard">
<file>demoimage.c</file>
<file>demoimage.h</file>
</gresource>
<gresource prefix="/css_accordion">
<file>css_accordion.css</file>
<file>reset.css</file>
@@ -114,10 +111,6 @@
<file>gtkfishbowl.c</file>
<file>gtkfishbowl.h</file>
</gresource>
<gresource prefix="/gears">
<file>gtkgears.c</file>
<file>gtkgears.h</file>
</gresource>
<gresource prefix="/iconscroll">
<file>iconscroll.ui</file>
</gresource>
@@ -138,9 +131,6 @@
<gresource prefix="/listview_weather">
<file compressed="true">listview_weather.txt</file>
</gresource>
<gresource prefix="/listview_colors">
<file compressed="true">color.names.txt</file>
</gresource>
<gresource prefix="/shortcuts">
<file>shortcuts.ui</file>
<file>shortcuts-builder.ui</file>
@@ -180,7 +170,9 @@
<file>awardview.c</file>
<file>assistant.c</file>
<file>builder.c</file>
<file>changedisplay.c</file>
<file>clipboard.c</file>
<file>colorsel.c</file>
<file>combobox.c</file>
<file>constraints.c</file>
<file>constraints2.c</file>
@@ -203,10 +195,10 @@
<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>headerbar.c</file>
@@ -219,7 +211,6 @@
<file>links.c</file>
<file>listbox.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>
@@ -227,6 +218,7 @@
<file>listview_weather.c</file>
<file>list_store.c</file>
<file>markup.c</file>
<file>menus.c</file>
<file>modelbutton.c</file>
<file>overlay.c</file>
<file>overlay2.c</file>
@@ -237,9 +229,9 @@
<file>paintable_mediastream.c</file>
<file>panes.c</file>
<file>password_entry.c</file>
<file>peg_solitaire.c</file>
<file>pickers.c</file>
<file>pixbufs.c</file>
<file>popover.c</file>
<file>printing.c</file>
<file>revealer.c</file>
<file>rotated_text.c</file>
@@ -247,7 +239,6 @@
<file>search_entry.c</file>
<file>search_entry2.c</file>
<file>shortcuts.c</file>
<file>shortcut_triggers.c</file>
<file>sizegroup.c</file>
<file>sidebar.c</file>
<file>sliding_puzzle.c</file>
@@ -277,6 +268,9 @@
<file>messages.txt</file>
<file>apple-red.png</file>
</gresource>
<gresource prefix="/popover">
<file>popover.ui</file>
</gresource>
<gresource prefix="/glarea">
<file>glarea-gl.fs.glsl</file>
<file>glarea-gl.vs.glsl</file>
@@ -310,6 +304,9 @@
<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>
@@ -339,7 +336,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>
+114 -83
View File
@@ -22,79 +22,9 @@
</row>
</data>
</object>
<menu id="menubar">
<submenu>
<attribute name="label" translatable="yes">_File</attribute>
<section>
<item>
<attribute name="label" translatable="yes">_New</attribute>
<attribute name="action">win.new</attribute>
<attribute name="accel">&lt;Control&gt;n</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Open</attribute>
<attribute name="action">win.open</attribute>
<attribute name="accel">&lt;Control&gt;o</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Save</attribute>
<attribute name="action">win.save</attribute>
<attribute name="accel">&lt;Control&gt;s</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Save _As</attribute>
<attribute name="action">win.save-as</attribute>
<attribute name="accel">&lt;Control&gt;q</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">_Quit</attribute>
<attribute name="action">win.quit</attribute>
<attribute name="accel">&lt;Control&gt;&lt;Shift&gt;s</attribute>
</item>
</section>
</submenu>
<submenu>
<attribute name="label" translatable="yes">_Edit</attribute>
<section>
<item>
<attribute name="label" translatable="yes">_Copy</attribute>
<attribute name="action">win.copy</attribute>
<attribute name="accel">&lt;Control&gt;c</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Cut</attribute>
<attribute name="action">win.cut</attribute>
<attribute name="accel">&lt;Control&gt;x</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Paste</attribute>
<attribute name="action">win.paste</attribute>
<attribute name="accel">&lt;Control&gt;v</attribute>
</item>
</section>
</submenu>
<submenu>
<attribute name="label" translatable="yes">_Help</attribute>
<section>
<item>
<attribute name="label" translatable="yes">_Help</attribute>
<attribute name="action">win.help</attribute>
<attribute name="accel">F1</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_About</attribute>
<attribute name="action">win.about</attribute>
<attribute name="accel">F7</attribute>
</item>
</section>
</submenu>
</menu>
<object class="GtkAboutDialog" id="aboutdialog1">
<property name="program-name" translatable="yes">Builder demo</property>
<property name="logo-icon-name" translatable="yes">gtk3-demo</property>
<property name="modal">True</property>
<accessibility>
<relation target="window1" type="subwindow-of"/>
</accessibility>
@@ -107,57 +37,159 @@
<object class="GtkBox" id="vbox1">
<property name="orientation">vertical</property>
<child>
<object class="GtkPopoverMenuBar" id="menubar1">
<property name="menu-model">menubar</property>
<object class="GtkMenuBar" id="menubar1">
<child internal-child="accessible">
<object class="AtkObject" id="a11y-menubar">
<property name="AtkObject::accessible-name">The menubar</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="label" translatable="yes">_File</property>
<property name="use-underline">1</property>
<child type="submenu">
<object class="GtkMenu">
<child>
<object class="GtkMenuItem" id="new_item">
<property name="label" translatable="yes">_New</property>
<property name="use-underline">1</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="open_item">
<property name="label" translatable="yes">_Open</property>
<property name="use-underline">1</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="save_item">
<property name="label" translatable="yes">_Save</property>
<property name="use-underline">1</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="save_as_item">
<property name="label" translatable="yes">Save _As</property>
<property name="use-underline">1</property>
<accelerator key="s" modifiers="primary | shift-mask" signal="activate"/>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem"/>
</child>
<child>
<object class="GtkMenuItem" id="quit_item">
<property name="label" translatable="yes">_Quit</property>
<property name="use-underline">1</property>
<property name="action-name">win.quit</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="label" translatable="yes">_Edit</property>
<property name="use-underline">1</property>
<child type="submenu">
<object class="GtkMenu">
<child>
<object class="GtkMenuItem" id="copy_item">
<property name="label" translatable="yes">_Copy</property>
<property name="use-underline">1</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="cut_item">
<property name="label" translatable="yes">_Cut</property>
<property name="use-underline">1</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="paste_item">
<property name="label" translatable="yes">_Paste</property>
<property name="use-underline">1</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="label" translatable="yes">_Help</property>
<property name="use-underline">1</property>
<child type="submenu">
<object class="GtkMenu">
<child>
<object class="GtkMenuItem" id="help_item">
<property name="label" translatable="yes">_Help</property>
<property name="use-underline">1</property>
<property name="action-name">win.help</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="about_item">
<property name="label" translatable="yes">_About</property>
<property name="use-underline">1</property>
<property name="action-name">win.about</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="toolbar1">
<object class="GtkToolbar" id="toolbar1">
<child internal-child="accessible">
<object class="AtkObject" id="a11y-toolbar">
<property name="AtkObject::accessible-name">The toolbar</property>
</object>
</child>
<child>
<object class="GtkButton">
<object class="GtkToolButton">
<property name="label" translatable="yes">New</property>
<property name="tooltip-text" translatable="yes">Create a new file</property>
<property name="icon-name">document-new</property>
</object>
</child>
<child>
<object class="GtkButton">
<object class="GtkToolButton">
<property name="label" translatable="yes">Open</property>
<property name="tooltip-text" translatable="yes">Open a file</property>
<property name="icon-name">document-open</property>
</object>
</child>
<child>
<object class="GtkButton">
<object class="GtkToolButton">
<property name="label" translatable="yes">Save</property>
<property name="tooltip-text" translatable="yes">Save a file</property>
<property name="icon-name">document-save</property>
<property name="is-important">1</property>
</object>
</child>
<child>
<object class="GtkSeparator"/>
<object class="GtkSeparatorToolItem"/>
</child>
<child>
<object class="GtkButton">
<object class="GtkToolButton">
<property name="label" translatable="yes">Copy</property>
<property name="tooltip-text" translatable="yes">Copy selected object into the clipboard</property>
<property name="icon-name">edit-copy</property>
</object>
</child>
<child>
<object class="GtkButton">
<object class="GtkToolButton">
<property name="label" translatable="yes">Cut</property>
<property name="tooltip-text" translatable="yes">Cut selected object into the clipboard</property>
<property name="icon-name">edit-cut</property>
</object>
</child>
<child>
<object class="GtkButton">
<object class="GtkToolButton">
<property name="label" translatable="yes">Paste</property>
<property name="tooltip-text" translatable="yes">Paste object from the clipboard</property>
<property name="icon-name">edit-paste</property>
@@ -167,9 +199,8 @@
</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>
-259
View File
@@ -1,259 +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 gchar *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
drag_begin (GtkDragSource *source,
GdkDrag *drag,
gpointer data)
{
GtkWidget *widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (source));
DemoImage *demo = DEMO_IMAGE (widget);
GdkPaintable *paintable;
paintable = get_image_paintable (GTK_IMAGE (demo->image));
if (paintable)
{
gtk_drag_icon_set_from_paintable (drag, paintable, -2, -2);
g_object_unref (paintable);
}
}
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
+9 -9
View File
@@ -49,7 +49,7 @@ demo_tagged_entry_init (DemoTaggedEntry *entry)
gtk_widget_set_vexpand (priv->entry, TRUE);
gtk_widget_set_hexpand (priv->box, FALSE);
gtk_widget_set_vexpand (priv->box, FALSE);
gtk_box_append (GTK_BOX (priv->box), priv->entry);
gtk_container_add (GTK_CONTAINER (priv->box), priv->entry);
gtk_editable_init_delegate (GTK_EDITABLE (entry));
}
@@ -188,7 +188,7 @@ demo_tagged_entry_add_tag (DemoTaggedEntry *entry,
g_return_if_fail (DEMO_IS_TAGGED_ENTRY (entry));
gtk_box_append (GTK_BOX (priv->box), tag);
gtk_container_add (GTK_CONTAINER (priv->box), tag);
}
void
@@ -201,7 +201,7 @@ demo_tagged_entry_insert_tag_after (DemoTaggedEntry *entry,
g_return_if_fail (DEMO_IS_TAGGED_ENTRY (entry));
if (sibling == NULL)
gtk_box_append (GTK_BOX (priv->box), tag);
gtk_container_add (GTK_CONTAINER (priv->box), tag);
else
gtk_box_insert_child_after (GTK_BOX (priv->box), tag, sibling);
}
@@ -214,7 +214,7 @@ demo_tagged_entry_remove_tag (DemoTaggedEntry *entry,
g_return_if_fail (DEMO_IS_TAGGED_ENTRY (entry));
gtk_box_remove (GTK_BOX (priv->box), tag);
gtk_container_remove (GTK_CONTAINER (priv->box), tag);
}
struct _DemoTaggedEntryTag
@@ -268,7 +268,7 @@ demo_tagged_entry_tag_init (DemoTaggedEntryTag *tag)
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);
@@ -460,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)
@@ -469,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_box_append (GTK_BOX (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);
}
+29 -61
View File
@@ -25,36 +25,11 @@ message_dialog_clicked (GtkButton *button,
"number of times:");
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
"%d", i);
g_signal_connect (dialog, "response", G_CALLBACK (gtk_window_destroy), NULL);
gtk_widget_show (dialog);
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)
@@ -67,7 +42,7 @@ interactive_dialog_clicked (GtkButton *button,
GtkWidget *local_entry1;
GtkWidget *local_entry2;
GtkWidget *label;
ResponseData *data;
gint response;
dialog = gtk_dialog_new_with_buttons ("Interactive Dialog",
GTK_WINDOW (window),
@@ -81,16 +56,16 @@ interactive_dialog_clicked (GtkButton *button,
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
gtk_box_append (GTK_BOX (content_area), hbox);
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_box_append (GTK_BOX (hbox), image);
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_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);
local_entry1 = gtk_entry_new ();
@@ -106,18 +81,15 @@ 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 *
@@ -133,51 +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 and Message Boxes");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
frame = gtk_frame_new ("Dialogs");
gtk_widget_set_margin_start (frame, 8);
gtk_widget_set_margin_end (frame, 8);
gtk_widget_set_margin_top (frame, 8);
gtk_widget_set_margin_bottom (frame, 8);
gtk_window_set_child (GTK_WINDOW (window), frame);
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_frame_set_child (GTK_FRAME (frame), 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);
@@ -196,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;
}
+230 -469
View File
@@ -1,418 +1,235 @@
/* Drag-and-Drop
*
* This demo shows dragging colors and widgets.
* The items in this demo can be moved, recolored
* and rotated.
* I can't believe its not glade!
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <string.h>
G_DECLARE_FINAL_TYPE (CanvasItem, canvas_item, CANVAS, ITEM, GtkWidget)
struct _CanvasItem {
GtkWidget parent;
GtkWidget *fixed;
GtkWidget *label;
double r;
double angle;
double delta;
GtkWidget *editor;
typedef struct _GtkDemoWidget GtkDemoWidget;
struct _GtkDemoWidget
{
GType type;
union {
char *text;
gboolean active;
};
};
struct _CanvasItemClass {
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE (CanvasItem, canvas_item, GTK_TYPE_WIDGET)
static int n_items = 0;
static void
set_color (CanvasItem *item,
GdkRGBA *color)
static gpointer
copy_demo_widget (gpointer data)
{
char *css;
char *str;
GtkStyleContext *context;
GtkCssProvider *provider;
GtkDemoWidget *demo = g_memdup (data, sizeof (GtkDemoWidget));
str = gdk_rgba_to_string (color);
css = g_strdup_printf ("* { background: %s; padding: 10px; margin: 1px; }", str);
if (demo->type == GTK_TYPE_LABEL)
demo->text = g_strdup (demo->text);
context = gtk_widget_get_style_context (item->label);
provider = g_object_get_data (G_OBJECT (context), "style-provider");
if (provider)
gtk_style_context_remove_provider (context, GTK_STYLE_PROVIDER (provider));
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_data (provider, css, -1);
gtk_style_context_add_provider (gtk_widget_get_style_context (item->label), GTK_STYLE_PROVIDER (provider), 800);
g_object_set_data_full (G_OBJECT (context), "style-provider", provider, g_object_unref);
g_free (str);
g_free (css);
}
static gboolean
item_drag_drop (GtkDropTarget *dest,
const GValue *value,
double x,
double y)
{
GtkWidget *label = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest));
CanvasItem *item = CANVAS_ITEM (gtk_widget_get_parent (gtk_widget_get_parent (label)));
set_color (item, g_value_get_boxed (value));
return TRUE;
return demo;
}
static void
apply_transform (CanvasItem *item)
free_demo_widget (gpointer data)
{
GskTransform *transform;
double x, y;
GtkDemoWidget *demo = data;
x = gtk_widget_get_allocated_width (item->label) / 2.0;
y = gtk_widget_get_allocated_height (item->label) / 2.0;
item->r = sqrt (x*x + y*y);
if (demo->type == GTK_TYPE_LABEL)
g_free (demo->text);
transform = gsk_transform_translate (
gsk_transform_rotate (
gsk_transform_translate (NULL,
&(graphene_point_t) { item->r, item->r }),
item->angle + item->delta),
&(graphene_point_t) { - x, - y });
gtk_fixed_set_child_transform (GTK_FIXED (item->fixed), item->label, transform);
gsk_transform_unref (transform);
g_free (demo);
}
static void
angle_changed (GtkGestureRotate *gesture,
double angle,
double delta)
#define GTK_TYPE_DEMO_WIDGET (gtk_demo_widget_get_type ())
G_DEFINE_BOXED_TYPE (GtkDemoWidget, gtk_demo_widget, copy_demo_widget, free_demo_widget)
static GtkDemoWidget *
serialize_widget (GtkWidget *widget)
{
CanvasItem *item = CANVAS_ITEM (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture)));
GtkDemoWidget *demo;
item->delta = angle / M_PI * 180.0;
demo = g_new0 (GtkDemoWidget, 1);
demo->type = G_OBJECT_TYPE (widget);
apply_transform (item);
}
if (GTK_IS_LABEL (widget))
{
demo->text = g_strdup (gtk_label_get_text (GTK_LABEL (widget)));
}
else if (GTK_IS_SPINNER (widget))
{
g_object_get (widget, "active", &demo->active, NULL);
}
else
{
g_print ("Type %s not supported\n", g_type_name (demo->type));
}
static void
rotate_done (GtkGesture *gesture)
{
CanvasItem *item = CANVAS_ITEM (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture)));
item->angle = item->angle + item->delta;
item->delta = 0;
}
static void
click_done (GtkGesture *gesture)
{
GtkWidget *item = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
GtkWidget *canvas = gtk_widget_get_parent (item);
GtkWidget *last_child;
last_child = gtk_widget_get_last_child (canvas);
if (item != last_child)
gtk_widget_insert_after (item, canvas, last_child);
}
static void
canvas_item_init (CanvasItem *item)
{
char *text;
char *id;
GdkRGBA rgba;
GtkDropTarget *dest;
GtkGesture *gesture;
n_items++;
text = g_strdup_printf ("Item %d", n_items);
item->label = gtk_label_new (text);
g_free (text);
item->fixed = gtk_fixed_new ();
gtk_widget_set_parent (item->fixed, GTK_WIDGET (item));
gtk_fixed_put (GTK_FIXED (item->fixed), item->label, 0, 0);
gtk_widget_add_css_class (item->label, "frame");
id = g_strdup_printf ("item%d", n_items);
gtk_widget_set_name (item->label, id);
g_free (id);
gdk_rgba_parse (&rgba, "yellow");
set_color (item, &rgba);
item->angle = 0;
dest = gtk_drop_target_new (GDK_TYPE_RGBA, GDK_ACTION_COPY);
g_signal_connect (dest, "drop", G_CALLBACK (item_drag_drop), NULL);
gtk_widget_add_controller (GTK_WIDGET (item->label), GTK_EVENT_CONTROLLER (dest));
gesture = gtk_gesture_rotate_new ();
g_signal_connect (gesture, "angle-changed", G_CALLBACK (angle_changed), NULL);
g_signal_connect (gesture, "end", G_CALLBACK (rotate_done), NULL);
gtk_widget_add_controller (GTK_WIDGET (item), GTK_EVENT_CONTROLLER (gesture));
gesture = gtk_gesture_click_new ();
g_signal_connect (gesture, "released", G_CALLBACK (click_done), NULL);
gtk_widget_add_controller (GTK_WIDGET (item), GTK_EVENT_CONTROLLER (gesture));
}
static void
canvas_item_dispose (GObject *object)
{
CanvasItem *item = CANVAS_ITEM (object);
g_clear_pointer (&item->fixed, gtk_widget_unparent);
g_clear_pointer (&item->editor, gtk_widget_unparent);
G_OBJECT_CLASS (canvas_item_parent_class)->dispose (object);
}
static void
canvas_item_map (GtkWidget *widget)
{
CanvasItem *item = CANVAS_ITEM (widget);
GTK_WIDGET_CLASS (canvas_item_parent_class)->map (widget);
apply_transform (item);
}
static void
canvas_item_class_init (CanvasItemClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->dispose = canvas_item_dispose;
widget_class->map = canvas_item_map;
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_set_css_name (widget_class, "item");
return demo;
}
static GtkWidget *
canvas_item_new (void)
deserialize_widget (GtkDemoWidget *demo)
{
CanvasItem *item = g_object_new (canvas_item_get_type (), NULL);
GtkWidget *widget = NULL;
return GTK_WIDGET (item);
if (demo->type == GTK_TYPE_LABEL)
{
widget = gtk_label_new (demo->text);
}
else if (demo->type == GTK_TYPE_SPINNER)
{
widget = g_object_new (demo->type, "active", demo->active, NULL);
gtk_style_context_add_class (gtk_widget_get_style_context (widget), "demo");
}
else
{
g_print ("Type %s not supported\n", g_type_name (demo->type));
}
return widget;
}
static GdkPaintable *
canvas_item_get_drag_icon (CanvasItem *item)
{
return gtk_widget_paintable_new (item->fixed);
}
static double pos_x, pos_y;
static gboolean
canvas_item_is_editing (CanvasItem *item)
static void
new_label_cb (GtkMenuItem *item,
gpointer data)
{
return item->editor != NULL;
GtkFixed *fixed = data;
GtkWidget *widget;
widget = gtk_label_new ("Label");
gtk_fixed_put (fixed, widget, pos_x, pos_y);
}
static void
scale_changed (GtkRange *range,
CanvasItem *item)
new_spinner_cb (GtkMenuItem *item,
gpointer data)
{
item->angle = gtk_range_get_value (range);
apply_transform (item);
GtkFixed *fixed = data;
GtkWidget *widget;
widget = gtk_spinner_new ();
gtk_style_context_add_class (gtk_widget_get_style_context (widget), "demo");
gtk_spinner_start (GTK_SPINNER (widget));
gtk_fixed_put (fixed, widget, pos_x, pos_y);
}
static void
text_changed (GtkEditable *editable,
GParamSpec *pspec,
CanvasItem *item)
copy_cb (GtkWidget *child)
{
gtk_label_set_text (GTK_LABEL (item->label), gtk_editable_get_text (editable));
apply_transform (item);
GdkClipboard *clipboard;
GtkDemoWidget *demo;
g_print ("Copy %s\n", G_OBJECT_TYPE_NAME (child));
demo = serialize_widget (child);
clipboard = gdk_display_get_clipboard (gdk_display_get_default ());
gdk_clipboard_set (clipboard, GTK_TYPE_DEMO_WIDGET, demo);
}
static void
canvas_item_stop_editing (CanvasItem *item)
delete_cb (GtkWidget *child)
{
GtkWidget *scale;
if (!item->editor)
return;
scale = gtk_widget_get_last_child (item->editor);
g_signal_handlers_disconnect_by_func (scale, scale_changed, item);
gtk_fixed_remove (GTK_FIXED (gtk_widget_get_parent (item->editor)), item->editor);
item->editor = NULL;
gtk_widget_destroy (child);
}
static void
canvas_item_start_editing (CanvasItem *item)
cut_cb (GtkWidget *child)
{
GtkWidget *canvas = gtk_widget_get_parent (GTK_WIDGET (item));
GtkWidget *entry;
GtkWidget *scale;
double x, y;
if (item->editor)
return;
item->editor = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
entry = gtk_entry_new ();
gtk_editable_set_text (GTK_EDITABLE (entry),
gtk_label_get_text (GTK_LABEL (item->label)));
gtk_editable_set_width_chars (GTK_EDITABLE (entry), 12);
g_signal_connect (entry, "notify::text", G_CALLBACK (text_changed), item);
g_signal_connect_swapped (entry, "activate", G_CALLBACK (canvas_item_stop_editing), item);
gtk_box_append (GTK_BOX (item->editor), entry);
scale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0, 360, 1);
gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE);
gtk_range_set_value (GTK_RANGE (scale), fmod (item->angle, 360));
g_signal_connect (scale, "value-changed", G_CALLBACK (scale_changed), item);
gtk_box_append (GTK_BOX (item->editor), scale);
gtk_widget_translate_coordinates (GTK_WIDGET (item), canvas, 0, 0, &x, &y);
gtk_fixed_put (GTK_FIXED (canvas), item->editor, x, y + 2 * item->r);
gtk_widget_grab_focus (entry);
}
static GdkContentProvider *
prepare (GtkDragSource *source,
double x,
double y)
{
GtkWidget *canvas;
GtkWidget *item;
canvas = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (source));
item = gtk_widget_pick (canvas, x, y, GTK_PICK_DEFAULT);
item = gtk_widget_get_ancestor (item, canvas_item_get_type ());
if (!item)
return NULL;
g_object_set_data (G_OBJECT (canvas), "dragged-item", item);
return gdk_content_provider_new_typed (GTK_TYPE_WIDGET, item);
copy_cb (child);
delete_cb (child);
}
static void
drag_begin (GtkDragSource *source,
GdkDrag *drag)
value_read (GObject *source,
GAsyncResult *res,
gpointer data)
{
GtkWidget *canvas;
CanvasItem *item;
GdkPaintable *paintable;
GdkClipboard *clipboard = GDK_CLIPBOARD (source);
GError *error = NULL;
const GValue *value;
GtkDemoWidget *demo;
GtkWidget *widget = NULL;
canvas = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (source));
item = CANVAS_ITEM (g_object_get_data (G_OBJECT (canvas), "dragged-item"));
value = gdk_clipboard_read_value_finish (clipboard, res, &error);
paintable = canvas_item_get_drag_icon (item);
gtk_drag_source_set_icon (source, paintable, item->r, item->r);
g_object_unref (paintable);
if (value == NULL)
{
g_print ("error: %s\n", error->message);
g_error_free (error);
return;
}
gtk_widget_set_opacity (GTK_WIDGET (item), 0.3);
if (!G_VALUE_HOLDS (value, GTK_TYPE_DEMO_WIDGET))
{
g_print ("can't handle clipboard contents\n");
return;
}
demo = g_value_get_boxed (value);
widget = deserialize_widget (demo);
gtk_fixed_put (GTK_FIXED (data), widget, pos_x, pos_y);
}
static void
drag_end (GtkDragSource *source,
GdkDrag *drag)
paste_cb (GtkWidget *fixed)
{
GtkWidget *canvas;
GtkWidget *item;
GdkClipboard *clipboard;
canvas = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (source));
item = g_object_get_data (G_OBJECT (canvas), "dragged-item");
g_object_set_data (G_OBJECT (canvas), "dragged-item", NULL);
gtk_widget_set_opacity (item, 1.0);
}
static gboolean
drag_cancel (GtkDragSource *source,
GdkDrag *drag,
GdkDragCancelReason reason)
{
return FALSE;
}
static gboolean
drag_drop (GtkDropTarget *target,
const GValue *value,
double x,
double y)
{
CanvasItem *item;
GtkWidget *canvas;
GtkWidget *last_child;
item = g_value_get_object (value);
canvas = gtk_widget_get_parent (GTK_WIDGET (item));
last_child = gtk_widget_get_last_child (canvas);
if (GTK_WIDGET (item) != last_child)
gtk_widget_insert_after (GTK_WIDGET (item), canvas, last_child);
gtk_fixed_move (GTK_FIXED (canvas), GTK_WIDGET (item), x - item->r, y - item->r);
return TRUE;
clipboard = gdk_display_get_clipboard (gdk_display_get_default ());
if (gdk_content_formats_contain_gtype (gdk_clipboard_get_formats (clipboard), GTK_TYPE_DEMO_WIDGET))
{
g_print ("Paste %s\n", g_type_name (GTK_TYPE_DEMO_WIDGET));
gdk_clipboard_read_value_async (clipboard, GTK_TYPE_DEMO_WIDGET, 0, NULL, value_read, fixed);
}
else
g_print ("Don't know how to handle clipboard contents\n");
}
static void
new_item_cb (GtkWidget *button, gpointer data)
edit_label_done (GtkWidget *entry, gpointer data)
{
GtkWidget *canvas = data;
GtkWidget *popover;
GtkWidget *item;
GdkRectangle rect;
GtkWidget *fixed = gtk_widget_get_parent (entry);
GtkWidget *label;
int x, y;
popover = gtk_widget_get_ancestor (button, GTK_TYPE_POPOVER);
gtk_popover_get_pointing_to (GTK_POPOVER (popover), &rect);
gtk_fixed_get_child_position (GTK_FIXED (fixed), entry, &x, &y);
item = canvas_item_new ();
gtk_fixed_put (GTK_FIXED (canvas), item, rect.x, rect.y);
apply_transform (CANVAS_ITEM (item));
label = GTK_WIDGET (g_object_get_data (G_OBJECT (entry), "label"));
gtk_label_set_text (GTK_LABEL (label), gtk_editable_get_text (GTK_EDITABLE (entry)));
gtk_popover_popdown (GTK_POPOVER (gtk_widget_get_ancestor (button, GTK_TYPE_POPOVER)));
gtk_widget_destroy (entry);
}
static void
edit_cb (GtkWidget *button, GtkWidget *child)
edit_cb (GtkWidget *child)
{
CanvasItem *item = CANVAS_ITEM (child);
GtkWidget *fixed = gtk_widget_get_parent (child);
int x, y;
if (button)
gtk_popover_popdown (GTK_POPOVER (gtk_widget_get_ancestor (button, GTK_TYPE_POPOVER)));
gtk_fixed_get_child_position (GTK_FIXED (fixed), child, &x, &y);
if (!canvas_item_is_editing (item))
canvas_item_start_editing (item);
}
if (GTK_IS_LABEL (child))
{
GtkWidget *entry = gtk_entry_new ();
static void
delete_cb (GtkWidget *button, GtkWidget *child)
{
GtkWidget *canvas = gtk_widget_get_parent (child);
g_object_set_data (G_OBJECT (entry), "label", child);
gtk_fixed_remove (GTK_FIXED (canvas), child);
gtk_editable_set_text (GTK_EDITABLE (entry), gtk_label_get_text (GTK_LABEL (child)));
g_signal_connect (entry, "activate", G_CALLBACK (edit_label_done), NULL);
gtk_fixed_put (GTK_FIXED (fixed), entry, x, y);
gtk_widget_grab_focus (entry);
}
else if (GTK_IS_SPINNER (child))
{
gboolean active;
gtk_popover_popdown (GTK_POPOVER (gtk_widget_get_ancestor (button, GTK_TYPE_POPOVER)));
g_object_get (child, "active", &active, NULL);
g_object_set (child, "active", !active, NULL);
}
}
static void
@@ -427,45 +244,68 @@ pressed_cb (GtkGesture *gesture,
widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
child = gtk_widget_pick (widget, x, y, GTK_PICK_DEFAULT);
child = gtk_widget_get_ancestor (child, canvas_item_get_type ());
if (gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture)) == GDK_BUTTON_SECONDARY)
{
GdkRectangle rect;
GtkWidget *menu;
GtkWidget *box;
GtkWidget *item;
GdkClipboard *clipboard;
menu = gtk_popover_new ();
gtk_widget_set_parent (menu, widget);
gtk_popover_set_has_arrow (GTK_POPOVER (menu), FALSE);
gtk_popover_set_pointing_to (GTK_POPOVER (menu), &(GdkRectangle){ x, y, 1, 1});
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_popover_set_child (GTK_POPOVER (menu), box);
pos_x = x;
pos_y = y;
item = gtk_button_new_with_label ("New");
gtk_button_set_has_frame (GTK_BUTTON (item), FALSE);
g_signal_connect (item, "clicked", G_CALLBACK (new_item_cb), widget);
gtk_box_append (GTK_BOX (box), item);
menu = gtk_menu_new ();
item = gtk_menu_item_new_with_label ("New Label");
g_signal_connect (item, "activate", G_CALLBACK (new_label_cb), widget);
gtk_container_add (GTK_CONTAINER (menu), item);
item = gtk_menu_item_new_with_label ("New Spinner");
g_signal_connect (item, "activate", G_CALLBACK (new_spinner_cb), widget);
gtk_container_add (GTK_CONTAINER (menu), item);
item = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
gtk_box_append (GTK_BOX (box), item);
item = gtk_separator_menu_item_new ();
gtk_container_add (GTK_CONTAINER (menu), item);
item = gtk_button_new_with_label ("Edit");
gtk_button_set_has_frame (GTK_BUTTON (item), FALSE);
item = gtk_menu_item_new_with_label ("Edit");
gtk_widget_set_sensitive (item, child != NULL && child != widget);
g_signal_connect (item, "clicked", G_CALLBACK (edit_cb), child);
gtk_box_append (GTK_BOX (box), item);
g_signal_connect_swapped (item, "activate", G_CALLBACK (edit_cb), child);
gtk_container_add (GTK_CONTAINER (menu), item);
item = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
gtk_box_append (GTK_BOX (box), item);
item = gtk_separator_menu_item_new ();
gtk_container_add (GTK_CONTAINER (menu), item);
item = gtk_button_new_with_label ("Delete");
gtk_button_set_has_frame (GTK_BUTTON (item), FALSE);
item = gtk_menu_item_new_with_label ("Cut");
gtk_widget_set_sensitive (item, child != NULL && child != widget);
g_signal_connect (item, "clicked", G_CALLBACK (delete_cb), child);
gtk_box_append (GTK_BOX (box), item);
g_signal_connect_swapped (item, "activate", G_CALLBACK (cut_cb), child);
gtk_container_add (GTK_CONTAINER (menu), item);
item = gtk_menu_item_new_with_label ("Copy");
gtk_widget_set_sensitive (item, child != NULL && child != widget);
g_signal_connect_swapped (item, "activate", G_CALLBACK (copy_cb), child);
gtk_container_add (GTK_CONTAINER (menu), item);
item = gtk_menu_item_new_with_label ("Paste");
clipboard = gdk_display_get_clipboard (gdk_display_get_default ());
gtk_widget_set_sensitive (item,
gdk_content_formats_contain_gtype (gdk_clipboard_get_formats (clipboard), GTK_TYPE_DEMO_WIDGET));
g_signal_connect_swapped (item, "activate", G_CALLBACK (paste_cb), widget);
gtk_container_add (GTK_CONTAINER (menu), item);
item = gtk_menu_item_new_with_label ("Delete");
gtk_widget_set_sensitive (item, child != NULL && child != widget);
g_signal_connect_swapped (item, "activate", G_CALLBACK (delete_cb), child);
gtk_container_add (GTK_CONTAINER (menu), item);
gtk_popover_popup (GTK_POPOVER (menu));
rect.x = x;
rect.y = y;
rect.width = 0;
rect.height = 0;
gtk_menu_popup_at_rect (GTK_MENU (menu),
gtk_native_get_surface (gtk_widget_get_native (widget)),
&rect,
GDK_GRAVITY_NORTH_WEST,
GDK_GRAVITY_NORTH_WEST,
NULL);
return;
}
}
@@ -478,57 +318,17 @@ released_cb (GtkGesture *gesture,
{
GtkWidget *widget;
GtkWidget *child;
CanvasItem *item;
widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
child = gtk_widget_pick (widget, x, y, 0);
item = (CanvasItem *)gtk_widget_get_ancestor (child, canvas_item_get_type ());
if (!item)
return;
if (gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture)) == GDK_BUTTON_PRIMARY)
{
if (canvas_item_is_editing (item))
canvas_item_stop_editing (item);
else
canvas_item_start_editing (item);
if (child != NULL && child != widget)
edit_cb (child);
}
}
static GtkWidget *
canvas_new (void)
{
GtkWidget *canvas;
GtkDragSource *source;
GtkDropTarget *dest;
GtkGesture *gesture;
canvas = gtk_fixed_new ();
gtk_widget_set_hexpand (canvas, TRUE);
gtk_widget_set_vexpand (canvas, TRUE);
gtk_widget_add_css_class (canvas, "frame");
source = gtk_drag_source_new ();
gtk_drag_source_set_actions (source, GDK_ACTION_MOVE);
g_signal_connect (source, "prepare", G_CALLBACK (prepare), NULL);
g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), NULL);
g_signal_connect (source, "drag-end", G_CALLBACK (drag_end), NULL);
g_signal_connect (source, "drag-cancel", G_CALLBACK (drag_cancel), NULL);
gtk_widget_add_controller (canvas, GTK_EVENT_CONTROLLER (source));
dest = gtk_drop_target_new (GTK_TYPE_WIDGET, GDK_ACTION_MOVE);
g_signal_connect (dest, "drop", G_CALLBACK (drag_drop), NULL);
gtk_widget_add_controller (canvas, GTK_EVENT_CONTROLLER (dest));
gesture = gtk_gesture_click_new ();
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), 0);
g_signal_connect (gesture, "pressed", G_CALLBACK (pressed_cb), NULL);
g_signal_connect (gesture, "released", G_CALLBACK (released_cb), NULL);
gtk_widget_add_controller (canvas, GTK_EVENT_CONTROLLER (gesture));
return canvas;
}
static GtkWidget *window = NULL;
GtkWidget *
@@ -536,82 +336,43 @@ do_dnd (GtkWidget *do_widget)
{
if (!window)
{
GtkWidget *button;
GtkWidget *sw;
GtkWidget *canvas;
GtkWidget *box, *box2, *box3;
const char *colors[] = {
"red", "green", "blue", "magenta", "orange", "gray", "black", "yellow",
"white", "gray", "brown", "pink", "cyan", "bisque", "gold", "maroon",
"navy", "orchid", "olive", "peru", "salmon", "silver", "wheat",
NULL
};
int i;
int x, y;
GtkWidget *vbox, *fixed;
GtkGesture *multipress;
GtkCssProvider *provider;
button = gtk_color_button_new ();
g_object_unref (g_object_ref_sink (button));
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Drag-and-Drop");
gtk_window_set_default_size (GTK_WINDOW (window), 640, 480);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
gtk_window_set_title (GTK_WINDOW (window), "Drag-and-drop");
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_window_set_child (GTK_WINDOW (window), box);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_append (GTK_BOX (box), box2);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add (GTK_CONTAINER (window), vbox);
canvas = canvas_new ();
gtk_box_append (GTK_BOX (box2), canvas);
fixed = gtk_fixed_new ();
gtk_container_add (GTK_CONTAINER (vbox), fixed);
gtk_widget_set_hexpand (fixed, TRUE);
gtk_widget_set_vexpand (fixed, TRUE);
n_items = 0;
multipress = gtk_gesture_click_new ();
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (multipress), 0);
g_signal_connect (multipress, "pressed", G_CALLBACK (pressed_cb), NULL);
g_signal_connect (multipress, "released", G_CALLBACK (released_cb), NULL);
gtk_widget_add_controller (fixed, GTK_EVENT_CONTROLLER (multipress));
x = y = 40;
for (i = 0; i < 4; i++)
{
GtkWidget *item;
item = canvas_item_new ();
gtk_fixed_put (GTK_FIXED (canvas), item, x, y);
apply_transform (CANVAS_ITEM (item));
x += 150;
y += 100;
}
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_NEVER);
gtk_box_append (GTK_BOX (box), sw);
box3 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_add_css_class (box3, "linked");
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), box3);
for (i = 0; colors[i]; i++)
{
GdkRGBA rgba;
GtkWidget *swatch;
gdk_rgba_parse (&rgba, colors[i]);
swatch = g_object_new (g_type_from_name ("GtkColorSwatch"),
"rgba", &rgba,
"selectable", FALSE,
NULL);
gtk_box_append (GTK_BOX (box3), swatch);
}
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider, "/dnd/dnd.css");
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
800);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
return window;
}
+3
View File
@@ -0,0 +1,3 @@
spinner.demo {
opacity: 1;
}
+55 -172
View File
@@ -42,9 +42,7 @@ create_surface (GtkWidget *widget)
}
static void
scribble_resize (GtkWidget *widget,
int width,
int height)
scribble_size_allocate (GtkWidget *widget)
{
create_surface (widget);
}
@@ -125,164 +123,49 @@ drag_end (GtkGestureDrag *gesture,
}
static void
oval_path (cairo_t *cr,
double xc, double yc,
double xr, double yr)
checkerboard_draw (GtkDrawingArea *da,
cairo_t *cr,
int width,
int height,
gpointer data)
{
cairo_save (cr);
gint i, j, xcount, ycount;
cairo_translate (cr, xc, yc);
cairo_scale (cr, 1.0, yr / xr);
cairo_move_to (cr, xr, 0.0);
cairo_arc (cr,
0, 0,
xr,
0, 2 * G_PI);
cairo_close_path (cr);
#define CHECK_SIZE 10
#define SPACING 2
cairo_restore (cr);
}
/* At the start of a draw handler, a clip region has been set on
* the Cairo context, and the contents have been cleared to the
* widget's background color. The docs for
* gdk_surface_begin_paint_region() give more details on how this
* works.
*/
/* Fill the given area with checks in the standard style
* for showing compositing effects.
*
* It would make sense to do this as a repeating surface,
* but most implementations of RENDER currently have broken
* implementations of repeat + transform, even when the
* transform is a translation.
*/
static void
fill_checks (cairo_t *cr,
int x, int y,
int width, int height)
{
int i, j;
#define CHECK_SIZE 16
cairo_rectangle (cr, x, y, width, height);
cairo_set_source_rgb (cr, 0.4, 0.4, 0.4);
cairo_fill (cr);
/* Only works for CHECK_SIZE a power of 2 */
j = x & (-CHECK_SIZE);
for (; j < height; j += CHECK_SIZE)
xcount = 0;
i = SPACING;
while (i < width)
{
i = y & (-CHECK_SIZE);
for (; i < width; i += CHECK_SIZE)
if ((i / CHECK_SIZE + j / CHECK_SIZE) % 2 == 0)
j = SPACING;
ycount = xcount % 2; /* start with even/odd depending on row */
while (j < height)
{
if (ycount % 2)
cairo_set_source_rgb (cr, 0.45777, 0, 0.45777);
else
cairo_set_source_rgb (cr, 1, 1, 1);
/* If we're outside the clip, this will do nothing.
*/
cairo_rectangle (cr, i, j, CHECK_SIZE, CHECK_SIZE);
cairo_fill (cr);
j += CHECK_SIZE + SPACING;
++ycount;
}
i += CHECK_SIZE + SPACING;
++xcount;
}
cairo_set_source_rgb (cr, 0.7, 0.7, 0.7);
cairo_fill (cr);
#undef CHECK_SIZE
}
/* Draw a red, green, and blue circle equally spaced inside
* the larger circle of radius r at (xc, yc)
*/
static void
draw_3circles (cairo_t *cr,
double xc, double yc,
double radius,
double alpha)
{
double subradius = radius * (2 / 3. - 0.1);
cairo_set_source_rgba (cr, 1., 0., 0., alpha);
oval_path (cr,
xc + radius / 3. * cos (G_PI * (0.5)),
yc - radius / 3. * sin (G_PI * (0.5)),
subradius, subradius);
cairo_fill (cr);
cairo_set_source_rgba (cr, 0., 1., 0., alpha);
oval_path (cr,
xc + radius / 3. * cos (G_PI * (0.5 + 2/.3)),
yc - radius / 3. * sin (G_PI * (0.5 + 2/.3)),
subradius, subradius);
cairo_fill (cr);
cairo_set_source_rgba (cr, 0., 0., 1., alpha);
oval_path (cr,
xc + radius / 3. * cos (G_PI * (0.5 + 4/.3)),
yc - radius / 3. * sin (G_PI * (0.5 + 4/.3)),
subradius, subradius);
cairo_fill (cr);
}
static void
groups_draw (GtkDrawingArea *darea,
cairo_t *cr,
int width,
int height,
gpointer data)
{
cairo_surface_t *overlay, *punch, *circles;
cairo_t *overlay_cr, *punch_cr, *circles_cr;
/* Fill the background */
double radius = 0.5 * (width < height ? width : height) - 10;
double xc = width / 2.;
double yc = height / 2.;
overlay = cairo_surface_create_similar (cairo_get_target (cr),
CAIRO_CONTENT_COLOR_ALPHA,
width, height);
punch = cairo_surface_create_similar (cairo_get_target (cr),
CAIRO_CONTENT_ALPHA,
width, height);
circles = cairo_surface_create_similar (cairo_get_target (cr),
CAIRO_CONTENT_COLOR_ALPHA,
width, height);
fill_checks (cr, 0, 0, width, height);
/* Draw a black circle on the overlay
*/
overlay_cr = cairo_create (overlay);
cairo_set_source_rgb (overlay_cr, 0., 0., 0.);
oval_path (overlay_cr, xc, yc, radius, radius);
cairo_fill (overlay_cr);
/* Draw 3 circles to the punch surface, then cut
* that out of the main circle in the overlay
*/
punch_cr = cairo_create (punch);
draw_3circles (punch_cr, xc, yc, radius, 1.0);
cairo_destroy (punch_cr);
cairo_set_operator (overlay_cr, CAIRO_OPERATOR_DEST_OUT);
cairo_set_source_surface (overlay_cr, punch, 0, 0);
cairo_paint (overlay_cr);
/* Now draw the 3 circles in a subgroup again
* at half intensity, and use OperatorAdd to join up
* without seams.
*/
circles_cr = cairo_create (circles);
cairo_set_operator (circles_cr, CAIRO_OPERATOR_OVER);
draw_3circles (circles_cr, xc, yc, radius, 0.5);
cairo_destroy (circles_cr);
cairo_set_operator (overlay_cr, CAIRO_OPERATOR_ADD);
cairo_set_source_surface (overlay_cr, circles, 0, 0);
cairo_paint (overlay_cr);
cairo_destroy (overlay_cr);
cairo_set_source_surface (cr, overlay, 0, 0);
cairo_paint (cr);
cairo_surface_destroy (overlay);
cairo_surface_destroy (punch);
cairo_surface_destroy (circles);
}
static void
@@ -306,7 +189,7 @@ do_drawingarea (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Drawing Area");
@@ -315,29 +198,28 @@ do_drawingarea (GtkWidget *do_widget)
G_CALLBACK (close_window), NULL);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8);
gtk_widget_set_margin_start (vbox, 16);
gtk_widget_set_margin_end (vbox, 16);
gtk_widget_set_margin_top (vbox, 16);
gtk_widget_set_margin_bottom (vbox, 16);
gtk_window_set_child (GTK_WINDOW (window), vbox);
g_object_set (vbox, "margin", 16, NULL);
gtk_container_add (GTK_CONTAINER (window), vbox);
/*
* Create the groups area
* Create the checkerboard area
*/
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label),
"<u>Knockout groups</u>");
gtk_box_append (GTK_BOX (vbox), label);
"<u>Checkerboard pattern</u>");
gtk_container_add (GTK_CONTAINER (vbox), label);
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
gtk_widget_set_vexpand (frame, TRUE);
gtk_box_append (GTK_BOX (vbox), frame);
gtk_container_add (GTK_CONTAINER (vbox), frame);
da = gtk_drawing_area_new ();
gtk_drawing_area_set_content_width (GTK_DRAWING_AREA (da), 100);
gtk_drawing_area_set_content_height (GTK_DRAWING_AREA (da), 100);
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (da), groups_draw, NULL, NULL);
gtk_frame_set_child (GTK_FRAME (frame), da);
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (da), checkerboard_draw, NULL, NULL);
gtk_container_add (GTK_CONTAINER (frame), da);
/*
* Create the scribble area
@@ -346,20 +228,21 @@ do_drawingarea (GtkWidget *do_widget)
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label),
"<u>Scribble area</u>");
gtk_box_append (GTK_BOX (vbox), label);
gtk_container_add (GTK_CONTAINER (vbox), label);
frame = gtk_frame_new (NULL);
gtk_widget_set_vexpand (frame, TRUE);
gtk_box_append (GTK_BOX (vbox), frame);
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), 100);
gtk_drawing_area_set_content_height (GTK_DRAWING_AREA (da), 100);
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (da), scribble_draw, NULL, NULL);
gtk_frame_set_child (GTK_FRAME (frame), da);
gtk_container_add (GTK_CONTAINER (frame), da);
g_signal_connect (da, "resize",
G_CALLBACK (scribble_resize), NULL);
g_signal_connect (da, "size-allocate",
G_CALLBACK (scribble_size_allocate), NULL);
drag = gtk_gesture_drag_new ();
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (drag), GDK_BUTTON_PRIMARY);
@@ -374,7 +257,7 @@ do_drawingarea (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;
}
+14 -18
View File
@@ -275,9 +275,6 @@ cell_edited (GtkCellRendererText *cell,
g_array_index (articles, Item, i).product, -1);
}
break;
default:
g_assert_not_reached ();
}
gtk_tree_path_free (path);
@@ -348,28 +345,27 @@ do_editable_cells (GtkWidget *do_widget)
GtkTreeModel *items_model;
GtkTreeModel *numbers_model;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Editable Cells");
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, 5);
gtk_widget_set_margin_start (vbox, 5);
gtk_widget_set_margin_end (vbox, 5);
gtk_widget_set_margin_top (vbox, 5);
gtk_widget_set_margin_bottom (vbox, 5);
gtk_window_set_child (GTK_WINDOW (window), vbox);
g_object_set (vbox, "margin", 5, NULL);
gtk_container_add (GTK_CONTAINER (window), vbox);
gtk_box_append (GTK_BOX (vbox),
gtk_container_add (GTK_CONTAINER (vbox),
gtk_label_new ("Shopping list (you can edit the cells!)"));
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (sw), TRUE);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
GTK_SHADOW_ETCHED_IN);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_box_append (GTK_BOX (vbox), sw);
gtk_container_add (GTK_CONTAINER (vbox), sw);
/* create models */
items_model = create_items_model ();
@@ -386,22 +382,22 @@ do_editable_cells (GtkWidget *do_widget)
g_object_unref (numbers_model);
g_object_unref (items_model);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), treeview);
gtk_container_add (GTK_CONTAINER (sw), treeview);
/* some buttons */
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
gtk_box_set_homogeneous (GTK_BOX (hbox), TRUE);
gtk_box_append (GTK_BOX (vbox), hbox);
gtk_container_add (GTK_CONTAINER (vbox), hbox);
button = gtk_button_new_with_label ("Add item");
g_signal_connect (button, "clicked",
G_CALLBACK (add_item), treeview);
gtk_box_append (GTK_BOX (hbox), button);
gtk_container_add (GTK_CONTAINER (hbox), button);
button = gtk_button_new_with_label ("Remove item");
g_signal_connect (button, "clicked",
G_CALLBACK (remove_item), treeview);
gtk_box_append (GTK_BOX (hbox), button);
gtk_container_add (GTK_CONTAINER (hbox), button);
gtk_window_set_default_size (GTK_WINDOW (window), 320, 200);
}
@@ -409,7 +405,7 @@ do_editable_cells (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 -11
View File
@@ -9,7 +9,7 @@
#include <gtk/gtk.h>
/* Creates a tree model containing the completions */
static GtkTreeModel *
GtkTreeModel *
create_completion_model (void)
{
GtkListStore *store;
@@ -45,27 +45,26 @@ do_entry_completion (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Entry Completion");
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
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, 5);
gtk_widget_set_margin_start (vbox, 5);
gtk_widget_set_margin_end (vbox, 5);
gtk_widget_set_margin_top (vbox, 5);
gtk_widget_set_margin_bottom (vbox, 5);
gtk_window_set_child (GTK_WINDOW (window), vbox);
g_object_set (vbox, "margin", 5, NULL);
gtk_container_add (GTK_CONTAINER (window), vbox);
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label), "Completion demo, try writing <b>total</b> or <b>gnome</b> for example.");
gtk_box_append (GTK_BOX (vbox), label);
gtk_container_add (GTK_CONTAINER (vbox), label);
/* Create our entry */
entry = gtk_entry_new ();
gtk_box_append (GTK_BOX (vbox), entry);
gtk_container_add (GTK_CONTAINER (vbox), entry);
/* Create the completion object */
completion = gtk_entry_completion_new ();
@@ -86,7 +85,7 @@ do_entry_completion (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;
}
+8 -10
View File
@@ -20,35 +20,33 @@ do_entry_undo (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Entry Undo");
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
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, 5);
gtk_widget_set_margin_start (vbox, 5);
gtk_widget_set_margin_end (vbox, 5);
gtk_widget_set_margin_top (vbox, 5);
gtk_widget_set_margin_bottom (vbox, 5);
gtk_window_set_child (GTK_WINDOW (window), vbox);
g_object_set (vbox, "margin", 5, NULL);
gtk_container_add (GTK_CONTAINER (window), vbox);
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label),
"Use Primary+z or Primary+Shift+z to undo or redo changes");
gtk_box_append (GTK_BOX (vbox), label);
gtk_container_add (GTK_CONTAINER (vbox), label);
/* Create our entry */
entry = gtk_entry_new ();
gtk_editable_set_enable_undo (GTK_EDITABLE (entry), TRUE);
gtk_box_append (GTK_BOX (vbox), entry);
gtk_container_add (GTK_CONTAINER (vbox), entry);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
return window;
}
+6 -6
View File
@@ -15,7 +15,7 @@ static GtkWidget *window = NULL;
static void
response_cb (GtkDialog *dialog, gint response_id)
{
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
window = NULL;
}
@@ -59,7 +59,7 @@ do_expander (GtkWidget *do_widget)
gtk_widget_set_vexpand (expander, TRUE);
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (sw), 100);
gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (sw), TRUE);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
@@ -78,9 +78,9 @@ do_expander (GtkWidget *do_widget)
"A second paragraph will contain even more "
"innuendo, just to make you scroll down or "
"resize the window. Do it already !", -1);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), tv);
gtk_expander_set_child (GTK_EXPANDER (expander), sw);
gtk_box_append (GTK_BOX (area), expander);
gtk_container_add (GTK_CONTAINER (sw), tv);
gtk_container_add (GTK_CONTAINER (expander), sw);
gtk_container_add (GTK_CONTAINER (area), expander);
g_signal_connect (expander, "notify::expanded",
G_CALLBACK (expander_cb), window);
@@ -90,7 +90,7 @@ do_expander (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;
}
+3 -2
View File
@@ -125,7 +125,8 @@ do_filtermodel (GtkWidget *do_widget)
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);
store = (GtkListStore*)gtk_builder_get_object (builder, "liststore1");
@@ -198,7 +199,7 @@ do_filtermodel (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 -4
View File
@@ -31,10 +31,7 @@
<property name="title" translatable="yes">Filter Model</property>
<child>
<object class="GtkGrid" id="grid1">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="row-spacing">10</property>
<property name="column-spacing">10</property>
<property name="column-homogeneous">1</property>
@@ -56,6 +53,7 @@
</child>
<child>
<object class="GtkTreeView" id="treeview1">
<property name="can-focus">1</property>
<property name="model">liststore1</property>
<property name="headers-clickable">0</property>
<child internal-child="selection">
@@ -94,6 +92,7 @@
</child>
<child>
<object class="GtkTreeView" id="treeview2">
<property name="can-focus">1</property>
<property name="headers-clickable">0</property>
<property name="search-column">0</property>
<child internal-child="selection">
@@ -176,6 +175,7 @@
</child>
<child>
<object class="GtkTreeView" id="treeview3">
<property name="can-focus">1</property>
<property name="headers-clickable">0</property>
<property name="search-column">0</property>
<child internal-child="selection">
+33 -15
View File
@@ -22,11 +22,29 @@ gsize n_icon_names = 0;
static void
init_icon_names (GtkIconTheme *theme)
{
GPtrArray *icons;
GList *l, *icon_list;
if (icon_names)
return;
icon_names = gtk_icon_theme_get_icon_names (theme);
n_icon_names = g_strv_length (icon_names);
icon_list = gtk_icon_theme_list_icons (theme, NULL);
icons = g_ptr_array_new ();
for (l = icon_list; l; l = l->next)
{
if (g_str_has_suffix (l->data, "symbolic"))
continue;
g_ptr_array_add (icons, g_strdup (l->data));
}
n_icon_names = icons->len;
g_ptr_array_add (icons, NULL); /* NULL-terminate the array */
icon_names = (char **) g_ptr_array_free (icons, FALSE);
/* don't free strings, we assigned them to the array */
g_list_free_full (icon_list, g_free);
}
static const char *
@@ -37,16 +55,13 @@ get_random_icon_name (GtkIconTheme *theme)
return icon_names[g_random_int_range(0, n_icon_names)];
}
/* Can't be static because it's also used in iconscroll.c */
GtkWidget *
create_icon (void)
{
GtkWidget *image;
image = gtk_image_new ();
image = gtk_image_new_from_icon_name (get_random_icon_name (gtk_icon_theme_get_default ()));
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
gtk_image_set_from_icon_name (GTK_IMAGE (image),
get_random_icon_name (gtk_icon_theme_get_for_display (gtk_widget_get_display (image))));
return image;
}
@@ -62,7 +77,7 @@ create_blurred_button (void)
{
GtkWidget *w = gtk_button_new ();
gtk_widget_add_css_class (w, "blurred-button");
gtk_style_context_add_class (gtk_widget_get_style_context (w), "blurred-button");
return w;
}
@@ -159,9 +174,9 @@ static GtkWidget *
create_menu_button (void)
{
GtkWidget *w = gtk_menu_button_new ();
GtkWidget *popover = gtk_popover_new ();
GtkWidget *popover = gtk_popover_new (NULL);
gtk_popover_set_child (GTK_POPOVER (popover), gtk_button_new_with_label ("Hey!"));
gtk_container_add (GTK_CONTAINER (popover), gtk_button_new_with_label ("Hey!"));
gtk_popover_set_autohide (GTK_POPOVER (popover), FALSE);
gtk_menu_button_set_popover (GTK_MENU_BUTTON (w), popover);
g_signal_connect (w, "map", G_CALLBACK (mapped), NULL);
@@ -194,7 +209,7 @@ static void
set_widget_type (GtkFishbowl *fishbowl,
int widget_type_index)
{
GtkWidget *window;
GtkWidget *window, *headerbar;
if (widget_type_index == selected_widget_type)
return;
@@ -205,8 +220,9 @@ set_widget_type (GtkFishbowl *fishbowl,
widget_types[selected_widget_type].create_func);
window = GTK_WIDGET (gtk_widget_get_root (GTK_WIDGET (fishbowl)));
gtk_window_set_title (GTK_WINDOW (window),
widget_types[selected_widget_type].name);
headerbar = gtk_window_get_titlebar (GTK_WINDOW (window));
gtk_header_bar_set_title (GTK_HEADER_BAR (headerbar),
widget_types[selected_widget_type].name);
}
void
@@ -281,13 +297,15 @@ do_fishbowl (GtkWidget *do_widget)
builder = gtk_builder_new_from_resource ("/fishbowl/fishbowl.ui");
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
bowl = GTK_WIDGET (gtk_builder_get_object (builder, "bowl"));
selected_widget_type = -1;
set_widget_type (GTK_FISHBOWL (bowl), 0);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
gtk_widget_realize (window);
g_object_unref (builder);
@@ -296,7 +314,7 @@ do_fishbowl (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;
}
+1 -2
View File
@@ -39,7 +39,7 @@
<child type="end">
<object class="GtkToggleButton" id="changes_allow">
<property name="icon-name">changes-allow</property>
<property name="has-frame">0</property>
<property name="relief">none</property>
<signal name="notify::active" handler="fishbowl_changes_toggled_cb"/>
</object>
</child>
@@ -48,7 +48,6 @@
<child>
<object class="GtkFishbowl" id="bowl">
<property name="visible">True</property>
<property name="overflow">hidden</property>
<property name="animating">True</property>
<property name="benchmark" bind-source="changes_allow" bind-property="active" bind-flags="invert-boolean | sync-create"/>
</object>
+7 -7
View File
@@ -52,8 +52,8 @@ create_faces (void)
/* Add a face */
faces[i].face = gtk_frame_new (NULL);
gtk_widget_set_size_request (faces[i].face, face_size, face_size);
gtk_widget_add_css_class (faces[i].face, faces[i].css_class);
gtk_fixed_put (GTK_FIXED (fixed), faces[i].face, 0, 0);
gtk_style_context_add_class (gtk_widget_get_style_context (faces[i].face), faces[i].css_class);
gtk_container_add (GTK_CONTAINER (fixed), faces[i].face);
/* Set up the transformation for each face */
transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (w, h));
@@ -124,22 +124,22 @@ create_demo_window (GtkWidget *do_widget)
{
GtkWidget *window, *sw, *fixed, *cube;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Fixed layout");
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_window_set_child (GTK_WINDOW (window), sw);
gtk_container_add (GTK_CONTAINER (window), sw);
fixed = gtk_fixed_new ();
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), fixed);
gtk_container_add (GTK_CONTAINER (sw), fixed);
gtk_widget_set_halign (GTK_WIDGET (fixed), GTK_ALIGN_CENTER);
gtk_widget_set_valign (GTK_WIDGET (fixed), GTK_ALIGN_CENTER);
cube = create_faces ();
gtk_fixed_put (GTK_FIXED (fixed), cube, 0, 0);
gtk_container_add (GTK_CONTAINER (fixed), cube);
gtk_widget_set_overflow (fixed, GTK_OVERFLOW_VISIBLE);
provider = gtk_css_provider_new ();
@@ -161,7 +161,7 @@ do_fixed (GtkWidget *do_widget)
if (!gtk_widget_get_visible (demo_window))
gtk_widget_show (demo_window);
else
gtk_window_destroy (GTK_WINDOW (demo_window));
gtk_widget_destroy (demo_window);
return demo_window;
}
+9 -9
View File
@@ -4,8 +4,6 @@
* as needed and support sorting and filtering.
*
* The children of a GtkFlowBox are regular widgets
*
* The dataset used here has 665 colors.
*/
#include <gtk/gtk.h>
@@ -39,7 +37,7 @@ color_swatch_new (const gchar *color)
gtk_drawing_area_set_content_width (GTK_DRAWING_AREA (area), 24);
gtk_drawing_area_set_content_height (GTK_DRAWING_AREA (area), 24);
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (area), draw_color, (gpointer) color, NULL);
gtk_button_set_child (GTK_BUTTON (button), area);
gtk_container_add (GTK_CONTAINER (button), area);
return button;
}
@@ -721,12 +719,14 @@ do_flowbox (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Flow Box");
gtk_window_set_default_size (GTK_WINDOW (window), 400, 600);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
scrolled = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
@@ -735,17 +735,17 @@ do_flowbox (GtkWidget *do_widget)
gtk_flow_box_set_max_children_per_line (GTK_FLOW_BOX (flowbox), 30);
gtk_flow_box_set_selection_mode (GTK_FLOW_BOX (flowbox), GTK_SELECTION_NONE);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolled), flowbox);
gtk_window_set_child (GTK_WINDOW (window), scrolled);
gtk_container_add (GTK_CONTAINER (scrolled), flowbox);
gtk_container_add (GTK_CONTAINER (window), scrolled);
for (i = 0; colors[i]; i++)
gtk_flow_box_insert (GTK_FLOW_BOX (flowbox), color_swatch_new (colors[i]), -1);
gtk_container_add (GTK_CONTAINER (flowbox), color_swatch_new (colors[i]));
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
return window;
}
+7 -9
View File
@@ -4,12 +4,13 @@
<object class="GtkWindow" id="window">
<property name="default-width">600</property>
<property name="default-height">500</property>
<property name="title">Font Explorer</property>
<child type="titlebar">
<object class="GtkHeaderBar">
<property name="show-title-buttons">1</property>
<property name="title">Font Explorer</property>
<child>
<object class="GtkButton" id="reset">
<property name="can-focus">1</property>
<property name="receives-default">1</property>
<property name="tooltip-text">Reset</property>
<signal name="clicked" handler="font_features_reset_features" swapped="no"/>
@@ -26,19 +27,18 @@
<object class="GtkBox">
<child>
<object class="GtkScrolledWindow">
<property name="can-focus">1</property>
<property name="hscrollbar-policy">never</property>
<child>
<object class="GtkViewport">
<child>
<object class="GtkBox">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="margin">10</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkFontButton" id="font">
<property name="can-focus">1</property>
<property name="receives-default">1</property>
<property name="font">Sans 12</property>
<property name="level">family|style|size|variations|features</property>
@@ -61,6 +61,7 @@
<property name="orientation">vertical</property>
<child>
<object class="GtkComboBox" id="script_lang">
<property name="can-focus">1</property>
<property name="margin-top">10</property>
<signal name="changed" handler="font_features_script_changed" swapped="no"/>
<child>
@@ -108,10 +109,7 @@
<property name="orientation">vertical</property>
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<property name="margin-start">20</property>
<property name="margin-end">20</property>
<property name="margin-top">20</property>
<property name="margin-bottom">20</property>
<property name="margin">20</property>
<property name="spacing">20</property>
<child>
<object class="GtkStack" id="stack">
+34 -31
View File
@@ -25,14 +25,14 @@
#define MAKE_TAG(a,b,c,d) (unsigned int)(((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
static GtkWidget *the_label;
static GtkWidget *label;
static GtkWidget *settings;
static GtkWidget *description;
static GtkWidget *font;
static GtkWidget *script_lang;
static GtkWidget *resetbutton;
static GtkWidget *stack;
static GtkWidget *the_entry;
static GtkWidget *entry;
static GtkWidget *variations_heading;
static GtkWidget *variations_grid;
static GtkWidget *instance_combo;
@@ -194,7 +194,7 @@ add_check_group (GtkWidget *box,
pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
gtk_label_set_attributes (GTK_LABEL (label), attrs);
pango_attr_list_unref (attrs);
gtk_box_append (GTK_BOX (group), label);
gtk_container_add (GTK_CONTAINER (group), label);
for (i = 0; tags[i]; i++)
{
@@ -211,7 +211,7 @@ add_check_group (GtkWidget *box,
g_signal_connect (feat, "notify::inconsistent", G_CALLBACK (update_display), NULL);
g_signal_connect (feat, "clicked", G_CALLBACK (feat_clicked), NULL);
gtk_box_append (GTK_BOX (group), feat);
gtk_container_add (GTK_CONTAINER (group), feat);
item = g_new (FeatureItem, 1);
item->name = tags[i];
@@ -223,7 +223,7 @@ add_check_group (GtkWidget *box,
feature_items = g_list_prepend (feature_items, item);
}
gtk_box_append (GTK_BOX (box), group);
gtk_container_add (GTK_CONTAINER (box), group);
}
static void
@@ -248,7 +248,7 @@ add_radio_group (GtkWidget *box,
pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
gtk_label_set_attributes (GTK_LABEL (label), attrs);
pango_attr_list_unref (attrs);
gtk_box_append (GTK_BOX (group), label);
gtk_container_add (GTK_CONTAINER (group), label);
for (i = 0; tags[i]; i++)
{
@@ -268,7 +268,7 @@ add_radio_group (GtkWidget *box,
g_signal_connect (feat, "notify::active", G_CALLBACK (update_display), NULL);
g_object_set_data (G_OBJECT (feat), "default", group_button);
gtk_box_append (GTK_BOX (group), feat);
gtk_container_add (GTK_CONTAINER (group), feat);
item = g_new (FeatureItem, 1);
item->name = tags[i];
@@ -280,7 +280,7 @@ add_radio_group (GtkWidget *box,
feature_items = g_list_prepend (feature_items, item);
}
gtk_box_append (GTK_BOX (box), group);
gtk_container_add (GTK_CONTAINER (box), group);
}
static void
@@ -301,9 +301,9 @@ update_display (void)
char *font_desc;
char *features;
text = gtk_editable_get_text (GTK_EDITABLE (the_entry));
text = gtk_editable_get_text (GTK_EDITABLE (entry));
if (gtk_label_get_selection_bounds (GTK_LABEL (the_label), &ins, &bound))
if (gtk_label_get_selection_bounds (GTK_LABEL (label), &ins, &bound))
{
start = g_utf8_offset_to_pointer (text, ins) - text;
end = g_utf8_offset_to_pointer (text, bound) - text;
@@ -409,8 +409,8 @@ update_display (void)
gtk_label_set_text (GTK_LABEL (description), font_desc);
gtk_label_set_text (GTK_LABEL (settings), features);
gtk_label_set_text (GTK_LABEL (the_label), text);
gtk_label_set_attributes (GTK_LABEL (the_label), attrs);
gtk_label_set_text (GTK_LABEL (label), text);
gtk_label_set_attributes (GTK_LABEL (label), attrs);
g_free (font_desc);
pango_font_description_free (desc);
@@ -548,7 +548,7 @@ update_script_combo (void)
{
const char *langname;
char langbuf[5];
GtkTreeIter tree_iter;
GtkTreeIter iter;
if (pair->lang_tag == HB_OT_TAG_DEFAULT_LANGUAGE)
langname = NC_("Language", "Default");
@@ -563,7 +563,7 @@ update_script_combo (void)
}
}
gtk_list_store_insert_with_values (store, &tree_iter, -1,
gtk_list_store_insert_with_values (store, &iter, -1,
0, langname,
1, pair->script_index,
2, pair->lang_index,
@@ -572,7 +572,7 @@ update_script_combo (void)
if (pair->lang_tag == active)
{
have_active = TRUE;
active_iter = tree_iter;
active_iter = iter;
}
}
@@ -751,7 +751,7 @@ add_font_variations (GString *s)
GHashTableIter iter;
Axis *axis;
char buf[G_ASCII_DTOSTR_BUF_SIZE];
const char *sep = "";
char *sep = "";
g_hash_table_iter_init (&iter, axes);
while (g_hash_table_iter_next (&iter, (gpointer *)NULL, (gpointer *)&axis))
@@ -1025,7 +1025,7 @@ denorm_coord (hb_ot_var_axis_info_t *axis, int coord)
static void
update_font_variations (void)
{
GtkWidget *child;
GtkWidget *child, *next;
PangoFont *pango_font = NULL;
hb_font_t *hb_font;
hb_face_t *hb_face;
@@ -1037,8 +1037,12 @@ update_font_variations (void)
int i;
child = gtk_widget_get_first_child (variations_grid);
while ((child = gtk_widget_get_first_child (variations_grid)))
gtk_grid_remove (GTK_GRID (variations_grid), child);
while (child != NULL)
{
next = gtk_widget_get_next_sibling (child);
gtk_widget_destroy (child);
child = next;
}
instance_combo = NULL;
@@ -1125,7 +1129,7 @@ font_features_reset_features (void)
{
GList *l;
gtk_label_select_region (GTK_LABEL (the_label), 0, 0);
gtk_label_select_region (GTK_LABEL (label), 0, 0);
g_list_free_full (ranges, free_range);
ranges = NULL;
@@ -1152,9 +1156,9 @@ static char *text;
static void
switch_to_entry (void)
{
text = g_strdup (gtk_editable_get_text (GTK_EDITABLE (the_entry)));
text = g_strdup (gtk_editable_get_text (GTK_EDITABLE (entry)));
gtk_stack_set_visible_child_name (GTK_STACK (stack), "entry");
gtk_widget_grab_focus (the_entry);
gtk_widget_grab_focus (entry);
}
static void
@@ -1213,20 +1217,20 @@ do_font_features (GtkWidget *do_widget)
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
feature_list = GTK_WIDGET (gtk_builder_get_object (builder, "feature_list"));
the_label = GTK_WIDGET (gtk_builder_get_object (builder, "label"));
label = GTK_WIDGET (gtk_builder_get_object (builder, "label"));
settings = GTK_WIDGET (gtk_builder_get_object (builder, "settings"));
description = GTK_WIDGET (gtk_builder_get_object (builder, "description"));
resetbutton = GTK_WIDGET (gtk_builder_get_object (builder, "reset"));
font = GTK_WIDGET (gtk_builder_get_object (builder, "font"));
script_lang = GTK_WIDGET (gtk_builder_get_object (builder, "script_lang"));
stack = GTK_WIDGET (gtk_builder_get_object (builder, "stack"));
the_entry = GTK_WIDGET (gtk_builder_get_object (builder, "entry"));
entry = GTK_WIDGET (gtk_builder_get_object (builder, "entry"));
edit_toggle = GTK_WIDGET (gtk_builder_get_object (builder, "edit_toggle"));
controller = gtk_event_controller_key_new ();
g_object_set_data_full (G_OBJECT (the_entry), "controller", g_object_ref (controller), g_object_unref);
g_signal_connect (controller, "key-pressed", G_CALLBACK (entry_key_press), the_entry);
gtk_widget_add_controller (the_entry, controller);
g_object_set_data_full (G_OBJECT (entry), "controller", controller, g_object_unref);
g_signal_connect (controller, "key-pressed", G_CALLBACK (entry_key_press), entry);
gtk_widget_add_controller (entry, controller);
add_check_group (feature_list, _("Kerning"), (const char *[]){ "kern", NULL });
add_check_group (feature_list, _("Ligatures"), (const char *[]){ "liga",
@@ -1329,17 +1333,16 @@ do_font_features (GtkWidget *do_widget)
font_features_font_changed ();
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
g_object_unref (builder);
update_display ();
}
if (!gtk_widget_get_visible (window))
gtk_window_present (GTK_WINDOW (window));
else
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
return window;
}
+29
View File
@@ -19,6 +19,8 @@
#include "fontplane.h"
#include "gtk.h"
enum {
PROP_0,
PROP_WEIGHT_ADJUSTMENT,
@@ -140,6 +142,17 @@ update_value (GtkFontPlane *plane,
gtk_widget_queue_draw (widget);
}
static void
hold_action (GtkGestureLongPress *gesture,
gdouble x,
gdouble y,
GtkFontPlane *plane)
{
gboolean handled;
g_signal_emit_by_name (plane, "popup-menu", &handled);
}
static void
plane_drag_gesture_begin (GtkGestureDrag *gesture,
gdouble start_x,
@@ -150,6 +163,13 @@ plane_drag_gesture_begin (GtkGestureDrag *gesture,
button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
if (button == GDK_BUTTON_SECONDARY)
{
gboolean handled;
g_signal_emit_by_name (plane, "popup-menu", &handled);
}
if (button != GDK_BUTTON_PRIMARY)
{
gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
@@ -189,6 +209,8 @@ gtk_font_plane_init (GtkFontPlane *plane)
{
GtkGesture *gesture;
gtk_widget_set_can_focus (GTK_WIDGET (plane), TRUE);
gesture = gtk_gesture_drag_new ();
g_signal_connect (gesture, "drag-begin",
G_CALLBACK (plane_drag_gesture_begin), plane);
@@ -198,6 +220,13 @@ gtk_font_plane_init (GtkFontPlane *plane)
G_CALLBACK (plane_drag_gesture_end), plane);
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), 0);
gtk_widget_add_controller (GTK_WIDGET (plane), GTK_EVENT_CONTROLLER (gesture));
gesture = gtk_gesture_long_press_new ();
g_signal_connect (gesture, "pressed",
G_CALLBACK (hold_action), plane);
gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (gesture),
TRUE);
gtk_widget_add_controller (GTK_WIDGET (plane), GTK_EVENT_CONTROLLER (gesture));
}
static void
+2 -2
View File
@@ -43,6 +43,7 @@ update_image (void)
cairo_font_options_t *fopt;
cairo_hint_style_t hintstyle;
cairo_hint_metrics_t hintmetrics;
int i;
if (!context)
context = gtk_widget_create_pango_context (image);
@@ -115,7 +116,6 @@ update_image (void)
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (show_grid)))
{
int i;
cairo_set_source_rgba (cr, 0.2, 0, 0, 0.2);
for (i = 1; i < ink.height + 20; i++)
{
@@ -281,7 +281,7 @@ do_fontrendering (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 -5
View File
@@ -165,11 +165,10 @@
</child>
<child>
<object class="GtkBox">
<property name="orientation">horizontal</property>
<property name="halign">center</property>
<property name="valign">center</property>
<style>
<class name="linked"/>
</style>
<style><class name="linked"/></style>
<child>
<object class="GtkRadioButton" id="text_radio">
<property name="draw-indicator">0</property>
@@ -184,7 +183,7 @@
</object>
</child>
<layout>
<property name="left-attach">0</property>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
<property name="column-span">7</property>
</layout>
@@ -193,7 +192,7 @@
<child>
<object class="GtkScrolledWindow">
<property name="propagate-natural-height">1</property>
<property name="has-frame">1</property>
<property name="shadow-type">in</property>
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<child>
+984
View File
@@ -0,0 +1,984 @@
/* Foreign drawing
*
* Many applications can't use GTK widgets, for a variety of reasons,
* but still want their user interface to appear integrated with the
* rest of the desktop, and follow GTK themes. This demo shows how to
* use GtkStyleContext and the gtk_render_ APIs to achieve this.
*
* Note that this is a very simple, non-interactive example.
*/
#include <gtk/gtk.h>
#include <string.h>
static void
append_element (GtkWidgetPath *path,
const char *selector)
{
static const struct {
const char *name;
GtkStateFlags state_flag;
} pseudo_classes[] = {
{ "active", GTK_STATE_FLAG_ACTIVE },
{ "hover", GTK_STATE_FLAG_PRELIGHT },
{ "selected", GTK_STATE_FLAG_SELECTED },
{ "disabled", GTK_STATE_FLAG_INSENSITIVE },
{ "indeterminate", GTK_STATE_FLAG_INCONSISTENT },
{ "focus", GTK_STATE_FLAG_FOCUSED },
{ "backdrop", GTK_STATE_FLAG_BACKDROP },
{ "dir(ltr)", GTK_STATE_FLAG_DIR_LTR },
{ "dir(rtl)", GTK_STATE_FLAG_DIR_RTL },
{ "link", GTK_STATE_FLAG_LINK },
{ "visited", GTK_STATE_FLAG_VISITED },
{ "checked", GTK_STATE_FLAG_CHECKED },
{ "drop(active)", GTK_STATE_FLAG_DROP_ACTIVE }
};
const char *next;
char *name;
char type;
guint i;
next = strpbrk (selector, "#.:");
if (next == NULL)
next = selector + strlen (selector);
name = g_strndup (selector, next - selector);
if (g_ascii_isupper (selector[0]))
{
GType gtype;
gtype = g_type_from_name (name);
if (gtype == G_TYPE_INVALID)
{
g_critical ("Unknown type name `%s'", name);
g_free (name);
return;
}
gtk_widget_path_append_type (path, gtype);
}
else
{
/* Omit type, we're using name */
gtk_widget_path_append_type (path, G_TYPE_NONE);
gtk_widget_path_iter_set_object_name (path, -1, name);
}
g_free (name);
while (*next != '\0')
{
type = *next;
selector = next + 1;
next = strpbrk (selector, "#.:");
if (next == NULL)
next = selector + strlen (selector);
name = g_strndup (selector, next - selector);
switch (type)
{
case '#':
gtk_widget_path_iter_set_name (path, -1, name);
break;
case '.':
gtk_widget_path_iter_add_class (path, -1, name);
break;
case ':':
for (i = 0; i < G_N_ELEMENTS (pseudo_classes); i++)
{
if (g_str_equal (pseudo_classes[i].name, name))
{
gtk_widget_path_iter_set_state (path,
-1,
gtk_widget_path_iter_get_state (path, -1)
| pseudo_classes[i].state_flag);
break;
}
}
if (i == G_N_ELEMENTS (pseudo_classes))
g_critical ("Unknown pseudo-class :%s", name);
break;
default:
g_assert_not_reached ();
break;
}
g_free (name);
}
}
static GtkStyleContext *
create_context_for_path (GtkWidgetPath *path,
GtkStyleContext *parent)
{
GtkStyleContext *context;
context = gtk_style_context_new ();
gtk_style_context_set_path (context, path);
gtk_style_context_set_parent (context, parent);
/* Unfortunately, we have to explicitly set the state again here
* for it to take effect
*/
gtk_style_context_set_state (context, gtk_widget_path_iter_get_state (path, -1));
gtk_widget_path_unref (path);
return context;
}
static GtkStyleContext *
get_style (GtkStyleContext *parent,
const char *selector)
{
GtkWidgetPath *path;
if (parent)
path = gtk_widget_path_copy (gtk_style_context_get_path (parent));
else
path = gtk_widget_path_new ();
append_element (path, selector);
return create_context_for_path (path, parent);
}
static GtkStyleContext *
get_style_with_siblings (GtkStyleContext *parent,
const char *selector,
const char **siblings,
gint position)
{
GtkWidgetPath *path, *siblings_path;
guint i;
if (parent)
path = gtk_widget_path_copy (gtk_style_context_get_path (parent));
else
path = gtk_widget_path_new ();
siblings_path = gtk_widget_path_new ();
for (i = 0; siblings[i]; i++)
append_element (siblings_path, siblings[i]);
gtk_widget_path_append_with_siblings (path, siblings_path, position);
gtk_widget_path_unref (siblings_path);
return create_context_for_path (path, parent);
}
static void
draw_style_common (GtkStyleContext *context,
cairo_t *cr,
gint x,
gint y,
gint width,
gint height,
gint *contents_x,
gint *contents_y,
gint *contents_width,
gint *contents_height)
{
GtkBorder margin, border, padding;
int min_width, min_height;
gtk_style_context_get_margin (context, &margin);
gtk_style_context_get_border (context, &border);
gtk_style_context_get_padding (context, &padding);
gtk_style_context_get (context,
"min-width", &min_width,
"min-height", &min_height,
NULL);
x += margin.left;
y += margin.top;
width -= margin.left + margin.right;
height -= margin.top + margin.bottom;
width = MAX (width, min_width);
height = MAX (height, min_height);
gtk_render_background (context, cr, x, y, width, height);
gtk_render_frame (context, cr, x, y, width, height);
if (contents_x)
*contents_x = x + border.left + padding.left;
if (contents_y)
*contents_y = y + border.top + padding.top;
if (contents_width)
*contents_width = width - border.left - border.right - padding.left - padding.right;
if (contents_height)
*contents_height = height - border.top - border.bottom - padding.top - padding.bottom;
}
static void
query_size (GtkStyleContext *context,
gint *width,
gint *height)
{
GtkBorder margin, border, padding;
int min_width, min_height;
gtk_style_context_get_margin (context, &margin);
gtk_style_context_get_border (context, &border);
gtk_style_context_get_padding (context, &padding);
gtk_style_context_get (context,
"min-width", &min_width,
"min-height", &min_height,
NULL);
min_width += margin.left + margin.right + border.left + border.right + padding.left + padding.right;
min_height += margin.top + margin.bottom + border.top + border.bottom + padding.top + padding.bottom;
if (width)
*width = MAX (*width, min_width);
if (height)
*height = MAX (*height, min_height);
}
static void
draw_menu (GtkWidget *widget,
cairo_t *cr,
gint x,
gint y,
gint width,
gint *height)
{
GtkStyleContext *menu_context;
GtkStyleContext *menuitem_context;
GtkStyleContext *hovermenuitem_context;
GtkStyleContext *hoveredarrowmenuitem_context;
GtkStyleContext *arrowmenuitem_context;
GtkStyleContext *checkmenuitem_context;
GtkStyleContext *disabledarrowmenuitem_context;
GtkStyleContext *disabledcheckmenuitem_context;
GtkStyleContext *radiomenuitem_context;
GtkStyleContext *disablemenuitem_context;
GtkStyleContext *disabledradiomenuitem_context;
GtkStyleContext *separatormenuitem_context;
gint menuitem1_height, menuitem2_height, menuitem3_height, menuitem4_height, menuitem5_height;
gint contents_x, contents_y, contents_width, contents_height;
gint menu_x, menu_y, menu_width, menu_height;
gint arrow_width, arrow_height, arrow_size;
gint toggle_x, toggle_y, toggle_width, toggle_height;
/* This information is taken from the GtkMenu docs, see "CSS nodes" */
menu_context = get_style (gtk_widget_get_style_context(widget), "menu");
hovermenuitem_context = get_style (menu_context, "menuitem:hover");
hoveredarrowmenuitem_context = get_style (hovermenuitem_context, "arrow.right:dir(ltr)");
menuitem_context = get_style (menu_context, "menuitem");
arrowmenuitem_context = get_style (menuitem_context, "arrow:dir(rtl)");
disablemenuitem_context = get_style (menu_context, "menuitem:disabled");
disabledarrowmenuitem_context = get_style (disablemenuitem_context, "arrow:dir(rtl)");
checkmenuitem_context = get_style (menuitem_context, "check:checked");
disabledcheckmenuitem_context = get_style (disablemenuitem_context, "check");
separatormenuitem_context = get_style (menu_context, "separator:disabled");
radiomenuitem_context = get_style (menuitem_context, "radio:checked");
disabledradiomenuitem_context = get_style (disablemenuitem_context, "radio");
*height = 0;
query_size (menu_context, NULL, height);
menuitem1_height = 0;
query_size (hovermenuitem_context, NULL, &menuitem1_height);
query_size (hoveredarrowmenuitem_context, NULL, &menuitem1_height);
*height += menuitem1_height;
menuitem2_height = 0;
query_size (menu_context, NULL, &menuitem5_height);
query_size (menuitem_context, NULL, &menuitem2_height);
query_size (arrowmenuitem_context, NULL, &menuitem2_height);
query_size (disabledarrowmenuitem_context, NULL, &menuitem2_height);
*height += menuitem2_height;
menuitem3_height = 0;
query_size (menu_context, NULL, &menuitem5_height);
query_size (menuitem_context, NULL, &menuitem3_height);
query_size (checkmenuitem_context, NULL, &menuitem3_height);
query_size (disabledcheckmenuitem_context, NULL, &menuitem3_height);
*height += menuitem3_height;
menuitem4_height = 0;
query_size (menu_context, NULL, &menuitem5_height);
query_size (separatormenuitem_context, NULL, &menuitem4_height);
*height += menuitem4_height;
menuitem5_height = 0;
query_size (menu_context, NULL, &menuitem5_height);
query_size (menuitem_context, NULL, &menuitem5_height);
query_size (radiomenuitem_context, NULL, &menuitem5_height);
query_size (disabledradiomenuitem_context, NULL, &menuitem5_height);
*height += menuitem5_height;
draw_style_common (menu_context, cr, x, y, width, *height,
&menu_x, &menu_y, &menu_width, &menu_height);
/* Hovered with right arrow */
gtk_style_context_get (hoveredarrowmenuitem_context,
"min-width", &arrow_width, "min-height", &arrow_height, NULL);
arrow_size = MIN (arrow_width, arrow_height);
draw_style_common (hovermenuitem_context, cr, menu_x, menu_y, menu_width, menuitem1_height,
&contents_x, &contents_y, &contents_width, &contents_height);
gtk_render_arrow (hoveredarrowmenuitem_context, cr, G_PI / 2,
contents_x + contents_width - arrow_size,
contents_y + (contents_height - arrow_size) / 2, arrow_size);
/* Left arrow sensitive, and right arrow insensitive */
draw_style_common (menuitem_context, cr, menu_x, menu_y + menuitem1_height, menu_width, menuitem2_height,
&contents_x, &contents_y, &contents_width, &contents_height);
gtk_style_context_get (arrowmenuitem_context,
"min-width", &arrow_width, "min-height", &arrow_height, NULL);
arrow_size = MIN (arrow_width, arrow_height);
gtk_render_arrow (arrowmenuitem_context, cr, G_PI / 2,
contents_x,
contents_y + (contents_height - arrow_size) / 2, arrow_size);
gtk_style_context_get (disabledarrowmenuitem_context,
"min-width", &arrow_width, "min-height", &arrow_height, NULL);
arrow_size = MIN (arrow_width, arrow_height);
gtk_render_arrow (disabledarrowmenuitem_context, cr, G_PI / 2,
contents_x + contents_width - arrow_size,
contents_y + (contents_height - arrow_size) / 2, arrow_size);
/* Left check enabled, sensitive, and right check unchecked, insensitive */
draw_style_common (menuitem_context, cr, menu_x, menu_y + menuitem1_height + menuitem2_height, menu_width, menuitem3_height,
&contents_x, &contents_y, &contents_width, &contents_height);
gtk_style_context_get (checkmenuitem_context,
"min-width", &toggle_width, "min-height", &toggle_height, NULL);
draw_style_common (checkmenuitem_context, cr,
contents_x,
contents_y,
toggle_width, toggle_height,
&toggle_x, &toggle_y, &toggle_width, &toggle_height);
gtk_render_check (checkmenuitem_context, cr, toggle_x, toggle_y, toggle_width, toggle_height);
gtk_style_context_get (disabledcheckmenuitem_context,
"min-width", &toggle_width, "min-height", &toggle_height, NULL);
draw_style_common (disabledcheckmenuitem_context, cr,
contents_x + contents_width - toggle_width,
contents_y,
toggle_width, toggle_height,
&toggle_x, &toggle_y, &toggle_width, &toggle_height);
gtk_render_check (disabledcheckmenuitem_context, cr, toggle_x, toggle_y, toggle_width, toggle_height);
/* Separator */
draw_style_common (separatormenuitem_context, cr, menu_x, menu_y + menuitem1_height + menuitem2_height + menuitem3_height,
menu_width, menuitem4_height,
NULL, NULL, NULL, NULL);
/* Left check enabled, sensitive, and right check unchecked, insensitive */
draw_style_common (menuitem_context, cr, menu_x, menu_y + menuitem1_height + menuitem2_height + menuitem3_height + menuitem4_height,
menu_width, menuitem5_height,
&contents_x, &contents_y, &contents_width, &contents_height);
gtk_style_context_get (radiomenuitem_context,
"min-width", &toggle_width, "min-height", &toggle_height, NULL);
draw_style_common (radiomenuitem_context, cr,
contents_x,
contents_y,
toggle_width, toggle_height,
&toggle_x, &toggle_y, &toggle_width, &toggle_height);
gtk_render_check (radiomenuitem_context, cr, toggle_x, toggle_y, toggle_width, toggle_height);
gtk_style_context_get (disabledradiomenuitem_context,
"min-width", &toggle_width, "min-height", &toggle_height, NULL);
draw_style_common (disabledradiomenuitem_context, cr,
contents_x + contents_width - toggle_width,
contents_y,
toggle_width, toggle_height,
&toggle_x, &toggle_y, &toggle_width, &toggle_height);
gtk_render_check (disabledradiomenuitem_context, cr, toggle_x, toggle_y, toggle_width, toggle_height);
g_object_unref (menu_context);
g_object_unref (menuitem_context);
g_object_unref (hovermenuitem_context);
g_object_unref (hoveredarrowmenuitem_context);
g_object_unref (arrowmenuitem_context);
g_object_unref (checkmenuitem_context);
g_object_unref (disabledarrowmenuitem_context);
g_object_unref (disabledcheckmenuitem_context);
g_object_unref (radiomenuitem_context);
g_object_unref (disablemenuitem_context);
g_object_unref (disabledradiomenuitem_context);
g_object_unref (separatormenuitem_context);
}
static void
draw_menubar (GtkWidget *widget,
cairo_t *cr,
gint x,
gint y,
gint width,
gint *height)
{
GtkStyleContext *frame_context;
GtkStyleContext *border_context;
GtkStyleContext *menubar_context;
GtkStyleContext *hovered_menuitem_context;
GtkStyleContext *menuitem_context;
gint contents_x, contents_y, contents_width, contents_height;
gint item_width;
/* Menubar background is the same color as our base background, so use a frame */
frame_context = get_style (NULL, "frame");
border_context = get_style (frame_context, "border");
/* This information is taken from the GtkMenuBar docs, see "CSS nodes" */
menubar_context = get_style (NULL, "menubar");
hovered_menuitem_context = get_style (menubar_context, "menuitem:hover");
menuitem_context = get_style (menubar_context, "menuitem");
*height = 0;
query_size (frame_context, NULL, height);
query_size (border_context, NULL, height);
query_size (menubar_context, NULL, height);
query_size (hovered_menuitem_context, NULL, height);
query_size (menuitem_context, NULL, height);
draw_style_common (frame_context, cr, x, y, width, *height,
NULL, NULL, NULL, NULL);
draw_style_common (border_context, cr, x, y, width, *height,
&contents_x, &contents_y, &contents_width, &contents_height);
draw_style_common (menubar_context, cr, contents_x, contents_y, contents_width, contents_height,
NULL, NULL, NULL, NULL);
item_width = contents_width / 3;
draw_style_common (hovered_menuitem_context, cr, contents_x, contents_y, item_width, contents_height,
NULL, NULL, NULL, NULL);
draw_style_common (menuitem_context, cr, contents_x + item_width * 2, contents_y, item_width, contents_height,
NULL, NULL, NULL, NULL);
g_object_unref (menuitem_context);
g_object_unref (hovered_menuitem_context);
g_object_unref (menubar_context);
g_object_unref (border_context);
g_object_unref (frame_context);
}
static void
draw_notebook (GtkWidget *widget,
cairo_t *cr,
gint x,
gint y,
gint width,
gint height)
{
GtkStyleContext *notebook_context;
GtkStyleContext *header_context;
GtkStyleContext *tabs_context;
GtkStyleContext *tab1_context, *tab2_context;
GtkStyleContext *stack_context;
gint header_height;
gint contents_x, contents_y, contents_width, contents_height;
/* This information is taken from the GtkNotebook docs, see "CSS nodes" */
notebook_context = get_style (NULL, "notebook.frame");
header_context = get_style (notebook_context, "header.top");
tabs_context = get_style (header_context, "tabs");
tab1_context = get_style (tabs_context, "tab:checked");
tab2_context = get_style (tabs_context, "tab:hover");
stack_context = get_style (notebook_context, "stack");
header_height = 0;
query_size (notebook_context, NULL, &header_height);
query_size (header_context, NULL, &header_height);
query_size (tabs_context, NULL, &header_height);
query_size (tab1_context, NULL, &header_height);
query_size (tab2_context, NULL, &header_height);
draw_style_common (notebook_context, cr, x, y, width, height, NULL, NULL, NULL, NULL);
draw_style_common (header_context, cr, x, y, width, header_height, NULL, NULL, NULL, NULL);
draw_style_common (tabs_context, cr, x, y, width, header_height, NULL, NULL, NULL, NULL);
draw_style_common (tab1_context, cr, x, y, width / 2, header_height,
&contents_x, &contents_y, &contents_width, &contents_height);
draw_style_common (tab2_context, cr, x + width / 2, y, width / 2, header_height,
NULL, NULL, NULL, NULL);
draw_style_common (stack_context, cr, x, y + header_height, width,height - header_height,
NULL, NULL, NULL, NULL);
g_object_unref (stack_context);
g_object_unref (tabs_context);
g_object_unref (tab1_context);
g_object_unref (tab2_context);
g_object_unref (header_context);
g_object_unref (notebook_context);
}
static void
draw_horizontal_scrollbar (GtkWidget *widget,
cairo_t *cr,
gint x,
gint y,
gint width,
gint position,
GtkStateFlags state,
gint *height)
{
GtkStyleContext *scrollbar_context;
GtkStyleContext *contents_context;
GtkStyleContext *trough_context;
GtkStyleContext *slider_context;
gint slider_width;
/* This information is taken from the GtkScrollbar docs, see "CSS nodes" */
scrollbar_context = get_style (NULL, "scrollbar.horizontal.bottom");
contents_context = get_style (scrollbar_context, "contents");
trough_context = get_style (contents_context, "trough");
slider_context = get_style (trough_context, "slider");
gtk_style_context_set_state (scrollbar_context, state);
gtk_style_context_set_state (contents_context, state);
gtk_style_context_set_state (trough_context, state);
gtk_style_context_set_state (slider_context, state);
*height = 0;
query_size (scrollbar_context, NULL, height);
query_size (contents_context, NULL, height);
query_size (trough_context, NULL, height);
query_size (slider_context, NULL, height);
gtk_style_context_get (slider_context,
"min-width", &slider_width, NULL);
draw_style_common (scrollbar_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
draw_style_common (contents_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
draw_style_common (trough_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
draw_style_common (slider_context, cr, x + position, y, slider_width, *height, NULL, NULL, NULL, NULL);
g_object_unref (slider_context);
g_object_unref (trough_context);
g_object_unref (contents_context);
g_object_unref (scrollbar_context);
}
static void
draw_text (GtkWidget *widget,
cairo_t *cr,
gint x,
gint y,
gint width,
gint height,
const gchar *text,
GtkStateFlags state)
{
GtkStyleContext *label_context;
GtkStyleContext *selection_context;
GtkStyleContext *context;
PangoLayout *layout;
/* This information is taken from the GtkLabel docs, see "CSS nodes" */
label_context = get_style (NULL, "label.view");
selection_context = get_style (label_context, "selection");
gtk_style_context_set_state (label_context, state);
if (state & GTK_STATE_FLAG_SELECTED)
context = selection_context;
else
context = label_context;
layout = gtk_widget_create_pango_layout (widget, text);
gtk_render_background (context, cr, x, y, width, height);
gtk_render_frame (context, cr, x, y, width, height);
gtk_render_layout (context, cr, x, y, layout);
g_object_unref (layout);
g_object_unref (selection_context);
g_object_unref (label_context);
}
static void
draw_check (GtkWidget *widget,
cairo_t *cr,
gint x,
gint y,
GtkStateFlags state,
gint *width,
gint *height)
{
GtkStyleContext *button_context;
GtkStyleContext *check_context;
gint contents_x, contents_y, contents_width, contents_height;
/* This information is taken from the GtkCheckButton docs, see "CSS nodes" */
button_context = get_style (NULL, "checkbutton");
check_context = get_style (button_context, "check");
gtk_style_context_set_state (check_context, state);
*width = *height = 0;
query_size (button_context, width, height);
query_size (check_context, width, height);
draw_style_common (button_context, cr, x, y, *width, *height, NULL, NULL, NULL, NULL);
draw_style_common (check_context, cr, x, y, *width, *height,
&contents_x, &contents_y, &contents_width, &contents_height);
gtk_render_check (check_context, cr, contents_x, contents_y, contents_width, contents_height);
g_object_unref (check_context);
g_object_unref (button_context);
}
static void
draw_radio (GtkWidget *widget,
cairo_t *cr,
gint x,
gint y,
GtkStateFlags state,
gint *width,
gint *height)
{
GtkStyleContext *button_context;
GtkStyleContext *check_context;
gint contents_x, contents_y, contents_width, contents_height;
/* This information is taken from the GtkRadioButton docs, see "CSS nodes" */
button_context = get_style (NULL, "radiobutton");
check_context = get_style (button_context, "radio");
gtk_style_context_set_state (check_context, state);
*width = *height = 0;
query_size (button_context, width, height);
query_size (check_context, width, height);
draw_style_common (button_context, cr, x, y, *width, *height, NULL, NULL, NULL, NULL);
draw_style_common (check_context, cr, x, y, *width, *height,
&contents_x, &contents_y, &contents_width, &contents_height);
gtk_render_check (check_context, cr, contents_x, contents_y, contents_width, contents_height);
g_object_unref (check_context);
g_object_unref (button_context);
}
static void
draw_progress (GtkWidget *widget,
cairo_t *cr,
gint x,
gint y,
gint width,
gint position,
gint *height)
{
GtkStyleContext *bar_context;
GtkStyleContext *trough_context;
GtkStyleContext *progress_context;
/* This information is taken from the GtkProgressBar docs, see "CSS nodes" */
bar_context = get_style (NULL, "progressbar.horizontal");
trough_context = get_style (bar_context, "trough");
progress_context = get_style (trough_context, "progress.left");
*height = 0;
query_size (bar_context, NULL, height);
query_size (trough_context, NULL, height);
query_size (progress_context, NULL, height);
draw_style_common (bar_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
draw_style_common (trough_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
draw_style_common (progress_context, cr, x, y, position, *height, NULL, NULL, NULL, NULL);
g_object_unref (progress_context);
g_object_unref (trough_context);
g_object_unref (bar_context);
}
static void
draw_scale (GtkWidget *widget,
cairo_t *cr,
gint x,
gint y,
gint width,
gint position,
gint *height)
{
GtkStyleContext *scale_context;
GtkStyleContext *contents_context;
GtkStyleContext *trough_context;
GtkStyleContext *slider_context;
GtkStyleContext *highlight_context;
gint contents_x, contents_y, contents_width, contents_height;
gint trough_height, slider_height;
scale_context = get_style (NULL, "scale.horizontal");
contents_context = get_style (scale_context, "contents");
trough_context = get_style (contents_context, "trough");
slider_context = get_style (trough_context, "slider");
highlight_context = get_style (trough_context, "highlight.top");
*height = 0;
query_size (scale_context, NULL, height);
query_size (contents_context, NULL, height);
query_size (trough_context, NULL, height);
query_size (slider_context, NULL, height);
query_size (highlight_context, NULL, height);
draw_style_common (scale_context, cr, x, y, width, *height,
&contents_x, &contents_y, &contents_width, &contents_height);
draw_style_common (contents_context, cr, contents_x, contents_y, contents_width, contents_height,
&contents_x, &contents_y, &contents_width, &contents_height);
/* Scale trough defines its size querying slider and highlight */
trough_height = 0;
query_size (trough_context, NULL, &trough_height);
slider_height = 0;
query_size (slider_context, NULL, &slider_height);
query_size (highlight_context, NULL, &slider_height);
trough_height += slider_height;
draw_style_common (trough_context, cr, contents_x, contents_y, contents_width, trough_height,
&contents_x, &contents_y, &contents_width, &contents_height);
draw_style_common (highlight_context, cr, contents_x, contents_y,
contents_width / 2, contents_height,
NULL, NULL, NULL, NULL);
draw_style_common (slider_context, cr, contents_x + position, contents_y, contents_height, contents_height,
NULL, NULL, NULL, NULL);
g_object_unref (scale_context);
g_object_unref (contents_context);
g_object_unref (trough_context);
g_object_unref (slider_context);
g_object_unref (highlight_context);
}
static void
draw_combobox (GtkWidget *widget,
cairo_t *cr,
gint x,
gint y,
gint width,
gboolean has_entry,
gint *height)
{
GtkStyleContext *combo_context;
GtkStyleContext *box_context;
GtkStyleContext *button_context;
GtkStyleContext *button_box_context;
GtkStyleContext *entry_context;
GtkStyleContext *arrow_context;
gint contents_x, contents_y, contents_width, contents_height;
gint button_width;
gint arrow_width, arrow_height, arrow_size;
/* This information is taken from the GtkComboBox docs, see "CSS nodes" */
combo_context = get_style (NULL, "combobox:focus");
box_context = get_style (combo_context, "box.horizontal.linked");
if (has_entry)
{
const char *siblings[3] = { "entry.combo:focus", "button.combo" , NULL };
entry_context = get_style_with_siblings (box_context, "entry.combo:focus", siblings, 0);
button_context = get_style_with_siblings (box_context, "button.combo", siblings, 1);
}
else
{
const char *siblings[2] = { "button.combo" , NULL };
button_context = get_style_with_siblings (box_context, "button.combo", siblings, 0);
}
button_box_context = get_style (button_context, "box.horizontal");
arrow_context = get_style (button_box_context, "arrow");
*height = 0;
query_size (combo_context, NULL, height);
query_size (box_context, NULL, height);
if (has_entry)
query_size (entry_context, NULL, height);
query_size (button_context, NULL, height);
query_size (button_box_context, NULL, height);
query_size (arrow_context, NULL, height);
gtk_style_context_get (arrow_context,
"min-width", &arrow_width, "min-height", &arrow_height, NULL);
arrow_size = MIN (arrow_width, arrow_height);
draw_style_common (combo_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
draw_style_common (box_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
if (has_entry)
{
button_width = *height;
draw_style_common (entry_context, cr, x, y, width - button_width, *height, NULL, NULL, NULL, NULL);
draw_style_common (button_context, cr, x + width - button_width, y, button_width, *height,
&contents_x, &contents_y, &contents_width, &contents_height);
}
else
{
button_width = width;
draw_style_common (button_context, cr, x, y, width, *height,
&contents_x, &contents_y, &contents_width, &contents_height);
}
draw_style_common (button_box_context, cr, contents_x, contents_y, contents_width, contents_height,
NULL, NULL, NULL, NULL);
draw_style_common (arrow_context, cr, contents_x, contents_y, contents_width, contents_height,
NULL, NULL, NULL, NULL);
gtk_render_arrow (arrow_context, cr, G_PI / 2,
contents_x + contents_width - arrow_size,
contents_y + (contents_height - arrow_size) / 2, arrow_size);
g_object_unref (arrow_context);
if (has_entry)
g_object_unref (entry_context);
g_object_unref (button_context);
g_object_unref (combo_context);
}
static void
draw_spinbutton (GtkWidget *widget,
cairo_t *cr,
gint x,
gint y,
gint width,
gint *height)
{
GtkStyleContext *spin_context;
GtkStyleContext *entry_context;
GtkStyleContext *up_context;
GtkStyleContext *down_context;
GtkIconTheme *icon_theme;
GtkIconInfo *icon_info;
GdkTexture *texture;
gint icon_width, icon_height, icon_size;
gint button_width;
gint contents_x, contents_y, contents_width, contents_height;
/* This information is taken from the GtkSpinButton docs, see "CSS nodes" */
spin_context = get_style (NULL, "spinbutton.horizontal:focus");
entry_context = get_style (spin_context, "entry:focus");
up_context = get_style (spin_context, "button.up:focus:active");
down_context = get_style (spin_context, "button.down:focus");
*height = 0;
query_size (spin_context, NULL, height);
query_size (entry_context, NULL, height);
query_size (up_context, NULL, height);
query_size (down_context, NULL, height);
button_width = *height;
draw_style_common (spin_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
draw_style_common (entry_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (widget));
gtk_style_context_get (up_context,
"min-width", &icon_width, "min-height", &icon_height, NULL);
icon_size = MIN (icon_width, icon_height);
icon_info = gtk_icon_theme_lookup_icon (icon_theme, "list-add-symbolic", icon_size, 0);
texture = GDK_TEXTURE (gtk_icon_info_load_symbolic_for_context (icon_info, up_context, NULL, NULL));
g_object_unref (icon_info);
draw_style_common (up_context, cr, x + width - button_width, y, button_width, *height,
&contents_x, &contents_y, &contents_width, &contents_height);
gtk_render_icon (up_context, cr, texture, contents_x, contents_y + (contents_height - icon_size) / 2);
g_object_unref (texture);
gtk_style_context_get (down_context,
"min-width", &icon_width, "min-height", &icon_height, NULL);
icon_size = MIN (icon_width, icon_height);
icon_info = gtk_icon_theme_lookup_icon (icon_theme, "list-remove-symbolic", icon_size, 0);
texture = GDK_TEXTURE (gtk_icon_info_load_symbolic_for_context (icon_info, down_context, NULL, NULL));
g_object_unref (icon_info);
draw_style_common (down_context, cr, x + width - 2 * button_width, y, button_width, *height,
&contents_x, &contents_y, &contents_width, &contents_height);
gtk_render_icon (down_context, cr, texture, contents_x, contents_y + (contents_height - icon_size) / 2);
g_object_unref (texture);
g_object_unref (down_context);
g_object_unref (up_context);
g_object_unref (entry_context);
g_object_unref (spin_context);
}
static void
draw_func (GtkDrawingArea *da,
cairo_t *cr,
int width,
int height,
gpointer data)
{
GtkWidget *widget = GTK_WIDGET (da);
gint panewidth;
gint x, y;
panewidth = width / 2;
cairo_rectangle (cr, 0, 0, width, height);
cairo_set_source_rgb (cr, 0.9, 0.9, 0.9);
cairo_fill (cr);
x = y = 10;
draw_horizontal_scrollbar (widget, cr, x, y, panewidth - 20, 30, GTK_STATE_FLAG_NORMAL, &height);
y += height + 8;
draw_horizontal_scrollbar (widget, cr, x, y, panewidth - 20, 40, GTK_STATE_FLAG_PRELIGHT, &height);
y += height + 8;
draw_horizontal_scrollbar (widget, cr, x, y, panewidth - 20, 50, GTK_STATE_FLAG_ACTIVE|GTK_STATE_FLAG_PRELIGHT, &height);
y += height + 8;
draw_text (widget, cr, x, y, panewidth - 20, 20, "Not selected", GTK_STATE_FLAG_NORMAL);
y += 20 + 10;
draw_text (widget, cr, x, y, panewidth - 20, 20, "Selected", GTK_STATE_FLAG_SELECTED);
x = 10;
y += 20 + 10;
draw_check (widget, cr, x, y, GTK_STATE_FLAG_NORMAL, &width, &height);
x += width + 10;
draw_check (widget, cr, x, y, GTK_STATE_FLAG_CHECKED, &width, &height);
x += width + 10;
draw_radio (widget, cr, x, y, GTK_STATE_FLAG_NORMAL, &width, &height);
x += width + 10;
draw_radio (widget, cr, x, y, GTK_STATE_FLAG_CHECKED, &width, &height);
x = 10;
y += height + 10;
draw_progress (widget, cr, x, y, panewidth - 20, 50, &height);
y += height + 10;
draw_scale (widget, cr, x, y, panewidth - 20, 75, &height);
y += height + 20;
draw_notebook (widget, cr, x, y, panewidth - 20, 160);
/* Second column */
x += panewidth;
y = 10;
draw_menu (widget, cr, x, y, panewidth - 20, &height);
y += height + 10;
draw_menubar (widget, cr, x, y, panewidth - 20, &height);
y += height + 20;
draw_spinbutton (widget, cr, x, y, panewidth - 20, &height);
y += height + 30;
draw_combobox (widget, cr, x, y, panewidth - 20, FALSE, &height);
y += height + 10;
draw_combobox (widget, cr, 10 + panewidth, y, panewidth - 20, TRUE, &height);
}
GtkWidget *
do_foreigndrawing (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
if (!window)
{
GtkWidget *box;
GtkWidget *da;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Foreign drawing");
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
gtk_container_add (GTK_CONTAINER (window), box);
da = gtk_drawing_area_new ();
gtk_drawing_area_set_content_width (GTK_DRAWING_AREA (da), 400);
gtk_drawing_area_set_content_height (GTK_DRAWING_AREA (da), 400);
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (da), draw_func, NULL, NULL);
gtk_widget_set_hexpand (da, TRUE);
gtk_widget_set_vexpand (da, TRUE);
gtk_container_add (GTK_CONTAINER (box), da);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_widget_destroy (window);
return window;
}
-137
View File
@@ -1,137 +0,0 @@
/* OpenGL/Gears
*
* This is a classic OpenGL demo, running in a GtkGLArea.
*/
#include <stdlib.h>
#include <gtk/gtk.h>
#include "gtkgears.h"
/************************************************************************
* DEMO CODE *
************************************************************************/
static void
on_axis_value_change (GtkAdjustment *adjustment,
gpointer data)
{
GtkGears *gears = GTK_GEARS (data);
int axis = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (adjustment), "axis"));
gtk_gears_set_axis (gears, axis, gtk_adjustment_get_value (adjustment));
}
static GtkWidget *
create_axis_slider (GtkGears *gears,
int axis)
{
GtkWidget *box, *label, *slider;
GtkAdjustment *adj;
const char *text;
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE);
switch (axis)
{
case GTK_GEARS_X_AXIS:
text = "X";
break;
case GTK_GEARS_Y_AXIS:
text = "Y";
break;
case GTK_GEARS_Z_AXIS:
text = "Z";
break;
default:
g_assert_not_reached ();
}
label = gtk_label_new (text);
gtk_box_append (GTK_BOX (box), label);
gtk_widget_show (label);
adj = gtk_adjustment_new (gtk_gears_get_axis (gears, axis), 0.0, 360.0, 1.0, 12.0, 0.0);
g_object_set_data (G_OBJECT (adj), "axis", GINT_TO_POINTER (axis));
g_signal_connect (adj, "value-changed",
G_CALLBACK (on_axis_value_change),
gears);
slider = gtk_scale_new (GTK_ORIENTATION_VERTICAL, adj);
gtk_scale_set_draw_value (GTK_SCALE (slider), FALSE);
gtk_box_append (GTK_BOX (box), slider);
gtk_widget_set_vexpand (slider, TRUE);
gtk_widget_show (slider);
gtk_widget_show (box);
return box;
}
GtkWidget *
do_gears (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
GtkWidget *box, *hbox, *fps_label, *gears, *overlay, *frame;
int i;
if (!window)
{
window = gtk_window_new ();
gtk_window_set_title (GTK_WINDOW (window), "Gears");
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
gtk_window_set_default_size (GTK_WINDOW (window), 640, 640);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
overlay = gtk_overlay_new ();
gtk_widget_set_margin_start (overlay, 12);
gtk_widget_set_margin_end (overlay, 12);
gtk_widget_set_margin_top (overlay, 12);
gtk_widget_set_margin_bottom (overlay, 12);
gtk_window_set_child (GTK_WINDOW (window), overlay);
frame = gtk_frame_new (NULL);
gtk_widget_set_halign (frame, GTK_ALIGN_START);
gtk_widget_set_valign (frame, GTK_ALIGN_START);
gtk_widget_add_css_class (frame, "app-notification");
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), frame);
fps_label = gtk_label_new ("");
gtk_widget_set_halign (fps_label, GTK_ALIGN_START);
gtk_frame_set_child (GTK_FRAME (frame), fps_label);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE);
gtk_box_set_spacing (GTK_BOX (box), 6);
gtk_overlay_set_child (GTK_OVERLAY (overlay), box);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE);
gtk_box_set_spacing (GTK_BOX (box), 6);
gtk_box_append (GTK_BOX (box), hbox);
gears = gtk_gears_new ();
gtk_widget_set_hexpand (gears, TRUE);
gtk_widget_set_vexpand (gears, TRUE);
gtk_box_append (GTK_BOX (hbox), gears);
for (i = 0; i < GTK_GEARS_N_AXIS; i++)
gtk_box_append (GTK_BOX (hbox), create_axis_slider (GTK_GEARS (gears), i));
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE);
gtk_box_set_spacing (GTK_BOX (hbox), 6);
gtk_box_append (GTK_BOX (box), hbox);
gtk_gears_set_fps_label (GTK_GEARS (gears), GTK_LABEL (fps_label));
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}
+3 -3
View File
@@ -17,9 +17,9 @@ typedef struct _DemoData DemoData;
struct _DemoData
{
const char *name;
const char *title;
const char *filename;
char *name;
char *title;
char *filename;
GDoDemoFunc func;
DemoData *children;
};
+6 -8
View File
@@ -94,12 +94,9 @@ drawing_area_draw (GtkDrawingArea *area,
cairo_pattern_t *pat;
cairo_matrix_t matrix;
gdouble angle, scale;
gdouble x_center, y_center;
gtk_gesture_get_bounding_box_center (GTK_GESTURE (zoom), &x_center, &y_center);
cairo_get_matrix (cr, &matrix);
cairo_matrix_translate (&matrix, x_center, y_center);
cairo_matrix_translate (&matrix, width / 2, height / 2);
cairo_save (cr);
@@ -146,13 +143,14 @@ do_gestures (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (window), 400, 400);
gtk_window_set_title (GTK_WINDOW (window), "Gestures");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
drawing_area = gtk_drawing_area_new ();
gtk_window_set_child (GTK_WINDOW (window), drawing_area);
gtk_container_add (GTK_CONTAINER (window), drawing_area);
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (drawing_area),
drawing_area_draw,
@@ -209,7 +207,7 @@ do_gestures (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;
}
+13 -16
View File
@@ -1,4 +1,4 @@
/* OpenGL/OpenGL Area
/* OpenGL Area
*
* GtkGLArea is a widget that allows custom drawing using OpenGL calls.
*/
@@ -354,7 +354,7 @@ create_axis_slider (int axis)
}
label = gtk_label_new (text);
gtk_box_append (GTK_BOX (box), label);
gtk_container_add (GTK_CONTAINER (box), label);
gtk_widget_show (label);
adj = gtk_adjustment_new (0.0, 0.0, 360.0, 1.0, 12.0, 0.0);
@@ -362,7 +362,7 @@ create_axis_slider (int axis)
G_CALLBACK (on_axis_value_change),
GINT_TO_POINTER (axis));
slider = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, adj);
gtk_box_append (GTK_BOX (box), slider);
gtk_container_add (GTK_CONTAINER (box), slider);
gtk_widget_set_hexpand (slider, TRUE);
gtk_widget_show (slider);
@@ -383,30 +383,27 @@ close_window (GtkWidget *widget)
rotation_angles[Z_AXIS] = 0.0;
}
static GtkWidget *
GtkWidget *
create_glarea_window (GtkWidget *do_widget)
{
GtkWidget *window, *box, *button, *controls;
int i;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "OpenGL Area");
gtk_window_set_default_size (GTK_WINDOW (window), 400, 600);
g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE);
gtk_widget_set_margin_start (box, 12);
gtk_widget_set_margin_end (box, 12);
gtk_widget_set_margin_top (box, 12);
gtk_widget_set_margin_bottom (box, 12);
g_object_set (box, "margin", 12, NULL);
gtk_box_set_spacing (GTK_BOX (box), 6);
gtk_window_set_child (GTK_WINDOW (window), box);
gtk_container_add (GTK_CONTAINER (window), box);
gl_area = gtk_gl_area_new ();
gtk_widget_set_hexpand (gl_area, TRUE);
gtk_widget_set_vexpand (gl_area, TRUE);
gtk_box_append (GTK_BOX (box), gl_area);
gtk_container_add (GTK_CONTAINER (box), gl_area);
/* We need to initialize and free GL resources, so we use
* the realize and unrealize signals on the widget
@@ -418,16 +415,16 @@ create_glarea_window (GtkWidget *do_widget)
g_signal_connect (gl_area, "render", G_CALLBACK (render), NULL);
controls = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE);
gtk_box_append (GTK_BOX (box), controls);
gtk_container_add (GTK_CONTAINER (box), controls);
gtk_widget_set_hexpand (controls, TRUE);
for (i = 0; i < N_AXIS; i++)
gtk_box_append (GTK_BOX (controls), create_axis_slider (i));
gtk_container_add (GTK_CONTAINER (controls), create_axis_slider (i));
button = gtk_button_new_with_label ("Quit");
gtk_widget_set_hexpand (button, TRUE);
gtk_box_append (GTK_BOX (box), button);
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_window_destroy), window);
gtk_container_add (GTK_CONTAINER (box), button);
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), window);
return window;
}
@@ -441,7 +438,7 @@ do_glarea (GtkWidget *do_widget)
if (!gtk_widget_get_visible (demo_window))
gtk_widget_show (demo_window);
else
gtk_window_destroy (GTK_WINDOW (demo_window));
gtk_widget_destroy (demo_window);
return demo_window;
}
+1 -1
View File
@@ -197,7 +197,7 @@ gtk_gears_class_init (GtkGearsClass *klass)
* @param v the vertex to fill
* @param x the x coordinate
* @param y the y coordinate
* @param z the z coordinate
* @param z the z coortinate
* @param n pointer to the normal table
*
* @return the operation error code
+16 -14
View File
@@ -2,8 +2,9 @@
*
* GtkHeaderBar is a container that is suitable for implementing
* window titlebars. One of its features is that it can position
* a title centered with regard to the full width, regardless of
* variable-width content at the left or right.
* a title (and optional subtitle) centered with regard to the
* full width, regardless of variable-width content at the left
* or right.
*
* It is commonly used with gtk_window_set_titlebar()
*/
@@ -22,43 +23,44 @@ do_headerbar (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Welcome to Facebook - Log in, sign up or learn more");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
header = gtk_header_bar_new ();
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
gtk_header_bar_set_title (GTK_HEADER_BAR (header), "Welcome to Facebook - Log in, sign up or learn more");
gtk_header_bar_set_has_subtitle (GTK_HEADER_BAR (header), FALSE);
button = gtk_button_new ();
icon = g_themed_icon_new ("mail-send-receive-symbolic");
image = gtk_image_new_from_gicon (icon);
g_object_unref (icon);
gtk_button_set_child (GTK_BUTTON (button), image);
gtk_container_add (GTK_CONTAINER (button), image);
gtk_header_bar_pack_end (GTK_HEADER_BAR (header), button);
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_add_css_class (box, "linked");
gtk_style_context_add_class (gtk_widget_get_style_context (box), "linked");
button = gtk_button_new ();
gtk_button_set_child (GTK_BUTTON (button), gtk_image_new_from_icon_name ("pan-start-symbolic"));
gtk_box_append (GTK_BOX (box), button);
gtk_container_add (GTK_CONTAINER (button), gtk_image_new_from_icon_name ("pan-start-symbolic"));
gtk_container_add (GTK_CONTAINER (box), button);
button = gtk_button_new ();
gtk_button_set_child (GTK_BUTTON (button), gtk_image_new_from_icon_name ("pan-end-symbolic"));
gtk_box_append (GTK_BOX (box), button);
gtk_container_add (GTK_CONTAINER (button), gtk_image_new_from_icon_name ("pan-end-symbolic"));
gtk_container_add (GTK_CONTAINER (box), button);
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), box);
gtk_window_set_titlebar (GTK_WINDOW (window), header);
gtk_window_set_child (GTK_WINDOW (window), gtk_text_view_new ());
gtk_container_add (GTK_CONTAINER (window), gtk_text_view_new ());
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
return window;
}
-25
View File
@@ -1,25 +0,0 @@
<interface>
<object class="GtkShortcutsWindow" id="help_overlay">
<child>
<object class="GtkShortcutsSection">
<child>
<object class="GtkShortcutsGroup">
<property name="title">General</property>
<child>
<object class="GtkShortcutsShortcut">
<property name="accelerator">F1</property>
<property name="title">Show About Dialog</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="accelerator">&lt;Control&gt;q</property>
<property name="title">Quit</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>
+8 -6
View File
@@ -17,7 +17,7 @@
static void
insert_link (GtkTextBuffer *buffer,
GtkTextIter *iter,
const char *text,
gchar *text,
gint page)
{
GtkTextTag *tag;
@@ -232,12 +232,14 @@ do_hypertext (GtkWidget *do_widget)
GtkTextBuffer *buffer;
GtkEventController *controller;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Hypertext");
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_default_size (GTK_WINDOW (window), 450, 450);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
view = gtk_text_view_new ();
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD);
@@ -264,8 +266,8 @@ do_hypertext (GtkWidget *do_widget)
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_window_set_child (GTK_WINDOW (window), sw);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), view);
gtk_container_add (GTK_CONTAINER (window), sw);
gtk_container_add (GTK_CONTAINER (sw), view);
show_page (buffer, 1);
}
@@ -273,7 +275,7 @@ do_hypertext (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;
}
+19 -70
View File
@@ -12,7 +12,7 @@ static GtkWidget *window = NULL;
static GtkWidget *scrolledwindow;
static int selected;
#define N_WIDGET_TYPES 6
#define N_WIDGET_TYPES 4
static int hincrement = 5;
@@ -52,10 +52,7 @@ populate_icons (void)
grid = gtk_grid_new ();
gtk_widget_set_halign (grid, GTK_ALIGN_CENTER);
gtk_widget_set_margin_start (grid, 10);
gtk_widget_set_margin_end (grid, 10);
gtk_widget_set_margin_top (grid, 10);
gtk_widget_set_margin_bottom (grid, 10);
g_object_set (grid, "margin", 10, NULL);
gtk_grid_set_row_spacing (GTK_GRID (grid), 10);
gtk_grid_set_column_spacing (GTK_GRID (grid), 10);
@@ -64,12 +61,11 @@ populate_icons (void)
gtk_grid_attach (GTK_GRID (grid), create_icon (), left, top, 1, 1);
hincrement = 0;
vincrement = 5;
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolledwindow), grid);
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
gtk_container_add (GTK_CONTAINER (scrolledwindow), grid);
}
static char *content;
@@ -101,12 +97,11 @@ populate_text (gboolean hilight)
gtk_text_view_set_buffer (GTK_TEXT_VIEW (textview), buffer);
hincrement = 0;
vincrement = 5;
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolledwindow), textview);
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
gtk_container_add (GTK_CONTAINER (scrolledwindow), textview);
}
static void
@@ -126,48 +121,11 @@ populate_image (void)
gtk_picture_set_can_shrink (GTK_PICTURE (image), FALSE);
hincrement = 5;
vincrement = 5;
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolledwindow), image);
}
extern GtkWidget *create_weather_view (void);
static void
populate_list (void)
{
GtkWidget *list;
list = create_weather_view ();
hincrement = 5;
vincrement = 0;
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolledwindow), list);
}
extern GtkWidget *create_color_grid (void);
static void
populate_grid (void)
{
GtkWidget *list;
list = create_color_grid ();
hincrement = 0;
vincrement = 5;
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolledwindow), list);
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_container_add (GTK_CONTAINER (scrolledwindow), image);
}
static void
@@ -176,8 +134,9 @@ set_widget_type (int type)
if (tick_cb)
gtk_widget_remove_tick_callback (window, tick_cb);
if (gtk_scrolled_window_get_child (GTK_SCROLLED_WINDOW (scrolledwindow)))
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolledwindow), NULL);
if (gtk_bin_get_child (GTK_BIN (scrolledwindow)))
gtk_container_remove (GTK_CONTAINER (scrolledwindow),
gtk_bin_get_child (GTK_BIN (scrolledwindow)));
selected = type;
@@ -203,16 +162,6 @@ set_widget_type (int type)
populate_image ();
break;
case 4:
gtk_window_set_title (GTK_WINDOW (window), "Scrolling a list");
populate_list ();
break;
case 5:
gtk_window_set_title (GTK_WINDOW (window), "Scrolling a grid");
populate_grid ();
break;
default:
g_assert_not_reached ();
}
@@ -258,23 +207,23 @@ do_iconscroll (GtkWidget *do_widget)
builder = gtk_builder_new_from_resource ("/iconscroll/iconscroll.ui");
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
scrolledwindow = GTK_WIDGET (gtk_builder_get_object (builder, "scrolledwindow"));
gtk_widget_realize (window);
hadjustment = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "hadjustment"));
vadjustment = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "vadjustment"));
set_widget_type (0);
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;
}
+3 -6
View File
@@ -31,12 +31,9 @@
<child>
<object class="GtkScrolledWindow" id="scrolledwindow">
<property name="hscrollbar-policy">never</property>
<property name="hadjustment">
<object class="GtkAdjustment" id="hadjustment"/>
</property>
<property name="vadjustment">
<object class="GtkAdjustment" id="vadjustment"/>
</property>
<property name="vscrollbar-policy">automatic</property>
<property name="hadjustment"><object class="GtkAdjustment" id="hadjustment"/></property>
<property name="vadjustment"><object class="GtkAdjustment" id="vadjustment"/></property>
</object>
</child>
</object>
+28 -19
View File
@@ -26,7 +26,7 @@ enum
static GdkPixbuf *file_pixbuf, *folder_pixbuf;
gchar *parent;
GtkWidget *up_button;
GtkToolItem *up_button;
/* Loads the images for the demo and returns whether the operation succeeded */
static void
@@ -188,8 +188,8 @@ item_activated (GtkIconView *icon_view,
}
static void
up_clicked (GtkButton *item,
gpointer user_data)
up_clicked (GtkToolItem *item,
gpointer user_data)
{
GtkListStore *store;
gchar *dir_name;
@@ -209,8 +209,8 @@ up_clicked (GtkButton *item,
}
static void
home_clicked (GtkButton *item,
gpointer user_data)
home_clicked (GtkToolItem *item,
gpointer user_data)
{
GtkListStore *store;
@@ -228,7 +228,7 @@ home_clicked (GtkButton *item,
static void close_window(void)
{
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
window = NULL;
g_object_unref (file_pixbuf);
@@ -248,9 +248,9 @@ do_iconview (GtkWidget *do_widget)
GtkListStore *store;
GtkWidget *vbox;
GtkWidget *tool_bar;
GtkWidget *home_button;
GtkToolItem *home_button;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (window), 650, 400);
gtk_window_set_display (GTK_WINDOW (window),
@@ -263,27 +263,36 @@ do_iconview (GtkWidget *do_widget)
load_pixbufs ();
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_window_set_child (GTK_WINDOW (window), vbox);
gtk_container_add (GTK_CONTAINER (window), vbox);
tool_bar = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_append (GTK_BOX (vbox), tool_bar);
tool_bar = gtk_toolbar_new ();
gtk_container_add (GTK_CONTAINER (vbox), tool_bar);
up_button = gtk_button_new_with_mnemonic ("_Up");
up_button = gtk_tool_button_new (NULL, NULL);
gtk_tool_button_set_label (GTK_TOOL_BUTTON (up_button), _("_Up"));
gtk_tool_button_set_use_underline (GTK_TOOL_BUTTON (up_button), TRUE);
gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (up_button), "go-up");
gtk_tool_item_set_is_important (up_button, TRUE);
gtk_widget_set_sensitive (GTK_WIDGET (up_button), FALSE);
gtk_box_append (GTK_BOX (tool_bar), up_button);
gtk_toolbar_insert (GTK_TOOLBAR (tool_bar), up_button, -1);
home_button = gtk_button_new_with_mnemonic ("_Home");
gtk_box_append (GTK_BOX (tool_bar), home_button);
home_button = gtk_tool_button_new (NULL, NULL);
gtk_tool_button_set_label (GTK_TOOL_BUTTON (home_button), _("_Home"));
gtk_tool_button_set_use_underline (GTK_TOOL_BUTTON (home_button), TRUE);
gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (home_button), "go-home");
gtk_tool_item_set_is_important (home_button, TRUE);
gtk_toolbar_insert (GTK_TOOLBAR (tool_bar), home_button, -1);
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (sw), TRUE);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
GTK_SHADOW_ETCHED_IN);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_widget_set_vexpand (sw, TRUE);
gtk_box_append (GTK_BOX (vbox), sw);
gtk_container_add (GTK_CONTAINER (vbox), sw);
/* Create the store and fill it with the contents of '/' */
parent = g_strdup ("/");
@@ -312,7 +321,7 @@ do_iconview (GtkWidget *do_widget)
/* Connect to the "item-activated" signal */
g_signal_connect (icon_view, "item-activated",
G_CALLBACK (item_activated), store);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), icon_view);
gtk_container_add (GTK_CONTAINER (sw), icon_view);
gtk_widget_grab_focus (icon_view);
}
@@ -320,7 +329,7 @@ do_iconview (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;
}
+6 -4
View File
@@ -106,12 +106,14 @@ do_iconview_edit (GtkWidget *do_widget)
GtkListStore *store;
GtkCellRenderer *renderer;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Editing and Drag-and-Drop");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
store = create_store ();
fill_store (store);
@@ -144,13 +146,13 @@ do_iconview_edit (GtkWidget *do_widget)
"text", COL_TEXT,
NULL);
gtk_window_set_child (GTK_WINDOW (window), icon_view);
gtk_container_add (GTK_CONTAINER (window), icon_view);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
return window;
}
+53 -42
View File
@@ -91,7 +91,7 @@ progressive_timeout (gpointer data)
g_error_free (error);
g_signal_connect (dialog, "response",
G_CALLBACK (gtk_window_destroy), NULL);
G_CALLBACK (gtk_widget_destroy), NULL);
g_object_unref (image_stream);
image_stream = NULL;
@@ -119,7 +119,7 @@ progressive_timeout (gpointer data)
g_error_free (error);
g_signal_connect (dialog, "response",
G_CALLBACK (gtk_window_destroy), NULL);
G_CALLBACK (gtk_widget_destroy), NULL);
g_object_unref (image_stream);
image_stream = NULL;
@@ -152,7 +152,7 @@ progressive_timeout (gpointer data)
g_error_free (error);
g_signal_connect (dialog, "response",
G_CALLBACK (gtk_window_destroy), NULL);
G_CALLBACK (gtk_widget_destroy), NULL);
gtk_widget_show (dialog);
@@ -189,7 +189,7 @@ progressive_timeout (gpointer data)
g_error_free (error);
g_signal_connect (dialog, "response",
G_CALLBACK (gtk_window_destroy), NULL);
G_CALLBACK (gtk_widget_destroy), NULL);
gtk_widget_show (dialog);
@@ -223,7 +223,7 @@ progressive_timeout (gpointer data)
g_error_free (error);
g_signal_connect (dialog, "response",
G_CALLBACK (gtk_window_destroy), NULL);
G_CALLBACK (gtk_widget_destroy), NULL);
gtk_widget_show (dialog);
@@ -293,16 +293,24 @@ static void
toggle_sensitivity_callback (GtkWidget *togglebutton,
gpointer user_data)
{
GtkWidget *child;
GtkContainer *container = user_data;
GList *list;
GList *tmp;
for (child = gtk_widget_get_first_child (GTK_WIDGET (user_data));
child != NULL;
child = gtk_widget_get_next_sibling (child))
list = gtk_container_get_children (container);
tmp = list;
while (tmp != NULL)
{
/* don't disable our toggle */
if (child != togglebutton)
gtk_widget_set_sensitive (child, !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (togglebutton)));
if (GTK_WIDGET (tmp->data) != togglebutton)
gtk_widget_set_sensitive (GTK_WIDGET (tmp->data),
!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (togglebutton)));
tmp = tmp->next;
}
g_list_free (list);
}
@@ -323,42 +331,41 @@ do_images (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Images");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
g_signal_connect (window, "destroy",
G_CALLBACK (cleanup_callback), NULL);
base_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8);
gtk_widget_set_margin_start (base_vbox, 16);
gtk_widget_set_margin_end (base_vbox, 16);
gtk_widget_set_margin_top (base_vbox, 16);
gtk_widget_set_margin_bottom (base_vbox, 16);
gtk_window_set_child (GTK_WINDOW (window), base_vbox);
g_object_set (base_vbox, "margin", 16, NULL);
gtk_container_add (GTK_CONTAINER (window), base_vbox);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 16);
gtk_box_append (GTK_BOX (base_vbox), hbox);
gtk_container_add (GTK_CONTAINER (base_vbox), hbox);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8);
gtk_box_append (GTK_BOX (hbox), vbox);
gtk_container_add (GTK_CONTAINER (hbox), vbox);
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label),
"<u>Image loaded from a file</u>");
gtk_box_append (GTK_BOX (vbox), label);
gtk_container_add (GTK_CONTAINER (vbox), label);
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
gtk_widget_set_halign (frame, GTK_ALIGN_CENTER);
gtk_widget_set_valign (frame, GTK_ALIGN_CENTER);
gtk_box_append (GTK_BOX (vbox), frame);
gtk_container_add (GTK_CONTAINER (vbox), frame);
image = gtk_image_new_from_icon_name ("gtk3-demo");
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
gtk_frame_set_child (GTK_FRAME (frame), image);
gtk_container_add (GTK_CONTAINER (frame), image);
/* Animation */
@@ -366,94 +373,98 @@ do_images (GtkWidget *do_widget)
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label),
"<u>Animation loaded from a file</u>");
gtk_box_append (GTK_BOX (vbox), label);
gtk_container_add (GTK_CONTAINER (vbox), label);
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
gtk_widget_set_halign (frame, GTK_ALIGN_CENTER);
gtk_widget_set_valign (frame, GTK_ALIGN_CENTER);
gtk_box_append (GTK_BOX (vbox), frame);
gtk_container_add (GTK_CONTAINER (vbox), frame);
picture = gtk_picture_new_for_resource ("/images/floppybuddy.gif");
gtk_frame_set_child (GTK_FRAME (frame), picture);
gtk_container_add (GTK_CONTAINER (frame), picture);
/* Symbolic icon */
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label),
"<u>Symbolic themed icon</u>");
gtk_box_append (GTK_BOX (vbox), label);
gtk_container_add (GTK_CONTAINER (vbox), label);
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
gtk_widget_set_halign (frame, GTK_ALIGN_CENTER);
gtk_widget_set_valign (frame, GTK_ALIGN_CENTER);
gtk_box_append (GTK_BOX (vbox), frame);
gtk_container_add (GTK_CONTAINER (vbox), frame);
gicon = g_themed_icon_new_with_default_fallbacks ("battery-caution-charging-symbolic");
image = gtk_image_new_from_gicon (gicon);
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
gtk_frame_set_child (GTK_FRAME (frame), image);
gtk_container_add (GTK_CONTAINER (frame), image);
/* Progressive */
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8);
gtk_box_append (GTK_BOX (hbox), vbox);
gtk_container_add (GTK_CONTAINER (hbox), vbox);
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label),
"<u>Progressive image loading</u>");
gtk_box_append (GTK_BOX (vbox), label);
gtk_container_add (GTK_CONTAINER (vbox), label);
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
gtk_widget_set_halign (frame, GTK_ALIGN_CENTER);
gtk_widget_set_valign (frame, GTK_ALIGN_CENTER);
gtk_box_append (GTK_BOX (vbox), frame);
gtk_container_add (GTK_CONTAINER (vbox), frame);
/* Create an empty image for now; the progressive loader
* will create the pixbuf and fill it in.
*/
picture = gtk_picture_new ();
gtk_frame_set_child (GTK_FRAME (frame), picture);
gtk_container_add (GTK_CONTAINER (frame), picture);
start_progressive_loading (picture);
/* Video */
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8);
gtk_box_append (GTK_BOX (hbox), vbox);
gtk_container_add (GTK_CONTAINER (hbox), vbox);
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label),
"<u>Displaying video</u>");
gtk_box_append (GTK_BOX (vbox), label);
gtk_container_add (GTK_CONTAINER (vbox), label);
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
gtk_widget_set_halign (frame, GTK_ALIGN_CENTER);
gtk_widget_set_valign (frame, GTK_ALIGN_CENTER);
gtk_box_append (GTK_BOX (vbox), frame);
gtk_container_add (GTK_CONTAINER (vbox), frame);
video = gtk_video_new_for_resource ("/images/gtk-logo.webm");
gtk_media_stream_set_loop (gtk_video_get_media_stream (GTK_VIDEO (video)), TRUE);
gtk_frame_set_child (GTK_FRAME (frame), video);
gtk_container_add (GTK_CONTAINER (frame), video);
/* Widget paintables */
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8);
gtk_box_append (GTK_BOX (hbox), vbox);
gtk_container_add (GTK_CONTAINER (hbox), vbox);
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label),
"<u>GtkWidgetPaintable</u>");
gtk_box_append (GTK_BOX (vbox), label);
gtk_container_add (GTK_CONTAINER (vbox), label);
paintable = gtk_widget_paintable_new (do_widget);
picture = gtk_picture_new_for_paintable (paintable);
gtk_widget_set_size_request (picture, 100, 100);
gtk_widget_set_valign (picture, GTK_ALIGN_START);
gtk_box_append (GTK_BOX (vbox), picture);
gtk_container_add (GTK_CONTAINER (vbox), picture);
/* Sensitivity control */
button = gtk_toggle_button_new_with_mnemonic ("_Insensitive");
gtk_box_append (GTK_BOX (base_vbox), button);
gtk_container_add (GTK_CONTAINER (base_vbox), button);
g_signal_connect (button, "toggled",
G_CALLBACK (toggle_sensitivity_callback),
@@ -463,7 +474,7 @@ do_images (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;
}
+36 -36
View File
@@ -29,8 +29,10 @@ on_bar_response (GtkInfoBar *info_bar,
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
"Your response has id %d", response_id);
g_signal_connect_swapped (dialog, "response",
G_CALLBACK (gtk_window_destroy), dialog);
g_signal_connect_swapped (dialog,
"response",
G_CALLBACK (gtk_widget_destroy),
dialog);
gtk_widget_show (dialog);
}
@@ -42,6 +44,7 @@ do_infobar (GtkWidget *do_widget)
GtkWidget *frame;
GtkWidget *bar;
GtkWidget *vbox;
GtkWidget *vbox2;
GtkWidget *label;
GtkWidget *actions;
GtkWidget *button;
@@ -49,104 +52,101 @@ do_infobar (GtkWidget *do_widget)
if (!window)
{
actions = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_add_css_class (actions, "linked");
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Info Bars");
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
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);
gtk_window_set_child (GTK_WINDOW (window), vbox);
g_object_set (vbox, "margin", 8, NULL);
gtk_container_add (GTK_CONTAINER (window), vbox);
bar = gtk_info_bar_new ();
gtk_box_append (GTK_BOX (vbox), bar);
gtk_container_add (GTK_CONTAINER (vbox), bar);
gtk_info_bar_set_message_type (GTK_INFO_BAR (bar), GTK_MESSAGE_INFO);
label = gtk_label_new ("This is an info bar with message type GTK_MESSAGE_INFO");
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_info_bar_add_child (GTK_INFO_BAR (bar), label);
gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (bar))), label);
button = gtk_toggle_button_new_with_label ("Message");
g_object_bind_property (bar, "revealed", button, "active", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
gtk_box_append (GTK_BOX (actions), button);
gtk_container_add (GTK_CONTAINER (actions), button);
bar = gtk_info_bar_new ();
gtk_box_append (GTK_BOX (vbox), bar);
gtk_container_add (GTK_CONTAINER (vbox), bar);
gtk_info_bar_set_message_type (GTK_INFO_BAR (bar), GTK_MESSAGE_WARNING);
label = gtk_label_new ("This is an info bar with message type GTK_MESSAGE_WARNING");
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_info_bar_add_child (GTK_INFO_BAR (bar), label);
gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (bar))), label);
button = gtk_toggle_button_new_with_label ("Warning");
g_object_bind_property (bar, "revealed", button, "active", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
gtk_box_append (GTK_BOX (actions), button);
gtk_container_add (GTK_CONTAINER (actions), button);
bar = gtk_info_bar_new_with_buttons (_("_OK"), GTK_RESPONSE_OK, NULL);
gtk_info_bar_set_show_close_button (GTK_INFO_BAR (bar), TRUE);
g_signal_connect (bar, "response", G_CALLBACK (on_bar_response), window);
gtk_box_append (GTK_BOX (vbox), bar);
gtk_container_add (GTK_CONTAINER (vbox), bar);
gtk_info_bar_set_message_type (GTK_INFO_BAR (bar), GTK_MESSAGE_QUESTION);
label = gtk_label_new ("This is an info bar with message type GTK_MESSAGE_QUESTION");
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_info_bar_add_child (GTK_INFO_BAR (bar), label);
gtk_info_bar_set_default_response (GTK_INFO_BAR (bar), GTK_RESPONSE_OK);
gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (bar))), label);
button = gtk_toggle_button_new_with_label ("Question");
g_object_bind_property (bar, "revealed", button, "active", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
gtk_box_append (GTK_BOX (actions), button);
gtk_container_add (GTK_CONTAINER (actions), button);
bar = gtk_info_bar_new ();
gtk_box_append (GTK_BOX (vbox), bar);
gtk_container_add (GTK_CONTAINER (vbox), bar);
gtk_info_bar_set_message_type (GTK_INFO_BAR (bar), GTK_MESSAGE_ERROR);
label = gtk_label_new ("This is an info bar with message type GTK_MESSAGE_ERROR");
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_info_bar_add_child (GTK_INFO_BAR (bar), label);
gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (bar))), label);
button = gtk_toggle_button_new_with_label ("Error");
g_object_bind_property (bar, "revealed", button, "active", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
gtk_box_append (GTK_BOX (actions), button);
gtk_container_add (GTK_CONTAINER (actions), button);
bar = gtk_info_bar_new ();
gtk_box_append (GTK_BOX (vbox), bar);
gtk_container_add (GTK_CONTAINER (vbox), bar);
gtk_info_bar_set_message_type (GTK_INFO_BAR (bar), GTK_MESSAGE_OTHER);
label = gtk_label_new ("This is an info bar with message type GTK_MESSAGE_OTHER");
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_info_bar_add_child (GTK_INFO_BAR (bar), label);
gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (bar))), label);
button = gtk_toggle_button_new_with_label ("Other");
g_object_bind_property (bar, "revealed", button, "active", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
gtk_box_append (GTK_BOX (actions), button);
gtk_container_add (GTK_CONTAINER (actions), button);
frame = gtk_frame_new ("An example of different info bars");
frame = gtk_frame_new ("Info bars");
gtk_widget_set_margin_top (frame, 8);
gtk_widget_set_margin_bottom (frame, 8);
gtk_box_append (GTK_BOX (vbox), frame);
gtk_container_add (GTK_CONTAINER (vbox), frame);
gtk_widget_set_halign (actions, GTK_ALIGN_CENTER);
vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8);
g_object_set (vbox2, "margin", 8, NULL);
gtk_container_add (GTK_CONTAINER (frame), vbox2);
gtk_widget_set_margin_start (actions, 8);
gtk_widget_set_margin_end (actions, 8);
gtk_widget_set_margin_top (actions, 8);
gtk_widget_set_margin_bottom (actions, 8);
gtk_frame_set_child (GTK_FRAME (frame), actions);
/* Standard message dialog */
label = gtk_label_new ("An example of different info bars");
gtk_container_add (GTK_CONTAINER (vbox2), label);
gtk_container_add (GTK_CONTAINER (vbox2), actions);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
return window;
}
+11 -20
View File
@@ -1,7 +1,7 @@
/* Links
*
* GtkLabel can show hyperlinks. The default action is to call
* gtk_show_uri() on their URI, but it is possible to override
* gtk_show_uri_on_window() on their URI, but it is possible to override
* this with a custom handler.
*/
@@ -12,7 +12,7 @@ response_cb (GtkWidget *dialog,
gint response_id,
gpointer data)
{
gtk_window_destroy (GTK_WINDOW (dialog));
gtk_widget_destroy (dialog);
}
static gboolean
@@ -30,8 +30,6 @@ activate_link (GtkWidget *label,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
"Keyboard navigation");
gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog),
"The term <i>keynav</i> is a shorthand for "
"keyboard navigation and refers to the process of using "
"a program (exclusively) via keyboard input.");
@@ -54,40 +52,33 @@ do_links (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Links");
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
label = gtk_label_new ("Some <a href=\"http://en.wikipedia.org/wiki/Text\""
"title=\"plain text\">text</a> may be marked up "
"as hyperlinks, which can be clicked "
"or activated via <a href=\"keynav\">keynav</a> "
"and they work fine with other markup, like when "
"title=\"plain text\">text</a> may be marked up\n"
"as hyperlinks, which can be clicked\n"
"or activated via <a href=\"keynav\">keynav</a>\n"
"and they work fine with other markup, like when\n"
"searching on <a href=\"http://www.google.com/\">"
"<span color=\"#0266C8\">G</span><span color=\"#F90101\">o</span>"
"<span color=\"#F2B50F\">o</span><span color=\"#0266C8\">g</span>"
"<span color=\"#00933B\">l</span><span color=\"#F90101\">e</span>"
"</a>.");
gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
gtk_label_set_max_width_chars (GTK_LABEL (label), 40);
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
gtk_label_set_wrap_mode (GTK_LABEL (label), PANGO_WRAP_WORD);
g_signal_connect (label, "activate-link", G_CALLBACK (activate_link), NULL);
gtk_widget_set_margin_start (label, 20);
gtk_widget_set_margin_end (label, 20);
gtk_widget_set_margin_top (label, 20);
gtk_widget_set_margin_bottom (label, 20);
gtk_window_set_child (GTK_WINDOW (window), label);
gtk_container_add (GTK_CONTAINER (window), label);
gtk_widget_show (label);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
return window;
}
+29 -27
View File
@@ -16,9 +16,10 @@ typedef struct
{
const gboolean fixed;
const guint number;
const char *severity;
const char *description;
} Bug;
const gchar *severity;
const gchar *description;
}
Bug;
enum
{
@@ -33,7 +34,7 @@ enum
NUM_COLUMNS
};
static Bug bugs[] =
static Bug data[] =
{
{ FALSE, 60482, "Normal", "scrollable notebooks and hidden tabs" },
{ FALSE, 60620, "Critical", "gdk_surface_clear_area (gdksurface-win32.c) is not thread-safe" },
@@ -97,9 +98,9 @@ create_model (void)
G_TYPE_BOOLEAN);
/* add data to the list store */
for (i = 0; i < G_N_ELEMENTS (bugs); i++)
for (i = 0; i < G_N_ELEMENTS (data); i++)
{
const char *icon_name;
gchar *icon_name;
gboolean sensitive;
if (i == 1 || i == 3)
@@ -112,10 +113,10 @@ create_model (void)
sensitive = TRUE;
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
COLUMN_FIXED, bugs[i].fixed,
COLUMN_NUMBER, bugs[i].number,
COLUMN_SEVERITY, bugs[i].severity,
COLUMN_DESCRIPTION, bugs[i].description,
COLUMN_FIXED, data[i].fixed,
COLUMN_NUMBER, data[i].number,
COLUMN_SEVERITY, data[i].severity,
COLUMN_DESCRIPTION, data[i].description,
COLUMN_PULSE, 0,
COLUMN_ICON, icon_name,
COLUMN_ACTIVE, FALSE,
@@ -128,23 +129,23 @@ create_model (void)
static void
fixed_toggled (GtkCellRendererToggle *cell,
char *path_str,
gchar *path_str,
gpointer data)
{
GtkTreeModel *tree_model = (GtkTreeModel *)data;
GtkTreeModel *model = (GtkTreeModel *)data;
GtkTreeIter iter;
GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
gboolean fixed;
/* get toggled iter */
gtk_tree_model_get_iter (tree_model, &iter, path);
gtk_tree_model_get (tree_model, &iter, COLUMN_FIXED, &fixed, -1);
gtk_tree_model_get_iter (model, &iter, path);
gtk_tree_model_get (model, &iter, COLUMN_FIXED, &fixed, -1);
/* do something with the value */
fixed ^= 1;
/* set new value */
gtk_list_store_set (GTK_LIST_STORE (tree_model), &iter, COLUMN_FIXED, fixed, -1);
gtk_list_store_set (GTK_LIST_STORE (model), &iter, COLUMN_FIXED, fixed, -1);
/* clean up */
gtk_tree_path_free (path);
@@ -155,6 +156,7 @@ add_columns (GtkTreeView *treeview)
{
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
GtkTreeModel *model = gtk_tree_view_get_model (treeview);
/* column for fixed toggles */
renderer = gtk_cell_renderer_toggle_new ();
@@ -253,28 +255,28 @@ do_list_store (GtkWidget *do_widget)
GtkWidget *treeview;
/* create window, etc */
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "List Store");
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, 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 (window), vbox);
label = gtk_label_new ("This is the bug list (note: not based on real data, it would be nice to have a nice ODBC interface to bugzilla or so, though).");
gtk_box_append (GTK_BOX (vbox), label);
gtk_container_add (GTK_CONTAINER (vbox), label);
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (sw), TRUE);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
GTK_SHADOW_ETCHED_IN);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
gtk_box_append (GTK_BOX (vbox), sw);
gtk_container_add (GTK_CONTAINER (vbox), sw);
/* create tree model */
model = create_model ();
@@ -287,7 +289,7 @@ do_list_store (GtkWidget *do_widget)
g_object_unref (model);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), treeview);
gtk_container_add (GTK_CONTAINER (sw), treeview);
/* add columns to the tree view */
add_columns (GTK_TREE_VIEW (treeview));
@@ -307,7 +309,7 @@ do_list_store (GtkWidget *do_widget)
}
else
{
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
window = NULL;
if (timeout != 0)
{
+14 -9
View File
@@ -351,23 +351,28 @@ do_listbox (GtkWidget *do_widget)
{
avatar_pixbuf_other = gdk_pixbuf_new_from_resource_at_scale ("/listbox/apple-red.png", 32, 32, FALSE, NULL);
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "List Box");
gtk_window_set_default_size (GTK_WINDOW (window), 400, 600);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
gtk_window_set_default_size (GTK_WINDOW (window),
400, 600);
/* NULL window variable when window is closed */
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed),
&window);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
gtk_window_set_child (GTK_WINDOW (window), vbox);
gtk_container_add (GTK_CONTAINER (window), vbox);
label = gtk_label_new ("Messages from GTK and friends");
gtk_box_append (GTK_BOX (vbox), label);
gtk_container_add (GTK_CONTAINER (vbox), label);
scrolled = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_widget_set_vexpand (scrolled, TRUE);
gtk_box_append (GTK_BOX (vbox), scrolled);
gtk_container_add (GTK_CONTAINER (vbox), scrolled);
listbox = gtk_list_box_new ();
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolled), listbox);
gtk_container_add (GTK_CONTAINER (scrolled), listbox);
gtk_list_box_set_sort_func (GTK_LIST_BOX (listbox), (GtkListBoxSortFunc)gtk_message_row_sort, listbox, NULL);
gtk_list_box_set_activate_on_single_click (GTK_LIST_BOX (listbox), FALSE);
@@ -381,7 +386,7 @@ do_listbox (GtkWidget *do_widget)
message = gtk_message_new (lines[i]);
row = gtk_message_row_new (message);
gtk_widget_show (GTK_WIDGET (row));
gtk_list_box_insert (GTK_LIST_BOX (listbox), GTK_WIDGET (row), -1);
gtk_container_add (GTK_CONTAINER (listbox), GTK_WIDGET (row));
}
g_strfreev (lines);
@@ -391,7 +396,7 @@ do_listbox (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;
}
+34 -20
View File
@@ -1,15 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface domain="gtk40">
<menu id="menu1">
<section>
<item>
<attribute name="label" translatable="yes">Email message</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Embed message</attribute>
</item>
</section>
</menu>
<object class="GtkMenu" id="menu1">
<child>
<object class="GtkMenuItem" id="menuitem1">
<property name="label" translatable="yes">Email message</property>
<property name="use-underline">1</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menuitem2">
<property name="label" translatable="yes">Embed message</property>
<property name="use-underline">1</property>
</object>
</child>
</object>
<template class="GtkMessageRow" parent="GtkListBoxRow">
<child>
<object class="GtkGrid" id="grid1">
@@ -38,9 +42,10 @@
<property name="baseline-position">top</property>
<child>
<object class="GtkButton" id="button2">
<property name="can-focus">1</property>
<property name="receives-default">1</property>
<property name="valign">baseline</property>
<property name="has-frame">0</property>
<property name="relief">none</property>
<child>
<object class="GtkLabel" id="source_name">
<property name="valign">baseline</property>
@@ -108,8 +113,9 @@
<child>
<object class="GtkLinkButton" id="resent_by_button">
<property name="label" translatable="0">reshareer</property>
<property name="can-focus">1</property>
<property name="receives-default">1</property>
<property name="has-frame">0</property>
<property name="relief">none</property>
<property name="uri">http://www.gtk.org</property>
</object>
</child>
@@ -125,8 +131,9 @@
<child>
<object class="GtkButton" id="expand_button">
<property name="label" translatable="yes">Expand</property>
<property name="can-focus">1</property>
<property name="receives-default">1</property>
<property name="has-frame">0</property>
<property name="relief">none</property>
<signal name="clicked" handler="expand_clicked" swapped="yes"/>
</object>
</child>
@@ -137,31 +144,35 @@
<child>
<object class="GtkButton" id="reply-button">
<property name="label" translatable="yes">Reply</property>
<property name="can-focus">1</property>
<property name="receives-default">1</property>
<property name="has-frame">0</property>
<property name="relief">none</property>
</object>
</child>
<child>
<object class="GtkButton" id="reshare-button">
<property name="label" translatable="yes">Reshare</property>
<property name="can-focus">1</property>
<property name="receives-default">1</property>
<property name="has-frame">0</property>
<property name="relief">none</property>
<signal name="clicked" handler="reshare_clicked" swapped="yes"/>
</object>
</child>
<child>
<object class="GtkButton" id="favorite-button">
<object class="GtkButton" id="favorite-buttton">
<property name="label" translatable="yes">Favorite</property>
<property name="can-focus">1</property>
<property name="receives-default">1</property>
<property name="has-frame">0</property>
<property name="relief">none</property>
<signal name="clicked" handler="favorite_clicked" swapped="yes"/>
</object>
</child>
<child>
<object class="GtkMenuButton" id="more-button">
<property name="can-focus">1</property>
<property name="receives-default">1</property>
<property name="menu-model">menu1</property>
<property name="has-frame">0</property>
<property name="popup">menu1</property>
<property name="relief">none</property>
<property name="label" translatable="yes">More...</property>
</object>
</child>
@@ -185,6 +196,7 @@
<property name="spacing">8</property>
<child>
<object class="GtkFrame" id="frame1">
<property name="shadow-type">none</property>
<child>
<object class="GtkLabel" id="n_reshares_label">
<property name="label" translatable="0">&lt;b&gt;2&lt;/b&gt;
@@ -197,6 +209,7 @@ Reshares</property>
</child>
<child>
<object class="GtkFrame" id="frame2">
<property name="shadow-type">none</property>
<child>
<object class="GtkLabel" id="n_favorites_label">
<property name="label" translatable="0">&lt;b&gt;2&lt;/b&gt;
@@ -222,8 +235,9 @@ FAVORITES</property>
<child>
<object class="GtkButton" id="button5">
<property name="label" translatable="yes">Details</property>
<property name="can-focus">1</property>
<property name="receives-default">1</property>
<property name="has-frame">0</property>
<property name="relief">none</property>
<style>
<class name="dim-label"/>
</style>
+19 -19
View File
@@ -8,10 +8,8 @@
#include <gtk/gtk.h>
/* This is the function that creates the #GListModel that we need.
* GTK list widgets need a #GListModel to display, as models support change
* notifications.
* Unfortunately various older APIs do not provide list models, so we create
* our own.
* GTK list widgets need a #GListModel to display, as it support change
* notifications, but various older APIs do not support one.
*/
static GListModel *
create_application_list (void)
@@ -75,7 +73,7 @@ bind_listitem_cb (GtkListItemFactory *factory,
}
/* In more complex code, we would also need functions to unbind and teardown
* the listitem, but this is simple code, so the default implementations are
* the listitem, but this is simple code, so the default implemntations are
* enough. If we had connected signals, this step would have been necessary.
*
* The #GtkSignalListItemFactory documentation contains more information about
@@ -141,38 +139,40 @@ do_listview_applauncher (GtkWidget *do_widget)
GtkListItemFactory *factory;
/* Create a window and set a few defaults */
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (window), 640, 320);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Application Launcher");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *) &window);
g_signal_connect (window, "destroy",
G_CALLBACK(gtk_widget_destroyed), &window);
/* The #GtkListitemFactory is what is used to create #GtkListItems
* to display the data from the model. So it is absolutely necessary
* to create one.
* We will use a #GtkSignalListItemFactory because it is the simplest
* We will use a #GtkSignalListitemFactory because it is the simplest
* one to use. Different ones are available for different use cases.
* The most powerful one is #GtkBuilderListItemFactory which uses
* #GtkBuilder .ui files, so it requires little code.
* The most powerful one being the #GtkBuilderListItemFactory which
* will to everything without requiring any code and just using a
* #GtkBuilder .ui file.
*/
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup", G_CALLBACK (setup_listitem_cb), NULL);
g_signal_connect (factory, "bind", G_CALLBACK (bind_listitem_cb), NULL);
/* Create the list widget here: We use a coverflow widget because it's
/* Create the list widget here: We use a coverflow widgets, because it's
* the coolest one. We could just as well use other list widgets such
* as a #GtkListView or a #GtkGridView and the code would look very
* similar.
* as a #GtkListView or a #GtkGridView and the code would look quite
* the same.
*/
coverflow = gtk_cover_flow_new_with_factory (factory);
/* We connect the activate signal here. It's the function we defined
* above for launching the selected application.
/* We connect the activate signal here. It's the function you remember
* from above for launching the selected application.
*/
g_signal_connect (coverflow, "activate", G_CALLBACK (activate_cb), NULL);
/* And of course we need to set the data model. Here we call the function
* we wrote above that gives us the list of applications. Then we set
* we wrote above that gives us the list of applications and then we set
* it on the coverflow list widget.
* The coverflow will now take items from the model and use the factory
* to create as many listitems as it needs to show itself to the user.
@@ -186,14 +186,14 @@ do_listview_applauncher (GtkWidget *do_widget)
* be scrollable.
*/
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_window_set_child (GTK_WINDOW (window), sw);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), coverflow);
gtk_container_add (GTK_CONTAINER (window), sw);
gtk_container_add (GTK_CONTAINER (sw), coverflow);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
gtk_widget_destroy (window);
return window;
}

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