303 lines
6.9 KiB
Julia
303 lines
6.9 KiB
Julia
|
|
using Gtk, Distributed
|
||
|
|
|
||
|
|
function glade(win)
|
||
|
|
showall(win)
|
||
|
|
if !isinteractive()
|
||
|
|
c = Condition()
|
||
|
|
signal_connect(win, :destroy) do widget
|
||
|
|
notify(c)
|
||
|
|
end
|
||
|
|
@async Gtk.gtk_main()
|
||
|
|
wait(c)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function window(f)
|
||
|
|
win = GtkWindow("My First Gtk.jl program", 400, 200)
|
||
|
|
v = f(win)
|
||
|
|
if v != nothing
|
||
|
|
push!(win, v)
|
||
|
|
end
|
||
|
|
showall(win)
|
||
|
|
if !isinteractive()
|
||
|
|
c = Condition()
|
||
|
|
signal_connect(win, :destroy) do widget
|
||
|
|
notify(c)
|
||
|
|
end
|
||
|
|
@async Gtk.gtk_main()
|
||
|
|
wait(c)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
@enum ToShow begin
|
||
|
|
Button
|
||
|
|
Label
|
||
|
|
Label_Accessor
|
||
|
|
Label_Markup
|
||
|
|
Entry
|
||
|
|
ComboBox
|
||
|
|
List
|
||
|
|
Tree
|
||
|
|
File_Dialog
|
||
|
|
Message_Dialog
|
||
|
|
Key_Event
|
||
|
|
Canvas
|
||
|
|
Sliders
|
||
|
|
Async
|
||
|
|
Async2
|
||
|
|
Glade
|
||
|
|
end
|
||
|
|
|
||
|
|
const start_times = Dict{UInt32, UInt32}()
|
||
|
|
|
||
|
|
target = Async2
|
||
|
|
target == Button && window() do
|
||
|
|
button = GtkButton("Click me")
|
||
|
|
|
||
|
|
signal_connect(button, "clicked") do widget
|
||
|
|
println("The button has been clicked")
|
||
|
|
end
|
||
|
|
return button
|
||
|
|
end
|
||
|
|
target == Label && window() do win
|
||
|
|
return GtkLabel("My Text")
|
||
|
|
end
|
||
|
|
target == Label_Accessor && window() do win
|
||
|
|
label = GtkLabel("My Text")
|
||
|
|
GAccessor.text(label, "My other text")
|
||
|
|
return label
|
||
|
|
end
|
||
|
|
target == Label_Markup && window() do win
|
||
|
|
label = GtkLabel("My Text")
|
||
|
|
format = """<b>My Bold text</b>\n
|
||
|
|
<a href=\"https://www.gtk.org\"
|
||
|
|
title=\"Our website\">GTK+ website</a>"""
|
||
|
|
GAccessor.markup(label, format)
|
||
|
|
GAccessor.selectable(label, true)
|
||
|
|
GAccessor.justify(label, Gtk.GConstants.GtkJustification.RIGHT)
|
||
|
|
return label
|
||
|
|
end
|
||
|
|
target == Entry && window() do win
|
||
|
|
entry = GtkEntry()
|
||
|
|
set_gtk_property!(entry, :text, "My String")
|
||
|
|
#str = get_gtk_property(entry, :text, String)
|
||
|
|
return entry
|
||
|
|
end
|
||
|
|
target == ComboBox && window() do win
|
||
|
|
cb = GtkComboBoxText()
|
||
|
|
choices = ["one", "two", "three", "four"]
|
||
|
|
for c in choices
|
||
|
|
push!(cb, c)
|
||
|
|
end
|
||
|
|
|
||
|
|
set_gtk_property!(cb, :active, 1)
|
||
|
|
|
||
|
|
signal_connect(cb, "changed") do width, others...
|
||
|
|
idx = get_gtk_property(cb, "active", Int)
|
||
|
|
str = Gtk.bytestring(GAccessor.active_text(cb))
|
||
|
|
println("Active element is \"$str\" at index $idx")
|
||
|
|
end
|
||
|
|
return cb
|
||
|
|
end
|
||
|
|
target == List && window() do win
|
||
|
|
ls = GtkListStore(String, Int, Bool, Bool)
|
||
|
|
push!(ls, ("Peter", 20, false, true))
|
||
|
|
push!(ls, ("Paul", 30, false, true))
|
||
|
|
push!(ls, ("Mary", 25, true, true))
|
||
|
|
push!(ls, ("Susanne", 35, true, true))
|
||
|
|
tmFiltered = GtkTreeModelFilter(ls)
|
||
|
|
GAccessor.visible_column(tmFiltered, 3)
|
||
|
|
tv = GtkTreeView(GtkTreeModel(tmFiltered))
|
||
|
|
rTxt = GtkCellRendererText()
|
||
|
|
rTog = GtkCellRendererToggle()
|
||
|
|
c1 = GtkTreeViewColumn("Name", rTxt, Dict([("text", 0)]))
|
||
|
|
c2 = GtkTreeViewColumn("Age", rTxt, Dict([("text", 1)]))
|
||
|
|
c3 = GtkTreeViewColumn("Female", rTog, Dict([("active", 2)]))
|
||
|
|
for (i, c) in enumerate([c1, c2, c3])
|
||
|
|
GAccessor.resizable(c, true)
|
||
|
|
GAccessor.sort_column_id(c, i-1)
|
||
|
|
GAccessor.reorderable(c, i)
|
||
|
|
end
|
||
|
|
selection = GAccessor.selection(tv)
|
||
|
|
# selection = GAccessor.mode(selection, Gtk.GConstants.GtkSelectionMode.MULTIPLE)
|
||
|
|
signal_connect(selection, "changed") do widget
|
||
|
|
if hasselection(selection)
|
||
|
|
currentIt = selected(selection)
|
||
|
|
|
||
|
|
#println("Name: ", ls[currentIt, 1], " Age: ", ls[currentIt, 2])
|
||
|
|
println("Name: ", GtkTreeModel(tmFiltered)[currentIt, 1],
|
||
|
|
"Age: ", GtkTreeModel(tmFiltered)[currentIt, 2])
|
||
|
|
end
|
||
|
|
end
|
||
|
|
push!(tv, c1, c2, c3)
|
||
|
|
|
||
|
|
entry = GtkEntry()
|
||
|
|
|
||
|
|
signal_connect(entry, "changed") do widget
|
||
|
|
searchText = get_gtk_property(entry, :text, String)
|
||
|
|
|
||
|
|
for l=1:length(ls)
|
||
|
|
showMe = true
|
||
|
|
|
||
|
|
if length(searchText) > 0
|
||
|
|
showMe = showMe && occursin(lowercase(searchText), lowercase(ls[l, 1]))
|
||
|
|
end
|
||
|
|
|
||
|
|
ls[l, 4] = showMe
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
vbox = GtkBox(:v)
|
||
|
|
push!(vbox, entry, tv)
|
||
|
|
return vbox
|
||
|
|
end
|
||
|
|
target == Tree && window() do win
|
||
|
|
ts = GtkTreeStore(String)
|
||
|
|
iter1 = push!(ts, ("one", ))
|
||
|
|
iter2 = push!(ts, ("two", ), iter1)
|
||
|
|
iter3 = push!(ts, ("three", ), iter2)
|
||
|
|
tv = GtkTreeView(GtkTreeModel(ts))
|
||
|
|
r1 = GtkCellRendererText()
|
||
|
|
c1 = GtkTreeViewColumn("A", r1, Dict([("text", 0)]))
|
||
|
|
push!(tv, c1)
|
||
|
|
return tv
|
||
|
|
end
|
||
|
|
target == File_Dialog && begin
|
||
|
|
result = open_dialog("Pick some files", GtkNullContainer(), ["*.jl, *.csv"], select_multiple=true)
|
||
|
|
println(result)
|
||
|
|
end
|
||
|
|
target == Message_Dialog && begin
|
||
|
|
info_dialog("Julia Rocks!")
|
||
|
|
end
|
||
|
|
target == Key_Event && window() do win
|
||
|
|
signal_connect(win, "key-press-event") do widget, event
|
||
|
|
k = event.keyval
|
||
|
|
if !(k in keys(start_times))
|
||
|
|
start_times[k] = event.time
|
||
|
|
println("You pressed key ", k, " which is '", Char(k), "'.")
|
||
|
|
else
|
||
|
|
println("repeating key ", k)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
signal_connect(win, "key-release-event") do widget, event
|
||
|
|
k = event.keyval
|
||
|
|
start_time = pop!(start_times, k)
|
||
|
|
duration = event.time - start_time
|
||
|
|
println("You released key ", k, " after time ", duration, " msec.")
|
||
|
|
end
|
||
|
|
nothing
|
||
|
|
end
|
||
|
|
target == Canvas && window() do win
|
||
|
|
c = @GtkCanvas()
|
||
|
|
@guarded draw(c) do widget
|
||
|
|
ctx = getgc(c)
|
||
|
|
h = height(c)
|
||
|
|
w = width(c)
|
||
|
|
rectangle(ctx, 0, 0, w, h/2)
|
||
|
|
set_source_rgb(ctx, 1, 0, 0)
|
||
|
|
fill(ctx)
|
||
|
|
rectangle(ctx, 0, 3h/4, w, h/4)
|
||
|
|
set_source_rgb(ctx, 0, 0, 1)
|
||
|
|
fill(ctx)
|
||
|
|
end
|
||
|
|
c.mouse.button1press = @guarded (widget, event) -> begin
|
||
|
|
ctx = getgc(widget)
|
||
|
|
set_source_rgb(ctx, 0, 1, 0)
|
||
|
|
arc(ctx, event.x, event.y, 5, 0, 2pi)
|
||
|
|
stroke(ctx)
|
||
|
|
reveal(widget)
|
||
|
|
end
|
||
|
|
return c
|
||
|
|
end
|
||
|
|
target == Sliders && window() do win
|
||
|
|
slider1 = GtkScale(false, 0:10)
|
||
|
|
slider2 = GtkScale(false, 0:30)
|
||
|
|
signal_connect(slider1, "value-changed") do widget, others...
|
||
|
|
value = GAccessor.value(slider1)
|
||
|
|
GAccessor.value(slider2, value)
|
||
|
|
println("slider value is $value")
|
||
|
|
if value == 10
|
||
|
|
GAccessor.range(slider1, 1, 20)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
g = GtkGrid()
|
||
|
|
g[1,1] = slider1
|
||
|
|
g[1,2] = slider2
|
||
|
|
set_gtk_property!(g, :column_homogeneous, true)
|
||
|
|
return g
|
||
|
|
end
|
||
|
|
target == Async && window() do win
|
||
|
|
btn = GtkButton("Start")
|
||
|
|
sp = GtkSpinner()
|
||
|
|
ent = GtkEntry()
|
||
|
|
|
||
|
|
grid = GtkGrid()
|
||
|
|
grid[1,1] = btn
|
||
|
|
grid[2,1] = sp
|
||
|
|
grid[1:2,2] = ent
|
||
|
|
|
||
|
|
signal_connect(btn, "clicked") do widget
|
||
|
|
start(sp)
|
||
|
|
Threads.@spawn begin
|
||
|
|
stop_time = time() + 3
|
||
|
|
counter = 0
|
||
|
|
while time() < stop_time
|
||
|
|
counter += 1
|
||
|
|
end
|
||
|
|
|
||
|
|
# Interacting with GTK from a thread other than the main thread is
|
||
|
|
# generally not allowed, so we register an idle callback instead.
|
||
|
|
Gtk.GLib.g_idle_add(nothing) do user_data
|
||
|
|
stop(sp)
|
||
|
|
set_gtk_property!(ent, :text, "I counted to $counter in a thread!")
|
||
|
|
Cint(false)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
return grid
|
||
|
|
end
|
||
|
|
target == Async2 && window() do win
|
||
|
|
btn = GtkButton("Start")
|
||
|
|
sp = GtkSpinner()
|
||
|
|
ent = GtkEntry()
|
||
|
|
|
||
|
|
grid = GtkGrid()
|
||
|
|
grid[1,1]=btn
|
||
|
|
grid[2,1]=sp
|
||
|
|
grid[1:2,2] = ent
|
||
|
|
|
||
|
|
id = addprocs(1)[1]
|
||
|
|
|
||
|
|
signal_connect(btn, "clicked") do widget
|
||
|
|
start(sp)
|
||
|
|
@async begin
|
||
|
|
counter = @fetchfrom id begin
|
||
|
|
stop_time = time() + 3
|
||
|
|
counter = 0
|
||
|
|
while time() < stop_time
|
||
|
|
counter += 1
|
||
|
|
end
|
||
|
|
counter
|
||
|
|
end
|
||
|
|
|
||
|
|
# We are still in the main thread so it is okay to directly access widgets
|
||
|
|
stop(sp)
|
||
|
|
set_gtk_property!(ent, :text, "I counted to $counter in a separate process!")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return grid
|
||
|
|
end
|
||
|
|
target == Glade && begin
|
||
|
|
g = GtkBuilder(filename="interface.glade")
|
||
|
|
# g = GtkBuilder(buffer=myapp) # if pointing to string
|
||
|
|
|
||
|
|
win = g["window1"]
|
||
|
|
signal_connect(g["button1"], "clicked") do widget
|
||
|
|
println("The button has been clicked")
|
||
|
|
end
|
||
|
|
glade(win)
|
||
|
|
end
|
||
|
|
|