提交 b08eae70 编写于 作者: R rebornix

Add support for decorations that cover the entire margin

上级 956de01b
......@@ -30,7 +30,9 @@ import { GlyphMarginOverlay } from 'vs/editor/browser/viewParts/glyphMargin/glyp
import { LineNumbersOverlay } from 'vs/editor/browser/viewParts/lineNumbers/lineNumbers';
import { IndentGuidesOverlay } from 'vs/editor/browser/viewParts/indentGuides/indentGuides';
import { ViewLines } from 'vs/editor/browser/viewParts/lines/viewLines';
import { Margin } from 'vs/editor/browser/viewParts/margin/margin';
import { LinesDecorationsOverlay } from 'vs/editor/browser/viewParts/linesDecorations/linesDecorations';
import { MarginViewLineDecorationsOverlay } from 'vs/editor/browser/viewParts/marginDecorations/marginDecorations';
import { ViewOverlayWidgets } from 'vs/editor/browser/viewParts/overlayWidgets/overlayWidgets';
import { DecorationsOverviewRuler } from 'vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler';
import { OverviewRuler } from 'vs/editor/browser/viewParts/overviewRuler/overviewRuler';
......@@ -237,9 +239,14 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp
let marginViewOverlays = new MarginViewOverlays(this._context, this.layoutProvider);
this.viewParts.push(marginViewOverlays);
marginViewOverlays.addDynamicOverlay(new GlyphMarginOverlay(this._context));
marginViewOverlays.addDynamicOverlay(new MarginViewLineDecorationsOverlay(this._context));
marginViewOverlays.addDynamicOverlay(new LinesDecorationsOverlay(this._context));
marginViewOverlays.addDynamicOverlay(new LineNumbersOverlay(this._context));
let margin = new Margin(this._context, this.layoutProvider);
margin.domNode.appendChild(this.viewZones.marginDomNode);
margin.domNode.appendChild(marginViewOverlays.getDomNode());
this.viewParts.push(margin);
// Content widgets
this.contentWidgets = new ViewContentWidgets(this._context, this.domNode);
......@@ -271,8 +278,7 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp
this.linesContent.appendChild(this.viewLines.getDomNode());
this.linesContent.appendChild(this.contentWidgets.domNode);
this.linesContent.appendChild(this.viewCursors.getDomNode());
this.overflowGuardContainer.appendChild(marginViewOverlays.getDomNode());
this.overflowGuardContainer.appendChild(this.viewZones.marginDomNode);
this.overflowGuardContainer.appendChild(margin.domNode);
this.overflowGuardContainer.appendChild(this.linesContentContainer);
this.overflowGuardContainer.appendChild(scrollDecoration.getDomNode());
this.overflowGuardContainer.appendChild(this.overlayWidgets.domNode);
......
......@@ -233,7 +233,7 @@ export class MarginViewOverlays extends ViewOverlays {
this._contentLeft = context.configuration.editor.layoutInfo.contentLeft;
this._canUseTranslate3d = context.configuration.editor.viewInfo.canUseTranslate3d;
this.domNode.setClassName(editorBrowser.ClassNames.MARGIN_VIEW_OVERLAYS + ' monaco-editor-background');
this.domNode.setClassName(editorBrowser.ClassNames.MARGIN_VIEW_OVERLAYS);
this.domNode.setWidth(1);
Configuration.applyFontInfo(this.domNode, this._context.configuration.editor.fontInfo);
......@@ -283,14 +283,6 @@ export class MarginViewOverlays extends ViewOverlays {
_viewOverlaysRender(ctx: IRestrictedRenderingContext): void {
super._viewOverlaysRender(ctx);
if (this._canUseTranslate3d) {
let transform = 'translate3d(0px, ' + ctx.linesViewportData.visibleRangesDeltaTop + 'px, 0px)';
this.domNode.setTransform(transform);
this.domNode.setTop(0);
} else {
this.domNode.setTransform('');
this.domNode.setTop(ctx.linesViewportData.visibleRangesDeltaTop);
}
let height = Math.min(this._layoutProvider.getTotalHeight(), 1000000);
this.domNode.setHeight(height);
this.domNode.setWidth(this._contentLeft);
......
......@@ -10,6 +10,7 @@
vertical-align: middle;
box-sizing: border-box;
cursor: default;
height: 100%;
}
.monaco-editor .relative-current-line-number {
......
......@@ -97,20 +97,15 @@ export class LineNumbersOverlay extends DynamicViewOverlay {
// --- end event handlers
public prepareRender(ctx: IRenderingContext): void {
if (!this.shouldRender()) {
throw new Error('I did not ask to render!');
}
if (!this._renderLineNumbers) {
this._renderResult = null;
return;
}
let lineHeightClassName = (platform.isLinux ? (this._lineHeight % 2 === 0 ? ' lh-even' : ' lh-odd') : '');
let lineHeight = this._lineHeight.toString();
let visibleStartLineNumber = ctx.visibleRange.startLineNumber;
let visibleEndLineNumber = ctx.visibleRange.endLineNumber;
let common = '<div class="' + ClassNames.LINE_NUMBERS + lineHeightClassName + '" style="left:' + this._lineNumbersLeft.toString() + 'px;width:' + this._lineNumbersWidth.toString() + 'px;height:' + lineHeight + 'px;">';
let common = '<div class="' + ClassNames.LINE_NUMBERS + lineHeightClassName + '" style="left:' + this._lineNumbersLeft.toString() + 'px;width:' + this._lineNumbersWidth.toString() + 'px;">';
let output: string[] = [];
for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) {
......
......@@ -14,4 +14,5 @@
*/
.monaco-editor .margin-view-overlays .cldr {
position: absolute;
height: 100%;
}
\ No newline at end of file
......@@ -14,7 +14,6 @@ import { IRenderingContext } from 'vs/editor/common/view/renderingContext';
export class LinesDecorationsOverlay extends DedupOverlay {
private _context: ViewContext;
private _lineHeight: number;
private _decorationsLeft: number;
private _decorationsWidth: number;
......@@ -23,7 +22,6 @@ export class LinesDecorationsOverlay extends DedupOverlay {
constructor(context: ViewContext) {
super();
this._context = context;
this._lineHeight = this._context.configuration.editor.lineHeight;
this._decorationsLeft = 0;
this._decorationsWidth = 0;
this._renderResult = null;
......@@ -63,9 +61,6 @@ export class LinesDecorationsOverlay extends DedupOverlay {
return false;
}
public onConfigurationChanged(e: editorCommon.IConfigurationChangedEvent): boolean {
if (e.lineHeight) {
this._lineHeight = this._context.configuration.editor.lineHeight;
}
return true;
}
public onLayoutChanged(layoutInfo: editorCommon.EditorLayoutInfo): boolean {
......@@ -95,18 +90,13 @@ export class LinesDecorationsOverlay extends DedupOverlay {
}
public prepareRender(ctx: IRenderingContext): void {
if (!this.shouldRender()) {
throw new Error('I did not ask to render!');
}
let visibleStartLineNumber = ctx.visibleRange.startLineNumber;
let visibleEndLineNumber = ctx.visibleRange.endLineNumber;
let toRender = this._render(visibleStartLineNumber, visibleEndLineNumber, this._getDecorations(ctx));
let lineHeight = this._lineHeight.toString();
let left = this._decorationsLeft.toString();
let width = this._decorationsWidth.toString();
let common = '" style="left:' + left + 'px;width:' + width + 'px' + ';height:' + lineHeight + 'px;"></div>';
let common = '" style="left:' + left + 'px;width:' + width + 'px;"></div>';
let output: string[] = [];
for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) {
......@@ -126,10 +116,6 @@ export class LinesDecorationsOverlay extends DedupOverlay {
if (!this._renderResult) {
return '';
}
let lineIndex = lineNumber - startLineNumber;
if (lineIndex < 0 || lineIndex >= this._renderResult.length) {
throw new Error('Unexpected render request');
}
return this._renderResult[lineIndex];
return this._renderResult[lineNumber - startLineNumber];
}
}
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { StyleMutator } from 'vs/base/browser/styleMutator';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { ViewPart } from 'vs/editor/browser/view/viewPart';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { IRenderingContext, IRestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import { ILayoutProvider } from 'vs/editor/browser/viewLayout/layoutProvider';
export class Margin extends ViewPart {
public domNode: HTMLElement;
private _layoutProvider: ILayoutProvider;
private _canUseTranslate3d: boolean;
private _height: number;
private _contentLeft: number;
constructor(context: ViewContext, layoutProvider: ILayoutProvider) {
super(context);
this._layoutProvider = layoutProvider;
this._canUseTranslate3d = this._context.configuration.editor.viewInfo.canUseTranslate3d;
this.domNode = this._createDomNode();
this._height = this._context.configuration.editor.layoutInfo.contentHeight;
this._contentLeft = this._context.configuration.editor.layoutInfo.contentLeft;
}
public dispose(): void {
super.dispose();
}
public _createDomNode(): HTMLElement {
let domNode = document.createElement('div');
domNode.className = 'margin monaco-editor-background';
domNode.style.position = 'absolute';
domNode.setAttribute('role', 'presentation');
domNode.setAttribute('aria-hidden', 'true');
return domNode;
}
// --- begin event handlers
public onConfigurationChanged(e: editorCommon.IConfigurationChangedEvent): boolean {
if (e.viewInfo.canUseTranslate3d) {
this._canUseTranslate3d = this._context.configuration.editor.viewInfo.canUseTranslate3d;
}
return super.onConfigurationChanged(e);
}
public onScrollChanged(e: editorCommon.IScrollEvent): boolean {
return super.onScrollChanged(e) || e.scrollTopChanged;
}
public onLayoutChanged(layoutInfo: editorCommon.EditorLayoutInfo): boolean {
this._contentLeft = layoutInfo.contentLeft;
return super.onLayoutChanged(layoutInfo) || true;
}
// --- end event handlers
public prepareRender(ctx: IRenderingContext): void {
// Nothing to read
}
public render(ctx: IRestrictedRenderingContext): void {
if (this._canUseTranslate3d) {
let transform = 'translate3d(0px, ' + ctx.linesViewportData.visibleRangesDeltaTop + 'px, 0px)';
StyleMutator.setTransform(this.domNode, transform);
StyleMutator.setTop(this.domNode, 0);
} else {
StyleMutator.setTransform(this.domNode, '');
StyleMutator.setTop(this.domNode, ctx.linesViewportData.visibleRangesDeltaTop);
}
let height = Math.min(this._layoutProvider.getTotalHeight(), 1000000);
StyleMutator.setHeight(this.domNode, height);
StyleMutator.setWidth(this.domNode, this._contentLeft);
}
}
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/*
Keeping name short for faster parsing.
cmdr = core margin decorations rendering (div)
*/
.monaco-editor .margin-view-overlays .cmdr {
position: absolute;
left: 0;
width: 100%;
height: 100%;
}
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./marginDecorations';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { DecorationToRender, DedupOverlay } from 'vs/editor/browser/viewParts/glyphMargin/glyphMargin';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { IRenderingContext } from 'vs/editor/common/view/renderingContext';
export class MarginViewLineDecorationsOverlay extends DedupOverlay {
private _context: ViewContext;
private _renderResult: string[];
constructor(context: ViewContext) {
super();
this._context = context;
this._renderResult = null;
this._context.addEventHandler(this);
}
public dispose(): void {
this._context.removeEventHandler(this);
this._context = null;
this._renderResult = null;
}
// --- begin event handlers
public onModelFlushed(): boolean {
return true;
}
public onModelDecorationsChanged(e: editorCommon.IViewDecorationsChangedEvent): boolean {
return true;
}
public onModelLinesDeleted(e: editorCommon.IViewLinesDeletedEvent): boolean {
return true;
}
public onModelLineChanged(e: editorCommon.IViewLineChangedEvent): boolean {
return true;
}
public onModelLinesInserted(e: editorCommon.IViewLinesInsertedEvent): boolean {
return true;
}
public onCursorPositionChanged(e: editorCommon.IViewCursorPositionChangedEvent): boolean {
return false;
}
public onCursorSelectionChanged(e: editorCommon.IViewCursorSelectionChangedEvent): boolean {
return false;
}
public onCursorRevealRange(e: editorCommon.IViewRevealRangeEvent): boolean {
return false;
}
public onConfigurationChanged(e: editorCommon.IConfigurationChangedEvent): boolean {
return true;
}
public onLayoutChanged(layoutInfo: editorCommon.EditorLayoutInfo): boolean {
return true;
}
public onScrollChanged(e: editorCommon.IScrollEvent): boolean {
return e.scrollTopChanged;
}
public onZonesChanged(): boolean {
return true;
}
// --- end event handlers
protected _getDecorations(ctx: IRenderingContext): DecorationToRender[] {
let decorations = ctx.getDecorationsInViewport();
let r: DecorationToRender[] = [];
for (let i = 0, len = decorations.length; i < len; i++) {
let d = decorations[i];
if (d.options.marginClassName) {
r.push(new DecorationToRender(d.range.startLineNumber, d.range.endLineNumber, d.options.marginClassName));
}
}
return r;
}
public prepareRender(ctx: IRenderingContext): void {
let visibleStartLineNumber = ctx.visibleRange.startLineNumber;
let visibleEndLineNumber = ctx.visibleRange.endLineNumber;
let toRender = this._render(visibleStartLineNumber, visibleEndLineNumber, this._getDecorations(ctx));
let output: string[] = [];
for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) {
let lineIndex = lineNumber - visibleStartLineNumber;
let classNames = toRender[lineIndex];
let lineOutput = '';
for (let i = 0, len = classNames.length; i < len; i++) {
lineOutput += '<div class="cmdr ' + classNames[i] + '" style=""></div>';
}
output[lineIndex] = lineOutput;
}
this._renderResult = output;
}
public render(startLineNumber: number, lineNumber: number): string {
if (!this._renderResult) {
return '';
}
return this._renderResult[lineNumber - startLineNumber];
}
}
\ No newline at end of file
......@@ -344,7 +344,7 @@ export class ViewZones extends ViewPart {
StyleMutator.setDisplay(zone.delegate.domNode, newDisplay);
if (zone.delegate.marginDomNode) {
StyleMutator.setTop(zone.delegate.marginDomNode, newTop - ctx.viewportTop);
StyleMutator.setTop(zone.delegate.marginDomNode, newTop);
StyleMutator.setHeight(zone.delegate.marginDomNode, newHeight);
StyleMutator.setDisplay(zone.delegate.marginDomNode, newDisplay);
}
......
......@@ -1150,6 +1150,10 @@ export interface IModelDecorationOptions {
* If set, the decoration will be rendered in the lines decorations with this CSS class name.
*/
linesDecorationsClassName?: string;
/**
* If set, the decoration will be rendered in the margin (covering its full width) with this CSS class name.
*/
marginClassName?: string;
/**
* If set, the decoration will be rendered inline with the text with this CSS class name.
* Please use this only for CSS rules that must impact the text. For example, use `className`
......
......@@ -654,6 +654,7 @@ class ModelDecorationOptions implements editorCommon.IModelDecorationOptions {
overviewRuler: editorCommon.IModelDecorationOverviewRulerOptions;
glyphMarginClassName: string;
linesDecorationsClassName: string;
marginClassName: string;
inlineClassName: string;
beforeContentClassName: string;
afterContentClassName: string;
......@@ -667,6 +668,7 @@ class ModelDecorationOptions implements editorCommon.IModelDecorationOptions {
this.overviewRuler = _normalizeOverviewRulerOptions(options.overviewRuler, options.showInOverviewRuler);
this.glyphMarginClassName = cleanClassName(options.glyphMarginClassName || strings.empty);
this.linesDecorationsClassName = cleanClassName(options.linesDecorationsClassName || strings.empty);
this.marginClassName = cleanClassName(options.marginClassName || strings.empty);
this.inlineClassName = cleanClassName(options.inlineClassName || strings.empty);
this.beforeContentClassName = cleanClassName(options.beforeContentClassName || strings.empty);
this.afterContentClassName = cleanClassName(options.afterContentClassName || strings.empty);
......@@ -689,6 +691,7 @@ class ModelDecorationOptions implements editorCommon.IModelDecorationOptions {
&& this.showInOverviewRuler === other.showInOverviewRuler
&& this.glyphMarginClassName === other.glyphMarginClassName
&& this.linesDecorationsClassName === other.linesDecorationsClassName
&& this.marginClassName === other.marginClassName
&& this.inlineClassName === other.inlineClassName
&& this.beforeContentClassName === other.beforeContentClassName
&& this.afterContentClassName === other.afterContentClassName
......
......@@ -1581,6 +1581,10 @@ declare module monaco.editor {
* If set, the decoration will be rendered in the lines decorations with this CSS class name.
*/
linesDecorationsClassName?: string;
/**
* If set, the decoration will be rendered in the margin (covering its full width) with this CSS class name.
*/
marginClassName?: string;
/**
* If set, the decoration will be rendered inline with the text with this CSS class name.
* Please use this only for CSS rules that must impact the text. For example, use `className`
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册