feat(ui): Add diagonal stripe pattern to disabled modules

Replaced lock icon-only approach with diagonal stripe overlay for better visual distinction:
- Added static (non-animated) diagonal stripe pattern to disabled tiles
- Stripes use semi-transparent dark overlay (similar to queue progress bars)
- Thicker diagonal lines (8px spacing instead of 4px)
- Pattern clearly distinguishes disabled from enabled modules
- Kept lock icon as secondary indicator

This addresses the issue where adaptive text colors made it difficult to distinguish available vs. disabled modules. The stripe pattern provides immediate visual feedback without relying solely on color dimming.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Stu Leak 2025-12-31 12:42:18 -05:00
parent 89824f7859
commit 776ec1f672

View File

@ -2,6 +2,7 @@ package ui
import (
"fmt"
"image"
"image/color"
"strings"
"time"
@ -176,11 +177,35 @@ func (m *ModuleTile) CreateRenderer() fyne.WidgetRenderer {
lockIcon.Hide()
}
// Diagonal stripe overlay for disabled modules
disabledStripe := canvas.NewRaster(func(w, h int) image.Image {
if m.enabled {
return nil
}
img := image.NewRGBA(image.Rect(0, 0, w, h))
// Semi-transparent dark stripes
darkStripe := color.NRGBA{R: 0, G: 0, B: 0, A: 100}
lightStripe := color.NRGBA{R: 0, G: 0, B: 0, A: 30}
for y := 0; y < h; y++ {
for x := 0; x < w; x++ {
// Thicker diagonal stripes (dividing by 8 instead of 4)
if ((x + y) / 8 % 2) == 0 {
img.Set(x, y, darkStripe)
} else {
img.Set(x, y, lightStripe)
}
}
}
return img
})
return &moduleTileRenderer{
tile: m,
bg: bg,
label: txt,
lockIcon: lockIcon,
tile: m,
bg: bg,
label: txt,
lockIcon: lockIcon,
disabledStripe: disabledStripe,
}
}
@ -191,14 +216,23 @@ func (m *ModuleTile) Tapped(*fyne.PointEvent) {
}
type moduleTileRenderer struct {
tile *ModuleTile
bg *canvas.Rectangle
label *canvas.Text
lockIcon *canvas.Text
tile *ModuleTile
bg *canvas.Rectangle
label *canvas.Text
lockIcon *canvas.Text
disabledStripe *canvas.Raster
}
func (r *moduleTileRenderer) Layout(size fyne.Size) {
r.bg.Resize(size)
r.bg.Move(fyne.NewPos(0, 0))
// Stripe overlay covers entire tile
if r.disabledStripe != nil {
r.disabledStripe.Resize(size)
r.disabledStripe.Move(fyne.NewPos(0, 0))
}
// Center the label by positioning it in the middle
labelSize := r.label.MinSize()
r.label.Resize(labelSize)
@ -260,12 +294,15 @@ func (r *moduleTileRenderer) Refresh() {
if r.lockIcon != nil {
r.lockIcon.Refresh()
}
if r.disabledStripe != nil {
r.disabledStripe.Refresh()
}
}
func (r *moduleTileRenderer) Destroy() {}
func (r *moduleTileRenderer) Objects() []fyne.CanvasObject {
return []fyne.CanvasObject{r.bg, r.label, r.lockIcon}
return []fyne.CanvasObject{r.bg, r.disabledStripe, r.label, r.lockIcon}
}
// TintedBar creates a colored bar container