Skip to content

Commit

Permalink
Editor: Themable cursor (#1373)
Browse files Browse the repository at this point in the history
* convert CursorView to immediate mode

* invert color of text under cursor

* add cursor theme colors

* use column instead of offset for BufferLine.subExn

* don't render whitespace

* clean up BufferViewToenizer

* remove  unused Cursor module from Oni_Core

* don't crash
  • Loading branch information
glennsl authored Feb 27, 2020
1 parent 44833cf commit 5af4abc
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 84 deletions.
1 change: 0 additions & 1 deletion src/Core/Cursor.re

This file was deleted.

1 change: 0 additions & 1 deletion src/Core/Oni_Core.re
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ module ConfigurationParser = ConfigurationParser;
module ConfigurationTransformer = ConfigurationTransformer;
module ConfigurationValues = ConfigurationValues;
module Constants = Constants;
module Cursor = Cursor;
module Diff = Diff;
module EditorFont = EditorFont;
module EditorSize = EditorSize;
Expand Down
17 changes: 17 additions & 0 deletions src/Core/Theme.re
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ type t = {
activityBarForeground: Color.t,
editorBackground: Color.t,
editorForeground: Color.t,
editorCursorBackground: Color.t,
editorCursorForeground: Color.t,
editorHoverWidgetBackground: Color.t,
editorHoverWidgetBorder: Color.t,
editorLineHighlightBackground: Color.t,
Expand Down Expand Up @@ -153,6 +155,8 @@ let default: t = {
activityBarForeground: Color.hex("#DCDCDC"),
editorBackground: Color.hex("#2F3440"),
editorForeground: Color.hex("#DCDCDC"),
editorCursorBackground: Color.hex("#2F3440"),
editorCursorForeground: Color.hex("#DCDCDC"),
editorFindMatchBackground: Color.hex("#42557b"),
editorFindMatchBorder: Color.hex("#457dff"),
editorFindMatchHighlightBackground: Color.hex("#314365"),
Expand Down Expand Up @@ -265,6 +269,17 @@ let ofColorTheme = (uiTheme, ct: Textmate.ColorTheme.t) => {
let editorForeground =
getColor(defaultForeground, ["editor.foreground", "foreground"]);

let editorCursorBackground =
getColor(
defaultBackground,
["editorCursor.background", "editor.background", "background"],
);
let editorCursorForeground =
getColor(
defaultForeground,
["editorCursor.foreground", "editor.foreground", "foreground"],
);

let editorHoverWidgetBackground =
getColor(
defaultBackground,
Expand Down Expand Up @@ -547,6 +562,8 @@ let ofColorTheme = (uiTheme, ct: Textmate.ColorTheme.t) => {
activityBarForeground,
editorBackground,
editorForeground,
editorCursorBackground,
editorCursorForeground,
editorHoverWidgetBackground,
editorHoverWidgetBorder,
editorIndentGuideBackground,
Expand Down
40 changes: 10 additions & 30 deletions src/Feature/Editor/BufferViewTokenizer.re
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,18 @@ let tab = UChar.of_char('\t');
let cr = UChar.of_char('\r');
let lf = UChar.of_char('\n');

let _isWhitespace = c => {
let isWhitespace = c => {
UChar.eq(space, c)
|| UChar.eq(tab, c)
|| UChar.eq(cr, c)
|| UChar.eq(lf, c);
};

let _isNonWhitespace = c => !_isWhitespace(c);
let filterRuns = (r: Tokenizer.TextRun.t) => ZedBundled.length(r.text) != 0;

let filterRuns = (r: Tokenizer.TextRun.t) => {
let len = ZedBundled.length(r.text);

if (len == 0) {
false;
} else {
true;
};
};

type colorizer = int => (Color.t, Color.t);

let textRunToToken = (colorizer: colorizer, r: Tokenizer.TextRun.t) => {
let textRunToToken = (colorizer, r: Tokenizer.TextRun.t) => {
let startIndex = Index.toZeroBased(r.startIndex);
let (bg, fg) = colorizer(startIndex);
let (backgroundColor, color) = colorizer(startIndex);

let firstChar = ZedBundled.get(r.text, 0);

Expand All @@ -64,18 +52,14 @@ let textRunToToken = (colorizer: colorizer, r: Tokenizer.TextRun.t) => {
Text;
};

let color = fg;
let backgroundColor = bg;

let ret: t = {
{
tokenType,
text: r.text,
startPosition: r.startPosition,
endPosition: r.endPosition,
color,
backgroundColor,
};
ret;
};

let getCharacterPositionAndWidth = (~viewOffset: int=0, line: BufferLine.t, i) => {
Expand All @@ -91,18 +75,14 @@ let getCharacterPositionAndWidth = (~viewOffset: int=0, line: BufferLine.t, i) =
(actualOffset, width);
};

let colorEqual = (c1: Color.t, c2: Color.t) => {
Color.equals(c1, c2);
};

let tokenize = (~startIndex=0, ~endIndex, line, colorizer) => {
let split = (i0, c0, i1, c1) => {
let (bg1, fg1) = colorizer(i0);
let (bg2, fg2) = colorizer(i1);
let (bg0, fg0) = colorizer(i0);
let (bg1, fg1) = colorizer(i1);

!colorEqual(bg1, bg2)
|| !colorEqual(fg1, fg2)
|| _isWhitespace(c0) != _isWhitespace(c1)
!Color.equals(bg0, bg1)
|| !Color.equals(fg0, fg1)
|| isWhitespace(c0) != isWhitespace(c1)
/* Always split on tabs */
|| UChar.eq(c0, tab)
|| UChar.eq(c1, tab);
Expand Down
90 changes: 39 additions & 51 deletions src/Feature/Editor/CursorView.re
Original file line number Diff line number Diff line change
@@ -1,68 +1,56 @@
open EditorCoreTypes;
open Revery;
open Revery.UI;

open Oni_Core;

let make =
let render =
(
~context: Draw.context,
~buffer,
~mode: Vim.Mode.t,
~isActiveSplit,
~editorFont: EditorFont.t,
~cursorPosition: Location.t,
~editor: Editor.t,
(),
~theme: Theme.t,
) => {
let cursorLine = Index.toZeroBased(cursorPosition.line);
let line = Index.toZeroBased(cursorPosition.line);
let column = Index.toZeroBased(cursorPosition.column);
let lineCount = Buffer.getNumberOfLines(buffer);

let (cursorOffset, cursorCharacterWidth) =
if (lineCount > 0 && cursorLine < lineCount) {
let cursorLine = Buffer.getLine(cursorLine, buffer);
if (lineCount <= 0 || line >= lineCount) {
();
} else {
let bufferLine = Buffer.getLine(line, buffer);
let (offset, characterWidth) =
BufferViewTokenizer.getCharacterPositionAndWidth(bufferLine, column);

let (cursorOffset, width) =
BufferViewTokenizer.getCharacterPositionAndWidth(
cursorLine,
Index.toZeroBased(cursorPosition.column),
);
(cursorOffset, width);
} else {
(0, 1);
};

let fullCursorWidth =
cursorCharacterWidth * int_of_float(editorFont.measuredWidth);
let x = float(offset) *. context.charWidth;
let y = float(line) *. context.lineHeight +. 0.5;
let height = context.lineHeight;
let background = theme.editorCursorBackground;
let foreground = theme.editorCursorForeground;

let cursorWidth =
switch (mode, isActiveSplit) {
| (Insert, true) => 2
| _ => fullCursorWidth
| (Insert, true) =>
let width = 2.;
Draw.rect(~context, ~x, ~y, ~width, ~height, ~color=foreground);

| _ =>
let width = float(characterWidth) *. context.charWidth;
Draw.rect(~context, ~x, ~y, ~width, ~height, ~color=foreground);

switch (BufferLine.subExn(~index=column, ~length=1, bufferLine)) {
| exception _
| "" => ()
| text when BufferViewTokenizer.isWhitespace(ZedBundled.get(text, 0)) =>
()
| text =>
Draw.shapedText(
~context,
~x=x -. 0.5,
~y=y -. context.fontMetrics.ascent -. 0.5,
~color=background,
text,
)
};
};

let cursorPixelY =
int_of_float(
editorFont.measuredHeight
*. float(Index.toZeroBased(cursorPosition.line))
-. editor.scrollY
+. 0.5,
);

let cursorPixelX =
int_of_float(
editorFont.measuredWidth *. float(cursorOffset) -. editor.scrollX +. 0.5,
);

let style =
Style.[
position(`Absolute),
top(cursorPixelY),
left(cursorPixelX),
height(int_of_float(editorFont.measuredHeight)),
width(cursorWidth),
backgroundColor(Colors.white),
];
let cursorOpacity = isActiveSplit ? 0.5 : 0.25;

<Opacity opacity=cursorOpacity> <View style /> </Opacity>;
};
};
10 changes: 9 additions & 1 deletion src/Feature/Editor/SurfaceView.re
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,17 @@ let%component make =
indentation,
);
};

CursorView.render(
~context,
~buffer,
~mode,
~isActiveSplit,
~cursorPosition,
~theme,
);
}}
/>
<CursorView buffer mode isActiveSplit cursorPosition editor editorFont />
<View style=Styles.horizontalScrollBar>
<EditorHorizontalScrollbar
editor
Expand Down

0 comments on commit 5af4abc

Please sign in to comment.