Rework dialog icons.

This commit is contained in:
Nuno Cruces 2022-05-17 16:18:12 +01:00
parent 0b2f5d218d
commit 15547b2097
9 changed files with 57 additions and 49 deletions

View file

@ -401,27 +401,23 @@ func loadFlags() []zenity.Option {
opts = append(opts, zenity.DefaultCancel())
}
var ico zenity.DialogIcon
switch icon {
case unspecified:
ico = 0
case "error", "dialog-error":
ico = zenity.ErrorIcon
opts = append(opts, zenity.ErrorIcon)
case "info", "dialog-information":
ico = zenity.InfoIcon
opts = append(opts, zenity.InfoIcon)
case "question", "dialog-question":
ico = zenity.QuestionIcon
opts = append(opts, zenity.QuestionIcon)
case "important", "warning", "dialog-warning":
ico = zenity.WarningIcon
opts = append(opts, zenity.WarningIcon)
case "dialog-password":
ico = zenity.PasswordIcon
opts = append(opts, zenity.PasswordIcon)
case "":
ico = zenity.NoIcon
opts = append(opts, zenity.NoIcon)
case unspecified:
//
default:
opts = append(opts, zenity.CustomIcon(ingestPath(icon)))
}
if ico != 0 {
opts = append(opts, ico)
opts = append(opts, zenity.Icon(ingestPath(icon)))
}
// Message options

View file

