Selections render themselves on screen (1 div per line)

Still a lot of details to cover, but basic selection creation is
working.
This commit is contained in:
Nathan Sobo
2012-01-26 18:54:18 -08:00
parent 5aeef9e58f
commit 6bf82a27c9
8 changed files with 153 additions and 11 deletions

View File

@@ -233,8 +233,6 @@ describe "Editor", ->
editor.trigger keydownEvent('right', shiftKey: true)
expect(selection.isEmpty()).toBeFalsy()
expect(selection.anchor.getPosition()).toEqual(row: 1, column: 6)
expect(selection.cursor.getPosition()).toEqual(row: 1, column: 7)
range = selection.getRange()
expect(range.start).toEqual(row: 1, column: 6)
expect(range.end).toEqual(row: 1, column: 7)

View File

@@ -10,7 +10,7 @@ describe "Range", ->
range2 = new Range(new Point(1, 4), new Point(0, 1))
expect(range2.start).toEqual(row: 0, column: 1)
describe "isEmpty", ->
describe ".isEmpty()", ->
it "returns true if @start equals @end", ->
expect(new Range(new Point(1, 1), new Point(1, 1)).isEmpty()).toBeTruthy()
expect(new Range(new Point(1, 1), new Point(1, 2)).isEmpty()).toBeFalsy()

View File

@@ -0,0 +1,90 @@
Buffer = require 'buffer'
Editor = require 'editor'
Range = require 'range'
describe "Selection", ->
[editor, buffer, selection] = []
beforeEach ->
buffer = new Buffer(require.resolve('fixtures/sample.js'))
editor = Editor.build()
editor.enableKeymap()
editor.setBuffer(buffer)
selection = editor.selection
describe ".setRange(range)", ->
it "places the anchor at the start of the range and the cursor at the end", ->
range = new Range({row: 2, column: 7}, {row: 3, column: 18})
selection.setRange(range)
expect(selection.anchor.getPosition()).toEqual range.start
expect(selection.cursor.getPosition()).toEqual range.end
fdescribe ".updateAppearence()", ->
[charWidth, lineHeight] = []
beforeEach ->
editor.attachToDom()
{ charWidth, lineHeight } = editor
describe "when the selection is within a single line", ->
it "covers the selection's range with a single region", ->
selection.setRange(new Range({row: 2, column: 7}, {row: 2, column: 25}))
expect(selection.regions.length).toBe 1
region = selection.regions[0]
expect(region.position().top).toBe(2 * lineHeight)
expect(region.position().left).toBe(7 * charWidth)
expect(region.height()).toBe lineHeight
expect(region.width()).toBe((25 - 7) * charWidth)
describe "when the selection spans 2 lines", ->
it "covers the selection's range with 2 regions", ->
selection.setRange(new Range({row: 2, column: 7}, {row: 3, column: 25}))
expect(selection.regions.length).toBe 2
region1 = selection.regions[0]
expect(region1.position().top).toBe(2 * lineHeight)
expect(region1.position().left).toBe(7 * charWidth)
expect(region1.height()).toBe lineHeight
expect(region1.width()).toBe(editor.width() - region1.position().left)
region2 = selection.regions[1]
expect(region2.position().top).toBe(3 * lineHeight)
expect(region2.position().left).toBe(0)
expect(region2.height()).toBe lineHeight
expect(region2.width()).toBe(25 * charWidth)
describe "when the selection spans more than 2 lines", ->
it "covers the selection's range with a region for each line", ->
selection.setRange(new Range({row: 2, column: 7}, {row: 4, column: 25}))
expect(selection.regions.length).toBe 3
region1 = selection.regions[0]
expect(region1.position().top).toBe(2 * lineHeight)
expect(region1.position().left).toBe(7 * charWidth)
expect(region1.height()).toBe lineHeight
expect(region1.width()).toBe(editor.width() - region1.position().left)
region2 = selection.regions[1]
expect(region2.position().top).toBe(3 * lineHeight)
expect(region2.position().left).toBe(0)
expect(region2.height()).toBe lineHeight
expect(region2.width()).toBe(editor.width())
region3 = selection.regions[2]
expect(region3.position().top).toBe(4 * lineHeight)
expect(region3.position().left).toBe(0)
expect(region3.height()).toBe lineHeight
expect(region3.width()).toBe(25 * charWidth)
it "clears previously drawn regions before creating new ones", ->
selection.setRange(new Range({row: 2, column: 7}, {row: 4, column: 25}))
expect(selection.regions.length).toBe 3
expect(selection.find('.selection').length).toBe 3
selection.updateAppearance()
expect(selection.regions.length).toBe 3
expect(selection.find('.selection').length).toBe 3

View File

@@ -10,8 +10,8 @@ class Cursor extends Template
viewProperties:
editor: null
initialize: (editor) ->
@editor = editor
initialize: (@selection) ->
@editor = @selection.editor
bufferChanged: (e) ->
@setPosition(e.postRange.end)
@@ -20,7 +20,7 @@ class Cursor extends Template
point = Point.fromObject(point)
@point = @editor.clipPosition(point)
@goalColumn = null
@updateScreenPosition()
@selection.updateAppearance()
getPosition: -> _.clone(@point)
@@ -81,7 +81,7 @@ class Cursor extends Template
@setPosition({row, column})
updateScreenPosition: ->
updateAppearance: ->
position = @editor.pixelPositionFromPoint(@point)
@css(position)

View File

@@ -115,7 +115,7 @@ class Editor extends Template
@charWidth = fragment.width()
@lineHeight = fragment.outerHeight()
fragment.remove()
@selection.updateScreenPosition()
@selection.updateAppearance()
scrollBottom: (newValue) ->
if newValue?

View File

@@ -1,6 +1,11 @@
Point = require 'point'
module.exports =
class Range
constructor: (pointA, pointB) ->
pointA = Point.fromObject(pointA)
pointB = Point.fromObject(pointB)
if pointA.compare(pointB) <= 0
@start = pointA
@end = pointB

View File

@@ -1,6 +1,7 @@
Template = require 'template'
Cursor = require 'cursor'
Range = require 'range'
$$ = require 'template/builder'
module.exports =
class Selection extends Template
@@ -8,15 +9,59 @@ class Selection extends Template
@div()
viewProperties:
regions: null
initialize: (editor) ->
@editor = editor
@cursor = Cursor.build(editor).appendTo(this)
@cursor = Cursor.build(this).appendTo(this)
@regions = []
bufferChanged: (e) ->
@cursor.setPosition(e.postRange.end)
updateScreenPosition: ->
@cursor.updateScreenPosition()
updateAppearance: ->
@cursor.updateAppearance()
@clearRegions()
range = @getRange()
return if range.isEmpty()
for row in [range.start.row..range.end.row]
start =
if row == range.start.row
range.start
else
{ row: row, column: 0 }
end =
if row == range.end.row
range.end
else
null
@appendRegion(start, end)
appendRegion: (start, end) ->
{ lineHeight, charWidth } = @editor
top = start.row * lineHeight
left = start.column * charWidth
height = lineHeight
width = if end
end.column * charWidth - left
else
@editor.width() - left
region = $$.div(class: 'selection').css({top, left, height, width})
@append(region)
@regions.push(region)
clearRegions: ->
region.remove() for region in @regions
@regions = []
setRange: (range) ->
@cursor.setPosition(range.start)
@placeAnchor()
@cursor.setPosition(range.end)
insertText: (text) ->
@editor.buffer.change(@getRange(), text)

View File

@@ -23,3 +23,7 @@
left: 100%;
}
.editor .selection {
position: absolute;
background: blue;
}