Skip to content

Commit

Permalink
Document GtkColumnView, add example including filtering and sorting
Browse files Browse the repository at this point in the history
  • Loading branch information
jwahlstrand committed Nov 10, 2023
1 parent f49b9b8 commit 44b3fa7
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 6 deletions.
7 changes: 3 additions & 4 deletions docs/src/manual/canvas.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Drawing with Cairo

!!! note "Example"
The code on this page can be found in "canvas.jl" in the ["examples" subdirectory](https://github.com/JuliaGtk/Gtk4.jl/tree/main/examples).
The code below can be found in "canvas.jl" in the ["examples" subdirectory](https://github.com/JuliaGtk/Gtk4.jl/tree/main/examples).

Cairo based drawing can be done on Gtk4.jl's `GtkCanvas` widget, which is based on GTK's `GtkDrawingArea`. The canvas widget comes with a backing store (a Cairo image surface). You control what is drawn on this backing store by defining a `draw` function:

Expand Down Expand Up @@ -54,7 +54,6 @@ function on_pressed(controller, n_press, x, y)
end

signal_connect(on_pressed, g, "pressed")

```

This will draw a green circle on the canvas at every mouse click.
Expand Down Expand Up @@ -94,5 +93,5 @@ w = GtkWindow(canvas,"CairoMakie example")
end
```

A more complicated example can be found in the ["examples" subdirectory](https://github.com/JuliaGtk/Gtk4.jl/tree/main/examples).
For interactive plots, you can try [Gtk4Makie.jl](https://github.com/JuliaGtk/Gtk4Makie.jl), which draws GLMakie plots onto GTK's `GtkGLArea` widget.
!!! note "Example"
A more complicated example can be found in "canvas_cairomakie.jl" in the ["examples" subdirectory](https://github.com/JuliaGtk/Gtk4.jl/tree/main/examples).
60 changes: 59 additions & 1 deletion docs/src/manual/listtreeview.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ In version 4, GTK introduced new widgets for efficiently displaying
table-like data as one-dimensional lists, trees, or two-dimensional arrays.

## GtkListView

!!! note "Example"
The code below can be found in "listview.jl" in the ["examples" subdirectory](https://github.com/JuliaGtk/Gtk4.jl/tree/main/examples).

We start with the widget for displaying one-dimensional lists. Here is a simple example:
```julia
using Gtk4
Expand Down Expand Up @@ -56,6 +60,9 @@ Finally, we construct the `GtkListView` using the selection model and the factor

### Filtering

!!! note "Example"
The code below can be found in "filteredlistview.jl" in the ["examples" subdirectory](https://github.com/JuliaGtk/Gtk4.jl/tree/main/examples).

The list above is very long, and it's useful to allow the user to filter it down. An easy way to
implement this is to use `GtkFilterListModel`, which wraps the model and allows it to be filtered
before being displayed.
Expand Down Expand Up @@ -89,7 +96,10 @@ end

## Sorting

It's also useful to sort the list. This can be done using another model wrapper, `GtkSortListModel`.
!!! note "Example"
The code below can be found in "sortedlistview.jl" in the ["examples" subdirectory](https://github.com/JuliaGtk/Gtk4.jl/tree/main/examples).

It's also useful to be able to sort the list. This can be done using another model wrapper, `GtkSortListModel`.

Here is an example that sorts the list in reverse alphabetical order:
```julia
Expand All @@ -104,6 +114,54 @@ sortedModel = GtkSortListModel(GListModel(model), sorter)
We create a `GtkCustomSorter` using a `compare` callback that takes two arguments `item1` and `item2` and returns -1 if `item1` is before `item2`, 0 if they are equal, and 1 if `item1` is after `item2`. We construct a `GtkSortListModel` using this filter and use it instead of the `GListModel` in the constructor
for `GtkSingleSelection`.

## GtkColumnView

What if we want to display information in columns? Let's say we want to have one column show the name of the function and another show the number of methods. For this we can use `GtkColumnView`. It works very similarly to `GtkListView`, but instead of having one factory for the entire widget, each column has a factory whose `setup` and `bind` callbacks populate the widgets used to display the information for that column.

Here is an example:
```julia
using Gtk4

win = GtkWindow("ColumnView demo", 450, 800)
sw = GtkScrolledWindow()
push!(win, sw)

model = GtkStringList(string.(names(Gtk4)))

function setup_cb(f, li)
set_child(li,GtkLabel(""))
end

function bind_cb(f, li)
text = li[].string
label = get_child(li)
label.label = text
end

function bind2_cb(f, li)
text = li[].string
label = get_child(li)
label.label = string(length(methods(eval(Symbol(text)))))
end

list = GtkColumnView(GtkSelectionModel(GtkSingleSelection(GListModel(model))))

factory1 = GtkSignalListItemFactory(setup_cb, bind_cb)
col1 = GtkColumnViewColumn("name", factory1)
push!(list, col1)

factory2 = GtkSignalListItemFactory(setup_cb, bind2_cb)
col2 = GtkColumnViewColumn("methods", factory2)
push!(list, col2)

sw[] = list
```

Note that filtering and sorting work just the same as with `GtkListView` since they operate on the model.

!!! note "Example"
An example of using `GtkColumnView` with filtering and sorting can be found in "columnview.jl" in the ["examples" subdirectory](https://github.com/JuliaGtk/Gtk4.jl/tree/main/examples).

## GtkTreeView
The `GtkTreeView` was the widget used to display table-like or hierarchical data and trees in version 3 of GTK.
It's also present in version 4 but is being deprecated in the C library in favor of the widgets discussed above.
Expand Down
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- `listview.jl` demonstrates using `GtkListView` to show a huge list of strings.
- `filteredlistview.jl` demonstrates `GtkListView` with a `GtkSearchEntry` to filter what's shown.
- `sortedlistview.jl` demonstrates `GtkListView` with a `GtkDropDown` widget to control how the list is sorted.
- `columnview.jl` demonstrates using `GtkColumnView` to show lists with multiple columns.
- `listbox.jl` demonstrates `GtkListBox` to show a huge list of strings. This widget is a little easier to use than `GtkListView` but may be less performant.

## Applications
Expand Down
94 changes: 94 additions & 0 deletions examples/columnview.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using Gtk4

# Column view with filtering and sorting

win = GtkWindow("ColumnView demo", 450, 800)
bx = GtkBox(:v)
sw = GtkScrolledWindow()
push!(win, bx)
hbx = GtkBox(:h)
entry = GtkSearchEntry()
push!(hbx, entry)
sort_control = GtkDropDown(["Alphabetical","Reverse alphabetical","# methods (most to least)"])
push!(hbx, sort_control)
push!(bx, hbx)
push!(bx, sw)

# The model

model = GtkStringList(string.(names(Gtk4)))

# Sorting

# define sorting functions (should return -1 if item1 is before item2, 0 if they are equal, and 1 if item1 is after item2
alpha_compare(item1, item2) = isless(item1.string, item2.string) ? -1 : 1 # alphabetical
ralpha_compare(item1, item2) = -alpha_compare(item1, item2) # reverse alphabetical
function methods_compare(item1, item2)
n1 = length(methods(eval(Symbol(item1.string))))
n2 = length(methods(eval(Symbol(item2.string))))
if n1 == n2
return 0
end
isless(n1,n2) ? 1 : -1
end

signal_connect(sort_control, "notify::selected") do w, others...
sel = Gtk4.selected_string(w)
c = if sel == "Alphabetical"
alpha_compare
elseif sel == "Reverse alphabetical"
ralpha_compare
elseif sel == "# methods (most to least)"
methods_compare
end
@idle_add begin
Gtk4.set_sort_func(sorter, c)
changed(sorter)
end
end

sorter = GtkCustomSorter(alpha_compare)
sortedModel = GtkSortListModel(GListModel(model), sorter)

function match(item)
return startswith(item.string, entry.text)
end

# Filtering

filter = GtkCustomFilter(match)
filteredModel = GtkFilterListModel(GListModel(sortedModel), filter)

signal_connect(entry, :search_changed) do w
@idle_add changed(filter, Gtk4.FilterChange_DIFFERENT)
end

# Create ColumnView

function setup_cb(f, li)
set_child(li,GtkLabel(""))
end

function bind_cb(f, li)
text = li[].string
label = get_child(li)
label.label = text
end

function bind2_cb(f, li)
text = li[].string
label = get_child(li)
label.label = string(length(methods(eval(Symbol(text)))))
end

list = GtkColumnView(GtkSelectionModel(GtkSingleSelection(GListModel(filteredModel))); vexpand=true)
factory1 = GtkSignalListItemFactory(setup_cb, bind_cb)
col1 = GtkColumnViewColumn("name", factory1)
push!(list, col1)

factory2 = GtkSignalListItemFactory(setup_cb, bind2_cb)
col2 = GtkColumnViewColumn("methods", factory2)
push!(list, col2)

sw[] = list

3 changes: 3 additions & 0 deletions src/lists.jl
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ function CompareDataFunc(a, b, user_data)
convert(Cint, ret)
end

# enums in GTK are so...
Ordering(x::UInt32) = unsafe_trunc(Int16,0xffff)

## GtkListBox
setindex!(lb::GtkListBox, w::GtkWidget, i::Integer) = (G_.insert(lb, w, i - 1); lb[i])
getindex(lb::GtkListBox, i::Integer) = G_.get_row_at_index(lb, i - 1)
Expand Down
7 changes: 6 additions & 1 deletion test/gui/examples.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ end

@testset "Sorted List View" begin
include(joinpath(@__DIR__, "..", "..", "examples", "sortedlistview.jl"))
@test Gtk4.G_.compare(sorter,Gtk4.GLib.G_.get_item(GListModel(model),0), Gtk4.GLib.G_.get_item(GListModel(model),1))
@test Gtk4.G_.compare(sorter,Gtk4.GLib.G_.get_item(GListModel(model),0), Gtk4.GLib.G_.get_item(GListModel(model),1)) == -1
destroy(win)
end

@testset "Column View" begin
include(joinpath(@__DIR__, "..", "..", "examples", "columnview.jl"))
destroy(win)
end

Expand Down

0 comments on commit 44b3fa7

Please sign in to comment.