|
|
@@ -2,16 +2,83 @@ package editor
|
|
|
|
|
|
import (
|
|
|
"moose/internal/layout"
|
|
|
+ "moose/internal/buffer"
|
|
|
+ "fmt"
|
|
|
+ "strings"
|
|
|
+ "github.com/gdamore/tcell/v3/color"
|
|
|
)
|
|
|
|
|
|
-func (m *Model) DrawLayout(lm *layout.LayoutManager, rect layout.Rect) {
|
|
|
-
|
|
|
+func (m *Model) Draw() {
|
|
|
+ m.DrawWorkspace(&m.LM.Workspaces[m.LM.ActiveIdx], layout.RectFromScren(m.Screen))
|
|
|
}
|
|
|
|
|
|
func (m *Model) DrawWorkspace(w *layout.Workspace, rect layout.Rect) {
|
|
|
-
|
|
|
+ m.DrawContainer(&w.RootContainer, rect)
|
|
|
}
|
|
|
|
|
|
-func (m *Model) DrawContainer(c *layout.Container[[]int], rect layout.Rect) {
|
|
|
+func (m *Model) DrawContainer(c *layout.Container[layout.ContainerBuffers], rect layout.Rect) {
|
|
|
+ length := len(c.Children)
|
|
|
+ rect = layout.RectDivide(rect, c.Split, length)
|
|
|
+
|
|
|
+ for i, child := range c.Children {
|
|
|
+ switch child.(type) {
|
|
|
+ case layout.ContainerBuffers: {
|
|
|
+ cb := child.(layout.ContainerBuffers)
|
|
|
+ m.DrawContainerBuffers(&cb, layout.RectDisplace(rect, c.Split, i))
|
|
|
+ }
|
|
|
+ case layout.Container[layout.ContainerBuffers]: {
|
|
|
+ c := child.(layout.Container[layout.ContainerBuffers])
|
|
|
+ m.DrawContainer(&c, layout.RectDisplace(rect, c.Split, i))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
+func (m *Model) DrawContainerBuffers(c *layout.ContainerBuffers, rect layout.Rect) {
|
|
|
+ m.DrawBuffer(&m.BM.Buffers[c.Buffers[c.ActiveIdx]], c.Buffers[c.ActiveIdx] == m.BM.CurrentIdx, rect)
|
|
|
}
|
|
|
+
|
|
|
+func (m *Model) DrawBuffer(buf *buffer.Buffer, isActive bool, rect layout.Rect) {
|
|
|
+ primary := buf.CM.Cursors[buf.CM.PrimaryIdx]
|
|
|
+ curLine, _ := buffer.LineCol(buf, primary.Offset)
|
|
|
+ buf.ScrollToShow(curLine, rect.Height)
|
|
|
+
|
|
|
+ startOffset := buffer.OffsetForLine(buf, buf.TopLine)
|
|
|
+ endOffset := buf.Rope.Len()
|
|
|
+ if endLine := buf.TopLine + rect.Height; endLine < buffer.LineCount(buf) {
|
|
|
+ endOffset = buffer.OffsetForLine(buf, endLine)
|
|
|
+ }
|
|
|
+
|
|
|
+ visible := string(buf.Rope.Slice(startOffset, endOffset))
|
|
|
+ table := strings.SplitAfter(visible, "\n")
|
|
|
+ for j, line := range table {
|
|
|
+ if j + 1 > rect.Height { break }
|
|
|
+
|
|
|
+ nums := fmt.Sprintf("%4d ", j + buf.TopLine)
|
|
|
+ r := []rune(nums + expandTabs(line))
|
|
|
+ if len(r) + 1 > rect.Width {
|
|
|
+ r = r[:rect.Width]
|
|
|
+ }
|
|
|
+
|
|
|
+ m.Screen.PutStrStyled(rect.X, rect.Y + j, string(r), m.Style)
|
|
|
+ }
|
|
|
+
|
|
|
+ if isActive {
|
|
|
+ for _, cur := range buf.CM.Cursors {
|
|
|
+ line, col := buffer.LineCol(buf, cur.Offset)
|
|
|
+ screenLine := line - buf.TopLine
|
|
|
+ if screenLine < 0 || screenLine + 1 > rect.Height { continue }
|
|
|
+
|
|
|
+ visCol := visualCol(buffer.LineText(buf, line), col)
|
|
|
+ if visCol + 1 > rect.Width { continue }
|
|
|
+
|
|
|
+ ch := buffer.RuneAt(buf, cur.Offset)
|
|
|
+
|
|
|
+ if m.Mode == ModeWrite {
|
|
|
+ m.Screen.SetContent(rect.X + visCol + 5, rect.Y + screenLine, ch, nil, m.Style.Reverse(true))
|
|
|
+ } else {
|
|
|
+ m.Screen.SetContent(rect.X + visCol + 5, rect.Y + screenLine, ch, nil, m.Style.Reverse(true).Foreground(color.Gray))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|