Skip to content

Commit 26f9433

Browse files
authored
Merge pull request #140 from emer/leabra-merge
mergeable version of changes from leabra branch
2 parents e619cee + 727125a commit 26f9433

File tree

5 files changed

+150
-6
lines changed

5 files changed

+150
-6
lines changed

egui/gui.go

Lines changed: 131 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,24 @@ package egui
77
//go:generate core generate -add-types
88

99
import (
10+
"embed"
11+
"fmt"
1012
"io/fs"
13+
"net/http"
14+
"strings"
1115
"sync"
1216

17+
"cogentcore.org/core/base/errors"
18+
"cogentcore.org/core/base/fileinfo/mimedata"
19+
"cogentcore.org/core/base/labels"
1320
"cogentcore.org/core/core"
1421
"cogentcore.org/core/enums"
1522
"cogentcore.org/core/events"
23+
"cogentcore.org/core/htmlcore"
1624
"cogentcore.org/core/styles"
25+
"cogentcore.org/core/styles/abilities"
26+
"cogentcore.org/core/system"
27+
"cogentcore.org/core/text/textcore"
1728
"cogentcore.org/core/tree"
1829
_ "cogentcore.org/lab/gosl/slbool/slboolcore" // include to get gui views
1930
"cogentcore.org/lab/lab"
@@ -40,6 +51,9 @@ type GUI struct {
4051
// Body is the entire content of the sim window.
4152
Body *core.Body `display:"-"`
4253

54+
// Readme is the sim readme frame
55+
Readme *core.Frame `display:"-"`
56+
4357
// OnStop is called when running is stopped through the GUI,
4458
// via the Stopped method. It should update the network view for example.
4559
OnStop func(mode, level enums.Enum)
@@ -136,8 +150,8 @@ func NewGUIBody(b tree.Node, sim any, fsroot fs.FS, appname, title, about string
136150
// a [core.Form] editor of the given sim object, and a filetree for the data filesystem
137151
// rooted at fsroot, and with given app name, title, and about information.
138152
// The first arg is an optional existing [core.Body] to make into: if nil then
139-
// a new body is made first.
140-
func (gui *GUI) MakeBody(b tree.Node, sim any, fsroot fs.FS, appname, title, about string) {
153+
// a new body is made first. It takes an optional fs with a README.md file.
154+
func (gui *GUI) MakeBody(b tree.Node, sim any, fsroot fs.FS, appname, title, about string, readme ...embed.FS) {
141155
gui.StopLevel = etime.NoTime // corresponds to the first level typically
142156
core.NoSentenceCaseFor = append(core.NoSentenceCaseFor, "github.com/emer")
143157
if b == nil {
@@ -183,8 +197,121 @@ func (gui *GUI) MakeBody(b tree.Node, sim any, fsroot fs.FS, appname, title, abo
183197
gui.CycleUpdateInterval = 10
184198
gui.UpdateFiles()
185199
gui.Files.Tabber = tabs
186-
split.SetTiles(core.TileSplit, core.TileSpan)
187-
split.SetSplits(.2, .5, .8)
200+
201+
if len(readme) > 0 {
202+
gui.addReadme(readme[0], split)
203+
} else {
204+
split.SetTiles(core.TileSplit, core.TileSpan)
205+
split.SetSplits(.2, .5, .8)
206+
}
207+
}
208+
209+
func (gui *GUI) addReadme(readmefs embed.FS, split *core.Splits) {
210+
gui.Readme = core.NewFrame(split)
211+
gui.Readme.Name = "readme"
212+
213+
split.SetTiles(core.TileSplit, core.TileSpan, core.TileSpan)
214+
split.SetSplits(.2, .5, .5, .3)
215+
216+
ctx := htmlcore.NewContext()
217+
218+
ctx.GetURL = func(rawURL string) (*http.Response, error) {
219+
return htmlcore.GetURLFromFS(readmefs, rawURL)
220+
}
221+
222+
ctx.AddWikilinkHandler(gui.readmeWikilink("sim"))
223+
224+
ctx.OpenURL = gui.readmeOpenURL
225+
226+
eds := []*textcore.Editor{}
227+
228+
ctx.ElementHandlers["sim-question"] = func(ctx *htmlcore.Context) bool {
229+
ed := textcore.NewEditor(ctx.BlockParent)
230+
ed.Lines.Settings.LineNumbers = false
231+
eds = append(eds, ed)
232+
id := htmlcore.GetAttr(ctx.Node, "id")
233+
ed.SetName(id)
234+
return true
235+
}
236+
237+
core.NewButton(gui.Readme).SetText("Copy answers").OnClick(func(e events.Event) {
238+
clipboard := gui.Readme.Clipboard()
239+
var ab strings.Builder
240+
for _, ed := range eds {
241+
ab.WriteString("## Question " + ed.Name + "\n" + ed.Lines.String() + "\n")
242+
}
243+
answers := ab.String()
244+
md := mimedata.NewText(answers)
245+
clipboard.Write(md)
246+
core.MessageSnackbar(gui.Body, "Answers copied to clipboard")
247+
})
248+
249+
readme, err := readmefs.ReadFile("README.md")
250+
251+
if errors.Log(err) == nil {
252+
htmlcore.ReadMDString(ctx, gui.Readme, string(readme))
253+
}
254+
}
255+
256+
func (gui *GUI) readmeWikilink(prefix string) htmlcore.WikilinkHandler {
257+
return func(text string) (url string, label string) {
258+
if !strings.HasPrefix(text, prefix+":") {
259+
return "", ""
260+
}
261+
text = strings.TrimPrefix(text, prefix+":")
262+
url = prefix + "://" + text
263+
if strings.Contains(text, "/") {
264+
_, text, _ = strings.Cut(text, "/")
265+
}
266+
return url, text
267+
}
268+
}
269+
270+
// readmeOpenURL Parses URL, highlights linked button or opens URL
271+
func (gui *GUI) readmeOpenURL(url string) {
272+
focusSet := false
273+
if !strings.HasPrefix(url, "sim://") {
274+
system.TheApp.OpenURL(url)
275+
return
276+
}
277+
278+
text := strings.TrimPrefix(url, "sim://")
279+
var pathPrefix string = ""
280+
hasPath := false
281+
if strings.Contains(text, "/") {
282+
pathPrefix, text, hasPath = strings.Cut(text, "/")
283+
}
284+
285+
gui.Body.Scene.WidgetWalkDown(func(cw core.Widget, cwb *core.WidgetBase) bool {
286+
if focusSet {
287+
return tree.Break
288+
}
289+
if !hasPath && !cwb.IsDisplayable() {
290+
return tree.Break
291+
}
292+
if hasPath && !strings.Contains(cw.AsTree().Path(), pathPrefix) {
293+
return tree.Continue
294+
}
295+
label := labels.ToLabel(cw)
296+
if !strings.EqualFold(label, text) {
297+
return tree.Continue
298+
}
299+
if cwb.AbilityIs(abilities.Focusable) {
300+
cwb.SetFocus()
301+
focusSet = true
302+
return tree.Break
303+
}
304+
next := core.AsWidget(tree.Next(cwb))
305+
if next.AbilityIs(abilities.Focusable) {
306+
next.SetFocus()
307+
focusSet = true
308+
return tree.Break
309+
}
310+
return tree.Continue
311+
})
312+
if !focusSet {
313+
core.ErrorSnackbar(gui.Body, fmt.Errorf("invalid sim url %q", url))
314+
}
188315
}
189316

190317
// AddNetView adds NetView in tab with given name

egui/plots.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ func (gui *GUI) AddTableView(lg *elog.Logs, mode etime.Modes, time etime.Times)
215215
return nil
216216
}
217217
218-
tt, _ := gui.Tabs.NewTab(mode.String() + " " + time.String() + " ")
218+
tt, _ := gui.Tabs.NewTab(mode.String() + " " + time.String())
219219
tv := tensorcore.NewTable(tt)
220220
gui.TableViews[key] = tv
221221
tv.SetReadOnly(true)

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ require (
2121
github.com/cogentcore/webgpu v0.23.0 // indirect
2222
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
2323
github.com/dlclark/regexp2 v1.11.0 // indirect
24+
github.com/ericchiang/css v1.3.0 // indirect
2425
github.com/fsnotify/fsnotify v1.8.0 // indirect
2526
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a // indirect
2627
github.com/go-text/typesetting v0.3.1-0.20250402122313-7a0f05577ff5 // indirect
2728
github.com/gobwas/glob v0.2.3 // indirect
29+
github.com/gomarkdown/markdown v0.0.0-20250311123330-531bef5e742b // indirect
2830
github.com/gorilla/css v1.0.1 // indirect
2931
github.com/h2non/filetype v1.1.3 // indirect
3032
github.com/hack-pad/go-indexeddb v0.3.2 // indirect

go.sum

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
3636
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3737
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
3838
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
39+
github.com/ericchiang/css v1.3.0 h1:e0vS+vpujMjtT3/SYu7qTHn1LVzXWcLCCDjlfq3YlLY=
40+
github.com/ericchiang/css v1.3.0/go.mod h1:sVSdL+MFR9Q4cKJMQzpIkHIDOLiK+7Wmjjhq7D+MubA=
3941
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
4042
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
4143
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
@@ -49,6 +51,9 @@ github.com/go-text/typesetting-utils v0.0.0-20241103174707-87a29e9e6066 h1:qCuYC
4951
github.com/go-text/typesetting-utils v0.0.0-20241103174707-87a29e9e6066/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o=
5052
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
5153
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
54+
github.com/gomarkdown/markdown v0.0.0-20250311123330-531bef5e742b h1:EY/KpStFl60qA17CptGXhwfZ+k1sFNJIUNR8DdbcuUk=
55+
github.com/gomarkdown/markdown v0.0.0-20250311123330-531bef5e742b/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
56+
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
5257
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
5358
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
5459
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
@@ -127,19 +132,26 @@ golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ=
127132
golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs=
128133
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
129134
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
135+
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
130136
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
131137
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
132138
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
133139
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
134140
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
141+
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
142+
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
135143
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
136144
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
137145
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
146+
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
138147
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
148+
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
139149
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
140150
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
151+
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
141152
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
142153
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
154+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
143155
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
144156
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
145157
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

netview/netview.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ func (nv *NetView) Init() {
103103
})
104104

105105
tree.AddChildAt(nv, "tbar", func(w *core.Toolbar) {
106-
w.FinalStyler(func(s *styles.Style) {
106+
w.Styler(func(s *styles.Style) {
107107
s.Wrap = true
108108
})
109109
w.Maker(nv.MakeToolbar)
@@ -139,6 +139,9 @@ func (nv *NetView) Init() {
139139
})
140140
})
141141
tree.AddChildAt(nv, "vbar", func(w *core.Toolbar) {
142+
w.Styler(func(s *styles.Style) {
143+
s.Wrap = true
144+
})
142145
w.Maker(nv.MakeViewbar)
143146
})
144147
}

0 commit comments

Comments
 (0)