File: palettemap.go

package info (click to toggle)
golang-github-gcla-gowid 1.4.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 1,456 kB
  • sloc: makefile: 4
file content (159 lines) | stat: -rw-r--r-- 4,059 bytes parent folder | download
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: