1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
// Copyright 2019-2022 Graham Clark. All rights reserved. Use of this source
// code is governed by the MIT license that can be found in the LICENSE
// file.
// Package palettemap provides a widget that can change the color and style of an inner widget.
package palettemap
import (
"fmt"
"github.com/gcla/gowid"
)
//======================================================================
type IPaletteMapper interface {
GetMappedColor(string) (string, bool)
}
type Map map[string]string
func (p Map) GetMappedColor(key string) (x string, y bool) {
x, y = p[key]
return
}
type IPaletteMap interface {
FocusMap() IPaletteMapper
NotFocusMap() IPaletteMapper
}
type IWidget interface {
gowid.ICompositeWidget
IPaletteMap
}
// Widget that adjusts the palette used - if the rendering context provides for a foreground
// color of red (when focused), this widget can provide a map from red -> green to change its
// display
type Widget struct {
gowid.IWidget
focusMap IPaletteMapper
notFocusMap IPaletteMapper
*gowid.Callbacks
gowid.SubWidgetCallbacks
}
func New(inner gowid.IWidget, focusMap Map, notFocusMap Map) *Widget {
res := &Widget{
IWidget: inner,
focusMap: focusMap,
notFocusMap: notFocusMap,
}
res.SubWidgetCallbacks = gowid.SubWidgetCallbacks{CB: &res.Callbacks}
var _ gowid.IWidget = res
var _ gowid.ICompositeWidget = res
var _ IWidget = res
return res
}
func (w *Widget) String() string {
return fmt.Sprintf("palettemap[%v]", w.SubWidget())
}
func (w *Widget) SubWidget() gowid.IWidget {
return w.IWidget
}
func (w *Widget) SetSubWidget(inner gowid.IWidget, app gowid.IApp) {
w.IWidget = inner
gowid.RunWidgetCallbacks(w, gowid.SubWidgetCB{}, app, w)
}
func (w *Widget) FocusMap() IPaletteMapper {
return w.focusMap
}
func (w *Widget) NotFocusMap() IPaletteMapper {
return w.notFocusMap
}
func (w *Widget) SubWidgetSize(size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) gowid.IRenderSize {
return w.SubWidget().RenderSize(size, focus, app)
}
func (w *Widget) RenderSize(size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) gowid.IRenderBox {
return w.SubWidget().RenderSize(size, focus, app)
}
func (w *Widget) Render(size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) gowid.ICanvas {
return Render(w, size, focus, app)
}
func (w *Widget) UserInput(ev interface{}, size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) bool {
return gowid.UserInputIfSelectable(w.IWidget, ev, size, focus, app)
}
//''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
func Render(w IWidget, size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) gowid.ICanvas {
newAttrs := make(gowid.Palette)
var mapToUse IPaletteMapper
if focus.Focus {
mapToUse = w.FocusMap()
} else {
mapToUse = w.NotFocusMap()
}
// walk through palette, making a copy with changes as dictated by either the focus map or
// not-focus map.
app.RangeOverPalette(func(k string, v gowid.ICellStyler) bool {
done := false
if newk, ok := mapToUse.GetMappedColor(k); ok {
if newval, ok := app.CellStyler(newk); ok {
newAttrs[k] = newval
done = true
}
}
if !done {
newAttrs[k] = v
}
return true
})
override := NewOverride(app, &newAttrs)
res := w.SubWidget().Render(size, focus, override)
return res
}
//======================================================================
type PaletteOverride struct {
gowid.IApp
Palette gowid.IPalette
}
func NewOverride(app gowid.IApp, newattrs gowid.IPalette) *PaletteOverride {
return &PaletteOverride{
IApp: app,
Palette: newattrs,
}
}
func (a *PaletteOverride) CellStyler(name string) (gowid.ICellStyler, bool) {
p, ok := a.Palette.CellStyler(name)
if ok {
return p, ok
}
return a.IApp.CellStyler(name)
}
func (a *PaletteOverride) RangeOverPalette(f func(k string, v gowid.ICellStyler) bool) {
a.Palette.RangeOverPalette(f)
}
//======================================================================
// Local Variables:
// mode: Go
// fill-column: 110
// End:
|