@ -14,14 +14,15 @@ func entry(text string, opts options) (string, error) {
data.Options.Answer = &opts.entryText
data.Options.Hidden = opts.hideText
data.Options.Timeout = zenutil.Timeout
if opts.customIcon != "" {
_, err := os.Stat(opts.customIcon)
switch i := opts.icon.(type) {
case string:
_, err := os.Stat(i)
if err != nil {
return "", err
}
data.IconPath = opts.customIcon
} else {
data.Options.Icon = opts.icon.String()
data.IconPath = i
case DialogIcon:
data.Options.Icon = i.String()
}
data.SetButtons(getButtons(true, true, opts))

View file

@ -13,7 +13,7 @@ func message(kind messageKind, text string, opts options) error {
// dialog is more flexible, alert prettier
var dialog bool
if opts.icon != 0 || opts.customIcon != "" { // use if we want to show a specific icon
if opts.icon != nil { // use if we want to show a specific icon
dialog = true
} else if kind == questionKind && opts.cancelLabel == nil { // use for questions with default buttons
dialog = true
@ -22,14 +22,15 @@ func message(kind messageKind, text string, opts options) error {
if dialog {
data.Operation = "displayDialog"
data.Options.Title = opts.title
if opts.customIcon != "" {
_, err := os.Stat(opts.customIcon)
switch i := opts.icon.(type) {
case string:
_, err := os.Stat(i)
if err != nil {
return err
}
data.IconPath = opts.customIcon
} else {
data.Options.Icon = opts.icon.String()
data.IconPath = i
case DialogIcon:
data.Options.Icon = i.String()
}
} else {
data.Operation = "displayAlert"

View file

@ -40,10 +40,10 @@ func ExampleQuestion() {
// Output:
}
func ExampleCustomIcon() {
func ExampleIcon_custom() {
zenity.Info("All updates are complete.",
zenity.Title("Information"),
zenity.CustomIcon("testdata/icon.png"))
zenity.Icon("testdata/icon.png"))
// Output:
}

View file

@ -37,7 +37,7 @@ func message(kind messageKind, text string, opts options) error {
flags |= _MB_ICONWARNING
case InfoIcon:
flags |= _MB_ICONINFORMATION
case unspecifiedIcon:
case nil:
switch kind {
case errorKind:
flags |= _MB_ICONERROR
@ -60,7 +60,7 @@ func message(kind messageKind, text string, opts options) error {
defer setup()()
if opts.ctx != nil || opts.okLabel != nil || opts.cancelLabel != nil || opts.extraButton != nil || opts.customIcon != "" {
if opts.ctx != nil || opts.okLabel != nil || opts.cancelLabel != nil || opts.extraButton != nil || opts.icon != nil {
unhook, err := hookMessageDialog(kind, opts)
if err != nil {
return err
@ -114,13 +114,13 @@ func hookMessageDialogCallback(wnd uintptr, lparam *options) uintptr {
setWindowText.Call(wnd, strptr(*text))
}
if ctl == 20 /*IDC_STATIC_OK*/ && lparam.customIcon != "" {
if i, ok := lparam.icon.(string); ok && ctl == 20 /*IDC_STATIC_OK*/ {
var icon uintptr
data, _ := os.ReadFile(lparam.customIcon)
data, _ := os.ReadFile(i)
switch {
case bytes.HasPrefix(data, []byte("\x00\x00\x01\x00")):
icon, _, _ = loadImage.Call(0,
strptr(lparam.customIcon),
strptr(i),
1, /*IMAGE_ICON*/
0, 0,
0x00008050 /*LR_LOADFROMFILE|LR_DEFAULTSIZE|LR_SHARED*/)

View file

@ -18,14 +18,15 @@ func password(opts options) (string, string, error) {
data.Separator = zenutil.Separator
data.Options.Title = opts.title
data.Options.Timeout = zenutil.Timeout
if opts.customIcon != "" {
_, err := os.Stat(opts.customIcon)
switch i := opts.icon.(type) {
case string:
_, err := os.Stat(i)
if err != nil {
return "", "", err
}
data.IconPath = opts.customIcon
} else {
data.Options.Icon = opts.icon.String()
data.IconPath = i
case DialogIcon:
data.Options.Icon = i.String()
}
data.SetButtons(getButtons(true, true, opts))

View file

@ -42,8 +42,8 @@ func appendWidthHeight(args []string, opts options) []string {
}
func appendIcon(args []string, opts options) []string {
if opts.customIcon != "" {
args = append(args, "--window-icon", opts.customIcon)
if i, ok := opts.icon.(string); ok {
args = append(args, "--window-icon", i)
}
switch opts.icon {
case ErrorIcon:

View file

@ -18,6 +18,9 @@ import (
"github.com/ncruces/zenity/internal/zenutil"
)
// Remove after 1.18.
type any = interface{}
func stringPtr(s string) *string { return &s }
// ErrCanceled is returned when the cancel button is pressed,
@ -38,9 +41,8 @@ type options struct {
okLabel *string
cancelLabel *string
extraButton *string
icon DialogIcon
customIcon string
defaultCancel bool
icon any
// Message options
noWrap bool
@ -139,14 +141,12 @@ func DefaultCancel() Option {
type DialogIcon int
func (i DialogIcon) apply(o *options) {
o.customIcon = ""
o.icon = i
}
// The stock dialog icons.
const (
unspecifiedIcon DialogIcon = iota
ErrorIcon
ErrorIcon DialogIcon = iota
WarningIcon
InfoIcon
QuestionIcon
@ -156,15 +156,23 @@ const (
// Icon returns an Option to set the dialog icon.
//
// Tip: use DialogIcon directly.
func Icon(icon DialogIcon) Option { return icon }
// 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) {
case string:
case DialogIcon:
default:
panic("interface conversion: expected string or DialogIcon")
}
return funcOption(func(o *options) { o.icon = icon })
}
// CustomIcon returns an Option to set a custom dialog icon, loaded from a file.
//
// Deprecated: use Icon instead.
func CustomIcon(path string) Option {
return funcOption(func(o *options) {
o.icon = unspecifiedIcon
o.customIcon = path
})
return Icon(path)
}
// Context returns an Option to set a Context that can dismiss the dialog.

View file

@ -24,6 +24,7 @@ func Test_applyOptions(t *testing.T) {
{name: "ExtraButton", args: ExtraButton("Extra"), want: options{extraButton: stringPtr("Extra")}},
{name: "DefaultCancel", args: DefaultCancel(), want: options{defaultCancel: true}},
{name: "Icon", args: Icon(ErrorIcon), want: options{icon: ErrorIcon}},
{name: "Icon", args: Icon("error"), want: options{icon: "error"}},
// Message options
{name: "NoWrap", args: NoWrap(), want: options{noWrap: true}},