From 2ecb69d0282b943b3a2b5390ba378beb2a77d77e Mon Sep 17 00:00:00 2001
From: "Andrew E. Torda" <torda@zbh.uni-hamburg.de>
Date: Sat, 19 Feb 2022 17:36:24 +0100
Subject: [PATCH] Tidying.

---
 ui/output_tab.go | 43 ++++++++++++++-----------------------------
 ui/param_tab.go  | 36 ++++++++++++++++++++----------------
 ui/ui_run.go     | 33 ++++++++++++++++++---------------
 3 files changed, 52 insertions(+), 60 deletions(-)

diff --git a/ui/output_tab.go b/ui/output_tab.go
index 261b813..e4504f6 100644
--- a/ui/output_tab.go
+++ b/ui/output_tab.go
@@ -24,45 +24,32 @@ import (
 	"fyne.io/fyne/v2/widget"
 )
 
-// A message is sent to the output tab, telling us the current status
+// We have a channel that sends the status to the output tab.
 type status uint8
 
 const (
-	calculating status = iota
-	resultsReady
-	errorCalc
+	calculating  status = iota // currently running a simulation
+	resultsReady               // You should collect the results
+	errorCalc                  // You should display an error message
 )
 
 type workstatus struct {
-	fdata, xdata []byte
+	fdata, xdata []byte // the data in a function or X value plot
 	err          error
-	status       status
-}
-
-// showIniTab is a card to be shown before we have any calculations.
-func showIniTab(cntr *fyne.Container) {
-	cntr.Add(widget.NewCard("No results yet", "go back to the input", nil))
+	status       status // Tells us what we should do now
 }
 
 // If we get a message with an error, display it
 func showErrTab(cntr *fyne.Container, err error) {
+	cntr.Objects = nil
 	cntr.Add(widget.NewCard("ERROR in MC", err.Error(), nil))
 }
 
-// emptyContainer gets rid of any old contents. Could I just say,
-// cntr.Objects = nil ?
-func emptyContainer(cntr *fyne.Container) {
-	for _, o := range cntr.Objects {
-		cntr.Remove(o)
-	}
-}
-
 // showCalcTab is shown while calculating. Have to check if the refresh()
 // is actually necessary.
 func showCalcTab(cntr *fyne.Container) {
-	emptyContainer(cntr)
+	cntr.Objects = nil
 	cntr.Add(widget.NewCard("calculating", "busy", nil))
-	cntr.Refresh()
 }
 
 // fwrt writes the file. It will be called by the filesave dialog
