Permalink
Browse files

wrote tests

  • Loading branch information...
1 parent 0d9c260 commit 86249222379d7efa289c64c77b0dd7bd2dfd4139 @jverzani jverzani committed Mar 27, 2013
Showing with 547 additions and 110 deletions.
  1. +2 −1 examples/README.md
  2. +91 −0 examples/workspace.jl
  3. +4 −3 src/Tk.jl
  4. +28 −22 src/containers.jl
  5. +47 −13 src/core.jl
  6. +3 −0 src/methods.jl
  7. +120 −71 src/widgets.jl
  8. +252 −0 test/tests.jl
View
@@ -742,5 +742,6 @@ formlayout(Entry(f), "Rank:")
formlayout(Entry(f), "Serial Number:")
page_add(f)
-tcl(pg, "sashpos", 0, 50) ## move first sash
+set_value(pg, 50) ## move first sash 50 pixels
+tcl(pg, "sashpos", 1, 100) ## set_value, get_value are first sash (0-based)
```
View
@@ -0,0 +1,91 @@
+## simple workspace browser for julia
+using Tk
+
+## Some functions to work with a module
+function get_names(m::Module)
+ sort!(map(string, names(m)))
+end
+
+unique_id(v::Symbol, m::Module) = isdefined(m,v) ? unique_id(eval(m,v)) : ""
+unique_id(x) = string(object_id(x))
+
+## short_summary
+## can customize description here
+short_summary(x) = summary(x)
+short_summary(x::String) = "A string"
+
+## update ids, returning false if the same, true if not
+__ids__ = Array(String, 0)
+function update_ids(m::Module)
+ global __ids__
+ nms = get_names(m)
+ nms = filter(u -> u != "__ids__", nms)
+ a_ids = map(u -> unique_id(symbol(u), m), nms)
+ if __ids__ == a_ids
+ false
+ else
+ __ids__ = a_ids
+ true
+ end
+end
+
+
+negate(x::Bool, val::Bool) = val ? !x : x
+MaybeRegex = Union(Nothing, Regex)
+MaybeType = Union(Nothing, DataType, UnionType)
+
+## get array of names and summaries
+## m module
+## pat regular expression to filter by
+## dtype: DataType or UnionType to filter out by.
+## dtypefilter: If true not these types, if false only these types
+function get_names_summaries(m::Module, pat::MaybeRegex, dtype::MaybeType, dtypefilter::Bool)
+ nms = get_names(m)
+
+ if pat != nothing
+ nms = filter(s -> ismatch(pat, s), nms)
+ end
+ ## filter out this type
+ if dtype != nothing
+ nms = filter(u -> isdefined(m, symbol(u)) && negate(isa(eval(m,symbol(u)), dtype), dtypefilter), nms)
+ end
+ summaries = map(u -> isdefined(m, symbol(u)) ? short_summary(eval(m,symbol(u))) : "undefined", nms)
+
+ if length(nms) == length(summaries)
+ return [nms summaries]
+ else
+ return nothing # didn't match
+ end
+end
+get_names_summaries(m::Module, pat::Regex) = get_names_summaries(m, pat, nothing, true)
+get_names_summaries(m::Module, dtype::MaybeType) = get_names_summaries(m, nothing, dtype, true)
+get_names_summaries(m::Module) = get_names_summaries(m::Module, nothing, nothing, true)
+
+## Simple layout for our tree view.
+
+w = Toplevel("Workspace", 600, 600)
+f = Frame(w)
+pack_stop_propagate(w)
+pack(f, {:expand=>true, :fill=>"both"})
+tv = Treeview(f, get_names_summaries(Main, nothing, (Module), true))
+tree_key_header(tv, "Object")
+tree_headers(tv, ["Summary"])
+scrollbars_add(f, tv)
+
+## add a callback. Here we get the obj clicked on.
+callback_add(tv, (path) -> begin
+ val = get_value(tv)[1]
+ obj = eval(Main, symbol(val))
+ println(short_summary(obj))
+end)
+
+## Update values after 1000ms. Call aft.stop() to stop
+function cb()
+ tk_exists(tv) ? nothing : aft.stop()
+ if update_ids(Main)
+ set_items(tv, get_names_summaries(Main, nothing, (Module), true))
+ end
+end
+aft = tcl_after(1000, cb)
+aft.start()
+
View
@@ -34,16 +34,16 @@ export Window, TkCanvas, Canvas, pack, place, tcl_eval, TclError,
cairo_context, cairo_surface,
tcl_doevent, MouseHandler
-export tcl, tclvar, tk_configure, tk_cget, tk_identify, tk_state, tk_instate, tk_winfo, tk_wm, tk_bind, callback_add
+export tcl, tclvar, tk_configure, tk_cget, tk_identify, tk_state, tk_instate, tk_winfo, tk_wm, tk_exists,
+ tcl_after, tk_bind, callback_add
export Tk_Widget, TTk_Widget, Tk_Container
export Toplevel, Frame, Labelframe, Notebook, Panedwindow
export Label, Button
export Checkbutton, Radio, Combobox
export Slider, Spinbox
-export Entry, Text
+export Entry, set_validation, Text
export Treeview, selected_nodes, node_insert, node_move, node_delete, node_open
export tree_headers, tree_column_widths, tree_key_header, tree_key_width
-export Kanvas
export Sizegrip, Separator, Progressbar, Image, Scrollbar
export Menu, menu_add
export GetOpenFile, GetSaveFile, ChooseDirectory, Messagebox
@@ -59,6 +59,7 @@ export get_value, set_value,
get_enabled, set_enabled,
get_editable, set_editable,
get_visible, set_visible,
+ set_position,
raise, focus, update, destroy
View
@@ -5,7 +5,7 @@ type Tk_Labelframe <: TTk_Container w::TkWidget end
type Tk_Notebook <: TTk_Container w::TkWidget end
type Tk_Panedwindow <: TTk_Container w::TkWidget end
-show(io::IO, widget::TkWidget) = println(typeof(widget))
+
## Toplevel window
function Toplevel(title::String, width::Integer, height::Integer, visible::Bool)
@@ -17,7 +17,7 @@ end
Toplevel(title::String, width::Integer, height::Integer) = Toplevel(title, width, height, true)
Toplevel(title::String, visible::Bool) = Toplevel(title, 200, 200, visible)
Toplevel(title::String) = Toplevel(title, 200, 200)
-Toplevel() = Toplevel("Default window")
+Toplevel() = Toplevel("Toplevel window")
get_value(widget::Tk_Toplevel) = tk_wm(widget, "title")
@@ -29,6 +29,15 @@ function set_visible(widget::Tk_Toplevel, value::Bool)
end
set_size(widget::Tk_Toplevel, width::Integer, height::Integer) = tcl(I"wm minsize", widget, width, height)
+
+## Set upper left corner of Toplevel to...
+function set_position(widget::Tk_Toplevel, x::Integer, y::Integer)
+ p_or_m(x) = x < 0 ? "$x" : "+$x"
+ tk_wm(widget, "geometry", I(p_or_m(x) * p_or_m(y)))
+end
+set_position{T <: Integer}(widget::Tk_Toplevel, pos::Vector{T}) = set_position(w, pos[1], pos[2])
+set_position(widget::Tk_Toplevel, pos::Tk_Widget) = set_position(widget, Integer[parse_int(tk_winfo(pos, i)) for i in ["x", "y"]] + [10,10])
+
update(widget::Tk_Toplevel) = tk_wm(widget, "geometry")
destroy(widget::Tk_Toplevel) = tcl("destroy", widget)
@@ -37,7 +46,8 @@ destroy(widget::Tk_Toplevel) = tcl("destroy", widget)
## Labelframe
Labelframe(parent::Widget, text::String) = Labelframe(parent, {:text=>text})
-set_value(widget::Tk_Labelframe, text::String) = tk_configure(f, {:text=> text})
+get_value(widget::Tk_Labelframe) = tk_cget(widget, "text")
+set_value(widget::Tk_Labelframe, text::String) = tk_configure(widget, {:text=> text})
## Notebook
@@ -54,7 +64,7 @@ end
get_value(widget::Tk_Notebook) = 1 + int(tcl(widget, I"index current"))
set_value(widget::Tk_Notebook, index::Integer) = tcl(widget, "select", index - 1)
-
+no_tabs(widget::Tk_Notebook) = length(split(tcl(widget, "tabs"), " "))
## Panedwindow
@@ -72,11 +82,16 @@ function get_value(widget::Tk_Panedwindow)
pos = tcl(widget, "sashpos", 0) | int
floor(pos/sz*100)
end
-function set_value(widget::Tk_Panedwindow, value::Integer)
- sz = (tk_cget(widget, "orient") == "horizontal") ? get_width(widget) : get_height(widget)
- pos = int(value * sz/100)
- tcl(widget, "sashpos", 0, pos)
+## can set with Integer -- pixels, or real (proportion in [0,1])
+set_value(widget::Tk_Panedwindow, value::Integer) = tcl(widget, "sashpos", 0, value)
+function set_value(widget::Tk_Panedwindow, value::Real)
+ if value <= 1 && value >= 0
+ sz = (tk_cget(widget, "orient") == "horizontal") ? get_width(widget) : get_height(widget)
+ set_value(widget, int(value * sz/100))
+ end
end
+
+
page_add(child::Widget) = page_add(child, 1)
@@ -142,23 +157,15 @@ end
## Wrap child in frame, return frame to pack (or grid) into parent of child
##
## w = Toplevel()
-## f = Frame(w); pack(f) ## f shouldn't have any layout management
+## f = Frame(w); pack(f) ## f shouldn't have any layout management of its children
## t = Text(f)
## scrollbars_add(f,t)
##
function scrollbars_add(parent::Tk_Frame, child::Tk_Widget)
- ## we use tcl commands for the scrollbar, not Scrollbar. Can't get the callbacks to work properly
- fpath = parent.w.path
- wpath = child.w.path
- xscr = "$fpath.xscr"
- yscr = "$fpath.yscr"
-
- tcl_eval("ttk::scrollbar $xscr -orient horizontal -command \"$wpath xview\"")
- tcl_eval("ttk::scrollbar $yscr -orient vertical -command \"$wpath yview\"")
-
- tk_configure(child, {:xscrollcommand => "$xscr set",
- :yscrollcommand => "$yscr set"})
+ grid_stop_propagate(parent)
+ xscr = Scrollbar(parent, child, "horizontal")
+ yscr = Scrollbar(parent, child, "vertical")
grid(child, 1, 1)
grid(yscr, 1, 2)
@@ -168,7 +175,6 @@ function scrollbars_add(parent::Tk_Frame, child::Tk_Widget)
grid_configure(xscr, {:sticky => "ew"})
grid_rowconfigure(parent, 1, {:weight => 1})
grid_columnconfigure(parent, 1, {:weight => 1})
-
- tcl(I"grid propagate", parent, false) ## size request comes from parent, not from child.
+
end
View
@@ -1,9 +1,11 @@
+show(io::IO, widget::TkWidget) = print(io, typeof(widget))
+show(io::IO, widget::Tk_Widget) = print(io, "Tk widget of type $(typeof(widget))")
+
+
tcl_eval("set auto_path")
tcl_add_path(path::String) = tcl_eval("lappend auto_path $path")
-tcl_add_path(Pkg.dir("Tk", "tcl"))
tcl_require(pkg::String) = tcl_eval("package require $pkg")
-## tk_configure helpers
## helper to get path
## assumes Tk_Widgets have w property storing TkWidget
@@ -27,22 +29,26 @@ function to_tcl{T <: String}(x::Vector{T})
end
to_tcl(x::Widget) = get_path(x)
function to_tcl(x::Dict)
- out = Dict()
- for (k,v) in x
- if v!=nothing out[k] = v end
- end
+ out = filter((k,v) -> v != nothing, x)
join([" -$(string(k)) $(to_tcl(v))" for (k, v) in out], "")
end
-to_tcl(x::Function) = Tk.tcl_callback(x)
-
+function to_tcl(x::Function)
+ ccb = tcl_callback(x)
+ args = get_args(x)
+ perc_args = join(map(u -> "%$(string(u))", args[2:end]), " ")
+ cmd = "{$ccb $perc_args}"
+end
## Function to simplify call to tcl_eval, ala R's tcl() function
+## converts argumets through to_tcl
function tcl(xs...)
cmd = join([" $(to_tcl(x))" for x in xs], "")
- ## println(cmd)
+ println(cmd)
tcl_eval(cmd)
end
+
+## tclvar for textvariables
## Work with a text variable. Stores values as strings. Must coerce!
## getter -- THIS FAILS IN A CALLBACK!!!
#function tclvar(nm::String)
@@ -75,7 +81,7 @@ function tk_cget(widget::Widget, prop::String, coerce::MaybeFunction)
end
tk_cget(widget::Widget, prop::String) = tk_cget(widget, prop, nothing)
-## Identify
+## Identify widget at x,y
tk_identify(widget::Widget, x::Integer, y::Integer) = tcl(widget, "identify", "%x", "%y")
## tk_state(w, "!disabled")
@@ -89,8 +95,8 @@ function tk_winfo(widget::Widget, prop::String, coerce::MaybeFunction)
end
tk_winfo(widget::Widget, prop::String) = tk_winfo(widget, prop, nothing)
-## wm. Is this okay? In many case args is wanted
-tk_wm(window::Widget, prop::String, args::MaybeString) = tcl("wm", prop, window, args)
+## wm.
+tk_wm(window::Widget, prop::String, args...) = tcl("wm", prop, window, args...)
tk_wm(window::Widget, prop::String) = tk_wm(window, prop, nothing)
## Take a function, get its args as array of symbols. There must be better way...
@@ -126,7 +132,7 @@ end
## bind
## Function callbacks have first argument path that is ignored
## others match percent substitution
-## e.g. (W, x, y) -> x will have W, x and y available through %W %x %y bindings
+## e.g. (path, W, x, y) -> x will have W, x and y available through %W %x %y bindings
function tk_bind(widget::Widget, event::String, callback::Function)
if event == "command"
tk_configure(widget, {:command => callback})
@@ -186,3 +192,31 @@ function make_widget(parent::Widget, str::String, args::Dict)
w
end
make_widget(parent::Widget, str::String) = make_widget(parent, str, Dict())
+
+
+## tcl after ... (Maybe there is a better julia construct...)
+## create an object that will repeatedly call a
+## function after a delay of ms milliseconds. This is started with
+## obj.start() and stopped, if desired, with obj.stop(). To restart is
+## possible, but first set obj.run=true.
+type TclAfter
+ cb::Function
+ run::Bool
+ start::Union(Nothing, Function)
+ stop::Union(Nothing, Function)
+ ms::Int
+
+ function TclAfter(ms, cb::Function)
+ obj = new(cb, true, nothing, nothing, ms)
+ function fun(path)
+ cb()
+ if obj.run
+ Tk.tcl("after", obj.ms, fun)
+ end
+ end
+ obj.start = () -> Tk.tcl("after", obj.ms, fun)
+ obj.stop = () -> obj.run = false
+ obj
+ end
+end
+tcl_after(ms::Integer, cb::Function) = TclAfter(ms, cb)
View
@@ -47,3 +47,6 @@ set_visible(widget::Widget, value::Bool) = XXX()
## set focus
focus(widget::Widget) = tcl("focus", widget)
raise(widget::Widget) = tcl("raise", widget)
+
+## does widget exist?
+tk_exists(widget::Widget) = tk_winfo(widget, "exists") == "1"
Oops, something went wrong.

0 comments on commit 8624922

Please sign in to comment.