This ensures we only perform a single update with the most up-to-date
information about line height, default character width, and specific
character widths. If this update causes more lines to be drawn we may
measure again, but not necessarily.
Previously, SelectionsComponenet::shouldComponentUpdate was storing the
ranges for selections as a side effect. We also were passing boolean
values (cursorMoved and selectionUpdated) to determine if these
components should update.
Now, we compute a simple hash of screen ranges for selections and
cursors in the root component and pass them down. This simplifies
shouldComponentUpdate for selections and allows us to implement one
for cursors.
I don't think that this component was really carrying its weight. Its
render function basically passed through directly to other components
that updated between renders, but didn't contain any content on its
own that actually changed after the first render.
React components seem to carry overhead, so I want every component we
use to count. Also, I'm considering circumventing some of React's
standard update logic for performance reasons, and making the structure
more shallow will help with that.
The indentation level is not anymore reduced by adding a new line,
which previously caused multiple reductions of the indentation level.
This fixes the behavior of HTML closing tags, which currently
"jump" backwards if you try to move them down.
If a mousewheel event is triggered when the editor can't be scrolled,
we still want to clear the mouseWheelScreenRow. This is typically done
when we stop scrolling, but if we never start scrolling it will never
happen. This commit adds another timeout to cover that case.
Fixes#2429, #2443
Otherwise, it's possible to duplicate lines. If a line is in the
rendered row range and it's not in the set of lines returned by the
editor, we should remove it no matter what. Line preservation is only
intended for lines that are out of view.
When we handle a mousewheel event targeting a line or line number, we
assign the mousewheelScreenRow to prevent the removal of the target
node, which interferes with velocity scrolling.
However, the ::mousewheelScreenRow is only cleared 100ms after we stop
scrolling vertically. This means that if we're only scrolling
horizontally, it's never cleared. This causes the line node associated
with this screen row to hang around longer until the mousewheel screen
row is cleared again, which is not what we want.
This commit only assigns the ::mousewheelScreenRow when scrolling
vertically, so we can be sure it will be cleared.
The editor's scroll view is getting autoscrolled when the editor is
focused, so we won't position the hidden input until after the editor
is focused, and will always return it to 0,0 when the editor is blurred.
CSS has a line-height property with values like '1.3', but we also have
a measured pixel value for line height. It's important to keep these
separate conceptually.
Now that everything is absolutely position, the editor no longer assumes
a "natural" height and width. This can be addressed later if we want to
allow editors to expand based on their content.
Rename functions `backspaceToBeginningOfWord` to `deleteToBeginningOfWord` and
`backspaceToBeginningOfLine to `deleteToBeginningOfLine`.
Rename commands `editor:backspace-to-beginning-of-word` to
`delete-to-beginning-of-word` and `editor:backspace-to-beginning-of-line` to
`editor:delete-to-beginning-of-line`.
Fix#1791
This enables subscribers to detect not just that stylesheets have
changed, but specifically how they have changed. This is used by the
React editor component to only refresh scrollbars when a stylesheet
that actually contains selectors for scrollbar elements is added or
removed.
We measure the scrollbar-corner node when there's a stylesheet change,
but Chromium won't apply the new style if it was already visible before
the change. This commit hides and shows it before measuring so we get
accurate values.
Previously, dummy scrollbars were always 15px wide/tall. This caused
them to obscure the ability to click for the entire 15px region, even if
the actual scrollbar was styled to be much thinner. Now we explicitly
measure the size of scrollbars on mount and when the stylesheets change
and set the height/width explicitly.
Horizontal / vertical scrollbars render a 'corner' on the lower right
when they would otherwise overlap. I previously relied on drawing both
dummy scrollbars at their full width/height so the corner got rendered,
but that interfered with the display of the horizontal scrollbar in
certain circumstances because it was too wide to scroll. This commit
provides that behavior with an absolutely positioned div with the same
dimensions as the intersection of scrollbars when both are visible.
This entailed quite a few changes to dial in scrollbars. The scrollbars
are now adjusted in size to account for the width of the opposite
scrollbar. If the width or height are not explicitly constrained and we
are scrollable in the opposite direction that is constrained, we account
for the width of the opposite scrollbar in assigning a natural height
or width based on the content.
Because the scrollbar now spans the entire editor but the scrollable
area does not include the gutter, we need to add the current width of
the gutter to the scroll width of the horizontal scrollbar to allow
it to scroll to the end of the longest lines.
We set overflow to hidden in the opposite scroll direction only if we
can't actually scroll in that direction, causing the white square where
neither scrollbar overlaps to appear at the lower right corner.
This was previously throwing an error when Workspace::open was called
with a split: right option and the rightmost sibling was a PaneAxis
since it was assuming findOrCreateRightmostSibling was always returning
a Pane, not a PaneAxis.
This assumes the scrollbar is 15px high, which is incorrect when using
overlay scrollbars or when the scrollbar is styled to have a different
height. We'll need to measure it in a subsequent commit.
This commit breaks the initial render of the editor component into two
stages.
The first stage just renders the shell of the editor so the height,
width, line height, and default character width can be measured. Nothing
that depends on these values is rendered on the first render pass.
Once the editor component is mounted, all these values are measured and
we force another update, which fills in the lines, line numbers,
selections, etc.
We also refrain from assigning an explicit height and width on the
model if these values aren't explicitly styled in the DOM, and just
assume the editor will stretch to accommodate its contents.
When the target of a mousewheel event is removed, it breaks velocity
scrolling.
Previously, we were preserving the entire screen range when scrolling
with the mouse wheel, which caused a lot of DOM nodes to accumulate. Now
we only preserve the individual line and line number associated with the
target of the mousewheel event, moving them just off screen below all
the on-screen lines and line numbers. This keeps the number of DOM nodes
limited while retaining velocity effects.