diff --git a/Project.toml b/Project.toml index 2564f80d..c5eb7ffd 100644 --- a/Project.toml +++ b/Project.toml @@ -8,6 +8,7 @@ CEnum = "fa961155-64e5-5f13-b03f-caf6b980ea82" Cairo = "159f3aea-2a34-519c-b102-8c37f9878175" Cairo_jll = "83423d85-b0ee-5818-9007-b63ccbeb887a" ColorTypes = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" +FixedPointNumbers = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" GTK4_jll = "6ebb71f1-8434-552f-b6b1-dc18babcca63" Glib_jll = "7746bdde-850d-59dc-9ae8-88ece973131d" Graphene_jll = "75302f13-0b7e-5bab-a6d1-23fa92e4c2ea" @@ -31,6 +32,7 @@ CEnum = "0.4, 0.5" Cairo = "1.0.0" Cairo_jll = "1.16.0" ColorTypes = "0.10, 0.11" +FixedPointNumbers = "0.5, 0.6, 0.7, 0.8" GTK4_jll = "4.6.0" Glib_jll = "2.74.0" Graphene_jll = "1.10" diff --git a/src/GLib/gobject.jl b/src/GLib/gobject.jl index 56699ebe..0a7c6f1b 100644 --- a/src/GLib/gobject.jl +++ b/src/GLib/gobject.jl @@ -32,32 +32,37 @@ function show(io::IO, w::GObject) props = ccall((:g_object_class_list_properties, libgobject), Ptr{Ptr{GParamSpec}}, (Ptr{Nothing}, Ptr{Cuint}), G_OBJECT_GET_CLASS(w), n) v = gvalue(String) - first = true - for i = 1:n[] - param = unsafe_load(unsafe_load(props, i)) - if !first - print(io, ", ") - else - first = false - end - print(io, bytestring(param.name)) - if (ParamFlags(param.flags) & ParamFlags_READABLE) != 0 && - (param.flags & DEPRECATED) == 0 && - (ccall((:g_value_type_transformable, libgobject), Cint, - (Int, Int), param.value_type, g_type(AbstractString)) != 0) - ccall((:g_object_get_property, libgobject), Nothing, - (Ptr{GObject}, Ptr{UInt8}, Ptr{GValue}), w, param.name, v) - str = ccall((:g_value_get_string, libgobject), Ptr{UInt8}, (Ptr{GValue},), v) - value = gvalue_string_convert(str) - if param.value_type == g_type(AbstractString) && str != C_NULL - print(io, "=\"", value, '"') + if get(io, :compact, false)::Bool + print(io, getfield(w,:handle)) # show pointer + else # show properties + first = true + for i = 1:n[] + param = unsafe_load(unsafe_load(props, i)) + if !first + print(io, ", ") else - print(io, '=', value) + first = false + end + print(io, bytestring(param.name)) + if (ParamFlags(param.flags) & ParamFlags_READABLE) != 0 && + (param.flags & DEPRECATED) == 0 && + (ccall((:g_value_type_transformable, libgobject), Cint, + (Int, Int), param.value_type, g_type(AbstractString)) != 0) + ccall((:g_object_get_property, libgobject), Nothing, + (Ptr{GObject}, Ptr{UInt8}, Ptr{GValue}), w, param.name, v) + str = ccall((:g_value_get_string, libgobject), Ptr{UInt8}, (Ptr{GValue},), v) + value = gvalue_string_convert(str) + if param.value_type == g_type(AbstractString) && str != C_NULL + print(io, "=\"", value, '"') + else + print(io, '=', value) + end end end end print(io, ')') ccall((:g_value_unset, libgobject), Ptr{Nothing}, (Ptr{GValue},), v) + nothing end """ @@ -92,8 +97,10 @@ function propertyinfo(w::GObject, name::AbstractString) end print("\n") blurb = ccall((:g_param_spec_get_blurb, libgobject), Ptr{UInt8}, (Ptr{GParamSpec},), p) - printstyled("Description: "; bold = true) - println(bytestring(blurb)) + if blurb != C_NULL + printstyled("Description: "; bold = true) + println(bytestring(blurb)) + end if ccall((:g_value_type_transformable, libgobject), Cint, (Int, Int), param.value_type, g_type(AbstractString)) != 0 diff --git a/src/GLib/listmodel.jl b/src/GLib/listmodel.jl index 550f8fcf..bfc2006f 100644 --- a/src/GLib/listmodel.jl +++ b/src/GLib/listmodel.jl @@ -15,6 +15,9 @@ getindex(ls::GListStore, i::Integer) = getindex(GListModel(ls),i) iterate(ls::GListStore, i=0) = (i==length(ls) ? nothing : (getindex(ls, i+1),i+1)) eltype(::Type{GListStore}) = GObject Base.keys(lm::GListStore) = Base.OneTo(length(lm)) +Base.lastindex(lm::GListStore) = length(lm) + +show(io::IO, ls::GListStore) = show(io, GListModel(ls), GListStore) ## GListModel interface length(lm::GListModel) = G_.get_n_items(lm) @@ -22,4 +25,47 @@ getindex(lm::GListModel, i::Integer) = G_.get_item(lm,i - 1) iterate(lm::GListModel, i=0) = (i==length(lm) ? nothing : (getindex(lm, i+1),i+1)) eltype(::Type{GListModel}) = GObject Base.keys(lm::GListModel) = 1:length(lm) +Base.lastindex(lm::GListModel) = length(lm) + +function _get_screenheight(io) + if !(get(io, :limit, false)::Bool) + return typemax(Int) + else + sz = displaysize(io)::Tuple{Int,Int} + return sz[1] - 4 + end +end +function show(io::IO, lm::GListModel, t = GListModel) + l=length(lm) + if l>0 + screenheight = _get_screenheight(io) + print(io, l) + println(io, "-element $t:") + if l<= screenheight + for el in lm + print(io," ") + print(IOContext(io, :compact=>true), el) + if el != last(lm) + println(io) + end + end + else + halfheight = div(screenheight,2) + for i in 1:halfheight-1 + print(io," ") + println(IOContext(io, :compact=>true), lm[i]) + end + println(io," \u22ee") + for i in l - halfheight+1:l + print(io," ") + print(IOContext(io, :compact=>true), lm[i]) + if i!=l + println(io) + end + end + end + else + println(io, "0-element GListModel") + end +end diff --git a/src/GLib/signals.jl b/src/GLib/signals.jl index 06cafd19..d0888fa4 100644 --- a/src/GLib/signals.jl +++ b/src/GLib/signals.jl @@ -412,11 +412,12 @@ end waitforsignal(obj::GObject, signal) Returns when a GObject's signal is emitted. Can be used to wait for a window to -be closed. This function should only be used for signals that return nothing, with one exception: the "close-request" signal of GtkWindow. +be closed. This function should only be used for signals that return nothing, with one +exception: the "close-request" signal of GtkWindow. """ function waitforsignal(obj::GObject,signal) c = Condition() - signal_connect(obj, signal) do w + signal_connect(obj, signal) do args... notify(c) end wait(c) diff --git a/src/GdkPixbufLib.jl b/src/GdkPixbufLib.jl index c79e1e4a..946478ba 100644 --- a/src/GdkPixbufLib.jl +++ b/src/GdkPixbufLib.jl @@ -6,6 +6,8 @@ using gdk_pixbuf_jll using Librsvg_jll using JLLWrappers using Scratch +using ColorTypes +import FixedPointNumbers: N0f8 import Base: convert, size, eltype, getindex, setindex! import CEnum: @cenum @@ -68,6 +70,10 @@ struct RGB end convert(::Type{RGB}, x::Unsigned) = RGB(UInt8(x), UInt8(x >> 8), UInt8(x >> 16)) convert(::Type{U}, x::RGB) where {U <: Unsigned} = convert(U, (x.r) | (x.g >> 8) | (x.b >> 16)) +function convert(::Type{RGB}, x::Colorant) + c = ColorTypes.RGB{N0f8}(x) + RGB(reinterpret(UInt8,red(c)),reinterpret(UInt8,green(c)),reinterpret(UInt8,blue(c))) +end struct RGBA r::UInt8; g::UInt8; b::UInt8; a::UInt8 @@ -75,6 +81,10 @@ struct RGBA end convert(::Type{RGBA}, x::Unsigned) = RGBA(UInt8(x), UInt8(x >> 8), UInt8(x >> 16), UInt8(x >> 24)) convert(::Type{U}, x::RGBA) where {U <: Unsigned} = convert(U, (x.r) | (x.g >> 8) | (x.b >> 16) | (x.a >> 24)) +function convert(::Type{RGBA}, x::Colorant) + c = ColorTypes.RGBA{N0f8}(x) + RGBA(reinterpret(UInt8,red(c)),reinterpret(UInt8,green(c)),reinterpret(UInt8,blue(c)),reinterpret(UInt8,alpha(c))) +end # Example constructors: #MatrixStrided(width = 10, height = 20) diff --git a/src/lists.jl b/src/lists.jl index 8e52d54d..6313efd1 100644 --- a/src/lists.jl +++ b/src/lists.jl @@ -35,10 +35,45 @@ deleteat!(sl::GtkStringList, i::Integer) = (G_.remove(sl, i-1); sl) empty!(sl::GtkStringList) = (G_.splice(sl, 0, length(sl), nothing); sl) length(sl::GtkStringList) = length(GListModel(sl)) Base.keys(sl::GtkStringList) = Base.OneTo(length(sl)) +Base.lastindex(sl::GtkStringList) = length(sl) iterate(ls::GtkStringList, i=0) = (i==length(ls) ? nothing : (getindex(ls, i+1),i+1)) getindex(sl::GtkStringList, i::Integer) = G_.get_string(sl, i - 1) eltype(::Type{GtkStringList}) = String +function show(io::IO, sl::GtkStringList) + l=length(sl) + if l>0 + screenheight = GLib._get_screenheight(io) + print(io, l) + println(io, "-element GtkStringList:") + if l <= screenheight + for i in 1:l + print(io," ") + print(IOContext(io, :compact=>true), repr(sl[i])) + if itrue), repr(sl[i])) + end + println(io," \u22ee") + for i in l - halfheight+1:l + print(io," ") + print(IOContext(io, :compact=>true), repr(sl[i])) + if i!=l + println(io) + end + end + end + else + println(io, "0-element GtkStringList") + end +end + ## GtkDropdown """ diff --git a/test/Project.toml b/test/Project.toml index 6f0d2d93..a234b8df 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -2,5 +2,6 @@ Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" Cairo = "159f3aea-2a34-519c-b102-8c37f9878175" ColorTypes = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" +Colors = "5ae59095-9a9b-59fe-a467-6f913c188581" ModernGL = "66fc600b-dfda-50eb-8b99-91cfa97b1301" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/test/action-group.jl b/test/action-group.jl index c1d03c7f..42e393fa 100644 --- a/test/action-group.jl +++ b/test/action-group.jl @@ -16,6 +16,18 @@ signames = signalnames(GSimpleAction) end +@testset "waitforsignal" begin + +a=GSimpleAction("do-something",nothing) +a.enabled=false + +g_timeout_add(500) do + a.enabled=true +end +GLib.waitforsignal(a,"notify::enabled") + +end + # GSimpleAction is an object with properties @testset "simple action" begin @@ -119,7 +131,12 @@ function cb(ac,va) nothing end -add_action(GActionMap(g), "new-action", cb) +@test g["new-action"] === nothing + +ac = add_action(GActionMap(g), "new-action", cb) + +@test g["new-action"] == ac + add_action(GActionMap(g), "new-action-with-parameter", Bool, cb) end diff --git a/test/gdkpixbuf.jl b/test/gdkpixbuf.jl index 5f3a5e41..455eea85 100644 --- a/test/gdkpixbuf.jl +++ b/test/gdkpixbuf.jl @@ -1,4 +1,4 @@ -using Test, Gtk4.GdkPixbufLib +using Test, Gtk4.GdkPixbufLib, Colors @testset "pixbuf" begin @@ -15,6 +15,9 @@ pb[1:3,1:3]=x @test pb[3,1] == GdkPixbufLib.RGB(0xff,0xff,0xff) @test pb[4,1] != GdkPixbufLib.RGB(0xff,0xff,0xff) +pb[1,1]=colorant"blue" +@test pb[1,1] == GdkPixbufLib.RGB(0,0,0xff) + end @testset "Transparent pixbuf" begin @@ -23,5 +26,8 @@ fill!(icon, GdkPixbufLib.RGBA(0,0xff,0, 0xff)) icon[5:end-5, 3:end-3] .= Ref(GdkPixbufLib.RGBA(0,0,0xff,0x80)) pb=GdkPixbuf(icon, true) @test eltype(pb) == GdkPixbufLib.RGBA + +icon[1,1] = colorant"red" +@test icon[1,1] == GdkPixbufLib.RGBA(0xff,0,0,0xff) end diff --git a/test/gui/listviews.jl b/test/gui/listviews.jl index 1cf7896a..8e18d947 100644 --- a/test/gui/listviews.jl +++ b/test/gui/listviews.jl @@ -7,9 +7,15 @@ push!(win, sw) slist0 = GtkStringList() @test length(slist0) == 0 +show(IOBuffer(), slist0) +show(IOBuffer(), GListModel(slist0)) slist = GtkStringList(["Apple","Orange","Kiwi"]) +show(IOBuffer(), slist) +show(IOContext(IOBuffer(),:limit=>true,:displaysize=>(5,80)),slist) model = GLib.GListModel(slist) +show(IOBuffer(), model) +show(IOContext(IOBuffer(),:limit=>true,:displaysize=>(5,80)),model) push!(slist, "Mango") factory = GtkSignalListItemFactory() diff --git a/test/gui/window.jl b/test/gui/window.jl index c16868d2..54d0c489 100644 --- a/test/gui/window.jl +++ b/test/gui/window.jl @@ -1,4 +1,4 @@ -using Test, Gtk4, Gtk4.G_ +using Test, Gtk4, Gtk4.G_, Gtk4.GLib @testset "Window" begin @@ -31,8 +31,14 @@ end hide(w) show(w) grab_focus(w) -close(w) -sleep(0.2) + +g_timeout_add(500) do + close(w) + false +end +Gtk4.GLib.waitforsignal(w,"close-request") + +sleep(1.0) destroy(w) end