├── resource
├── sample
│ └── sample.gif
├── document
│ ├── screenshot.gif
│ ├── screenshot.png
│ ├── media-play.svg
│ ├── media-pause.svg
│ ├── media-skip-previous.svg
│ ├── media-skip-next.svg
│ ├── media-fast-forward.svg
│ ├── media-fast-rewind.svg
│ ├── zoom-out.svg
│ └── zoom-in.svg
└── icons
│ ├── README.md
│ └── svg
│ ├── image.svg
│ ├── close.svg
│ ├── open.svg
│ └── credits.svg
├── go.mod
├── image
├── gif_test.go
└── gif.go
├── Makefile
├── about.go
├── LICENSE
├── thumbnail.go
├── player.go
├── info.go
├── README.md
├── view.go
├── main.go
├── go.sum
├── bar.go
├── resource.go
└── credits.go
/resource/sample/sample.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lusingander/go-gif-viewer/HEAD/resource/sample/sample.gif
--------------------------------------------------------------------------------
/resource/document/screenshot.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lusingander/go-gif-viewer/HEAD/resource/document/screenshot.gif
--------------------------------------------------------------------------------
/resource/document/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lusingander/go-gif-viewer/HEAD/resource/document/screenshot.png
--------------------------------------------------------------------------------
/resource/icons/README.md:
--------------------------------------------------------------------------------
1 | ```
2 | $ go get fyne.io/fyne/cmd/fyne
3 | $ fyne bundle ./svg > ../../resource.go
4 | ```
5 |
6 | by http://www.evericons.com/
7 |
--------------------------------------------------------------------------------
/resource/document/media-play.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resource/document/media-pause.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resource/document/media-skip-previous.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resource/document/media-skip-next.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resource/document/media-fast-forward.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resource/document/media-fast-rewind.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/lusingander/go-gif-viewer
2 |
3 | go 1.13
4 |
5 | require (
6 | fyne.io/fyne v1.4.3
7 | github.com/dustin/go-humanize v1.0.0
8 | github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
9 | )
10 |
--------------------------------------------------------------------------------
/image/gif_test.go:
--------------------------------------------------------------------------------
1 | package image
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestLoadGif(t *testing.T) {
8 | _, err := LoadGIFImageFromPath("../resource/sample/sample.gif")
9 | if err != nil {
10 | t.Fatalf("failed to load: %v", err)
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: all run build bundle clean credits
2 |
3 | BINARY_NAME=go-gif-viewer
4 |
5 | all: build
6 |
7 | run:
8 | go run *.go
9 |
10 | build: bundle
11 | go build -o $(BINARY_NAME)
12 |
13 | bundle:
14 | fyne bundle ./resource/icons/svg/ > ./resource.go
15 |
16 | clean:
17 | rm $(BINARY_NAME)
18 |
19 | credits:
20 | fyne-credits-generator > ./credits.go
--------------------------------------------------------------------------------
/resource/document/zoom-out.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resource/document/zoom-in.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/about.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "net/url"
6 |
7 | "fyne.io/fyne"
8 | "fyne.io/fyne/widget"
9 | )
10 |
11 | const (
12 | aboutWindowName = "About"
13 | repositoryURL = "https://github.com/lusingander/go-gif-viewer"
14 | )
15 |
16 | func newAboutWindow() fyne.Window {
17 | w := fyne.CurrentApp().NewWindow(aboutWindowName)
18 | w.SetContent(
19 | widget.NewVBox(
20 | widget.NewHBox(
21 | widget.NewLabelWithStyle("go-gif-viewer", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}),
22 | widget.NewLabel(fmt.Sprintf("(Version %s)", version)),
23 | ),
24 | widget.NewHyperlink(repositoryURL, parseRepositoryURL()),
25 | ),
26 | )
27 | return w
28 | }
29 |
30 | func parseRepositoryURL() *url.URL {
31 | u, _ := url.Parse(repositoryURL)
32 | return u
33 | }
34 |
--------------------------------------------------------------------------------
/resource/icons/svg/image.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resource/icons/svg/close.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resource/icons/svg/open.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resource/icons/svg/credits.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 lusingander
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/thumbnail.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 |
6 | "fyne.io/fyne"
7 | "fyne.io/fyne/canvas"
8 | "fyne.io/fyne/layout"
9 | "fyne.io/fyne/widget"
10 | "github.com/lusingander/go-gif-viewer/image"
11 | "github.com/nfnt/resize"
12 | )
13 |
14 | const (
15 | thumbnailListWindowName = "List"
16 | )
17 |
18 | var (
19 | thumbnailListDefaultWidth = 150
20 | thumbnailListDefaultHeight = 400
21 | thumbnailListDefaultSize = fyne.NewSize(thumbnailListDefaultWidth, thumbnailListDefaultHeight)
22 | )
23 |
24 | func thumbnailContainer(img *canvas.Image, i int) fyne.CanvasObject {
25 | label := fmt.Sprintf("%d", i+1)
26 | return widget.NewGroup(label, img)
27 | }
28 |
29 | func addThumbnails(container *fyne.Container, gif *image.GIFImage) {
30 | size := uint(thumbnailListDefaultWidth)
31 | for i := 0; i < gif.Length(); i++ {
32 | resized := resize.Resize(size, size, gif.Get(i), resize.NearestNeighbor)
33 | img := &canvas.Image{
34 | Image: resized,
35 | FillMode: canvas.ImageFillOriginal,
36 | }
37 | container.AddObject(thumbnailContainer(img, i))
38 | }
39 | }
40 |
41 | func newThumbnailListWindow(gif *image.GIFImage) fyne.Window {
42 | w := fyne.CurrentApp().NewWindow(thumbnailListWindowName)
43 | l := fyne.NewContainerWithLayout(layout.NewVBoxLayout())
44 | w.SetContent(widget.NewVScrollContainer(l))
45 | w.Resize(thumbnailListDefaultSize)
46 | go addThumbnails(l, gif)
47 | return w
48 | }
49 |
--------------------------------------------------------------------------------
/player.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "time"
5 |
6 | "github.com/lusingander/go-gif-viewer/image"
7 | )
8 |
9 | type player struct {
10 | delayMilliSec int // TODO: fix
11 | speed float64
12 |
13 | observers []func()
14 | stopPlay chan bool
15 | changeSpeed chan float64
16 | }
17 |
18 | func newPlayer(i *image.GIFImage, speed float64) *player {
19 | return &player{
20 | delayMilliSec: i.DelayMilliSec()[0], // TODO: fix
21 | speed: speed,
22 | observers: make([]func(), 0),
23 | changeSpeed: make(chan float64),
24 | }
25 | }
26 |
27 | func (p *player) addObserver(f func()) {
28 | p.observers = append(p.observers, f)
29 | }
30 |
31 | func (p *player) calcWaitDuration() time.Duration {
32 | ms := float64(p.delayMilliSec) * float64(time.Millisecond) / p.speed
33 | return time.Duration(ms)
34 | }
35 |
36 | func (p *player) play() {
37 | if p.stopPlay != nil {
38 | return
39 | }
40 | p.stopPlay = make(chan bool)
41 | go func() {
42 | t := time.NewTicker(p.calcWaitDuration())
43 | for {
44 | select {
45 | case <-t.C:
46 | for _, o := range p.observers {
47 | o()
48 | }
49 | case <-p.changeSpeed:
50 | t = time.NewTicker(p.calcWaitDuration())
51 | case <-p.stopPlay:
52 | t.Stop()
53 | return
54 | }
55 | }
56 | }()
57 | }
58 |
59 | func (p *player) pause() {
60 | if p.stopPlay == nil {
61 | return
62 | }
63 | p.stopPlay <- true
64 | p.stopPlay = nil
65 | }
66 |
67 | func (p *player) playing() bool {
68 | return p.stopPlay != nil
69 | }
70 |
71 | func (p *player) setSpeed(s float64) {
72 | p.speed = s
73 | if p.playing() {
74 | p.changeSpeed <- s
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/info.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 |
6 | "fyne.io/fyne"
7 | "fyne.io/fyne/layout"
8 | "fyne.io/fyne/widget"
9 | "github.com/dustin/go-humanize"
10 | "github.com/lusingander/go-gif-viewer/image"
11 | )
12 |
13 | const (
14 | infoWindowName = "Info"
15 | )
16 |
17 | func newInfoWindow(gif *image.GIFImage) fyne.Window {
18 | w := fyne.CurrentApp().NewWindow(infoWindowName)
19 | w.SetContent(
20 | fyne.NewContainerWithLayout(
21 | layout.NewHBoxLayout(),
22 | fyne.NewContainerWithLayout(
23 | layout.NewVBoxLayout(),
24 | keyLabel("File name"),
25 | keyLabel("File path"),
26 | keyLabel("Last updated"),
27 | keyLabel("File size"),
28 | keyLabel("Image size"),
29 | keyLabel("Frame count"),
30 | ),
31 | fyne.NewContainerWithLayout(
32 | layout.NewVBoxLayout(),
33 | valueLabel(gif.FileName()),
34 | valueLabel(gif.FilePath()),
35 | valueLabel(formatLastUpdated(gif)),
36 | valueLabel(formatFileSize(gif)),
37 | valueLabel(formatImageSize(gif)),
38 | valueLabel(gif.Length()),
39 | ),
40 | ),
41 | )
42 | return w
43 | }
44 |
45 | func formatFileSize(gif *image.GIFImage) string {
46 | sizeByte := gif.FileSizeByte()
47 | return fmt.Sprintf("%s (%d bytes)", humanize.Bytes(uint64(sizeByte)), sizeByte)
48 | }
49 |
50 | func formatImageSize(gif *image.GIFImage) string {
51 | w, h := gif.Size()
52 | return fmt.Sprintf("%d x %d", w, h)
53 | }
54 |
55 | func formatLastUpdated(gif *image.GIFImage) string {
56 | t := gif.FileLastUpdated()
57 | return t.Format("2006-01-02 03:04:56")
58 | }
59 |
60 | func keyLabel(l string) *widget.Label {
61 | return widget.NewLabelWithStyle(l+":", fyne.TextAlignTrailing, fyne.TextStyle{})
62 | }
63 |
64 | func valueLabel(v interface{}) *widget.Label {
65 | return widget.NewLabelWithStyle(fmt.Sprintf("%v", v), fyne.TextAlignLeading, fyne.TextStyle{})
66 | }
67 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 | [](https://goreportcard.com/report/github.com/lusingander/go-gif-viewer)
3 | 
4 |
5 | # go-gif-viewer
6 |
7 | Simple animated GIF viewer with Go and [Fyne](https://fyne.io/)
8 |
9 |
10 |
11 | ## Installation
12 |
13 | `$ go get github.com/lusingander/go-gif-viewer`
14 |
15 | ## Usage
16 |
17 | `$ go-gif-viewer sample.gif`
18 |
19 | or
20 |
21 | `$ go-gif-viewer` and select open file icon (
).
22 |
23 | ### Keybindings
24 |
25 | |Key|Description|Icon|
26 | |-|-|-|
27 | |←|Go to previous frame|
|
28 | |→|Go to next frame|
|
29 | |↑|Go to first frame|
|
30 | |↓|Go to last frame|
|
31 | |Space|Play / Pause|
/
|
32 | ||||
33 | |+|Zoom in|
|
34 | |-|Zoom out|
|
35 | |[|Decrease playback speed|-|
36 | |]|Increase playback speed|-|
37 | ||||
38 | |⌘O|Open image file|
|
39 | |⌘W|Close image file|
|
40 |
41 | ## Screenshot
42 |
43 |
44 |
45 | ----
46 |
47 | Sample image: By Marvel - Based upon a NASA image, see [1]., CC BY-SA 3.0, Link
48 |
--------------------------------------------------------------------------------
/view.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | im "image"
5 |
6 | "fyne.io/fyne"
7 | "fyne.io/fyne/canvas"
8 | "fyne.io/fyne/layout"
9 | "fyne.io/fyne/widget"
10 | "github.com/lusingander/go-gif-viewer/image"
11 | "github.com/nfnt/resize"
12 | )
13 |
14 | const (
15 | scaleDefault = 1.0
16 | scaleMax = 2.0 - 0.01
17 | scaleMin = 0.1 + 0.01
18 | scaleStep = 0.1
19 | )
20 |
21 | type imageView struct {
22 | *canvas.Image
23 | fyne.CanvasObject
24 |
25 | *image.GIFImage
26 |
27 | scale float64
28 |
29 | caches []im.Image
30 | }
31 |
32 | func newImageView() *imageView {
33 | image := &canvas.Image{
34 | FillMode: canvas.ImageFillOriginal,
35 | }
36 | imageBox := widget.NewVBox(
37 | layout.NewSpacer(),
38 | widget.NewHBox(
39 | layout.NewSpacer(),
40 | image,
41 | layout.NewSpacer(),
42 | ),
43 | layout.NewSpacer(),
44 | )
45 | canvas := widget.NewScrollContainer(imageBox)
46 | return &imageView{
47 | Image: image,
48 | CanvasObject: canvas,
49 | scale: scaleDefault,
50 | }
51 | }
52 |
53 | func (v *imageView) zoomIn() {
54 | if v.scale < scaleMax {
55 | v.scale += scaleStep
56 | v.loadImageCaches()
57 | }
58 | }
59 |
60 | func (v *imageView) zoomOut() {
61 | if v.scale > scaleMin {
62 | v.scale -= scaleStep
63 | v.loadImageCaches()
64 | }
65 | }
66 |
67 | func (v *imageView) setImage(img *image.GIFImage) {
68 | v.GIFImage = img
69 | v.scale = scaleDefault
70 | v.loadImageCaches()
71 | v.refleshFrame(0)
72 | }
73 |
74 | func (v *imageView) loadImageCaches() {
75 | l := v.GIFImage.Length()
76 | caches := make([]im.Image, l)
77 | for i := 0; i < l; i++ {
78 | img := v.GIFImage.Get(i)
79 | w, h := v.scaledImageSize()
80 | caches[i] = resize.Resize(w, h, img, resize.NearestNeighbor)
81 | }
82 | v.caches = caches
83 | }
84 |
85 | func (v *imageView) clearImage() {
86 | v.Image.Image = nil
87 | v.reflesh()
88 | }
89 |
90 | func (v *imageView) refleshFrame(n int) {
91 | v.Image.Image = v.caches[n]
92 | v.reflesh()
93 | }
94 |
95 | func (v *imageView) reflesh() {
96 | canvas.Refresh(v.Image)
97 | }
98 |
99 | func (v *imageView) scaledImageSize() (uint, uint) {
100 | w, h := v.GIFImage.Size()
101 | fw := float64(w) * v.scale
102 | fh := float64(h) * v.scale
103 | return uint(fw), uint(fh)
104 | }
105 |
--------------------------------------------------------------------------------
/image/gif.go:
--------------------------------------------------------------------------------
1 | package image
2 |
3 | import (
4 | "image"
5 | "image/color"
6 | "image/gif"
7 | "os"
8 | "path/filepath"
9 | "time"
10 | )
11 |
12 | type fileInfo struct {
13 | name string
14 | path string
15 | sizeByte int64
16 | lastUpdated time.Time
17 | }
18 |
19 | // GIFImage represents GIF iamge file that can be displayed in frame units.
20 | type GIFImage struct {
21 | origin *gif.GIF
22 | *fileInfo
23 | images []image.Image
24 | }
25 |
26 | // FileName returns the original file name.
27 | func (g *GIFImage) FileName() string {
28 | return g.fileInfo.name
29 | }
30 |
31 | // FilePath returns the original file path.
32 | func (g *GIFImage) FilePath() string {
33 | return g.fileInfo.path
34 | }
35 |
36 | // FileSizeByte returns the original file size in bytes.
37 | func (g *GIFImage) FileSizeByte() int64 {
38 | return g.fileInfo.sizeByte
39 | }
40 |
41 | // FileLastUpdated returns the original file last updated datetime.
42 | func (g *GIFImage) FileLastUpdated() time.Time {
43 | return g.fileInfo.lastUpdated
44 | }
45 |
46 | // Size returns width and height of the image.
47 | func (g *GIFImage) Size() (w, h int) {
48 | c := g.origin.Config
49 | return c.Width, c.Height
50 | }
51 |
52 | // Get returns the image of ith frame.
53 | func (g *GIFImage) Get(i int) image.Image {
54 | return g.images[i]
55 | }
56 |
57 | // Length returns the number of frames.
58 | func (g *GIFImage) Length() int {
59 | return len(g.images)
60 | }
61 |
62 | // DelayMilliSec returns delay times in milliseconds.
63 | func (g *GIFImage) DelayMilliSec() []int {
64 | delay := make([]int, g.Length())
65 | for i, d := range g.origin.Delay {
66 | delay[i] = d * 10
67 | }
68 | return delay
69 | }
70 |
71 | // LoadGIFImageFromPath reads the specified gif image file.
72 | func LoadGIFImageFromPath(path string) (*GIFImage, error) {
73 | g, i, err := loadGIF(path)
74 | if err != nil {
75 | return nil, err
76 | }
77 | return newGIFImage(g, i)
78 | }
79 |
80 | func newGIFImage(g *gif.GIF, i *fileInfo) (*GIFImage, error) {
81 | rect := g.Image[0].Rect
82 | images := make([]image.Image, len(g.Image))
83 | images[0] = g.Image[0]
84 | for i := 1; i < len(g.Image); i++ {
85 | images[i] = restoreFrame(g.Image[i], images[i-1], rect)
86 | }
87 | return &GIFImage{
88 | origin: g,
89 | fileInfo: i,
90 | images: images,
91 | }, nil
92 | }
93 |
94 | func restoreFrame(current *image.Paletted, prev image.Image, rect image.Rectangle) image.Image {
95 | img := image.NewRGBA(rect)
96 | for x := 0; x < rect.Dx(); x++ {
97 | for y := 0; y < rect.Dy(); y++ {
98 | if isInRect(x, y, current.Rect) && isOpaque(current.At(x, y)) {
99 | img.Set(x, y, current.At(x, y))
100 | } else {
101 | img.Set(x, y, prev.At(x, y))
102 | }
103 | }
104 | }
105 | return img
106 | }
107 |
108 | func loadGIF(path string) (*gif.GIF, *fileInfo, error) {
109 | f, err := os.Open(path)
110 | if err != nil {
111 | return nil, nil, err
112 | }
113 | defer f.Close()
114 | i, err := getFileInfo(f, path)
115 | if err != nil {
116 | return nil, nil, err
117 | }
118 | g, err := gif.DecodeAll(f)
119 | if err != nil {
120 | return nil, nil, err
121 | }
122 | return g, i, nil
123 | }
124 |
125 | func getFileInfo(f *os.File, p string) (*fileInfo, error) {
126 | i, err := f.Stat()
127 | if err != nil {
128 | return nil, err
129 | }
130 | path, err := filepath.Abs(p)
131 | if err != nil {
132 | return nil, err
133 | }
134 | return &fileInfo{
135 | name: i.Name(),
136 | path: path,
137 | sizeByte: i.Size(),
138 | lastUpdated: i.ModTime(),
139 | }, nil
140 | }
141 |
142 | func isOpaque(c color.Color) bool {
143 | _, _, _, a := c.RGBA()
144 | return a > 0
145 | }
146 |
147 | func isInRect(x, y int, r image.Rectangle) bool {
148 | return r.Min.X <= x && x < r.Max.X &&
149 | r.Min.Y <= y && y < r.Max.Y
150 | }
151 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 | "os"
6 |
7 | "fyne.io/fyne"
8 | "fyne.io/fyne/app"
9 | "fyne.io/fyne/dialog"
10 | "fyne.io/fyne/driver/desktop"
11 | "fyne.io/fyne/layout"
12 | "fyne.io/fyne/storage"
13 | "github.com/lusingander/go-gif-viewer/image"
14 | )
15 |
16 | const (
17 | appName = "GIF Viewer"
18 | version = "0.3.0"
19 | )
20 |
21 | var defaultWindowSize = fyne.NewSize(400, 400)
22 |
23 | type mainView struct {
24 | fyne.Window
25 |
26 | *fyne.Container
27 |
28 | *menuBar
29 | *imageView
30 | *navigateBar
31 |
32 | *player
33 |
34 | isThumbnailListWindowOpening bool
35 | isInfoWindowOpening bool
36 | isCreditsWindowOpening bool
37 | isAboutWindowOpening bool
38 | }
39 |
40 | func newMainView(w fyne.Window) *mainView {
41 | mainView := &mainView{
42 | Window: w,
43 | }
44 | menuBar := newMenuBar(
45 | mainView.openFileDialog,
46 | mainView.clearImage,
47 | mainView.thumbnailList,
48 | mainView.info,
49 | mainView.credits,
50 | mainView.about,
51 | mainView.zoomIn,
52 | mainView.zoomOut,
53 | )
54 | imageView := newImageView()
55 | navigateBar := newNavigateBar()
56 | panel := fyne.NewContainerWithLayout(
57 | layout.NewBorderLayout(menuBar.CanvasObject, navigateBar.CanvasObject, nil, nil),
58 | menuBar.CanvasObject, navigateBar.CanvasObject, imageView.CanvasObject,
59 | )
60 | mainView.Container = panel
61 | mainView.menuBar = menuBar
62 | mainView.imageView = imageView
63 | mainView.navigateBar = navigateBar
64 | return mainView
65 | }
66 |
67 | func (v *mainView) loadImageFromPath(path string) error {
68 | img, err := image.LoadGIFImageFromPath(path)
69 | if err != nil {
70 | return err
71 | }
72 | v.loadImage(img)
73 | return nil
74 | }
75 |
76 | func (v *mainView) loadImage(img *image.GIFImage) {
77 | v.imageView.setImage(img)
78 | v.navigateBar.setImage(img)
79 | v.navigateBar.addObserver(v.refleshFrame)
80 |
81 | v.player = newPlayer(img, v.menuBar.currentSpeed())
82 | v.player.addObserver(v.navigateBar.next)
83 | v.menuBar.setPlayer(v.player)
84 | v.navigateBar.setPlayer(v.player)
85 | }
86 |
87 | func (v *mainView) clearImage() {
88 | v.imageView.clearImage()
89 | v.navigateBar.clearImage()
90 |
91 | v.player = nil
92 | v.menuBar.setPlayer(v.player)
93 | v.navigateBar.setPlayer(v.player)
94 | }
95 |
96 | func (v *mainView) openFileDialog() {
97 | fd := dialog.NewFileOpen(func(reader fyne.URIReadCloser, err error) {
98 | if err == nil && reader == nil {
99 | return
100 | }
101 | if err != nil {
102 | dialog.ShowError(err, v.Window)
103 | return
104 | }
105 | v.withLoadingDialog(func() {
106 | err = v.loadImageFromPath(reader.URI().String()[7:]) // `file://`
107 | if err != nil {
108 | dialog.ShowError(err, v.Window)
109 | return
110 | }
111 | })
112 | }, v.Window)
113 | fd.SetFilter(storage.NewExtensionFileFilter([]string{".gif"}))
114 | fd.Show()
115 | }
116 |
117 | func (v *mainView) withLoadingDialog(f func()) {
118 | d := dialog.NewProgressInfinite("Loading", "Now loading...", v.Window)
119 | go func() {
120 | f()
121 | d.Hide()
122 | }()
123 | d.Show()
124 | }
125 |
126 | func (v *mainView) thumbnailList() {
127 | if v.imageView.GIFImage == nil {
128 | return
129 | }
130 | wf := func() fyne.Window { return newThumbnailListWindow(v.imageView.GIFImage) }
131 | v.openWindow(wf, &v.isThumbnailListWindowOpening)
132 | }
133 |
134 | func (v *mainView) info() {
135 | if v.imageView.GIFImage == nil {
136 | return
137 | }
138 | wf := func() fyne.Window { return newInfoWindow(v.imageView.GIFImage) }
139 | v.openWindow(wf, &v.isInfoWindowOpening)
140 | }
141 |
142 | func (v *mainView) credits() {
143 | wf := func() fyne.Window { return CreditsWindow(fyne.CurrentApp(), fyne.NewSize(800, 400)) }
144 | v.openWindow(wf, &v.isCreditsWindowOpening)
145 | }
146 |
147 | func (v *mainView) about() {
148 | v.openWindow(newAboutWindow, &v.isAboutWindowOpening)
149 | }
150 |
151 | func (v *mainView) openWindow(windowOpen func() fyne.Window, isOpening *bool) {
152 | if *isOpening {
153 | return
154 | }
155 | w := windowOpen()
156 | w.SetOnClosed(func() { *isOpening = false })
157 | w.Show()
158 | *isOpening = true
159 | }
160 |
161 | func (v *mainView) zoomIn() {
162 | if v.imageView.GIFImage == nil {
163 | return
164 | }
165 | v.imageView.zoomIn()
166 | v.navigateBar.update()
167 | }
168 |
169 | func (v *mainView) zoomOut() {
170 | if v.imageView.GIFImage == nil {
171 | return
172 | }
173 | v.imageView.zoomOut()
174 | v.navigateBar.update()
175 | }
176 |
177 | func (v *mainView) handleKeys(e *fyne.KeyEvent) {
178 | switch e.Name {
179 | case fyne.KeyLeft:
180 | v.prev()
181 | case fyne.KeyRight:
182 | v.next()
183 | case fyne.KeyUp:
184 | v.first()
185 | case fyne.KeyDown:
186 | v.last()
187 | case fyne.KeySpace:
188 | v.pressPlayButton()
189 | }
190 | }
191 |
192 | func (v *mainView) handleRune(r rune) {
193 | switch r {
194 | case '+':
195 | v.zoomIn()
196 | case '-':
197 | v.zoomOut()
198 | case '[':
199 | v.decreaseSpeed()
200 | case ']':
201 | v.increaseSpeed()
202 | }
203 | }
204 |
205 | func (v *mainView) addShortcuts() {
206 | // TODO: want to use ctrl on Windows...
207 | v.addSuperShotrcuts(fyne.KeyO, v.openFileDialog)
208 | v.addSuperShotrcuts(fyne.KeyW, v.clearImage)
209 | }
210 |
211 | func (v *mainView) addSuperShotrcuts(key fyne.KeyName, f func()) {
212 | v.Window.Canvas().AddShortcut(
213 | &desktop.CustomShortcut{KeyName: key, Modifier: desktop.SuperModifier},
214 | func(_ fyne.Shortcut) { f() },
215 | )
216 | }
217 |
218 | func run(args []string) error {
219 | a := app.New()
220 | w := a.NewWindow(appName)
221 | w.Resize(defaultWindowSize)
222 | v := newMainView(w)
223 | w.SetContent(v.Container)
224 | w.Canvas().SetOnTypedKey(v.handleKeys)
225 | w.Canvas().SetOnTypedRune(v.handleRune)
226 | v.addShortcuts()
227 | if len(args) > 1 {
228 | v.withLoadingDialog(func() {
229 | err := v.loadImageFromPath(args[1])
230 | if err != nil {
231 | dialog.ShowError(err, w)
232 | }
233 | })
234 | }
235 | w.ShowAndRun()
236 | return nil
237 | }
238 |
239 | func main() {
240 | if err := run(os.Args); err != nil {
241 | log.Fatal(err)
242 | }
243 | }
244 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | fyne.io/fyne v1.4.3 h1:356CnXCiYrrfaLGsB7qLK3c6ktzyh8WR05v/2RBu51I=
2 | fyne.io/fyne v1.4.3/go.mod h1:8kiPBNSDmuplxs9WnKCkaWYqbcXFy0DeAzwa6PBO9Z8=
3 | github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9/go.mod h1:7uhhqiBaR4CpN0k9rMjOtjpcfGd6DG2m04zQxKnWQ0I=
4 | github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
5 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
6 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
7 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
8 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
9 | github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
10 | github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
11 | github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
12 | github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
13 | github.com/fyne-io/mobile v0.1.2 h1:0HaXDtOOwyOTn3Umi0uKVCOgJtfX73c6unC4U8i5VZU=
14 | github.com/fyne-io/mobile v0.1.2/go.mod h1:/kOrWrZB6sasLbEy2JIvr4arEzQTXBTZGb3Y96yWbHY=
15 | github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 h1:SCYMcCJ89LjRGwEa0tRluNRiMjZHalQZrVrvTbPh+qw=
16 | github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7/go.mod h1:482civXOzJJCPzJ4ZOX/pwvXBWSnzD4OKMdH4ClKGbk=
17 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200625191551-73d3c3675aa3 h1:q521PfSp5/z6/sD9FZZOWj4d1MLmfQW8PkRnI9M6PCE=
18 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200625191551-73d3c3675aa3/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
19 | github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME=
20 | github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
21 | github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff h1:W71vTCKoxtdXgnm1ECDFkfQnpdqAO00zzGXLA5yaEX8=
22 | github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff/go.mod h1:wfqRWLHRBsRgkp5dmbG56SA0DmVtwrF5N3oPdI8t+Aw=
23 | github.com/jackmordaunt/icns v0.0.0-20181231085925-4f16af745526/go.mod h1:UQkeMHVoNcyXYq9otUupF7/h/2tmHlhrS2zw7ZVvUqc=
24 | github.com/josephspurrier/goversioninfo v0.0.0-20200309025242-14b0ab84c6ca/go.mod h1:eJTEwMjXb7kZ633hO3Ln9mBUCOjX2+FlTljvpl9SYdE=
25 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
26 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
27 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
28 | github.com/lucor/goinfo v0.0.0-20200401173949-526b5363a13a/go.mod h1:ORP3/rB5IsulLEBwQZCJyyV6niqmI7P4EWSmkug+1Ng=
29 | github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
30 | github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
31 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
32 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
33 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
34 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
35 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
36 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
37 | github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
38 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
39 | github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564 h1:HunZiaEKNGVdhTRQOVpMmj5MQnGnv+e8uZNu3xFLgyM=
40 | github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564/go.mod h1:afMbS0qvv1m5tfENCwnOdZGOF8RGR/FsZ7bvBxQGZG4=
41 | github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9 h1:m59mIOBO4kfcNCEzJNy71UkeF4XIx2EVmL9KLwDQdmM=
42 | github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9/go.mod h1:mvWM0+15UqyrFKqdRjY6LuAVJR0HOVhJlEgZ5JWtSWU=
43 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
44 | github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
45 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
46 | github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
47 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
48 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
49 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=
50 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
51 | golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw=
52 | golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
53 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
54 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
55 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
56 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
57 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
58 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
59 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
60 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
61 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
62 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
63 | golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
64 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
65 | golang.org/x/sys v0.0.0-20200720211630-cb9d2d5c5666 h1:gVCS+QOncANNPlmlO1AhlU3oxs4V9z+gTtPwIk3p2N8=
66 | golang.org/x/sys v0.0.0-20200720211630-cb9d2d5c5666/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
67 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
68 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
69 | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
70 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
71 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
72 | golang.org/x/tools v0.0.0-20190808195139-e713427fea3f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
73 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
74 | golang.org/x/tools v0.0.0-20200328031815-3db5fc6bac03/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
75 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
76 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
77 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
78 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
79 | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
80 | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
81 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
82 | gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
83 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
84 |
--------------------------------------------------------------------------------
/bar.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "strconv"
6 |
7 | "fyne.io/fyne"
8 | "fyne.io/fyne/layout"
9 | "fyne.io/fyne/theme"
10 | "fyne.io/fyne/widget"
11 | "github.com/lusingander/go-gif-viewer/image"
12 | )
13 |
14 | var (
15 | openIcon fyne.Resource = theme.NewThemedResource(resourceOpenSvg, nil)
16 | closeIcon fyne.Resource = theme.NewThemedResource(resourceCloseSvg, nil)
17 |
18 | thumbnailIcon fyne.Resource = theme.NewThemedResource(resourceImageSvg, nil)
19 | infoIcon fyne.Resource = theme.NewThemedResource(theme.InfoIcon(), nil)
20 | creditsIcon fyne.Resource = theme.NewThemedResource(resourceCreditsSvg, nil) // TODO: better icon...
21 | aboutIcon fyne.Resource = theme.NewThemedResource(theme.QuestionIcon(), nil)
22 |
23 | zoomInIcon fyne.Resource = theme.NewThemedResource(theme.ZoomInIcon(), nil)
24 | zoomOutIcon fyne.Resource = theme.NewThemedResource(theme.ZoomOutIcon(), nil)
25 |
26 | playIcon fyne.Resource = theme.NewThemedResource(theme.MediaPlayIcon(), nil)
27 | pauseIcon fyne.Resource = theme.NewThemedResource(theme.MediaPauseIcon(), nil)
28 |
29 | prevIcon fyne.Resource = theme.NewThemedResource(theme.MediaFastRewindIcon(), nil)
30 | nextIcon fyne.Resource = theme.NewThemedResource(theme.MediaFastForwardIcon(), nil)
31 | firstIcon fyne.Resource = theme.NewThemedResource(theme.MediaSkipPreviousIcon(), nil)
32 | lastIcon fyne.Resource = theme.NewThemedResource(theme.MediaSkipNextIcon(), nil)
33 | )
34 |
35 | var speeds = []string{
36 | "0.25x",
37 | "0.5x",
38 | "1.0x",
39 | "1.5x",
40 | "2.0x",
41 | "3.0x",
42 | "4.0x",
43 | }
44 |
45 | func defaultSpeed() string {
46 | return speeds[2] // 1.0x
47 | }
48 |
49 | type menuBar struct {
50 | fyne.CanvasObject
51 |
52 | *widget.Toolbar
53 | *widget.Select
54 |
55 | *player
56 | }
57 |
58 | func createSpeedSelect() *widget.Select {
59 | sel := widget.NewSelect(speeds, func(string) {})
60 | sel.SetSelected(defaultSpeed())
61 | return sel
62 | }
63 |
64 | func newMenuBar(open, close, thumbnail, info, credits, about, zoomIn, zoomOut func()) *menuBar {
65 | toolBar := widget.NewToolbar(
66 | widget.NewToolbarAction(openIcon, open),
67 | widget.NewToolbarAction(closeIcon, close),
68 | widget.NewToolbarAction(thumbnailIcon, thumbnail),
69 | widget.NewToolbarAction(infoIcon, info),
70 | widget.NewToolbarAction(creditsIcon, credits),
71 | widget.NewToolbarAction(aboutIcon, about),
72 | widget.NewToolbarSpacer(),
73 | widget.NewToolbarAction(zoomInIcon, zoomIn),
74 | widget.NewToolbarAction(zoomOutIcon, zoomOut),
75 | )
76 | sppedSelect := createSpeedSelect()
77 | return &menuBar{
78 | CanvasObject: fyne.NewContainerWithLayout(
79 | layout.NewBorderLayout(nil, nil, nil, sppedSelect),
80 | sppedSelect, toolBar,
81 | ),
82 | Toolbar: toolBar,
83 | Select: sppedSelect,
84 | }
85 | }
86 |
87 | func (b *menuBar) setPlayer(p *player) {
88 | b.player = p
89 | b.Select.OnChanged = func(s string) {
90 | // TODO: fix
91 | if b.player != nil {
92 | b.player.setSpeed(parseSpeed(s))
93 | }
94 | }
95 | b.Select.SetSelected(defaultSpeed())
96 | }
97 |
98 | func (b *menuBar) currentSpeed() float64 {
99 | return parseSpeed(b.Select.Selected)
100 | }
101 |
102 | func parseSpeed(s string) float64 {
103 | f, _ := strconv.ParseFloat(s[:len(s)-1], 64)
104 | return f
105 | }
106 |
107 | func (b *menuBar) increaseSpeed() {
108 | // TODO: fix
109 | if b.player == nil {
110 | return
111 | }
112 | for i := 0; i < len(speeds)-1; i++ {
113 | if speeds[i] == b.Selected {
114 | b.SetSelected(speeds[i+1])
115 | b.player.setSpeed(b.currentSpeed())
116 | return
117 | }
118 | }
119 | }
120 |
121 | func (b *menuBar) decreaseSpeed() {
122 | // TODO: fix
123 | if b.player == nil {
124 | return
125 | }
126 | for i := 1; i < len(speeds); i++ {
127 | if speeds[i] == b.Selected {
128 | b.SetSelected(speeds[i-1])
129 | b.player.setSpeed(b.currentSpeed())
130 | return
131 | }
132 | }
133 | }
134 |
135 | type playButton struct {
136 | *widget.Button
137 |
138 | playing bool
139 | play, pause func()
140 | }
141 |
142 | func newPlayButton(play, pause func()) *playButton {
143 | return &playButton{
144 | Button: widget.NewButtonWithIcon("", playIcon, play),
145 | playing: false,
146 | play: play,
147 | pause: pause,
148 | }
149 | }
150 |
151 | func (b *playButton) click() {
152 | if b.playing {
153 | b.OnTapped = b.play
154 | b.SetIcon(playIcon)
155 | } else {
156 | b.OnTapped = b.pause
157 | b.SetIcon(pauseIcon)
158 | }
159 | b.playing = !b.playing
160 | }
161 |
162 | type navigateBar struct {
163 | fyne.CanvasObject
164 |
165 | *widget.Label
166 | *widget.Slider
167 | *playButton
168 | *player
169 |
170 | current, total int
171 | totalDigit int
172 |
173 | observers []func(int)
174 |
175 | canPlay bool
176 | }
177 |
178 | func (b *navigateBar) addObserver(f func(int)) {
179 | b.observers = append(b.observers, f)
180 | }
181 |
182 | func (b *navigateBar) clearObservers() {
183 | b.observers = make([]func(int), 0)
184 | }
185 |
186 | func (b *navigateBar) pressPlayButton() {
187 | if b.player == nil {
188 | return
189 | }
190 | if b.player.playing() {
191 | b.stop()
192 | } else {
193 | b.start()
194 | }
195 | }
196 |
197 | func (b *navigateBar) start() {
198 | if !b.canPlay || b.player.playing() {
199 | return
200 | }
201 | b.playButton.click()
202 | b.player.play()
203 | }
204 |
205 | func (b *navigateBar) stop() {
206 | if !b.player.playing() {
207 | return
208 | }
209 | b.player.pause()
210 | b.playButton.click()
211 | }
212 |
213 | func (b *navigateBar) next() {
214 | if !b.canPlay {
215 | return
216 | }
217 | if b.current == b.total {
218 | b.first()
219 | } else if b.current < b.total {
220 | b.current++
221 | b.update()
222 | }
223 | }
224 |
225 | func (b *navigateBar) prev() {
226 | if !b.canPlay {
227 | return
228 | }
229 | if b.current == 1 {
230 | b.last()
231 | } else if b.current > 1 {
232 | b.current--
233 | b.update()
234 | }
235 | }
236 |
237 | func (b *navigateBar) first() {
238 | if !b.canPlay {
239 | return
240 | }
241 | if b.current > 1 {
242 | b.current = 1
243 | b.update()
244 | }
245 | }
246 |
247 | func (b *navigateBar) last() {
248 | if !b.canPlay {
249 | return
250 | }
251 | if b.current < b.total {
252 | b.current = b.total
253 | b.update()
254 | }
255 | }
256 |
257 | func (b *navigateBar) change(n int) {
258 | if !b.canPlay {
259 | return
260 | }
261 | if 1 <= n && n <= b.total {
262 | b.current = n
263 | b.update()
264 | }
265 | }
266 |
267 | func (b *navigateBar) update() {
268 | b.SetText(b.createCountText())
269 | // Note: Slider doesn't have proper method...
270 | b.Slider.Value = float64(b.current - 1)
271 | b.Slider.Refresh()
272 | for _, o := range b.observers {
273 | o(b.current - 1)
274 | }
275 | }
276 |
277 | func (b *navigateBar) createCountText() string {
278 | if !b.canPlay {
279 | return ""
280 | }
281 | return fmt.Sprintf("%*d/%*d",
282 | b.totalDigit, b.current, b.totalDigit, b.total)
283 | }
284 |
285 | func (b *navigateBar) setImage(img *image.GIFImage) {
286 | b.clearObservers()
287 | n := img.Length()
288 | b.current = 1
289 | b.total = n
290 | b.Slider.Max = float64(n - 1)
291 | b.totalDigit = len(strconv.Itoa(n))
292 | b.canPlay = true
293 | b.update()
294 | }
295 |
296 | func (b *navigateBar) clearImage() {
297 | b.clearObservers()
298 | b.current = 1
299 | b.Slider.Max = 1
300 | b.canPlay = false
301 | b.update()
302 | }
303 |
304 | func (b *navigateBar) setPlayer(p *player) {
305 | b.player = p
306 | }
307 |
308 | func newNavigateBar() *navigateBar {
309 | bar := &navigateBar{
310 | observers: make([]func(int), 0),
311 | canPlay: false,
312 | }
313 | slider := createSliderBar(bar)
314 | buttons := createButtons(bar)
315 | bar.CanvasObject = widget.NewVBox(slider, buttons)
316 | return bar
317 | }
318 |
319 | func createSliderBar(bar *navigateBar) fyne.CanvasObject {
320 | bar.Slider = widget.NewSlider(0, 1)
321 | bar.Slider.OnChanged = func(f float64) { bar.change(int(f) + 1) }
322 | bar.Label = widget.NewLabel(bar.createCountText())
323 | bar.Label.TextStyle.Monospace = true
324 | return fyne.NewContainerWithLayout(
325 | layout.NewBorderLayout(nil, nil, nil, bar.Label),
326 | bar.Label, bar.Slider,
327 | )
328 | }
329 |
330 | func createButtons(bar *navigateBar) fyne.CanvasObject {
331 | bar.playButton = newPlayButton(bar.start, bar.stop)
332 | first := widget.NewButtonWithIcon("", firstIcon, bar.first)
333 | prev := widget.NewButtonWithIcon("", prevIcon, bar.prev)
334 | next := widget.NewButtonWithIcon("", nextIcon, bar.next)
335 | last := widget.NewButtonWithIcon("", lastIcon, bar.last)
336 | return widget.NewHBox(
337 | layout.NewSpacer(), first, prev, bar.playButton.Button, next, last, layout.NewSpacer(),
338 | )
339 | }
340 |
--------------------------------------------------------------------------------
/resource.go:
--------------------------------------------------------------------------------
1 | // auto-generated
2 |
3 | package main
4 |
5 | import "fyne.io/fyne"
6 |
7 | var resourceCloseSvg = &fyne.StaticResource{
8 | StaticName: "close.svg",
9 | StaticContent: []byte{
10 | 60, 115, 118, 103, 32, 120, 109, 108, 110, 115, 61, 34, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 119, 51, 46, 111, 114, 103, 47, 50, 48, 48, 48, 47, 115, 118, 103, 34, 32, 119, 105, 100, 116, 104, 61, 34, 50, 52, 34, 32, 104, 101, 105, 103, 104, 116, 61, 34, 50, 52, 34, 32, 118, 105, 101, 119, 66, 111, 120, 61, 34, 48, 32, 48, 32, 50, 52, 32, 50, 52, 34, 62, 10, 32, 32, 60, 112, 97, 116, 104, 32, 102, 105, 108, 108, 45, 114, 117, 108, 101, 61, 34, 101, 118, 101, 110, 111, 100, 100, 34, 32, 100, 61, 34, 77, 50, 49, 44, 53, 32, 67, 50, 50, 46, 49, 48, 52, 53, 54, 57, 53, 44, 53, 32, 50, 51, 44, 53, 46, 56, 57, 53, 52, 51, 48, 53, 32, 50, 51, 44, 55, 32, 76, 50, 51, 44, 49, 57, 32, 67, 50, 51, 44, 50, 48, 46, 49, 48, 52, 53, 54, 57, 53, 32, 50, 50, 46, 49, 48, 52, 53, 54, 57, 53, 44, 50, 49, 32, 50, 49, 44, 50, 49, 32, 76, 51, 44, 50, 49, 32, 67, 49, 46, 56, 57, 53, 52, 51, 48, 53, 44, 50, 49, 32, 49, 44, 50, 48, 46, 49, 48, 52, 53, 54, 57, 53, 32, 49, 44, 49, 57, 32, 76, 49, 44, 53, 32, 67, 49, 44, 51, 46, 56, 57, 53, 52, 51, 48, 53, 32, 49, 46, 56, 57, 53, 52, 51, 48, 53, 44, 51, 32, 51, 44, 51, 32, 76, 57, 44, 51, 32, 67, 49, 48, 46, 49, 50, 48, 48, 48, 50, 51, 44, 51, 32, 49, 48, 46, 56, 51, 50, 57, 51, 57, 44, 51, 46, 52, 55, 53, 52, 53, 49, 49, 56, 32, 49, 49, 46, 53, 52, 56, 57, 55, 54, 52, 44, 52, 46, 51, 55, 56, 56, 53, 51, 48, 57, 32, 67, 49, 49, 46, 53, 57, 54, 55, 53, 52, 55, 44, 52, 46, 52, 51, 57, 49, 51, 51, 53, 50, 32, 49, 49, 46, 56, 49, 48, 48, 57, 57, 57, 44, 52, 46, 55, 49, 53, 56, 56, 50, 55, 53, 32, 49, 49, 46, 56, 54, 50, 52, 56, 51, 49, 44, 52, 46, 55, 56, 48, 56, 49, 57, 52, 53, 32, 67, 49, 50, 46, 48, 49, 57, 55, 50, 54, 44, 52, 46, 57, 55, 53, 55, 52, 52, 57, 53, 32, 49, 50, 46, 48, 53, 49, 55, 55, 57, 53, 44, 52, 46, 57, 57, 57, 55, 50, 57, 53, 54, 32, 49, 50, 46, 48, 48, 49, 55, 56, 54, 51, 44, 53, 32, 76, 50, 49, 44, 53, 32, 90, 32, 77, 50, 49, 44, 49, 57, 32, 76, 50, 49, 44, 55, 32, 76, 49, 49, 46, 57, 57, 52, 54, 52, 54, 44, 54, 46, 57, 57, 57, 57, 56, 53, 54, 55, 32, 67, 49, 49, 46, 50, 55, 54, 52, 57, 49, 53, 44, 54, 46, 57, 57, 54, 49, 52, 48, 53, 56, 32, 49, 48, 46, 56, 48, 56, 54, 57, 49, 54, 44, 54, 46, 54, 53, 57, 57, 48, 57, 50, 51, 32, 49, 48, 46, 51, 48, 53, 56, 51, 50, 50, 44, 54, 46, 48, 51, 54, 53, 52, 49, 52, 54, 32, 67, 49, 48, 46, 50, 51, 54, 52, 50, 56, 49, 44, 53, 46, 57, 53, 48, 53, 48, 52, 57, 55, 32, 49, 48, 46, 48, 49, 53, 56, 55, 51, 55, 44, 53, 46, 54, 54, 52, 52, 48, 51, 57, 56, 32, 57, 46, 57, 56, 49, 53, 57, 55, 55, 56, 44, 53, 46, 54, 50, 49, 49, 53, 57, 49, 54, 32, 67, 57, 46, 54, 48, 55, 48, 50, 49, 53, 56, 44, 53, 46, 49, 52, 56, 53, 54, 56, 49, 49, 32, 57, 46, 51, 56, 52, 50, 52, 52, 52, 50, 44, 53, 32, 57, 44, 53, 32, 76, 51, 44, 53, 32, 76, 51, 44, 49, 57, 32, 76, 50, 49, 44, 49, 57, 32, 90, 32, 77, 49, 50, 44, 49, 49, 46, 53, 56, 53, 55, 56, 54, 52, 32, 76, 49, 52, 46, 50, 57, 50, 56, 57, 51, 50, 44, 57, 46, 50, 57, 50, 56, 57, 51, 50, 50, 32, 76, 49, 53, 46, 55, 48, 55, 49, 48, 54, 56, 44, 49, 48, 46, 55, 48, 55, 49, 48, 54, 56, 32, 76, 49, 51, 46, 52, 49, 52, 50, 49, 51, 54, 44, 49, 51, 32, 76, 49, 53, 46, 55, 48, 55, 49, 48, 54, 56, 44, 49, 53, 46, 50, 57, 50, 56, 57, 51, 50, 32, 76, 49, 52, 46, 50, 57, 50, 56, 57, 51, 50, 44, 49, 54, 46, 55, 48, 55, 49, 48, 54, 56, 32, 76, 49, 50, 44, 49, 52, 46, 52, 49, 52, 50, 49, 51, 54, 32, 76, 57, 46, 55, 48, 55, 49, 48, 54, 55, 56, 44, 49, 54, 46, 55, 48, 55, 49, 48, 54, 56, 32, 76, 56, 46, 50, 57, 50, 56, 57, 51, 50, 50, 44, 49, 53, 46, 50, 57, 50, 56, 57, 51, 50, 32, 76, 49, 48, 46, 53, 56, 53, 55, 56, 54, 52, 44, 49, 51, 32, 76, 56, 46, 50, 57, 50, 56, 57, 51, 50, 50, 44, 49, 48, 46, 55, 48, 55, 49, 48, 54, 56, 32, 76, 57, 46, 55, 48, 55, 49, 48, 54, 55, 56, 44, 57, 46, 50, 57, 50, 56, 57, 51, 50, 50, 32, 76, 49, 50, 44, 49, 49, 46, 53, 56, 53, 55, 56, 54, 52, 32, 90, 34, 47, 62, 10, 60, 47, 115, 118, 103, 62, 10}}
11 |
12 | var resourceCreditsSvg = &fyne.StaticResource{
13 | StaticName: "credits.svg",
14 | StaticContent: []byte{
15 | 60, 115, 118, 103, 32, 120, 109, 108, 110, 115, 61, 34, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 119, 51, 46, 111, 114, 103, 47, 50, 48, 48, 48, 47, 115, 118, 103, 34, 32, 119, 105, 100, 116, 104, 61, 34, 50, 52, 34, 32, 104, 101, 105, 103, 104, 116, 61, 34, 50, 52, 34, 32, 118, 105, 101, 119, 66, 111, 120, 61, 34, 48, 32, 48, 32, 50, 52, 32, 50, 52, 34, 62, 10, 32, 32, 60, 112, 97, 116, 104, 32, 102, 105, 108, 108, 45, 114, 117, 108, 101, 61, 34, 101, 118, 101, 110, 111, 100, 100, 34, 32, 100, 61, 34, 77, 54, 46, 48, 51, 53, 51, 49, 55, 55, 56, 44, 49, 56, 46, 55, 51, 57, 55, 54, 52, 32, 67, 55, 46, 54, 50, 51, 50, 57, 57, 55, 57, 44, 50, 48, 46, 49, 52, 54, 49, 55, 54, 32, 57, 46, 55, 49, 49, 57, 51, 57, 50, 53, 44, 50, 49, 32, 49, 50, 44, 50, 49, 32, 67, 49, 52, 46, 50, 56, 56, 48, 54, 48, 56, 44, 50, 49, 32, 49, 54, 46, 51, 55, 54, 55, 48, 48, 50, 44, 50, 48, 46, 49, 52, 54, 49, 55, 54, 32, 49, 55, 46, 57, 54, 52, 54, 56, 50, 50, 44, 49, 56, 46, 55, 51, 57, 55, 54, 52, 32, 67, 49, 55, 46, 54, 55, 49, 57, 57, 57, 52, 44, 49, 55, 46, 54, 56, 55, 51, 52, 57, 32, 49, 53, 46, 53, 54, 57, 51, 56, 50, 51, 44, 49, 55, 32, 49, 50, 44, 49, 55, 32, 67, 56, 46, 52, 51, 48, 54, 49, 55, 55, 52, 44, 49, 55, 32, 54, 46, 51, 50, 56, 48, 48, 48, 54, 53, 44, 49, 55, 46, 54, 56, 55, 51, 52, 57, 32, 54, 46, 48, 51, 53, 51, 49, 55, 55, 56, 44, 49, 56, 46, 55, 51, 57, 55, 54, 52, 32, 90, 32, 77, 52, 46, 54, 48, 48, 53, 48, 51, 53, 56, 44, 49, 55, 46, 49, 50, 52, 54, 52, 55, 53, 32, 67, 53, 46, 55, 50, 53, 57, 53, 49, 51, 49, 44, 49, 53, 46, 54, 51, 56, 48, 54, 52, 32, 56, 46, 51, 55, 48, 54, 48, 49, 56, 57, 44, 49, 53, 32, 49, 50, 44, 49, 53, 32, 67, 49, 53, 46, 54, 50, 57, 51, 57, 56, 49, 44, 49, 53, 32, 49, 56, 46, 50, 55, 52, 48, 52, 56, 55, 44, 49, 53, 46, 54, 51, 56, 48, 54, 52, 32, 49, 57, 46, 51, 57, 57, 52, 57, 54, 52, 44, 49, 55, 46, 49, 50, 52, 54, 52, 55, 53, 32, 67, 50, 48, 46, 52, 48, 56, 54, 49, 55, 57, 44, 49, 53, 46, 54, 55, 48, 51, 49, 56, 51, 32, 50, 49, 44, 49, 51, 46, 57, 48, 52, 50, 50, 49, 53, 32, 50, 49, 44, 49, 50, 32, 67, 50, 49, 44, 55, 46, 48, 50, 57, 52, 51, 55, 50, 53, 32, 49, 54, 46, 57, 55, 48, 53, 54, 50, 55, 44, 51, 32, 49, 50, 44, 51, 32, 67, 55, 46, 48, 50, 57, 52, 51, 55, 50, 53, 44, 51, 32, 51, 44, 55, 46, 48, 50, 57, 52, 51, 55, 50, 53, 32, 51, 44, 49, 50, 32, 67, 51, 44, 49, 51, 46, 57, 48, 52, 50, 50, 49, 53, 32, 51, 46, 53, 57, 49, 51, 56, 50, 49, 51, 44, 49, 53, 46, 54, 55, 48, 51, 49, 56, 51, 32, 52, 46, 54, 48, 48, 53, 48, 51, 53, 56, 44, 49, 55, 46, 49, 50, 52, 54, 52, 55, 53, 32, 90, 32, 77, 49, 50, 44, 50, 51, 32, 67, 53, 46, 57, 50, 52, 56, 54, 55, 55, 53, 44, 50, 51, 32, 49, 44, 49, 56, 46, 48, 55, 53, 49, 51, 50, 50, 32, 49, 44, 49, 50, 32, 67, 49, 44, 53, 46, 57, 50, 52, 56, 54, 55, 55, 53, 32, 53, 46, 57, 50, 52, 56, 54, 55, 55, 53, 44, 49, 32, 49, 50, 44, 49, 32, 67, 49, 56, 46, 48, 55, 53, 49, 51, 50, 50, 44, 49, 32, 50, 51, 44, 53, 46, 57, 50, 52, 56, 54, 55, 55, 53, 32, 50, 51, 44, 49, 50, 32, 67, 50, 51, 44, 49, 56, 46, 48, 55, 53, 49, 51, 50, 50, 32, 49, 56, 46, 48, 55, 53, 49, 51, 50, 50, 44, 50, 51, 32, 49, 50, 44, 50, 51, 32, 90, 32, 77, 56, 44, 49, 48, 32, 67, 56, 44, 55, 46, 55, 53, 53, 55, 53, 57, 51, 54, 32, 57, 46, 53, 55, 57, 48, 57, 57, 53, 55, 44, 54, 32, 49, 50, 44, 54, 32, 67, 49, 52, 46, 52, 49, 52, 49, 57, 52, 56, 44, 54, 32, 49, 54, 44, 55, 46, 57, 50, 49, 53, 55, 56, 50, 49, 32, 49, 54, 44, 49, 48, 46, 50, 32, 67, 49, 54, 44, 49, 51, 46, 52, 55, 57, 54, 49, 52, 32, 49, 52, 46, 50, 49, 56, 48, 56, 54, 49, 44, 49, 53, 32, 49, 50, 44, 49, 53, 32, 67, 57, 46, 55, 54, 48, 56, 54, 51, 56, 50, 44, 49, 53, 32, 56, 44, 49, 51, 46, 52, 50, 55, 51, 55, 52, 51, 32, 56, 44, 49, 48, 32, 90, 32, 77, 49, 48, 44, 49, 48, 32, 67, 49, 48, 44, 49, 50, 46, 50, 54, 57, 50, 53, 54, 56, 32, 49, 48, 46, 56, 49, 56, 50, 49, 48, 56, 44, 49, 51, 32, 49, 50, 44, 49, 51, 32, 67, 49, 51, 46, 49, 55, 55, 55, 48, 54, 51, 44, 49, 51, 32, 49, 52, 44, 49, 50, 46, 50, 57, 56, 51, 57, 50, 55, 32, 49, 52, 44, 49, 48, 46, 50, 32, 67, 49, 52, 44, 56, 46, 57, 53, 48, 52, 49, 55, 51, 54, 32, 49, 51, 46, 50, 49, 53, 54, 53, 54, 56, 44, 56, 32, 49, 50, 44, 56, 32, 67, 49, 48, 46, 55, 51, 51, 55, 51, 56, 55, 44, 56, 32, 49, 48, 44, 56, 46, 56, 49, 53, 56, 50, 52, 55, 57, 32, 49, 48, 44, 49, 48, 32, 90, 34, 47, 62, 10, 60, 47, 115, 118, 103, 62, 10}}
16 |
17 | var resourceImageSvg = &fyne.StaticResource{
18 | StaticName: "image.svg",
19 | StaticContent: []byte{
20 | 60, 115, 118, 103, 32, 120, 109, 108, 110, 115, 61, 34, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 119, 51, 46, 111, 114, 103, 47, 50, 48, 48, 48, 47, 115, 118, 103, 34, 32, 119, 105, 100, 116, 104, 61, 34, 50, 52, 34, 32, 104, 101, 105, 103, 104, 116, 61, 34, 50, 52, 34, 32, 118, 105, 101, 119, 66, 111, 120, 61, 34, 48, 32, 48, 32, 50, 52, 32, 50, 52, 34, 62, 10, 32, 32, 60, 112, 97, 116, 104, 32, 102, 105, 108, 108, 45, 114, 117, 108, 101, 61, 34, 101, 118, 101, 110, 111, 100, 100, 34, 32, 100, 61, 34, 77, 52, 44, 49, 53, 46, 53, 56, 53, 55, 56, 54, 52, 32, 76, 56, 44, 49, 49, 46, 53, 56, 53, 55, 56, 54, 52, 32, 76, 49, 49, 46, 53, 44, 49, 53, 46, 48, 56, 53, 55, 56, 54, 52, 32, 76, 49, 56, 44, 56, 46, 53, 56, 53, 55, 56, 54, 52, 52, 32, 76, 50, 48, 44, 49, 48, 46, 53, 56, 53, 55, 56, 54, 52, 32, 76, 50, 48, 44, 52, 32, 76, 52, 44, 52, 32, 76, 52, 44, 49, 53, 46, 53, 56, 53, 55, 56, 54, 52, 32, 90, 32, 77, 52, 44, 49, 56, 46, 52, 49, 52, 50, 49, 51, 54, 32, 76, 52, 44, 50, 48, 32, 76, 49, 51, 46, 53, 56, 53, 55, 56, 54, 52, 44, 50, 48, 32, 76, 56, 44, 49, 52, 46, 52, 49, 52, 50, 49, 51, 54, 32, 76, 52, 44, 49, 56, 46, 52, 49, 52, 50, 49, 51, 54, 32, 90, 32, 77, 49, 54, 46, 52, 49, 52, 50, 49, 51, 54, 44, 50, 48, 32, 76, 50, 48, 44, 50, 48, 32, 76, 50, 48, 44, 49, 51, 46, 52, 49, 52, 50, 49, 51, 54, 32, 76, 49, 56, 44, 49, 49, 46, 52, 49, 52, 50, 49, 51, 54, 32, 76, 49, 50, 46, 57, 49, 52, 50, 49, 51, 54, 44, 49, 54, 46, 53, 32, 76, 49, 54, 46, 52, 49, 52, 50, 49, 51, 54, 44, 50, 48, 32, 90, 32, 77, 52, 44, 50, 32, 76, 50, 48, 44, 50, 32, 67, 50, 49, 46, 49, 48, 52, 53, 54, 57, 53, 44, 50, 32, 50, 50, 44, 50, 46, 56, 57, 53, 52, 51, 48, 53, 32, 50, 50, 44, 52, 32, 76, 50, 50, 44, 50, 48, 32, 67, 50, 50, 44, 50, 49, 46, 49, 48, 52, 53, 54, 57, 53, 32, 50, 49, 46, 49, 48, 52, 53, 54, 57, 53, 44, 50, 50, 32, 50, 48, 44, 50, 50, 32, 76, 52, 44, 50, 50, 32, 67, 50, 46, 56, 57, 53, 52, 51, 48, 53, 44, 50, 50, 32, 50, 44, 50, 49, 46, 49, 48, 52, 53, 54, 57, 53, 32, 50, 44, 50, 48, 32, 76, 50, 44, 52, 32, 67, 50, 44, 50, 46, 56, 57, 53, 52, 51, 48, 53, 32, 50, 46, 56, 57, 53, 52, 51, 48, 53, 44, 50, 32, 52, 44, 50, 32, 90, 32, 77, 49, 49, 44, 53, 32, 67, 49, 50, 46, 54, 53, 54, 56, 53, 52, 50, 44, 53, 32, 49, 52, 44, 54, 46, 51, 52, 51, 49, 52, 53, 55, 53, 32, 49, 52, 44, 56, 32, 67, 49, 52, 44, 57, 46, 54, 53, 54, 56, 53, 52, 50, 53, 32, 49, 50, 46, 54, 53, 54, 56, 53, 52, 50, 44, 49, 49, 32, 49, 49, 44, 49, 49, 32, 67, 57, 46, 51, 52, 51, 49, 52, 53, 55, 53, 44, 49, 49, 32, 56, 44, 57, 46, 54, 53, 54, 56, 53, 52, 50, 53, 32, 56, 44, 56, 32, 67, 56, 44, 54, 46, 51, 52, 51, 49, 52, 53, 55, 53, 32, 57, 46, 51, 52, 51, 49, 52, 53, 55, 53, 44, 53, 32, 49, 49, 44, 53, 32, 90, 32, 77, 49, 49, 44, 55, 32, 67, 49, 48, 46, 52, 52, 55, 55, 49, 53, 51, 44, 55, 32, 49, 48, 44, 55, 46, 52, 52, 55, 55, 49, 53, 50, 53, 32, 49, 48, 44, 56, 32, 67, 49, 48, 44, 56, 46, 53, 53, 50, 50, 56, 52, 55, 53, 32, 49, 48, 46, 52, 52, 55, 55, 49, 53, 51, 44, 57, 32, 49, 49, 44, 57, 32, 67, 49, 49, 46, 53, 53, 50, 50, 56, 52, 55, 44, 57, 32, 49, 50, 44, 56, 46, 53, 53, 50, 50, 56, 52, 55, 53, 32, 49, 50, 44, 56, 32, 67, 49, 50, 44, 55, 46, 52, 52, 55, 55, 49, 53, 50, 53, 32, 49, 49, 46, 53, 53, 50, 50, 56, 52, 55, 44, 55, 32, 49, 49, 44, 55, 32, 90, 34, 47, 62, 10, 60, 47, 115, 118, 103, 62, 10}}
21 |
22 | var resourceOpenSvg = &fyne.StaticResource{
23 | StaticName: "open.svg",
24 | StaticContent: []byte{
25 | 60, 115, 118, 103, 32, 120, 109, 108, 110, 115, 61, 34, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 119, 51, 46, 111, 114, 103, 47, 50, 48, 48, 48, 47, 115, 118, 103, 34, 32, 119, 105, 100, 116, 104, 61, 34, 50, 52, 34, 32, 104, 101, 105, 103, 104, 116, 61, 34, 50, 52, 34, 32, 118, 105, 101, 119, 66, 111, 120, 61, 34, 48, 32, 48, 32, 50, 52, 32, 50, 52, 34, 62, 10, 32, 32, 60, 112, 97, 116, 104, 32, 102, 105, 108, 108, 45, 114, 117, 108, 101, 61, 34, 101, 118, 101, 110, 111, 100, 100, 34, 32, 100, 61, 34, 77, 50, 49, 44, 56, 32, 67, 50, 50, 46, 49, 48, 52, 53, 54, 57, 53, 44, 56, 32, 50, 51, 44, 56, 46, 56, 57, 53, 52, 51, 48, 53, 32, 50, 51, 44, 49, 48, 32, 76, 50, 50, 46, 57, 55, 54, 49, 56, 55, 49, 44, 49, 48, 46, 50, 49, 54, 57, 51, 48, 53, 32, 76, 50, 48, 46, 57, 57, 53, 57, 55, 56, 50, 44, 49, 57, 46, 49, 50, 55, 56, 55, 48, 52, 32, 67, 50, 48, 46, 57, 51, 48, 48, 52, 50, 57, 44, 50, 48, 46, 49, 55, 50, 56, 53, 54, 51, 32, 50, 48, 46, 48, 54, 49, 54, 49, 54, 51, 44, 50, 49, 32, 49, 57, 44, 50, 49, 32, 76, 51, 44, 50, 49, 32, 67, 49, 46, 56, 57, 53, 52, 51, 48, 53, 44, 50, 49, 32, 49, 44, 50, 48, 46, 49, 48, 52, 53, 54, 57, 53, 32, 49, 44, 49, 57, 32, 76, 49, 44, 53, 32, 67, 49, 44, 51, 46, 56, 57, 53, 52, 51, 48, 53, 32, 49, 46, 56, 57, 53, 52, 51, 48, 53, 44, 51, 32, 51, 44, 51, 32, 76, 57, 44, 51, 32, 67, 49, 48, 46, 49, 50, 48, 48, 48, 50, 51, 44, 51, 32, 49, 48, 46, 56, 51, 50, 57, 51, 57, 44, 51, 46, 52, 55, 53, 52, 53, 49, 49, 56, 32, 49, 49, 46, 53, 52, 56, 57, 55, 54, 52, 44, 52, 46, 51, 55, 56, 56, 53, 51, 48, 57, 32, 67, 49, 49, 46, 53, 57, 54, 55, 53, 52, 55, 44, 52, 46, 52, 51, 57, 49, 51, 51, 53, 50, 32, 49, 49, 46, 56, 49, 48, 48, 57, 57, 57, 44, 52, 46, 55, 49, 53, 56, 56, 50, 55, 53, 32, 49, 49, 46, 56, 54, 50, 52, 56, 51, 49, 44, 52, 46, 55, 56, 48, 56, 49, 57, 52, 53, 32, 67, 49, 50, 46, 48, 49, 57, 55, 50, 54, 44, 52, 46, 57, 55, 53, 55, 52, 52, 57, 53, 32, 49, 50, 46, 48, 53, 49, 55, 55, 57, 53, 44, 52, 46, 57, 57, 57, 55, 50, 57, 53, 54, 32, 49, 50, 46, 48, 48, 49, 55, 56, 54, 51, 44, 53, 32, 76, 49, 57, 44, 53, 32, 67, 50, 48, 46, 49, 48, 52, 53, 54, 57, 53, 44, 53, 32, 50, 49, 44, 53, 46, 56, 57, 53, 52, 51, 48, 53, 32, 50, 49, 44, 55, 32, 76, 50, 49, 44, 56, 32, 90, 32, 77, 49, 57, 44, 56, 32, 76, 49, 57, 44, 55, 32, 76, 49, 49, 46, 57, 57, 52, 54, 52, 54, 44, 54, 46, 57, 57, 57, 57, 56, 53, 54, 55, 32, 67, 49, 49, 46, 50, 55, 54, 52, 57, 49, 53, 44, 54, 46, 57, 57, 54, 49, 52, 48, 53, 56, 32, 49, 48, 46, 56, 48, 56, 54, 57, 49, 54, 44, 54, 46, 54, 53, 57, 57, 48, 57, 50, 51, 32, 49, 48, 46, 51, 48, 53, 56, 51, 50, 50, 44, 54, 46, 48, 51, 54, 53, 52, 49, 52, 54, 32, 67, 49, 48, 46, 50, 51, 54, 52, 50, 56, 49, 44, 53, 46, 57, 53, 48, 53, 48, 52, 57, 55, 32, 49, 48, 46, 48, 49, 53, 56, 55, 51, 55, 44, 53, 46, 54, 54, 52, 52, 48, 51, 57, 56, 32, 57, 46, 57, 56, 49, 53, 57, 55, 55, 56, 44, 53, 46, 54, 50, 49, 49, 53, 57, 49, 54, 32, 67, 57, 46, 54, 48, 55, 48, 50, 49, 53, 56, 44, 53, 46, 49, 52, 56, 53, 54, 56, 49, 49, 32, 57, 46, 51, 56, 52, 50, 52, 52, 52, 50, 44, 53, 32, 57, 44, 53, 32, 76, 51, 44, 53, 32, 76, 51, 44, 57, 46, 56, 57, 49, 52, 53, 56, 54, 57, 32, 76, 51, 46, 48, 50, 57, 49, 50, 55, 48, 55, 44, 57, 46, 55, 54, 48, 52, 48, 53, 48, 50, 32, 67, 51, 46, 51, 49, 48, 50, 48, 48, 48, 54, 44, 56, 46, 54, 50, 49, 52, 53, 55, 50, 54, 32, 51, 46, 56, 51, 51, 51, 57, 53, 56, 55, 44, 56, 32, 53, 44, 56, 32, 76, 49, 57, 44, 56, 32, 90, 32, 77, 51, 46, 48, 50, 52, 51, 57, 51, 56, 51, 44, 49, 57, 32, 76, 49, 57, 44, 49, 57, 32, 76, 49, 57, 46, 48, 50, 51, 56, 49, 50, 57, 44, 49, 56, 46, 55, 56, 51, 48, 54, 57, 53, 32, 76, 50, 48, 46, 57, 55, 53, 54, 48, 54, 50, 44, 49, 48, 32, 76, 53, 46, 48, 51, 54, 51, 48, 53, 55, 56, 44, 49, 48, 32, 67, 53, 46, 48, 50, 48, 54, 56, 48, 55, 50, 44, 49, 48, 46, 48, 52, 57, 53, 53, 48, 49, 32, 52, 46, 57, 57, 57, 57, 49, 57, 49, 55, 44, 49, 48, 46, 49, 50, 49, 50, 57, 52, 55, 32, 52, 46, 57, 55, 54, 49, 56, 55, 48, 54, 44, 49, 48, 46, 50, 49, 54, 57, 51, 48, 53, 32, 76, 51, 46, 48, 50, 52, 51, 57, 51, 56, 51, 44, 49, 57, 32, 90, 34, 47, 62, 10, 60, 47, 115, 118, 103, 62, 10}}
26 |
--------------------------------------------------------------------------------
/credits.go:
--------------------------------------------------------------------------------
1 | // Code generated by github.com/lusingander/fyne-credits-generator (v0.3.0); DO NOT EDIT.
2 |
3 | package main
4 |
5 | import (
6 | "net/url"
7 | "strings"
8 |
9 | "fyne.io/fyne"
10 | "fyne.io/fyne/layout"
11 | "fyne.io/fyne/widget"
12 | )
13 |
14 | // CreditsWindow returns a window displaying a list of licenses.
15 | func CreditsWindow(app fyne.App, size fyne.Size) fyne.Window {
16 | w := app.NewWindow("CREDITS")
17 | w.Resize(size)
18 | w.SetContent(CreditsContainer())
19 | return w
20 | }
21 |
22 | // CreditsContainer returns a container displaying a list of licenses.
23 | func CreditsContainer() fyne.CanvasObject {
24 | nameLabel := widget.NewLabel("")
25 | urlLabel := widget.NewHyperlink("", nil)
26 | header := widget.NewVBox(nameLabel, urlLabel)
27 | entry := widget.NewMultiLineEntry()
28 | entry.Wrapping = fyne.TextWrapBreak
29 | width := 0
30 | for _, c := range credits {
31 | l := len(c.name)
32 | if l > width {
33 | width = l
34 | }
35 | }
36 | list := widget.NewList(
37 | func() int {
38 | return len(credits)
39 | },
40 | func() fyne.CanvasObject {
41 | dummy := strings.Repeat("*", width)
42 | label := widget.NewLabel(dummy)
43 | label.Alignment = fyne.TextAlignCenter
44 | return label
45 | },
46 | func(id widget.ListItemID, item fyne.CanvasObject) {
47 | item.(*widget.Label).SetText(credits[id].name)
48 | },
49 | )
50 | list.OnSelected = func(id widget.ListItemID) {
51 | c := credits[id]
52 | nameLabel.SetText(c.name)
53 | u, _ := url.Parse(c.url)
54 | urlLabel.SetText(c.url)
55 | urlLabel.SetURL(u)
56 | entry.SetText(c.text)
57 | }
58 | list.Select(0)
59 | text := widget.NewScrollContainer(entry)
60 | license := fyne.NewContainerWithLayout(
61 | layout.NewBorderLayout(header, nil, nil, nil),
62 | header, text,
63 | )
64 | splitContainer := widget.NewHSplitContainer(list, license)
65 | splitContainer.SetOffset(0)
66 | return splitContainer
67 | }
68 |
69 | type credit struct {
70 | name, url, text string
71 | }
72 |
73 | var credits = []*credit{
74 | {
75 | "Go (the standard library)",
76 | "https://golang.org/",
77 | `
78 | Copyright (c) 2009 The Go Authors. All rights reserved.
79 |
80 | Redistribution and use in source and binary forms, with or without
81 | modification, are permitted provided that the following conditions are
82 | met:
83 |
84 | * Redistributions of source code must retain the above copyright
85 | notice, this list of conditions and the following disclaimer.
86 | * Redistributions in binary form must reproduce the above
87 | copyright notice, this list of conditions and the following disclaimer
88 | in the documentation and/or other materials provided with the
89 | distribution.
90 | * Neither the name of Google Inc. nor the names of its
91 | contributors may be used to endorse or promote products derived from
92 | this software without specific prior written permission.
93 |
94 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
95 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
96 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
97 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
98 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
99 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
100 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
101 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
102 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
103 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
104 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
105 |
106 | `,
107 | },
108 | {
109 | "fyne.io/fyne",
110 | "https://fyne.io/fyne",
111 | `
112 | BSD 3-Clause License
113 |
114 | Copyright (C) 2018 Fyne.io developers (see AUTHORS)
115 | All rights reserved.
116 |
117 |
118 | Redistribution and use in source and binary forms, with or without
119 | modification, are permitted provided that the following conditions are met:
120 | * Redistributions of source code must retain the above copyright
121 | notice, this list of conditions and the following disclaimer.
122 | * Redistributions in binary form must reproduce the above copyright
123 | notice, this list of conditions and the following disclaimer in the
124 | documentation and/or other materials provided with the distribution.
125 | * Neither the name of Fyne.io nor the names of its contributors may be
126 | used to endorse or promote products derived from this software without
127 | specific prior written permission.
128 |
129 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
130 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
131 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
132 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
133 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
134 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
135 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
136 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
137 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
138 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
139 |
140 |
141 | `,
142 | },
143 | {
144 | "github.com/davecgh/go-spew",
145 | "https://github.com/davecgh/go-spew",
146 | `
147 | ISC License
148 |
149 | Copyright (c) 2012-2016 Dave Collins
150 |
151 | Permission to use, copy, modify, and/or distribute this software for any
152 | purpose with or without fee is hereby granted, provided that the above
153 | copyright notice and this permission notice appear in all copies.
154 |
155 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
156 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
157 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
158 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
159 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
160 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
161 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
162 |
163 | `,
164 | },
165 | {
166 | "github.com/dustin/go-humanize",
167 | "https://github.com/dustin/go-humanize",
168 | `
169 | Copyright (c) 2005-2008 Dustin Sallings
170 |
171 | Permission is hereby granted, free of charge, to any person obtaining a copy
172 | of this software and associated documentation files (the "Software"), to deal
173 | in the Software without restriction, including without limitation the rights
174 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
175 | copies of the Software, and to permit persons to whom the Software is
176 | furnished to do so, subject to the following conditions:
177 |
178 | The above copyright notice and this permission notice shall be included in
179 | all copies or substantial portions of the Software.
180 |
181 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
182 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
183 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
184 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
185 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
186 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
187 | SOFTWARE.
188 |
189 |
190 |
191 | `,
192 | },
193 | {
194 | "github.com/fsnotify/fsnotify",
195 | "https://github.com/fsnotify/fsnotify",
196 | `
197 | Copyright (c) 2012 The Go Authors. All rights reserved.
198 | Copyright (c) 2012-2019 fsnotify Authors. All rights reserved.
199 |
200 | Redistribution and use in source and binary forms, with or without
201 | modification, are permitted provided that the following conditions are
202 | met:
203 |
204 | * Redistributions of source code must retain the above copyright
205 | notice, this list of conditions and the following disclaimer.
206 | * Redistributions in binary form must reproduce the above
207 | copyright notice, this list of conditions and the following disclaimer
208 | in the documentation and/or other materials provided with the
209 | distribution.
210 | * Neither the name of Google Inc. nor the names of its
211 | contributors may be used to endorse or promote products derived from
212 | this software without specific prior written permission.
213 |
214 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
215 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
216 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
217 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
218 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
219 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
220 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
221 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
222 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
223 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
224 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
225 |
226 | `,
227 | },
228 | {
229 | "github.com/fyne-io/mobile",
230 | "https://github.com/fyne-io/mobile",
231 | `
232 | Copyright (c) 2009 The Go Authors. All rights reserved.
233 |
234 | Redistribution and use in source and binary forms, with or without
235 | modification, are permitted provided that the following conditions are
236 | met:
237 |
238 | * Redistributions of source code must retain the above copyright
239 | notice, this list of conditions and the following disclaimer.
240 | * Redistributions in binary form must reproduce the above
241 | copyright notice, this list of conditions and the following disclaimer
242 | in the documentation and/or other materials provided with the
243 | distribution.
244 | * Neither the name of Google Inc. nor the names of its
245 | contributors may be used to endorse or promote products derived from
246 | this software without specific prior written permission.
247 |
248 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
249 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
250 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
251 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
252 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
253 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
254 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
256 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
257 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
258 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
259 |
260 | `,
261 | },
262 | {
263 | "github.com/go-gl/gl",
264 | "https://github.com/go-gl/gl",
265 | `
266 | The MIT License (MIT)
267 |
268 | Copyright (c) 2014 Eric Woroshow
269 |
270 | Permission is hereby granted, free of charge, to any person obtaining a copy
271 | of this software and associated documentation files (the "Software"), to deal
272 | in the Software without restriction, including without limitation the rights
273 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
274 | copies of the Software, and to permit persons to whom the Software is
275 | furnished to do so, subject to the following conditions:
276 |
277 | The above copyright notice and this permission notice shall be included in all
278 | copies or substantial portions of the Software.
279 |
280 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
281 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
282 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
283 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
284 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
285 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
286 | SOFTWARE.
287 | `,
288 | },
289 | {
290 | "github.com/go-gl/glfw/v3.3/glfw",
291 | "https://github.com/go-gl/glfw/v3.3/glfw",
292 | `
293 | Copyright (c) 2012 The glfw3-go Authors. All rights reserved.
294 |
295 | Redistribution and use in source and binary forms, with or without
296 | modification, are permitted provided that the following conditions are
297 | met:
298 |
299 | * Redistributions of source code must retain the above copyright
300 | notice, this list of conditions and the following disclaimer.
301 | * Redistributions in binary form must reproduce the above
302 | copyright notice, this list of conditions and the following disclaimer
303 | in the documentation and/or other materials provided with the
304 | distribution.
305 | * Neither the name of Google Inc. nor the names of its
306 | contributors may be used to endorse or promote products derived from
307 | this software without specific prior written permission.
308 |
309 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
310 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
311 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
312 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
313 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
314 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
315 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
316 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
317 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
318 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
319 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
320 |
321 | `,
322 | },
323 | {
324 | "github.com/godbus/dbus/v5",
325 | "https://github.com/godbus/dbus/v5",
326 | `
327 | Copyright (c) 2013, Georg Reinke (), Google
328 | All rights reserved.
329 |
330 | Redistribution and use in source and binary forms, with or without
331 | modification, are permitted provided that the following conditions
332 | are met:
333 |
334 | 1. Redistributions of source code must retain the above copyright notice,
335 | this list of conditions and the following disclaimer.
336 |
337 | 2. Redistributions in binary form must reproduce the above copyright
338 | notice, this list of conditions and the following disclaimer in the
339 | documentation and/or other materials provided with the distribution.
340 |
341 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
342 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
343 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
344 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
345 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
346 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
347 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
348 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
349 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
350 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
351 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
352 |
353 | `,
354 | },
355 | {
356 | "github.com/goki/freetype",
357 | "https://github.com/goki/freetype",
358 | `
359 | Use of the Freetype-Go software is subject to your choice of exactly one of
360 | the following two licenses:
361 | * The FreeType License, which is similar to the original BSD license with
362 | an advertising clause, or
363 | * The GNU General Public License (GPL), version 2 or later.
364 |
365 | The text of these licenses are available in the licenses/ftl.txt and the
366 | licenses/gpl.txt files respectively. They are also available at
367 | http://freetype.sourceforge.net/license.html
368 |
369 | The Luxi fonts in the testdata directory are licensed separately. See the
370 | testdata/COPYING file for details.
371 |
372 | `,
373 | },
374 | {
375 | "github.com/kr/text",
376 | "https://github.com/kr/text",
377 | `
378 | Copyright 2012 Keith Rarick
379 |
380 | Permission is hereby granted, free of charge, to any person obtaining a copy
381 | of this software and associated documentation files (the "Software"), to deal
382 | in the Software without restriction, including without limitation the rights
383 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
384 | copies of the Software, and to permit persons to whom the Software is
385 | furnished to do so, subject to the following conditions:
386 |
387 | The above copyright notice and this permission notice shall be included in
388 | all copies or substantial portions of the Software.
389 |
390 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
391 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
392 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
393 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
394 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
395 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
396 | THE SOFTWARE.
397 |
398 | `,
399 | },
400 | {
401 | "github.com/nfnt/resize",
402 | "https://github.com/nfnt/resize",
403 | `
404 | Copyright (c) 2012, Jan Schlicht
405 |
406 | Permission to use, copy, modify, and/or distribute this software for any purpose
407 | with or without fee is hereby granted, provided that the above copyright notice
408 | and this permission notice appear in all copies.
409 |
410 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
411 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
412 | FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
413 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
414 | OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
415 | TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
416 | THIS SOFTWARE.
417 |
418 | `,
419 | },
420 | {
421 | "github.com/niemeyer/pretty",
422 | "https://github.com/niemeyer/pretty",
423 | `
424 | Copyright 2012 Keith Rarick
425 |
426 | Permission is hereby granted, free of charge, to any person obtaining a copy
427 | of this software and associated documentation files (the "Software"), to deal
428 | in the Software without restriction, including without limitation the rights
429 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
430 | copies of the Software, and to permit persons to whom the Software is
431 | furnished to do so, subject to the following conditions:
432 |
433 | The above copyright notice and this permission notice shall be included in
434 | all copies or substantial portions of the Software.
435 |
436 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
437 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
438 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
439 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
440 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
441 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
442 | THE SOFTWARE.
443 |
444 | `,
445 | },
446 | {
447 | "github.com/pmezard/go-difflib",
448 | "https://github.com/pmezard/go-difflib",
449 | `
450 | Copyright (c) 2013, Patrick Mezard
451 | All rights reserved.
452 |
453 | Redistribution and use in source and binary forms, with or without
454 | modification, are permitted provided that the following conditions are
455 | met:
456 |
457 | Redistributions of source code must retain the above copyright
458 | notice, this list of conditions and the following disclaimer.
459 | Redistributions in binary form must reproduce the above copyright
460 | notice, this list of conditions and the following disclaimer in the
461 | documentation and/or other materials provided with the distribution.
462 | The names of its contributors may not be used to endorse or promote
463 | products derived from this software without specific prior written
464 | permission.
465 |
466 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
467 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
468 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
469 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
470 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
471 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
472 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
473 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
474 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
475 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
476 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
477 |
478 | `,
479 | },
480 | {
481 | "github.com/srwiley/oksvg",
482 | "https://github.com/srwiley/oksvg",
483 | `
484 | BSD 3-Clause License
485 |
486 | Copyright (c) 2018, Steven R Wiley
487 | All rights reserved.
488 |
489 | Redistribution and use in source and binary forms, with or without
490 | modification, are permitted provided that the following conditions are met:
491 |
492 | * Redistributions of source code must retain the above copyright notice, this
493 | list of conditions and the following disclaimer.
494 |
495 | * Redistributions in binary form must reproduce the above copyright notice,
496 | this list of conditions and the following disclaimer in the documentation
497 | and/or other materials provided with the distribution.
498 |
499 | * Neither the name of the copyright holder nor the names of its
500 | contributors may be used to endorse or promote products derived from
501 | this software without specific prior written permission.
502 |
503 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
504 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
505 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
506 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
507 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
508 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
509 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
510 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
511 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
512 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
513 |
514 | `,
515 | },
516 | {
517 | "github.com/srwiley/rasterx",
518 | "https://github.com/srwiley/rasterx",
519 | `
520 | BSD 3-Clause License
521 |
522 | Copyright (c) 2018, Steven R Wiley
523 | All rights reserved.
524 |
525 | Redistribution and use in source and binary forms, with or without
526 | modification, are permitted provided that the following conditions are met:
527 |
528 | * Redistributions of source code must retain the above copyright notice, this
529 | list of conditions and the following disclaimer.
530 |
531 | * Redistributions in binary form must reproduce the above copyright notice,
532 | this list of conditions and the following disclaimer in the documentation
533 | and/or other materials provided with the distribution.
534 |
535 | * Neither the name of the copyright holder nor the names of its
536 | contributors may be used to endorse or promote products derived from
537 | this software without specific prior written permission.
538 |
539 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
540 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
541 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
542 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
543 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
544 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
545 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
546 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
547 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
548 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
549 |
550 | `,
551 | },
552 | {
553 | "github.com/stretchr/testify",
554 | "https://github.com/stretchr/testify",
555 | `
556 | MIT License
557 |
558 | Copyright (c) 2012-2018 Mat Ryer and Tyler Bunnell
559 |
560 | Permission is hereby granted, free of charge, to any person obtaining a copy
561 | of this software and associated documentation files (the "Software"), to deal
562 | in the Software without restriction, including without limitation the rights
563 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
564 | copies of the Software, and to permit persons to whom the Software is
565 | furnished to do so, subject to the following conditions:
566 |
567 | The above copyright notice and this permission notice shall be included in all
568 | copies or substantial portions of the Software.
569 |
570 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
571 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
572 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
573 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
574 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
575 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
576 | SOFTWARE.
577 |
578 | `,
579 | },
580 | {
581 | "golang.org/x/image",
582 | "https://golang.org/x/image",
583 | `
584 | Copyright (c) 2009 The Go Authors. All rights reserved.
585 |
586 | Redistribution and use in source and binary forms, with or without
587 | modification, are permitted provided that the following conditions are
588 | met:
589 |
590 | * Redistributions of source code must retain the above copyright
591 | notice, this list of conditions and the following disclaimer.
592 | * Redistributions in binary form must reproduce the above
593 | copyright notice, this list of conditions and the following disclaimer
594 | in the documentation and/or other materials provided with the
595 | distribution.
596 | * Neither the name of Google Inc. nor the names of its
597 | contributors may be used to endorse or promote products derived from
598 | this software without specific prior written permission.
599 |
600 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
601 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
602 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
603 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
604 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
605 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
606 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
607 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
608 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
609 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
610 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
611 |
612 | `,
613 | },
614 | {
615 | "golang.org/x/net",
616 | "https://golang.org/x/net",
617 | `
618 | Copyright (c) 2009 The Go Authors. All rights reserved.
619 |
620 | Redistribution and use in source and binary forms, with or without
621 | modification, are permitted provided that the following conditions are
622 | met:
623 |
624 | * Redistributions of source code must retain the above copyright
625 | notice, this list of conditions and the following disclaimer.
626 | * Redistributions in binary form must reproduce the above
627 | copyright notice, this list of conditions and the following disclaimer
628 | in the documentation and/or other materials provided with the
629 | distribution.
630 | * Neither the name of Google Inc. nor the names of its
631 | contributors may be used to endorse or promote products derived from
632 | this software without specific prior written permission.
633 |
634 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
635 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
636 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
637 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
638 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
639 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
640 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
641 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
642 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
643 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
644 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
645 |
646 | `,
647 | },
648 | {
649 | "golang.org/x/sys",
650 | "https://golang.org/x/sys",
651 | `
652 | Copyright (c) 2009 The Go Authors. All rights reserved.
653 |
654 | Redistribution and use in source and binary forms, with or without
655 | modification, are permitted provided that the following conditions are
656 | met:
657 |
658 | * Redistributions of source code must retain the above copyright
659 | notice, this list of conditions and the following disclaimer.
660 | * Redistributions in binary form must reproduce the above
661 | copyright notice, this list of conditions and the following disclaimer
662 | in the documentation and/or other materials provided with the
663 | distribution.
664 | * Neither the name of Google Inc. nor the names of its
665 | contributors may be used to endorse or promote products derived from
666 | this software without specific prior written permission.
667 |
668 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
669 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
670 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
671 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
672 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
673 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
674 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
675 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
676 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
677 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
678 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
679 |
680 | `,
681 | },
682 | {
683 | "golang.org/x/text",
684 | "https://golang.org/x/text",
685 | `
686 | Copyright (c) 2009 The Go Authors. All rights reserved.
687 |
688 | Redistribution and use in source and binary forms, with or without
689 | modification, are permitted provided that the following conditions are
690 | met:
691 |
692 | * Redistributions of source code must retain the above copyright
693 | notice, this list of conditions and the following disclaimer.
694 | * Redistributions in binary form must reproduce the above
695 | copyright notice, this list of conditions and the following disclaimer
696 | in the documentation and/or other materials provided with the
697 | distribution.
698 | * Neither the name of Google Inc. nor the names of its
699 | contributors may be used to endorse or promote products derived from
700 | this software without specific prior written permission.
701 |
702 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
703 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
704 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
705 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
706 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
707 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
708 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
709 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
710 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
711 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
712 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
713 |
714 | `,
715 | },
716 | {
717 | "gopkg.in/check.v1",
718 | "https://gopkg.in/check.v1",
719 | `
720 | Gocheck - A rich testing framework for Go
721 |
722 | Copyright (c) 2010-2013 Gustavo Niemeyer
723 |
724 | All rights reserved.
725 |
726 | Redistribution and use in source and binary forms, with or without
727 | modification, are permitted provided that the following conditions are met:
728 |
729 | 1. Redistributions of source code must retain the above copyright notice, this
730 | list of conditions and the following disclaimer.
731 | 2. Redistributions in binary form must reproduce the above copyright notice,
732 | this list of conditions and the following disclaimer in the documentation
733 | and/or other materials provided with the distribution.
734 |
735 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
736 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
737 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
738 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
739 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
740 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
741 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
742 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
743 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
744 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
745 |
746 | `,
747 | },
748 | {
749 | "gopkg.in/yaml.v2",
750 | "https://gopkg.in/yaml.v2",
751 | `
752 | Apache License
753 | Version 2.0, January 2004
754 | http://www.apache.org/licenses/
755 |
756 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
757 |
758 | 1. Definitions.
759 |
760 | "License" shall mean the terms and conditions for use, reproduction,
761 | and distribution as defined by Sections 1 through 9 of this document.
762 |
763 | "Licensor" shall mean the copyright owner or entity authorized by
764 | the copyright owner that is granting the License.
765 |
766 | "Legal Entity" shall mean the union of the acting entity and all
767 | other entities that control, are controlled by, or are under common
768 | control with that entity. For the purposes of this definition,
769 | "control" means (i) the power, direct or indirect, to cause the
770 | direction or management of such entity, whether by contract or
771 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
772 | outstanding shares, or (iii) beneficial ownership of such entity.
773 |
774 | "You" (or "Your") shall mean an individual or Legal Entity
775 | exercising permissions granted by this License.
776 |
777 | "Source" form shall mean the preferred form for making modifications,
778 | including but not limited to software source code, documentation
779 | source, and configuration files.
780 |
781 | "Object" form shall mean any form resulting from mechanical
782 | transformation or translation of a Source form, including but
783 | not limited to compiled object code, generated documentation,
784 | and conversions to other media types.
785 |
786 | "Work" shall mean the work of authorship, whether in Source or
787 | Object form, made available under the License, as indicated by a
788 | copyright notice that is included in or attached to the work
789 | (an example is provided in the Appendix below).
790 |
791 | "Derivative Works" shall mean any work, whether in Source or Object
792 | form, that is based on (or derived from) the Work and for which the
793 | editorial revisions, annotations, elaborations, or other modifications
794 | represent, as a whole, an original work of authorship. For the purposes
795 | of this License, Derivative Works shall not include works that remain
796 | separable from, or merely link (or bind by name) to the interfaces of,
797 | the Work and Derivative Works thereof.
798 |
799 | "Contribution" shall mean any work of authorship, including
800 | the original version of the Work and any modifications or additions
801 | to that Work or Derivative Works thereof, that is intentionally
802 | submitted to Licensor for inclusion in the Work by the copyright owner
803 | or by an individual or Legal Entity authorized to submit on behalf of
804 | the copyright owner. For the purposes of this definition, "submitted"
805 | means any form of electronic, verbal, or written communication sent
806 | to the Licensor or its representatives, including but not limited to
807 | communication on electronic mailing lists, source code control systems,
808 | and issue tracking systems that are managed by, or on behalf of, the
809 | Licensor for the purpose of discussing and improving the Work, but
810 | excluding communication that is conspicuously marked or otherwise
811 | designated in writing by the copyright owner as "Not a Contribution."
812 |
813 | "Contributor" shall mean Licensor and any individual or Legal Entity
814 | on behalf of whom a Contribution has been received by Licensor and
815 | subsequently incorporated within the Work.
816 |
817 | 2. Grant of Copyright License. Subject to the terms and conditions of
818 | this License, each Contributor hereby grants to You a perpetual,
819 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
820 | copyright license to reproduce, prepare Derivative Works of,
821 | publicly display, publicly perform, sublicense, and distribute the
822 | Work and such Derivative Works in Source or Object form.
823 |
824 | 3. Grant of Patent License. Subject to the terms and conditions of
825 | this License, each Contributor hereby grants to You a perpetual,
826 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
827 | (except as stated in this section) patent license to make, have made,
828 | use, offer to sell, sell, import, and otherwise transfer the Work,
829 | where such license applies only to those patent claims licensable
830 | by such Contributor that are necessarily infringed by their
831 | Contribution(s) alone or by combination of their Contribution(s)
832 | with the Work to which such Contribution(s) was submitted. If You
833 | institute patent litigation against any entity (including a
834 | cross-claim or counterclaim in a lawsuit) alleging that the Work
835 | or a Contribution incorporated within the Work constitutes direct
836 | or contributory patent infringement, then any patent licenses
837 | granted to You under this License for that Work shall terminate
838 | as of the date such litigation is filed.
839 |
840 | 4. Redistribution. You may reproduce and distribute copies of the
841 | Work or Derivative Works thereof in any medium, with or without
842 | modifications, and in Source or Object form, provided that You
843 | meet the following conditions:
844 |
845 | (a) You must give any other recipients of the Work or
846 | Derivative Works a copy of this License; and
847 |
848 | (b) You must cause any modified files to carry prominent notices
849 | stating that You changed the files; and
850 |
851 | (c) You must retain, in the Source form of any Derivative Works
852 | that You distribute, all copyright, patent, trademark, and
853 | attribution notices from the Source form of the Work,
854 | excluding those notices that do not pertain to any part of
855 | the Derivative Works; and
856 |
857 | (d) If the Work includes a "NOTICE" text file as part of its
858 | distribution, then any Derivative Works that You distribute must
859 | include a readable copy of the attribution notices contained
860 | within such NOTICE file, excluding those notices that do not
861 | pertain to any part of the Derivative Works, in at least one
862 | of the following places: within a NOTICE text file distributed
863 | as part of the Derivative Works; within the Source form or
864 | documentation, if provided along with the Derivative Works; or,
865 | within a display generated by the Derivative Works, if and
866 | wherever such third-party notices normally appear. The contents
867 | of the NOTICE file are for informational purposes only and
868 | do not modify the License. You may add Your own attribution
869 | notices within Derivative Works that You distribute, alongside
870 | or as an addendum to the NOTICE text from the Work, provided
871 | that such additional attribution notices cannot be construed
872 | as modifying the License.
873 |
874 | You may add Your own copyright statement to Your modifications and
875 | may provide additional or different license terms and conditions
876 | for use, reproduction, or distribution of Your modifications, or
877 | for any such Derivative Works as a whole, provided Your use,
878 | reproduction, and distribution of the Work otherwise complies with
879 | the conditions stated in this License.
880 |
881 | 5. Submission of Contributions. Unless You explicitly state otherwise,
882 | any Contribution intentionally submitted for inclusion in the Work
883 | by You to the Licensor shall be under the terms and conditions of
884 | this License, without any additional terms or conditions.
885 | Notwithstanding the above, nothing herein shall supersede or modify
886 | the terms of any separate license agreement you may have executed
887 | with Licensor regarding such Contributions.
888 |
889 | 6. Trademarks. This License does not grant permission to use the trade
890 | names, trademarks, service marks, or product names of the Licensor,
891 | except as required for reasonable and customary use in describing the
892 | origin of the Work and reproducing the content of the NOTICE file.
893 |
894 | 7. Disclaimer of Warranty. Unless required by applicable law or
895 | agreed to in writing, Licensor provides the Work (and each
896 | Contributor provides its Contributions) on an "AS IS" BASIS,
897 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
898 | implied, including, without limitation, any warranties or conditions
899 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
900 | PARTICULAR PURPOSE. You are solely responsible for determining the
901 | appropriateness of using or redistributing the Work and assume any
902 | risks associated with Your exercise of permissions under this License.
903 |
904 | 8. Limitation of Liability. In no event and under no legal theory,
905 | whether in tort (including negligence), contract, or otherwise,
906 | unless required by applicable law (such as deliberate and grossly
907 | negligent acts) or agreed to in writing, shall any Contributor be
908 | liable to You for damages, including any direct, indirect, special,
909 | incidental, or consequential damages of any character arising as a
910 | result of this License or out of the use or inability to use the
911 | Work (including but not limited to damages for loss of goodwill,
912 | work stoppage, computer failure or malfunction, or any and all
913 | other commercial damages or losses), even if such Contributor
914 | has been advised of the possibility of such damages.
915 |
916 | 9. Accepting Warranty or Additional Liability. While redistributing
917 | the Work or Derivative Works thereof, You may choose to offer,
918 | and charge a fee for, acceptance of support, warranty, indemnity,
919 | or other liability obligations and/or rights consistent with this
920 | License. However, in accepting such obligations, You may act only
921 | on Your own behalf and on Your sole responsibility, not on behalf
922 | of any other Contributor, and only if You agree to indemnify,
923 | defend, and hold each Contributor harmless for any liability
924 | incurred by, or claims asserted against, such Contributor by reason
925 | of your accepting any such warranty or additional liability.
926 |
927 | END OF TERMS AND CONDITIONS
928 |
929 | APPENDIX: How to apply the Apache License to your work.
930 |
931 | To apply the Apache License to your work, attach the following
932 | boilerplate notice, with the fields enclosed by brackets "{}"
933 | replaced with your own identifying information. (Don't include
934 | the brackets!) The text should be enclosed in the appropriate
935 | comment syntax for the file format. We also recommend that a
936 | file or class name and description of purpose be included on the
937 | same "printed page" as the copyright notice for easier
938 | identification within third-party archives.
939 |
940 | Copyright {yyyy} {name of copyright owner}
941 |
942 | Licensed under the Apache License, Version 2.0 (the "License");
943 | you may not use this file except in compliance with the License.
944 | You may obtain a copy of the License at
945 |
946 | http://www.apache.org/licenses/LICENSE-2.0
947 |
948 | Unless required by applicable law or agreed to in writing, software
949 | distributed under the License is distributed on an "AS IS" BASIS,
950 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
951 | See the License for the specific language governing permissions and
952 | limitations under the License.
953 |
954 | `,
955 | },
956 | {
957 | "fyne-credits-generator",
958 | "https://github.com/lusingander/fyne-credits-generator",
959 | `
960 | MIT License
961 |
962 | Copyright (c) 2020 lusingander
963 |
964 | Permission is hereby granted, free of charge, to any person obtaining a copy
965 | of this software and associated documentation files (the "Software"), to deal
966 | in the Software without restriction, including without limitation the rights
967 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
968 | copies of the Software, and to permit persons to whom the Software is
969 | furnished to do so, subject to the following conditions:
970 |
971 | The above copyright notice and this permission notice shall be included in all
972 | copies or substantial portions of the Software.
973 |
974 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
975 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
976 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
977 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
978 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
979 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
980 | SOFTWARE.
981 | `,
982 | },
983 | }
984 |
--------------------------------------------------------------------------------