Add comments to gui
This commit is contained in:
parent
ea63f43638
commit
50f3f244a3
@ -11,20 +11,28 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func guiErr(err error, msg string, parent fyne.Window) {
|
func guiErr(err error, msg string, parent fyne.Window) {
|
||||||
|
// Create new label containing message
|
||||||
msgLbl := widget.NewLabel(msg)
|
msgLbl := widget.NewLabel(msg)
|
||||||
|
// Text formatting settings
|
||||||
msgLbl.Wrapping = fyne.TextWrapWord
|
msgLbl.Wrapping = fyne.TextWrapWord
|
||||||
msgLbl.Alignment = fyne.TextAlignCenter
|
msgLbl.Alignment = fyne.TextAlignCenter
|
||||||
|
// Create new rectangle to set the size of the dialog
|
||||||
rect := canvas.NewRectangle(color.Transparent)
|
rect := canvas.NewRectangle(color.Transparent)
|
||||||
|
// Set minimum size of rectangle to 350x0
|
||||||
rect.SetMinSize(fyne.NewSize(350, 0))
|
rect.SetMinSize(fyne.NewSize(350, 0))
|
||||||
|
// Create new container containing message and rectangle
|
||||||
content := container.NewVBox(
|
content := container.NewVBox(
|
||||||
msgLbl,
|
msgLbl,
|
||||||
rect,
|
rect,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// Create new label containing error text
|
||||||
errLbl := widget.NewLabel(err.Error())
|
errLbl := widget.NewLabel(err.Error())
|
||||||
|
// Create new dropdown containing error label
|
||||||
content.Add(widget.NewAccordion(
|
content.Add(widget.NewAccordion(
|
||||||
widget.NewAccordionItem("More Details", errLbl),
|
widget.NewAccordionItem("More Details", errLbl),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
// Show error dialog
|
||||||
dialog.NewCustom("Error", "Ok", content, parent).Show()
|
dialog.NewCustom("Error", "Ok", content, parent).Show()
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,9 @@ func infoTab(parent fyne.Window) *fyne.Container {
|
|||||||
canvas.NewRectangle(color.Transparent),
|
canvas.NewRectangle(color.Transparent),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Create label for heart rate
|
||||||
heartRateLbl := newText("0 BPM", 24)
|
heartRateLbl := newText("0 BPM", 24)
|
||||||
|
// Creae container to store heart rate section
|
||||||
heartRate := container.NewVBox(
|
heartRate := container.NewVBox(
|
||||||
newText("Heart Rate", 12),
|
newText("Heart Rate", 12),
|
||||||
heartRateLbl,
|
heartRateLbl,
|
||||||
@ -30,12 +32,17 @@ func infoTab(parent fyne.Window) *fyne.Container {
|
|||||||
)
|
)
|
||||||
infoLayout.Add(heartRate)
|
infoLayout.Add(heartRate)
|
||||||
|
|
||||||
|
// Watch for heart rate updates
|
||||||
go watch(types.ReqTypeWatchHeartRate, func(data interface{}) {
|
go watch(types.ReqTypeWatchHeartRate, func(data interface{}) {
|
||||||
|
// Change text of heart rate label
|
||||||
heartRateLbl.Text = fmt.Sprintf("%d BPM", int(data.(float64)))
|
heartRateLbl.Text = fmt.Sprintf("%d BPM", int(data.(float64)))
|
||||||
|
// Refresh label
|
||||||
heartRateLbl.Refresh()
|
heartRateLbl.Refresh()
|
||||||
}, parent)
|
}, parent)
|
||||||
|
|
||||||
|
// Create label for battery level
|
||||||
battLevelLbl := newText("0%", 24)
|
battLevelLbl := newText("0%", 24)
|
||||||
|
// Create container to store battery level section
|
||||||
battLevel := container.NewVBox(
|
battLevel := container.NewVBox(
|
||||||
newText("Battery Level", 12),
|
newText("Battery Level", 12),
|
||||||
battLevelLbl,
|
battLevelLbl,
|
||||||
@ -43,6 +50,7 @@ func infoTab(parent fyne.Window) *fyne.Container {
|
|||||||
)
|
)
|
||||||
infoLayout.Add(battLevel)
|
infoLayout.Add(battLevel)
|
||||||
|
|
||||||
|
// Watch for changes in battery level
|
||||||
go watch(types.ReqTypeWatchBattLevel, func(data interface{}) {
|
go watch(types.ReqTypeWatchBattLevel, func(data interface{}) {
|
||||||
battLevelLbl.Text = fmt.Sprintf("%d%%", int(data.(float64)))
|
battLevelLbl.Text = fmt.Sprintf("%d%%", int(data.(float64)))
|
||||||
battLevelLbl.Refresh()
|
battLevelLbl.Refresh()
|
||||||
|
@ -8,9 +8,12 @@ import (
|
|||||||
var SockPath = "/tmp/itd/socket"
|
var SockPath = "/tmp/itd/socket"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
// Create new app
|
||||||
a := app.New()
|
a := app.New()
|
||||||
|
// Create new window with title "itgui"
|
||||||
window := a.NewWindow("itgui")
|
window := a.NewWindow("itgui")
|
||||||
|
|
||||||
|
// Create new app tabs container
|
||||||
tabs := container.NewAppTabs(
|
tabs := container.NewAppTabs(
|
||||||
container.NewTabItem("Info", infoTab(window)),
|
container.NewTabItem("Info", infoTab(window)),
|
||||||
container.NewTabItem("Notify", notifyTab(window)),
|
container.NewTabItem("Notify", notifyTab(window)),
|
||||||
@ -18,6 +21,8 @@ func main() {
|
|||||||
container.NewTabItem("Upgrade", upgradeTab(window)),
|
container.NewTabItem("Upgrade", upgradeTab(window)),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Set tabs as window content
|
||||||
window.SetContent(tabs)
|
window.SetContent(tabs)
|
||||||
|
// Show window and run app
|
||||||
window.ShowAndRun()
|
window.ShowAndRun()
|
||||||
}
|
}
|
||||||
|
@ -12,18 +12,23 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func notifyTab(parent fyne.Window) *fyne.Container {
|
func notifyTab(parent fyne.Window) *fyne.Container {
|
||||||
|
// Create new entry for notification title
|
||||||
titleEntry := widget.NewEntry()
|
titleEntry := widget.NewEntry()
|
||||||
titleEntry.SetPlaceHolder("Title")
|
titleEntry.SetPlaceHolder("Title")
|
||||||
|
|
||||||
|
// Create multiline entry for notification body
|
||||||
bodyEntry := widget.NewMultiLineEntry()
|
bodyEntry := widget.NewMultiLineEntry()
|
||||||
bodyEntry.SetPlaceHolder("Body")
|
bodyEntry.SetPlaceHolder("Body")
|
||||||
|
|
||||||
|
// Create new button to send notification
|
||||||
sendBtn := widget.NewButton("Send", func() {
|
sendBtn := widget.NewButton("Send", func() {
|
||||||
|
// Dial itd UNIX socket
|
||||||
conn, err := net.Dial("unix", SockPath)
|
conn, err := net.Dial("unix", SockPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
guiErr(err, "Error dialing socket", parent)
|
guiErr(err, "Error dialing socket", parent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// Encode notify request on connection
|
||||||
json.NewEncoder(conn).Encode(types.Request{
|
json.NewEncoder(conn).Encode(types.Request{
|
||||||
Type: types.ReqTypeNotify,
|
Type: types.ReqTypeNotify,
|
||||||
Data: types.ReqDataNotify{
|
Data: types.ReqDataNotify{
|
||||||
@ -33,6 +38,7 @@ func notifyTab(parent fyne.Window) *fyne.Container {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Return new container containing all elements
|
||||||
return container.NewVBox(
|
return container.NewVBox(
|
||||||
layout.NewSpacer(),
|
layout.NewSpacer(),
|
||||||
titleEntry,
|
titleEntry,
|
||||||
|
@ -13,24 +13,30 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func timeTab(parent fyne.Window) *fyne.Container {
|
func timeTab(parent fyne.Window) *fyne.Container {
|
||||||
|
// Create new entry for time string
|
||||||
timeEntry := widget.NewEntry()
|
timeEntry := widget.NewEntry()
|
||||||
|
// Set text to current time formatter properly
|
||||||
timeEntry.SetText(time.Now().Format(time.RFC1123))
|
timeEntry.SetText(time.Now().Format(time.RFC1123))
|
||||||
|
|
||||||
|
// Create button to set current time
|
||||||
currentBtn := widget.NewButton("Set Current", func() {
|
currentBtn := widget.NewButton("Set Current", func() {
|
||||||
timeEntry.SetText(time.Now().Format(time.RFC1123))
|
timeEntry.SetText(time.Now().Format(time.RFC1123))
|
||||||
setTime(true)
|
setTime(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Create button to set time inside entry
|
||||||
timeBtn := widget.NewButton("Set", func() {
|
timeBtn := widget.NewButton("Set", func() {
|
||||||
|
// Parse time as RFC1123 string
|
||||||
parsedTime, err := time.Parse(time.RFC1123, timeEntry.Text)
|
parsedTime, err := time.Parse(time.RFC1123, timeEntry.Text)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
guiErr(err, "Error parsing time string", parent)
|
guiErr(err, "Error parsing time string", parent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// Set time to parsed time
|
||||||
setTime(false, parsedTime)
|
setTime(false, parsedTime)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Return new container with all elements centered
|
||||||
return container.NewVBox(
|
return container.NewVBox(
|
||||||
layout.NewSpacer(),
|
layout.NewSpacer(),
|
||||||
timeEntry,
|
timeEntry,
|
||||||
@ -43,17 +49,25 @@ func timeTab(parent fyne.Window) *fyne.Container {
|
|||||||
// setTime sets the first element in the variadic parameter
|
// setTime sets the first element in the variadic parameter
|
||||||
// if current is false, otherwise, it sets the current time.
|
// if current is false, otherwise, it sets the current time.
|
||||||
func setTime(current bool, t ...time.Time) error {
|
func setTime(current bool, t ...time.Time) error {
|
||||||
|
// Dial UNIX socket
|
||||||
conn, err := net.Dial("unix", SockPath)
|
conn, err := net.Dial("unix", SockPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer conn.Close()
|
||||||
var data string
|
var data string
|
||||||
|
// If current is true, use the string "now"
|
||||||
|
// otherwise, use the formatted time from the
|
||||||
|
// first element in the variadic parameter.
|
||||||
|
// "now" is more accurate than formatting
|
||||||
|
// current time as only seconds are preserved
|
||||||
|
// in that case.
|
||||||
if current {
|
if current {
|
||||||
data = "now"
|
data = "now"
|
||||||
} else {
|
} else {
|
||||||
data = t[0].Format(time.RFC3339)
|
data = t[0].Format(time.RFC3339)
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
// Encode SetTime request with above data
|
||||||
err = json.NewEncoder(conn).Encode(types.Request{
|
err = json.NewEncoder(conn).Encode(types.Request{
|
||||||
Type: types.ReqTypeSetTime,
|
Type: types.ReqTypeSetTime,
|
||||||
Data: data,
|
Data: data,
|
||||||
|
@ -23,6 +23,7 @@ func upgradeTab(parent fyne.Window) *fyne.Container {
|
|||||||
initPktPath string
|
initPktPath string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Create archive selection dialog
|
||||||
archiveDialog := dialog.NewFileOpen(func(uc fyne.URIReadCloser, e error) {
|
archiveDialog := dialog.NewFileOpen(func(uc fyne.URIReadCloser, e error) {
|
||||||
if e != nil || uc == nil {
|
if e != nil || uc == nil {
|
||||||
return
|
return
|
||||||
@ -30,9 +31,12 @@ func upgradeTab(parent fyne.Window) *fyne.Container {
|
|||||||
uc.Close()
|
uc.Close()
|
||||||
archivePath = uc.URI().Path()
|
archivePath = uc.URI().Path()
|
||||||
}, parent)
|
}, parent)
|
||||||
|
// Limit dialog to .zip files
|
||||||
archiveDialog.SetFilter(storage.NewExtensionFileFilter([]string{".zip"}))
|
archiveDialog.SetFilter(storage.NewExtensionFileFilter([]string{".zip"}))
|
||||||
|
// Create button to show dialog
|
||||||
archiveBtn := widget.NewButton("Select archive (.zip)", archiveDialog.Show)
|
archiveBtn := widget.NewButton("Select archive (.zip)", archiveDialog.Show)
|
||||||
|
|
||||||
|
// Create firmware selection dialog
|
||||||
firmwareDialog := dialog.NewFileOpen(func(uc fyne.URIReadCloser, e error) {
|
firmwareDialog := dialog.NewFileOpen(func(uc fyne.URIReadCloser, e error) {
|
||||||
if e != nil || uc == nil {
|
if e != nil || uc == nil {
|
||||||
return
|
return
|
||||||
@ -40,9 +44,12 @@ func upgradeTab(parent fyne.Window) *fyne.Container {
|
|||||||
uc.Close()
|
uc.Close()
|
||||||
fiwmarePath = uc.URI().Path()
|
fiwmarePath = uc.URI().Path()
|
||||||
}, parent)
|
}, parent)
|
||||||
|
// Limit dialog to .bin files
|
||||||
firmwareDialog.SetFilter(storage.NewExtensionFileFilter([]string{".bin"}))
|
firmwareDialog.SetFilter(storage.NewExtensionFileFilter([]string{".bin"}))
|
||||||
|
// Create button to show dialog
|
||||||
firmwareBtn := widget.NewButton("Select init packet (.bin)", firmwareDialog.Show)
|
firmwareBtn := widget.NewButton("Select init packet (.bin)", firmwareDialog.Show)
|
||||||
|
|
||||||
|
// Create init packet selection dialog
|
||||||
initPktDialog := dialog.NewFileOpen(func(uc fyne.URIReadCloser, e error) {
|
initPktDialog := dialog.NewFileOpen(func(uc fyne.URIReadCloser, e error) {
|
||||||
if e != nil || uc == nil {
|
if e != nil || uc == nil {
|
||||||
return
|
return
|
||||||
@ -50,19 +57,25 @@ func upgradeTab(parent fyne.Window) *fyne.Container {
|
|||||||
uc.Close()
|
uc.Close()
|
||||||
initPktPath = uc.URI().Path()
|
initPktPath = uc.URI().Path()
|
||||||
}, parent)
|
}, parent)
|
||||||
|
// Limit dialog to .dat files
|
||||||
initPktDialog.SetFilter(storage.NewExtensionFileFilter([]string{".dat"}))
|
initPktDialog.SetFilter(storage.NewExtensionFileFilter([]string{".dat"}))
|
||||||
|
// Create button to show dialog
|
||||||
initPktBtn := widget.NewButton("Select init packet (.dat)", initPktDialog.Show)
|
initPktBtn := widget.NewButton("Select init packet (.dat)", initPktDialog.Show)
|
||||||
|
|
||||||
|
// Hide init packet and firmware buttons
|
||||||
initPktBtn.Hide()
|
initPktBtn.Hide()
|
||||||
firmwareBtn.Hide()
|
firmwareBtn.Hide()
|
||||||
|
|
||||||
|
// Create dropdown to select upgrade type
|
||||||
upgradeTypeSelect := widget.NewSelect([]string{
|
upgradeTypeSelect := widget.NewSelect([]string{
|
||||||
"Archive",
|
"Archive",
|
||||||
"Files",
|
"Files",
|
||||||
}, func(s string) {
|
}, func(s string) {
|
||||||
|
// Hide all buttons
|
||||||
archiveBtn.Hide()
|
archiveBtn.Hide()
|
||||||
initPktBtn.Hide()
|
initPktBtn.Hide()
|
||||||
firmwareBtn.Hide()
|
firmwareBtn.Hide()
|
||||||
|
// Unhide appropriate button(s)
|
||||||
switch s {
|
switch s {
|
||||||
case "Archive":
|
case "Archive":
|
||||||
archiveBtn.Show()
|
archiveBtn.Show()
|
||||||
@ -71,26 +84,35 @@ func upgradeTab(parent fyne.Window) *fyne.Container {
|
|||||||
firmwareBtn.Show()
|
firmwareBtn.Show()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
// Select first elemetn
|
||||||
upgradeTypeSelect.SetSelectedIndex(0)
|
upgradeTypeSelect.SetSelectedIndex(0)
|
||||||
|
|
||||||
|
// Create new button to start DFU
|
||||||
startBtn := widget.NewButton("Start", func() {
|
startBtn := widget.NewButton("Start", func() {
|
||||||
|
// If archive path does not exist and both init packet and firmware paths
|
||||||
|
// also do not exist, return error
|
||||||
if archivePath == "" && (initPktPath == "" && fiwmarePath == "") {
|
if archivePath == "" && (initPktPath == "" && fiwmarePath == "") {
|
||||||
guiErr(nil, "Upgrade requires archive or files selected", parent)
|
guiErr(nil, "Upgrade requires archive or files selected", parent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create new label for byte progress
|
||||||
progressLbl := widget.NewLabelWithStyle("0 / 0 B", fyne.TextAlignCenter, fyne.TextStyle{})
|
progressLbl := widget.NewLabelWithStyle("0 / 0 B", fyne.TextAlignCenter, fyne.TextStyle{})
|
||||||
|
// Create new progress bar
|
||||||
progressBar := widget.NewProgressBar()
|
progressBar := widget.NewProgressBar()
|
||||||
|
// Create modal dialog containing label and progress bar
|
||||||
progressDlg := widget.NewModalPopUp(container.NewVBox(
|
progressDlg := widget.NewModalPopUp(container.NewVBox(
|
||||||
layout.NewSpacer(),
|
layout.NewSpacer(),
|
||||||
progressLbl,
|
progressLbl,
|
||||||
progressBar,
|
progressBar,
|
||||||
layout.NewSpacer(),
|
layout.NewSpacer(),
|
||||||
), parent.Canvas())
|
), parent.Canvas())
|
||||||
|
// Resize modal to 300x100
|
||||||
progressDlg.Resize(fyne.NewSize(300, 100))
|
progressDlg.Resize(fyne.NewSize(300, 100))
|
||||||
|
|
||||||
var fwUpgType int
|
var fwUpgType int
|
||||||
var files []string
|
var files []string
|
||||||
|
// Get appropriate upgrade type and file paths
|
||||||
switch upgradeTypeSelect.Selected {
|
switch upgradeTypeSelect.Selected {
|
||||||
case "Archive":
|
case "Archive":
|
||||||
fwUpgType = types.UpgradeTypeArchive
|
fwUpgType = types.UpgradeTypeArchive
|
||||||
@ -100,6 +122,7 @@ func upgradeTab(parent fyne.Window) *fyne.Container {
|
|||||||
files = append(files, initPktPath, fiwmarePath)
|
files = append(files, initPktPath, fiwmarePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dial itd UNIX socket
|
||||||
conn, err := net.Dial("unix", SockPath)
|
conn, err := net.Dial("unix", SockPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
guiErr(err, "Error dialing socket", parent)
|
guiErr(err, "Error dialing socket", parent)
|
||||||
@ -107,6 +130,7 @@ func upgradeTab(parent fyne.Window) *fyne.Container {
|
|||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
|
// Encode firmware upgrade request to connection
|
||||||
json.NewEncoder(conn).Encode(types.Request{
|
json.NewEncoder(conn).Encode(types.Request{
|
||||||
Type: types.ReqTypeFwUpgrade,
|
Type: types.ReqTypeFwUpgrade,
|
||||||
Data: types.ReqDataFwUpgrade{
|
Data: types.ReqDataFwUpgrade{
|
||||||
@ -115,7 +139,10 @@ func upgradeTab(parent fyne.Window) *fyne.Container {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Show progress dialog
|
||||||
progressDlg.Show()
|
progressDlg.Show()
|
||||||
|
// Hide progress dialog after completion
|
||||||
|
defer progressDlg.Hide()
|
||||||
|
|
||||||
scanner := bufio.NewScanner(conn)
|
scanner := bufio.NewScanner(conn)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
@ -141,16 +168,17 @@ func upgradeTab(parent fyne.Window) *fyne.Container {
|
|||||||
if event.Received == event.Total {
|
if event.Received == event.Total {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
// Set label text to received / total B
|
||||||
progressLbl.SetText(fmt.Sprintf("%d / %d B", event.Received, event.Total))
|
progressLbl.SetText(fmt.Sprintf("%d / %d B", event.Received, event.Total))
|
||||||
|
// Set progress bar values
|
||||||
progressBar.Max = float64(event.Total)
|
progressBar.Max = float64(event.Total)
|
||||||
progressBar.Value = float64(event.Received)
|
progressBar.Value = float64(event.Received)
|
||||||
|
// Refresh progress bar
|
||||||
progressBar.Refresh()
|
progressBar.Refresh()
|
||||||
}
|
}
|
||||||
conn.Close()
|
|
||||||
|
|
||||||
progressDlg.Hide()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Return container containing all elements
|
||||||
return container.NewVBox(
|
return container.NewVBox(
|
||||||
layout.NewSpacer(),
|
layout.NewSpacer(),
|
||||||
upgradeTypeSelect,
|
upgradeTypeSelect,
|
||||||
|
Loading…
Reference in New Issue
Block a user