Replace Unicode icons with PNG icons in StatusBar
- Move icons/ to internal/ui/icons/ for go:embed - Renderer.loadIcons() loads PNGs from embedded filesystem - drawStatusBar() uses drawPng() for cut/copy/paste/search/conflict icons - Icons are 16dp, rendered from 48x48 PNGs (2x density)
|
Before Width: | Height: | Size: 444 B After Width: | Height: | Size: 444 B |
|
Before Width: | Height: | Size: 301 B After Width: | Height: | Size: 301 B |
|
Before Width: | Height: | Size: 778 B After Width: | Height: | Size: 778 B |
|
Before Width: | Height: | Size: 347 B After Width: | Height: | Size: 347 B |
|
Before Width: | Height: | Size: 485 B After Width: | Height: | Size: 485 B |
|
Before Width: | Height: | Size: 552 B After Width: | Height: | Size: 552 B |
|
|
@ -1,8 +1,12 @@
|
|||
package ui
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"embed"
|
||||
"image"
|
||||
"image/color"
|
||||
_ "image/png"
|
||||
"strings"
|
||||
|
||||
"gioui.org/f32"
|
||||
"gioui.org/layout"
|
||||
|
|
@ -15,6 +19,9 @@ import (
|
|||
"golang.org/x/image/math/fixed"
|
||||
)
|
||||
|
||||
//go:embed icons/*.png
|
||||
var iconFS embed.FS
|
||||
|
||||
// StateReader provides access to scale and window dimensions from State.
|
||||
// Implemented by editor.State to avoid import cycles.
|
||||
type StateReader interface {
|
||||
|
|
@ -28,11 +35,31 @@ type Renderer struct {
|
|||
theme Theme
|
||||
shp *text.Shaper
|
||||
state StateReader // read-only access to State for scale/window size
|
||||
icons map[string]image.Image // loaded PNG icons
|
||||
}
|
||||
|
||||
// New creates a new Renderer.
|
||||
func New(th Theme, shp *text.Shaper) *Renderer {
|
||||
return &Renderer{theme: th, shp: shp}
|
||||
r := &Renderer{theme: th, shp: shp, icons: make(map[string]image.Image)}
|
||||
r.loadIcons()
|
||||
return r
|
||||
}
|
||||
|
||||
// loadIcons loads all PNG icons from the embedded filesystem.
|
||||
func (r *Renderer) loadIcons() {
|
||||
files := []string{"cut.png", "copy.png", "paste.png", "search.png", "conflict.png", "wrapOn.png", "wrapOff.png"}
|
||||
for _, filename := range files {
|
||||
data, err := iconFS.ReadFile(filename)
|
||||
if err != nil {
|
||||
continue // skip missing icons
|
||||
}
|
||||
img, _, err := image.Decode(bytes.NewReader(data))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
name := strings.TrimSuffix(filename, ".png")
|
||||
r.icons[name] = img
|
||||
}
|
||||
}
|
||||
|
||||
// SetState sets the State reference for the Renderer.
|
||||
|
|
@ -167,22 +194,23 @@ func (r *Renderer) drawStatusBar(gtx layout.Context, sb StatusBar, _ WindowConst
|
|||
// Left side: Cut, Copy, Paste icons (always visible)
|
||||
leftX := reg.X + Dp(8)
|
||||
iconY := iconsLineY
|
||||
iconSize := Dp(16) // 16dp icons
|
||||
|
||||
r.drawText(gtx, th.Shaper, "✂", r.theme.FontSize, leftX, iconY, color.NRGBA{R: 0, G: 0, B: 0, A: 255})
|
||||
leftX += Dp(36)
|
||||
r.drawText(gtx, th.Shaper, "⎘", r.theme.FontSize, leftX, iconY, color.NRGBA{R: 0, G: 0, B: 0, A: 255})
|
||||
leftX += Dp(36)
|
||||
r.drawText(gtx, th.Shaper, "⎘", r.theme.FontSize, leftX, iconY, color.NRGBA{R: 0, G: 0, B: 0, A: 255})
|
||||
r.drawPng(gtx, r.icons["cut"], leftX, iconY, iconSize, iconSize, color.NRGBA{R: 0, G: 0, B: 0, A: 255})
|
||||
leftX += Dp(28)
|
||||
r.drawPng(gtx, r.icons["copy"], leftX, iconY, iconSize, iconSize, color.NRGBA{R: 0, G: 0, B: 0, A: 255})
|
||||
leftX += Dp(28)
|
||||
r.drawPng(gtx, r.icons["paste"], leftX, iconY, iconSize, iconSize, color.NRGBA{R: 0, G: 0, B: 0, A: 255})
|
||||
leftX += Dp(12)
|
||||
|
||||
// Right side: Conflict (conditional), Search (always visible)
|
||||
rightX := reg.X + reg.W - Dp(8)
|
||||
if sb.ConflictIcon {
|
||||
rightX -= Dp(36)
|
||||
r.drawText(gtx, th.Shaper, "⚠", r.theme.FontSize, rightX, iconY, color.NRGBA{R: 0, G: 0, B: 0, A: 255})
|
||||
rightX -= Dp(28)
|
||||
r.drawPng(gtx, r.icons["conflict"], rightX, iconY, iconSize, iconSize, color.NRGBA{R: 0, G: 0, B: 0, A: 255})
|
||||
}
|
||||
rightX -= Dp(36)
|
||||
r.drawText(gtx, th.Shaper, "🔍", r.theme.FontSize, rightX, iconY, color.NRGBA{R: 0, G: 0, B: 0, A: 255})
|
||||
rightX -= Dp(28)
|
||||
r.drawPng(gtx, r.icons["search"], rightX, iconY, iconSize, iconSize, color.NRGBA{R: 0, G: 0, B: 0, A: 255})
|
||||
|
||||
c.Pop()
|
||||
}
|
||||
|
|
|
|||