Skip to content

Commit 30a478b

Browse files
committed
reimplement @gtype using g_type_get_parent
1 parent b1990ee commit 30a478b

File tree

13 files changed

+174
-122
lines changed

13 files changed

+174
-122
lines changed

src/Gtk.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,11 @@ typealias Index Union(Integer,AbstractVector{TypeVar(:I,Integer)})
8080
include(joinpath("..","deps","ext.jl"))
8181
ccall((:g_type_init,libgobject),Void,())
8282
include("gslist.jl")
83-
include("gobject.jl")
83+
include("gtype.jl")
8484
include("gvalues.jl")
8585
include("gerror.jl")
8686
include("signals.jl")
87+
8788
include("gtktypes.jl")
8889
include("gdk.jl")
8990
include("events.jl")
@@ -126,6 +127,7 @@ for container in subtypes(GtkContainerI,true)
126127
@eval $(symbol(string(container)))(child::GtkWidgetI,vargs...) = push!($container(vargs...),child)
127128
end
128129
for orientable in tuple(:GtkPaned, :GtkScale, [sym.name.name for sym in subtypes(GtkBoxI)]...)
130+
if !isleaftype(eval(orientable)); continue; end
129131
@eval $orientable(orientation::Symbol,vargs...) = $orientable(
130132
(orientation==:v ? true :
131133
(orientation==:h ? false :

src/buttons.jl

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,26 @@
1313
#GtkSwitch — A "light switch" style toggle
1414
#GtkLockButton — A widget to unlock or lock privileged operations
1515

16-
@GType GtkButton <: GtkBin
16+
@gtktype GtkButton
1717
GtkButton() = GtkButton(ccall((:gtk_button_new,libgtk),Ptr{GObject},()))
1818
GtkButton(title::String) =
1919
GtkButton(ccall((:gtk_button_new_with_mnemonic,libgtk),Ptr{GObject},
2020
(Ptr{Uint8},), bytestring(title)))
2121

22-
@GType GtkCheckButton <: GtkBin
22+
@gtktype GtkCheckButton
2323
GtkCheckButton() = GtkCheckButton(ccall((:gtk_check_button_new,libgtk),Ptr{GObject},()))
2424
GtkCheckButton(title::String) =
2525
GtkCheckButton(ccall((:gtk_check_button_new_with_mnemonic,libgtk),Ptr{GObject},
2626
(Ptr{Uint8},), bytestring(title)))
2727

28-
@GType GtkToggleButton <: GtkBin
28+
@gtktype GtkToggleButton
2929
GtkToggleButton() = GtkToggleButton(ccall((:gtk_toggle_button_new,libgtk),Ptr{GObject},()))
3030
GtkToggleButton(title::String) =
3131
GtkToggleButton(ccall((:gtk_toggle_button_new_with_mnemonic,libgtk),Ptr{GObject},
3232
(Ptr{Uint8},), bytestring(title)))
3333

3434
if gtk_version >= 3
35-
@GType GtkSwitch <: GtkWidget
35+
@gtktype GtkSwitch
3636
GtkSwitch() = GtkSwitch(ccall((:gtk_switch_new,libgtk),Ptr{GObject},()))
3737
function GtkSwitch(active::Bool)
3838
b = GtkSwitch()
@@ -43,7 +43,7 @@ else
4343
const GtkSwitch = GtkToggleButton
4444
end
4545

46-
@GType GtkRadioButton <: GtkBin
46+
@gtktype GtkRadioButton
4747
GtkRadioButton(group::Ptr{Void}=C_NULL) =
4848
GtkRadioButton(ccall((:gtk_radio_button_new,libgtk),Ptr{GObject},
4949
(Ptr{Void},),group))
@@ -157,7 +157,7 @@ for btn in (:GtkCheckButton, :GtkToggleButton, :GtkRadioButton)
157157
end
158158

159159

160-
@GType GtkLinkButton <: GtkBin
160+
@gtktype GtkLinkButton
161161
GtkLinkButton(uri::String) =
162162
GtkLinkButton(ccall((:gtk_link_button_new,libgtk),Ptr{GObject},
163163
(Ptr{Uint8},),bytestring(uri)))
@@ -175,9 +175,9 @@ function GtkLinkButton(uri::String,visited::Bool)
175175
b
176176
end
177177

178-
#TODO: @GType GtkScaleButton
178+
#TODO: @gtktype GtkScaleButton
179179

180-
@GType GtkVolumeButton <: GtkBin
180+
@gtktype GtkVolumeButton
181181
GtkVolumeButton() = GtkVolumeButton(ccall((:gtk_volume_button_new,libgtk),Ptr{GObject},()))
182182
function GtkVolumeButton(value::Real) # 0<=value<=1
183183
b = GtkVolumeButton()

src/displays.jl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ convert{P<:Ptr}(::Type{P}, a::MatrixStrided) = convert(P, a.p)
144144
bstride(a::MatrixStrided,i) = (i == 1 ? sizeof(eltype(a)) : (i == 2 ? a.rowstride : 0))
145145
bstride(a,i) = stride(a,i)*sizeof(eltype(a))
146146

147-
@GType GdkPixbuf
147+
@Gtype GdkPixbuf libgtk gdk_pixbuf
148148

149149
# Example constructors:
150150
#GdkPixbuf(filename="", width=-1, height=-1, preserve_aspect_ratio=true)
@@ -287,7 +287,7 @@ baremodule GtkIconSize
287287
end
288288
end
289289

290-
@GType GtkImage <: GtkWidget
290+
@gtktype GtkImage
291291
GtkImage(pixbuf::GdkPixbuf) = GtkImage(ccall((:gtk_image_new_from_pixbuf,libgtk),Ptr{GObject},(Ptr{GObject},),pixbuf))
292292
GtkImage(filename::String) = GtkImage(ccall((:gtk_image_new_from_file,libgtk),Ptr{GObject},(Ptr{Uint8},),bytestring(filename)))
293293

@@ -310,14 +310,14 @@ end
310310
empty!(img::GtkImage) = ccall((:gtk_image_clear,libgtk),Void,(Ptr{GObject},),img)
311311
GdkPixbuf(img::GtkImage) = GdkPixbuf(ccall((:gtk_image_get_pixbuf,libgtk),Ptr{GObject},(Ptr{GObject},),img))
312312

313-
@GType GtkProgressBar <: GtkWidget
313+
@gtktype GtkProgressBar
314314
GtkProgressBar() = GtkProgressBar(ccall((:gtk_progress_bar_new,libgtk),Ptr{GObject},()))
315315
pulse(progress::GtkProgressBar) = ccall((:gtk_progress_bar_pulse,libgtk),Void,(Ptr{GObject},),progress)
316316

317-
@GType GtkSpinner <: GtkWidget
317+
@gtktype GtkSpinner
318318
GtkSpinner() = GtkSpinner(ccall((:gtk_spinner_new,libgtk),Ptr{GObject},()))
319319

320-
@GType GtkStatusbar <: GtkBox
320+
@gtktype GtkStatusbar
321321
GtkStatusbar() = GtkStatusbar(ccall((:gtk_statusbar_new,libgtk),Ptr{GObject},()))
322322
context_id(status::GtkStatusbar,source) =
323323
ccall((:gtk_statusbar_get_context_id,libgtk),Cuint,(Ptr{GObject},Ptr{Uint8}),
@@ -336,9 +336,9 @@ empty!(status::GtkStatusbar,context) =
336336
ccall((:gtk_statusbar_remove_all,libgtk),Ptr{GObject},(Ptr{GObject},Cuint,Cuint),
337337
status,context_id(status,context),context_id(context))
338338

339-
#@GType GtkInfoBar <: GtkBox
339+
#@gtktype GtkInfoBar
340340
#GtkInfoBar() = GtkInfoBar(ccall((:gtk_info_bar_new,libgtk),Ptr{GObject},())
341341

342-
@GType GtkStatusIcon
342+
@gtktype GtkStatusIcon
343343
GtkStatusIcon() = GtkStatusIcon(ccall((:gtk_status_icon_new,libgtk),Ptr{GObject},()))
344344

src/gtktypes.jl

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
1+
macro gtkabstract(name)
2+
groups = split(string(name), r"(?=[A-Z])")
3+
@assert groups[end] == "I"
4+
symname = join([lowercase(s) for s in groups[1:end-1]],"_")
5+
(: @Gabstract $(esc(name)) libgtk $(esc(symname)))
6+
end
17

2-
abstract GtkWidgetI <: GObjectI
3-
abstract GtkContainerI <: GtkWidgetI
4-
abstract GtkBinI <: GtkContainerI
5-
abstract GtkWindowI <: GtkBinI
6-
abstract GtkDialogI <: GtkWindowI
7-
abstract GtkBoxI <: GtkContainerI
8-
abstract GtkMenuShellI <: GtkContainerI
9-
abstract GtkMenuItemI <: GtkMenuShellI
8+
macro gtktype(name)
9+
groups = split(string(name), r"(?=[A-Z])")
10+
symname = join([lowercase(s) for s in groups],"_")
11+
(: @Gtype $(esc(name)) libgtk $(esc(symname)))
12+
end
13+
@gtkabstract GtkWidgetI
14+
@gtkabstract GtkContainerI
15+
@gtkabstract GtkBinI
16+
@gtkabstract GtkWindowI
17+
@gtkabstract GtkDialogI
18+
@gtkabstract GtkBoxI
19+
@gtkabstract GtkMenuShellI
20+
@gtkabstract GtkMenuItemI
1021

1122
convert(::Type{Ptr{GObjectI}},w::String) = convert(Ptr{GObjectI},GtkLabel(w))
1223

src/gobject.jl renamed to src/gtype.jl

Lines changed: 109 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,63 @@
11
abstract GObjectI
22
typealias GObject GObjectI
33

4+
typealias Enum Int32
5+
typealias GType Csize_t
6+
immutable GParamSpec
7+
g_type_instance::Ptr{Void}
8+
name::Ptr{Uint8}
9+
flags::Cint
10+
value_type::GType
11+
owner_type::GType
12+
end
13+
14+
const fundamental_types = (
15+
#(:name, Ctype, JuliaType, g_value_fn)
16+
#(:invalid, Void, Void, :error),
17+
#(:void, Nothing, Nothing, :error),
18+
#(:GInterface, Ptr{Void}, None, :???),
19+
(:gchar, Int8, Int8, :schar),
20+
(:guchar, Uint8, Uint8, :uchar),
21+
(:gboolean, Cint, Bool, :boolean),
22+
(:gint, Cint, None, :int),
23+
(:guint, Cuint, None, :uint),
24+
(:glong, Clong, None, :long),
25+
(:gulong, Culong, None, :ulong),
26+
(:gint64, Int64, Signed, :int64),
27+
(:guint64, Uint64, Unsigned, :uint64),
28+
(:GEnum, Enum, None, :enum),
29+
(:GFlags, Enum, None, :flags),
30+
(:gfloat, Float32, Float32, :float),
31+
(:gdouble, Float64, FloatingPoint, :double),
32+
(:gchararray, Ptr{Uint8}, String, :string),
33+
(:gpointer, Ptr{Void}, Ptr, :pointer),
34+
(:GBoxed, Ptr{Void}, None, :boxed),
35+
(:GParam, Ptr{GParamSpec}, Ptr{GParamSpec},:param),
36+
(:GObject, Ptr{GObject}, GObject, :object),
37+
(:GType, Int, None, :gtype),
38+
#(:GVariant, Ptr{GVariant}, GVariant, :variant),
39+
)
40+
# NOTE: in general do not cache ids, except for the fundamental values
41+
g_type_from_name(name::Symbol) = ccall((:g_type_from_name,libgobject),Int,(Ptr{Uint8},),name)
42+
# these constants are used elsewhere
43+
const gvoid_id = g_type_from_name(:void)
44+
const gboxed_id = g_type_from_name(:GBoxed)
45+
const gobject_id = g_type_from_name(:GObject)
46+
const gstring_id = g_type_from_name(:gchararray)
47+
48+
G_TYPE_FROM_CLASS(w::Ptr{Void}) = unsafe_load(convert(Ptr{GType},w))
49+
G_OBJECT_GET_CLASS(w::GObject) = G_OBJECT_GET_CLASS(w.handle)
50+
G_OBJECT_GET_CLASS(hnd::Ptr{GObjectI}) = unsafe_load(convert(Ptr{Ptr{Void}},hnd))
51+
G_OBJECT_CLASS_TYPE(w) = G_TYPE_FROM_CLASS(G_OBJECT_GET_CLASS(w))
52+
53+
g_type_parent(child::GType ) = ccall((:g_type_parent, libgobject), GType, (GType,), child)
54+
g_type_name(g_type::GType) = bytestring(ccall((:g_type_name,libgobject),Ptr{Uint8},(GType,),g_type))
55+
56+
g_type_test_flags(g_type::GType, flag) = ccall((:g_type_test_flags,libgobject), Bool, (GType,Enum), g_type, flag)
57+
const G_TYPE_FLAG_CLASSED = 1 << 0
58+
const G_TYPE_FLAG_INSTANTIATABLE = 1 << 1
59+
const G_TYPE_FLAG_DERIVABLE = 1 << 2
60+
const G_TYPE_FLAG_DEEP_DERIVABLE = 1 << 3
461
# Alternative object construction style. This would let us share constructors
562
# by creating const aliases: `const Z = GObject{:Z}`
663
type GObjectAny{Name} <: GObjectI
@@ -11,33 +68,61 @@ end
1168
# handle::Ptr{GObject}
1269
# GtkWidgetAny(handle::Ptr{GObject}) = gc_ref(new(handle))
1370
#end
14-
#type GtkContainerAny{T} <: GtkContainerI
15-
# handle::Ptr{GObject}
16-
# GtkContainerAny(handle::Ptr{GObject}) = gc_ref(new(handle))
17-
#end
18-
#type GtkBinAny{T} <: GtkBinI
19-
# handle::Ptr{GObject}
20-
# GtkBinAny(handle::Ptr{GObject}) = gc_ref(new(handle))
21-
#end
22-
#type GtkBoxAny{T} <: GtkBoxI
23-
# handle::Ptr{GObject}
24-
# GtkBoxAny(handle::Ptr{GObject}) = gc_ref(new(handle))
25-
#end
2671

27-
macro GType(gname)
28-
if isa(gname,Expr)
29-
@assert(gname.head == :comparison && length(gname.args) == 3 && gname.args[2] == :<:, "invalid GType expr")
30-
super = gname.args[3]
31-
gname = gname.args[1]
32-
else
33-
super = :GObject
72+
const gtype_ifaces = Dict{Symbol,Type}()
73+
const gtype_wrappers = Dict{Symbol,Type}()
74+
75+
gtype_ifaces[:GObject] = GObjectI
76+
77+
function get_iface(name::Symbol,g_type)
78+
if haskey(gtype_ifaces,name)
79+
return gtype_ifaces[name]
3480
end
35-
gname = gname::Symbol
36-
quote
37-
type $(esc(gname)) <: $(esc(symbol(string(super,'I'))))
81+
parent = g_type_parent(g_type)
82+
pname = g_type_name(parent)
83+
piface = get_iface(symbol(pname),parent)
84+
iname = symbol("$(name)I")
85+
iface = eval(:(abstract ($iname) <: $(piface); $iname))
86+
gtype_ifaces[name] = iface
87+
iface
88+
end
89+
90+
function get_wrapper(name,g_type)
91+
if haskey(gtype_wrappers,name)
92+
return gtype_wrappers[name]
93+
end
94+
if !g_type_test_flags(g_type, G_TYPE_FLAG_CLASSED)
95+
error("not implemented yet")
96+
end
97+
iface = get_iface(name,g_type)
98+
99+
wrapper = eval(quote
100+
#TODO: check if instantiable
101+
type ($name) <: ($iface)
38102
handle::Ptr{GObjectI}
39-
$(esc(gname))(handle::Ptr{GObjectI}) = (handle != C_NULL ? gc_ref(new(handle)) : error("Cannot construct $gname with a NULL pointer"))
40-
end
103+
$name(handle::Ptr{GObjectI}) = (handle != C_NULL ? GLib.gc_ref(new(handle)) : error($("Cannot construct $name with a NULL pointer")))
104+
end #FIXME
105+
$name
106+
end)
107+
gtype_wrappers[name] = wrapper
108+
wrapper
109+
end
110+
111+
macro Gtype(name,lib,symname)
112+
iname = symbol("$(name)I")
113+
quote
114+
g_type = ccall(($("$(symname)_get_type"), $lib), GType, ())
115+
const $(esc(iname)) = get_iface($(Meta.quot(name)),g_type)
116+
const $(esc(name)) = get_wrapper($(Meta.quot(name)),g_type)
117+
end
118+
end
119+
120+
macro Gabstract(name,lib,symname)
121+
@assert endswith(string(name),"I")
122+
typename = symbol(string(name)[1:end-1])
123+
quote
124+
g_type = ccall(($("$(symname)_get_type"), $lib), GType, ())
125+
const $(esc(name)) = get_iface($(Meta.quot(typename)),g_type)
41126
end
42127
end
43128

@@ -64,7 +149,6 @@ show(io::IO, w::GObjectI) = print(io,typeof(w))
64149

65150

66151
### Miscellaneous types
67-
typealias Enum Int32
68152
baremodule GConnectFlags
69153
const AFTER = 1
70154
const SWAPPED = 2

src/gvalues.jl

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,4 @@
11
### Getting and Setting Properties
2-
immutable GParamSpec
3-
g_type_instance::Ptr{Void}
4-
name::Ptr{Uint8}
5-
flags::Cint
6-
value_type::Csize_t
7-
owner_type::Csize_t
8-
end
9-
10-
const fundamental_types = (
11-
#(:name, Ctype, JuliaType, g_value_fn)
12-
#(:invalid, Void, Void, :error),
13-
#(:void, Nothing, Nothing, :error),
14-
#(:GInterface, Ptr{Void}, None, :???),
15-
(:gchar, Int8, Int8, :schar),
16-
(:guchar, Uint8, Uint8, :uchar),
17-
(:gboolean, Cint, Bool, :boolean),
18-
(:gint, Cint, None, :int),
19-
(:guint, Cuint, None, :uint),
20-
(:glong, Clong, None, :long),
21-
(:gulong, Culong, None, :ulong),
22-
(:gint64, Int64, Signed, :int64),
23-
(:guint64, Uint64, Unsigned, :uint64),
24-
(:GEnum, Enum, None, :enum),
25-
(:GFlags, Enum, None, :flags),
26-
(:gfloat, Float32, Float32, :float),
27-
(:gdouble, Float64, FloatingPoint, :double),
28-
(:gchararray, Ptr{Uint8}, String, :string),
29-
(:gpointer, Ptr{Void}, Ptr, :pointer),
30-
(:GBoxed, Ptr{Void}, None, :boxed),
31-
(:GParam, Ptr{GParamSpec}, Ptr{GParamSpec},:param),
32-
(:GObject, Ptr{GObject}, GObject, :object),
33-
(:GType, Int, None, :gtype),
34-
#(:GVariant, Ptr{GVariant}, GVariant, :variant),
35-
)
36-
# NOTE: in general do not cache ids, except for the fundamental values
37-
g_type_from_name(name::Symbol) = ccall((:g_type_from_name,libgobject),Int,(Ptr{Uint8},),name)
38-
# these constants are used elsewhere
39-
const gvoid_id = g_type_from_name(:void)
40-
const gboxed_id = g_type_from_name(:GBoxed)
41-
const gobject_id = g_type_from_name(:GObject)
42-
const gstring_id = g_type_from_name(:gchararray)
432

443
immutable GValue
454
g_type::Csize_t
@@ -192,10 +151,6 @@ function setindex!(w::GObject, value, name::Union(String,Symbol))
192151
w
193152
end
194153

195-
G_TYPE_FROM_CLASS(w::Ptr{Void}) = unsafe_load(convert(Ptr{Csize_t},w))
196-
G_OBJECT_GET_CLASS(w::GObject) = unsafe_load(convert(Ptr{Ptr{Void}},w.handle))
197-
G_OBJECT_CLASS_TYPE(w::GObject) = G_TYPE_FROM_CLASS(G_OBJECT_GET_CLASS(w))
198-
199154
function show(io::IO, w::GObject)
200155
print(io,typeof(w),'(')
201156
if convert(Ptr{GObjectI},w) == C_NULL

0 commit comments

Comments
 (0)