Skip to content

Instantly share code, notes, and snippets.

@penciltester
Created July 18, 2017 01:01
Show Gist options
  • Save penciltester/0b12cf75e145bf5aaf5308c22a6b81a3 to your computer and use it in GitHub Desktop.
Save penciltester/0b12cf75e145bf5aaf5308c22a6b81a3 to your computer and use it in GitHub Desktop.
Concurrent window modification v.2 (with net/http)
package main
import (
"fmt"
"github.com/lxn/walk"
. "github.com/lxn/walk/declarative"
"io"
"io/ioutil"
"net/http"
)
var mainWindow *walk.MainWindow
func main() {
_, err := MainWindow{
AssignTo: &mainWindow,
Title: "Main Window",
MinSize: Size{400, 300},
Layout: VBox{},
Children: []Widget{
Label{Text: "something in main window"},
PushButton{
Text: "Do progress",
OnClicked: func() {
go askDialog()
},
},
},
}.Run()
if err != nil {
fmt.Println(err)
}
}
func askDialog() {
var dialog *walk.Dialog
var acceptPB, cancelPB *walk.PushButton
_, err := Dialog{
AssignTo: &dialog,
Title: "Do you want some progress?",
DefaultButton: &acceptPB,
CancelButton: &cancelPB,
MinSize: Size{300, 100},
Layout: HBox{},
Children: []Widget{
PushButton{
AssignTo: &acceptPB,
Text: "Yes",
OnClicked: func() {
dialog.Accept()
go doProgress()
},
},
PushButton{
AssignTo: &cancelPB,
Text: "No",
OnClicked: func() { dialog.Cancel() },
},
},
}.Run(mainWindow)
if err != nil {
fmt.Println(err)
}
}
func doProgress() {
var dialog *walk.Dialog
var progressBar *walk.ProgressBar
err := Dialog{
AssignTo: &dialog,
Title: "Progress dialog",
MinSize: Size{300, 200},
Layout: VBox{},
Children: []Widget{
ProgressBar{AssignTo: &progressBar},
},
}.Create(mainWindow)
if err != nil {
fmt.Println(err)
return
}
dialog.Starting().Attach(func() {
go progressWorker(dialog, progressBar)
})
dialog.Run()
}
func progressWorker(dialog *walk.Dialog, progressBar *walk.ProgressBar) {
defer dialog.Synchronize(func() {
dialog.Close(0)
})
resp, err := http.Get("http://ipv4.download.thinkbroadband.com/5MB.zip")
if err != nil {
return
}
defer resp.Body.Close()
length := resp.ContentLength
mainWindow.Synchronize(func() {
mainWindow.ProgressIndicator().SetTotal(uint32(length))
})
dialog.Synchronize(func() {
progressBar.SetRange(0, int(length))
})
copyBufCallback(ioutil.Discard, resp.Body, func(n int64) {
fmt.Println("progress", n)
mainWindow.Synchronize(func() {
if err := mainWindow.ProgressIndicator().SetCompleted(uint32(n)); err != nil {
fmt.Println(err)
}
})
dialog.Synchronize(func() {
progressBar.SetValue(int(n))
})
})
fmt.Println("done")
}
func copyBufCallback(dst io.Writer, src io.Reader, callback func(int64)) (written int64, err error) {
buf := make([]byte, 32*1024)
for {
nr, er := src.Read(buf)
if nr > 0 {
nw, ew := dst.Write(buf[0:nr])
if nw > 0 {
written += int64(nw)
callback(written)
}
if ew != nil {
err = ew
break
}
if nr != nw {
err = io.ErrShortWrite
break
}
}
if er != nil {
if er != io.EOF {
err = er
}
break
}
}
return written, err
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment