diff --git a/extensions/markdown/package.json b/extensions/markdown/package.json index 0a9ad0e646ea07c855cad891d2741211e3b82d09..27d4fa8c058a506d5e9f3204e1da2ac643e5a42e 100644 --- a/extensions/markdown/package.json +++ b/extensions/markdown/package.json @@ -12,8 +12,8 @@ "Languages" ], "activationEvents": [ - "onCommand:extension.previewMarkdown", - "onCommand:extension.previewMarkdownSide" + "onCommand:markdown.showPreview", + "onCommand:markdown.showPreviewToSide" ], "contributes": { "languages": [ @@ -41,7 +41,14 @@ ], "commands": [ { - "command": "extension.previewMarkdown", + "command": "markdown.showPreview", + "title": "%markdown.openPreview%", + "category": "%markdown.category%", + "where": ["explorer/context"], + "when": "markdown" + }, + { + "command": "markdown.showPreview", "title": "%markdown.previewMarkdown.title%", "category": "%markdown.category%", "icon": { @@ -52,6 +59,7 @@ "when": "markdown" }, { + "command": "markdown.showSource", "title": "%markdown.previewMarkdown.title%", "category": "%markdown.category%", "icon": { @@ -59,11 +67,10 @@ "dark": "./media/ViewSource_inverse.svg" }, "where": ["editor/primary"], - "when": { "scheme": "markdown" }, - "command": "extension.previewMarkdown" + "when": { "scheme": "markdown" } }, { - "command": "extension.previewMarkdownSide", + "command": "markdown.showPreviewToSide", "title": "%markdown.previewMarkdownSide.title%", "where": "editor/secondary", "when": "markdown" @@ -71,12 +78,12 @@ ], "keybindings": [ { - "command": "extension.previewMarkdown", + "command": "markdown.showPreview", "key": "shift+ctrl+v", "mac": "shift+cmd+v" }, { - "command": "extension.previewMarkdownSide", + "command": "markdown.showPreviewToSide", "key": "ctrl+k v", "mac": "cmd+k v" } diff --git a/extensions/markdown/package.nls.json b/extensions/markdown/package.nls.json index d41fc234818ca025281ef805f43b0c47b39eb35f..8c3b2a994bc49a4d2768ec4a3531d5f2639d9ada 100644 --- a/extensions/markdown/package.nls.json +++ b/extensions/markdown/package.nls.json @@ -1,5 +1,6 @@ { "markdown.category" : "Markdown", + "markdown.openPreview" : "Open Preview", "markdown.previewMarkdown.title" : "Toggle Preview", "markdown.previewMarkdownSide.title" : "Open Preview to the Side" } \ No newline at end of file diff --git a/extensions/markdown/src/extension.ts b/extensions/markdown/src/extension.ts index bc0835469d240c1e1bdad1c32540a5154afd31e4..99486ad5451ed69cdf309c738a7b811d24d7319e 100644 --- a/extensions/markdown/src/extension.ts +++ b/extensions/markdown/src/extension.ts @@ -27,21 +27,22 @@ export function activate(context: ExtensionContext) { let provider = new MDDocumentContentProvider(context); let registration = vscode.workspace.registerTextDocumentContentProvider('markdown', provider); - let d1 = vscode.commands.registerCommand('extension.previewMarkdown', () => openPreview()); - let d2 = vscode.commands.registerCommand('extension.previewMarkdownSide', () => openPreview(true)); + let d1 = vscode.commands.registerCommand('markdown.showPreview', showPreview); + let d2 = vscode.commands.registerCommand('markdown.showPreviewToSide', uri => showPreview(uri, true)); + let d3 = vscode.commands.registerCommand('markdown.showSource', showSource); - context.subscriptions.push(d1, d2, registration); + context.subscriptions.push(d1, d2, d3, registration); vscode.workspace.onDidSaveTextDocument(document => { if (isMarkdownFile(document)) { - const uri = getMarkdownUri(document); + const uri = getMarkdownUri(document.uri); provider.update(uri); } }); vscode.workspace.onDidChangeTextDocument(event => { if (isMarkdownFile(event.document)) { - const uri = getMarkdownUri(event.document); + const uri = getMarkdownUri(event.document.uri); provider.update(uri); } @@ -61,22 +62,28 @@ function isMarkdownFile(document: vscode.TextDocument) { && document.uri.scheme !== 'markdown'; // prevent processing of own documents } -function getMarkdownUri(document: vscode.TextDocument) { - return document.uri.with({ scheme: 'markdown', path: document.uri.path + '.rendered', query: document.uri.toString() }); +function getMarkdownUri(uri: Uri) { + return uri.with({ scheme: 'markdown', path: uri.path + '.rendered', query: uri.toString() }); } -function openPreview(sideBySide?: boolean): void { - const activeEditor = vscode.window.activeTextEditor; - if (!activeEditor) { - vscode.commands.executeCommand('workbench.action.navigateBack'); +function showPreview(resource?: Uri, sideBySide: boolean = false) { + + if (!(resource instanceof Uri)) { + if (vscode.window.activeTextEditor) { + // we are relaxed and don't check for markdown files + resource = vscode.window.activeTextEditor.document.uri; + } + } + + if (!(resource instanceof Uri)) { + // nothing found that could be shown return; } - let markdownPreviewUri = getMarkdownUri(activeEditor.document); - vscode.commands.executeCommand('vscode.previewHtml', - markdownPreviewUri, + return vscode.commands.executeCommand('vscode.previewHtml', + getMarkdownUri(resource), getViewColumn(sideBySide), - `Preview '${path.basename(activeEditor.document.fileName)}'`); + `Preview '${path.basename(resource.fsPath)}'`); } function getViewColumn(sideBySide): ViewColumn { @@ -99,6 +106,19 @@ function getViewColumn(sideBySide): ViewColumn { return active.viewColumn; } +function showSource(mdUri: Uri) { + const docUri = Uri.parse(mdUri.query); + + for (let editor of vscode.window.visibleTextEditors) { + if (editor.document.uri.toString() === docUri.toString()) { + return vscode.window.showTextDocument(editor.document, editor.viewColumn); + } + } + + return vscode.workspace.openTextDocument(docUri).then(doc => { + return vscode.window.showTextDocument(doc); + }); +} class MDDocumentContentProvider implements TextDocumentContentProvider { private _context: ExtensionContext; diff --git a/package.json b/package.json index 218a57fec22f4df4323f42ac51e0d801618a604d..9dd9d64c2d1c57dc88ff11ce94a3479944b33827 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "vscode-debugprotocol": "1.9.0", "vscode-textmate": "1.1.0", "winreg": "1.2.0", - "xterm": "git+https://github.com/sourcelair/xterm.js.git#9d34ed8", + "xterm": "git+https://github.com/sourcelair/xterm.js.git#09d67a6", "yauzl": "2.3.1" }, "devDependencies": { diff --git a/resources/linux/debian/control.template b/resources/linux/debian/control.template index f92290eb12b9b50851a1b8ec85cdcb4ca27ac175..1d1cc3c4a8317b79a12dffa1285c9a03dbf39161 100644 --- a/resources/linux/debian/control.template +++ b/resources/linux/debian/control.template @@ -9,4 +9,4 @@ Homepage: https://code.visualstudio.com/ Installed-Size: @@INSTALLEDSIZE@@ Replaces: visual-studio-@@NAME@@ Description: Code editing. Redefined. - Visual Studio Code is a new choice of tool that combines the simplicity of a code editor with what developers need for the core edit-build-debug cycle. + Visual Studio Code is a new choice of tool that combines the simplicity of a code editor with what developers need for the core edit-build-debug cycle. See https://code.visualstudio.com/docs/setup/linux for installation instructions and FAQ. diff --git a/resources/linux/rpm/code.spec.template b/resources/linux/rpm/code.spec.template index 52abe620fe0a870a15d7f9f45edd2663c9bd79e2..17b1c63b7d94381d0fb40b40f79ecc24d5a29d50 100644 --- a/resources/linux/rpm/code.spec.template +++ b/resources/linux/rpm/code.spec.template @@ -12,7 +12,7 @@ Requires: glibc >= 2.15 AutoReq: 0 %description -Visual Studio Code is a new choice of tool that combines the simplicity of a code editor with what developers need for the core edit-build-debug cycle. +Visual Studio Code is a new choice of tool that combines the simplicity of a code editor with what developers need for the core edit-build-debug cycle. See https://code.visualstudio.com/docs/setup/linux for installation instructions and FAQ. %install mkdir -p %{buildroot}/usr/share/@@NAME@@ diff --git a/src/vs/editor/browser/editor.all.ts b/src/vs/editor/browser/editor.all.ts index 9a3a4165faa2b6af5363f7fc85f7a6dc770abd82..84d92706363effac05a71981fdf3879e84b11d09 100644 --- a/src/vs/editor/browser/editor.all.ts +++ b/src/vs/editor/browser/editor.all.ts @@ -24,6 +24,7 @@ import 'vs/css!vs/editor/contrib/inPlaceReplace/browser/inPlaceReplace'; import 'vs/editor/contrib/inPlaceReplace/common/inPlaceReplace'; import 'vs/editor/contrib/iPadShowKeyboard/browser/iPadShowKeyboard'; import 'vs/editor/contrib/linesOperations/common/linesOperations'; +import 'vs/editor/contrib/carretOperations/common/carretOperations'; import 'vs/editor/contrib/links/browser/links'; import 'vs/editor/contrib/multicursor/common/multicursor'; import 'vs/editor/contrib/outlineMarker/browser/outlineMarker'; diff --git a/src/vs/editor/browser/services/codeEditorServiceImpl.ts b/src/vs/editor/browser/services/codeEditorServiceImpl.ts index abd50689f9e8f2fc69c0d960a848404778cf5abc..12dd875b4e06785685447f86bf8ba49cb4b13ee1 100644 --- a/src/vs/editor/browser/services/codeEditorServiceImpl.ts +++ b/src/vs/editor/browser/services/codeEditorServiceImpl.ts @@ -18,9 +18,9 @@ export class CodeEditorServiceImpl extends AbstractCodeEditorService { private _styleSheet: HTMLStyleElement; private _decorationOptionProviders: {[key:string]:IModelDecorationOptionsProvider}; - constructor() { + constructor(styleSheet = dom.createStyleSheet()) { super(); - this._styleSheet = dom.createStyleSheet(); + this._styleSheet = styleSheet; this._decorationOptionProviders = Object.create(null); } @@ -141,6 +141,8 @@ class DecorationTypeOptionsProvider implements IModelDecorationOptionsProvider { public stickiness: TrackedRangeStickiness; constructor(styleSheet: HTMLStyleElement, key:string, options:IDecorationRenderOptions) { + this.refCount = 0; + var themedOpts = getThemedRenderOptions(options); this.className = DecorationRenderHelper.createCSSRules( @@ -262,6 +264,7 @@ class DecorationRenderHelper { letterSpacing: 'letter-spacing:{0};', gutterIconPath: 'background:url(\'{0}\') center center no-repeat;', + gutterIconSize: 'background-size:{0};', contentText: 'content:\'{0}\';', contentIconPath: 'content:url(\'{0}\')', @@ -321,7 +324,10 @@ class DecorationRenderHelper { let cssTextArr = []; if (typeof opts.gutterIconPath !== 'undefined') { - cssTextArr.push(strings.format(this._CSS_MAP.gutterIconPath, URI.file(opts.gutterIconPath).toString())); + cssTextArr.push(strings.format(this._CSS_MAP.gutterIconPath, URI.parse(opts.gutterIconPath).toString())); + if (typeof opts.gutterIconSize !== 'undefined') { + cssTextArr.push(strings.format(this._CSS_MAP.gutterIconSize, opts.gutterIconSize)); + } } return cssTextArr.join(''); diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index 1f48f54d6dc24119c418aeb1b2dae4e16b564114..3bc6922b5a031fb0e8daa345e6acdfc3db0dfca9 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -3711,6 +3711,7 @@ export interface IThemeDecorationRenderOptions { letterSpacing?: string; gutterIconPath?: string; + gutterIconSize?: string; overviewRulerColor?: string; diff --git a/src/vs/editor/contrib/carretOperations/common/carretOperations.ts b/src/vs/editor/contrib/carretOperations/common/carretOperations.ts new file mode 100644 index 0000000000000000000000000000000000000000..aa21fcca2cdd3c25ada3c2eff982fed859fbd588 --- /dev/null +++ b/src/vs/editor/contrib/carretOperations/common/carretOperations.ts @@ -0,0 +1,65 @@ +/*--------------------------------------------------------------------------------------------- + * 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 * as nls from 'vs/nls'; +import {KeyCode, KeyMod} from 'vs/base/common/keyCodes'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {EditorAction} from 'vs/editor/common/editorAction'; +import {ICommand, ICommonCodeEditor, IEditorActionDescriptorData} from 'vs/editor/common/editorCommon'; +import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions'; +import {MoveCarretCommand} from './moveCarretCommand'; + +class MoveCarretAction extends EditorAction { + + private left:boolean; + + constructor(descriptor:IEditorActionDescriptorData, editor:ICommonCodeEditor, left:boolean) { + super(descriptor, editor); + this.left = left; + } + + public run():TPromise { + + var commands:ICommand[] = []; + var selections = this.editor.getSelections(); + + for (var i = 0; i < selections.length; i++) { + commands.push(new MoveCarretCommand(selections[i], this.left)); + } + + this.editor.executeCommands(this.id, commands); + + return TPromise.as(true); + } +} + +class MoveCarretLeftAction extends MoveCarretAction { + static ID = 'editor.action.moveCarretLeftAction'; + + constructor(descriptor:IEditorActionDescriptorData, editor:ICommonCodeEditor) { + super(descriptor, editor, true); + } +} + +class MoveCarretRightAction extends MoveCarretAction { + static ID = 'editor.action.moveCarretRightAction'; + + constructor(descriptor:IEditorActionDescriptorData, editor:ICommonCodeEditor) { + super(descriptor, editor, false); + } +} + +CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(MoveCarretLeftAction, MoveCarretLeftAction.ID, nls.localize('carret.moveLeft', "Move Carret Left"), { + context: ContextKey.EditorTextFocus, + primary: KeyMod.Alt | KeyCode.LeftArrow, + linux: { primary: KeyMod.Alt | KeyCode.LeftArrow } +}, 'Move Carret Left')); + +CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(MoveCarretRightAction, MoveCarretRightAction.ID, nls.localize('carret.moveRight', "Move Carret Right"), { + context: ContextKey.EditorTextFocus, + primary: KeyMod.Alt | KeyCode.RightArrow, + linux: { primary: KeyMod.Alt | KeyCode.LeftArrow } +}, 'Move Carret Right')); \ No newline at end of file diff --git a/src/vs/editor/contrib/carretOperations/common/moveCarretCommand.ts b/src/vs/editor/contrib/carretOperations/common/moveCarretCommand.ts new file mode 100644 index 0000000000000000000000000000000000000000..05e5c5739e0360122ba2a2b0fc2b755b91c22686 --- /dev/null +++ b/src/vs/editor/contrib/carretOperations/common/moveCarretCommand.ts @@ -0,0 +1,74 @@ +/*--------------------------------------------------------------------------------------------- + * 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 {Range} from 'vs/editor/common/core/range'; +import {Selection} from 'vs/editor/common/core/selection'; +import {ICommand, ICursorStateComputerData, IEditOperationBuilder, ITokenizedModel} from 'vs/editor/common/editorCommon'; + +export class MoveCarretCommand implements ICommand { + + private _selection: Selection; + private _isMovingLeft: boolean; + + private _cutStartIndex: number; + private _cutEndIndex: number; + private _moved: boolean; + + private _selectionId: string; + + constructor(selection: Selection, isMovingLeft: boolean) { + this._selection = selection; + this._isMovingLeft = isMovingLeft; + } + + public getEditOperations(model: ITokenizedModel, builder: IEditOperationBuilder): void { + var s = this._selection; + this._selectionId = builder.trackSelection(s); + if (s.startLineNumber !== s.endLineNumber) { + return; + } + if (this._isMovingLeft && s.startColumn === 0) { + return; + } else if (!this._isMovingLeft && s.endColumn === model.getLineMaxColumn(s.startLineNumber)) { + return; + } + + var lineNumber = s.selectionStartLineNumber; + var lineContent = model.getLineContent(lineNumber); + + var left; + var middle; + var right; + + if (this._isMovingLeft) { + left = lineContent.substring(0, s.startColumn - 2); + middle = lineContent.substring(s.startColumn - 1, s.endColumn - 1); + right = lineContent.substring(s.startColumn - 2, s.startColumn - 1) + lineContent.substring(s.endColumn - 1); + } else { + left = lineContent.substring(0, s.startColumn - 1) + lineContent.substring(s.endColumn - 1, s.endColumn); + middle = lineContent.substring(s.startColumn - 1, s.endColumn - 1); + right = lineContent.substring(s.endColumn); + } + + var newLineContent = left + middle + right; + + builder.addEditOperation(new Range(lineNumber, 1, lineNumber, model.getLineMaxColumn(lineNumber)), null); + builder.addEditOperation(new Range(lineNumber, 1, lineNumber, 1), newLineContent); + + this._cutStartIndex = s.startColumn + (this._isMovingLeft ? -1 : 1); + this._cutEndIndex = this._cutStartIndex + s.endColumn - s.startColumn; + this._moved = true; + } + + public computeCursorState(model: ITokenizedModel, helper: ICursorStateComputerData): Selection { + var result = helper.getTrackedSelection(this._selectionId); + if (this._moved) { + result = result.setStartPosition(result.startLineNumber, this._cutStartIndex); + result = result.setEndPosition(result.startLineNumber, this._cutEndIndex); + } + return result; + } +} diff --git a/src/vs/editor/contrib/carretOperations/test/common/moveCarretCommand.test.ts b/src/vs/editor/contrib/carretOperations/test/common/moveCarretCommand.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..999f3dc305e36486ddb2b3a351972e441571c8e5 --- /dev/null +++ b/src/vs/editor/contrib/carretOperations/test/common/moveCarretCommand.test.ts @@ -0,0 +1,70 @@ +/*--------------------------------------------------------------------------------------------- + * 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 {Selection} from 'vs/editor/common/core/selection'; +import {MoveCarretCommand} from 'vs/editor/contrib/carretOperations/common/moveCarretCommand'; +import {testCommand} from 'vs/editor/test/common/commands/commandTestUtils'; + + +function testMoveCarretLeftCommand(lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection): void { + testCommand(lines, null, selection, (sel) => new MoveCarretCommand(sel, true), expectedLines, expectedSelection); +} + +function testMoveCarretRightCommand(lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection): void { + testCommand(lines, null, selection, (sel) => new MoveCarretCommand(sel, false), expectedLines, expectedSelection); +} + +suite('Editor Contrib - Move Carret Command', () => { + + test('move selection to left', function () { + testMoveCarretLeftCommand( + [ + '012345' + ], + new Selection(1, 3, 1, 5), + [ + '023145' + ], + new Selection(1, 2, 1, 4) + ); + }); + test('move selection to right', function () { + testMoveCarretRightCommand( + [ + '012345' + ], + new Selection(1, 3, 1, 5), + [ + '014235' + ], + new Selection(1, 4, 1, 6) + ); + }); + test('move selection to left - from first column - no change', function () { + testMoveCarretLeftCommand( + [ + '012345' + ], + new Selection(1, 1, 1, 1), + [ + '012345' + ], + new Selection(1, 1, 1, 1) + ); + }); + test('move selection to right - from last column - no change', function () { + testMoveCarretRightCommand( + [ + '012345' + ], + new Selection(1, 5, 1, 7), + [ + '012345' + ], + new Selection(1, 5, 1, 7) + ); + }); +}); \ No newline at end of file diff --git a/src/vs/editor/test/browser/services/decorationRenderOptions.test.ts b/src/vs/editor/test/browser/services/decorationRenderOptions.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..3d009c2647f8b7e2cb96c3ed64ab2abc5f764a54 --- /dev/null +++ b/src/vs/editor/test/browser/services/decorationRenderOptions.test.ts @@ -0,0 +1,41 @@ +/*--------------------------------------------------------------------------------------------- + * 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 * as assert from 'assert'; +import * as dom from 'vs/base/browser/dom'; +import {CodeEditorServiceImpl} from 'vs/editor/browser/services/codeEditorServiceImpl'; +import {IDecorationRenderOptions} from 'vs/editor/common/editorCommon'; + +suite('Browser Services - EditorLayoutProvider', () => { + var options: IDecorationRenderOptions = { + gutterIconPath: 'https://github.com/Microsoft/vscode/blob/master/resources/linux/code.png', + gutterIconSize: 'contain', + backgroundColor: 'red', + borderColor: 'yellow' + }; + test('register and resolve decoration type', () => { + var s = new CodeEditorServiceImpl(); + s.registerDecorationType('example', options); + assert.notEqual(s.resolveDecorationOptions('example', false), undefined); + }); + test('remove decoration type', () => { + var s = new CodeEditorServiceImpl(); + s.registerDecorationType('example', options); + assert.notEqual(s.resolveDecorationOptions('example', false), undefined); + s.removeDecorationType('example'); + assert.throws(() => s.resolveDecorationOptions('example', false)); + }); + test('css properties', () => { + var styleSheet = dom.createStyleSheet(); + var s = new CodeEditorServiceImpl(styleSheet); + s.registerDecorationType('example', options); + var sheet = styleSheet.sheet.toString(); + assert(sheet.indexOf('background: url(\'https://github.com/Microsoft/vscode/blob/master/resources/linux/code.png\') center center no-repeat;') > 0); + assert(sheet.indexOf('background-size: contain;') > 0); + assert(sheet.indexOf('border-color: yellow;') > 0); + assert(sheet.indexOf('background-color: red;') > 0); + }); +}); diff --git a/src/vs/platform/extensionManagement/node/extensionManagementUtil.ts b/src/vs/platform/extensionManagement/node/extensionManagementUtil.ts index 16e731698e576476af7498a454cb5566f64be4e7..38f64108a0cb196899faa69824159c5fe27304a0 100644 --- a/src/vs/platform/extensionManagement/node/extensionManagementUtil.ts +++ b/src/vs/platform/extensionManagement/node/extensionManagementUtil.ts @@ -36,7 +36,11 @@ export function getOutdatedExtensions(extensionsService: IExtensionManagementSer return extensionsService.getInstalled().then(installed => { const ids = installed.map(getExtensionId); - return galleryService.query({ ids, pageSize: 1000 }).then(result => { + if (installed.length === 0) { + return TPromise.as([]); + } + + return galleryService.query({ ids, pageSize: ids.length }).then(result => { const available = result.firstPage; return available.filter(extension => { diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 52ffa6080868b91f790fe98361477664e05691e9..3817db9a13c159cee18a6de37d9a495bf4eb3cf0 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -738,6 +738,13 @@ declare namespace vscode { */ gutterIconPath?: string; + /** + * Specifies the size of the gutter icon. + * Available values are 'auto', 'contain', 'cover' and any percentage value. + * For further information: https://msdn.microsoft.com/en-us/library/jj127316(v=vs.85).aspx + */ + gutterIconSize?: string; + /** * The color of the decoration in the overview ruler. Use rgba() and define transparent colors to play well with other decorations. */ diff --git a/src/vs/workbench/electron-browser/main.contribution.ts b/src/vs/workbench/electron-browser/main.contribution.ts index 0ffb3c426359880f1f28f7664d22d115b1c017b1..dfa74e52f955b4e8506c4d2e0c80349de129c5c0 100644 --- a/src/vs/workbench/electron-browser/main.contribution.ts +++ b/src/vs/workbench/electron-browser/main.contribution.ts @@ -80,7 +80,7 @@ configurationRegistry.registerConfiguration({ 'type': 'string', 'enum': ['none', 'default'], 'default': 'default', - 'description': nls.localize('updateChannel', "Configure the update channel to receive updates from. Requires a restart after change.") + 'description': nls.localize('updateChannel', "Configure whether you receive automatic updates from an update channel. Requires a restart after change.") } } }); \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/debugActionsWidget.ts b/src/vs/workbench/parts/debug/browser/debugActionsWidget.ts index ecb97c63c72fd176982ab94a94e15653ca16c9cc..be03ff13a80777de95322b168c429e0937699843 100644 --- a/src/vs/workbench/parts/debug/browser/debugActionsWidget.ts +++ b/src/vs/workbench/parts/debug/browser/debugActionsWidget.ts @@ -7,6 +7,8 @@ import lifecycle = require('vs/base/common/lifecycle'); import errors = require('vs/base/common/errors'); import severity from 'vs/base/common/severity'; import builder = require('vs/base/browser/builder'); +import dom = require('vs/base/browser/dom'); +import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import actions = require('vs/base/common/actions'); import events = require('vs/base/common/events'); import actionbar = require('vs/base/browser/ui/actionbar/actionbar'); @@ -15,17 +17,20 @@ import wbext = require('vs/workbench/common/contributions'); import debug = require('vs/workbench/parts/debug/common/debug'); import dbgactions = require('vs/workbench/parts/debug/electron-browser/debugActions'); import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { IMessageService } from 'vs/platform/message/common/message'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import IDebugService = debug.IDebugService; const $ = builder.$; +const DEBUG_ACTIONS_WIDGET_POSITION_KEY = 'debug.actionswidgetposition'; export class DebugActionsWidget implements wbext.IWorkbenchContribution { private static ID = 'debug.actionsWidget'; private $el: builder.Builder; + private dragArea: builder.Builder; private toDispose: lifecycle.IDisposable[]; private actionBar: actionbar.ActionBar; private actions: actions.IAction[]; @@ -39,12 +44,18 @@ export class DebugActionsWidget implements wbext.IWorkbenchContribution { @IMessageService private messageService: IMessageService, @ITelemetryService private telemetryService: ITelemetryService, @IDebugService private debugService: IDebugService, - @IInstantiationService private instantiationService: IInstantiationService + @IInstantiationService private instantiationService: IInstantiationService, + @IStorageService private storageService: IStorageService ) { this.$el = $().div().addClass('debug-actions-widget'); + this.dragArea = $().div().addClass('drag-area'); + this.$el.append(this.dragArea); + + const actionBarContainter = $().div().addClass('.action-bar-container'); + this.$el.append(actionBarContainter); this.toDispose = []; - this.actionBar = new actionbar.ActionBar(this.$el, { + this.actionBar = new actionbar.ActionBar(actionBarContainter, { orientation: actionbar.ActionsOrientation.HORIZONTAL }); @@ -53,6 +64,7 @@ export class DebugActionsWidget implements wbext.IWorkbenchContribution { this.hide(); this.isBuilt = false; + this.onResize(); } private registerListeners(): void { @@ -70,6 +82,33 @@ export class DebugActionsWidget implements wbext.IWorkbenchContribution { this.telemetryService.publicLog('workbenchActionExecuted', { id: e.action.id, from: 'debugActionsWidget' }); } })); + $(window).on(dom.EventType.RESIZE, () => this.onResize(), this.toDispose); + + this.dragArea.on(dom.EventType.MOUSE_DOWN, event => { + const $window = $(window); + + $window.on('mousemove', (e: MouseEvent) => { + const mouseMoveEvent = new StandardMouseEvent(e); + this.setXCoordinate(mouseMoveEvent.posx); + }).once('mouseup', (e: MouseEvent) => { + const mouseMoveEvent = new StandardMouseEvent(e); + this.storageService.store(DEBUG_ACTIONS_WIDGET_POSITION_KEY, mouseMoveEvent.posx / window.innerWidth, StorageScope.WORKSPACE); + $window.off('mousemove'); + }); + }); + } + + private onResize(): void { + const x = parseFloat(this.storageService.get(DEBUG_ACTIONS_WIDGET_POSITION_KEY, StorageScope.WORKSPACE, '0.5')) * window.innerWidth; + this.setXCoordinate(x); + } + + private setXCoordinate(x: number): void { + const halfWidgetWidth = this.$el.getHTMLElement().clientWidth / 2; + x = x + halfWidgetWidth - 16; // take into account half the size of the widget + x = Math.max(148, x); // do not allow the widget to overflow on the left + x = Math.min(x, window.innerWidth - halfWidgetWidth); // do not allow the widget to overflow on the right + this.$el.style('left', `${x}px`); } public getId(): string { diff --git a/src/vs/workbench/parts/debug/browser/debugViewer.ts b/src/vs/workbench/parts/debug/browser/debugViewer.ts index 18efc7e919f85ac00867b0ead9c7e72f13cdeff3..0f0e6601ef00d366a2d130e5bd8f11ac56f017be 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewer.ts @@ -668,6 +668,22 @@ export class VariablesAccessibilityProvider implements tree.IAccessibilityProvid } } +export class VariablesController extends BaseDebugController { + + protected onLeftClick(tree: tree.ITree, element: any, event: IMouseEvent): boolean { + // double click on primitive value: open input box to be able to set the value + if (element instanceof model.Variable && event.detail === 2) { + const expression = element; + if (expression.reference === 0) { + this.debugService.getViewModel().setSelectedExpression(expression); + } + return true; + } + + return super.onLeftClick(tree, element, event); + } +} + // watch expressions export class WatchExpressionsActionProvider implements renderer.IActionProvider { diff --git a/src/vs/workbench/parts/debug/browser/debugViews.ts b/src/vs/workbench/parts/debug/browser/debugViews.ts index 6bc164fb0a605fbf1ba8757841449e12da4dd994..da0596e6aedbb9e72a66499568d21454ef86b3b1 100644 --- a/src/vs/workbench/parts/debug/browser/debugViews.ts +++ b/src/vs/workbench/parts/debug/browser/debugViews.ts @@ -75,7 +75,7 @@ export class VariablesView extends viewlet.CollapsibleViewletView { dataSource: new viewer.VariablesDataSource(this.debugService), renderer: this.instantiationService.createInstance(viewer.VariablesRenderer), accessibilityProvider: new viewer.VariablesAccessibilityProvider(), - controller: new viewer.BaseDebugController(this.debugService, this.contextMenuService, new viewer.VariablesActionProvider(this.instantiationService)) + controller: new viewer.VariablesController(this.debugService, this.contextMenuService, new viewer.VariablesActionProvider(this.instantiationService)) }, debugTreeOptions(nls.localize('variablesAriaTreeLabel', "Debug Variables"))); const viewModel = this.debugService.getViewModel(); diff --git a/src/vs/workbench/parts/debug/browser/media/debug.contribution.css b/src/vs/workbench/parts/debug/browser/media/debug.contribution.css index 12a0ebf3d2d84bdea723f179afac564f20f96940..8d683383b77471672ef0965b6365a7d9fa1d1608 100644 --- a/src/vs/workbench/parts/debug/browser/media/debug.contribution.css +++ b/src/vs/workbench/parts/debug/browser/media/debug.contribution.css @@ -130,9 +130,18 @@ padding-top: 3px; left: 50%; margin-left: -96px; + display: flex; + padding-left: 7px; } -.monaco-workbench .debug-actions-widget > .monaco-action-bar .action-label { +.monaco-workbench .debug-actions-widget .drag-area { + cursor: -webkit-grabbing; + height: 32px; + width: 10px; + background: url('drag.svg') center center no-repeat; +} + +.monaco-workbench .debug-actions-widget .monaco-action-bar .action-label { width: 32px; height: 32px; margin-right: 0; diff --git a/src/vs/workbench/parts/debug/browser/media/drag.svg b/src/vs/workbench/parts/debug/browser/media/drag.svg new file mode 100644 index 0000000000000000000000000000000000000000..7f4145d742be3500c96ff8f3aac626e7dde9eeca --- /dev/null +++ b/src/vs/workbench/parts/debug/browser/media/drag.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/vs/workbench/parts/files/browser/views/openEditorsViewer.ts b/src/vs/workbench/parts/files/browser/views/openEditorsViewer.ts index 1063cd2fb94f94e47cd939ed5580b869b737fd8b..bfc700188eeef8ff6868d40447c813ffae7577a2 100644 --- a/src/vs/workbench/parts/files/browser/views/openEditorsViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/openEditorsViewer.ts @@ -50,7 +50,7 @@ export class OpenEditor { } public getId(): string { - return `openeditor:${this.group.id}:${this.editor.getName()}:${this.editor.getDescription()}`; + return `openeditor:${this.group.id}:${this.group.indexOf(this.editor)}:${this.editor.getName()}:${this.editor.getDescription()}`; } public isPreview(): boolean {