summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtkcalls_unix.go4
-rw-r--r--progressbar.go1
-rw-r--r--sysdata_unix.go52
-rw-r--r--test/main.go5
-rw-r--r--todo.md1
5 files changed, 61 insertions, 2 deletions
diff --git a/gtkcalls_unix.go b/gtkcalls_unix.go
index bde6b74..5a1a1ae 100644
--- a/gtkcalls_unix.go
+++ b/gtkcalls_unix.go
@@ -216,3 +216,7 @@ func gtk_progress_bar_set_fraction(w *gtkWidget, percent int) {
p := C.gdouble(percent) / 100
C.gtk_progress_bar_set_fraction(togtkprogressbar(w), p)
}
+
+func gtk_progress_bar_pulse(w *gtkWidget) {
+ C.gtk_progress_bar_pulse(togtkprogressbar(w))
+}
diff --git a/progressbar.go b/progressbar.go
index 4d16874..000996c 100644
--- a/progressbar.go
+++ b/progressbar.go
@@ -27,6 +27,7 @@ func NewProgressBar() *ProgressBar {
// If percent is in the range [0,100], the progressBar shows that much percent complete.
// If percent is -1, the ProgressBar is made indeterminate.
// Otherwise, SetProgress panics.
+// TODO what happens if you repeatedly call SetProgress(-1)?
func (p *ProgressBar) SetProgress(percent int) {
p.lock.Lock()
defer p.lock.Unlock()
diff --git a/sysdata_unix.go b/sysdata_unix.go
index 6947e20..91b301c 100644
--- a/sysdata_unix.go
+++ b/sysdata_unix.go
@@ -4,7 +4,7 @@
package ui
import (
- // ...
+ "time"
)
type sysData struct {
@@ -12,6 +12,7 @@ type sysData struct {
widget *gtkWidget
container *gtkWidget // for moving
+ pulse chan bool // for sysData.progressPulse()
}
type classData struct {
@@ -285,7 +286,56 @@ func (s *sysData) delete(index int) {
<-ret
}
+// With GTK+, we must manually pulse the indeterminate progressbar ourselves. This goroutine does that.
+func (s *sysData) progressPulse() {
+ pulse := func() {
+ ret := make(chan struct{})
+ defer close(ret)
+ uitask <- func() {
+ gtk_progress_bar_pulse(s.widget)
+ ret <- struct{}{}
+ }
+ <-ret
+ }
+
+ var ticker *time.Ticker
+ var tickchan <-chan time.Time
+
+ // the default on Windows
+ const pulseRate = 30 * time.Millisecond
+
+ for {
+ select {
+ case start := <-s.pulse:
+ if start {
+ ticker = time.NewTicker(pulseRate)
+ tickchan = ticker.C
+ pulse() // start the pulse animation now, not 30ms later
+ } else {
+ if ticker != nil {
+ ticker.Stop()
+ }
+ ticker = nil
+ tickchan = nil
+ s.pulse <- true // notify sysData.setProgress()
+ }
+ case <-tickchan:
+ pulse()
+ }
+ }
+}
+
func (s *sysData) setProgress(percent int) {
+ if s.pulse == nil {
+ s.pulse = make(chan bool)
+ go s.progressPulse()
+ }
+ if percent == -1 {
+ s.pulse <- true
+ return
+ }
+ s.pulse <- false
+ <-s.pulse // wait for sysData.progressPulse() to register that
ret := make(chan struct{})
defer close(ret)
uitask <- func() {
diff --git a/test/main.go b/test/main.go
index 77adfae..36339ca 100644
--- a/test/main.go
+++ b/test/main.go
@@ -129,8 +129,9 @@ func myMain() {
prog := 0
incButton := NewButton("Inc")
decButton := NewButton("Dec")
+ indetButton := NewButton("Indeterminate")
invalidButton := NewButton("Run Invalid Test")
- sincdec := NewHorizontalStack(incButton, decButton, invalidButton)
+ sincdec := NewHorizontalStack(incButton, decButton, indetButton, invalidButton)
password := NewPasswordEdit()
s0 := NewVerticalStack(s2, c, cb1, cb2, e, s3, pbar, sincdec, Space(), password)
s0.SetStretchy(8)
@@ -224,6 +225,8 @@ mainloop:
prog = 0
}
pbar.SetProgress(prog)
+ case <-indetButton.Clicked:
+ pbar.SetProgress(-1)
case <-invalidButton.Clicked:
invalidTest(cb1, lb1, nil, nil)
}
diff --git a/todo.md b/todo.md
index b954682..a434321 100644
--- a/todo.md
+++ b/todo.md
@@ -23,6 +23,7 @@ so I don't forget:
- change sysData.make() so it does not take the initial window text as an argument and instead have the respective Control/Window.make() call sysData.setText() expressly; this would allow me to remove the "no such concept of text" checks from the GTK+ and Mac OS X backends
important things:
+- GTK+ ProgressBar indeterminate animation is running like mad; pretty sure it's our idle task being evil
- because the main event loop is not called if initialization fails, it is presently impossible for MsgBoxError() to work if UI initialization fails; this basically means we cannot allow initializiation to fail on Mac OS X if we want to be able to report UI init failures to the user with one (which would be desirable, maybe (would violate Windows HIG?))
- figure out where to auto-place windows in Cocoa (also window coordinates are still not flipped properly so (0,0) on screen is the bottom-left)
- also provide a method to center windows; Cocoa provides one for us but