diff --git a/src/vs/base/browser/builder.ts b/src/vs/base/browser/builder.ts index 0f6307e1d87bffed4ca2fad59295812228e00294..9206787843606c4a02516679b4743b4ebbe6d8bf 100644 --- a/src/vs/base/browser/builder.ts +++ b/src/vs/base/browser/builder.ts @@ -857,7 +857,8 @@ export class Builder implements IDisposable { * a) a single string passed in as argument will return the style value using the * string as key from the current element of the builder. * b) two strings passed in will set the style value identified by the first - * parameter to match the second parameter. + * parameter to match the second parameter. The second parameter can be null + * to unset a style * c) an object literal passed in will apply the properties of the literal as styles * to the current element of the builder. */ @@ -874,15 +875,19 @@ export class Builder implements IDisposable { this.doSetStyle(prop, value); } } + + return this; } + const hasFirstP = types.isString(firstP); + // Get Style Value - else if (types.isString(firstP) && !types.isString(secondP)) { + if (hasFirstP && types.isUndefined(secondP)) { return this.currentElement.style[this.cssKeyToJavaScriptProperty(firstP)]; } // Set Style Value - else if (types.isString(firstP) && types.isString(secondP)) { + else if (hasFirstP) { this.doSetStyle(firstP, secondP); } diff --git a/src/vs/workbench/browser/parts/editor/editorGroupsControl.ts b/src/vs/workbench/browser/parts/editor/editorGroupsControl.ts index 52cfa611c9e3eff83d4be60ddf8d5230d2fedee9..e043102d6ef9ad05e5d909b23be0451da53cdd1b 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupsControl.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupsControl.ts @@ -34,8 +34,8 @@ import { extractResources } from 'vs/base/browser/dnd'; import { IWindowService } from 'vs/platform/windows/common/windows'; import { getCodeEditor } from 'vs/editor/common/services/codeEditorService'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { editorBackground, highContrastBorder } from 'vs/platform/theme/common/colorRegistry'; -import { Themable, TABS_CONTAINER_BACKGROUND, NO_TABS_CONTAINER_BACKGROUND, EDITOR_GROUP_BORDER_COLOR } from 'vs/workbench/common/theme'; +import { editorBackground, highContrastBorder, highContrastOutline } from 'vs/platform/theme/common/colorRegistry'; +import { Themable, TABS_CONTAINER_BACKGROUND, NO_TABS_CONTAINER_BACKGROUND, EDITOR_GROUP_BORDER_COLOR, EDITOR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme'; export enum Rochade { NONE, @@ -396,9 +396,6 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro // Show editor container editor.getContainer().show(); - - // Styles - this.updateParentStyle(); } private getVisibleEditorCount(): number { @@ -603,21 +600,9 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro } } - // Styles - this.updateParentStyle(); - return result; } - private updateParentStyle(): void { - const editorCount = this.getVisibleEditorCount(); - if (editorCount > 1) { - this.parent.addClass('multiple-editors'); - } else { - this.parent.removeClass('multiple-editors'); - } - } - private doSetActive(editor: BaseEditor, newActive: Position): void { this.lastActivePosition = newActive; this.lastActiveEditor = editor; @@ -934,7 +919,6 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro } protected updateStyles(): void { - const isHighContrast = (this.theme.type === 'hc'); // Editor container colors this.silos.forEach((silo, index) => { @@ -954,9 +938,9 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro const container = this.getTitleAreaControl(position).getContainer(); container.style.backgroundColor = this.getColor(this.tabOptions.showTabs ? TABS_CONTAINER_BACKGROUND : NO_TABS_CONTAINER_BACKGROUND); - container.style.borderBottomWidth = (isHighContrast && this.tabOptions.showTabs) ? '1px' : null; - container.style.borderBottomStyle = (isHighContrast && this.tabOptions.showTabs) ? 'solid' : null; - container.style.borderBottomColor = (isHighContrast && this.tabOptions.showTabs) ? this.getColor(highContrastBorder) : null; + container.style.borderBottomWidth = (this.isHighContrastTheme && this.tabOptions.showTabs) ? '1px' : null; + container.style.borderBottomStyle = (this.isHighContrastTheme && this.tabOptions.showTabs) ? 'solid' : null; + container.style.borderBottomColor = (this.isHighContrastTheme && this.tabOptions.showTabs) ? this.getColor(highContrastBorder) : null; }); } @@ -995,7 +979,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro } function onDrop(e: DragEvent, position: Position, splitTo?: Position): void { - DOM.removeClass(node, 'dropfeedback'); + $this.updateFromDropping(node, false); cleanUp(); const editorService = $this.editorService; @@ -1163,7 +1147,12 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro if (container && DOM.isAncestor(target, container.getHTMLElement())) { overlay = $('div').style({ top: $this.tabOptions.showTabs ? `${EditorGroupsControl.EDITOR_TITLE_HEIGHT}px` : 0, - height: $this.tabOptions.showTabs ? `calc(100% - ${EditorGroupsControl.EDITOR_TITLE_HEIGHT}px` : '100%' + height: $this.tabOptions.showTabs ? `calc(100% - ${EditorGroupsControl.EDITOR_TITLE_HEIGHT}px` : '100%', + backgroundColor: $this.getColor(EDITOR_DRAG_AND_DROP_BACKGROUND), + outlineColor: $this.isHighContrastTheme ? $this.getColor(highContrastOutline) : null, + outlineOffset: $this.isHighContrastTheme ? '-2px' : null, + outlineStyle: $this.isHighContrastTheme ? 'dashed' : null, + outlineWidth: $this.isHighContrastTheme ? '2px' : null }).id(overlayId); overlay.appendTo(container); @@ -1204,7 +1193,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro DOM.EventHelper.stop(e, true); onDrop(e, Position.ONE); } else { - DOM.removeClass(node, 'dropfeedback'); + this.updateFromDropping(node, false); } })); @@ -1216,7 +1205,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro } counter++; - DOM.addClass(node, 'dropfeedback'); + this.updateFromDropping(node, true); const target = e.target; if (target) { @@ -1226,7 +1215,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro createOverlay(target); if (overlay) { - DOM.removeClass(node, 'dropfeedback'); // if we show an overlay, we can remove the drop feedback from the editor background + this.updateFromDropping(node, false); // if we show an overlay, we can remove the drop feedback from the editor background } } })); @@ -1235,7 +1224,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro this.toUnbind.push(DOM.addDisposableListener(node, DOM.EventType.DRAG_LEAVE, (e: DragEvent) => { counter--; if (counter === 0) { - DOM.removeClass(node, 'dropfeedback'); + this.updateFromDropping(node, false); } })); @@ -1243,7 +1232,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro [node, window].forEach(container => { this.toUnbind.push(DOM.addDisposableListener(container, DOM.EventType.DRAG_END, (e: DragEvent) => { counter = 0; - DOM.removeClass(node, 'dropfeedback'); + this.updateFromDropping(node, false); cleanUp(); })); }); @@ -1318,7 +1307,6 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro let oldNewPos: number = null; this.silos[position].addClass('drag'); - this.parent.addClass('drag'); const $window = $(window); $window.on(DOM.EventType.MOUSE_MOVE, (e: MouseEvent) => { @@ -1421,8 +1409,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro // Move the editor to provide feedback to the user and add class if (newPos !== null) { this.posSilo(position, `${newPos}px`); - this.silos[position].addClass('dragging'); - this.parent.addClass('dragging'); + this.updateFromDragging(position, true); } }).once(DOM.EventType.MOUSE_UP, (e: MouseEvent) => { DOM.EventHelper.stop(e, false); @@ -1437,10 +1424,8 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro } // Restore styles - this.parent.removeClass('drag'); this.silos[position].removeClass('drag'); - this.parent.removeClass('dragging'); - this.silos[position].removeClass('dragging'); + this.updateFromDragging(position, false); POSITIONS.forEach(p => this.silos[p].removeClass('draggedunder')); this.posSilo(Position.ONE, 0, 'auto'); @@ -1472,6 +1457,37 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro }); } + private updateFromDragging(position: Position, isDragging: boolean): void { + const silo = this.silos[position]; + if (silo.hasClass('dragging') === isDragging) { + return; // avoid repeated work + } + + let borderColor = null; + if (isDragging) { + this.parent.addClass('dragging'); + silo.addClass('dragging'); + borderColor = this.getColor(EDITOR_GROUP_BORDER_COLOR); + } else { + this.parent.removeClass('dragging'); + silo.removeClass('dragging'); + } + + silo.style(this.layoutVertically ? 'border-left-color' : 'border-top-color', borderColor); + silo.style(this.layoutVertically ? 'border-right-color' : 'border-bottom-color', borderColor); + } + + private updateFromDropping(element: HTMLElement, isDropping: boolean): void { + const background = this.getColor(isDropping ? EDITOR_DRAG_AND_DROP_BACKGROUND : null); + element.style.backgroundColor = background; + + const useOutline = this.isHighContrastTheme && isDropping; + element.style.outlineColor = useOutline ? this.getColor(highContrastOutline) : null; + element.style.outlineStyle = useOutline ? 'dashed' : null; + element.style.outlineWidth = useOutline ? '2px' : null; + (element).style.outlineOffset = useOutline ? '-2px' : null; // TODO@theme TS fail (gulp watch) + } + private posSilo(pos: number, leftTop: string | number, rightBottom?: string | number, borderLeftTopWidth?: string | number): void { let style: any; if (this.layoutVertically) { diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index 4cc3f1fdac6ea3969e4a41c0f742001d9fcc3e1d..dca7714ed6efce1ab58541bc7faecb0e546cd925 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -40,6 +40,7 @@ import Event, { Emitter } from 'vs/base/common/event'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { editorBackground } from 'vs/platform/theme/common/colorRegistry'; +import { EDITOR_GROUP_BACKGROUND } from 'vs/workbench/common/theme'; class ProgressMonitor { @@ -179,9 +180,15 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService this.toUnbind.push(this.stacks.onEditorDisposed(identifier => this.onEditorDisposed(identifier))); this.toUnbind.push(this.stacks.onEditorOpened(identifier => this.onEditorOpened(identifier))); this.toUnbind.push(this.stacks.onEditorClosed(event => this.onEditorClosed(event))); + this.toUnbind.push(this.stacks.onGroupOpened(event => this.onEditorGroupOpenedOrClosed())); + this.toUnbind.push(this.stacks.onGroupClosed(event => this.onEditorGroupOpenedOrClosed())); this.toUnbind.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationUpdated(e.config))); } + private onEditorGroupOpenedOrClosed(): void { + this.updateStyles(); + } + private onConfigurationUpdated(configuration: IWorkbenchEditorConfiguration): void { if (configuration && configuration.workbench && configuration.workbench.editor) { const editorConfig = configuration.workbench.editor; @@ -913,8 +920,22 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupService } protected updateStyles(): void { + + // Part container const container = this.getContainer(); container.style('background-color', this.getColor(editorBackground)); + + // Content area + const content = this.getContentArea(); + + const groupCount = this.stacks.groups.length; + if (groupCount > 1) { + content.addClass('multiple-groups'); + } else { + content.removeClass('multiple-groups'); + } + + content.style('background-color', groupCount > 0 ? this.getColor(EDITOR_GROUP_BACKGROUND) : null); } private onGroupFocusChanged(): void { diff --git a/src/vs/workbench/browser/parts/editor/media/editorGroupsControl.css b/src/vs/workbench/browser/parts/editor/media/editorGroupsControl.css index 548621bf999b423bf8b1be4231ee8eb219d89147..de949651215d4f1d478e205b6f63b5e7ee85493a 100644 --- a/src/vs/workbench/browser/parts/editor/media/editorGroupsControl.css +++ b/src/vs/workbench/browser/parts/editor/media/editorGroupsControl.css @@ -19,13 +19,6 @@ opacity: 0; /* initially not visible until moving around */ } -.hc-black #monaco-workbench-editor-drop-overlay, -.hc-black .monaco-workbench > .editor.empty > .content.dropfeedback { - background: none !important; - outline: 2px dashed; - outline-offset: -2px; -} - .monaco-workbench > .editor > .content > .one-editor-silo { position: absolute; box-sizing: border-box; /* use border box to be able to draw a border as separator between editors */ @@ -91,59 +84,4 @@ .monaco-workbench > .editor > .content > .one-editor-silo > .container > .editor-container { height: calc(100% - 35px); /* Editor is below editor title */ -} - -/* TODO@theme */ - -.vs .monaco-workbench > .editor > .content.drag { - background-color: #ECECEC; -} - -.vs-dark .monaco-workbench > .editor > .content.drag { - background-color: #2D2D2D; -} - -.vs #monaco-workbench-editor-drop-overlay, -.vs .monaco-workbench > .editor.empty > .content.dropfeedback { - background-color: rgba(51,153,255, 0.18); -} - -.vs-dark #monaco-workbench-editor-drop-overlay, -.vs-dark .monaco-workbench > .editor.empty > .content.dropfeedback { - background-color: rgba(83, 89, 93, 0.5); -} - -.hc-black #monaco-workbench-editor-drop-overlay, -.hc-black .monaco-workbench > .editor.empty > .content.dropfeedback { - outline-color: #f38518; -} - -.vs .monaco-workbench > .editor > .content.vertical-layout > .one-editor-silo.dragging { - border-left-color: #E7E7E7; - border-right-color: #E7E7E7; -} - -.vs .monaco-workbench > .editor > .content.horizontal-layout > .one-editor-silo.dragging { - border-top-color: #E7E7E7; - border-bottom-color: #E7E7E7; -} - -.vs-dark .monaco-workbench > .editor > .content.vertical-layout > .one-editor-silo.dragging { - border-left-color: #444; - border-right-color: #444; -} - -.vs-dark .monaco-workbench > .editor > .content.horizontal-layout > .one-editor-silo.dragging { - border-top-color: #444; - border-bottom-color: #444; -} - -.hc-black .monaco-workbench > .editor > .content.vertical-layout > .one-editor-silo.dragging { - border-left-color: #6FC3DF; - border-right-color: #6FC3DF; -} - -.hc-black .monaco-workbench > .editor > .content.horizontal-layout > .one-editor-silo.dragging { - border-top-color: #6FC3DF; - border-bottom-color: #6FC3DF; } \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/editor/media/notabstitle.css b/src/vs/workbench/browser/parts/editor/media/notabstitle.css index 0c88fc4ea6eee9235a88d22cbc14cf79fbcc6038..5ceb63642db4930a3647414570cc1ff112af3699 100644 --- a/src/vs/workbench/browser/parts/editor/media/notabstitle.css +++ b/src/vs/workbench/browser/parts/editor/media/notabstitle.css @@ -41,7 +41,7 @@ background: url('close-inverse.svg') center center no-repeat; } -/* TODO@theme */ +/* TODO@theme (widgets) */ .vs .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .title-actions, .vs-dark .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .title-actions, diff --git a/src/vs/workbench/browser/parts/editor/media/tabstitle.css b/src/vs/workbench/browser/parts/editor/media/tabstitle.css index 924c1cded9984f40653b7daebc6ae6cfeb87041f..90a6c105bcbec8b95b2e2821f2b8278334dd203f 100644 --- a/src/vs/workbench/browser/parts/editor/media/tabstitle.css +++ b/src/vs/workbench/browser/parts/editor/media/tabstitle.css @@ -64,13 +64,6 @@ outline-offset: -5px; } -.hc-black .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container.dropfeedback, -.hc-black .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.dropfeedback { - background: none !important; - outline: 2px dashed; - outline-offset: -5px; -} - /* Tab Label */ .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab .tab-label { @@ -178,30 +171,4 @@ cursor: default; flex: initial; padding-left: 4px; -} - -/* TODO@theme */ - -.hc-black .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.active, -.hc-black .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.active:hover { - outline-color: #f38518; -} - -.hc-black .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab:hover { - outline-color: #f38518; -} - -.vs .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container.dropfeedback, -.vs .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.dropfeedback { - background-color: #DDECFF; -} - -.vs-dark .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container.dropfeedback, -.vs-dark .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.dropfeedback { - background-color: #383B3D; -} - -.hc-black .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container.dropfeedback, -.hc-black .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.dropfeedback { - outline-color: #f38518; } \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/editor/media/titlecontrol.css b/src/vs/workbench/browser/parts/editor/media/titlecontrol.css index 5a150ed4368cb5dbb47d0b60b684f76d537fb0e2..7f7fe4a23c72ed15e0796b7bc9662eb511512cee 100644 --- a/src/vs/workbench/browser/parts/editor/media/titlecontrol.css +++ b/src/vs/workbench/browser/parts/editor/media/titlecontrol.css @@ -50,21 +50,21 @@ } /* Drag Cursor */ -.monaco-workbench > .part.editor > .content.multiple-editors > .one-editor-silo > .container > .title, -.monaco-workbench > .part.editor > .content.multiple-editors > .one-editor-silo > .container > .title.tabs .scrollbar .slider, -.monaco-workbench > .part.editor > .content.multiple-editors > .one-editor-silo > .container > .title .monaco-icon-label::before, -.monaco-workbench > .part.editor > .content.multiple-editors > .one-editor-silo > .container > .title .title-label a, -.monaco-workbench > .part.editor > .content.multiple-editors > .one-editor-silo > .container > .title .title-label span { +.monaco-workbench > .part.editor > .content.multiple-groups > .one-editor-silo > .container > .title, +.monaco-workbench > .part.editor > .content.multiple-groups > .one-editor-silo > .container > .title.tabs .scrollbar .slider, +.monaco-workbench > .part.editor > .content.multiple-groups > .one-editor-silo > .container > .title .monaco-icon-label::before, +.monaco-workbench > .part.editor > .content.multiple-groups > .one-editor-silo > .container > .title .title-label a, +.monaco-workbench > .part.editor > .content.multiple-groups > .one-editor-silo > .container > .title .title-label span { cursor: -webkit-grab; } #monaco-workbench-editor-move-overlay, -.monaco-workbench > .part.editor > .content.multiple-editors > .one-editor-silo.drag, -.monaco-workbench > .part.editor > .content.multiple-editors > .one-editor-silo.drag > .container > .title, -.monaco-workbench > .part.editor > .content.multiple-editors > .one-editor-silo.drag > .container > .title.tabs .scrollbar .slider, -.monaco-workbench > .part.editor > .content.multiple-editors > .one-editor-silo.drag > .container > .title .monaco-icon-label::before, -.monaco-workbench > .part.editor > .content.multiple-editors > .one-editor-silo.drag > .container > .title .title-label a, -.monaco-workbench > .part.editor > .content.multiple-editors > .one-editor-silo.drag > .container > .title .title-label span { +.monaco-workbench > .part.editor > .content.multiple-groups > .one-editor-silo.drag, +.monaco-workbench > .part.editor > .content.multiple-groups > .one-editor-silo.drag > .container > .title, +.monaco-workbench > .part.editor > .content.multiple-groups > .one-editor-silo.drag > .container > .title.tabs .scrollbar .slider, +.monaco-workbench > .part.editor > .content.multiple-groups > .one-editor-silo.drag > .container > .title .monaco-icon-label::before, +.monaco-workbench > .part.editor > .content.multiple-groups > .one-editor-silo.drag > .container > .title .title-label a, +.monaco-workbench > .part.editor > .content.multiple-groups > .one-editor-silo.drag > .container > .title .title-label span { cursor: -webkit-grabbing; } diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index 4ac18f3a5f4fd8b62380d27629e1cc5708bcc763..f9350df0bdbee2192752766e6982995b9675109b 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -41,7 +41,8 @@ import { LinkedMap } from 'vs/base/common/map'; import { DelegatingWorkbenchEditorService } from 'vs/workbench/services/editor/browser/editorService'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { INACTIVE_TAB_BACKGROUND, ACTIVE_TAB_BACKGROUND, ACTIVE_TAB_ACTIVE_GROUP_FOREGROUND, ACTIVE_TAB_INACTIVE_GROUP_FOREGROUND, INACTIVE_TAB_ACTIVE_GROUP_FOREGROUND, INACTIVE_TAB_INACTIVE_GROUP_FOREGROUND, TAB_BORDER } from 'vs/workbench/common/theme'; +import { INACTIVE_TAB_BACKGROUND, ACTIVE_TAB_BACKGROUND, ACTIVE_TAB_ACTIVE_GROUP_FOREGROUND, ACTIVE_TAB_INACTIVE_GROUP_FOREGROUND, INACTIVE_TAB_ACTIVE_GROUP_FOREGROUND, INACTIVE_TAB_INACTIVE_GROUP_FOREGROUND, TAB_BORDER, EDITOR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme'; +import { highContrastOutline } from 'vs/platform/theme/common/colorRegistry'; interface IEditorInputLabel { editor: IEditorInput; @@ -169,25 +170,25 @@ export class TabsTitleControl extends TitleControl { const target = e.target; if (target instanceof HTMLElement && target.className.indexOf('tabs-container') === 0) { - DOM.addClass(this.tabsContainer, 'dropfeedback'); + this.updateDropFeedback(this.tabsContainer, true); } })); // Drag leave this.toUnbind.push(DOM.addDisposableListener(this.tabsContainer, DOM.EventType.DRAG_LEAVE, (e: DragEvent) => { - DOM.removeClass(this.tabsContainer, 'dropfeedback'); + this.updateDropFeedback(this.tabsContainer, false); DOM.removeClass(this.tabsContainer, 'scroll'); })); // Drag end this.toUnbind.push(DOM.addDisposableListener(this.tabsContainer, DOM.EventType.DRAG_END, (e: DragEvent) => { - DOM.removeClass(this.tabsContainer, 'dropfeedback'); + this.updateDropFeedback(this.tabsContainer, false); DOM.removeClass(this.tabsContainer, 'scroll'); })); // Drop onto tabs container this.toUnbind.push(DOM.addDisposableListener(this.tabsContainer, DOM.EventType.DROP, (e: DragEvent) => { - DOM.removeClass(this.tabsContainer, 'dropfeedback'); + this.updateDropFeedback(this.tabsContainer, false); DOM.removeClass(this.tabsContainer, 'scroll'); const target = e.target; @@ -211,6 +212,28 @@ export class TabsTitleControl extends TitleControl { this.createEditorActionsToolBar(editorActionsContainer); } + private updateDropFeedback(element: HTMLElement, isDND: boolean, index?: number): void { + const isTab = (typeof index === 'number'); + const isActiveTab = isTab && this.context.isActive(this.context.getEditor(index)); + + // Background + const noDNDBackgroundColor = isTab ? this.getColor(isActiveTab ? ACTIVE_TAB_BACKGROUND : INACTIVE_TAB_BACKGROUND) : null; + element.style.backgroundColor = isDND ? this.getColor(EDITOR_DRAG_AND_DROP_BACKGROUND) : noDNDBackgroundColor; + + // Outline + if (this.isHighContrastTheme && isDND) { + element.style.outlineWidth = '2px'; + element.style.outlineStyle = 'dashed'; + element.style.outlineColor = this.getColor(highContrastOutline); + (element).style.outlineOffset = isTab ? '-5px' : '-3px'; // TODO@theme TS fail (gulp watch) + } else { + element.style.outlineWidth = null; + element.style.outlineStyle = null; + element.style.outlineColor = this.isHighContrastTheme ? this.getColor(highContrastOutline) : null; + (element).style.outlineOffset = null; // TODO@theme TS fail (gulp watch) + } + } + public allowDragging(element: HTMLElement): boolean { return (element.className === 'tabs-container'); } @@ -252,6 +275,8 @@ export class TabsTitleControl extends TitleControl { tabContainer.title = title; tabContainer.style.borderLeftColor = (index !== 0) ? this.getColor(TAB_BORDER) : null; tabContainer.style.borderRightColor = (index === editorsOfGroup.length - 1) ? this.getColor(TAB_BORDER) : null; + tabContainer.style.outlineColor = this.isHighContrastTheme ? this.getColor(highContrastOutline) : null; + const tabOptions = this.editorGroupService.getTabOptions(); ['off', 'left'].forEach(option => { const domAction = tabOptions.tabCloseButton === option ? DOM.addClass : DOM.removeClass; @@ -586,21 +611,21 @@ export class TabsTitleControl extends TitleControl { // Drag over disposables.push(DOM.addDisposableListener(tab, DOM.EventType.DRAG_ENTER, (e: DragEvent) => { counter++; - DOM.addClass(tab, 'dropfeedback'); + this.updateDropFeedback(tab, true, index); })); // Drag leave disposables.push(DOM.addDisposableListener(tab, DOM.EventType.DRAG_LEAVE, (e: DragEvent) => { counter--; if (counter === 0) { - DOM.removeClass(tab, 'dropfeedback'); + this.updateDropFeedback(tab, false, index); } })); // Drag end disposables.push(DOM.addDisposableListener(tab, DOM.EventType.DRAG_END, (e: DragEvent) => { counter = 0; - DOM.removeClass(tab, 'dropfeedback'); + this.updateDropFeedback(tab, false, index); this.onEditorDragEnd(); })); @@ -608,7 +633,7 @@ export class TabsTitleControl extends TitleControl { // Drop disposables.push(DOM.addDisposableListener(tab, DOM.EventType.DROP, (e: DragEvent) => { counter = 0; - DOM.removeClass(tab, 'dropfeedback'); + this.updateDropFeedback(tab, false, index); const { group, position } = this.toTabContext(index); @@ -627,7 +652,7 @@ export class TabsTitleControl extends TitleControl { } private onDrop(e: DragEvent, group: IEditorGroup, targetPosition: Position, targetIndex: number): void { - DOM.removeClass(this.tabsContainer, 'dropfeedback'); + this.updateDropFeedback(this.tabsContainer, false); DOM.removeClass(this.tabsContainer, 'scroll'); // Local DND diff --git a/src/vs/workbench/common/theme.ts b/src/vs/workbench/common/theme.ts index 11ea419f58b766dcbcb51d4fa7e9f0f165681678..f005f1797704c32609cfa0752aa1c79d6124bb97 100644 --- a/src/vs/workbench/common/theme.ts +++ b/src/vs/workbench/common/theme.ts @@ -14,7 +14,7 @@ import { Color, RGBA } from 'vs/base/common/color'; export const TABS_CONTAINER_BACKGROUND = registerColor('tabsContainerBackground', { dark: '#252526', light: '#F3F3F3', - hc: Color.transparent + hc: null }, nls.localize('tabsContainerBackground', "Background color of the tabs container. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.")); export const NO_TABS_CONTAINER_BACKGROUND = registerColor('noTabsContainerBackground', { @@ -32,7 +32,7 @@ export const ACTIVE_TAB_BACKGROUND = registerColor('activeTabBackground', { export const INACTIVE_TAB_BACKGROUND = registerColor('inactiveTabBackground', { dark: '#2D2D2D', light: '#ECECEC', - hc: Color.transparent + hc: null }, nls.localize('inactiveTabBackground', "Inactive tab background color. Tabs are the containers for editors in the editor area. Multiple tabs can be opened in one editor group. There can be multiple editor groups.")); export const ACTIVE_TAB_ACTIVE_GROUP_FOREGROUND = registerColor('activeTabActiveGroupForeground', { @@ -75,6 +75,17 @@ export const EDITOR_GROUP_BORDER_COLOR = registerColor('editorGroupBorder', { hc: highContrastBorder }, nls.localize('editorGroupBorder', "Color to separate multiple editor groups from each other. Editor groups are the containers of editors.")); +export const EDITOR_GROUP_BACKGROUND = registerColor('editorGroupBackground', { + dark: '#2D2D2D', + light: '#ECECEC', + hc: null +}, nls.localize('editorGroupBackground', "Backgrouund color of an editor group. Editor groups are the containers of editors.")); + +export const EDITOR_DRAG_AND_DROP_BACKGROUND = registerColor('editorDragAndDropBackground', { + dark: Color.fromRGBA(new RGBA(83, 89, 93)).transparent(0.5), + light: Color.fromRGBA(new RGBA(51, 153, 255)).transparent(0.18), + hc: null +}, nls.localize('editorDragAndDropBackground', "Background color when dragging editors around.")); // < --- Panels --- > @@ -104,13 +115,13 @@ export const STATUS_BAR_FOREGROUND = registerColor('statusBarForeground', { export const STATUS_BAR_BACKGROUND = registerColor('statusBarBackground', { dark: '#007ACC', light: '#007ACC', - hc: Color.transparent + hc: null }, nls.localize('statusBarBackground', "Standard status bar background color. The status bar is shown in the bottom of the window")); export const STATUS_BAR_NO_FOLDER_BACKGROUND = registerColor('statusBarNoFolderBackground', { dark: '#68217A', light: '#68217A', - hc: Color.transparent + hc: null }, nls.localize('statusBarNoFolderBackground', "Status bar background color when no folder is opened. The status bar is shown in the bottom of the window")); /** @@ -118,7 +129,7 @@ export const STATUS_BAR_NO_FOLDER_BACKGROUND = registerColor('statusBarNoFolderB */ export class Themable extends Disposable { private _toUnbind: IDisposable[]; - private _theme: ITheme; + private theme: ITheme; constructor( protected themeService: IThemeService @@ -126,14 +137,14 @@ export class Themable extends Disposable { super(); this._toUnbind = []; - this._theme = themeService.getTheme(); + this.theme = themeService.getTheme(); // Hook up to theme changes this._toUnbind.push(this.themeService.onThemeChange(theme => this.onThemeChange(theme))); } - protected get theme(): ITheme { - return this._theme; + protected get isHighContrastTheme(): boolean { + return this.theme.type === 'hc'; } protected get toUnbind() { @@ -141,7 +152,7 @@ export class Themable extends Disposable { } protected onThemeChange(theme: ITheme): void { - this._theme = theme; + this.theme = theme; this.updateStyles(theme); } @@ -151,7 +162,7 @@ export class Themable extends Disposable { } protected getColor(id: string): string { - const color = this._theme.getColor(id); + const color = this.theme.getColor(id); return color ? color.toString() : null; }