2020-01-23 06:44:28 -05:00
|
|
|
// Package zenity provides cross-platform access to simple dialogs that interact
|
|
|
|
// graphically with the user.
|
|
|
|
//
|
|
|
|
// It is inspired by, and closely follows the API of, the zenity program, which
|
|
|
|
// it uses to provide the functionality on various Unixes. See:
|
|
|
|
//
|
2020-01-26 11:04:49 -05:00
|
|
|
// https://help.gnome.org/users/zenity/stable/
|
2020-01-23 06:44:28 -05:00
|
|
|
//
|
|
|
|
// This package does not require cgo, and it does not impose any threading or
|
|
|
|
// initialization requirements.
|
2020-01-04 22:21:39 -05:00
|
|
|
package zenity
|
|
|
|
|
2020-01-28 07:46:43 -05:00
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"image/color"
|
2022-06-04 08:09:58 -04:00
|
|
|
"reflect"
|
|
|
|
"runtime"
|
2022-03-28 15:22:39 -04:00
|
|
|
"time"
|
2021-04-30 14:05:49 -04:00
|
|
|
|
|
|
|
"github.com/ncruces/zenity/internal/zenutil"
|
2020-01-28 07:46:43 -05:00
|
|
|
)
|
2020-01-18 07:40:16 -05:00
|
|
|
|
2022-05-17 11:18:12 -04:00
|
|
|
// Remove after 1.18.
|
|
|
|
type any = interface{}
|
|
|
|
|
2021-03-03 21:52:05 -05:00
|
|
|
func stringPtr(s string) *string { return &s }
|
2020-01-06 07:01:51 -05:00
|
|
|
|
2021-04-29 11:05:28 -04:00
|
|
|
// ErrCanceled is returned when the cancel button is pressed,
|
|
|
|
// or window functions are used to close the dialog.
|
2021-04-30 14:19:14 -04:00
|
|
|
const ErrCanceled = zenutil.ErrCanceled
|
2021-04-29 11:05:28 -04:00
|
|
|
|
|
|
|
// ErrExtraButton is returned when the extra button is pressed.
|
2021-04-30 14:19:14 -04:00
|
|
|
const ErrExtraButton = zenutil.ErrExtraButton
|
2021-04-29 11:05:28 -04:00
|
|
|
|
|
|
|
// ErrUnsupported is returned when a combination of options is not supported.
|
2021-04-30 14:19:14 -04:00
|
|
|
const ErrUnsupported = zenutil.ErrUnsupported
|
2021-04-30 14:05:49 -04:00
|
|
|
|
2020-01-04 22:21:39 -05:00
|
|
|
type options struct {
|
|
|
|
// General options
|
2021-05-11 09:51:56 -04:00
|
|
|
title *string
|
|
|
|
width uint
|
|
|
|
height uint
|
|
|
|
okLabel *string
|
|
|
|
cancelLabel *string
|
|
|
|
extraButton *string
|
|
|
|
defaultCancel bool
|
2022-05-17 11:18:12 -04:00
|
|
|
icon any
|
2022-05-18 09:48:09 -04:00
|
|
|
windowIcon any
|
2022-06-02 07:24:24 -04:00
|
|
|
attach any
|
|
|
|
modal bool
|
2021-05-11 09:51:56 -04:00
|
|
|
|
|
|
|
// Message options
|
|
|
|
noWrap bool
|
|
|
|
ellipsize bool
|
2021-03-05 10:14:30 -05:00
|
|
|
|
|
|
|
// Entry options
|
|
|
|
entryText string
|
|
|
|
hideText bool
|
2021-03-05 21:07:00 -05:00
|
|
|
username bool
|
2021-03-05 10:14:30 -05:00
|
|
|
|
2021-04-07 09:16:35 -04:00
|
|
|
// List options
|
|
|
|
disallowEmpty bool
|
|
|
|
defaultItems []string
|
|
|
|
|
2021-04-11 22:02:21 -04:00
|
|
|
// Calendar options
|
2022-03-28 22:05:46 -04:00
|
|
|
time *time.Time
|
2021-04-11 22:02:21 -04:00
|
|
|
|
2020-01-04 22:21:39 -05:00
|
|
|
// File selection options
|
2020-01-24 07:52:45 -05:00
|
|
|
directory bool
|
|
|
|
confirmOverwrite bool
|
|
|
|
confirmCreate bool
|
|
|
|
showHidden bool
|
2021-03-05 10:14:30 -05:00
|
|
|
filename string
|
2021-04-11 22:59:08 -04:00
|
|
|
fileFilters FileFilters
|
2020-01-04 22:21:39 -05:00
|
|
|
|
2020-01-18 07:40:16 -05:00
|
|
|
// Color selection options
|
2020-01-24 07:52:45 -05:00
|
|
|
color color.Color
|
|
|
|
showPalette bool
|
2020-01-18 07:40:16 -05:00
|
|
|
|
2021-04-25 13:34:56 -04:00
|
|
|
// Progress indication options
|
|
|
|
maxValue int
|
|
|
|
noCancel bool
|
|
|
|
timeRemaining bool
|
|
|
|
|
2020-01-28 07:46:43 -05:00
|
|
|
// Context for timeout
|
|
|
|
ctx context.Context
|
2020-01-04 22:21:39 -05:00
|
|
|
}
|
|
|
|
|
2020-01-23 06:44:28 -05:00
|
|
|
// An Option is an argument passed to dialog functions to customize their
|
|
|
|
// behavior.
|
2020-01-24 07:52:45 -05:00
|
|
|
type Option interface {
|
|
|
|
apply(*options)
|
|
|
|
}
|
|
|
|
|
|
|
|
type funcOption func(*options)
|
|
|
|
|
|
|
|
func (f funcOption) apply(o *options) { f(o) }
|
2020-01-04 22:21:39 -05:00
|
|
|
|
2020-01-24 07:52:45 -05:00
|
|
|
func applyOptions(options []Option) (res options) {
|
2020-01-04 22:21:39 -05:00
|
|
|
for _, o := range options {
|
2020-01-24 07:52:45 -05:00
|
|
|
o.apply(&res)
|
2020-01-04 22:21:39 -05:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-01-23 06:44:28 -05:00
|
|
|
// Title returns an Option to set the dialog title.
|
2020-01-04 22:21:39 -05:00
|
|
|
func Title(title string) Option {
|
2021-03-03 21:52:05 -05:00
|
|
|
return funcOption(func(o *options) { o.title = &title })
|
2020-01-04 22:21:39 -05:00
|
|
|
}
|
2020-01-27 10:42:43 -05:00
|
|
|
|
2021-02-12 09:24:13 -05:00
|
|
|
// Width returns an Option to set the dialog width (Unix only).
|
|
|
|
func Width(width uint) Option {
|
|
|
|
return funcOption(func(o *options) {
|
|
|
|
o.width = width
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Height returns an Option to set the dialog height (Unix only).
|
|
|
|
func Height(height uint) Option {
|
|
|
|
return funcOption(func(o *options) {
|
|
|
|
o.height = height
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-03-05 10:14:30 -05:00
|
|
|
// OKLabel returns an Option to set the label of the OK button.
|
|
|
|
func OKLabel(ok string) Option {
|
|
|
|
return funcOption(func(o *options) { o.okLabel = &ok })
|
|
|
|
}
|
|
|
|
|
|
|
|
// CancelLabel returns an Option to set the label of the Cancel button.
|
|
|
|
func CancelLabel(cancel string) Option {
|
|
|
|
return funcOption(func(o *options) { o.cancelLabel = &cancel })
|
|
|
|
}
|
|
|
|
|
2022-05-02 06:22:53 -04:00
|
|
|
// ExtraButton returns an Option to add one extra button.
|
2021-03-05 10:14:30 -05:00
|
|
|
func ExtraButton(extra string) Option {
|
|
|
|
return funcOption(func(o *options) { o.extraButton = &extra })
|
|
|
|
}
|
|
|
|
|
2022-05-17 10:36:00 -04:00
|
|
|
// DefaultCancel returns an Option to give the Cancel button focus by default.
|
|
|
|
func DefaultCancel() Option {
|
|
|
|
return funcOption(func(o *options) { o.defaultCancel = true })
|
|
|
|
}
|
|
|
|
|
2022-05-04 18:22:19 -04:00
|
|
|
// DialogIcon is an Option that sets the dialog icon.
|
2020-01-27 10:42:43 -05:00
|
|
|
type DialogIcon int
|
|
|
|
|
2022-05-05 08:04:27 -04:00
|
|
|
func (i DialogIcon) apply(o *options) {
|
|
|
|
o.icon = i
|
|
|
|
}
|
2021-05-11 09:58:04 -04:00
|
|
|
|
2020-01-30 09:14:42 -05:00
|
|
|
// The stock dialog icons.
|
2020-01-27 10:42:43 -05:00
|
|
|
const (
|
2022-05-17 11:18:12 -04:00
|
|
|
ErrorIcon DialogIcon = iota
|
2020-01-27 10:42:43 -05:00
|
|
|
WarningIcon
|
|
|
|
InfoIcon
|
|
|
|
QuestionIcon
|
2021-03-05 10:14:30 -05:00
|
|
|
PasswordIcon
|
2021-03-04 08:06:49 -05:00
|
|
|
NoIcon
|
2020-01-27 10:42:43 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
// Icon returns an Option to set the dialog icon.
|
2022-05-04 18:22:19 -04:00
|
|
|
//
|
2022-05-17 11:18:12 -04:00
|
|
|
// Icon accepts a DialogIcon, or a string.
|
|
|
|
// The string can be a GTK icon name (Unix), or a path (Windows and macOS).
|
|
|
|
func Icon(icon any) Option {
|
|
|
|
switch icon.(type) {
|
2022-06-04 08:09:58 -04:00
|
|
|
case DialogIcon, string:
|
2022-05-17 11:18:12 -04:00
|
|
|
default:
|
|
|
|
panic("interface conversion: expected string or DialogIcon")
|
|
|
|
}
|
|
|
|
return funcOption(func(o *options) { o.icon = icon })
|
|
|
|
}
|
2020-01-28 07:46:43 -05:00
|
|
|
|
2022-06-02 07:24:24 -04:00
|
|
|
// WindowIcon returns an Option to set the window icon.
|
2022-05-18 09:48:09 -04:00
|
|
|
//
|
|
|
|
// WindowIcon accepts a DialogIcon, or a string path.
|
|
|
|
func WindowIcon(icon any) Option {
|
|
|
|
switch icon.(type) {
|
2022-06-04 08:09:58 -04:00
|
|
|
case DialogIcon, string:
|
2022-05-18 09:48:09 -04:00
|
|
|
default:
|
|
|
|
panic("interface conversion: expected string or DialogIcon")
|
|
|
|
}
|
|
|
|
return funcOption(func(o *options) { o.windowIcon = icon })
|
|
|
|
}
|
|
|
|
|
2022-06-02 07:24:24 -04:00
|
|
|
// CustomIcon returns an Option to set a custom dialog icon.
|
2022-05-17 11:18:12 -04:00
|
|
|
//
|
|
|
|
// Deprecated: use Icon instead.
|
2021-10-06 18:39:36 -04:00
|
|
|
func CustomIcon(path string) Option {
|
2022-05-17 11:18:12 -04:00
|
|
|
return Icon(path)
|
2021-10-06 18:39:36 -04:00
|
|
|
}
|
|
|
|
|
2022-06-02 07:24:24 -04:00
|
|
|
// Attach returns an Option to set the parent window to attach to.
|
2022-06-04 08:09:58 -04:00
|
|
|
//
|
|
|
|
// Attach accepts:
|
|
|
|
// - a window id (int) on Unix
|
|
|
|
// - a window handle (~uintptr) on Windows
|
|
|
|
// - an application name (string) or process id (int) on macOS
|
2022-06-02 07:24:24 -04:00
|
|
|
func Attach(id any) Option {
|
2022-06-04 08:09:58 -04:00
|
|
|
switch runtime.GOOS {
|
|
|
|
case "windows":
|
|
|
|
if v := reflect.ValueOf(id); v.Kind() == reflect.Uintptr {
|
|
|
|
id = uintptr(v.Uint())
|
|
|
|
} else {
|
|
|
|
panic("interface conversion: expected uintptr")
|
|
|
|
}
|
|
|
|
|
|
|
|
case "darwin":
|
|
|
|
switch id.(type) {
|
|
|
|
case int, string:
|
|
|
|
default:
|
|
|
|
panic("interface conversion: expected int or string")
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
if _, ok := id.(int); !ok {
|
|
|
|
panic("interface conversion: expected int")
|
|
|
|
}
|
|
|
|
}
|
2022-06-02 07:24:24 -04:00
|
|
|
return funcOption(func(o *options) { o.attach = id })
|
|
|
|
}
|
|
|
|
|
|
|
|
// Modal returns an Option to set the modal hint.
|
|
|
|
func Modal() Option {
|
|
|
|
return funcOption(func(o *options) { o.modal = true })
|
|
|
|
}
|
|
|
|
|
2020-01-29 09:15:21 -05:00
|
|
|
// Context returns an Option to set a Context that can dismiss the dialog.
|
2020-01-30 09:14:42 -05:00
|
|
|
//
|
2022-05-02 06:22:53 -04:00
|
|
|
// Dialogs dismissed by ctx return ctx.Err().
|
2020-01-28 07:46:43 -05:00
|
|
|
func Context(ctx context.Context) Option {
|
|
|
|
return funcOption(func(o *options) { o.ctx = ctx })
|
|
|
|
}
|