mirror of
https://github.com/bloeys/gopad.git
synced 2025-12-29 06:58:21 +00:00
Starting custom editor window
This commit is contained in:
189
editor.go
Executable file
189
editor.go
Executable file
@ -0,0 +1,189 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/bloeys/gopad/settings"
|
||||
"github.com/inkyblackness/imgui-go/v4"
|
||||
)
|
||||
|
||||
const (
|
||||
linesPerNode int = 100
|
||||
)
|
||||
|
||||
type Line struct {
|
||||
chars []rune
|
||||
}
|
||||
|
||||
type LinesNode struct {
|
||||
Lines [linesPerNode]Line
|
||||
Next *LinesNode
|
||||
}
|
||||
|
||||
type Editor struct {
|
||||
FileName string
|
||||
FilePath string
|
||||
FileContents string
|
||||
|
||||
CursorX int
|
||||
CursorY int
|
||||
|
||||
SelectionStart int
|
||||
SelectionLength int
|
||||
|
||||
IsModified bool
|
||||
|
||||
LinesHead *LinesNode
|
||||
LineCount int
|
||||
}
|
||||
|
||||
func (e *Editor) SetCursorPos(x, y int) {
|
||||
e.CursorX = x
|
||||
e.CursorY = y
|
||||
}
|
||||
|
||||
func (e *Editor) Render(drawStartPos, winSize *imgui.Vec2) {
|
||||
|
||||
e.CursorY = clampInt(e.CursorY, 0, e.LineCount)
|
||||
e.CursorX = clampInt(e.CursorX, 0, e.GetLineCharCount(e.CursorY))
|
||||
|
||||
//Draw window
|
||||
imgui.SetNextWindowPos(*drawStartPos)
|
||||
imgui.SetNextWindowSize(*winSize)
|
||||
imgui.BeginV("editorText", nil, imgui.WindowFlagsNoCollapse|imgui.WindowFlagsNoDecoration|imgui.WindowFlagsNoMove)
|
||||
|
||||
imgui.PushStyleColor(imgui.StyleColorFrameBg, settings.EditorBgColor)
|
||||
imgui.PushStyleColor(imgui.StyleColorTextSelectedBg, settings.TextSelectionColor)
|
||||
|
||||
//Add padding to text
|
||||
drawStartPos.X += 10
|
||||
drawStartPos.Y += 10
|
||||
|
||||
//Draw lines
|
||||
lineHeight := imgui.TextLineHeightWithSpacing()
|
||||
linesToDraw := int(winSize.Y / lineHeight)
|
||||
println("Lines to draw:", linesToDraw)
|
||||
|
||||
dl := imgui.WindowDrawList()
|
||||
for i := 0; i < linesToDraw; i++ {
|
||||
dl.AddText(*drawStartPos, imgui.PackedColorFromVec4(imgui.Vec4{X: 1, Y: 1, Z: 1, W: 1}), string(e.GetLine(e.CursorY+i).chars))
|
||||
drawStartPos.Y += lineHeight
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Editor) GetLine(lineNum int) *Line {
|
||||
|
||||
if lineNum > e.LineCount {
|
||||
return &Line{
|
||||
chars: []rune{},
|
||||
}
|
||||
}
|
||||
|
||||
curr := e.LinesHead
|
||||
|
||||
//Advance to correct node
|
||||
nodeNum := lineNum / linesPerNode
|
||||
lineNum -= nodeNum * linesPerNode
|
||||
for nodeNum > 0 {
|
||||
curr = curr.Next
|
||||
nodeNum--
|
||||
}
|
||||
|
||||
return &curr.Lines[lineNum]
|
||||
}
|
||||
|
||||
func (e *Editor) GetLineCharCount(lineNum int) int {
|
||||
|
||||
curr := e.LinesHead
|
||||
|
||||
//Advance to correct node
|
||||
nodeNum := lineNum / linesPerNode
|
||||
lineNum -= nodeNum * linesPerNode
|
||||
for nodeNum > 0 {
|
||||
curr = curr.Next
|
||||
nodeNum--
|
||||
}
|
||||
|
||||
return len(curr.Lines[lineNum].chars)
|
||||
}
|
||||
|
||||
func ParseLines(fileContents string) (*LinesNode, int) {
|
||||
|
||||
head := NewLineNode()
|
||||
|
||||
lineCount := 0
|
||||
start := 0
|
||||
end := 0
|
||||
currLine := 0
|
||||
currNode := head
|
||||
for i := 0; i < len(fileContents); i++ {
|
||||
|
||||
if fileContents[i] != '\n' {
|
||||
end++
|
||||
continue
|
||||
}
|
||||
|
||||
lineCount++
|
||||
currNode.Lines[currLine].chars = []rune(fileContents[start:end])
|
||||
|
||||
end++
|
||||
start = end
|
||||
currLine++
|
||||
if currLine == linesPerNode {
|
||||
currLine = 0
|
||||
currNode.Next = NewLineNode()
|
||||
currNode = currNode.Next
|
||||
}
|
||||
}
|
||||
|
||||
return head, lineCount
|
||||
}
|
||||
|
||||
func NewLineNode() *LinesNode {
|
||||
|
||||
n := LinesNode{}
|
||||
for i := 0; i < len(n.Lines); i++ {
|
||||
n.Lines[i].chars = []rune{}
|
||||
}
|
||||
|
||||
return &n
|
||||
}
|
||||
|
||||
func clampInt(x, min, max int) int {
|
||||
|
||||
if x > max {
|
||||
return max
|
||||
}
|
||||
|
||||
if x < min {
|
||||
return min
|
||||
}
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
func NewScratchEditor() *Editor {
|
||||
|
||||
e := &Editor{
|
||||
FileName: "**scratch**",
|
||||
LinesHead: NewLineNode(),
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
func NewEditor(fPath string) *Editor {
|
||||
|
||||
b, err := os.ReadFile(fPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
e := &Editor{
|
||||
FileName: filepath.Base(fPath),
|
||||
FilePath: fPath,
|
||||
FileContents: string(b),
|
||||
}
|
||||
e.LinesHead, e.LineCount = ParseLines(e.FileContents)
|
||||
return e
|
||||
}
|
||||
Reference in New Issue
Block a user