UNPKG

monaco-editor-core

Version:

A browser based code editor

169 lines (168 loc) 7.8 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import './overlayWidgets.css'; import { createFastDomNode } from '../../../../base/browser/fastDomNode.js'; import { PartFingerprints, ViewPart } from '../../view/viewPart.js'; import * as dom from '../../../../base/browser/dom.js'; export class ViewOverlayWidgets extends ViewPart { constructor(context, viewDomNode) { super(context); this._viewDomNode = viewDomNode; const options = this._context.configuration.options; const layoutInfo = options.get(146 /* EditorOption.layoutInfo */); this._widgets = {}; this._verticalScrollbarWidth = layoutInfo.verticalScrollbarWidth; this._minimapWidth = layoutInfo.minimap.minimapWidth; this._horizontalScrollbarHeight = layoutInfo.horizontalScrollbarHeight; this._editorHeight = layoutInfo.height; this._editorWidth = layoutInfo.width; this._viewDomNodeRect = { top: 0, left: 0, width: 0, height: 0 }; this._domNode = createFastDomNode(document.createElement('div')); PartFingerprints.write(this._domNode, 4 /* PartFingerprint.OverlayWidgets */); this._domNode.setClassName('overlayWidgets'); this.overflowingOverlayWidgetsDomNode = createFastDomNode(document.createElement('div')); PartFingerprints.write(this.overflowingOverlayWidgetsDomNode, 5 /* PartFingerprint.OverflowingOverlayWidgets */); this.overflowingOverlayWidgetsDomNode.setClassName('overflowingOverlayWidgets'); } dispose() { super.dispose(); this._widgets = {}; } getDomNode() { return this._domNode; } // ---- begin view event handlers onConfigurationChanged(e) { const options = this._context.configuration.options; const layoutInfo = options.get(146 /* EditorOption.layoutInfo */); this._verticalScrollbarWidth = layoutInfo.verticalScrollbarWidth; this._minimapWidth = layoutInfo.minimap.minimapWidth; this._horizontalScrollbarHeight = layoutInfo.horizontalScrollbarHeight; this._editorHeight = layoutInfo.height; this._editorWidth = layoutInfo.width; return true; } // ---- end view event handlers addWidget(widget) { const domNode = createFastDomNode(widget.getDomNode()); this._widgets[widget.getId()] = { widget: widget, preference: null, domNode: domNode }; // This is sync because a widget wants to be in the dom domNode.setPosition('absolute'); domNode.setAttribute('widgetId', widget.getId()); if (widget.allowEditorOverflow) { this.overflowingOverlayWidgetsDomNode.appendChild(domNode); } else { this._domNode.appendChild(domNode); } this.setShouldRender(); this._updateMaxMinWidth(); } setWidgetPosition(widget, position) { const widgetData = this._widgets[widget.getId()]; const preference = position ? position.preference : null; const stack = position?.stackOridinal; if (widgetData.preference === preference && widgetData.stack === stack) { this._updateMaxMinWidth(); return false; } widgetData.preference = preference; widgetData.stack = stack; this.setShouldRender(); this._updateMaxMinWidth(); return true; } removeWidget(widget) { const widgetId = widget.getId(); if (this._widgets.hasOwnProperty(widgetId)) { const widgetData = this._widgets[widgetId]; const domNode = widgetData.domNode.domNode; delete this._widgets[widgetId]; domNode.remove(); this.setShouldRender(); this._updateMaxMinWidth(); } } _updateMaxMinWidth() { let maxMinWidth = 0; const keys = Object.keys(this._widgets); for (let i = 0, len = keys.length; i < len; i++) { const widgetId = keys[i]; const widget = this._widgets[widgetId]; const widgetMinWidthInPx = widget.widget.getMinContentWidthInPx?.(); if (typeof widgetMinWidthInPx !== 'undefined') { maxMinWidth = Math.max(maxMinWidth, widgetMinWidthInPx); } } this._context.viewLayout.setOverlayWidgetsMinWidth(maxMinWidth); } _renderWidget(widgetData, stackCoordinates) { const domNode = widgetData.domNode; if (widgetData.preference === null) { domNode.setTop(''); return; } const maxRight = (2 * this._verticalScrollbarWidth) + this._minimapWidth; if (widgetData.preference === 0 /* OverlayWidgetPositionPreference.TOP_RIGHT_CORNER */ || widgetData.preference === 1 /* OverlayWidgetPositionPreference.BOTTOM_RIGHT_CORNER */) { if (widgetData.preference === 1 /* OverlayWidgetPositionPreference.BOTTOM_RIGHT_CORNER */) { const widgetHeight = domNode.domNode.clientHeight; domNode.setTop((this._editorHeight - widgetHeight - 2 * this._horizontalScrollbarHeight)); } else { domNode.setTop(0); } if (widgetData.stack !== undefined) { domNode.setTop(stackCoordinates[widgetData.preference]); stackCoordinates[widgetData.preference] += domNode.domNode.clientWidth; } else { domNode.setRight(maxRight); } } else if (widgetData.preference === 2 /* OverlayWidgetPositionPreference.TOP_CENTER */) { domNode.domNode.style.right = '50%'; if (widgetData.stack !== undefined) { domNode.setTop(stackCoordinates[2 /* OverlayWidgetPositionPreference.TOP_CENTER */]); stackCoordinates[2 /* OverlayWidgetPositionPreference.TOP_CENTER */] += domNode.domNode.clientHeight; } else { domNode.setTop(0); } } else { const { top, left } = widgetData.preference; const fixedOverflowWidgets = this._context.configuration.options.get(42 /* EditorOption.fixedOverflowWidgets */); if (fixedOverflowWidgets && widgetData.widget.allowEditorOverflow) { // top, left are computed relative to the editor and we need them relative to the page const editorBoundingBox = this._viewDomNodeRect; domNode.setTop(top + editorBoundingBox.top); domNode.setLeft(left + editorBoundingBox.left); domNode.setPosition('fixed'); } else { domNode.setTop(top); domNode.setLeft(left); domNode.setPosition('absolute'); } } } prepareRender(ctx) { this._viewDomNodeRect = dom.getDomNodePagePosition(this._viewDomNode.domNode); } render(ctx) { this._domNode.setWidth(this._editorWidth); const keys = Object.keys(this._widgets); const stackCoordinates = Array.from({ length: 2 /* OverlayWidgetPositionPreference.TOP_CENTER */ + 1 }, () => 0); keys.sort((a, b) => (this._widgets[a].stack || 0) - (this._widgets[b].stack || 0)); for (let i = 0, len = keys.length; i < len; i++) { const widgetId = keys[i]; this._renderWidget(this._widgets[widgetId], stackCoordinates); } } }