Rework dialog icons.
This commit is contained in:
parent
0b2f5d218d
commit
15547b2097
9 changed files with 57 additions and 49 deletions
|
@ -401,27 +401,23 @@ func loadFlags() []zenity.Option {
|
||||||
opts = append(opts, zenity.DefaultCancel())
|
opts = append(opts, zenity.DefaultCancel())
|
||||||
}
|
}
|
||||||
|
|
||||||
var ico zenity.DialogIcon
|
|
||||||
switch icon {
|
switch icon {
|
||||||
case unspecified:
|
|
||||||
ico = 0
|
|
||||||
case "error", "dialog-error":
|
case "error", "dialog-error":
|
||||||
ico = zenity.ErrorIcon
|
opts = append(opts, zenity.ErrorIcon)
|
||||||
case "info", "dialog-information":
|
case "info", "dialog-information":
|
||||||
ico = zenity.InfoIcon
|
opts = append(opts, zenity.InfoIcon)
|
||||||
case "question", "dialog-question":
|
case "question", "dialog-question":
|
||||||
ico = zenity.QuestionIcon
|
opts = append(opts, zenity.QuestionIcon)
|
||||||
case "important", "warning", "dialog-warning":
|
case "important", "warning", "dialog-warning":
|
||||||
ico = zenity.WarningIcon
|
opts = append(opts, zenity.WarningIcon)
|
||||||
case "dialog-password":
|
case "dialog-password":
|
||||||
ico = zenity.PasswordIcon
|
opts = append(opts, zenity.PasswordIcon)
|
||||||
case "":
|
case "":
|
||||||
ico = zenity.NoIcon
|
opts = append(opts, zenity.NoIcon)
|
||||||
|
case unspecified:
|
||||||
|
//
|
||||||
default:
|
default:
|
||||||
opts = append(opts, zenity.CustomIcon(ingestPath(icon)))
|
opts = append(opts, zenity.Icon(ingestPath(icon)))
|
||||||
}
|
|
||||||
if ico != 0 {
|
|
||||||
opts = append(opts, ico)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Message options
|
// Message options
|
||||||
|
|
|
@ -14,14 +14,15 @@ func entry(text string, opts options) (string, error) {
|
||||||
data.Options.Answer = &opts.entryText
|
data.Options.Answer = &opts.entryText
|
||||||
data.Options.Hidden = opts.hideText
|
data.Options.Hidden = opts.hideText
|
||||||
data.Options.Timeout = zenutil.Timeout
|
data.Options.Timeout = zenutil.Timeout
|
||||||
if opts.customIcon != "" {
|
switch i := opts.icon.(type) {
|
||||||
_, err := os.Stat(opts.customIcon)
|
case string:
|
||||||
|
_, err := os.Stat(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
data.IconPath = opts.customIcon
|
data.IconPath = i
|
||||||
} else {
|
case DialogIcon:
|
||||||
data.Options.Icon = opts.icon.String()
|
data.Options.Icon = i.String()
|
||||||
}
|
}
|
||||||
data.SetButtons(getButtons(true, true, opts))
|
data.SetButtons(getButtons(true, true, opts))
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ func message(kind messageKind, text string, opts options) error {
|
||||||
|
|
||||||
// dialog is more flexible, alert prettier
|
// dialog is more flexible, alert prettier
|
||||||
var dialog bool
|
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
|
dialog = true
|
||||||
} else if kind == questionKind && opts.cancelLabel == nil { // use for questions with default buttons
|
} else if kind == questionKind && opts.cancelLabel == nil { // use for questions with default buttons
|
||||||
dialog = true
|
dialog = true
|
||||||
|
@ -22,14 +22,15 @@ func message(kind messageKind, text string, opts options) error {
|
||||||
if dialog {
|
if dialog {
|
||||||
data.Operation = "displayDialog"
|
data.Operation = "displayDialog"
|
||||||
data.Options.Title = opts.title
|
data.Options.Title = opts.title
|
||||||
if opts.customIcon != "" {
|
switch i := opts.icon.(type) {
|
||||||
_, err := os.Stat(opts.customIcon)
|
case string:
|
||||||
|
_, err := os.Stat(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
data.IconPath = opts.customIcon
|
data.IconPath = i
|
||||||
} else {
|
case DialogIcon:
|
||||||
data.Options.Icon = opts.icon.String()
|
data.Options.Icon = i.String()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
data.Operation = "displayAlert"
|
data.Operation = "displayAlert"
|
||||||
|
|
|
@ -40,10 +40,10 @@ func ExampleQuestion() {
|
||||||
// Output:
|
// Output:
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleCustomIcon() {
|
func ExampleIcon_custom() {
|
||||||
zenity.Info("All updates are complete.",
|
zenity.Info("All updates are complete.",
|
||||||
zenity.Title("Information"),
|
zenity.Title("Information"),
|
||||||
zenity.CustomIcon("testdata/icon.png"))
|
zenity.Icon("testdata/icon.png"))
|
||||||
// Output:
|
// Output:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ func message(kind messageKind, text string, opts options) error {
|
||||||
flags |= _MB_ICONWARNING
|
flags |= _MB_ICONWARNING
|
||||||
case InfoIcon:
|
case InfoIcon:
|
||||||
flags |= _MB_ICONINFORMATION
|
flags |= _MB_ICONINFORMATION
|
||||||
case unspecifiedIcon:
|
case nil:
|
||||||
switch kind {
|
switch kind {
|
||||||
case errorKind:
|
case errorKind:
|
||||||
flags |= _MB_ICONERROR
|
flags |= _MB_ICONERROR
|
||||||
|
@ -60,7 +60,7 @@ func message(kind messageKind, text string, opts options) error {
|
||||||
|
|
||||||
defer setup()()
|
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)
|
unhook, err := hookMessageDialog(kind, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -114,13 +114,13 @@ func hookMessageDialogCallback(wnd uintptr, lparam *options) uintptr {
|
||||||
setWindowText.Call(wnd, strptr(*text))
|
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
|
var icon uintptr
|
||||||
data, _ := os.ReadFile(lparam.customIcon)
|
data, _ := os.ReadFile(i)
|
||||||
switch {
|
switch {
|
||||||
case bytes.HasPrefix(data, []byte("\x00\x00\x01\x00")):
|
case bytes.HasPrefix(data, []byte("\x00\x00\x01\x00")):
|
||||||
icon, _, _ = loadImage.Call(0,
|
icon, _, _ = loadImage.Call(0,
|
||||||
strptr(lparam.customIcon),
|
strptr(i),
|
||||||
1, /*IMAGE_ICON*/
|
1, /*IMAGE_ICON*/
|
||||||
0, 0,
|
0, 0,
|
||||||
0x00008050 /*LR_LOADFROMFILE|LR_DEFAULTSIZE|LR_SHARED*/)
|
0x00008050 /*LR_LOADFROMFILE|LR_DEFAULTSIZE|LR_SHARED*/)
|
||||||
|
|
|
@ -18,14 +18,15 @@ func password(opts options) (string, string, error) {
|
||||||
data.Separator = zenutil.Separator
|
data.Separator = zenutil.Separator
|
||||||
data.Options.Title = opts.title
|
data.Options.Title = opts.title
|
||||||
data.Options.Timeout = zenutil.Timeout
|
data.Options.Timeout = zenutil.Timeout
|
||||||
if opts.customIcon != "" {
|
switch i := opts.icon.(type) {
|
||||||
_, err := os.Stat(opts.customIcon)
|
case string:
|
||||||
|
_, err := os.Stat(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
data.IconPath = opts.customIcon
|
data.IconPath = i
|
||||||
} else {
|
case DialogIcon:
|
||||||
data.Options.Icon = opts.icon.String()
|
data.Options.Icon = i.String()
|
||||||
}
|
}
|
||||||
data.SetButtons(getButtons(true, true, opts))
|
data.SetButtons(getButtons(true, true, opts))
|
||||||
|
|
||||||
|
|
|
@ -42,8 +42,8 @@ func appendWidthHeight(args []string, opts options) []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func appendIcon(args []string, opts options) []string {
|
func appendIcon(args []string, opts options) []string {
|
||||||
if opts.customIcon != "" {
|
if i, ok := opts.icon.(string); ok {
|
||||||
args = append(args, "--window-icon", opts.customIcon)
|
args = append(args, "--window-icon", i)
|
||||||
}
|
}
|
||||||
switch opts.icon {
|
switch opts.icon {
|
||||||
case ErrorIcon:
|
case ErrorIcon:
|
||||||
|
|
30
zenity.go
30
zenity.go
|
@ -18,6 +18,9 @@ import (
|
||||||
"github.com/ncruces/zenity/internal/zenutil"
|
"github.com/ncruces/zenity/internal/zenutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Remove after 1.18.
|
||||||
|
type any = interface{}
|
||||||
|
|
||||||
func stringPtr(s string) *string { return &s }
|
func stringPtr(s string) *string { return &s }
|
||||||
|
|
||||||
// ErrCanceled is returned when the cancel button is pressed,
|
// ErrCanceled is returned when the cancel button is pressed,
|
||||||
|
@ -38,9 +41,8 @@ type options struct {
|
||||||
okLabel *string
|
okLabel *string
|
||||||
cancelLabel *string
|
cancelLabel *string
|
||||||
extraButton *string
|
extraButton *string
|
||||||
icon DialogIcon
|
|
||||||
customIcon string
|
|
||||||
defaultCancel bool
|
defaultCancel bool
|
||||||
|
icon any
|
||||||
|
|
||||||
// Message options
|
// Message options
|
||||||
noWrap bool
|
noWrap bool
|
||||||
|
@ -139,14 +141,12 @@ func DefaultCancel() Option {
|
||||||
type DialogIcon int
|
type DialogIcon int
|
||||||
|
|
||||||
func (i DialogIcon) apply(o *options) {
|
func (i DialogIcon) apply(o *options) {
|
||||||
o.customIcon = ""
|
|
||||||
o.icon = i
|
o.icon = i
|
||||||
}
|
}
|
||||||
|
|
||||||
// The stock dialog icons.
|
// The stock dialog icons.
|
||||||
const (
|
const (
|
||||||
unspecifiedIcon DialogIcon = iota
|
ErrorIcon DialogIcon = iota
|
||||||
ErrorIcon
|
|
||||||
WarningIcon
|
WarningIcon
|
||||||
InfoIcon
|
InfoIcon
|
||||||
QuestionIcon
|
QuestionIcon
|
||||||
|
@ -156,15 +156,23 @@ const (
|
||||||
|
|
||||||
// Icon returns an Option to set the dialog icon.
|
// Icon returns an Option to set the dialog icon.
|
||||||
//
|
//
|
||||||
// Tip: use DialogIcon directly.
|
// Icon accepts a DialogIcon, or a string.
|
||||||
func Icon(icon DialogIcon) Option { return icon }
|
// 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.
|
// CustomIcon returns an Option to set a custom dialog icon, loaded from a file.
|
||||||
|
//
|
||||||
|
// Deprecated: use Icon instead.
|
||||||
func CustomIcon(path string) Option {
|
func CustomIcon(path string) Option {
|
||||||
return funcOption(func(o *options) {
|
return Icon(path)
|
||||||
o.icon = unspecifiedIcon
|
|
||||||
o.customIcon = path
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Context returns an Option to set a Context that can dismiss the dialog.
|
// Context returns an Option to set a Context that can dismiss the dialog.
|
||||||
|
|
|
@ -24,6 +24,7 @@ func Test_applyOptions(t *testing.T) {
|
||||||
{name: "ExtraButton", args: ExtraButton("Extra"), want: options{extraButton: stringPtr("Extra")}},
|
{name: "ExtraButton", args: ExtraButton("Extra"), want: options{extraButton: stringPtr("Extra")}},
|
||||||
{name: "DefaultCancel", args: DefaultCancel(), want: options{defaultCancel: true}},
|
{name: "DefaultCancel", args: DefaultCancel(), want: options{defaultCancel: true}},
|
||||||
{name: "Icon", args: Icon(ErrorIcon), want: options{icon: ErrorIcon}},
|
{name: "Icon", args: Icon(ErrorIcon), want: options{icon: ErrorIcon}},
|
||||||
|
{name: "Icon", args: Icon("error"), want: options{icon: "error"}},
|
||||||
|
|
||||||
// Message options
|
// Message options
|
||||||
{name: "NoWrap", args: NoWrap(), want: options{noWrap: true}},
|
{name: "NoWrap", args: NoWrap(), want: options{noWrap: true}},
|
||||||
|
|
Loading…
Reference in a new issue