diff --git a/src/base.jl b/src/base.jl index 635253fc..492752ee 100644 --- a/src/base.jl +++ b/src/base.jl @@ -54,6 +54,36 @@ function setproperty!(w::GtkContainer, name::StringLike, child::GtkWidget, value w end +# Shortcut for creating callbacks that don't corrupt Gtk state if +# there's an error +macro guarded(ex...) + retval = nothing + if length(ex) == 2 + retval = ex[1] + ex = ex[2] + else + length(ex) == 1 || error("@guarded requires 1 or 2 arguments") + ex = ex[1] + end + isa(ex, Expr) && ( + ex.head == :-> || + (ex.head == :(=) && isa(ex.args[1],Expr) && ex.args[1].head == :call) || + ex.head == :function + ) || error("@guarded requires an expression defining a function") + newbody = quote + begin + try + $(ex.args[2]) + catch err + warn("Error in @guarded callback") + Base.display_error(err, catch_backtrace()) + $retval + end + end + end + esc(Expr(ex.head, ex.args[1], newbody)) +end + @deprecate getindex(w::GtkContainer, child::GtkWidget, name::StringLike, T::Type) getproperty(w,name,child,T) @deprecate setindex!(w::GtkContainer, value, child::GtkWidget, name::StringLike, T::Type) setproperty!(w,name,child,T,value) @deprecate setindex!(w::GtkContainer, value, child::GtkWidget, name::StringLike) setproperty!(w,name,child,value) diff --git a/src/basic_exports.jl b/src/basic_exports.jl index b9f336c7..9eaf8f83 100644 --- a/src/basic_exports.jl +++ b/src/basic_exports.jl @@ -22,6 +22,8 @@ export add_events, signal_emit, on_signal_destroy, on_signal_button_press, on_signal_button_release, on_signal_motion +export @guarded + # Tk-compatibility (reference of potentially missing functionality): #export Frame, Labelframe, Notebook, Panedwindow #export Button diff --git a/test/misc.jl b/test/misc.jl new file mode 100644 index 00000000..cb710aaf --- /dev/null +++ b/test/misc.jl @@ -0,0 +1,36 @@ +module TestGuarded + +using Gtk + +const unhandled = convert(Cint, false) + +foo1 = @guarded (x,y) -> x+y +bar1 = @guarded (x,y) -> x+y+k +@guarded foo2(x,y) = x+y +@guarded bar2(x,y) = x+y+k +@guarded function foo3(x,y) + x+y +end +@guarded function bar3(x,y) + x+y+k +end +@guarded unhandled function bar4(x,y) + x+y+k +end + +print_with_color(:green, """ +The following messages: + WARNING: Error in @guarded callback + ERROR: UndefVarError: k not defined +are expected and a sign of normal operation. +""") + +@assert foo1(3,5) == 8 +@assert bar1(3,5) == nothing +@assert foo2(3,5) == 8 +@assert bar2(3,5) == nothing +@assert foo3(3,5) == 8 +@assert bar3(3,5) == nothing +@assert bar4(3,5) == unhandled + +end diff --git a/test/runtests.jl b/test/runtests.jl index 0078536e..36682466 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,4 +1,5 @@ module GtkTestModule include("gui.jl") include("glib.jl") +include("misc.jl") end