From d597f79a16b84e357a157d5468f10d9885dc8d0a Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Mon, 4 Sep 2023 02:35:01 -0400 Subject: [PATCH] hnnggg icons --- assets/mime-generic-medium.png | Bin 0 -> 912 bytes assets/mime-generic-medium.xcf | Bin 0 -> 80486 bytes assets/mime-medium.png | Bin 0 -> 17867 bytes go.mod | 2 +- go.sum | 4 +- icons.go | 84 ++++++++++++++++++--------------- theme.go | 77 +++++++++++++++++++++++++++++- 7 files changed, 126 insertions(+), 41 deletions(-) create mode 100644 assets/mime-generic-medium.png create mode 100644 assets/mime-generic-medium.xcf create mode 100644 assets/mime-medium.png diff --git a/assets/mime-generic-medium.png b/assets/mime-generic-medium.png new file mode 100644 index 0000000000000000000000000000000000000000..54a1194ea303427a56d763800b4694f097c5f490 GIT binary patch literal 912 zcmV;B18@9^P)001Be1^@s6m49>f000A5Nkl3D7P7hdWJF zuh)Tw@W;RyfCkX$pl8;+xxTgv;B|RtZ@(`z5G4_M5I6iEvicCm$H&cu850&UYyX34 zZzO{CwN>1`d9@7SQfMF=BA0rxNMmQ}e@jsmiX{NR=G*t0#>d2adPs!9M#lePt4T(N z1_1zzb5m{i7U!nGOztJ`Kh|82U+yn|_;N_;*oV7Vql_%;|8VE%%TOqmFcuxgMm7%s zSV~M|Bb&!kV%l^k^Wy14eENK-8Qa=a0N@S)1;8J2ofon%!%?kf`?>YCRqTKLCFOtV z2q+3pw9Od3(y!V-zL&Y#Ba`-tiv=&k>@pS|w)B5kW^q0d5nSwO;HXxU7H!xnzmE(J zYEo=NmvS30IZPycQQwKS(kjCMU^y|ZUh8eM(#-xYxK#s!F(}zQlx!YMu)$cfHe{@G zBfNVABiPIHv8Kr8V^FerEYHU@HgqDD@xOEp$QS5j6aGfo-fap_=v6`L#$=H`2jmkg z+q-Hrx+eUKUTFG2)Qtu#k6}iJ2EiCZDj5d=wdd%s34a~KnAxdh9O+C>?L|HOtybHf z={f}$iX}|kxTaZzFJv@E_!m)dsbpN^Z*HeEIn2f;or!>A4QM1T5*&%pC<;23g2f0Z zZmsS7Sd8|-{vnl&xA|WbAs46}|A%C2K;9tOGL4R5{8Iy_GdZBuuPn?UoymbQrrLa5 z^Sp)srFX#uv9d6OH(T%8dhx#FDVW!QM6jt=Dgc1l*d(fzifQloF-)OY!maV^~10 literal 0 HcmV?d00001 diff --git a/assets/mime-generic-medium.xcf b/assets/mime-generic-medium.xcf new file mode 100644 index 0000000000000000000000000000000000000000..3c02bd8a5bdfc97ea8616c31b24e048032ca00ae GIT binary patch literal 80486 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 G^M3#{r&j6! literal 0 HcmV?d00001 diff --git a/assets/mime-medium.png b/assets/mime-medium.png new file mode 100644 index 0000000000000000000000000000000000000000..c4b56e1b96b500b0b0d2de479d8323c75e7519fb GIT binary patch literal 17867 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 literal 0 HcmV?d00001 diff --git a/go.mod b/go.mod index 12edc19..3a1e761 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,6 @@ module git.tebibyte.media/tomo/aluminum go 1.20 require ( - git.tebibyte.media/tomo/tomo v0.26.1 + git.tebibyte.media/tomo/tomo v0.27.0 golang.org/x/image v0.11.0 ) diff --git a/go.sum b/go.sum index 3d1664a..12b71c7 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -git.tebibyte.media/tomo/tomo v0.26.1 h1:V5ciRuixMYb79aAawgquFEfJ1icyEmMKBKFPWwi94NE= -git.tebibyte.media/tomo/tomo v0.26.1/go.mod h1:C9EzepS9wjkTJjnZaPBh22YvVPyA4hbBAJVU20Rdmps= +git.tebibyte.media/tomo/tomo v0.27.0 h1:gCwxQe0qm1hZLfHkMI3OccNMC/lB1cfs4BbaMz/bXug= +git.tebibyte.media/tomo/tomo v0.27.0/go.mod h1:C9EzepS9wjkTJjnZaPBh22YvVPyA4hbBAJVU20Rdmps= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= diff --git a/icons.go b/icons.go index f7aaf08..00ab1ed 100644 --- a/icons.go +++ b/icons.go @@ -1,56 +1,66 @@ package aluminum -import "fmt" -import "io/fs" +import "io" import "image" -import _ "image/png" import "git.tebibyte.media/tomo/tomo" -import "git.tebibyte.media/tomo/tomo/data" import "git.tebibyte.media/tomo/tomo/theme" import "git.tebibyte.media/tomo/tomo/canvas" -type iconSet struct { - fs fs.FS - icons map[theme.IconSize] map[string] canvas.Texture +type iconIndex interface { + ~int | ~string } -func (this *iconSet) get (size theme.IconSize, name string) canvas.Texture { - texture := this.icons[size][name] - if texture != nil { - return texture - } else { - texture = nil - defer func () { this.icons[size][name] = texture } () +type iconEntry[T iconIndex] struct { + position image.Point + index T +} - file, err := this.fs.Open(fmt.Sprint(size, "/", name, ".png")) - if err != nil { return texture } - defer file.Close() - image, _, err := image.Decode(file) - if err != nil { return texture } - - texture = tomo.NewTexture(image) - return texture +func i[T iconIndex] (x, y int, index T) iconEntry[T] { + return iconEntry[T] { + position: image.Pt(x, y), + index: index, } } -func (this *iconSet) Icon (id theme.Icon, size theme.IconSize) canvas.Texture { - return this.get(size, fmt.Sprint("actions/", id)) +type iconSet[T iconIndex] struct { + icons map[theme.IconSize] map[T] canvas.Texture } -func (this *iconSet) MimeIcon (mime data.Mime, size theme.IconSize) canvas.Texture { - texture := this.get(size, fmt.Sprint("mime/", mime)) - if texture != nil { - return texture - } else { - return this.get(size, fmt.Sprint("mime-generic/", mime.Type)) - } +func (this *iconSet[T]) Get (index T,size theme.IconSize) canvas.Texture { + return this.icons[size][index] } -func (this *iconSet) ApplicationIcon (id theme.ApplicationIcon, size theme.IconSize) canvas.Texture { - texture := this.get(size, fmt.Sprint("app/", id.Name)) - if texture != nil { - return texture - } else { - return this.get(size, fmt.Sprint("app-generic/", id.Role)) +func (this *iconSet[T]) Init ( + small, medium, large io.Reader, + rows, columns int, + icons ...iconEntry[T], +) { + this.icons = make(map[theme.IconSize] map[T] canvas.Texture) + this.initFor(theme.IconSizeSmall, small, rows, columns, icons...) + this.initFor(theme.IconSizeMedium, medium, rows, columns, icons...) + this.initFor(theme.IconSizeLarge, large, rows, columns, icons...) +} + +func (this *iconSet[T]) initFor ( + size theme.IconSize, + file io.Reader, + rows, columns int, + icons ...iconEntry[T], +) { + if file == nil { return } + + atlasImage, _, err := image.Decode(file) + if err != nil { panic(err) } + atlas := tomo.NewTexture(atlasImage) + cellW := atlasImage.Bounds().Dx() / columns + cellH := atlasImage.Bounds().Dy() / rows + cellSize := image.Rect(0, 0, cellW, cellH) + + this.icons[size] = make(map[T] canvas.Texture) + for _, icon := range icons { + offset := image.Pt ( + icon.position.X * cellW, + icon.position.Y * cellH) + this.icons[size][icon.index] = atlas.Clip(cellSize.Add(offset)) } } diff --git a/theme.go b/theme.go index a287fbb..c50862d 100644 --- a/theme.go +++ b/theme.go @@ -1,12 +1,22 @@ package aluminum +import "bytes" import "image" +import _ "embed" +import _ "image/png" import "image/color" import "git.tebibyte.media/tomo/tomo" import "golang.org/x/image/font/basicfont" +import "git.tebibyte.media/tomo/tomo/data" import "git.tebibyte.media/tomo/tomo/theme" import "git.tebibyte.media/tomo/tomo/input" import "git.tebibyte.media/tomo/tomo/event" +import "git.tebibyte.media/tomo/tomo/canvas" + +//go:embed assets/mime-generic-medium.png +var genericMimeIconsMedium []byte +//go:embed assets/mime-medium.png +var mimeIconsMedium []byte func hex (color uint32) (c color.RGBA) { c.A = uint8(color) @@ -45,7 +55,12 @@ var gutterColor = hex(0xbfc6d1FF) var gutterColorHovered = hex(0xc5cbd6FF) type Theme struct { - iconSet + unpackedIcons bool + icons iconSet[theme.Icon] + mimeIcons iconSet[string] + genericMimeIcons iconSet[string] + appIcons iconSet[string] + genericAppIcons iconSet[tomo.ApplicationRole] } func (this *Theme) RGBA (id theme.Color) (r, g, b, a uint32) { @@ -215,7 +230,67 @@ func (this *Theme) Apply (object tomo.Object, role theme.Role) event.Cookie { } box.SetBorder(border...) box.SetColor(buttonColor) + + case "Icon": + switch role.Variant { + case "small": box.SetMinimumSize(image.Pt(16, 16)) + case "medium": box.SetMinimumSize(image.Pt(32, 32)) + case "large": box.SetMinimumSize(image.Pt(48, 48)) + } } return event.MultiCookie() } +func (this *Theme) Icon (id theme.Icon, size theme.IconSize) canvas.Texture { + this.ensureIcons() + return this.icons.Get(id, size) +} + +func (this *Theme) MimeIcon (mime data.Mime, size theme.IconSize) canvas.Texture { + this.ensureIcons() + texture := this.mimeIcons.Get(mime.String(), size) + if texture != nil { + return texture + } else { + return this.genericMimeIcons.Get(mime.Type, size) + } +} + +func (this *Theme) ApplicationIcon (id theme.ApplicationIcon, size theme.IconSize) canvas.Texture { + this.ensureIcons() + texture := this.appIcons.Get(id.Name, size) + if texture != nil { + return texture + } else { + return this.genericAppIcons.Get(id.Role, size) + } +} + +func (this *Theme) ensureIcons () { + if this.unpackedIcons { return } + this.unpackedIcons = true + + // this.icons.Init () // TODO + this.mimeIcons.Init ( + nil, // TODO + bytes.NewReader(mimeIconsMedium), + nil, // TODO + 32, 12, + + // TODO + ) + this.genericMimeIcons.Init ( + nil, // TODO + bytes.NewReader(genericMimeIconsMedium), + nil, // TODO + 1, 5, + + i(0, 0, "text"), + i(1, 0, "image"), + i(2, 0, "audio"), + i(3, 0, "video"), + i(4, 0, "application"), + ) + // this.appIcons.Init () // TODO + // this.genericAppIcons.Init () // TODO +}