Added GTK+ indeterminate ProgressBars.
This commit is contained in:
parent
bf093d534c
commit
6ee8d96a6e
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
1
todo.md
1
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
|
||||
|
|
Loading…
Reference in New Issue