| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329 |
- /*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
- import { createFastDomNode } from '../../../../base/browser/fastDomNode.js';
- import { onUnexpectedError } from '../../../../base/common/errors.js';
- import { ViewPart } from '../../view/viewPart.js';
- import { Position } from '../../../common/core/position.js';
- const invalidFunc = () => { throw new Error(`Invalid change accessor`); };
- export class ViewZones extends ViewPart {
- constructor(context) {
- super(context);
- const options = this._context.configuration.options;
- const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);
- this._lineHeight = options.get(61 /* EditorOption.lineHeight */);
- this._contentWidth = layoutInfo.contentWidth;
- this._contentLeft = layoutInfo.contentLeft;
- this.domNode = createFastDomNode(document.createElement('div'));
- this.domNode.setClassName('view-zones');
- this.domNode.setPosition('absolute');
- this.domNode.setAttribute('role', 'presentation');
- this.domNode.setAttribute('aria-hidden', 'true');
- this.marginDomNode = createFastDomNode(document.createElement('div'));
- this.marginDomNode.setClassName('margin-view-zones');
- this.marginDomNode.setPosition('absolute');
- this.marginDomNode.setAttribute('role', 'presentation');
- this.marginDomNode.setAttribute('aria-hidden', 'true');
- this._zones = {};
- }
- dispose() {
- super.dispose();
- this._zones = {};
- }
- // ---- begin view event handlers
- _recomputeWhitespacesProps() {
- const whitespaces = this._context.viewLayout.getWhitespaces();
- const oldWhitespaces = new Map();
- for (const whitespace of whitespaces) {
- oldWhitespaces.set(whitespace.id, whitespace);
- }
- let hadAChange = false;
- this._context.viewModel.changeWhitespace((whitespaceAccessor) => {
- const keys = Object.keys(this._zones);
- for (let i = 0, len = keys.length; i < len; i++) {
- const id = keys[i];
- const zone = this._zones[id];
- const props = this._computeWhitespaceProps(zone.delegate);
- zone.isInHiddenArea = props.isInHiddenArea;
- const oldWhitespace = oldWhitespaces.get(id);
- if (oldWhitespace && (oldWhitespace.afterLineNumber !== props.afterViewLineNumber || oldWhitespace.height !== props.heightInPx)) {
- whitespaceAccessor.changeOneWhitespace(id, props.afterViewLineNumber, props.heightInPx);
- this._safeCallOnComputedHeight(zone.delegate, props.heightInPx);
- hadAChange = true;
- }
- }
- });
- return hadAChange;
- }
- onConfigurationChanged(e) {
- const options = this._context.configuration.options;
- const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);
- this._lineHeight = options.get(61 /* EditorOption.lineHeight */);
- this._contentWidth = layoutInfo.contentWidth;
- this._contentLeft = layoutInfo.contentLeft;
- if (e.hasChanged(61 /* EditorOption.lineHeight */)) {
- this._recomputeWhitespacesProps();
- }
- return true;
- }
- onLineMappingChanged(e) {
- return this._recomputeWhitespacesProps();
- }
- onLinesDeleted(e) {
- return true;
- }
- onScrollChanged(e) {
- return e.scrollTopChanged || e.scrollWidthChanged;
- }
- onZonesChanged(e) {
- return true;
- }
- onLinesInserted(e) {
- return true;
- }
- // ---- end view event handlers
- _getZoneOrdinal(zone) {
- if (typeof zone.afterColumn !== 'undefined') {
- return zone.afterColumn;
- }
- return 10000;
- }
- _computeWhitespaceProps(zone) {
- if (zone.afterLineNumber === 0) {
- return {
- isInHiddenArea: false,
- afterViewLineNumber: 0,
- heightInPx: this._heightInPixels(zone),
- minWidthInPx: this._minWidthInPixels(zone)
- };
- }
- let zoneAfterModelPosition;
- if (typeof zone.afterColumn !== 'undefined') {
- zoneAfterModelPosition = this._context.viewModel.model.validatePosition({
- lineNumber: zone.afterLineNumber,
- column: zone.afterColumn
- });
- }
- else {
- const validAfterLineNumber = this._context.viewModel.model.validatePosition({
- lineNumber: zone.afterLineNumber,
- column: 1
- }).lineNumber;
- zoneAfterModelPosition = new Position(validAfterLineNumber, this._context.viewModel.model.getLineMaxColumn(validAfterLineNumber));
- }
- let zoneBeforeModelPosition;
- if (zoneAfterModelPosition.column === this._context.viewModel.model.getLineMaxColumn(zoneAfterModelPosition.lineNumber)) {
- zoneBeforeModelPosition = this._context.viewModel.model.validatePosition({
- lineNumber: zoneAfterModelPosition.lineNumber + 1,
- column: 1
- });
- }
- else {
- zoneBeforeModelPosition = this._context.viewModel.model.validatePosition({
- lineNumber: zoneAfterModelPosition.lineNumber,
- column: zoneAfterModelPosition.column + 1
- });
- }
- const viewPosition = this._context.viewModel.coordinatesConverter.convertModelPositionToViewPosition(zoneAfterModelPosition, zone.afterColumnAffinity);
- const isVisible = this._context.viewModel.coordinatesConverter.modelPositionIsVisible(zoneBeforeModelPosition);
- return {
- isInHiddenArea: !isVisible,
- afterViewLineNumber: viewPosition.lineNumber,
- heightInPx: (isVisible ? this._heightInPixels(zone) : 0),
- minWidthInPx: this._minWidthInPixels(zone)
- };
- }
- changeViewZones(callback) {
- let zonesHaveChanged = false;
- this._context.viewModel.changeWhitespace((whitespaceAccessor) => {
- const changeAccessor = {
- addZone: (zone) => {
- zonesHaveChanged = true;
- return this._addZone(whitespaceAccessor, zone);
- },
- removeZone: (id) => {
- if (!id) {
- return;
- }
- zonesHaveChanged = this._removeZone(whitespaceAccessor, id) || zonesHaveChanged;
- },
- layoutZone: (id) => {
- if (!id) {
- return;
- }
- zonesHaveChanged = this._layoutZone(whitespaceAccessor, id) || zonesHaveChanged;
- }
- };
- safeInvoke1Arg(callback, changeAccessor);
- // Invalidate changeAccessor
- changeAccessor.addZone = invalidFunc;
- changeAccessor.removeZone = invalidFunc;
- changeAccessor.layoutZone = invalidFunc;
- });
- return zonesHaveChanged;
- }
- _addZone(whitespaceAccessor, zone) {
- const props = this._computeWhitespaceProps(zone);
- const whitespaceId = whitespaceAccessor.insertWhitespace(props.afterViewLineNumber, this._getZoneOrdinal(zone), props.heightInPx, props.minWidthInPx);
- const myZone = {
- whitespaceId: whitespaceId,
- delegate: zone,
- isInHiddenArea: props.isInHiddenArea,
- isVisible: false,
- domNode: createFastDomNode(zone.domNode),
- marginDomNode: zone.marginDomNode ? createFastDomNode(zone.marginDomNode) : null
- };
- this._safeCallOnComputedHeight(myZone.delegate, props.heightInPx);
- myZone.domNode.setPosition('absolute');
- myZone.domNode.domNode.style.width = '100%';
- myZone.domNode.setDisplay('none');
- myZone.domNode.setAttribute('monaco-view-zone', myZone.whitespaceId);
- this.domNode.appendChild(myZone.domNode);
- if (myZone.marginDomNode) {
- myZone.marginDomNode.setPosition('absolute');
- myZone.marginDomNode.domNode.style.width = '100%';
- myZone.marginDomNode.setDisplay('none');
- myZone.marginDomNode.setAttribute('monaco-view-zone', myZone.whitespaceId);
- this.marginDomNode.appendChild(myZone.marginDomNode);
- }
- this._zones[myZone.whitespaceId] = myZone;
- this.setShouldRender();
- return myZone.whitespaceId;
- }
- _removeZone(whitespaceAccessor, id) {
- if (this._zones.hasOwnProperty(id)) {
- const zone = this._zones[id];
- delete this._zones[id];
- whitespaceAccessor.removeWhitespace(zone.whitespaceId);
- zone.domNode.removeAttribute('monaco-visible-view-zone');
- zone.domNode.removeAttribute('monaco-view-zone');
- zone.domNode.domNode.parentNode.removeChild(zone.domNode.domNode);
- if (zone.marginDomNode) {
- zone.marginDomNode.removeAttribute('monaco-visible-view-zone');
- zone.marginDomNode.removeAttribute('monaco-view-zone');
- zone.marginDomNode.domNode.parentNode.removeChild(zone.marginDomNode.domNode);
- }
- this.setShouldRender();
- return true;
- }
- return false;
- }
- _layoutZone(whitespaceAccessor, id) {
- if (this._zones.hasOwnProperty(id)) {
- const zone = this._zones[id];
- const props = this._computeWhitespaceProps(zone.delegate);
- zone.isInHiddenArea = props.isInHiddenArea;
- // const newOrdinal = this._getZoneOrdinal(zone.delegate);
- whitespaceAccessor.changeOneWhitespace(zone.whitespaceId, props.afterViewLineNumber, props.heightInPx);
- // TODO@Alex: change `newOrdinal` too
- this._safeCallOnComputedHeight(zone.delegate, props.heightInPx);
- this.setShouldRender();
- return true;
- }
- return false;
- }
- shouldSuppressMouseDownOnViewZone(id) {
- if (this._zones.hasOwnProperty(id)) {
- const zone = this._zones[id];
- return Boolean(zone.delegate.suppressMouseDown);
- }
- return false;
- }
- _heightInPixels(zone) {
- if (typeof zone.heightInPx === 'number') {
- return zone.heightInPx;
- }
- if (typeof zone.heightInLines === 'number') {
- return this._lineHeight * zone.heightInLines;
- }
- return this._lineHeight;
- }
- _minWidthInPixels(zone) {
- if (typeof zone.minWidthInPx === 'number') {
- return zone.minWidthInPx;
- }
- return 0;
- }
- _safeCallOnComputedHeight(zone, height) {
- if (typeof zone.onComputedHeight === 'function') {
- try {
- zone.onComputedHeight(height);
- }
- catch (e) {
- onUnexpectedError(e);
- }
- }
- }
- _safeCallOnDomNodeTop(zone, top) {
- if (typeof zone.onDomNodeTop === 'function') {
- try {
- zone.onDomNodeTop(top);
- }
- catch (e) {
- onUnexpectedError(e);
- }
- }
- }
- prepareRender(ctx) {
- // Nothing to read
- }
- render(ctx) {
- const visibleWhitespaces = ctx.viewportData.whitespaceViewportData;
- const visibleZones = {};
- let hasVisibleZone = false;
- for (const visibleWhitespace of visibleWhitespaces) {
- if (this._zones[visibleWhitespace.id].isInHiddenArea) {
- continue;
- }
- visibleZones[visibleWhitespace.id] = visibleWhitespace;
- hasVisibleZone = true;
- }
- const keys = Object.keys(this._zones);
- for (let i = 0, len = keys.length; i < len; i++) {
- const id = keys[i];
- const zone = this._zones[id];
- let newTop = 0;
- let newHeight = 0;
- let newDisplay = 'none';
- if (visibleZones.hasOwnProperty(id)) {
- newTop = visibleZones[id].verticalOffset - ctx.bigNumbersDelta;
- newHeight = visibleZones[id].height;
- newDisplay = 'block';
- // zone is visible
- if (!zone.isVisible) {
- zone.domNode.setAttribute('monaco-visible-view-zone', 'true');
- zone.isVisible = true;
- }
- this._safeCallOnDomNodeTop(zone.delegate, ctx.getScrolledTopFromAbsoluteTop(visibleZones[id].verticalOffset));
- }
- else {
- if (zone.isVisible) {
- zone.domNode.removeAttribute('monaco-visible-view-zone');
- zone.isVisible = false;
- }
- this._safeCallOnDomNodeTop(zone.delegate, ctx.getScrolledTopFromAbsoluteTop(-1000000));
- }
- zone.domNode.setTop(newTop);
- zone.domNode.setHeight(newHeight);
- zone.domNode.setDisplay(newDisplay);
- if (zone.marginDomNode) {
- zone.marginDomNode.setTop(newTop);
- zone.marginDomNode.setHeight(newHeight);
- zone.marginDomNode.setDisplay(newDisplay);
- }
- }
- if (hasVisibleZone) {
- this.domNode.setWidth(Math.max(ctx.scrollWidth, this._contentWidth));
- this.marginDomNode.setWidth(this._contentLeft);
- }
- }
- }
- function safeInvoke1Arg(func, arg1) {
- try {
- return func(arg1);
- }
- catch (e) {
- onUnexpectedError(e);
- }
- }
|