diff --git a/application.go b/application.go index fc4da83..6391b72 100644 --- a/application.go +++ b/application.go @@ -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,14 +152,18 @@ 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...) - err = backend.Run() - if err != nil { log.Fatalln("nasin: could not run application:", err) } + + 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 @@ -173,44 +181,80 @@ func NewApplicationWindow (application Application, bounds image.Rectangle) (tom return window, nil } -func applicationOpenUrls (application Application, args ...string) { - if application, ok := application.(ApplicationURLOpener); ok { - if len(args) <= 0 { - application.OpenNone() - } +var windows int - openedAny := false - for _, arg := range flag.Args() { - ur, err := url.Parse(arg) - if err != nil { - log.Fatalf ( - "nasin: invalid URL %v: %v", - arg, err) - } - if ur.Scheme == "" { - ur.Scheme = "file" - } - err = application.OpenURL(ur) - if err != nil { - dialog, err := objects.NewDialogOk ( - objects.DialogError, nil, - "Could Not Open URL", - fmt.Sprintf ( - "Could not open %v: %v", - arg, err), - func () { - if !openedAny { - application.OpenNone() - } - }) - if err != nil { log.Fatal(err) } - dialog.SetVisible(true) - } +func manageWindow (window tomo.Window) { + if window == nil { return } + windows ++ + window.OnClose(func () { + windows -- + if windows < 1 { + tomo.Stop() } - } else { + }) +} + +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 { + openNone() + return + } + + openedAny := false + for _, arg := range flag.Args() { + ur, err := url.Parse(arg) + if err != nil { + log.Fatalf ( + "nasin: invalid URL %v: %v", + arg, err) + } + if ur.Scheme == "" { + ur.Scheme = "file" + } + window, err := application.OpenURL(ur) + if err != nil { + errorPopupf( + "Could Not Open URL", + "Could not open %v: %v", + arg, err, + )(func () { + if !openedAny { + openNone() + } + }) + } + manageWindow(window) } }