cleanups; render re-order; wall of text test; simple selection rendering

selections can be created with the shift and arrow keys. note that this
does not actually do anything other than render a little box showing the
selection we've made.

also the box rendering isn't entirely accurate (mostly when you use the
up/left arrow key) as it doesnt handle negative values well yet.
This commit is contained in:
Felix Angell 2018-04-22 20:11:01 +01:00
parent b263501c7c
commit fe3c3c44a9
2 changed files with 162 additions and 35 deletions

View File

@ -66,6 +66,32 @@ func NewBuffer(conf *cfg.TomlConfig, parent *View, index int) *Buffer {
return buff return buff
} }
// sx, sy -> the starting x, y pos of the cursor
// ex, ey -> the end x, y of the selection
type selection struct {
parent *Buffer
sx, sy int
ex, ey int
}
func (s *selection) renderAt(ctx *strife.Renderer, xOff int, yOff int) {
ctx.SetColor(strife.Red)
xd := (s.ex - s.sx) + 1
yd := (s.ey - s.sy) + 1
for y := 0; y < yd; y++ {
lineLen := s.parent.contents[s.ey+y].Len() - s.sx
if y == yd-1 {
lineLen = xd
}
width := lineLen * last_w
ctx.Rect(xOff+(s.sx*last_w), yOff+((s.sy+y)*last_h), width, last_h, strife.Fill)
}
}
func (b *Buffer) OpenFile(filePath string) { func (b *Buffer) OpenFile(filePath string) {
b.filePath = filePath b.filePath = filePath
@ -455,13 +481,61 @@ func (b *Buffer) scrollDown() {
} }
} }
// processes a key press. returns if there var lastSelection *selection
// was a key that MODIFIED the buffer.
func (b *Buffer) processSelection(key int) bool {
if lastSelection == nil {
lastSelection = &selection{
b,
b.curs.x, b.curs.y,
b.curs.x, b.curs.y,
}
}
switch key {
case sdl.K_LEFT:
lastSelection.ex--
b.moveLeft()
break
case sdl.K_RIGHT:
lastSelection.ex++
b.moveRight()
break
case sdl.K_UP:
lastSelection.ey--
b.moveUp()
break
case sdl.K_DOWN:
lastSelection.ey++
b.moveDown()
break
}
return true
}
// processes a key press. returns if a key was processed
// or not, for example the letter 'a' could run through this
// which is not an action key, therefore we return false
// because it was not processed.
func (b *Buffer) processActionKey(key int) bool { func (b *Buffer) processActionKey(key int) bool {
if SHIFT_DOWN {
switch key {
case sdl.K_LEFT:
fallthrough
case sdl.K_RIGHT:
fallthrough
case sdl.K_DOWN:
fallthrough
case sdl.K_UP:
return b.processSelection(key)
}
}
switch key { switch key {
case sdl.K_CAPSLOCK: case sdl.K_CAPSLOCK:
CAPS_LOCK = !CAPS_LOCK CAPS_LOCK = !CAPS_LOCK
return true
case sdl.K_RETURN: case sdl.K_RETURN:
if SUPER_DOWN { if SUPER_DOWN {
// in sublime this goes // in sublime this goes
@ -504,30 +578,32 @@ func (b *Buffer) processActionKey(key int) bool {
b.contents = append(b.contents, nil) b.contents = append(b.contents, nil)
copy(b.contents[b.curs.y+1:], b.contents[b.curs.y:]) copy(b.contents[b.curs.y+1:], b.contents[b.curs.y:])
b.contents[b.curs.y] = newRope b.contents[b.curs.y] = newRope
return true
case sdl.K_BACKSPACE: case sdl.K_BACKSPACE:
if SUPER_DOWN { if SUPER_DOWN {
b.deleteBeforeCursor() b.deleteBeforeCursor()
} else { } else {
b.deletePrev() b.deletePrev()
} }
return true
case sdl.K_RIGHT: case sdl.K_RIGHT:
currLineLength := b.contents[b.curs.y].Len() currLineLength := b.contents[b.curs.y].Len()
if CONTROL_DOWN && b.parent != nil { if CONTROL_DOWN && b.parent != nil {
b.parent.ChangeFocus(1) b.parent.ChangeFocus(1)
return true break
} }
if SUPER_DOWN { if SUPER_DOWN {
for b.curs.x < currLineLength { for b.curs.x < currLineLength {
b.curs.move(1, 0) b.curs.move(1, 0)
} }
return true break
} }
// FIXME this is weird! // FIXME this is weird!
// this will move to the next blank or underscore
// character
if ALT_DOWN { if ALT_DOWN {
currLine := b.contents[b.curs.y] currLine := b.contents[b.curs.y]
@ -542,15 +618,14 @@ func (b *Buffer) processActionKey(key int) bool {
for j := 0; j < i; j++ { for j := 0; j < i; j++ {
b.moveRight() b.moveRight()
} }
return true break
} }
b.moveRight() b.moveRight()
return true
case sdl.K_LEFT: case sdl.K_LEFT:
if CONTROL_DOWN && b.parent != nil { if CONTROL_DOWN && b.parent != nil {
b.parent.ChangeFocus(-1) b.parent.ChangeFocus(-1)
return true break
} }
if SUPER_DOWN { if SUPER_DOWN {
@ -579,11 +654,10 @@ func (b *Buffer) processActionKey(key int) bool {
for j := 0; j < start-i; j++ { for j := 0; j < start-i; j++ {
b.moveLeft() b.moveLeft()
} }
return true break
} }
b.moveLeft() b.moveLeft()
return true
case sdl.K_UP: case sdl.K_UP:
if ALT_DOWN { if ALT_DOWN {
return b.swapLineUp() return b.swapLineUp()
@ -602,7 +676,7 @@ func (b *Buffer) processActionKey(key int) bool {
// TODO: offset should account for tabs // TODO: offset should account for tabs
b.curs.move(offs, -1) b.curs.move(offs, -1)
} }
return true
case sdl.K_DOWN: case sdl.K_DOWN:
if ALT_DOWN { if ALT_DOWN {
return b.swapLineDown() return b.swapLineDown()
@ -621,7 +695,7 @@ func (b *Buffer) processActionKey(key int) bool {
// TODO: offset should account for tabs // TODO: offset should account for tabs
b.curs.move(offs, 1) b.curs.move(offs, 1)
} }
return true
case sdl.K_TAB: case sdl.K_TAB:
if b.cfg.Editor.Tabs_Are_Spaces { if b.cfg.Editor.Tabs_Are_Spaces {
// make an empty rune array of TAB_SIZE, cast to string // make an empty rune array of TAB_SIZE, cast to string
@ -634,7 +708,6 @@ func (b *Buffer) processActionKey(key int) bool {
// move by TAB_SIZE characters on the view. // move by TAB_SIZE characters on the view.
b.curs.moveRender(1, 0, int(b.cfg.Editor.Tab_Size), 0) b.curs.moveRender(1, 0, int(b.cfg.Editor.Tab_Size), 0)
} }
return true
case sdl.K_END: case sdl.K_END:
currLine := b.contents[b.curs.y] currLine := b.contents[b.curs.y]
@ -642,25 +715,20 @@ func (b *Buffer) processActionKey(key int) bool {
distToMove := currLine.Len() - b.curs.x distToMove := currLine.Len() - b.curs.x
b.curs.move(distToMove, 0) b.curs.move(distToMove, 0)
} }
return true
case sdl.K_HOME: case sdl.K_HOME:
if b.curs.x > 0 { if b.curs.x > 0 {
b.curs.move(-b.curs.x, 0) b.curs.move(-b.curs.x, 0)
} }
return true
case sdl.K_PAGEUP: case sdl.K_PAGEUP:
b.scrollUp() b.scrollUp()
return true
case sdl.K_PAGEDOWN: case sdl.K_PAGEDOWN:
b.scrollDown() b.scrollDown()
return true
case sdl.K_DELETE: case sdl.K_DELETE:
b.deleteNext() b.deleteNext()
return true
case sdl.K_LGUI: case sdl.K_LGUI:
fallthrough fallthrough
@ -681,9 +749,12 @@ func (b *Buffer) processActionKey(key int) bool {
fallthrough fallthrough
case sdl.K_RSHIFT: case sdl.K_RSHIFT:
return true return true
default:
return false
} }
return false return true
} }
var ( var (
@ -735,6 +806,17 @@ func (b *Buffer) OnUpdate() bool {
// action first // action first
actionPerformed := b.processActionKey(keyCode) actionPerformed := b.processActionKey(keyCode)
if actionPerformed { if actionPerformed {
// check if we need to remove the selection
// or not, this is if we moved the cursor somehow
if lastSelection != nil {
if b.curs.x != lastSelection.ex {
lastSelection = nil
} else if b.curs.y != lastSelection.ey {
lastSelection = nil
}
}
return true return true
} }
@ -840,25 +922,15 @@ func (b *Buffer) renderAt(ctx *strife.Renderer, rx int, ry int) {
ctx.Rect(highlightLinePosX, highlightLinePosY, b.w, last_h, strife.Fill) ctx.Rect(highlightLinePosX, highlightLinePosY, b.w, last_h, strife.Fill)
} }
// render the ol' cursor
if b.HasFocus && renderFlashingCursor && b.cfg.Cursor.Draw {
cursorWidth := b.cfg.Cursor.GetCaretWidth()
if cursorWidth == -1 {
cursorWidth = last_w
}
ctx.SetColor(strife.HexRGB(b.cfg.Theme.Cursor)) // caret colour
ctx.Rect(ex+(rx+b.curs.rx*last_w)-(b.cam.x*last_w), (ry+b.curs.ry*last_h)-(b.cam.y*last_h), cursorWidth, last_h, strife.Fill)
}
var visibleLines int = 50 var visibleLines int = 50
// HACK // HACK
// force a render off screen // force a render off screen
// so we can calculate the size of characters // so we can calculate the size of characters
{
if int(last_h) == 0 || int(last_w) == 0 { if int(last_h) == 0 || int(last_w) == 0 {
last_w, last_h = ctx.String("_", -50, -50) last_w, last_h = ctx.String("_", -50, -50)
}
} }
// last_h > 0 means we have done // last_h > 0 means we have done
@ -879,6 +951,11 @@ func (b *Buffer) renderAt(ctx *strife.Renderer, rx int, ry int) {
upper = len(b.contents) upper = len(b.contents)
} }
// render the selection if any
if lastSelection != nil {
lastSelection.renderAt(ctx, b.x+ex, b.y+ey)
}
numLines := len(b.contents) numLines := len(b.contents)
var y_col int var y_col int
@ -947,6 +1024,17 @@ func (b *Buffer) renderAt(ctx *strife.Renderer, rx int, ry int) {
y_col += 1 y_col += 1
} }
// render the ol' cursor
if b.HasFocus && renderFlashingCursor && b.cfg.Cursor.Draw {
cursorWidth := b.cfg.Cursor.GetCaretWidth()
if cursorWidth == -1 {
cursorWidth = last_w
}
ctx.SetColor(strife.HexRGB(b.cfg.Theme.Cursor)) // caret colour
ctx.Rect(ex+(rx+b.curs.rx*last_w)-(b.cam.x*last_w), (ry+b.curs.ry*last_h)-(b.cam.y*last_h), cursorWidth, last_h, strife.Fill)
}
} }
func (b *Buffer) OnRender(ctx *strife.Renderer) { func (b *Buffer) OnRender(ctx *strife.Renderer) {

View File

@ -0,0 +1,39 @@
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx