| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- /*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
- import './viewCursors.css';
- import { createFastDomNode } from '../../../../base/browser/fastDomNode.js';
- import { IntervalTimer, TimeoutTimer } from '../../../../base/common/async.js';
- import { ViewPart } from '../../view/viewPart.js';
- import { ViewCursor } from './viewCursor.js';
- import { TextEditorCursorStyle } from '../../../common/config/editorOptions.js';
- import { editorCursorBackground, editorCursorForeground } from '../../../common/core/editorColorRegistry.js';
- import { registerThemingParticipant } from '../../../../platform/theme/common/themeService.js';
- import { isHighContrast } from '../../../../platform/theme/common/theme.js';
- export class ViewCursors extends ViewPart {
- constructor(context) {
- super(context);
- const options = this._context.configuration.options;
- this._readOnly = options.get(83 /* EditorOption.readOnly */);
- this._cursorBlinking = options.get(22 /* EditorOption.cursorBlinking */);
- this._cursorStyle = options.get(24 /* EditorOption.cursorStyle */);
- this._cursorSmoothCaretAnimation = options.get(23 /* EditorOption.cursorSmoothCaretAnimation */);
- this._selectionIsEmpty = true;
- this._isComposingInput = false;
- this._isVisible = false;
- this._primaryCursor = new ViewCursor(this._context);
- this._secondaryCursors = [];
- this._renderData = [];
- this._domNode = createFastDomNode(document.createElement('div'));
- this._domNode.setAttribute('role', 'presentation');
- this._domNode.setAttribute('aria-hidden', 'true');
- this._updateDomClassName();
- this._domNode.appendChild(this._primaryCursor.getDomNode());
- this._startCursorBlinkAnimation = new TimeoutTimer();
- this._cursorFlatBlinkInterval = new IntervalTimer();
- this._blinkingEnabled = false;
- this._editorHasFocus = false;
- this._updateBlinking();
- }
- dispose() {
- super.dispose();
- this._startCursorBlinkAnimation.dispose();
- this._cursorFlatBlinkInterval.dispose();
- }
- getDomNode() {
- return this._domNode;
- }
- // --- begin event handlers
- onCompositionStart(e) {
- this._isComposingInput = true;
- this._updateBlinking();
- return true;
- }
- onCompositionEnd(e) {
- this._isComposingInput = false;
- this._updateBlinking();
- return true;
- }
- onConfigurationChanged(e) {
- const options = this._context.configuration.options;
- this._readOnly = options.get(83 /* EditorOption.readOnly */);
- this._cursorBlinking = options.get(22 /* EditorOption.cursorBlinking */);
- this._cursorStyle = options.get(24 /* EditorOption.cursorStyle */);
- this._cursorSmoothCaretAnimation = options.get(23 /* EditorOption.cursorSmoothCaretAnimation */);
- this._updateBlinking();
- this._updateDomClassName();
- this._primaryCursor.onConfigurationChanged(e);
- for (let i = 0, len = this._secondaryCursors.length; i < len; i++) {
- this._secondaryCursors[i].onConfigurationChanged(e);
- }
- return true;
- }
- _onCursorPositionChanged(position, secondaryPositions) {
- this._primaryCursor.onCursorPositionChanged(position);
- this._updateBlinking();
- if (this._secondaryCursors.length < secondaryPositions.length) {
- // Create new cursors
- const addCnt = secondaryPositions.length - this._secondaryCursors.length;
- for (let i = 0; i < addCnt; i++) {
- const newCursor = new ViewCursor(this._context);
- this._domNode.domNode.insertBefore(newCursor.getDomNode().domNode, this._primaryCursor.getDomNode().domNode.nextSibling);
- this._secondaryCursors.push(newCursor);
- }
- }
- else if (this._secondaryCursors.length > secondaryPositions.length) {
- // Remove some cursors
- const removeCnt = this._secondaryCursors.length - secondaryPositions.length;
- for (let i = 0; i < removeCnt; i++) {
- this._domNode.removeChild(this._secondaryCursors[0].getDomNode());
- this._secondaryCursors.splice(0, 1);
- }
- }
- for (let i = 0; i < secondaryPositions.length; i++) {
- this._secondaryCursors[i].onCursorPositionChanged(secondaryPositions[i]);
- }
- }
- onCursorStateChanged(e) {
- const positions = [];
- for (let i = 0, len = e.selections.length; i < len; i++) {
- positions[i] = e.selections[i].getPosition();
- }
- this._onCursorPositionChanged(positions[0], positions.slice(1));
- const selectionIsEmpty = e.selections[0].isEmpty();
- if (this._selectionIsEmpty !== selectionIsEmpty) {
- this._selectionIsEmpty = selectionIsEmpty;
- this._updateDomClassName();
- }
- return true;
- }
- onDecorationsChanged(e) {
- // true for inline decorations that can end up relayouting text
- return true;
- }
- onFlushed(e) {
- return true;
- }
- onFocusChanged(e) {
- this._editorHasFocus = e.isFocused;
- this._updateBlinking();
- return false;
- }
- onLinesChanged(e) {
- return true;
- }
- onLinesDeleted(e) {
- return true;
- }
- onLinesInserted(e) {
- return true;
- }
- onScrollChanged(e) {
- return true;
- }
- onTokensChanged(e) {
- const shouldRender = (position) => {
- for (let i = 0, len = e.ranges.length; i < len; i++) {
- if (e.ranges[i].fromLineNumber <= position.lineNumber && position.lineNumber <= e.ranges[i].toLineNumber) {
- return true;
- }
- }
- return false;
- };
- if (shouldRender(this._primaryCursor.getPosition())) {
- return true;
- }
- for (const secondaryCursor of this._secondaryCursors) {
- if (shouldRender(secondaryCursor.getPosition())) {
- return true;
- }
- }
- return false;
- }
- onZonesChanged(e) {
- return true;
- }
- // --- end event handlers
- // ---- blinking logic
- _getCursorBlinking() {
- if (this._isComposingInput) {
- // avoid double cursors
- return 0 /* TextEditorCursorBlinkingStyle.Hidden */;
- }
- if (!this._editorHasFocus) {
- return 0 /* TextEditorCursorBlinkingStyle.Hidden */;
- }
- if (this._readOnly) {
- return 5 /* TextEditorCursorBlinkingStyle.Solid */;
- }
- return this._cursorBlinking;
- }
- _updateBlinking() {
- this._startCursorBlinkAnimation.cancel();
- this._cursorFlatBlinkInterval.cancel();
- const blinkingStyle = this._getCursorBlinking();
- // hidden and solid are special as they involve no animations
- const isHidden = (blinkingStyle === 0 /* TextEditorCursorBlinkingStyle.Hidden */);
- const isSolid = (blinkingStyle === 5 /* TextEditorCursorBlinkingStyle.Solid */);
- if (isHidden) {
- this._hide();
- }
- else {
- this._show();
- }
- this._blinkingEnabled = false;
- this._updateDomClassName();
- if (!isHidden && !isSolid) {
- if (blinkingStyle === 1 /* TextEditorCursorBlinkingStyle.Blink */) {
- // flat blinking is handled by JavaScript to save battery life due to Chromium step timing issue https://bugs.chromium.org/p/chromium/issues/detail?id=361587
- this._cursorFlatBlinkInterval.cancelAndSet(() => {
- if (this._isVisible) {
- this._hide();
- }
- else {
- this._show();
- }
- }, ViewCursors.BLINK_INTERVAL);
- }
- else {
- this._startCursorBlinkAnimation.setIfNotSet(() => {
- this._blinkingEnabled = true;
- this._updateDomClassName();
- }, ViewCursors.BLINK_INTERVAL);
- }
- }
- }
- // --- end blinking logic
- _updateDomClassName() {
- this._domNode.setClassName(this._getClassName());
- }
- _getClassName() {
- let result = 'cursors-layer';
- if (!this._selectionIsEmpty) {
- result += ' has-selection';
- }
- switch (this._cursorStyle) {
- case TextEditorCursorStyle.Line:
- result += ' cursor-line-style';
- break;
- case TextEditorCursorStyle.Block:
- result += ' cursor-block-style';
- break;
- case TextEditorCursorStyle.Underline:
- result += ' cursor-underline-style';
- break;
- case TextEditorCursorStyle.LineThin:
- result += ' cursor-line-thin-style';
- break;
- case TextEditorCursorStyle.BlockOutline:
- result += ' cursor-block-outline-style';
- break;
- case TextEditorCursorStyle.UnderlineThin:
- result += ' cursor-underline-thin-style';
- break;
- default:
- result += ' cursor-line-style';
- }
- if (this._blinkingEnabled) {
- switch (this._getCursorBlinking()) {
- case 1 /* TextEditorCursorBlinkingStyle.Blink */:
- result += ' cursor-blink';
- break;
- case 2 /* TextEditorCursorBlinkingStyle.Smooth */:
- result += ' cursor-smooth';
- break;
- case 3 /* TextEditorCursorBlinkingStyle.Phase */:
- result += ' cursor-phase';
- break;
- case 4 /* TextEditorCursorBlinkingStyle.Expand */:
- result += ' cursor-expand';
- break;
- case 5 /* TextEditorCursorBlinkingStyle.Solid */:
- result += ' cursor-solid';
- break;
- default:
- result += ' cursor-solid';
- }
- }
- else {
- result += ' cursor-solid';
- }
- if (this._cursorSmoothCaretAnimation) {
- result += ' cursor-smooth-caret-animation';
- }
- return result;
- }
- _show() {
- this._primaryCursor.show();
- for (let i = 0, len = this._secondaryCursors.length; i < len; i++) {
- this._secondaryCursors[i].show();
- }
- this._isVisible = true;
- }
- _hide() {
- this._primaryCursor.hide();
- for (let i = 0, len = this._secondaryCursors.length; i < len; i++) {
- this._secondaryCursors[i].hide();
- }
- this._isVisible = false;
- }
- // ---- IViewPart implementation
- prepareRender(ctx) {
- this._primaryCursor.prepareRender(ctx);
- for (let i = 0, len = this._secondaryCursors.length; i < len; i++) {
- this._secondaryCursors[i].prepareRender(ctx);
- }
- }
- render(ctx) {
- const renderData = [];
- let renderDataLen = 0;
- const primaryRenderData = this._primaryCursor.render(ctx);
- if (primaryRenderData) {
- renderData[renderDataLen++] = primaryRenderData;
- }
- for (let i = 0, len = this._secondaryCursors.length; i < len; i++) {
- const secondaryRenderData = this._secondaryCursors[i].render(ctx);
- if (secondaryRenderData) {
- renderData[renderDataLen++] = secondaryRenderData;
- }
- }
- this._renderData = renderData;
- }
- getLastRenderData() {
- return this._renderData;
- }
- }
- ViewCursors.BLINK_INTERVAL = 500;
- registerThemingParticipant((theme, collector) => {
- const caret = theme.getColor(editorCursorForeground);
- if (caret) {
- let caretBackground = theme.getColor(editorCursorBackground);
- if (!caretBackground) {
- caretBackground = caret.opposite();
- }
- collector.addRule(`.monaco-editor .inputarea.ime-input { caret-color: ${caret}; }`);
- collector.addRule(`.monaco-editor .cursors-layer .cursor { background-color: ${caret}; border-color: ${caret}; color: ${caretBackground}; }`);
- if (isHighContrast(theme.type)) {
- collector.addRule(`.monaco-editor .cursors-layer.has-selection .cursor { border-left: 1px solid ${caretBackground}; border-right: 1px solid ${caretBackground}; }`);
- }
- }
- });
|