@@ -115,29 +102,27 @@ func png2image(d []byte, fname string) *canvas.Image {
 
 // showResultsTab show the two plots
 func showResultsTab(cntr *fyne.Container, win fyne.Window, fdata, xdata []byte) {
-	emptyContainer(cntr)
+	cntr.Objects = nil
 	fImage := png2image(fdata, "function.png")
 	xImage := png2image(xdata, "xdata.png")
 
 	right := container.NewGridWithRows(2, fImage, xImage)
 	left := leftbar(win, fdata, xdata)
-	box := container.NewHBox(left, right)
+	box := container.NewHBox(left, widget.NewSeparator(), right)
 	cntr.Add(box)
 }
 
 // outputTab is run as a background process. After showing the initial
 // screen, it sits and waits on notifications. When it gets one,
 // it redraws its tab.
-func outputTab(chn chan workstatus, cntr *fyne.Container, form *widget.Form, win fyne.Window) {
-	showIniTab(cntr)
-	breaker()
-	for s := range chn {
+func outputTab(genParams genParams, cntr *fyne.Container, form *widget.Form) {
+	cntr.Add(widget.NewCard("No results yet", "go back to the input", nil))
+	for s := range genParams.chn {
 		switch s.status {
 		case calculating:
 			showCalcTab(cntr)
 		case resultsReady:
-			showResultsTab(cntr, win, s.fdata, s.xdata)
-			breaker()
+			showResultsTab(cntr, genParams.win, s.fdata, s.xdata)
 			form.Enable()
 			form.Refresh()
 		case errorCalc:
diff --git a/ui/param_tab.go b/ui/param_tab.go
index a53c609..b513ee8 100644
--- a/ui/param_tab.go
+++ b/ui/param_tab.go
@@ -21,6 +21,14 @@ import (
 	"example.com/ackley_mc/mc_work"
 )
 
+// startrun is what happens when you click on the form's button to start
+// a calculation.
+func startrun(genParams genParams, form *widget.Form, mcPrm *mcwork.McPrm) {
+	form.Disable()
+	go mcWrap(genParams)
+}
+
+
 // fslicestrng makes a nice string from a slice of float32's
 func fslicestrng(f []float32) string {
 	if len(f) == 0 {
@@ -33,6 +41,7 @@ func fslicestrng(f []float32) string {
 	return s
 }
 
+
 // str2f32 takes a string and returns a slice of float32's
 func s2f32(s string) ([]float32, error) {
 	y := strings.Split(s, ",")
@@ -62,7 +71,7 @@ func validateXini(s string) error {
 // This gets put on the list of things to do from the reload function.
 func floatItem(xAddr *float64, label string) (*widget.FormItem, func()) {
 	bind := binding.BindFloat(xAddr)
-	entry := widget.NewEntryWithData(binding.FloatToStringWithFormat(bind, "%10.2f"))
+	entry := widget.NewEntryWithData(binding.FloatToStringWithFormat(bind, "%.2f"))
 	fitem := widget.NewFormItem(label, entry)
 	reloadfunc := func() { bind.Reload() }
 	return fitem, reloadfunc
@@ -72,7 +81,8 @@ func floatItem(xAddr *float64, label string) (*widget.FormItem, func()) {
 // It returns the screen and a function to be called to refresh it.
 // This is necessary, since there is a button to read parameters from
 // a file, which means all the values should be updated.
-func paramBox(mcPrm *mcwork.McPrm, parent fyne.Window, chn chan workstatus) *widget.Form {
+func paramBox(genParams genParams) *widget.Form {
+	mcPrm := genParams.mcPrm
 	iniTmpItem, iniTmpReload := floatItem(&mcPrm.IniTmp, "initial temperature")
 	fnlTmpItem, fnlTmpReload := floatItem(&mcPrm.FnlTmp, "final temperature")
 	xDltaItem, xDltaReload := floatItem(&mcPrm.XDlta, "X delta")
@@ -103,14 +113,14 @@ func paramBox(mcPrm *mcwork.McPrm, parent fyne.Window, chn chan workstatus) *wid
 		_ = nStepBnd.Reload()
 	}
 
-	rdfile := func() { rdwork(mcPrm, parent, reloadPTab) }
+	rdfile := func() { rdwork(mcPrm, genParams.win, reloadPTab) }
 	rdfileBtn := widget.NewButton("get file       ", rdfile)
 	rdFileItem := widget.NewFormItem("read from a file", rdfileBtn)
 
 	r := widget.NewForm(
 		iniTmpItem, fnlTmpItem, xDltaItem, xIniItem, nStepItem, rdFileItem)
 	r.SubmitText = "start calculation"
-	r.OnSubmit = func() { startrun(chn, parent, r, mcPrm) }
+	r.OnSubmit = func() { startrun(genParams, r, mcPrm) }
 	return r
 }
 
@@ -149,24 +159,18 @@ func rdwork(mcPrm *mcwork.McPrm, parent fyne.Window, reloadPTab func()) {
 // mcWrap is run in the background so the interface does not block.
 // It runs the Monte Carlo, then when it is finished, sends a message
 // down the channel.
-func mcWrap(chn chan workstatus, parent fyne.Window, mcPrm *mcwork.McPrm) {
+func mcWrap(genParams genParams) {
+	chn := genParams.chn
 	chn <- workstatus{status: calculating}
-	if fdata, xdata, err := mcwork.DoRun(mcPrm); err != nil {
-		dialog.NewError(err, parent).Show()
+	if fdata, xdata, err := mcwork.DoRun(genParams.mcPrm); err != nil {
+		dialog.NewError(err, genParams.win).Show()
 		chn <- workstatus{status: errorCalc, err: err}
 	} else {
 		chn <- workstatus{fdata: fdata, xdata: xdata, status: resultsReady}
 	}
 }
 
-// startrun is what happens when you click on the button to start
-// a calculation.
-func startrun(chn chan workstatus, parent fyne.Window, form *widget.Form, mcPrm *mcwork.McPrm) {
-	form.Disable()
-	go mcWrap(chn, parent, mcPrm)
-}
-
 // inputTab sets up the input page.
-func inputTab(mcPrm *mcwork.McPrm, parent fyne.Window, chn chan workstatus) *widget.Form {
-	return paramBox(mcPrm, parent, chn)
+func inputTab(genParams genParams) *widget.Form {
+	return paramBox(genParams)
 }
diff --git a/ui/ui_run.go b/ui/ui_run.go
index a84062d..b041550 100644
--- a/ui/ui_run.go
+++ b/ui/ui_run.go
@@ -7,6 +7,7 @@
 package ui
 
 import (
+	"fyne.io/fyne/v2"
 	"fyne.io/fyne/v2/app"
 	"fyne.io/fyne/v2/container"
 	"fyne.io/fyne/v2/widget"
@@ -14,28 +15,30 @@ import (
 	"example.com/ackley_mc/mc_work"
 )
 
-func UiDoRun(mcPrm *mcwork.McPrm) error {
+// Convenience struct so we do not have perverse long parameter lists
+type genParams struct{
+	mcPrm *mcwork.McPrm  // The MC parameters shared with the main simulation
+	win fyne.Window      // Parent window. Needed for all dialog boxes
+	chn chan workstatus  // To tell the output tab current status
+}
 
+// UiDoRun sets up the screen to do a run. It is effectively a big
+// wrapper around the DoRun() function.
+func UiDoRun(mcPrm *mcwork.McPrm) error {
 	a := app.NewWithID("Monte Carlo")
-	w := a.NewWindow("Monte Carlo")
-	quitbutton := widget.NewButton("click somewhere in here to exit", a.Quit)
+	win := a.NewWindow("Monte Carlo")
 	chn := make(chan workstatus)
-	//	inputTabCallback := func() *widget.Form { return (inputTab(mcPrm, w, chn))}
-	inputForm := inputTab(mcPrm, w, chn)
+	var genParams = genParams {mcPrm, win, chn}
+	inputForm := inputTab(genParams)
+	quitbutton := widget.NewButton("click somewhere in here to confirm", a.Quit)
 	t1 := container.NewTabItem("input tab", inputForm)
 	cntrOut := container.NewWithoutLayout()
 	t2 := container.NewTabItem("output tab", cntrOut)
-	t3 := container.NewTabItem("quit me", quitbutton)
+	t3 := container.NewTabItem("quit", quitbutton)
 	appTab := container.NewAppTabs(t1, t2, t3)
-	w.SetContent(appTab)
-	go outputTab(chn, cntrOut, inputForm, w)
-	w.ShowAndRun()
+	win.SetContent(appTab)
+	go outputTab(genParams, cntrOut, inputForm)
+	win.ShowAndRun()
 	close(chn)
 	return nil
 }
-
-// nothing does nothing
-func nothing(...interface{}) {}
-
-// and breaker does not do much more
-func breaker(...interface{}) {}
-- 
GitLab