提交 b7ee78d6 编写于 作者: B Benjamin Pasero

tabs bugfixing and polish

上级 d7f953f5
...@@ -838,8 +838,9 @@ declare module Electron { ...@@ -838,8 +838,9 @@ declare module Electron {
* at the current mouse cursor position. * at the current mouse cursor position.
* @param x Horizontal coordinate where the menu will be placed. * @param x Horizontal coordinate where the menu will be placed.
* @param y Vertical coordinate where the menu will be placed. * @param y Vertical coordinate where the menu will be placed.
* @param positioningItem The item to select by default.
*/ */
popup(browserWindow: BrowserWindow, x?: number, y?: number): void; popup(browserWindow: BrowserWindow, x?: number, y?: number, positioningItem?: number): void;
/** /**
* Appends the menuItem to the menu. * Appends the menuItem to the menu.
*/ */
......
...@@ -970,6 +970,38 @@ export class ShowEditorsInRightGroupAction extends QuickOpenAction { ...@@ -970,6 +970,38 @@ export class ShowEditorsInRightGroupAction extends QuickOpenAction {
} }
} }
export class ShowEditorsInGroupAction extends Action {
public static ID = 'workbench.action.showEditorsInGroup';
public static LABEL = nls.localize('showEditorsInGroup', "Show Editors in Group");
constructor(
id: string,
label: string,
@IQuickOpenService private quickOpenService: IQuickOpenService,
@IEditorGroupService private editorGroupService: IEditorGroupService
) {
super(id, label);
}
public run(context?: IEditorContext): TPromise<any> {
const stacks = this.editorGroupService.getStacksModel();
const groupCount = stacks.groups.length;
if (groupCount <= 1 || !context) {
return this.quickOpenService.show(NAVIGATE_ALL_EDITORS_GROUP_PREFIX);
}
switch (stacks.positionOfGroup(context.group)) {
case Position.CENTER:
return this.quickOpenService.show((groupCount === 2) ? NAVIGATE_IN_RIGHT_GROUP_PREFIX : NAVIGATE_IN_CENTER_GROUP_PREFIX);
case Position.RIGHT:
return this.quickOpenService.show(NAVIGATE_IN_RIGHT_GROUP_PREFIX);
}
return this.quickOpenService.show(NAVIGATE_IN_LEFT_GROUP_PREFIX);
}
}
export const NAVIGATE_ALL_EDITORS_GROUP_PREFIX = 'edt '; export const NAVIGATE_ALL_EDITORS_GROUP_PREFIX = 'edt ';
export class ShowAllEditorsAction extends QuickOpenAction { export class ShowAllEditorsAction extends QuickOpenAction {
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
position: absolute; position: absolute;
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%;
z-index: 3000000; z-index: 3000000;
} }
......
...@@ -11,11 +11,14 @@ ...@@ -11,11 +11,14 @@
.monaco-workbench > .part.editor > .content > .one-editor-container > .title .tabs-container { .monaco-workbench > .part.editor > .content > .one-editor-container > .title .tabs-container {
display: flex; display: flex;
/*overflow: scroll;*/
background-color: rgba(128, 128, 128, 0.2); background-color: rgba(128, 128, 128, 0.2);
height: 35px; height: 35px;
} }
.monaco-workbench > .part.editor > .content > .one-editor-container > .title .tabs-container.scroll {
overflow: scroll !important;
}
.monaco-workbench > .part.editor > .content > .one-editor-container > .title .tabs-container::-webkit-scrollbar { .monaco-workbench > .part.editor > .content > .one-editor-container > .title .tabs-container::-webkit-scrollbar {
display: none; display: none;
} }
...@@ -36,10 +39,6 @@ ...@@ -36,10 +39,6 @@
padding-left: 10px; padding-left: 10px;
} }
.monaco-workbench > .part.editor > .content > .one-editor-container > .title .tabs-container > .tab:focus {
outline-offset: -2px;
}
.hc-black .monaco-workbench > .part.editor > .content > .one-editor-container > .title.active .tabs-container > .tab.active { .hc-black .monaco-workbench > .part.editor > .content > .one-editor-container > .title.active .tabs-container > .tab.active {
border: 1px solid #f38518; border: 1px solid #f38518;
} }
...@@ -49,15 +48,19 @@ ...@@ -49,15 +48,19 @@
} }
.monaco-workbench > .part.editor > .content > .one-editor-container > .title .tabs-container > .tab.active { .monaco-workbench > .part.editor > .content > .one-editor-container > .title .tabs-container > .tab.active {
border-bottom: 0; border-bottom-color: transparent;
opacity: 1 !important; opacity: 1 !important;
} }
.vs .monaco-workbench > .part.editor > .content > .one-editor-container > .title .tabs-container.dropfeedback, .vs .monaco-workbench > .part.editor > .content > .one-editor-container > .title .tabs-container.dropfeedback {
.vs .monaco-workbench > .part.editor > .content > .one-editor-container > .title .tabs-container > .tab.dropfeedback {
background-color: rgba(51,153,255, 0.18); background-color: rgba(51,153,255, 0.18);
} }
.vs .monaco-workbench > .part.editor > .content > .one-editor-container > .title .tabs-container > .tab.dropfeedback {
background-color: rgba(187, 230, 255, 0.5);
opacity: 1 !important;
}
.vs-dark .monaco-workbench > .part.editor > .content > .one-editor-container > .title .tabs-container.dropfeedback, .vs-dark .monaco-workbench > .part.editor > .content > .one-editor-container > .title .tabs-container.dropfeedback,
.vs-dark .monaco-workbench > .part.editor > .content > .one-editor-container > .title .tabs-container > .tab.dropfeedback { .vs-dark .monaco-workbench > .part.editor > .content > .one-editor-container > .title .tabs-container > .tab.dropfeedback {
background-color: rgba(83, 89, 93, 0.5); background-color: rgba(83, 89, 93, 0.5);
...@@ -70,10 +73,6 @@ ...@@ -70,10 +73,6 @@
outline-offset: -2px; outline-offset: -2px;
} }
.monaco-workbench > .part.editor > .content > .one-editor-container > .title .tabs-container > .tab.dragged {
opacity: 0.7 !important;
}
/* Tab Close */ /* Tab Close */
.monaco-workbench > .part.editor > .content > .one-editor-container .title .tabs-container > .tab > .tab-close { .monaco-workbench > .part.editor > .content > .one-editor-container .title .tabs-container > .tab > .tab-close {
......
...@@ -758,6 +758,7 @@ export class SideBySideEditorControl implements ISideBySideEditorControl, IVerti ...@@ -758,6 +758,7 @@ export class SideBySideEditorControl implements ISideBySideEditorControl, IVerti
const $this = this; const $this = this;
const overlayId = 'monaco-workbench-editor-drop-overlay'; const overlayId = 'monaco-workbench-editor-drop-overlay';
const splitToPropertyKey = 'splitToPosition'; const splitToPropertyKey = 'splitToPosition';
const stacks = this.editorGroupService.getStacksModel();
let overlay: Builder; let overlay: Builder;
function onDrop(e: DragEvent, position: Position, splitTo?: Position): void { function onDrop(e: DragEvent, position: Position, splitTo?: Position): void {
...@@ -766,7 +767,6 @@ export class SideBySideEditorControl implements ISideBySideEditorControl, IVerti ...@@ -766,7 +767,6 @@ export class SideBySideEditorControl implements ISideBySideEditorControl, IVerti
const editorService = $this.editorService; const editorService = $this.editorService;
const groupService = $this.editorGroupService; const groupService = $this.editorGroupService;
const stacks = groupService.getStacksModel();
const splitEditor = (typeof splitTo === 'number'); // TODO@Ben ugly split code should benefit from empty group support once available! const splitEditor = (typeof splitTo === 'number'); // TODO@Ben ugly split code should benefit from empty group support once available!
const freeGroup = (stacks.groups.length === 1) ? Position.CENTER : Position.RIGHT; const freeGroup = (stacks.groups.length === 1) ? Position.CENTER : Position.RIGHT;
...@@ -784,7 +784,7 @@ export class SideBySideEditorControl implements ISideBySideEditorControl, IVerti ...@@ -784,7 +784,7 @@ export class SideBySideEditorControl implements ISideBySideEditorControl, IVerti
if (splitTo !== freeGroup) { if (splitTo !== freeGroup) {
groupService.moveGroup(freeGroup, splitTo); groupService.moveGroup(freeGroup, splitTo);
} }
}); }).done(null, errors.onUnexpectedError);
} else { } else {
editorService.openEditor(draggedEditor.editor, pinned, position).done(null, errors.onUnexpectedError); editorService.openEditor(draggedEditor.editor, pinned, position).done(null, errors.onUnexpectedError);
} }
...@@ -794,12 +794,17 @@ export class SideBySideEditorControl implements ISideBySideEditorControl, IVerti ...@@ -794,12 +794,17 @@ export class SideBySideEditorControl implements ISideBySideEditorControl, IVerti
else { else {
const sourcePosition = stacks.positionOfGroup(draggedEditor.group); const sourcePosition = stacks.positionOfGroup(draggedEditor.group);
if (splitEditor) { if (splitEditor) {
editorService.openEditor(draggedEditor.editor, pinned, freeGroup).then(() => { if (draggedEditor.group.count === 1) {
if (splitTo !== freeGroup) { groupService.moveGroup(sourcePosition, splitTo);
groupService.moveGroup(freeGroup, splitTo); } else {
} editorService.openEditor(draggedEditor.editor, pinned, freeGroup).then(() => {
groupService.moveEditor(draggedEditor.editor, stacks.positionOfGroup(draggedEditor.group), splitTo); if (splitTo !== freeGroup) {
}); groupService.moveGroup(freeGroup, splitTo);
}
groupService.moveEditor(draggedEditor.editor, stacks.positionOfGroup(draggedEditor.group), splitTo);
}).done(null, errors.onUnexpectedError);
}
} else { } else {
groupService.moveEditor(draggedEditor.editor, sourcePosition, position); groupService.moveEditor(draggedEditor.editor, sourcePosition, position);
} }
...@@ -840,39 +845,71 @@ export class SideBySideEditorControl implements ISideBySideEditorControl, IVerti ...@@ -840,39 +845,71 @@ export class SideBySideEditorControl implements ISideBySideEditorControl, IVerti
const overlayWidth = target.clientWidth; const overlayWidth = target.clientWidth;
const splitThreshold = overlayIsSplit ? overlayWidth / 5 : overlayWidth / 10; const splitThreshold = overlayIsSplit ? overlayWidth / 5 : overlayWidth / 10;
const isCopy = (e.ctrlKey && !isMacintosh) || (e.altKey && isMacintosh); const isCopy = (e.ctrlKey && !isMacintosh) || (e.altKey && isMacintosh);
const draggedEditor = TitleControl.getDraggedEditor();
let allowSplit = true; const isOverSplitLeft = posXOnOverlay < splitThreshold;
const isOverSplitRight = posXOnOverlay + splitThreshold > overlayWidth;
let splitTarget: Position;
// No splitting if we reached maximum group count
if (groups === POSITIONS.length) { if (groups === POSITIONS.length) {
allowSplit = false; // do not show split feedback when we already at the maximum splitTarget = null;
} }
const draggedEditor = TitleControl.getDraggedEditor(); // Special splitting if we drag an editor of a group with only one editor
if (!isCopy && draggedEditor && draggedEditor.group.count === 1) { else if (!isCopy && draggedEditor && draggedEditor.group.count === 1) {
allowSplit = false; // do not show split feedback when moving the only one editor of a group const positionOfDraggedEditor = stacks.positionOfGroup(draggedEditor.group);
switch (positionOfDraggedEditor) {
case Position.LEFT:
if (position === Position.CENTER && isOverSplitRight) {
splitTarget = Position.CENTER; // allow to move single editor from LEFT to CENTER
}
break;
case Position.CENTER:
if (position === Position.LEFT && isOverSplitLeft) {
splitTarget = Position.LEFT; // allow to move single editor from CENTER to LEFT
}
break;
default:
splitTarget = null; // splitting not allowed
}
} }
// Compute split decoration // Any other case, check for mouse position
if (allowSplit) { else {
if (posXOnOverlay + splitThreshold > overlayWidth) { if (isOverSplitRight) {
overlay.setProperty(splitToPropertyKey, position === Position.LEFT ? Position.CENTER : Position.RIGHT); splitTarget = (position === Position.LEFT) ? Position.CENTER : Position.RIGHT;
overlay.style({ } else if (isOverSplitLeft) {
left: '50%', splitTarget = (position === Position.LEFT) ? Position.LEFT : Position.CENTER;
width: '50%',
});
} else if (posXOnOverlay < splitThreshold) {
overlay.setProperty(splitToPropertyKey, position === Position.LEFT ? Position.LEFT : Position.CENTER);
overlay.style({
width: '50%'
});
} else {
overlay.removeProperty(splitToPropertyKey);
overlay.style({
left: '0',
width: '100%'
});
} }
} }
// Apply split target
const canSplit = (typeof splitTarget === 'number');
if (canSplit) {
overlay.setProperty(splitToPropertyKey, splitTarget);
} else {
overlay.removeProperty(splitToPropertyKey);
}
// Update overlay styles
if (canSplit && isOverSplitRight) {
overlay.style({
left: '50%',
width: '50%',
});
} else if (canSplit && isOverSplitLeft) {
overlay.style({
width: '50%'
});
} else {
overlay.style({
left: '0',
width: '100%'
});
}
// Make sure the overlay is visible // Make sure the overlay is visible
overlay.style({ opacity: 1 }); overlay.style({ opacity: 1 });
} }
...@@ -885,7 +922,8 @@ export class SideBySideEditorControl implements ISideBySideEditorControl, IVerti ...@@ -885,7 +922,8 @@ export class SideBySideEditorControl implements ISideBySideEditorControl, IVerti
const useTabs = !!$this.configurationService.getConfiguration<IWorkbenchEditorConfiguration>().workbench.editor.showTabs; const useTabs = !!$this.configurationService.getConfiguration<IWorkbenchEditorConfiguration>().workbench.editor.showTabs;
overlay = $('div').style({ overlay = $('div').style({
top: useTabs ? SideBySideEditorControl.EDITOR_TITLE_HEIGHT + 'px' : 0 top: useTabs ? SideBySideEditorControl.EDITOR_TITLE_HEIGHT + 'px' : 0,
height: useTabs ? `calc(100% - ${SideBySideEditorControl.EDITOR_TITLE_HEIGHT}px` : '100%'
}).id(overlayId); }).id(overlayId);
overlay.appendTo(container); overlay.appendTo(container);
...@@ -976,7 +1014,8 @@ export class SideBySideEditorControl implements ISideBySideEditorControl, IVerti ...@@ -976,7 +1014,8 @@ export class SideBySideEditorControl implements ISideBySideEditorControl, IVerti
// Overlay the editor area with a div to be able to capture all mouse events // Overlay the editor area with a div to be able to capture all mouse events
let overlayDiv = $('div').style({ let overlayDiv = $('div').style({
top: SideBySideEditorControl.EDITOR_TITLE_HEIGHT + 'px' top: SideBySideEditorControl.EDITOR_TITLE_HEIGHT + 'px',
height: '100%'
}).id('monaco-workbench-editor-move-overlay'); }).id('monaco-workbench-editor-move-overlay');
overlayDiv.appendTo(this.parent); overlayDiv.appendTo(this.parent);
...@@ -1122,8 +1161,12 @@ export class SideBySideEditorControl implements ISideBySideEditorControl, IVerti ...@@ -1122,8 +1161,12 @@ export class SideBySideEditorControl implements ISideBySideEditorControl, IVerti
// Move to valid position if any // Move to valid position if any
if (moveTo !== null) { if (moveTo !== null) {
this.editorGroupService.moveGroup(position, moveTo); this.editorGroupService.moveGroup(position, moveTo);
this.titleAreaControl[position].refresh(true);
this.titleAreaControl[moveTo].refresh(true); // To reduce flickering during this operation we trigger a refresh of all
// title controls right after.
POSITIONS.forEach(p => {
this.titleAreaControl[p].refresh(true);
});
} }
// Otherwise layout to restore proper positioning // Otherwise layout to restore proper positioning
......
...@@ -78,6 +78,14 @@ export class TabsTitleControl extends TitleControl { ...@@ -78,6 +78,14 @@ export class TabsTitleControl extends TitleControl {
this.tabsContainer.setAttribute('role', 'tablist'); this.tabsContainer.setAttribute('role', 'tablist');
DOM.addClass(this.tabsContainer, 'tabs-container'); DOM.addClass(this.tabsContainer, 'tabs-container');
this.toDispose.push(DOM.addDisposableListener(this.tabsContainer, DOM.EventType.SCROLL, e => {
if (DOM.hasClass(this.tabsContainer, 'scroll')) {
this.scrollbar.updateState({
scrollLeft: this.tabsContainer.scrollLeft // during DND the container gets scrolled so we need to update the custom scrollbar
});
}
}));
// Custom Scrollbar // Custom Scrollbar
this.scrollbar = new ScrollableElement(this.tabsContainer, { this.scrollbar = new ScrollableElement(this.tabsContainer, {
horizontal: ScrollbarVisibility.Auto, horizontal: ScrollbarVisibility.Auto,
...@@ -87,7 +95,6 @@ export class TabsTitleControl extends TitleControl { ...@@ -87,7 +95,6 @@ export class TabsTitleControl extends TitleControl {
canUseTranslate3d: true, canUseTranslate3d: true,
horizontalScrollbarSize: 3 horizontalScrollbarSize: 3
}); });
// this.tabsContainer.style.overflow = 'scroll'; // custom scrollbar is eager on removing this style but we want it for DND scroll feedback
this.scrollbar.onScroll(e => { this.scrollbar.onScroll(e => {
this.tabsContainer.scrollLeft = e.scrollLeft; this.tabsContainer.scrollLeft = e.scrollLeft;
...@@ -97,6 +104,8 @@ export class TabsTitleControl extends TitleControl { ...@@ -97,6 +104,8 @@ export class TabsTitleControl extends TitleControl {
// Drag over // Drag over
this.toDispose.push(DOM.addDisposableListener(this.tabsContainer, DOM.EventType.DRAG_OVER, (e: DragEvent) => { this.toDispose.push(DOM.addDisposableListener(this.tabsContainer, DOM.EventType.DRAG_OVER, (e: DragEvent) => {
DOM.addClass(this.tabsContainer, 'scroll'); // enable support to scroll while dragging
const target = e.target; const target = e.target;
if (target instanceof HTMLElement && target.className.indexOf('tabs-container') === 0) { if (target instanceof HTMLElement && target.className.indexOf('tabs-container') === 0) {
DOM.addClass(this.tabsContainer, 'dropfeedback'); DOM.addClass(this.tabsContainer, 'dropfeedback');
...@@ -106,16 +115,19 @@ export class TabsTitleControl extends TitleControl { ...@@ -106,16 +115,19 @@ export class TabsTitleControl extends TitleControl {
// Drag leave // Drag leave
this.toDispose.push(DOM.addDisposableListener(this.tabsContainer, DOM.EventType.DRAG_LEAVE, (e: DragEvent) => { this.toDispose.push(DOM.addDisposableListener(this.tabsContainer, DOM.EventType.DRAG_LEAVE, (e: DragEvent) => {
DOM.removeClass(this.tabsContainer, 'dropfeedback'); DOM.removeClass(this.tabsContainer, 'dropfeedback');
DOM.removeClass(this.tabsContainer, 'scroll');
})); }));
// Drag end // Drag end
this.toDispose.push(DOM.addDisposableListener(this.tabsContainer, DOM.EventType.DRAG_END, (e: DragEvent) => { this.toDispose.push(DOM.addDisposableListener(this.tabsContainer, DOM.EventType.DRAG_END, (e: DragEvent) => {
DOM.removeClass(this.tabsContainer, 'dropfeedback'); DOM.removeClass(this.tabsContainer, 'dropfeedback');
DOM.removeClass(this.tabsContainer, 'scroll');
})); }));
// Drop onto tabs container // Drop onto tabs container
this.toDispose.push(DOM.addDisposableListener(this.tabsContainer, DOM.EventType.DROP, (e: DragEvent) => { this.toDispose.push(DOM.addDisposableListener(this.tabsContainer, DOM.EventType.DROP, (e: DragEvent) => {
DOM.removeClass(this.tabsContainer, 'dropfeedback'); DOM.removeClass(this.tabsContainer, 'dropfeedback');
DOM.removeClass(this.tabsContainer, 'scroll');
const target = e.target; const target = e.target;
if (target instanceof HTMLElement && target.className.indexOf('tabs-container') === 0) { if (target instanceof HTMLElement && target.className.indexOf('tabs-container') === 0) {
...@@ -339,10 +351,7 @@ export class TabsTitleControl extends TitleControl { ...@@ -339,10 +351,7 @@ export class TabsTitleControl extends TitleControl {
// Update enablement of certain actions that depend on overflow // Update enablement of certain actions that depend on overflow
const isOverflowing = (totalContainerWidth > visibleContainerWidth); const isOverflowing = (totalContainerWidth > visibleContainerWidth);
this.showEditorsOfLeftGroup.enabled = isOverflowing; this.showEditorsInGroupAction.enabled = isOverflowing;
this.showEditorsOfCenterGroup.enabled = isOverflowing;
this.showEditorsOfRightGroup.enabled = isOverflowing;
this.showAllEditorsAction.enabled = isOverflowing;
} }
private hookTabListeners(tab: HTMLElement, identifier: IEditorIdentifier): void { private hookTabListeners(tab: HTMLElement, identifier: IEditorIdentifier): void {
...@@ -420,7 +429,6 @@ export class TabsTitleControl extends TitleControl { ...@@ -420,7 +429,6 @@ export class TabsTitleControl extends TitleControl {
// Drag start // Drag start
this.tabDisposeables.push(DOM.addDisposableListener(tab, DOM.EventType.DRAG_START, (e: DragEvent) => { this.tabDisposeables.push(DOM.addDisposableListener(tab, DOM.EventType.DRAG_START, (e: DragEvent) => {
DOM.addClass(tab, 'dragged');
this.onEditorDragStart({ editor, group }); this.onEditorDragStart({ editor, group });
e.dataTransfer.effectAllowed = 'copyMove'; e.dataTransfer.effectAllowed = 'copyMove';
...@@ -443,13 +451,15 @@ export class TabsTitleControl extends TitleControl { ...@@ -443,13 +451,15 @@ export class TabsTitleControl extends TitleControl {
// Drag end // Drag end
this.tabDisposeables.push(DOM.addDisposableListener(tab, DOM.EventType.DRAG_END, (e: DragEvent) => { this.tabDisposeables.push(DOM.addDisposableListener(tab, DOM.EventType.DRAG_END, (e: DragEvent) => {
DOM.removeClass(tab, 'dragged');
DOM.removeClass(tab, 'dropfeedback'); DOM.removeClass(tab, 'dropfeedback');
this.onEditorDragEnd(); this.onEditorDragEnd();
})); }));
// Drop // Drop
this.tabDisposeables.push(DOM.addDisposableListener(tab, DOM.EventType.DROP, (e: DragEvent) => { this.tabDisposeables.push(DOM.addDisposableListener(tab, DOM.EventType.DROP, (e: DragEvent) => {
DOM.removeClass(tab, 'dropfeedback');
const targetPosition = this.stacks.positionOfGroup(group); const targetPosition = this.stacks.positionOfGroup(group);
const targetIndex = group.indexOf(editor); const targetIndex = group.indexOf(editor);
......
...@@ -15,7 +15,7 @@ import DOM = require('vs/base/browser/dom'); ...@@ -15,7 +15,7 @@ import DOM = require('vs/base/browser/dom');
import {TPromise} from 'vs/base/common/winjs.base'; import {TPromise} from 'vs/base/common/winjs.base';
import {BaseEditor, IEditorInputActionContext} from 'vs/workbench/browser/parts/editor/baseEditor'; import {BaseEditor, IEditorInputActionContext} from 'vs/workbench/browser/parts/editor/baseEditor';
import {RunOnceScheduler} from 'vs/base/common/async'; import {RunOnceScheduler} from 'vs/base/common/async';
import {IEditorStacksModel, IEditorGroup, IEditorIdentifier, EditorInput, IWorkbenchEditorConfiguration} from 'vs/workbench/common/editor'; import {IEditorStacksModel, IEditorGroup, IEditorIdentifier, EditorInput, IWorkbenchEditorConfiguration, IStacksModelChangeEvent} from 'vs/workbench/common/editor';
import {EventType as BaseEventType} from 'vs/base/common/events'; import {EventType as BaseEventType} from 'vs/base/common/events';
import {IActionItem, ActionsOrientation, Separator} from 'vs/base/browser/ui/actionbar/actionbar'; import {IActionItem, ActionsOrientation, Separator} from 'vs/base/browser/ui/actionbar/actionbar';
import {ToolBar} from 'vs/base/browser/ui/toolbar/toolbar'; import {ToolBar} from 'vs/base/browser/ui/toolbar/toolbar';
...@@ -25,14 +25,11 @@ import {Position} from 'vs/platform/editor/common/editor'; ...@@ -25,14 +25,11 @@ import {Position} from 'vs/platform/editor/common/editor';
import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; import {IConfigurationService} from 'vs/platform/configuration/common/configuration';
import {IEditorGroupService} from 'vs/workbench/services/group/common/groupService'; import {IEditorGroupService} from 'vs/workbench/services/group/common/groupService';
import {IMessageService, Severity} from 'vs/platform/message/common/message'; import {IMessageService, Severity} from 'vs/platform/message/common/message';
import {QuickOpenAction} from 'vs/workbench/browser/quickopen';
import {StandardMouseEvent} from 'vs/base/browser/mouseEvent'; import {StandardMouseEvent} from 'vs/base/browser/mouseEvent';
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation'; import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService';
import {ShowEditorsInLeftGroupAction, ShowAllEditorsAction, ShowEditorsInCenterGroupAction, ShowEditorsInRightGroupAction, CloseEditorsInGroupAction, MoveGroupLeftAction, import {CloseEditorsInGroupAction, MoveGroupLeftAction, MoveGroupRightAction, SplitEditorAction, CloseEditorAction, KeepEditorAction, CloseOtherEditorsInGroupAction, CloseRightEditorsInGroupAction, ShowEditorsInGroupAction} from 'vs/workbench/browser/parts/editor/editorActions';
MoveGroupRightAction, SplitEditorAction, CloseEditorAction, KeepEditorAction, CloseOtherEditorsInGroupAction, CloseRightEditorsInGroupAction}
from 'vs/workbench/browser/parts/editor/editorActions';
import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import {IDisposable, dispose} from 'vs/base/common/lifecycle';
export interface IToolbarActions { export interface IToolbarActions {
...@@ -62,14 +59,11 @@ export abstract class TitleControl { ...@@ -62,14 +59,11 @@ export abstract class TitleControl {
protected pinEditorAction: KeepEditorAction; protected pinEditorAction: KeepEditorAction;
protected closeOtherEditorsAction: CloseOtherEditorsInGroupAction; protected closeOtherEditorsAction: CloseOtherEditorsInGroupAction;
protected closeRightEditorsAction: CloseRightEditorsInGroupAction; protected closeRightEditorsAction: CloseRightEditorsInGroupAction;
protected showEditorsOfLeftGroup: QuickOpenAction;
protected showEditorsOfCenterGroup: QuickOpenAction;
protected showEditorsOfRightGroup: QuickOpenAction;
protected moveGroupLeftAction: MoveGroupLeftAction; protected moveGroupLeftAction: MoveGroupLeftAction;
protected moveGroupRightAction: MoveGroupRightAction; protected moveGroupRightAction: MoveGroupRightAction;
protected closeEditorsInGroupAction: CloseEditorsInGroupAction; protected closeEditorsInGroupAction: CloseEditorsInGroupAction;
protected splitEditorAction: SplitEditorAction; protected splitEditorAction: SplitEditorAction;
protected showAllEditorsAction: ShowAllEditorsAction; protected showEditorsInGroupAction: ShowEditorsInGroupAction;
private previewEditors: boolean; private previewEditors: boolean;
private showTabs: boolean; private showTabs: boolean;
...@@ -115,6 +109,13 @@ export abstract class TitleControl { ...@@ -115,6 +109,13 @@ export abstract class TitleControl {
private registerListeners(): void { private registerListeners(): void {
this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationUpdated(e.config))); this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationUpdated(e.config)));
this.toDispose.push(this.stacks.onModelChanged(e => this.onStacksChanged(e)));
}
private onStacksChanged(e: IStacksModelChangeEvent): void {
if (e.structural) {
this.updateSplitActionEnablement();
}
} }
private onConfigurationUpdated(config: IWorkbenchEditorConfiguration): void { private onConfigurationUpdated(config: IWorkbenchEditorConfiguration): void {
...@@ -122,37 +123,18 @@ export abstract class TitleControl { ...@@ -122,37 +123,18 @@ export abstract class TitleControl {
this.showTabs = config.workbench.editor.showTabs; this.showTabs = config.workbench.editor.showTabs;
} }
private updateActionEnablement(): void { private updateSplitActionEnablement(): void {
if (!this.context) { if (!this.context) {
return; return;
} }
const group = this.context;
const groupCount = this.stacks.groups.length; const groupCount = this.stacks.groups.length;
// Move group
switch (this.stacks.positionOfGroup(group)) {
case Position.LEFT:
this.moveGroupLeftAction.enabled = false;
this.moveGroupRightAction.enabled = this.stacks.groups.length > 1;
break;
case Position.CENTER:
this.moveGroupRightAction.enabled = this.stacks.groups.length > 2;
break;
case Position.RIGHT:
this.moveGroupRightAction.enabled = false;
break;
}
// Split editor // Split editor
this.splitEditorAction.enabled = groupCount < 3; this.splitEditorAction.enabled = groupCount < 3;
} }
private onSchedule(): void { private onSchedule(): void {
this.updateActionEnablement();
if (this.refreshScheduled) { if (this.refreshScheduled) {
this.doRefresh(); this.doRefresh();
} else { } else {
...@@ -206,15 +188,12 @@ export abstract class TitleControl { ...@@ -206,15 +188,12 @@ export abstract class TitleControl {
this.closeRightEditorsAction = this.instantiationService.createInstance(CloseRightEditorsInGroupAction, CloseRightEditorsInGroupAction.ID, nls.localize('closeRight', "Close to the Right")); this.closeRightEditorsAction = this.instantiationService.createInstance(CloseRightEditorsInGroupAction, CloseRightEditorsInGroupAction.ID, nls.localize('closeRight', "Close to the Right"));
this.closeEditorsInGroupAction = this.instantiationService.createInstance(CloseEditorsInGroupAction, CloseEditorsInGroupAction.ID, nls.localize('closeAll', "Close All")); this.closeEditorsInGroupAction = this.instantiationService.createInstance(CloseEditorsInGroupAction, CloseEditorsInGroupAction.ID, nls.localize('closeAll', "Close All"));
this.pinEditorAction = this.instantiationService.createInstance(KeepEditorAction, KeepEditorAction.ID, nls.localize('keepEditor', "Keep Editor")); this.pinEditorAction = this.instantiationService.createInstance(KeepEditorAction, KeepEditorAction.ID, nls.localize('keepEditor', "Keep Editor"));
this.showAllEditorsAction = this.instantiationService.createInstance(ShowAllEditorsAction, ShowAllEditorsAction.ID, nls.localize('showEditors', "Show Editors")); this.showEditorsInGroupAction = this.instantiationService.createInstance(ShowEditorsInGroupAction, ShowEditorsInGroupAction.ID, ShowEditorsInGroupAction.LABEL);
this.splitEditorAction = this.instantiationService.createInstance(SplitEditorAction, SplitEditorAction.ID, SplitEditorAction.LABEL); this.splitEditorAction = this.instantiationService.createInstance(SplitEditorAction, SplitEditorAction.ID, SplitEditorAction.LABEL);
this.moveGroupLeftAction = this.instantiationService.createInstance(MoveGroupLeftAction, MoveGroupLeftAction.ID, nls.localize('moveLeft', "Move Left")); this.moveGroupLeftAction = this.instantiationService.createInstance(MoveGroupLeftAction, MoveGroupLeftAction.ID, nls.localize('moveLeft', "Move Left"));
this.moveGroupRightAction = this.instantiationService.createInstance(MoveGroupRightAction, MoveGroupRightAction.ID, nls.localize('moveRight', "Move Right")); this.moveGroupRightAction = this.instantiationService.createInstance(MoveGroupRightAction, MoveGroupRightAction.ID, nls.localize('moveRight', "Move Right"));
this.showEditorsOfLeftGroup = this.instantiationService.createInstance(ShowEditorsInLeftGroupAction, ShowEditorsInLeftGroupAction.ID, nls.localize('showEditors', "Show Editors"));
this.showEditorsOfCenterGroup = this.instantiationService.createInstance(ShowEditorsInCenterGroupAction, ShowEditorsInCenterGroupAction.ID, nls.localize('showEditors', "Show Editors"));
this.showEditorsOfRightGroup = this.instantiationService.createInstance(ShowEditorsInRightGroupAction, ShowEditorsInRightGroupAction.ID, nls.localize('showEditors', "Show Editors"));
[this.showEditorsOfLeftGroup, this.showEditorsOfCenterGroup, this.showEditorsOfRightGroup, this.showAllEditorsAction].forEach(a => a.class = 'show-group-editors-action'); this.showEditorsInGroupAction.class = 'show-group-editors-action';
} }
protected doCreateToolbar(container: HTMLElement): ToolBar { protected doCreateToolbar(container: HTMLElement): ToolBar {
...@@ -328,35 +307,30 @@ export abstract class TitleControl { ...@@ -328,35 +307,30 @@ export abstract class TitleControl {
const editor = group.activeEditor; const editor = group.activeEditor;
const primary: IAction[] = []; const primary: IAction[] = [];
const groupCount = this.stacks.groups.length;
// Overflow // Overflow
let overflowAction: Action; primary.push(this.showEditorsInGroupAction);
if (groupCount === 1) {
overflowAction = this.showAllEditorsAction;
} else {
switch (this.stacks.positionOfGroup(group)) {
case Position.LEFT:
overflowAction = this.showEditorsOfLeftGroup;
break;
case Position.CENTER:
overflowAction = (groupCount === 2) ? this.showEditorsOfRightGroup : this.showEditorsOfCenterGroup;
break;
case Position.RIGHT:
overflowAction = this.showEditorsOfRightGroup;
break;
}
}
primary.push(overflowAction);
// Splitting // Splitting
if (editor instanceof EditorInput && editor.supportsSplitEditor()) { if (editor instanceof EditorInput && editor.supportsSplitEditor()) {
primary.push(this.splitEditorAction); primary.push(this.splitEditorAction);
} }
// Enablement
switch (this.stacks.positionOfGroup(group)) {
case Position.LEFT:
this.moveGroupLeftAction.enabled = false;
this.moveGroupRightAction.enabled = this.stacks.groups.length > 1;
break;
case Position.CENTER:
this.moveGroupRightAction.enabled = this.stacks.groups.length > 2;
break;
case Position.RIGHT:
this.moveGroupRightAction.enabled = false;
break;
}
// Return actions // Return actions
const secondary = [ const secondary = [
this.moveGroupLeftAction, this.moveGroupLeftAction,
...@@ -423,10 +397,7 @@ export abstract class TitleControl { ...@@ -423,10 +397,7 @@ export abstract class TitleControl {
// Actions // Actions
[ [
this.splitEditorAction, this.splitEditorAction,
this.showAllEditorsAction, this.showEditorsInGroupAction,
this.showEditorsOfLeftGroup,
this.showEditorsOfCenterGroup,
this.showEditorsOfRightGroup,
this.closeEditorAction, this.closeEditorAction,
this.closeRightEditorsAction, this.closeRightEditorsAction,
this.closeOtherEditorsAction, this.closeOtherEditorsAction,
......
...@@ -1541,13 +1541,18 @@ export abstract class BaseSaveAllAction extends BaseActionWithErrorReporting { ...@@ -1541,13 +1541,18 @@ export abstract class BaseSaveAllAction extends BaseActionWithErrorReporting {
const stacks = this.editorGroupService.getStacksModel(); const stacks = this.editorGroupService.getStacksModel();
// Store some properties per untitled file to restore later after save is completed // Store some properties per untitled file to restore later after save is completed
const mapUntitledToProperties: { [resource: string]: { mime: string; encoding: string; indexInGroups: number[]; } } = Object.create(null); const mapUntitledToProperties: { [resource: string]: { mime: string; encoding: string; indexInGroups: number[]; activeInGroups: boolean[] } } = Object.create(null);
this.textFileService.getDirty() this.textFileService.getDirty()
.filter(r => r.scheme === 'untitled') // All untitled resources .filter(r => r.scheme === 'untitled') // All untitled resources
.map(r => this.untitledEditorService.get(r)) // Mapped to their inputs .map(r => this.untitledEditorService.get(r)) // Mapped to their inputs
.filter(i => !!i) // If possible :) .filter(input => !!input) // If possible :)
.forEach(i => { .forEach(input => {
mapUntitledToProperties[i.getResource().toString()] = { mime: i.getMime(), encoding: i.getEncoding(), indexInGroups: stacks.groups.map(g => g.indexOf(i)) }; mapUntitledToProperties[input.getResource().toString()] = {
mime: input.getMime(),
encoding: input.getEncoding(),
indexInGroups: stacks.groups.map(g => g.indexOf(input)),
activeInGroups: stacks.groups.map(g => g.isActive(input))
};
}); });
// Save all // Save all
...@@ -1582,7 +1587,8 @@ export abstract class BaseSaveAllAction extends BaseActionWithErrorReporting { ...@@ -1582,7 +1587,8 @@ export abstract class BaseSaveAllAction extends BaseActionWithErrorReporting {
options: { options: {
pinned: true, pinned: true,
index: indexInGroup, index: indexInGroup,
preserveFocus: true preserveFocus: true,
inactive: !untitledProps.activeInGroups[index]
} }
}, },
position: index position: index
......
...@@ -57,7 +57,7 @@ export class ContextMenuService implements IContextMenuService { ...@@ -57,7 +57,7 @@ export class ContextMenuService implements IContextMenuService {
x *= zoom; x *= zoom;
y *= zoom; y *= zoom;
menu.popup(remote.getCurrentWindow(), Math.floor(x), Math.floor(y)); menu.popup(remote.getCurrentWindow(), Math.floor(x), Math.floor(y), -1 /* no item selected by default */);
if (delegate.onHide) { if (delegate.onHide) {
delegate.onHide(undefined); delegate.onHide(undefined);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册