Nasin now counts application windows to determine when to shut down

This commit is contained in:
Sasha Koshka 2024-08-14 11:58:06 -04:00
parent bc26e78024
commit 7da00e990e

View File

@ -15,8 +15,9 @@ type Application interface {
// Describe returns a description of the application.
Describe () ApplicationDescription
// Init performs the initial setup of the application.
Init () error
// Init performs the initial setup of the application. This behavior
// should return a window if it creates one.
Init () (tomo.Window, error)
}
// ApplicationURLOpener is an application that can open a URL.
@ -29,12 +30,15 @@ type ApplicationURLOpener interface {
//
// Applications should support the file:// scheme at the very least, and
// should also support others like http:// and https:// if possible.
OpenURL (*url.URL) error
//
// This behavior should return a window if it creates one.
OpenURL (*url.URL) (tomo.Window, error)
// OpenNone is called when the application is launched without any URLs
// to open. The application may create some sort of default starting
// window, or call tomo.Stop().
OpenNone ()
// window, or do nothing. This behavior should return a window if it
// creates one.
OpenNone () (tomo.Window, error)
}
// ApplicationFlagAdder is an application that supports reading command line
@ -148,15 +152,19 @@ func RunApplication (application Application) {
if err != nil { log.Fatalln("nasin: could not set icon set:", err) }
err = reg.SetFaceSet()
if err != nil { log.Fatalln("nasin: could not set face set:", err) }
err = application.Init()
window, err := application.Init()
if err != nil { log.Fatalln("nasin: could not run application:", err) }
manageWindow(window)
// open URLs
args := flag.Args()
applicationOpenUrls(application, args...)
if windows > 0 {
err = backend.Run()
if err != nil { log.Fatalln("nasin: could not run application:", err) }
}
}
// NewApplicationWindow creates a window for an application. It will
// automatically set window information to signal to the OS that the window is
@ -173,10 +181,54 @@ func NewApplicationWindow (application Application, bounds image.Rectangle) (tom
return window, nil
}
func applicationOpenUrls (application Application, args ...string) {
if application, ok := application.(ApplicationURLOpener); ok {
var windows int
func manageWindow (window tomo.Window) {
if window == nil { return }
windows ++
window.OnClose(func () {
windows --
if windows < 1 {
tomo.Stop()
}
})
}
func errorPopupf (title, format string, v ...any) func (func ()) {
return func (callback func ()) {
dialog, err := objects.NewDialogOk (
objects.DialogError, nil,
title,
fmt.Sprintf(format, v...),
callback)
if err != nil { log.Fatal(err) }
dialog.SetVisible(true)
manageWindow(dialog)
}
}
func applicationOpenUrls (app Application, args ...string) {
application, ok := app.(ApplicationURLOpener)
if !ok {
if len(args) > 0 {
log.Fatal("nasin: this application cannot open URLs")
}
return
}
openNone := func () bool {
window, err := application.OpenNone()
if err != nil {
log.Fatalf("nasin: could not open main window: %v", err)
return false
}
manageWindow(window)
return true
}
if len(args) <= 0 {
application.OpenNone()
openNone()
return
}
openedAny := false
@ -190,27 +242,19 @@ func applicationOpenUrls (application Application, args ...string) {
if ur.Scheme == "" {
ur.Scheme = "file"
}
err = application.OpenURL(ur)
window, err := application.OpenURL(ur)
if err != nil {
dialog, err := objects.NewDialogOk (
objects.DialogError, nil,
errorPopupf(
"Could Not Open URL",
fmt.Sprintf (
"Could not open %v: %v",
arg, err),
func () {
arg, err,
)(func () {
if !openedAny {
application.OpenNone()
openNone()
}
})
if err != nil { log.Fatal(err) }
dialog.SetVisible(true)
}
}
} else {
if len(args) > 0 {
log.Fatal("nasin: this application cannot open URLs")
}
manageWindow(window)
}
}