Correct cursor positioning+proper scrolling

This commit is contained in:
bloeys
2022-02-27 14:06:39 +04:00
parent f562ec674b
commit eb3ce8e466
5 changed files with 67 additions and 35 deletions

View File

@ -39,6 +39,9 @@ type Editor struct {
LinesHead *LinesNode
LineCount int
LineHeight float32
CharWidth float32
StartPos float32
}
@ -51,6 +54,23 @@ func (e *Editor) SetStartPos(mouseDeltaNorm int32) {
e.StartPos = clampF32(e.StartPos+float32(-mouseDeltaNorm)*settings.ScrollSpeed, 0, float32(e.LineCount))
}
func (e *Editor) RefreshFontSettings() {
e.LineHeight = imgui.TextLineHeightWithSpacing()
//NOTE: Because of 'https://github.com/ocornut/imgui/issues/792', CalcTextSize returns slightly incorrect width
//values for sentences than to be expected with singleCharWidth*sentenceCharCount. For example, with 3 chars at width 10
//we expect width of 30 (for a fixed-width font), but instead we might get 29.
// This is fixed in the newer releases, but imgui-go hasn't updated yet.
//
//That's why instead of getting width of one char, we get the average width from the width of a sentence, which helps us position
//cursors properly for now
e.CharWidth = imgui.CalcTextSize("abcdefghijklmnopqrstuvwxyz", false, 1000).X / 26
}
func (e *Editor) RoundToNearestChar(x float32) float32 {
return float32(math.Round(float64(x/e.CharWidth))) * e.CharWidth
}
func (e *Editor) Render(drawStartPos, winSize *imgui.Vec2) {
//Draw window
@ -67,52 +87,42 @@ func (e *Editor) Render(drawStartPos, winSize *imgui.Vec2) {
paddedDrawStartPos := *drawStartPos
//Draw lines
lineHeight := imgui.TextLineHeightWithSpacing()
charWidth := imgui.CalcTextSize("a", false, 1000).X
linesToDraw := int(winSize.Y / lineHeight)
linesToDraw := int(winSize.Y / e.LineHeight)
// println("Lines to draw:", linesToDraw)
dl := imgui.WindowDrawList()
startLine := clampInt(int(e.StartPos), 0, e.LineCount)
println("Start Pos: ", e.StartPos, "; Start line:", startLine)
for i := startLine; i < startLine+linesToDraw; i++ {
dl.AddText(*drawStartPos, imgui.PackedColorFromVec4(imgui.Vec4{X: 1, Y: 1, Z: 1, W: 1}), string(e.GetLine(0+i).chars))
drawStartPos.Y += lineHeight
drawStartPos.Y += e.LineHeight
}
//Draw cursor
cx := clampInt(e.MouseX-int(paddedDrawStartPos.X), 0, int(winSize.X))
cy := clampInt(e.MouseY-int(paddedDrawStartPos.Y), 0, int(winSize.Y))
//Calculate position of cursor in window and grid coords.
//Window coords are as reported by SDL, but we correct for padding and snap to the nearest
//char window pos.
//
//Since gopad only supports fixed-width fonts, we treat the text area as a grid with each
//cell having identical width and one char.
clickedColWindowY := clampInt(e.MouseY-int(paddedDrawStartPos.Y), 0, math.MaxInt)
clickedColGridY := clampInt(clickedColWindowY/int(e.LineHeight), 0, e.LineCount)
clickedLine := clampInt(cy/int(lineHeight), 0, e.LineCount)
clickedCol := cx / int(charWidth)
// fmt.Printf("line,col: %v,%v\n", clickedLine, clickedCol)
clickedColWindowX := clampInt(int(e.RoundToNearestChar(float32(e.MouseX))), 0, math.MaxInt)
clickedColGridX := clickedColWindowX / int(e.CharWidth)
eee := e.GetLine(clickedLine)
tabCount, tabChars := getTabs(eee, clickedCol)
clickedLine := e.GetLine(startLine + clickedColGridY)
tabCount, _ := getTabs(clickedLine, clickedColGridX)
maxCol := len(eee.chars) - 1
if tabCount > 0 {
maxCol += clampInt(tabCount*settings.TabSize, 0, math.MaxInt)
}
finalCol := clampInt(clickedCol+tabChars, 0, maxCol)
// if len(eee.chars) > 0 && finalCol > 0 {
// x := finalCol - tabCount*settings.TabSize
// println("!!!!", len(string(eee.chars)), "; C:", string(eee.chars[x]))
// }
lineX := paddedDrawStartPos.X + float32(finalCol)*charWidth
textWidth := float32(len(clickedLine.chars)-tabCount+tabCount*settings.TabSize) * e.CharWidth
lineX := clampF32(float32(clickedColWindowX), 0, paddedDrawStartPos.X+textWidth)
lineStart := imgui.Vec2{
X: lineX,
Y: paddedDrawStartPos.Y + float32(clickedLine)*lineHeight - lineHeight*0.25,
Y: paddedDrawStartPos.Y + float32(clickedColGridY)*e.LineHeight - e.LineHeight*0.25,
}
lineEnd := imgui.Vec2{
X: lineX,
Y: paddedDrawStartPos.Y + float32(clickedLine)*lineHeight + lineHeight*0.75,
Y: paddedDrawStartPos.Y + float32(clickedColGridY)*e.LineHeight + e.LineHeight*0.75,
}
thickness := 0.2 * charWidth
dl.AddLineV(lineStart, lineEnd, imgui.PackedColorFromVec4(imgui.Vec4{Z: 0.7, W: 1}), thickness)
dl.AddLineV(lineStart, lineEnd, imgui.PackedColorFromVec4(imgui.Vec4{Z: 0.7, W: 1}), settings.CursorWidthFactor*e.CharWidth)
}
func getTabs(l *Line, col int) (tabCount, charsToOffsetBy int) {
@ -247,6 +257,7 @@ func NewScratchEditor() *Editor {
FileName: "**scratch**",
LinesHead: NewLineNode(),
}
return e
}

3
go.mod
View File

@ -3,12 +3,13 @@ module github.com/bloeys/gopad
go 1.17
require (
github.com/bloeys/nmage v0.0.8
github.com/bloeys/nmage v0.0.10
github.com/inkyblackness/imgui-go/v4 v4.3.0
github.com/veandco/go-sdl2 v0.4.14
)
require (
github.com/bloeys/assimp-go v0.4.2 // indirect
github.com/bloeys/gglm v0.3.1 // indirect
github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6 // indirect
)

5
go.sum
View File

@ -1,8 +1,13 @@
github.com/bloeys/assimp-go v0.4.2 h1:ArVK74BCFcTO/rCGj2NgZG9xtbjnJdEn5npIeJx1Z04=
github.com/bloeys/assimp-go v0.4.2/go.mod h1:my3yRxT7CfOztmvi+0svmwbaqw0KFrxaHxncoyaEIP0=
github.com/bloeys/gglm v0.3.1 h1:Sy9upW7SBsBfDXrSmEhid3aQ+7J7itej+upwcxOnPMQ=
github.com/bloeys/gglm v0.3.1/go.mod h1:qwJQ0WzV191wAMwlGicbfbChbKoSedMk7gFFX6GnyOk=
github.com/bloeys/nmage v0.0.8 h1:HCoEaTBWTucnXrjQ+8OCUTzG/3rjpV1eliXWUW44+FY=
github.com/bloeys/nmage v0.0.8/go.mod h1:4h2tKtMvk9ab8r/+rem4QonPXEBTho6VWvpCMm0M6iM=
github.com/bloeys/nmage v0.0.9 h1:dP0g8e7VeygbX5AcYLTIPheLJr+CZmG2uOICQfcDTDA=
github.com/bloeys/nmage v0.0.9/go.mod h1:4h2tKtMvk9ab8r/+rem4QonPXEBTho6VWvpCMm0M6iM=
github.com/bloeys/nmage v0.0.10 h1:6Ryl3qjEbXxeIL+9BnBxOrGaW9mKObyY/JbRYkR8ogQ=
github.com/bloeys/nmage v0.0.10/go.mod h1:4h2tKtMvk9ab8r/+rem4QonPXEBTho6VWvpCMm0M6iM=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-gl/gl v0.0.0-20211025173605-bda47ffaa784/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw=

23
main.go
View File

@ -6,9 +6,11 @@ import (
"os"
"path/filepath"
"github.com/bloeys/gopad/settings"
"github.com/bloeys/nmage/engine"
"github.com/bloeys/nmage/input"
"github.com/bloeys/nmage/logging"
"github.com/bloeys/nmage/renderer/rend3dgl"
nmageimgui "github.com/bloeys/nmage/ui/imgui"
"github.com/inkyblackness/imgui-go/v4"
"github.com/veandco/go-sdl2/sdl"
@ -56,7 +58,7 @@ func main() {
panic(err)
}
window, err := engine.CreateOpenGLWindowCentered("nMage", 1280, 720, engine.WindowFlags_RESIZABLE|engine.WindowFlags_ALLOW_HIGHDPI)
window, err := engine.CreateOpenGLWindowCentered("nMage", 1280, 720, engine.WindowFlags_RESIZABLE|engine.WindowFlags_ALLOW_HIGHDPI, rend3dgl.NewRend3DGL())
if err != nil {
logging.ErrLog.Fatalln("Failed to create window. Err: ", err)
}
@ -86,13 +88,12 @@ func (g *Gopad) Init() {
g.Win.EventCallbacks = append(g.Win.EventCallbacks, g.handleWindowEvents)
//Setup font
var fontSize float32 = 16
fConfig := imgui.NewFontConfig()
defer fConfig.Delete()
fConfig.SetOversampleH(2)
fConfig.SetOversampleV(2)
g.mainFont = g.ImGUIInfo.AddFontTTF("./res/fonts/courier-prime.regular.ttf", fontSize, &fConfig, nil)
g.mainFont = g.ImGUIInfo.AddFontTTF("./res/fonts/courier-prime.regular.ttf", settings.FontSize, &fConfig, nil)
//Sidebar
g.CurrDirContents = getDirContents(g.CurrDir)
@ -121,6 +122,15 @@ func (g *Gopad) Init() {
g.activeEditor = len(g.editors) - 1
}
func (g *Gopad) Start() {
imgui.PushFont(g.mainFont)
for i := 0; i < len(g.editors); i++ {
e := &g.editors[i]
e.RefreshFontSettings()
}
imgui.PopFont()
}
func (g *Gopad) handleWindowEvents(event sdl.Event) {
switch e := event.(type) {
@ -361,7 +371,8 @@ func (g *Gopad) getActiveEditor() *Editor {
func (g *Gopad) getEditor(index int) *Editor {
if len(g.editors) == 0 {
e := Editor{FileName: "**scratch**"}
e := *NewScratchEditor()
e.RefreshFontSettings()
g.editors = append(g.editors, e)
g.activeEditor = 0
return &e
@ -420,7 +431,9 @@ func (g *Gopad) handleFileClick(fPath string) {
}
//Read new file and switch to it
g.editors = append(g.editors, *NewEditor(fPath))
e := *NewEditor(fPath)
e.RefreshFontSettings()
g.editors = append(g.editors, e)
g.activeEditor = len(g.editors) - 1
}

View File

@ -3,8 +3,10 @@ package settings
import "github.com/inkyblackness/imgui-go/v4"
var (
FontSize float32 = 16
TextSelectionColor imgui.Vec4 = imgui.Vec4{X: 84 / 255.0, Y: 153 / 255.0, Z: 199 / 255.0, W: 0.4}
EditorBgColor imgui.Vec4 = imgui.Vec4{X: 0.1, Y: 0.1, Z: 0.1, W: 1}
TabSize int = 4
ScrollSpeed float32 = 4
CursorWidthFactor float32 = 0.15
)