From 2359e42bb9b584011e147086e0fb52aa89341410 Mon Sep 17 00:00:00 2001 From: Nuno Cruces Date: Thu, 3 Aug 2023 12:55:59 +0100 Subject: [PATCH] Issue #62. --- cmd/zenity/main.go | 3 ++ cmd/zenity/progress.go | 10 +++--- internal/zenutil/progress_unix.go | 4 +++ internal/zenutil/run_darwin.go | 5 +-- internal/zenutil/run_unix.go | 3 +- internal/zenutil/run_unix_test.go | 2 +- progress.go | 5 +++ progress_darwin.go | 2 +- progress_unix.go | 5 ++- progress_windows.go | 60 +++++++++++++++++-------------- zenity.go | 1 + 11 files changed, 63 insertions(+), 37 deletions(-) diff --git a/cmd/zenity/main.go b/cmd/zenity/main.go index e8877a6..8b051c7 100644 --- a/cmd/zenity/main.go +++ b/cmd/zenity/main.go @@ -609,6 +609,9 @@ func loadFlags() []zenity.Option { if noCancel { opts = append(opts, zenity.NoCancel()) } + if autoClose { + opts = append(opts, zenity.AutoClose()) + } if timeRemaining { opts = append(opts, zenity.TimeRemaining()) } diff --git a/cmd/zenity/progress.go b/cmd/zenity/progress.go index a2f2d59..932387f 100644 --- a/cmd/zenity/progress.go +++ b/cmd/zenity/progress.go @@ -14,6 +14,9 @@ import ( ) func progress(opts ...zenity.Option) (err error) { + const scale = 16777216 + + opts = append(opts, zenity.MaxValue(scale*100)) dlg, err := zenity.Progress(opts...) if err != nil { return err @@ -30,7 +33,7 @@ func progress(opts ...zenity.Option) (err error) { if err := dlg.Text(text); err != nil { 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 } @@ -54,12 +57,9 @@ func progress(opts ...zenity.Option) (err error) { return err } } 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 } - if v >= 100 && autoClose { - return dlg.Close() - } } continue case <-dlg.Done(): diff --git a/internal/zenutil/progress_unix.go b/internal/zenutil/progress_unix.go index 2d41486..c77f3f0 100644 --- a/internal/zenutil/progress_unix.go +++ b/internal/zenutil/progress_unix.go @@ -20,6 +20,7 @@ type progressDialog struct { ctx context.Context cmd *exec.Cmd max int + close bool percent bool closed int32 lines chan string @@ -41,6 +42,9 @@ func (d *progressDialog) Text(text string) error { } func (d *progressDialog) Value(value int) error { + if value >= d.max && d.close { + return d.Close() + } if d.percent { return d.send(strconv.FormatFloat(100*float64(value)/float64(d.max), 'f', -1, 64)) } else { diff --git a/internal/zenutil/run_darwin.go b/internal/zenutil/run_darwin.go index 65ad218..283d5ef 100644 --- a/internal/zenutil/run_darwin.go +++ b/internal/zenutil/run_darwin.go @@ -46,7 +46,7 @@ func Run(ctx context.Context, script string, data any) ([]byte, error) { } // 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 err = scripts.ExecuteTemplate(&buf, "progress", data) if err != nil { @@ -108,10 +108,11 @@ func RunProgress(ctx context.Context, max int, data Progress) (dlg *progressDial return nil, err } - dlg = &progressDialog{ + dlg := &progressDialog{ ctx: ctx, cmd: cmd, max: max, + close: close, lines: make(chan string), done: make(chan struct{}), } diff --git a/internal/zenutil/run_unix.go b/internal/zenutil/run_unix.go index df22935..f72c089 100644 --- a/internal/zenutil/run_unix.go +++ b/internal/zenutil/run_unix.go @@ -54,7 +54,7 @@ func Run(ctx context.Context, args []string) ([]byte, error) { } // 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) if Command && path != "" { if Timeout > 0 { @@ -85,6 +85,7 @@ func RunProgress(ctx context.Context, max int, extra *string, args []string) (*p cmd: cmd, max: max, percent: true, + close: close, lines: make(chan string), done: make(chan struct{}), } diff --git a/internal/zenutil/run_unix_test.go b/internal/zenutil/run_unix_test.go index fa2edc9..7bf8904 100644 --- a/internal/zenutil/run_unix_test.go +++ b/internal/zenutil/run_unix_test.go @@ -31,7 +31,7 @@ func TestRun_context(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 { t.Skip("skipping:", err) } diff --git a/progress.go b/progress.go index cfb5cc7..06a393f 100644 --- a/progress.go +++ b/progress.go @@ -47,6 +47,11 @@ func NoCancel() Option { 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). func TimeRemaining() Option { return funcOption(func(o *options) { o.timeRemaining = true }) diff --git a/progress_darwin.go b/progress_darwin.go index 0c16700..9e1e3ec 100644 --- a/progress_darwin.go +++ b/progress_darwin.go @@ -23,5 +23,5 @@ func progress(opts options) (ProgressDialog, error) { data.WindowIcon = i } - return zenutil.RunProgress(opts.ctx, opts.maxValue, data) + return zenutil.RunProgress(opts.ctx, opts.maxValue, opts.autoClose, data) } diff --git a/progress_unix.go b/progress_unix.go index 7c9f74f..74c31ee 100644 --- a/progress_unix.go +++ b/progress_unix.go @@ -19,8 +19,11 @@ func progress(opts options) (ProgressDialog, error) { if opts.noCancel { args = append(args, "--no-cancel") } + if opts.autoClose { + args = append(args, "--auto-close") + } if opts.timeRemaining { 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) } diff --git a/progress_windows.go b/progress_windows.go index 3e967d3..c9d3fa1 100644 --- a/progress_windows.go +++ b/progress_windows.go @@ -29,8 +29,9 @@ func progress(opts options) (ProgressDialog, error) { } dlg := &progressDialog{ - done: make(chan struct{}), - max: opts.maxValue, + done: make(chan struct{}), + max: opts.maxValue, + close: opts.autoClose, } dlg.init.Add(1) @@ -44,10 +45,11 @@ func progress(opts options) (ProgressDialog, error) { } type progressDialog struct { - init sync.WaitGroup - done chan struct{} - max int - err error + init sync.WaitGroup + done chan struct{} + err error + max int + close bool wnd win.HWND textCtl win.HWND @@ -69,6 +71,9 @@ func (d *progressDialog) Text(text string) error { } func (d *progressDialog) Value(value int) error { + if value >= d.max && d.close { + return d.Close() + } select { default: win.SendMessage(d.progCtl, win.PBM_SETPOS, uintptr(value), 0) @@ -156,10 +161,12 @@ func (dlg *progressDialog) setup(opts options) error { nil, flags, 12, 30, 241, 16, dlg.wnd, 0, instance, nil) - dlg.okBtn, _ = win.CreateWindowEx(0, - strptr("BUTTON"), strptr(quoteAccelerators(*opts.okLabel)), - _WS_ZEN_BUTTON|win.BS_DEFPUSHBUTTON|win.WS_DISABLED, - 12, 58, 75, 24, dlg.wnd, win.IDOK, instance, nil) + if !opts.noCancel || !opts.autoClose { + dlg.okBtn, _ = win.CreateWindowEx(0, + strptr("BUTTON"), strptr(quoteAccelerators(*opts.okLabel)), + _WS_ZEN_BUTTON|win.BS_DEFPUSHBUTTON|win.WS_DISABLED, + 12, 58, 75, 24, dlg.wnd, win.IDOK, instance, nil) + } if !opts.noCancel { dlg.cancelBtn, _ = win.CreateWindowEx(0, 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.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) - if d.extraBtn == 0 { - if d.cancelBtn == 0 { - win.SetWindowPos(d.okBtn, 0, dpi.scale(178), dpi.scale(58), dpi.scale(75), dpi.scale(24), win.SWP_NOZORDER) - } else { - win.SetWindowPos(d.okBtn, 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) - } - } else { - if d.cancelBtn == 0 { - 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) - } else { - win.SetWindowPos(d.okBtn, 0, dpi.scale(12), dpi.scale(58), dpi.scale(75), dpi.scale(24), win.SWP_NOZORDER) - 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) - } + + pos := 178 + if d.cancelBtn != 0 { + win.SetWindowPos(d.cancelBtn, 0, dpi.scale(pos), dpi.scale(58), dpi.scale(75), dpi.scale(24), win.SWP_NOZORDER) + pos -= 83 + } + if d.extraBtn != 0 { + win.SetWindowPos(d.extraBtn, 0, dpi.scale(pos), dpi.scale(58), dpi.scale(75), dpi.scale(24), win.SWP_NOZORDER) + pos -= 83 + } + if d.okBtn != 0 { + win.SetWindowPos(d.okBtn, 0, dpi.scale(pos), dpi.scale(58), dpi.scale(75), dpi.scale(24), win.SWP_NOZORDER) + pos -= 83 + } + + if pos == 178 { + win.SetWindowPos(d.wnd, 0, 0, 0, dpi.scale(281), dpi.scale(97), win.SWP_NOMOVE|win.SWP_NOZORDER) } } diff --git a/zenity.go b/zenity.go index 6ab618e..3acc873 100644 --- a/zenity.go +++ b/zenity.go @@ -86,6 +86,7 @@ type options struct { // Progress indication options maxValue int noCancel bool + autoClose bool timeRemaining bool // Context for timeout