Previously document.caretFromRange() was used which
required hiding and showing the overlayer which would
cause a relayout and entire repaint of the editor area.
Now the text nodes on the selected row are iterated over
until the column corresponding to the event's pageX value
is found.
Closes#290
The whitespace in lines that have no non-whitespace
text is treated as trailing whitespace so add the
indent guide to the trailing whitespace tokens when the
line is 100% whitespace.
Mouse events that occur in the gutter are forwarded to the
rendered lines with the y-coordinate translated to be the
leftmost pixel of the editor to simulate the event originating
from column 0 of the current line row.
Closes#287
In additional, rename `registerViewClass(es)` to `registerDeserializer(s)`.
This moves us to a situation where any kind of object may want to be
deserialized, not just views.
This closes#233. When an editor is focused, what's *actually* focused
is a hidden input element inside the editor. So clicking on a focused
editor was temporarily stealing focus away from the hidden input, and
then moving it back to the hidden input (which the editor always does
when it is focused). Returning false from the mousedown handler when
the editor is already focused prevents this bouncing of focus and
prevents the fuzzy finder from hiding when you click its editor.
When the font size changes and the editor is detached, it schedules
itself to be redrawn the next time we're reattached rather than
updating the display in a detached state.
Detached display updates worked in the past because we didn't need to
be on the DOM to determine horizontal and vertical positions once we
had calculated dimensions once. So it worked to temporarily attach
the editor when calculating new dimensions, and then continue updates
even when it was detached. That now breaks because we can't ask for
pixel positions if we aren't on the DOM.
When translating a logical screen position (columns/rows) to a pixel
position, the editor now builds a temporary version of the line for the
given row. It then uses the DOM range API to insert an empty range
at the correct text node and offset for the given column and determines
the left position based on its clientRect.
Depending on the speed impact, we may want to optimize this by
recycling the existing line node if it exists on screen rather than
building a new one every time. We will still have to build one if the
line we're moving to isn't on screen yet. We could also increase the
chances of the line being on screen by autoscrolling to the vertical
position first, and *then* calculating the horizontal position. Lots
to explore here.
- EditSessions destroy their Selections when they are destroyed
- Editors destroy their EditSessions when they are destroyed
- Editors unsubscribe from the document and window when they are
removed from the DOM.
- When an EditSession is destroyed via any code path, the Editor with
that EditSession removes it.
- Selections no longer trigger 'destroyed' events if their parent
EditSession has already been destroyed.
These are all really intertwined, so I'm doing them as one commit
since that was the only way to keep the specs green.