Issue #62.
This commit is contained in:
parent
46705a38f5
commit
2359e42bb9
11 changed files with 63 additions and 37 deletions
|
@ -609,6 +609,9 @@ func loadFlags() []zenity.Option {
|
||||||
if noCancel {
|
if noCancel {
|
||||||
opts = append(opts, zenity.NoCancel())
|
opts = append(opts, zenity.NoCancel())
|
||||||
}
|
}
|
||||||
|
if autoClose {
|
||||||
|
opts = append(opts, zenity.AutoClose())
|
||||||
|
}
|
||||||
if timeRemaining {
|
if timeRemaining {
|
||||||
opts = append(opts, zenity.TimeRemaining())
|
opts = append(opts, zenity.TimeRemaining())
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func progress(opts ...zenity.Option) (err error) {
|
func progress(opts ...zenity.Option) (err error) {
|
||||||
|
const scale = 16777216
|
||||||
|
|
||||||
|
opts = append(opts, zenity.MaxValue(scale*100))
|
||||||
dlg, err := zenity.Progress(opts...)
|
dlg, err := zenity.Progress(opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -30,7 +33,7 @@ func progress(opts ...zenity.Option) (err error) {
|
||||||
if err := dlg.Text(text); err != nil {
|
if err := dlg.Text(text); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := dlg.Value(int(math.Round(percentage))); err != nil {
|
if err := dlg.Value(int(math.Round(scale * percentage))); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,12 +57,9 @@ func progress(opts ...zenity.Option) (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if v, err := strconv.ParseFloat(line, 64); err == nil {
|
} else if v, err := strconv.ParseFloat(line, 64); err == nil {
|
||||||
if err := dlg.Value(int(math.Round(v))); err != nil {
|
if err := dlg.Value(int(math.Round(scale * v))); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if v >= 100 && autoClose {
|
|
||||||
return dlg.Close()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
case <-dlg.Done():
|
case <-dlg.Done():
|
||||||
|
|
|
@ -20,6 +20,7 @@ type progressDialog struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
cmd *exec.Cmd
|
cmd *exec.Cmd
|
||||||
max int
|
max int
|
||||||
|
close bool
|
||||||
percent bool
|
percent bool
|
||||||
closed int32
|
closed int32
|
||||||
lines chan string
|
lines chan string
|
||||||
|
@ -41,6 +42,9 @@ func (d *progressDialog) Text(text string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *progressDialog) Value(value int) error {
|
func (d *progressDialog) Value(value int) error {
|
||||||
|
if value >= d.max && d.close {
|
||||||
|
return d.Close()
|
||||||
|
}
|
||||||
if d.percent {
|
if d.percent {
|
||||||
return d.send(strconv.FormatFloat(100*float64(value)/float64(d.max), 'f', -1, 64))
|
return d.send(strconv.FormatFloat(100*float64(value)/float64(d.max), 'f', -1, 64))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -46,7 +46,7 @@ func Run(ctx context.Context, script string, data any) ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunProgress is internal.
|
// RunProgress is internal.
|
||||||
func RunProgress(ctx context.Context, max int, data Progress) (dlg *progressDialog, err error) {
|
func RunProgress(ctx context.Context, max int, close bool, data Progress) (_ *progressDialog, err error) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
err = scripts.ExecuteTemplate(&buf, "progress", data)
|
err = scripts.ExecuteTemplate(&buf, "progress", data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -108,10 +108,11 @@ func RunProgress(ctx context.Context, max int, data Progress) (dlg *progressDial
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
dlg = &progressDialog{
|
dlg := &progressDialog{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cmd: cmd,
|
cmd: cmd,
|
||||||
max: max,
|
max: max,
|
||||||
|
close: close,
|
||||||
lines: make(chan string),
|
lines: make(chan string),
|
||||||
done: make(chan struct{}),
|
done: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ func Run(ctx context.Context, args []string) ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunProgress is internal.
|
// RunProgress is internal.
|
||||||
func RunProgress(ctx context.Context, max int, extra *string, args []string) (*progressDialog, error) {
|
func RunProgress(ctx context.Context, max int, close bool, extra *string, args []string) (*progressDialog, error) {
|
||||||
pathOnce.Do(initPath)
|
pathOnce.Do(initPath)
|
||||||
if Command && path != "" {
|
if Command && path != "" {
|
||||||
if Timeout > 0 {
|
if Timeout > 0 {
|
||||||
|
@ -85,6 +85,7 @@ func RunProgress(ctx context.Context, max int, extra *string, args []string) (*p
|
||||||
cmd: cmd,
|
cmd: cmd,
|
||||||
max: max,
|
max: max,
|
||||||
percent: true,
|
percent: true,
|
||||||
|
close: close,
|
||||||
lines: make(chan string),
|
lines: make(chan string),
|
||||||
done: make(chan struct{}),
|
done: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ func TestRun_context(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunProgress(t *testing.T) {
|
func TestRunProgress(t *testing.T) {
|
||||||
_, err := RunProgress(nil, 100, nil, []string{"--version"})
|
_, err := RunProgress(nil, 100, false, nil, []string{"--version"})
|
||||||
if skip, err := skip(err); skip {
|
if skip, err := skip(err); skip {
|
||||||
t.Skip("skipping:", err)
|
t.Skip("skipping:", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,11 @@ func NoCancel() Option {
|
||||||
return funcOption(func(o *options) { o.noCancel = true })
|
return funcOption(func(o *options) { o.noCancel = true })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AutoClose returns an Option to dismiss the dialog when 100% has been reached.
|
||||||
|
func AutoClose() Option {
|
||||||
|
return funcOption(func(o *options) { o.autoClose = true })
|
||||||
|
}
|
||||||
|
|
||||||
// TimeRemaining returns an Option to estimate when progress will reach 100% (Unix only).
|
// TimeRemaining returns an Option to estimate when progress will reach 100% (Unix only).
|
||||||
func TimeRemaining() Option {
|
func TimeRemaining() Option {
|
||||||
return funcOption(func(o *options) { o.timeRemaining = true })
|
return funcOption(func(o *options) { o.timeRemaining = true })
|
||||||
|
|
|
@ -23,5 +23,5 @@ func progress(opts options) (ProgressDialog, error) {
|
||||||
data.WindowIcon = i
|
data.WindowIcon = i
|
||||||
}
|
}
|
||||||
|
|
||||||
return zenutil.RunProgress(opts.ctx, opts.maxValue, data)
|
return zenutil.RunProgress(opts.ctx, opts.maxValue, opts.autoClose, data)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,11 @@ func progress(opts options) (ProgressDialog, error) {
|
||||||
if opts.noCancel {
|
if opts.noCancel {
|
||||||
args = append(args, "--no-cancel")
|
args = append(args, "--no-cancel")
|
||||||
}
|
}
|
||||||
|
if opts.autoClose {
|
||||||
|
args = append(args, "--auto-close")
|
||||||
|
}
|
||||||
if opts.timeRemaining {
|
if opts.timeRemaining {
|
||||||
args = append(args, "--time-remaining")
|
args = append(args, "--time-remaining")
|
||||||
}
|
}
|
||||||
return zenutil.RunProgress(opts.ctx, opts.maxValue, opts.extraButton, args)
|
return zenutil.RunProgress(opts.ctx, opts.maxValue, opts.autoClose, opts.extraButton, args)
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,9 @@ func progress(opts options) (ProgressDialog, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
dlg := &progressDialog{
|
dlg := &progressDialog{
|
||||||
done: make(chan struct{}),
|
done: make(chan struct{}),
|
||||||
max: opts.maxValue,
|
max: opts.maxValue,
|
||||||
|
close: opts.autoClose,
|
||||||
}
|
}
|
||||||
dlg.init.Add(1)
|
dlg.init.Add(1)
|
||||||
|
|
||||||
|
@ -44,10 +45,11 @@ func progress(opts options) (ProgressDialog, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type progressDialog struct {
|
type progressDialog struct {
|
||||||
init sync.WaitGroup
|
init sync.WaitGroup
|
||||||
done chan struct{}
|
done chan struct{}
|
||||||
max int
|
err error
|
||||||
err error
|
max int
|
||||||
|
close bool
|
||||||
|
|
||||||
wnd win.HWND
|
wnd win.HWND
|
||||||
textCtl win.HWND
|
textCtl win.HWND
|
||||||
|
@ -69,6 +71,9 @@ func (d *progressDialog) Text(text string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *progressDialog) Value(value int) error {
|
func (d *progressDialog) Value(value int) error {
|
||||||
|
if value >= d.max && d.close {
|
||||||
|
return d.Close()
|
||||||
|
}
|
||||||
select {
|
select {
|
||||||
default:
|
default:
|
||||||
win.SendMessage(d.progCtl, win.PBM_SETPOS, uintptr(value), 0)
|
win.SendMessage(d.progCtl, win.PBM_SETPOS, uintptr(value), 0)
|
||||||
|
@ -156,10 +161,12 @@ func (dlg *progressDialog) setup(opts options) error {
|
||||||
nil, flags,
|
nil, flags,
|
||||||
12, 30, 241, 16, dlg.wnd, 0, instance, nil)
|
12, 30, 241, 16, dlg.wnd, 0, instance, nil)
|
||||||
|
|
||||||
dlg.okBtn, _ = win.CreateWindowEx(0,
|
if !opts.noCancel || !opts.autoClose {
|
||||||
strptr("BUTTON"), strptr(quoteAccelerators(*opts.okLabel)),
|
dlg.okBtn, _ = win.CreateWindowEx(0,
|
||||||
_WS_ZEN_BUTTON|win.BS_DEFPUSHBUTTON|win.WS_DISABLED,
|
strptr("BUTTON"), strptr(quoteAccelerators(*opts.okLabel)),
|
||||||
12, 58, 75, 24, dlg.wnd, win.IDOK, instance, nil)
|
_WS_ZEN_BUTTON|win.BS_DEFPUSHBUTTON|win.WS_DISABLED,
|
||||||
|
12, 58, 75, 24, dlg.wnd, win.IDOK, instance, nil)
|
||||||
|
}
|
||||||
if !opts.noCancel {
|
if !opts.noCancel {
|
||||||
dlg.cancelBtn, _ = win.CreateWindowEx(0,
|
dlg.cancelBtn, _ = win.CreateWindowEx(0,
|
||||||
strptr("BUTTON"), strptr(quoteAccelerators(*opts.cancelLabel)),
|
strptr("BUTTON"), strptr(quoteAccelerators(*opts.cancelLabel)),
|
||||||
|
@ -213,22 +220,23 @@ func (d *progressDialog) layout(dpi dpi) {
|
||||||
win.SetWindowPos(d.wnd, 0, 0, 0, dpi.scale(281), dpi.scale(133), win.SWP_NOMOVE|win.SWP_NOZORDER)
|
win.SetWindowPos(d.wnd, 0, 0, 0, dpi.scale(281), dpi.scale(133), win.SWP_NOMOVE|win.SWP_NOZORDER)
|
||||||
win.SetWindowPos(d.textCtl, 0, dpi.scale(12), dpi.scale(10), dpi.scale(241), dpi.scale(16), win.SWP_NOZORDER)
|
win.SetWindowPos(d.textCtl, 0, dpi.scale(12), dpi.scale(10), dpi.scale(241), dpi.scale(16), win.SWP_NOZORDER)
|
||||||
win.SetWindowPos(d.progCtl, 0, dpi.scale(12), dpi.scale(30), dpi.scale(241), dpi.scale(16), win.SWP_NOZORDER)
|
win.SetWindowPos(d.progCtl, 0, dpi.scale(12), dpi.scale(30), dpi.scale(241), dpi.scale(16), win.SWP_NOZORDER)
|
||||||
if d.extraBtn == 0 {
|
|
||||||
if d.cancelBtn == 0 {
|
pos := 178
|
||||||
win.SetWindowPos(d.okBtn, 0, dpi.scale(178), dpi.scale(58), dpi.scale(75), dpi.scale(24), win.SWP_NOZORDER)
|
if d.cancelBtn != 0 {
|
||||||
} else {
|
win.SetWindowPos(d.cancelBtn, 0, dpi.scale(pos), dpi.scale(58), dpi.scale(75), dpi.scale(24), win.SWP_NOZORDER)
|
||||||
win.SetWindowPos(d.okBtn, 0, dpi.scale(95), dpi.scale(58), dpi.scale(75), dpi.scale(24), win.SWP_NOZORDER)
|
pos -= 83
|
||||||
win.SetWindowPos(d.cancelBtn, 0, dpi.scale(178), dpi.scale(58), dpi.scale(75), dpi.scale(24), win.SWP_NOZORDER)
|
}
|
||||||
}
|
if d.extraBtn != 0 {
|
||||||
} else {
|
win.SetWindowPos(d.extraBtn, 0, dpi.scale(pos), dpi.scale(58), dpi.scale(75), dpi.scale(24), win.SWP_NOZORDER)
|
||||||
if d.cancelBtn == 0 {
|
pos -= 83
|
||||||
win.SetWindowPos(d.okBtn, 0, dpi.scale(95), dpi.scale(58), dpi.scale(75), dpi.scale(24), win.SWP_NOZORDER)
|
}
|
||||||
win.SetWindowPos(d.extraBtn, 0, dpi.scale(178), dpi.scale(58), dpi.scale(75), dpi.scale(24), win.SWP_NOZORDER)
|
if d.okBtn != 0 {
|
||||||
} else {
|
win.SetWindowPos(d.okBtn, 0, dpi.scale(pos), dpi.scale(58), dpi.scale(75), dpi.scale(24), win.SWP_NOZORDER)
|
||||||
win.SetWindowPos(d.okBtn, 0, dpi.scale(12), dpi.scale(58), dpi.scale(75), dpi.scale(24), win.SWP_NOZORDER)
|
pos -= 83
|
||||||
win.SetWindowPos(d.extraBtn, 0, dpi.scale(95), dpi.scale(58), dpi.scale(75), dpi.scale(24), win.SWP_NOZORDER)
|
}
|
||||||
win.SetWindowPos(d.cancelBtn, 0, dpi.scale(178), dpi.scale(58), dpi.scale(75), dpi.scale(24), win.SWP_NOZORDER)
|
|
||||||
}
|
if pos == 178 {
|
||||||
|
win.SetWindowPos(d.wnd, 0, 0, 0, dpi.scale(281), dpi.scale(97), win.SWP_NOMOVE|win.SWP_NOZORDER)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,6 +86,7 @@ type options struct {
|
||||||
// Progress indication options
|
// Progress indication options
|
||||||
maxValue int
|
maxValue int
|
||||||
noCancel bool
|
noCancel bool
|
||||||
|
autoClose bool
|
||||||
timeRemaining bool
|
timeRemaining bool
|
||||||
|
|
||||||
// Context for timeout
|
// Context for timeout
|
||||||
|
|
Loading…
Reference in a new issue