From c9328e958508040f0dba4553b7850c28cd71df75 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Thu, 4 Jul 2024 22:45:09 -0400 Subject: [PATCH] Actually make use of ApplicationURLOpener Progress on #4 --- application.go | 81 ++++++++++++++++++++++++++++++++++++++++++++++---- go.mod | 1 + go.sum | 2 ++ 3 files changed, 78 insertions(+), 6 deletions(-) diff --git a/application.go b/application.go index 4ed417c..a75e50c 100644 --- a/application.go +++ b/application.go @@ -1,10 +1,13 @@ package nasin +import "fmt" import "log" +import "flag" import "image" import "strings" import "net/url" import "git.tebibyte.media/tomo/tomo" +import "git.tebibyte.media/tomo/objects" import "git.tebibyte.media/tomo/tomo/canvas" import "git.tebibyte.media/tomo/nasin/internal/registrar" @@ -23,12 +26,27 @@ type ApplicationURLOpener interface { // OpenURL opens a new window with the contents of the given URL. If the // given URL is unsupported, it returns an error (for example, an image - // viewer is not expected to open a text file). If the URL scheme is - // empty, file:// is assumed. + // viewer is not expected to open a text file). // // 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 + + // 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 () +} + +// ApplicationFlagAdder is an application that supports reading command line +// flags. +type ApplicationFlagAdder interface { + Application + + // AddFlags is called before Init and given the default flag set that + // Nasin uses to parse command line arguments. Note that when this + // method is called, Tomo will not yet be initialized. + AddFlags (*flag.FlagSet) } // ApplicationDescription describes the name and type of an application. @@ -105,15 +123,26 @@ func (role ApplicationRole) Icon () tomo.Icon { // RunApplication is like tomo.Run, but runs an application. If something fails // to initialize, an error is written to the standard logger. func RunApplication (application Application) { + // TODO: see #4 + + if application, ok := application.(ApplicationFlagAdder); ok { + application.AddFlags(flag.CommandLine) + } + flag.Parse() + err := registrar.RegisterBackend() - if err != nil { log.Fatal("nasin: could not register backend:", err) } + if err != nil { log.Fatalln("nasin: could not register backend:", err) } err = tomo.Run(func () { err := registrar.SetTheme() - if err != nil { log.Fatal("nasin: could not set theme:", err) } + if err != nil { log.Fatalln("nasin: could not set theme:", err) } err = application.Init() - if err != nil { log.Fatal("nasin: could not run application:", err) } + if err != nil { log.Fatalln("nasin: could not run application:", err) } + + // open URLs + args := flag.Args() + applicationOpenUrls(application, args...) }) - if err != nil { log.Fatal("nasin: could not run application:", err) } + if err != nil { log.Fatalln("nasin: could not run application:", err) } } // NewApplicationWindow creates a window for an application. It will @@ -126,10 +155,50 @@ func NewApplicationWindow (application Application, bounds image.Rectangle) (tom if err != nil { return nil, err } description := application.Describe() window.SetTitle(description.Name) + setApplicationWindowIcon(window, description) return window, nil } +func applicationOpenUrls (application Application, args ...string) { + if application, ok := application.(ApplicationURLOpener); ok { + if len(args) <= 0 { + application.OpenNone() + } + + 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) + } + } + } else { + log.Fatal("nasin: this application cannot open URLs") + } +} + func setApplicationWindowIcon (window tomo.Window, description ApplicationDescription) { allSizes := func (icon tomo.Icon) (sizes []canvas.Texture) { small := icon.Texture(tomo.IconSizeSmall) diff --git a/go.mod b/go.mod index b789626..a721f3b 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.20 require ( git.tebibyte.media/tomo/backend v0.4.1 + git.tebibyte.media/tomo/objects v0.19.0 git.tebibyte.media/tomo/tomo v0.38.0 git.tebibyte.media/tomo/xdg v0.1.0 golang.org/x/image v0.11.0 diff --git a/go.sum b/go.sum index b00032b..a7d12e9 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,8 @@ git.tebibyte.media/sashakoshka/xgbkb v1.0.0/go.mod h1:pNcE6TRO93vHd6q42SdwLSTTj25L0Yzggz7yLe0JV6Q= git.tebibyte.media/tomo/backend v0.4.1 h1:rpkyTAfp/PE56aSqKNxtSN+D/aBSW8wjJ/vTtSgqQhE= git.tebibyte.media/tomo/backend v0.4.1/go.mod h1:2G04zmKbzf5fA/xzsjoQRrN55BWZkB+vknFxd3ialZ0= +git.tebibyte.media/tomo/objects v0.19.0 h1:ibnAoPvkPTiuJGlqQDnoGVZBQiUT/GZo1qqvDDUCK4w= +git.tebibyte.media/tomo/objects v0.19.0/go.mod h1:GP5BZ6lc2F2D0OxERfr9r46PIk7jFlpq2/BWOpoQDqc= git.tebibyte.media/tomo/tomo v0.38.0 h1:K5TP67RxnszudeNfmGZiU5cFTRjFueXiI3NCsgw+05U= git.tebibyte.media/tomo/tomo v0.38.0/go.mod h1:C9EzepS9wjkTJjnZaPBh22YvVPyA4hbBAJVU20Rdmps= git.tebibyte.media/tomo/typeset v0.7.1 h1:aZrsHwCG5ZB4f5CruRFsxLv5ezJUCFUFsQJJso2sXQ8=