aboutsummaryrefslogtreecommitdiff
path: root/internal/tui/app.go
blob: 066fa284a19ea5b6eab073ab719d6b3706443ecb (plain)
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
package tui

import (
	"os"

	"tui-ascii-mapper/internal/config"
	"tui-ascii-mapper/internal/mapio"
	"tui-ascii-mapper/internal/model"

	"github.com/charmbracelet/bubbles/textinput"
	tea "github.com/charmbracelet/bubbletea"
)

type FilePickerState struct {
	Files    []os.DirEntry
	CurDir   string
	Selected int
	PopupX   int
	PopupY   int
	ListTop  int
}

type ColorPickerState struct {
	Active   bool
	Cursor   model.Point
	Selected []string
	ForText  bool
	GridX    int
	GridY    int
}

type AppModel struct {
	map_        *model.Map
	rootMap     *model.Map
	cursor      model.Point
	offset      model.Point
	prevCursor  model.Point

	tool       model.Tool
	selected   int
	brushWidth int
	unicode    bool
	colorMode  bool
	fillShapes bool

	mode   model.Mode
	dialog model.DialogType

	ti        textinput.Model

	lineStart     model.Point
	linePreview   []model.Point
	rectStart     model.Point
	rectPreview   []model.Point
	circleCenter  model.Point
	circlePreview []model.Point

	textEditing      bool
	textInput        textinput.Model
	textColor        string
	movingLabel      int
	dragLabelOrigin  model.Point
	dragMouseOrigin  model.Point
	textCursorStart  model.Point

	mouseDown  bool
	mouseBtn   int
	mouseStart model.Point
	lastPaint  model.Point
	drawHeld   bool
	eraseHeld  bool

	undo       *model.UndoStack

	width      int
	height     int
	quitting   bool
	cfg        config.Config
	dialogMsg  string

	colorPicker   *ColorPickerState
	dirty         bool
	undoPosAtSave int
	hotkeySelect  [10]int
	palettePage   int
	filePicker    *FilePickerState
}

func (m *AppModel) curMap() *model.Map { return m.map_ }

func (m *AppModel) curPalette() []model.Terrain {
	if m.map_ != nil {
		return m.map_.Palette
	}
	return nil
}

func NewAppModel(cfg config.Config) *AppModel {
	palette := make([]model.Terrain, len(cfg.Symbols))
	copy(palette, cfg.Symbols)
	root := model.NewMap("untitled", cfg.DefaultMapWidth, cfg.DefaultMapHeight, palette)

	undo := &model.UndoStack{}
	undo.Push(root)
	undoAtSave := undo.Pos()

	ti := textinput.New()
	ti.Placeholder = ""
	ti.Prompt = ""
	ti.CharLimit = 64

	textTI := textinput.New()
	textTI.Placeholder = ""
	textTI.Prompt = ""
	textTI.CharLimit = 256

	return &AppModel{
		map_:      root,
		rootMap:   root,
		cursor:    model.Point{X: 0, Y: 0},
		prevCursor: model.Point{X: -1, Y: -1},
		tool:      model.ToolBrush,
		brushWidth: 1,
		selected:  0,
		unicode:   true,
		colorMode: true,
		mode:      model.ModeNormal,
		undo:      undo,
		cfg:       cfg,
		ti:        ti,
		textInput: textTI,
		movingLabel: -1,
		lastPaint:   model.Point{X: -1, Y: -1},
		undoPosAtSave: undoAtSave,
	}
}

func (m *AppModel) Init() tea.Cmd {
	return tea.Batch(
		textinput.Blink,
		tea.EnableMouseCellMotion,
	)
}

func (m *AppModel) loadMapCmd(path string) tea.Cmd {
	return func() tea.Msg {
		md, err := mapio.DeserializeMap(path)
		return mapLoadedMsg{data: md, err: err}
	}
}

type mapLoadedMsg struct {
	data *model.Map
	err  error
}