ted/session.go
Leon Mika 9267fc92a7 A few minor feature
Added automatic resizing of the columns when loading a model
Added colouring of the currently search for cell
2024-09-24 12:45:22 +10:00

185 lines
4.4 KiB
Go

package main
import (
"regexp"
"github.com/lmika/ted/ui"
)
const (
bestFixRightMargin = 2
bestFixMinColumnSize = 8
bestFixMaxColumnSize = 32
)
// The session is responsible for managing the UI and the model and handling
// the interaction between the two and the user.
type Session struct {
model Model
Source ModelSource
Frame *Frame
Commands *CommandMapping
UIManager *ui.Ui
modelController *ModelViewCtrl
pasteBoard RWModel
LastSearch *regexp.Regexp
}
func NewSession(uiManager *ui.Ui, frame *Frame, source ModelSource) *Session {
model := NewSingleCellStdModel()
session := &Session{
model: model,
Source: source,
Frame: frame,
Commands: NewCommandMapping(),
UIManager: uiManager,
modelController: NewGridViewModel(model),
pasteBoard: NewSingleCellStdModel(),
}
frame.SetModel(&SessionGridModel{session.modelController})
session.Commands.RegisterViewCommands()
session.Commands.RegisterViewKeyBindings()
// Also assign this session with the frame
frame.Session = session
return session
}
// LoadFromSource loads the model from the source, replacing the existing model
func (session *Session) LoadFromSource() {
newModel, err := session.Source.Read()
if err != nil {
session.Frame.Message(err.Error())
return
}
session.model = newModel
session.modelController.SetModel(newModel)
}
func (sesion *Session) ResizeToBestFit() {
mr, mc := sesion.model.Dimensions()
colMaxSize := make([]int, mc)
for c := 0; c < mc; c++ {
colMaxSize[c] = bestFixMinColumnSize
for r := 0; r < mr; r++ {
colMaxSize[c] = max(colMaxSize[c], len(sesion.model.CellValue(r, c))+bestFixRightMargin)
}
}
for c, ml := range colMaxSize {
sesion.modelController.SetColAttrs(c, SliceAttr{
Size: min(ml, bestFixMaxColumnSize),
})
}
}
// Input from the frame
func (session *Session) KeyPressed(key rune, mod int) {
// Add the mod key modifier
if mod&ui.ModKeyAlt != 0 {
key |= ModAlt
}
cmd := session.Commands.KeyMapping(key)
if cmd != nil {
err := cmd.Do(&CommandContext{session, nil})
if err != nil {
session.Frame.ShowMessage(err.Error())
}
}
}
func (s *Session) SetLastSearch(re *regexp.Regexp) {
s.LastSearch = re
s.modelController.lastSearchRegexp = re
}
// The command context used by the session
type CommandContext struct {
session *Session
args []string
}
func (scc *CommandContext) WithArgs(args []string) *CommandContext {
return &CommandContext{
session: scc.session,
args: args,
}
}
func (scc *CommandContext) Args() []string {
return scc.args
}
func (scc *CommandContext) ModelVC() *ModelViewCtrl {
return scc.session.modelController
}
func (scc *CommandContext) Session() *Session {
return scc.session
}
func (scc *CommandContext) Frame() *Frame {
return scc.session.Frame
}
// Error displays an error if err is not nil
func (scc *CommandContext) Error(err error) {
scc.Frame().Error(err)
}
// Session grid model
type SessionGridModel struct {
GridViewModel *ModelViewCtrl
}
// Returns the size of the grid model (width x height)
func (sgm *SessionGridModel) Dimensions() (int, int) {
rs, cs := sgm.GridViewModel.Model().Dimensions()
return cs, rs
}
// Returns the size of the particular column. If the size is 0, this indicates that the column is hidden.
func (sgm *SessionGridModel) ColWidth(col int) int {
return sgm.GridViewModel.ColAttrs(col).Size
}
// Returns the size of the particular row. If the size is 0, this indicates that the row is hidden.
func (sgm *SessionGridModel) RowHeight(row int) int {
return sgm.GridViewModel.RowAttrs(row).Size
}
// Returns the value of the cell a position X, Y
func (sgm *SessionGridModel) CellValue(x int, y int) string {
return sgm.GridViewModel.Model().CellValue(y, x)
}
func (sgm *SessionGridModel) CellAttributes(x int, y int) (fg, bg ui.Attribute) {
if sgm.GridViewModel.lastSearchRegexp != nil {
if sgm.GridViewModel.lastSearchRegexp.MatchString(sgm.GridViewModel.Model().CellValue(y, x)) {
return ui.ColorMagenta, 0
}
}
rowAttrs := sgm.GridViewModel.RowAttrs(y)
colAttrs := sgm.GridViewModel.ColAttrs(y)
if rowAttrs.Marker != MarkerNone {
return markerAttributes[rowAttrs.Marker], 0
} else if colAttrs.Marker != MarkerNone {
return markerAttributes[colAttrs.Marker], 0
}
return 0, 0
}
var markerAttributes = map[Marker]ui.Attribute{
MarkerRed: ui.ColorRed,
MarkerGreen: ui.ColorGreen,
MarkerBlue: ui.ColorBlue,
}