mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Refresh master with initial release/0.24 snapshot (#332)
* Initial port of release/0.24 source code * Fix additional headers * Fix a typo in launch.json
This commit is contained in:
@@ -23,6 +23,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
import { editorHoverHighlight, editorHoverBackground, editorHoverBorder, textLinkForeground, textCodeBlockBackground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||
import { MarkdownRenderer } from 'vs/editor/contrib/markdown/browser/markdownRenderer';
|
||||
|
||||
@editorContribution
|
||||
export class ModesHoverController implements editorCommon.IEditorContribution {
|
||||
@@ -64,9 +65,9 @@ export class ModesHoverController implements editorCommon.IEditorContribution {
|
||||
this._hideWidgets();
|
||||
}
|
||||
}));
|
||||
|
||||
this._contentWidget = new ModesContentHoverWidget(editor, openerService, modeService);
|
||||
this._glyphWidget = new ModesGlyphHoverWidget(editor, openerService, modeService);
|
||||
const renderer = new MarkdownRenderer(editor, modeService, openerService);
|
||||
this._contentWidget = new ModesContentHoverWidget(editor, renderer);
|
||||
this._glyphWidget = new ModesGlyphHoverWidget(editor, renderer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,5 +219,4 @@ registerThemingParticipant((theme, collector) => {
|
||||
if (codeBackground) {
|
||||
collector.addRule(`.monaco-editor .monaco-editor-hover code { background-color: ${codeBackground}; }`);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -130,10 +130,8 @@ export class ContentHoverWidget extends Widget implements editorBrowser.IContent
|
||||
}
|
||||
|
||||
private updateFont(): void {
|
||||
const codeTags: HTMLElement[] = Array.prototype.slice.call(this._domNode.getElementsByTagName('code'));
|
||||
const codeClasses: HTMLElement[] = Array.prototype.slice.call(this._domNode.getElementsByClassName('code'));
|
||||
|
||||
[...codeTags, ...codeClasses].forEach(node => this._editor.applyFontInfo(node));
|
||||
codeClasses.forEach(node => this._editor.applyFontInfo(node));
|
||||
}
|
||||
|
||||
protected updateContents(node: Node): void {
|
||||
|
||||
@@ -5,28 +5,24 @@
|
||||
'use strict';
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { renderMarkdown } from 'vs/base/browser/htmlContentRenderer';
|
||||
import { IOpenerService, NullOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { IRange, Range } from 'vs/editor/common/core/range';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { HoverProviderRegistry, Hover, IColor, IColorFormatter } from 'vs/editor/common/modes';
|
||||
import { tokenizeToString } from 'vs/editor/common/modes/textToHtmlTokenizer';
|
||||
import { HoverProviderRegistry, Hover, IColor, DocumentColorProvider } from 'vs/editor/common/modes';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { getHover } from '../common/hover';
|
||||
import { HoverOperation, IHoverComputer } from './hoverOperation';
|
||||
import { ContentHoverWidget } from './hoverWidgets';
|
||||
import { IMarkdownString, MarkdownString, isEmptyMarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { IMarkdownString, MarkdownString, isEmptyMarkdownString, markedStringsEquals } from 'vs/base/common/htmlContent';
|
||||
import { MarkdownRenderer } from 'vs/editor/contrib/markdown/browser/markdownRenderer';
|
||||
import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations';
|
||||
import { ColorPickerModel } from 'vs/editor/contrib/colorPicker/browser/colorPickerModel';
|
||||
import { ColorPickerWidget } from 'vs/editor/contrib/colorPicker/browser/colorPickerWidget';
|
||||
import { ColorDetector } from 'vs/editor/contrib/colorPicker/browser/colorDetector';
|
||||
import { Color, RGBA } from 'vs/base/common/color';
|
||||
import { IDisposable, empty as EmptyDisposable, dispose, combinedDisposable } from 'vs/base/common/lifecycle';
|
||||
import { getColorPresentations } from 'vs/editor/contrib/colorPicker/common/color';
|
||||
const $ = dom.$;
|
||||
|
||||
class ColorHover {
|
||||
@@ -34,7 +30,7 @@ class ColorHover {
|
||||
constructor(
|
||||
public readonly range: IRange,
|
||||
public readonly color: IColor,
|
||||
public readonly formatters: IColorFormatter[]
|
||||
public readonly provider: DocumentColorProvider
|
||||
) { }
|
||||
}
|
||||
|
||||
@@ -95,13 +91,13 @@ class ModesContentComputer implements IHoverComputer<HoverPart[]> {
|
||||
}
|
||||
|
||||
const range = new Range(this._range.startLineNumber, startColumn, this._range.startLineNumber, endColumn);
|
||||
const colorRange = colorDetector.getColorRange(d.range.getStartPosition());
|
||||
const colorData = colorDetector.getColorData(d.range.getStartPosition());
|
||||
|
||||
if (!didFindColor && colorRange) {
|
||||
if (!didFindColor && colorData) {
|
||||
didFindColor = true;
|
||||
|
||||
const { color, formatters } = colorRange;
|
||||
return new ColorHover(d.range, color, formatters);
|
||||
const { color, range } = colorData.colorInfo;
|
||||
return new ColorHover(range, color, colorData.provider);
|
||||
} else {
|
||||
if (isEmptyMarkdownString(d.options.hoverMessage)) {
|
||||
return null;
|
||||
@@ -166,22 +162,20 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
|
||||
private _hoverOperation: HoverOperation<HoverPart[]>;
|
||||
private _highlightDecorations: string[];
|
||||
private _isChangingDecorations: boolean;
|
||||
private _openerService: IOpenerService;
|
||||
private _modeService: IModeService;
|
||||
private _markdownRenderer: MarkdownRenderer;
|
||||
private _shouldFocus: boolean;
|
||||
private _colorPicker: ColorPickerWidget;
|
||||
|
||||
private renderDisposable: IDisposable = EmptyDisposable;
|
||||
private toDispose: IDisposable[];
|
||||
|
||||
constructor(editor: ICodeEditor, openerService: IOpenerService, modeService: IModeService) {
|
||||
constructor(editor: ICodeEditor, markdownRenderner: MarkdownRenderer) {
|
||||
super(ModesContentHoverWidget.ID, editor);
|
||||
|
||||
this._computer = new ModesContentComputer(this._editor);
|
||||
this._highlightDecorations = [];
|
||||
this._isChangingDecorations = false;
|
||||
this._openerService = openerService || NullOpenerService;
|
||||
this._modeService = modeService;
|
||||
this._markdownRenderer = markdownRenderner;
|
||||
|
||||
this._hoverOperation = new HoverOperation(
|
||||
this._computer,
|
||||
@@ -249,6 +243,9 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
|
||||
}
|
||||
}
|
||||
if (filteredMessages.length > 0) {
|
||||
if (hoverContentsEquals(filteredMessages, this._messages)) {
|
||||
return;
|
||||
}
|
||||
this._renderMessages(range, filteredMessages);
|
||||
} else {
|
||||
this.hide();
|
||||
@@ -300,6 +297,7 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
|
||||
highlightRange = messages[0].range,
|
||||
fragment = document.createDocumentFragment();
|
||||
|
||||
let containColorPicker = false;
|
||||
messages.forEach((msg) => {
|
||||
if (!msg.range) {
|
||||
return;
|
||||
@@ -312,75 +310,91 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
|
||||
msg.contents
|
||||
.filter(contents => !isEmptyMarkdownString(contents))
|
||||
.forEach(contents => {
|
||||
const renderedContents = renderMarkdown(contents, {
|
||||
actionCallback: (content) => {
|
||||
this._openerService.open(URI.parse(content)).then(void 0, onUnexpectedError);
|
||||
},
|
||||
codeBlockRenderer: (languageAlias, value): string | TPromise<string> => {
|
||||
// In markdown,
|
||||
// it is possible that we stumble upon language aliases (e.g.js instead of javascript)
|
||||
// it is possible no alias is given in which case we fall back to the current editor lang
|
||||
const modeId = languageAlias
|
||||
? this._modeService.getModeIdForLanguageName(languageAlias)
|
||||
: this._editor.getModel().getLanguageIdentifier().language;
|
||||
|
||||
return this._modeService.getOrCreateMode(modeId).then(_ => {
|
||||
return tokenizeToString(value, modeId);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const renderedContents = this._markdownRenderer.render(contents);
|
||||
fragment.appendChild($('div.hover-row', null, renderedContents));
|
||||
});
|
||||
} else {
|
||||
containColorPicker = true;
|
||||
|
||||
const { red, green, blue, alpha } = msg.color;
|
||||
const rgba = new RGBA(red * 255, green * 255, blue * 255, alpha);
|
||||
const color = new Color(rgba);
|
||||
|
||||
const formatters = [...msg.formatters];
|
||||
const text = this._editor.getModel().getValueInRange(msg.range);
|
||||
|
||||
let formatterIndex = 0;
|
||||
|
||||
for (let i = 0; i < formatters.length; i++) {
|
||||
if (text === formatters[i].format(msg.color)) {
|
||||
formatterIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const model = new ColorPickerModel(color, formatters, formatterIndex);
|
||||
const widget = new ColorPickerWidget(fragment, model, this._editor.getConfiguration().pixelRatio);
|
||||
|
||||
const editorModel = this._editor.getModel();
|
||||
let range = new Range(msg.range.startLineNumber, msg.range.startColumn, msg.range.endLineNumber, msg.range.endColumn);
|
||||
let colorInfo = { range: msg.range, color: msg.color };
|
||||
|
||||
const updateEditorModel = () => {
|
||||
const text = model.formatter.format({
|
||||
red: model.color.rgba.r / 255,
|
||||
green: model.color.rgba.g / 255,
|
||||
blue: model.color.rgba.b / 255,
|
||||
alpha: model.color.rgba.a
|
||||
// create blank olor picker model and widget first to ensure it's positioned correctly.
|
||||
const model = new ColorPickerModel(color, [], 0);
|
||||
const widget = new ColorPickerWidget(fragment, model, this._editor.getConfiguration().pixelRatio);
|
||||
|
||||
getColorPresentations(editorModel, colorInfo, msg.provider).then(colorPresentations => {
|
||||
model.colorPresentations = colorPresentations;
|
||||
const originalText = this._editor.getModel().getValueInRange(msg.range);
|
||||
model.guessColorPresentation(color, originalText);
|
||||
|
||||
const updateEditorModel = () => {
|
||||
let textEdits;
|
||||
let newRange;
|
||||
if (model.presentation.textEdit) {
|
||||
textEdits = [model.presentation.textEdit];
|
||||
newRange = new Range(
|
||||
model.presentation.textEdit.range.startLineNumber,
|
||||
model.presentation.textEdit.range.startColumn,
|
||||
model.presentation.textEdit.range.endLineNumber,
|
||||
model.presentation.textEdit.range.endColumn
|
||||
);
|
||||
newRange = newRange.setEndPosition(newRange.endLineNumber, newRange.startColumn + model.presentation.textEdit.text.length);
|
||||
} else {
|
||||
textEdits = [{ identifier: null, range, text: model.presentation.label, forceMoveMarkers: false }];
|
||||
newRange = range.setEndPosition(range.endLineNumber, range.startColumn + model.presentation.label.length);
|
||||
}
|
||||
|
||||
editorModel.pushEditOperations([], textEdits, () => []);
|
||||
|
||||
if (model.presentation.additionalTextEdits) {
|
||||
textEdits = [...model.presentation.additionalTextEdits];
|
||||
editorModel.pushEditOperations([], textEdits, () => []);
|
||||
this.hide();
|
||||
}
|
||||
this._editor.pushUndoStop();
|
||||
range = newRange;
|
||||
};
|
||||
|
||||
const updateColorPresentations = (color: Color) => {
|
||||
return getColorPresentations(editorModel, {
|
||||
range: range,
|
||||
color: {
|
||||
red: color.rgba.r / 255,
|
||||
green: color.rgba.g / 255,
|
||||
blue: color.rgba.b / 255,
|
||||
alpha: color.rgba.a
|
||||
}
|
||||
}, msg.provider).then((colorPresentations) => {
|
||||
model.colorPresentations = colorPresentations;
|
||||
});
|
||||
};
|
||||
|
||||
const colorListener = model.onColorFlushed((color: Color) => {
|
||||
updateColorPresentations(color).then(updateEditorModel);
|
||||
});
|
||||
editorModel.pushEditOperations([], [{ identifier: null, range, text, forceMoveMarkers: false }], () => []);
|
||||
this._editor.pushUndoStop();
|
||||
range = range.setEndPosition(range.endLineNumber, range.startColumn + text.length);
|
||||
};
|
||||
const colorChangeListener = model.onDidChangeColor(updateColorPresentations);
|
||||
|
||||
const colorListener = model.onColorFlushed(updateEditorModel);
|
||||
this._colorPicker = widget;
|
||||
this.showAt(new Position(renderRange.startLineNumber, renderColumn), this._shouldFocus);
|
||||
this.updateContents(fragment);
|
||||
this._colorPicker.layout();
|
||||
|
||||
this._colorPicker = widget;
|
||||
this.renderDisposable = combinedDisposable([colorListener, widget]);
|
||||
this.renderDisposable = combinedDisposable([colorListener, colorChangeListener, widget]);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// show
|
||||
this.showAt(new Position(renderRange.startLineNumber, renderColumn), this._shouldFocus);
|
||||
|
||||
this.updateContents(fragment);
|
||||
|
||||
if (this._colorPicker) {
|
||||
this._colorPicker.layout();
|
||||
if (!containColorPicker) {
|
||||
this.showAt(new Position(renderRange.startLineNumber, renderColumn), this._shouldFocus);
|
||||
this.updateContents(fragment);
|
||||
}
|
||||
|
||||
this._isChangingDecorations = true;
|
||||
@@ -395,3 +409,23 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
|
||||
className: 'hoverHighlight'
|
||||
});
|
||||
}
|
||||
|
||||
function hoverContentsEquals(first: HoverPart[], second: HoverPart[]): boolean {
|
||||
if ((!first && second) || (first && !second) || first.length !== second.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < first.length; i++) {
|
||||
const firstElement = first[i];
|
||||
const secondElement = second[i];
|
||||
if (firstElement instanceof ColorHover) {
|
||||
return false;
|
||||
}
|
||||
if (secondElement instanceof ColorHover) {
|
||||
return false;
|
||||
}
|
||||
if (!markedStringsEquals(firstElement.contents, secondElement.contents)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -8,13 +8,7 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { HoverOperation, IHoverComputer } from './hoverOperation';
|
||||
import { GlyphHoverWidget } from './hoverWidgets';
|
||||
import { $ } from 'vs/base/browser/dom';
|
||||
import { renderMarkdown } from 'vs/base/browser/htmlContentRenderer';
|
||||
import { IOpenerService, NullOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { tokenizeToString } from 'vs/editor/common/modes/textToHtmlTokenizer';
|
||||
import { MarkdownRenderer } from 'vs/editor/contrib/markdown/browser/markdownRenderer';
|
||||
import { IMarkdownString, isEmptyMarkdownString } from 'vs/base/common/htmlContent';
|
||||
|
||||
export interface IHoverMessage {
|
||||
@@ -94,16 +88,16 @@ export class ModesGlyphHoverWidget extends GlyphHoverWidget {
|
||||
private _messages: IHoverMessage[];
|
||||
private _lastLineNumber: number;
|
||||
|
||||
private _markdownRenderer: MarkdownRenderer;
|
||||
private _computer: MarginComputer;
|
||||
private _hoverOperation: HoverOperation<IHoverMessage[]>;
|
||||
|
||||
constructor(editor: ICodeEditor, private openerService: IOpenerService, private modeService: IModeService) {
|
||||
constructor(editor: ICodeEditor, markdownRenderer: MarkdownRenderer) {
|
||||
super(ModesGlyphHoverWidget.ID, editor);
|
||||
|
||||
this.openerService = openerService || NullOpenerService;
|
||||
|
||||
this._lastLineNumber = -1;
|
||||
|
||||
this._markdownRenderer = markdownRenderer;
|
||||
this._computer = new MarginComputer(this._editor);
|
||||
|
||||
this._hoverOperation = new HoverOperation(
|
||||
@@ -166,17 +160,7 @@ export class ModesGlyphHoverWidget extends GlyphHoverWidget {
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
messages.forEach((msg) => {
|
||||
const renderedContents = renderMarkdown(msg.value, {
|
||||
actionCallback: content => this.openerService.open(URI.parse(content)).then(undefined, onUnexpectedError),
|
||||
codeBlockRenderer: (languageAlias, value): string | TPromise<string> => {
|
||||
// In markdown, it is possible that we stumble upon language aliases (e.g. js instead of javascript)
|
||||
const modeId = this.modeService.getModeIdForLanguageName(languageAlias);
|
||||
return this.modeService.getOrCreateMode(modeId).then(_ => {
|
||||
return tokenizeToString(value, modeId);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const renderedContents = this._markdownRenderer.render(msg.value);
|
||||
fragment.appendChild($('div.hover-row', null, renderedContents));
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user