From 9877b0d45117f7f94a117d8da05c80195314b7b5 Mon Sep 17 00:00:00 2001
From: Rick Sprague <>
Date: Mon, 28 Oct 2024 10:02:43 -0400
Subject: [PATCH] julia
---
julia/genie/GenieFrameworkDemos_NewAPI | 1 +
julia/genie/main.jl | 39 ++++
julia/gtk_example.jl | 302 +++++++++++++++++++++++++
julia/interface.glade | 17 ++
julia/main.jl | 5 +
julia/packages | 1 +
julia/process.jl | 86 +++++++
julia/rick.jld2 | 3 +
julia/serialization.jld2 | 3 +
julia/tlv_example.jl | 34 +++
10 files changed, 491 insertions(+)
create mode 160000 julia/genie/GenieFrameworkDemos_NewAPI
create mode 100644 julia/genie/main.jl
create mode 100644 julia/gtk_example.jl
create mode 100644 julia/interface.glade
create mode 100644 julia/main.jl
create mode 160000 julia/packages
create mode 100644 julia/process.jl
create mode 100644 julia/rick.jld2
create mode 100644 julia/serialization.jld2
create mode 100644 julia/tlv_example.jl
diff --git a/julia/genie/GenieFrameworkDemos_NewAPI b/julia/genie/GenieFrameworkDemos_NewAPI
new file mode 160000
index 0000000..f95d68f
--- /dev/null
+++ b/julia/genie/GenieFrameworkDemos_NewAPI
@@ -0,0 +1 @@
+Subproject commit f95d68fc99bdd0baddf98c597fbf770a0e2bb28c
diff --git a/julia/genie/main.jl b/julia/genie/main.jl
new file mode 100644
index 0000000..b0f7194
--- /dev/null
+++ b/julia/genie/main.jl
@@ -0,0 +1,39 @@
+using GenieFramework
+
+@genietools
+
+
+@in my_button = false
+@in text = "Some text"
+@out function1 = jsfunction"""() => console.log("A")"""
+
+@handlers begin
+ @onchange text begin
+ println(text)
+ end
+
+ @onchange my_button begin
+ println("pressed")
+ end
+end
+
+function ui()
+ c = card([
+ card_section("This is a section", class="bg-primary text-white")
+ separator()
+ card_section("RR")
+ card_section("{{ text }}")
+ ])
+ rv = row([
+ c
+ btn("A button", @click("my_button = !my_button"))
+ btn("A button", @click("function1"))
+ textfield("What is your name?", :text, placeholder="Type some text")
+ ]; class="q-gutter-sm")
+ println(rv |> string)
+ return rv
+end
+
+@page("/", ui)
+
+Server.isrunning() || Server.up()
diff --git a/julia/gtk_example.jl b/julia/gtk_example.jl
new file mode 100644
index 0000000..f780391
--- /dev/null
+++ b/julia/gtk_example.jl
@@ -0,0 +1,302 @@
+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 = """My Bold text\n
+ GTK+ website"""
+ 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
+
diff --git a/julia/interface.glade b/julia/interface.glade
new file mode 100644
index 0000000..3a735a1
--- /dev/null
+++ b/julia/interface.glade
@@ -0,0 +1,17 @@
+
+
+
+
+
diff --git a/julia/main.jl b/julia/main.jl
new file mode 100644
index 0000000..8870b88
--- /dev/null
+++ b/julia/main.jl
@@ -0,0 +1,5 @@
+
+z = Dict(1=>10, 2=>20)
+for a in z
+ println(a)
+end
diff --git a/julia/packages b/julia/packages
new file mode 160000
index 0000000..feca907
--- /dev/null
+++ b/julia/packages
@@ -0,0 +1 @@
+Subproject commit feca90734fc35a6f81c994e72efe0857a6c6b3a3
diff --git a/julia/process.jl b/julia/process.jl
new file mode 100644
index 0000000..312a70b
--- /dev/null
+++ b/julia/process.jl
@@ -0,0 +1,86 @@
+#using Gtk
+
+@Base.kwdef mutable struct Lines
+ reminant::Union{String, Nothing} = nothing
+ lines::Vector{String} = String[]
+end
+
+function Base.push!(ls::Lines, s::String)
+ if ls.reminant != nothing
+ s = ls.reminant * s
+ ls.reminant = nothing
+ end
+
+ lines = split(s, '\n', keepempty=false)
+
+ if s[end] == '\n'
+ for l in lines
+ push!(ls.lines, l)
+ end
+ return
+ end
+
+ ls.reminant = String(lines[end])
+ for l in lines[1:end - 1]
+ push!(ls.lines, l)
+ end
+end
+
+function launch_process(running::Function, cmd::Cmd; start::Function=()->begin end, stop::Function=()->begin end)
+ Threads.@spawn begin
+ lines = Lines()
+ buf = IOBuffer()
+ process = run(pipeline(ignorestatus(cmd), stdout=buf), wait=false)
+ start()
+ while process_running(process)
+ sleep(1)
+ push!(lines, String(take!(buf)))
+ if length(lines.lines) > 0
+ running(lines.lines)
+ empty!(lines.lines)
+ end
+ end
+ stop()
+ end
+end
+
+launch_process(`./a.out`; start=()->println("Start"), stop=()->println("Stop")) do strings
+ for s in strings
+ println("Running: $s")
+ end
+end
+sleep(60)
+#win = GtkWindow("Hello", 800, 600)
+#
+#function createMenuBar()
+# mb = GtkMenuBar()
+#
+# # file menu
+# begin
+# fileMenu = GtkMenuItem("_File")
+# fileSub = GtkMenu(fileMenu)
+# push!(fileSub, GtkMenuItem("_New"))
+# push!(fileSub, GtkMenuItem("_Open"))
+# push!(fileSub, GtkSeparatorMenuItem())
+# fileExit = GtkMenuItem("E_xit")
+# signal_connect(fileExit, :activate) do widget
+# Gtk.destroy(win)
+# end
+# push!(fileSub, fileExit)
+# push!(mb, fileMenu)
+# end
+# return mb
+#end
+#
+#
+#vbox = GtkBox(:v)
+#tv = GtkTextView()
+#push!(vbox, createMenuBar())
+#push!(vbox, GtkScrolledWindow(tv))
+#push!(win, vbox)
+#showall(win)
+#
+#if !isinteractive()
+# @async Gtk.gtk_main()
+# Gtk.waitforsignal(win, :destroy)
+#end
diff --git a/julia/rick.jld2 b/julia/rick.jld2
new file mode 100644
index 0000000..4ec67e9
--- /dev/null
+++ b/julia/rick.jld2
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ae94a0300f71329c488c039ecda954b0a77a4416fa0bd9057ab4cd7d1eb59146
+size 810
diff --git a/julia/serialization.jld2 b/julia/serialization.jld2
new file mode 100644
index 0000000..27caeca
--- /dev/null
+++ b/julia/serialization.jld2
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6f6259a58035300abcfbcdd6faeab9214a4315c23a51ba166af3a43b2c61acf1
+size 843108
diff --git a/julia/tlv_example.jl b/julia/tlv_example.jl
new file mode 100644
index 0000000..6c2ef6b
--- /dev/null
+++ b/julia/tlv_example.jl
@@ -0,0 +1,34 @@
+include("packages/TLV.jl")
+
+#const DATA_DIR = "/data/Data/181283340_06_06_2022_HIGHWAY"
+const DATA_DIR = "/data/Data/166543251_10_27_2021_OVAL"
+
+@time points_east, points_north = TLV.cache("serialization.jld2"; force=false) do
+ east = []
+ north = []
+ function callback(header, msg)
+ pma = msg["s_Data"]["s_PMA_LocalizationPose"]
+ pose = pma["s_PoseLocation"]
+ push!(east, pose["e_l_east"])
+ push!(north, pose["e_l_north"])
+ return false
+ end
+
+ topics = TLV.log_create_reader_config(
+ [
+ # ["UC_SYSTEM", "GPS_DATA_SERVICE"]
+ # ["UC_SYSTEM", "PERCEIVED_ROAD_GEOMETRY"]
+ ["UC_LOC_OUT", "LOC_ASSOCIATED_ROAD_GEOMETRY"]
+ ]
+ )
+
+ TLV.log_read(DATA_DIR, topics, callback)
+ return east, north
+end
+
+
+using Plots
+display(scatter(points_east, points_north; title="Oval Track",
+ legend=false, mc=:blue, ms=.05))
+readline()
+#gui()