提交 e2929f66 编写于 作者: R rebornix

cell decoration polish.

上级 923189c7
......@@ -838,3 +838,9 @@
margin: 5px 4px !important;
cursor: none;
}
.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row .cell-decoration {
top: -6px;
position: absolute;
display: flex;
}
......@@ -168,6 +168,7 @@ export interface INotebookCellDecorationOptions {
className?: string;
gutterClassName?: string;
outputClassName?: string;
topClassName?: string;
}
export interface INotebookDeltaDecoration {
......
......@@ -5,6 +5,7 @@
import { getZoomLevel } from 'vs/base/browser/browser';
import * as DOM from 'vs/base/browser/dom';
import * as strings from 'vs/base/common/strings';
import { IMouseWheelEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { IListContextMenuEvent } from 'vs/base/browser/ui/list/list';
import { IAction, Separator } from 'vs/base/common/actions';
......@@ -22,7 +23,7 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
import { Range } from 'vs/editor/common/core/range';
import { IEditor, isThemeColor } from 'vs/editor/common/editorCommon';
import { IContentDecorationRenderOptions, IEditor, isThemeColor } from 'vs/editor/common/editorCommon';
import * as nls from 'vs/nls';
import { IMenuService, MenuId } from 'vs/platform/actions/common/actions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
......@@ -1266,7 +1267,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
const existingDecorations = this._decortionKeyToIds.get(key) || [];
const newDecorations = this.viewModel.viewCells.slice(range.start, range.end).map(cell => ({
handle: cell.handle,
options: { className: decorationRule.className, outputClassName: decorationRule.className }
options: { className: decorationRule.className, outputClassName: decorationRule.className, topClassName: decorationRule.topClassName }
}));
this._decortionKeyToIds.set(key, this.deltaCellDecorations(existingDecorations, newDecorations));
......@@ -2177,10 +2178,16 @@ interface ProviderArguments {
class DecorationCSSRules {
private _theme: IColorTheme;
private _className: string;
private _topClassName: string;
get className() {
return this._className;
}
get topClassName() {
return this._topClassName;
}
constructor(
private readonly _themeService: IThemeService,
private readonly _styleSheet: RefCountedStyleSheet,
......@@ -2189,12 +2196,11 @@ class DecorationCSSRules {
this._styleSheet.ref();
this._theme = this._themeService.getColorTheme();
this._className = CSSNameHelper.getClassName(this._providerArgs.key, CellDecorationCSSRuleType.ClassName);
this._topClassName = CSSNameHelper.getClassName(this._providerArgs.key, CellDecorationCSSRuleType.TopClassName);
this._buildCSS();
}
private _buildCSS() {
this._styleSheet.insertRule('.foo { color: red; }', 0);
if (this._providerArgs.options.backgroundColor) {
const backgroundColor = this._resolveValue(this._providerArgs.options.backgroundColor);
this._styleSheet.insertRule(`.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.code-cell-row.${this.className} .cell-focus-indicator,
......@@ -2221,6 +2227,67 @@ class DecorationCSSRules {
border-color: ${borderColor} !important;
}`);
}
if (this._providerArgs.options.top) {
const unthemedCSS = this._getCSSTextForModelDecorationContentClassName(this._providerArgs.options.top);
this._styleSheet.insertRule(`.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.${this.className} .cell-decoration .${this.topClassName} {
height: 1rem;
display: block;
}`);
this._styleSheet.insertRule(`.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.${this.className} .cell-decoration .${this.topClassName}::before {
display: block;
${unthemedCSS}
}`);
}
}
/**
* Build the CSS for decorations styled before or after content.
*/
private _getCSSTextForModelDecorationContentClassName(opts: IContentDecorationRenderOptions | undefined): string {
if (!opts) {
return '';
}
const cssTextArr: string[] = [];
if (typeof opts !== 'undefined') {
this._collectBorderSettingsCSSText(opts, cssTextArr);
if (typeof opts.contentIconPath !== 'undefined') {
cssTextArr.push(strings.format(_CSS_MAP.contentIconPath, DOM.asCSSUrl(URI.revive(opts.contentIconPath))));
}
if (typeof opts.contentText === 'string') {
const truncated = opts.contentText.match(/^.*$/m)![0]; // only take first line
const escaped = truncated.replace(/['\\]/g, '\\$&');
cssTextArr.push(strings.format(_CSS_MAP.contentText, escaped));
}
this._collectCSSText(opts, ['fontStyle', 'fontWeight', 'textDecoration', 'color', 'opacity', 'backgroundColor', 'margin'], cssTextArr);
if (this._collectCSSText(opts, ['width', 'height'], cssTextArr)) {
cssTextArr.push('display:inline-block;');
}
}
return cssTextArr.join('');
}
private _collectBorderSettingsCSSText(opts: any, cssTextArr: string[]): boolean {
if (this._collectCSSText(opts, ['border', 'borderColor', 'borderRadius', 'borderSpacing', 'borderStyle', 'borderWidth'], cssTextArr)) {
cssTextArr.push(strings.format('box-sizing: border-box;'));
return true;
}
return false;
}
private _collectCSSText(opts: any, properties: string[], cssTextArr: string[]): boolean {
const lenBefore = cssTextArr.length;
for (let property of properties) {
const value = this._resolveValue(opts[property]);
if (typeof value === 'string') {
cssTextArr.push(strings.format(_CSS_MAP[property], value));
}
}
return cssTextArr.length !== lenBefore;
}
private _resolveValue(value: string | ThemeColor): string {
......@@ -2239,8 +2306,43 @@ class DecorationCSSRules {
}
}
const _CSS_MAP: { [prop: string]: string; } = {
color: 'color:{0} !important;',
opacity: 'opacity:{0};',
backgroundColor: 'background-color:{0};',
outline: 'outline:{0};',
outlineColor: 'outline-color:{0};',
outlineStyle: 'outline-style:{0};',
outlineWidth: 'outline-width:{0};',
border: 'border:{0};',
borderColor: 'border-color:{0};',
borderRadius: 'border-radius:{0};',
borderSpacing: 'border-spacing:{0};',
borderStyle: 'border-style:{0};',
borderWidth: 'border-width:{0};',
fontStyle: 'font-style:{0};',
fontWeight: 'font-weight:{0};',
textDecoration: 'text-decoration:{0};',
cursor: 'cursor:{0};',
letterSpacing: 'letter-spacing:{0};',
gutterIconPath: 'background:{0} center center no-repeat;',
gutterIconSize: 'background-size:{0};',
contentText: 'content:\'{0}\';',
contentIconPath: 'content:{0};',
margin: 'margin:{0};',
width: 'width:{0};',
height: 'height:{0};'
};
const enum CellDecorationCSSRuleType {
ClassName = 0,
TopClassName = 0,
}
class CSSNameHelper {
......
......@@ -393,7 +393,7 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR
const container = DOM.append(rootContainer, DOM.$('.cell-inner-container'));
const disposables = new DisposableStore();
const contextKeyService = disposables.add(this.contextKeyServiceProvider(container));
const decorationContainer = DOM.append(container, $('.cell-decoration'));
const decorationContainer = DOM.append(rootContainer, $('.cell-decoration'));
const titleToolbarContainer = DOM.append(container, $('.cell-title-toolbar'));
const toolbar = disposables.add(this.createToolbar(titleToolbarContainer));
const deleteToolbar = disposables.add(this.createToolbar(titleToolbarContainer, 'cell-delete-toolbar'));
......@@ -483,6 +483,8 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR
templateData.rootContainer.classList.remove(className);
});
templateData.decorationContainer.innerText = '';
this.commonRenderElement(element, templateData);
templateData.currentRenderedCell = element;
......@@ -496,6 +498,22 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR
const elementDisposables = templateData.elementDisposables;
const generateCellTopDecorations = () => {
templateData.decorationContainer.innerText = '';
element.getCellDecorations().filter(options => options.topClassName !== undefined).forEach(options => {
templateData.decorationContainer.append(DOM.$(`.${options.topClassName!}`));
});
};
elementDisposables.add(element.onCellDecorationsChanged((e) => {
const modified = e.added.find(e => e.topClassName) || e.removed.find(e => e.topClassName);
if (modified) {
generateCellTopDecorations();
}
}));
elementDisposables.add(new CellContextKeyManager(templateData.contextKeyService, this.notebookEditor, this.notebookEditor.viewModel?.notebookDocument!, element));
// render toolbar first
......@@ -655,7 +673,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
const container = DOM.append(rootContainer, DOM.$('.cell-inner-container'));
const disposables = new DisposableStore();
const contextKeyService = disposables.add(this.contextKeyServiceProvider(container));
const decorationContainer = DOM.append(container, $('.cell-decoration'));
const decorationContainer = DOM.append(rootContainer, $('.cell-decoration'));
DOM.append(container, $('.cell-focus-indicator.cell-focus-indicator-top'));
const titleToolbarContainer = DOM.append(container, $('.cell-title-toolbar'));
const toolbar = disposables.add(this.createToolbar(titleToolbarContainer));
......@@ -831,6 +849,8 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
templateData.rootContainer.classList.remove(className);
});
templateData.decorationContainer.innerText = '';
this.commonRenderElement(element, templateData);
templateData.currentRenderedCell = element;
......@@ -843,6 +863,24 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
const elementDisposables = templateData.elementDisposables;
const generateCellTopDecorations = () => {
templateData.decorationContainer.innerText = '';
element.getCellDecorations().filter(options => options.topClassName !== undefined).forEach(options => {
templateData.decorationContainer.append(DOM.$(`.${options.topClassName!}`));
});
};
elementDisposables.add(element.onCellDecorationsChanged((e) => {
const modified = e.added.find(e => e.topClassName) || e.removed.find(e => e.topClassName);
if (modified) {
generateCellTopDecorations();
}
}));
generateCellTopDecorations();
elementDisposables.add(this.instantiationService.createInstance(CodeCell, this.notebookEditor, element, templateData));
this.renderedEditors.set(element, templateData.editor);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册