fix(editor): fix cursor positioning, scrolling, and clipping
- Fix cursor vertical alignment and ensure it respects ScrollOffset. - Fix scrolling in editor page by correctly registering scroll interactions in the renderer. - Ensure cursor is clipped to the editor text area to prevent drawing over status bars.
This commit is contained in:
parent
a5d1c4bee6
commit
d33e68ab2c
|
|
@ -374,13 +374,15 @@ func EditorLayout(screenWidth, screenHeight ui.Dp, wordWrap bool) []ui.Element {
|
|||
// approximation until GlyphLayout-based line tracking is added).
|
||||
line, col := byteOffsetToLineCol(TheState.Editor.Buffer, TheState.Editor.CursorPosition)
|
||||
|
||||
// Create the cursor element at the computed position
|
||||
// Create the cursor element at the computed position.
|
||||
// Ensure the cursor element knows its bounds for clipping.
|
||||
cursorElem := ui.NewCursor(
|
||||
"editor_cursor",
|
||||
ui.Region{X: cursorX, Y: cursorY, W: ui.Dp(2), H: lineHeight},
|
||||
line, col,
|
||||
true,
|
||||
)
|
||||
cursorElem.ClipRegion = editorRegion
|
||||
|
||||
return []ui.Element{statusBar, editorElem, cursorElem, bottomBar}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -480,6 +480,7 @@ func NewSearchBar(region Region, query string, match, total int, forward bool) S
|
|||
type Cursor struct {
|
||||
id string
|
||||
region Region
|
||||
ClipRegion Region // Region to clip drawing
|
||||
visible bool
|
||||
interactions []Interaction
|
||||
Line int
|
||||
|
|
@ -488,6 +489,7 @@ type Cursor struct {
|
|||
Selection *Selection
|
||||
}
|
||||
|
||||
func (c Cursor) NeedsClip() bool { return true }
|
||||
func (c Cursor) Type() string { return "cursor" }
|
||||
func (c Cursor) Region() Region { return c.region }
|
||||
func (c Cursor) Visible() bool { return c.visible }
|
||||
|
|
@ -499,6 +501,17 @@ func (c Cursor) String() string {
|
|||
return fmt.Sprintf("Cursor[%s] region=%+v line=%d col=%d", c.id, c.region, c.Line, c.Column)
|
||||
}
|
||||
func (c Cursor) Draw(gtx layout.Context, r *Renderer) {
|
||||
// Clip to the cursor's allocated clip region (e.g., the editor text field)
|
||||
// to prevent drawing over status bars.
|
||||
var stack *clip.Stack
|
||||
if c.ClipRegion.W > 0 && c.ClipRegion.H > 0 {
|
||||
stack = new(clip.Stack)
|
||||
*stack = clip.Rect{
|
||||
Min: image.Point{X: int(r.toPx(c.ClipRegion.X)), Y: int(r.toPx(c.ClipRegion.Y))},
|
||||
Max: image.Point{X: int(r.toPx(c.ClipRegion.X + c.ClipRegion.W)), Y: int(r.toPx(c.ClipRegion.Y + c.ClipRegion.H))},
|
||||
}.Op().Push(gtx.Ops)
|
||||
}
|
||||
|
||||
// Draw a thin vertical bar (e.g., width 2dp, height 18dp) at the cursor's top-left position
|
||||
// instead of filling the entire region, which covers the text editor.
|
||||
cursorRegion := Region{
|
||||
|
|
@ -508,6 +521,10 @@ func (c Cursor) Draw(gtx layout.Context, r *Renderer) {
|
|||
H: Dp(18),
|
||||
}
|
||||
r.drawBg(gtx, cursorRegion, Color{R: 0, G: 0, B: 0, A: 255})
|
||||
|
||||
if stack != nil {
|
||||
stack.Pop()
|
||||
}
|
||||
}
|
||||
|
||||
func NewCursor(id string, region Region, line, col int, blinking bool) Cursor {
|
||||
|
|
|
|||
|
|
@ -280,6 +280,15 @@ func (r *Renderer) drawElement(gtx layout.Context, e Element) {
|
|||
}
|
||||
}
|
||||
for _, interaction := range interactive.Interactions() {
|
||||
if interaction.Gesture == Scroll {
|
||||
reg, ok := r.scrolls[interactive.ID()]
|
||||
if !ok {
|
||||
reg = scrollReg{scroll: &gesture.Scroll{}}
|
||||
}
|
||||
reg.scroll.Add(gtx.Ops)
|
||||
reg.handler = interaction.Handler
|
||||
r.scrolls[interactive.ID()] = reg
|
||||
}
|
||||
if interaction.Gesture == Tap {
|
||||
reg, ok := r.clicks[interactive.ID()]
|
||||
if !ok {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user