diff --git a/ui/app/app.go b/ui/app/app.go index 26331a82..c1862d6e 100644 --- a/ui/app/app.go +++ b/ui/app/app.go @@ -69,7 +69,7 @@ type windowRendezvous struct { type windowAndOptions struct { window *Window - opts *WindowOptions + opts *windowOptions } const ( diff --git a/ui/app/os_android.go b/ui/app/os_android.go index 78fed504..18931386 100644 --- a/ui/app/os_android.go +++ b/ui/app/os_android.go @@ -422,7 +422,7 @@ func (w *window) showTextInput(show bool) { func main() { } -func createWindow(window *Window, opts *WindowOptions) error { +func createWindow(window *Window, opts *windowOptions) error { mainWindow.in <- windowAndOptions{window, opts} return <-mainWindow.errs } diff --git a/ui/app/os_ios.go b/ui/app/os_ios.go index f77a8772..cd144818 100644 --- a/ui/app/os_ios.go +++ b/ui/app/os_ios.go @@ -246,7 +246,7 @@ func (w *window) showTextInput(show bool) { } } -func createWindow(win *Window, opts *WindowOptions) error { +func createWindow(win *Window, opts *windowOptions) error { mainWindow.in <- windowAndOptions{win, opts} return <-mainWindow.errs } diff --git a/ui/app/os_js.go b/ui/app/os_js.go index 1e956357..63a19389 100644 --- a/ui/app/os_js.go +++ b/ui/app/os_js.go @@ -31,7 +31,7 @@ type window struct { var mainDone = make(chan struct{}) -func createWindow(win *Window, opts *WindowOptions) error { +func createWindow(win *Window, opts *windowOptions) error { doc := js.Global().Get("document") cont := getContainer(doc) cnv := createCanvas(doc) diff --git a/ui/app/os_macos.go b/ui/app/os_macos.go index d2b6b79c..90f26625 100644 --- a/ui/app/os_macos.go +++ b/ui/app/os_macos.go @@ -266,7 +266,7 @@ func gio_onCreate(view C.CFTypeRef) { }) } -func createWindow(win *Window, opts *WindowOptions) error { +func createWindow(win *Window, opts *windowOptions) error { mainWindow.in <- windowAndOptions{win, opts} return <-mainWindow.errs } diff --git a/ui/app/os_wayland.go b/ui/app/os_wayland.go index 5be6d14d..29544591 100644 --- a/ui/app/os_wayland.go +++ b/ui/app/os_wayland.go @@ -156,7 +156,7 @@ func main() { <-mainDone } -func createWindow(window *Window, opts *WindowOptions) error { +func createWindow(window *Window, opts *windowOptions) error { connMu.Lock() defer connMu.Unlock() if len(winMap) > 0 { @@ -182,7 +182,7 @@ func createWindow(window *Window, opts *WindowOptions) error { return nil } -func createNativeWindow(opts *WindowOptions) (*window, error) { +func createNativeWindow(opts *windowOptions) (*window, error) { pipe := make([]int, 2) if err := syscall.Pipe2(pipe, syscall.O_NONBLOCK|syscall.O_CLOEXEC); err != nil { return nil, fmt.Errorf("createNativeWindow: failed to create pipe: %v", err) diff --git a/ui/app/os_windows.go b/ui/app/os_windows.go index 7091bb48..a71e3459 100644 --- a/ui/app/os_windows.go +++ b/ui/app/os_windows.go @@ -161,7 +161,7 @@ func main() { <-mainDone } -func createWindow(window *Window, opts *WindowOptions) error { +func createWindow(window *Window, opts *windowOptions) error { onceMu.Lock() defer onceMu.Unlock() if len(winMap) > 0 { @@ -191,7 +191,7 @@ func createWindow(window *Window, opts *WindowOptions) error { return <-cerr } -func createNativeWindow(opts *WindowOptions) (*window, error) { +func createNativeWindow(opts *windowOptions) (*window, error) { setProcessDPIAware() screenDC, err := getDC(0) if err != nil { diff --git a/ui/app/window.go b/ui/app/window.go index bd568113..a9534dc6 100644 --- a/ui/app/window.go +++ b/ui/app/window.go @@ -15,11 +15,12 @@ import ( "gioui.org/ui/system" ) -// WindowOptions specifies a set of window properties -// for creating new Windows. -type WindowOptions struct { - // Width and Height of the Window. Use the zero value - // to choose a default size. +// WindowOption configures a Window. +type WindowOption struct{ + apply func(opts *windowOptions) +} + +type windowOptions struct { Width, Height ui.Value Title string } @@ -83,20 +84,15 @@ var ackEvent input.Event // platform. // // BUG: Calling NewWindow more than once is not yet supported. -func NewWindow(opts *WindowOptions) *Window { - if opts == nil { - opts = &WindowOptions{ - Title: "Gio", - } +func NewWindow(options ...WindowOption) *Window { + opts := &windowOptions{ + Width: ui.Dp(800), + Height: ui.Dp(600), + Title: "Gio", } - if opts.Width.V < 0 || opts.Height.V < 0 { - panic("window width and height must be larger than or equal to 0") - } - if opts.Width.V == 0 { - opts.Width = ui.Dp(800) - } - if opts.Height.V == 0 { - opts.Height = ui.Dp(600) + + for _, o := range options { + o.apply(opts) } w := &Window{ @@ -224,7 +220,7 @@ func (w *Window) destroy(err error) { } } -func (w *Window) run(opts *WindowOptions) { +func (w *Window) run(opts *windowOptions) { defer close(w.in) defer close(w.out) if err := createWindow(w, opts); err != nil { @@ -332,4 +328,38 @@ func (q *Queue) Next(k input.Key) (input.Event, bool) { return q.q.Next(k) } + +// WithTitle returns an option that sets the window title. +func WithTitle(t string) WindowOption { + return WindowOption{ + apply: func(opts *windowOptions) { + opts.Title = t + }, + } +} + +// WithWidth returns an option that sets the window width. +func WithWidth(w ui.Value) WindowOption { + if w.V<= 0 { + panic("width must be larger than or equal to 0") + } + return WindowOption{ + apply: func(opts *windowOptions) { + opts.Width= w + }, + } +} + +// WithHeight returns an option that sets the window height. +func WithHeight(h ui.Value) WindowOption { + if h.V<= 0 { + panic("height must be larger than or equal to 0") + } + return WindowOption{ + apply: func(opts *windowOptions) { + opts.Height = h + }, + } +} + func (_ driverEvent) ImplementsEvent() {}