Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Nav toolbar - impements #9418 #31162

Closed
wants to merge 13 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion src/vs/editor/browser/config/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,15 @@ class CSSBasedConfiguration extends Disposable {
}
}

export interface IEdgePaddings {
top: number;
bottom: number;
}

export interface IEdgePaddingSource {
getEdgePadding(): IEdgePaddings;
}

export class Configuration extends CommonEditorConfiguration {

public static applyFontInfoSlow(domNode: HTMLElement, fontInfo: BareFontInfo): void {
Expand All @@ -293,11 +302,13 @@ export class Configuration extends CommonEditorConfiguration {
}

private readonly _elementSizeObserver: ElementSizeObserver;
private readonly _edgePaddingSource: IEdgePaddingSource;

constructor(options: IEditorOptions, referenceDomElement: HTMLElement = null) {
constructor(options: IEditorOptions, referenceDomElement: HTMLElement = null, edgePaddingSource: IEdgePaddingSource = null) {
super(options);

this._elementSizeObserver = this._register(new ElementSizeObserver(referenceDomElement, () => this._onReferenceDomElementSizeChanged()));
this._edgePaddingSource = edgePaddingSource;

this._register(CSSBasedConfiguration.INSTANCE.onDidChange(() => this._onCSSBasedConfigurationChanged()));

Expand Down Expand Up @@ -343,8 +354,12 @@ export class Configuration extends CommonEditorConfiguration {
}

protected _getEnvConfiguration(): IEnvConfiguration {
const edgePaddings = this._edgePaddingSource && this._edgePaddingSource.getEdgePadding() || null;

return {
extraEditorClassName: this._getExtraEditorClassName(),
paddingTop: edgePaddings.top,
paddingBottom: edgePaddings.bottom,
outerWidth: this._elementSizeObserver.getWidth(),
outerHeight: this._elementSizeObserver.getHeight(),
emptySelectionClipboard: browser.isWebKit,
Expand Down
7 changes: 5 additions & 2 deletions src/vs/editor/browser/controller/textAreaHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export class TextAreaHandler extends ViewPart {
private readonly _viewHelper: ITextAreaHandlerHelper;
private _accessibilitySupport: platform.AccessibilitySupport;
private _contentLeft: number;
private _contentTop: number;
private _contentWidth: number;
private _contentHeight: number;
private _scrollLeft: number;
Expand Down Expand Up @@ -87,6 +88,7 @@ export class TextAreaHandler extends ViewPart {

this._accessibilitySupport = conf.accessibilitySupport;
this._contentLeft = conf.layoutInfo.contentLeft;
this._contentTop = conf.layoutInfo.contentTop;
this._contentWidth = conf.layoutInfo.contentWidth;
this._contentHeight = conf.layoutInfo.contentHeight;
this._scrollLeft = 0;
Expand Down Expand Up @@ -298,6 +300,7 @@ export class TextAreaHandler extends ViewPart {
}
if (e.layoutInfo) {
this._contentLeft = conf.layoutInfo.contentLeft;
this._contentTop = conf.layoutInfo.contentTop;
this._contentWidth = conf.layoutInfo.contentWidth;
this._contentHeight = conf.layoutInfo.contentHeight;
}
Expand Down Expand Up @@ -380,7 +383,7 @@ export class TextAreaHandler extends ViewPart {
if (this._visibleTextArea) {
// The text area is visible for composition reasons
this._renderInsideEditor(
this._visibleTextArea.top - this._scrollTop,
this._contentTop + this._visibleTextArea.top - this._scrollTop,
this._contentLeft + this._visibleTextArea.left - this._scrollLeft,
this._visibleTextArea.width,
this._lineHeight,
Expand All @@ -402,7 +405,7 @@ export class TextAreaHandler extends ViewPart {
return;
}

const top = this._context.viewLayout.getVerticalOffsetForLineNumber(this._selections[0].positionLineNumber) - this._scrollTop;
const top = this._contentTop + this._context.viewLayout.getVerticalOffsetForLineNumber(this._selections[0].positionLineNumber) - this._scrollTop;
if (top < 0 || top > this._contentHeight) {
// cursor is outside the viewport
this._renderAtTopLeft();
Expand Down
53 changes: 53 additions & 0 deletions src/vs/editor/browser/editorBrowser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,45 @@ export interface IOverlayWidget {
getPosition(): IOverlayWidgetPosition;
}

/**
* A positioning preference for rendering content widgets.
*/
export enum EdgeWidgetPositionEdge {
/**
* Place the edge widget at the top
*/
TOP,
/**
* Place the edge widget at the bottom
*/
BOTTOM
}
/**
* A position for rendering edge widgets.
*/
export interface IEdgeWidgetPosition {
size: number;
edge: EdgeWidgetPositionEdge;
}
/**
* An edge widget renders at the requested edge and pushed content inside.
*/
export interface IEdgeWidget {
/**
* Get a unique identifier of the edge widget.
*/
getId(): string;
/**
* Get the dom node of the content widget.
*/
getDomNode(): HTMLElement;
/**
* Get the placement of the content widget.
* If null is returned, the content widget will be placed off screen.
*/
getPosition(): IEdgeWidgetPosition;
}

/**
* Type of hit element with the mouse in the editor.
*/
Expand Down Expand Up @@ -678,6 +717,20 @@ export interface ICodeEditor extends editorCommon.IEditor {
*/
removeOverlayWidget(widget: IOverlayWidget): void;

/**
* Add an edge widget. Widgets must have unique ids, otherwise they will be overwritten.
*/
addEdgeWidget(widget: IEdgeWidget): void;
/**
* Layout/Reposition an edge widget. This is a ping to the editor to call widget.getPosition()
* and update appropiately.
*/
layoutEdgeWidget(widget: IEdgeWidget): void;
/**
* Remove an edge widget.
*/
removeEdgeWidget(widget: IEdgeWidget): void;

/**
* Change the view zones. View zones are lost when a new model is attached to the editor.
*/
Expand Down
32 changes: 32 additions & 0 deletions src/vs/editor/browser/view/viewImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ 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 { ViewEdgeWidgets } from 'vs/editor/browser/viewParts/edgeWidgets/edgeWidgets';
import { DecorationsOverviewRuler } from 'vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler';
import { OverviewRuler } from 'vs/editor/browser/viewParts/overviewRuler/overviewRuler';
import { Rulers } from 'vs/editor/browser/viewParts/rulers/rulers';
Expand Down Expand Up @@ -61,6 +62,11 @@ export interface IOverlayWidgetData {
position: editorBrowser.IOverlayWidgetPosition;
}

export interface IEdgeWidgetData {
widget: editorBrowser.IEdgeWidget;
position: editorBrowser.IEdgeWidgetPosition;
}

export class View extends ViewEventHandler {

private eventDispatcher: ViewEventDispatcher;
Expand All @@ -76,6 +82,7 @@ export class View extends ViewEventHandler {
private viewZones: ViewZones;
private contentWidgets: ViewContentWidgets;
private overlayWidgets: ViewOverlayWidgets;
private edgeWidgets: ViewEdgeWidgets;
private viewCursors: ViewCursors;
private viewParts: ViewPart[];

Expand Down Expand Up @@ -205,6 +212,10 @@ export class View extends ViewEventHandler {
this.overlayWidgets = new ViewOverlayWidgets(this._context);
this.viewParts.push(this.overlayWidgets);

// Edge widgets
this.edgeWidgets = new ViewEdgeWidgets(this._context);
this.viewParts.push(this.edgeWidgets);

let rulers = new Rulers(this._context);
this.viewParts.push(rulers);

Expand Down Expand Up @@ -233,6 +244,7 @@ export class View extends ViewEventHandler {
this.overflowGuardContainer.appendChild(minimap.getDomNode());
this.domNode.appendChild(this.overflowGuardContainer);
this.domNode.appendChild(this.contentWidgets.overflowingContentWidgetsDomNode);
this.domNode.appendChild(this.edgeWidgets.getDomNode());
}

private _flushAccumulatedAndRenderNow(): void {
Expand Down Expand Up @@ -574,6 +586,26 @@ export class View extends ViewEventHandler {
this._scheduleRender();
}

public addEdgeWidget(widgetData: IEdgeWidgetData): void {
this.edgeWidgets.addWidget(widgetData.widget);
this.layoutEdgeWidget(widgetData);
this._scheduleRender();
}

public layoutEdgeWidget(widgetData: IEdgeWidgetData): void {
let newEdge = widgetData.position ? widgetData.position.edge : null;
let newSize = widgetData.position ? widgetData.position.size : null;
let shouldRender = this.edgeWidgets.setWidgetPosition(widgetData.widget, newEdge, newSize);
if (shouldRender) {
this._scheduleRender();
}
}

public removeEdgeWidget(widgetData: IEdgeWidgetData): void {
this.edgeWidgets.removeWidget(widgetData.widget);
this._scheduleRender();
}

// --- END CodeEditor helpers

}
Expand Down
1 change: 1 addition & 0 deletions src/vs/editor/browser/view/viewPart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export const enum PartFingerprint {
OverflowingContentWidgets,
OverflowGuard,
OverlayWidgets,
EdgeWidgets,
ScrollableElement,
TextArea,
ViewLines,
Expand Down
7 changes: 7 additions & 0 deletions src/vs/editor/browser/viewParts/edgeWidgets/edgeWidgets.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

.monaco-editor .edgeWidgets {
}
137 changes: 137 additions & 0 deletions src/vs/editor/browser/viewParts/edgeWidgets/edgeWidgets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*---------------------------------------------------------------------------------------------
* 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!./edgeWidgets';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { IEdgeWidget, EdgeWidgetPositionEdge } from 'vs/editor/browser/editorBrowser';
import { ViewPart, PartFingerprint, PartFingerprints } from 'vs/editor/browser/view/viewPart';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';

interface IWidgetData {
widget: IEdgeWidget;
edge: EdgeWidgetPositionEdge;
size: number;
domNode: FastDomNode<HTMLElement>;
}

interface IWidgetMap {
[key: string]: IWidgetData;
}

export class ViewEdgeWidgets extends ViewPart {

private _widgets: IWidgetMap;
private _domNode: FastDomNode<HTMLElement>;

constructor(context: ViewContext) {
super(context);

this._widgets = {};

this._domNode = createFastDomNode(document.createElement('div'));
PartFingerprints.write(this._domNode, PartFingerprint.EdgeWidgets);
this._domNode.setClassName('edgeWidgets');
}

public dispose(): void {
super.dispose();
this._widgets = null;
}

public getDomNode(): FastDomNode<HTMLElement> {
return this._domNode;
}

// ---- begin view event handlers

public onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {
if (e.layoutInfo) {
//this._editorWidth = this._context.configuration.editor.layoutInfo.width;
return true;
}
return false;
}

// ---- end view event handlers

public addWidget(widget: IEdgeWidget): void {
const domNode = createFastDomNode(widget.getDomNode());

this._widgets[widget.getId()] = {
widget: widget,
edge: null,
size: null,
domNode: domNode
};

// This is sync because a widget wants to be in the dom
domNode.setPosition('absolute');
domNode.setAttribute('widgetId', widget.getId());
this._domNode.appendChild(domNode);

this.setShouldRender();
}

public setWidgetPosition(widget: IEdgeWidget, edge: EdgeWidgetPositionEdge, size: number): boolean {
let widgetData = this._widgets[widget.getId()];
if (widgetData.edge === edge && widgetData.size === size) {
return false;
}

widgetData.edge = edge;
widgetData.size = size;
this.setShouldRender();

return true;
}

public removeWidget(widget: IEdgeWidget): void {
let widgetId = widget.getId();
if (this._widgets.hasOwnProperty(widgetId)) {
const widgetData = this._widgets[widgetId];
const domNode = widgetData.domNode.domNode;
delete this._widgets[widgetId];

domNode.parentNode.removeChild(domNode);
this.setShouldRender();
}
}

private _renderWidget(widgetData: IWidgetData): void {
const domNode = widgetData.domNode;

if (widgetData.edge === null) {
domNode.unsetTop();
return;
}

if (widgetData.edge === EdgeWidgetPositionEdge.TOP) {
domNode.setTop(0);
domNode.setLeft(0);
//domNode.setWidth
} else if (widgetData.edge === EdgeWidgetPositionEdge.BOTTOM) {
domNode.setBottom(0);
domNode.setLeft(0);
}
}

public prepareRender(ctx: RenderingContext): void {
// Nothing to read
}

public render(ctx: RestrictedRenderingContext): void {
//this._domNode.setWidth(this._editorWidth);

let keys = Object.keys(this._widgets);
for (let i = 0, len = keys.length; i < len; i++) {
let widgetId = keys[i];
this._renderWidget(this._widgets[widgetId]);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export class EditorScrollbar extends ViewPart {
const layoutInfo = this._context.configuration.editor.layoutInfo;

this.scrollbarDomNode.setLeft(layoutInfo.contentLeft);
this.scrollbarDomNode.setTop(layoutInfo.contentTop);
this.scrollbarDomNode.setWidth(layoutInfo.contentWidth + layoutInfo.minimapWidth);
this.scrollbarDomNode.setHeight(layoutInfo.contentHeight);
}
Expand Down
Loading