diff --git a/exp/examples/kitchensink/main.go b/exp/examples/kitchensink/main.go index fb35f9e31..a7138db78 100644 --- a/exp/examples/kitchensink/main.go +++ b/exp/examples/kitchensink/main.go @@ -109,12 +109,11 @@ func main() { mySystray.SetIconPosition(application.NSImageLeading) myWindow := app.NewWindowWithOptions(&options.Window{ - Title: "Kitchen Sink", - Width: 600, - Height: 400, - AlwaysOnTop: true, - DisableResize: false, - EnableDevTools: true, + Title: "Kitchen Sink", + Width: 600, + Height: 400, + AlwaysOnTop: true, + DisableResize: false, BackgroundColour: &options.RGBA{ Red: 255, Green: 255, @@ -207,9 +206,8 @@ func main() { myWindow2Lock.RLock() myWindow.SetTitle("Wooooo") myWindow.SetAlwaysOnTop(true) - myWindow2.EnableDevTools() myWindow2.SetTitle("OMFG") - myWindow2.NavigateToURL("https://wails.io") + myWindow2.SetURL("https://wails.io") myWindow.SetMinSize(600, 600) myWindow.SetMaxSize(650, 650) myWindow.Center() diff --git a/exp/examples/window/main.go b/exp/examples/window/main.go index cb0dea554..926a90d86 100644 --- a/exp/examples/window/main.go +++ b/exp/examples/window/main.go @@ -3,33 +3,54 @@ package main import ( _ "embed" "log" + "strconv" "github.com/wailsapp/wails/exp/pkg/options" - "github.com/wailsapp/wails/exp/pkg/events" - "github.com/wailsapp/wails/exp/pkg/application" ) func main() { app := application.New() + app.SetName("Window Demo") + app.SetDescription("A demo of the windowing capabilities") - // Create window - myWindow := app.NewWindowWithOptions(&options.Window{ - Title: "My Window", - Width: 800, - Height: 600, - URL: "https://wails.io", - EnableDevTools: true, - Mac: &options.MacWindow{ - Backdrop: options.MacBackdropTranslucent, - TitleBar: options.TitleBarHiddenInsetUnified, - }, + // Create a custom menu + menu := app.NewMenu() + menu.AddRole(application.AppMenu) + + windowCounter := 1 + + // Let's make a "Demo" menu + myMenu := menu.AddSubmenu("Window") + myMenu.Add("New Blank Window").OnClick(func(ctx *application.Context) { + app.NewWindow().SetTitle("Window " + strconv.Itoa(windowCounter)).Run() + windowCounter++ }) - myWindow.On(events.Mac.WindowDidBecomeMain, func() { - println("Window did become main") + myMenu.Add("New Window").OnClick(func(ctx *application.Context) { + app.NewWindow(). + SetTitle("Window " + strconv.Itoa(windowCounter)). + SetBackgroundColour(&options.RGBA{ + Red: 255, + Green: 0, + Blue: 0, + Alpha: 0, + }). + Run() + windowCounter++ + }) + myMenu.Add("New Webview").OnClick(func(ctx *application.Context) { + app.NewWindow(). + SetTitle("Webview " + strconv.Itoa(windowCounter)). + SetURL("https://wails.app"). + Run() + windowCounter++ }) + // Disabled menu item + myMenu.Add("Not Enabled").SetEnabled(false) + + app.SetMenu(menu) err := app.Run() if err != nil { diff --git a/exp/pkg/application/roles.go b/exp/pkg/application/roles.go index b6f2b2da9..e85844e24 100644 --- a/exp/pkg/application/roles.go +++ b/exp/pkg/application/roles.go @@ -140,7 +140,7 @@ func newWindowMenu() *MenuItem { func newHelpMenu() *MenuItem { menu := NewMenu() menu.Add("Learn More").OnClick(func(ctx *Context) { - globalApplication.CurrentWindow().NavigateToURL("https://wails.io") + globalApplication.CurrentWindow().SetURL("https://wails.io") }) subMenu := newSubMenuItem("Help") subMenu.submenu = menu diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index 2e90085e5..0eb9f9871 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -12,11 +12,10 @@ type windowImpl interface { setTitle(title string) setSize(width, height int) setAlwaysOnTop(alwaysOnTop bool) - navigateToURL(url string) + setURL(url string) setResizable(resizable bool) setMinSize(width, height int) setMaxSize(width, height int) - enableDevTools() execJS(js string) setMaximised() setMinimised() @@ -25,7 +24,7 @@ type windowImpl interface { isMaximised() bool isFullscreen() bool restore() - setBackgroundColor(color *options.RGBA) + setBackgroundColour(color *options.RGBA) run() center() size() (int, int) @@ -43,7 +42,7 @@ type windowImpl interface { close() zoom() minimize() - renderHTML(html string) + setHTML(html string) } type Window struct { @@ -80,97 +79,93 @@ func NewWindow(options *options.Window) *Window { } } -func (w *Window) SetTitle(title string) { +func (w *Window) SetTitle(title string) *Window { w.implLock.RLock() defer w.implLock.RUnlock() - if w.impl == nil { - w.options.Title = title - return + w.options.Title = title + if w.impl != nil { + w.impl.setTitle(title) } - w.impl.setTitle(title) + return w } -func (w *Window) SetSize(width, height int) { - if w.impl == nil { - w.options.Width = width - w.options.Height = height - return +func (w *Window) SetSize(width, height int) *Window { + w.options.Width = width + w.options.Height = height + if w.impl != nil { + w.impl.setSize(width, height) } - w.impl.setSize(width, height) + return w } func (w *Window) Run() { + if w.impl != nil { + return + } w.implLock.Lock() w.impl = newWindowImpl(w) w.implLock.Unlock() w.impl.run() } -func (w *Window) SetAlwaysOnTop(b bool) { +func (w *Window) SetAlwaysOnTop(b bool) *Window { + w.options.AlwaysOnTop = b if w.impl == nil { - w.options.AlwaysOnTop = b - return + w.impl.setAlwaysOnTop(b) } - w.impl.setAlwaysOnTop(b) + return w } -func (w *Window) NavigateToURL(s string) { - if w.impl == nil { - w.options.URL = s - return +func (w *Window) SetURL(s string) *Window { + w.options.URL = s + if w.impl != nil { + w.impl.setURL(s) } - w.impl.navigateToURL(s) + return w } -func (w *Window) SetResizable(b bool) { +func (w *Window) SetResizable(b bool) *Window { w.options.DisableResize = !b - if w.impl == nil { - return + if w.impl != nil { + w.impl.setResizable(b) } - w.impl.setResizable(b) + return w } func (w *Window) Resizable() bool { return !w.options.DisableResize } -func (w *Window) SetMinSize(minWidth, minHeight int) { - if w.impl == nil { - w.options.MinWidth = minWidth - if w.options.Width < minWidth { - w.options.Width = minWidth - } - w.options.MinHeight = minHeight - if w.options.Height < minHeight { - w.options.Height = minHeight - } - return +func (w *Window) SetMinSize(minWidth, minHeight int) *Window { + w.options.MinWidth = minWidth + if w.options.Width < minWidth { + w.options.Width = minWidth } - w.impl.setSize(w.options.Width, w.options.Height) - w.impl.setMinSize(minWidth, minHeight) -} -func (w *Window) SetMaxSize(maxWidth, maxHeight int) { - if w.impl == nil { - w.options.MinWidth = maxWidth - if w.options.Width > maxWidth { - w.options.Width = maxWidth - } - w.options.MinHeight = maxHeight - if w.options.Height > maxHeight { - w.options.Height = maxHeight - } - return + w.options.MinHeight = minHeight + if w.options.Height < minHeight { + w.options.Height = minHeight } - w.impl.setSize(w.options.Width, w.options.Height) - w.impl.setMaxSize(maxWidth, maxHeight) + if w.impl != nil { + w.impl.setSize(w.options.Width, w.options.Height) + w.impl.setMinSize(minWidth, minHeight) + } + return w } -func (w *Window) EnableDevTools() { - if w.impl == nil { - w.options.EnableDevTools = true - return +func (w *Window) SetMaxSize(maxWidth, maxHeight int) *Window { + w.options.MinWidth = maxWidth + if w.options.Width > maxWidth { + w.options.Width = maxWidth } - w.impl.enableDevTools() + w.options.MinHeight = maxHeight + if w.options.Height > maxHeight { + w.options.Height = maxHeight + } + if w.impl != nil { + w.impl.setSize(w.options.Width, w.options.Height) + w.impl.setMaxSize(maxWidth, maxHeight) + } + return w } func (w *Window) ExecJS(js string) { @@ -180,30 +175,29 @@ func (w *Window) ExecJS(js string) { w.impl.execJS(js) } -func (w *Window) SetMaximized() { +func (w *Window) SetMaximized() *Window { w.options.StartState = options.WindowStateMaximised - if w.impl == nil { - return + if w.impl != nil { + w.impl.setMaximised() } - w.impl.setMaximised() + return w } // Set Minimized -func (w *Window) SetMinimized() { +func (w *Window) SetMinimized() *Window { w.options.StartState = options.WindowStateMinimised if w.impl == nil { - return + w.impl.setMinimised() } - w.impl.setMinimised() + return w } -// Set Fullscreen -func (w *Window) SetFullscreen() { +func (w *Window) SetFullscreen() *Window { w.options.StartState = options.WindowStateFullscreen if w.impl == nil { - return + w.impl.setFullscreen() } - w.impl.setFullscreen() + return w } // IsMinimised returns true if the window is minimised @@ -240,12 +234,12 @@ func (w *Window) IsFullscreen() bool { return w.impl.isFullscreen() } -func (w *Window) SetBackgroundColor(color *options.RGBA) { - w.options.BackgroundColour = color - if w.impl == nil { - return +func (w *Window) SetBackgroundColour(colour *options.RGBA) *Window { + w.options.BackgroundColour = colour + if w.impl != nil { + w.impl.setBackgroundColour(colour) } - w.impl.setBackgroundColor(color) + return w } func (w *Window) handleMessage(message string) { @@ -278,10 +272,6 @@ func (w *Window) handleWindowEvent(id uint) { w.eventListenersLock.RUnlock() } -func (w *Window) ID() uint { - return w.id -} - func (w *Window) Width() int { if w.impl == nil { return 0 @@ -340,11 +330,12 @@ func (w *Window) ToggleDevTools() { w.impl.toggleDevTools() } -func (w *Window) ResetZoom() { - if w.impl == nil { - return +func (w *Window) ResetZoom() *Window { + if w.impl != nil { + w.impl.resetZoom() } - w.impl.resetZoom() + return w + } func (w *Window) ZoomIn() { @@ -382,9 +373,10 @@ func (w *Window) Zoom() { w.impl.zoom() } -func (w *Window) RenderHTML(html string) { - if w.impl == nil { - return +func (w *Window) SetHTML(html string) *Window { + w.options.HTML = html + if w.impl != nil { + w.impl.setHTML(html) } - w.impl.renderHTML(html) + return w } diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index f4471eac4..d4704b1cf 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -301,8 +301,8 @@ void webviewSetTransparent(void* nsWindow) { }); } -// Set webview background color -void webviewSetBackgroundColor(void* nsWindow, int r, int g, int b, int alpha) { +// Set webview background colour +void webviewSetBackgroundColour(void* nsWindow, int r, int g, int b, int alpha) { // Set webview background color on main thread dispatch_async(dispatch_get_main_queue(), ^{ // Get window delegate @@ -312,6 +312,17 @@ void webviewSetBackgroundColor(void* nsWindow, int r, int g, int b, int alpha) { }); } +// Set the window background colour +void windowSetBackgroundColour(void* nsWindow, int r, int g, int b, int alpha) { + // Set window background color on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + // Get window + NSWindow* window = (NSWindow*)nsWindow; + // Set window background color + [window setBackgroundColor:[NSColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:alpha/255.0]]; + }); +} + // Set Window maximised void windowSetMaximised(void* nsWindow) { // Set window maximized on main thread @@ -746,7 +757,7 @@ func (w *macosWindow) execJS(js string) { C.windowExecJS(w.nsWindow, C.CString(js)) } -func (w *macosWindow) navigateToURL(url string) { +func (w *macosWindow) setURL(url string) { C.navigationLoadURL(w.nsWindow, C.CString(url)) } @@ -831,10 +842,8 @@ func (w *macosWindow) run() { if w.parent.options.MaxWidth != 0 || w.parent.options.MaxHeight != 0 { w.setMaxSize(w.parent.options.MaxWidth, w.parent.options.MaxHeight) } - if w.parent.options.EnableDevTools { - w.enableDevTools() - } - w.setBackgroundColor(w.parent.options.BackgroundColour) + w.enableDevTools() + w.setBackgroundColour(w.parent.options.BackgroundColour) if w.parent.options.Mac != nil { macOptions := w.parent.options.Mac switch macOptions.Backdrop { @@ -879,7 +888,7 @@ func (w *macosWindow) run() { C.windowCenter(w.nsWindow) if w.parent.options.URL != "" { - w.navigateToURL(w.parent.options.URL) + w.setURL(w.parent.options.URL) } // We need to wait for the HTML to load before we can execute the javascript w.parent.On(events.Mac.WebViewDidFinishNavigation, func() { @@ -891,18 +900,18 @@ func (w *macosWindow) run() { } }) if w.parent.options.HTML != "" { - w.renderHTML(w.parent.options.HTML) + w.setHTML(w.parent.options.HTML) } C.windowShow(w.nsWindow) }) } -func (w *macosWindow) setBackgroundColor(colour *options.RGBA) { +func (w *macosWindow) setBackgroundColour(colour *options.RGBA) { if colour == nil { return } - C.webviewSetBackgroundColor(w.nsWindow, C.int(colour.Red), C.int(colour.Green), C.int(colour.Blue), C.int(colour.Alpha)) + C.windowSetBackgroundColour(w.nsWindow, C.int(colour.Red), C.int(colour.Green), C.int(colour.Blue), C.int(colour.Alpha)) } func (w *macosWindow) position() (int, int) { @@ -921,7 +930,7 @@ func (w *macosWindow) destroy() { C.windowDestroy(w.nsWindow) } -func (w *macosWindow) renderHTML(html string) { +func (w *macosWindow) setHTML(html string) { // Convert HTML to C string cHTML := C.CString(html) // Render HTML diff --git a/exp/pkg/options/window.go b/exp/pkg/options/window.go index fc931f95b..b6ce5e280 100644 --- a/exp/pkg/options/window.go +++ b/exp/pkg/options/window.go @@ -27,7 +27,6 @@ type Window struct { MinHeight int MaxWidth int MaxHeight int - EnableDevTools bool StartState WindowState Mac *MacWindow BackgroundColour *RGBA @@ -38,11 +37,10 @@ type Window struct { } var WindowDefaults = &Window{ - Title: "", - Width: 1024, - Height: 768, - URL: "https://wails.io", - EnableDevTools: true, + Title: "", + Width: 800, + Height: 600, + URL: "", } type Assets struct { @@ -50,9 +48,9 @@ type Assets struct { URL string // FS to use for loading assets from FS fs.FS - // Handler is a custom handler to use for serving assets. If this is set, the `URL` and `FS` fields are ignored. + // Handler is a custom handler to use for serving assets. If this is set, the `SetURL` and `FS` fields are ignored. Handler http.Handler - // Middleware is a custom middleware to use for serving assets. If this is set, the `URL` and `FS` fields are ignored. + // Middleware is a custom middleware to use for serving assets. If this is set, the `SetURL` and `FS` fields are ignored. Middleware func(http.Handler) http.Handler }