Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
b6c47c23
V
vscode
项目概览
xxadev
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
b6c47c23
编写于
3月 13, 2018
作者:
B
Benjamin Pasero
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Keep scroll position stable when closing a tab in the tab well (fixes #45527)
上级
e9d92ca9
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
131 addition
and
20 deletion
+131
-20
src/vs/workbench/browser/parts/editor/editorActions.ts
src/vs/workbench/browser/parts/editor/editorActions.ts
+44
-0
src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts
src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts
+1
-1
src/vs/workbench/browser/parts/editor/tabsTitleControl.ts
src/vs/workbench/browser/parts/editor/tabsTitleControl.ts
+32
-3
src/vs/workbench/browser/parts/editor/titleControl.ts
src/vs/workbench/browser/parts/editor/titleControl.ts
+29
-15
src/vs/workbench/services/editor/common/editorService.ts
src/vs/workbench/services/editor/common/editorService.ts
+17
-0
src/vs/workbench/services/editor/test/browser/editorService.test.ts
...kbench/services/editor/test/browser/editorService.test.ts
+8
-1
未找到文件。
src/vs/workbench/browser/parts/editor/editorActions.ts
浏览文件 @
b6c47c23
...
...
@@ -543,6 +543,50 @@ export class CloseEditorAction extends Action {
}
}
export
class
CloseOneEditorAction
extends
Action
{
public
static
readonly
ID
=
'
workbench.action.closeActiveEditor
'
;
public
static
readonly
LABEL
=
nls
.
localize
(
'
closeOneEditor
'
,
"
Close
"
);
constructor
(
id
:
string
,
label
:
string
,
@
IWorkbenchEditorService
private
editorService
:
IWorkbenchEditorService
,
@
IEditorGroupService
private
editorGroupService
:
IEditorGroupService
)
{
super
(
id
,
label
,
'
close-editor-action
'
);
}
public
run
(
context
?:
IEditorCommandsContext
):
TPromise
<
any
>
{
const
model
=
this
.
editorGroupService
.
getStacksModel
();
const
group
=
context
?
model
.
getGroup
(
context
.
groupId
)
:
null
;
const
position
=
group
?
model
.
positionOfGroup
(
group
)
:
null
;
// Close Active Editor
if
(
typeof
position
!==
'
number
'
)
{
const
activeEditor
=
this
.
editorService
.
getActiveEditor
();
if
(
activeEditor
)
{
return
this
.
editorService
.
closeEditor
(
activeEditor
.
position
,
activeEditor
.
input
);
}
}
// Close Specific Editor
const
editor
=
group
&&
context
&&
typeof
context
.
editorIndex
===
'
number
'
?
group
.
getEditor
(
context
.
editorIndex
)
:
null
;
if
(
editor
)
{
return
this
.
editorService
.
closeEditor
(
position
,
editor
);
}
// Close First Editor at Position
const
visibleEditors
=
this
.
editorService
.
getVisibleEditors
();
if
(
visibleEditors
[
position
])
{
return
this
.
editorService
.
closeEditor
(
position
,
visibleEditors
[
position
].
input
);
}
return
TPromise
.
as
(
false
);
}
}
export
class
RevertAndCloseEditorAction
extends
Action
{
public
static
readonly
ID
=
'
workbench.action.revertAndCloseActiveEditor
'
;
...
...
src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts
浏览文件 @
b6c47c23
...
...
@@ -81,7 +81,7 @@ export class NoTabsTitleControl extends TitleControl {
// Close editor on middle mouse click
if
(
e
instanceof
MouseEvent
&&
e
.
button
===
1
/* Middle Button */
)
{
this
.
closeEditorAction
.
run
({
groupId
:
group
.
id
,
editorIndex
:
group
.
indexOf
(
group
.
activeEditor
)
}).
done
(
null
,
errors
.
onUnexpectedError
);
this
.
close
One
EditorAction
.
run
({
groupId
:
group
.
id
,
editorIndex
:
group
.
indexOf
(
group
.
activeEditor
)
}).
done
(
null
,
errors
.
onUnexpectedError
);
}
// Focus editor group unless:
...
...
src/vs/workbench/browser/parts/editor/tabsTitleControl.ts
浏览文件 @
b6c47c23
...
...
@@ -20,7 +20,7 @@ import { EventType as TouchEventType, GestureEvent, Gesture } from 'vs/base/brow
import
{
KeyCode
}
from
'
vs/base/common/keyCodes
'
;
import
{
ResourceLabel
}
from
'
vs/workbench/browser/labels
'
;
import
{
ActionBar
}
from
'
vs/base/browser/ui/actionbar/actionbar
'
;
import
{
IWorkbenchEditorService
}
from
'
vs/workbench/services/editor/common/editorService
'
;
import
{
IWorkbenchEditorService
,
DelegatingWorkbenchEditorService
}
from
'
vs/workbench/services/editor/common/editorService
'
;
import
{
IContextMenuService
}
from
'
vs/platform/contextview/browser/contextView
'
;
import
{
IEditorGroupService
}
from
'
vs/workbench/services/group/common/groupService
'
;
import
{
ITelemetryService
}
from
'
vs/platform/telemetry/common/telemetry
'
;
...
...
@@ -34,6 +34,7 @@ import { IDisposable, dispose, combinedDisposable } from 'vs/base/common/lifecyc
import
{
ScrollableElement
}
from
'
vs/base/browser/ui/scrollbar/scrollableElement
'
;
import
{
ScrollbarVisibility
}
from
'
vs/base/common/scrollable
'
;
import
{
getOrSet
}
from
'
vs/base/common/map
'
;
import
{
ServiceCollection
}
from
'
vs/platform/instantiation/common/serviceCollection
'
;
import
{
IThemeService
,
registerThemingParticipant
,
ITheme
,
ICssStyleCollector
}
from
'
vs/platform/theme/common/themeService
'
;
import
{
TAB_INACTIVE_BACKGROUND
,
TAB_ACTIVE_BACKGROUND
,
TAB_ACTIVE_FOREGROUND
,
TAB_INACTIVE_FOREGROUND
,
TAB_BORDER
,
EDITOR_DRAG_AND_DROP_BACKGROUND
,
TAB_UNFOCUSED_ACTIVE_FOREGROUND
,
TAB_UNFOCUSED_INACTIVE_FOREGROUND
,
TAB_UNFOCUSED_ACTIVE_BORDER
,
TAB_ACTIVE_BORDER
,
TAB_HOVER_BACKGROUND
,
TAB_HOVER_BORDER
,
TAB_UNFOCUSED_HOVER_BACKGROUND
,
TAB_UNFOCUSED_HOVER_BORDER
,
EDITOR_GROUP_HEADER_TABS_BACKGROUND
,
EDITOR_GROUP_BACKGROUND
,
WORKBENCH_BACKGROUND
}
from
'
vs/workbench/common/theme
'
;
import
{
activeContrastBorder
,
contrastBorder
,
editorBackground
}
from
'
vs/platform/theme/common/colorRegistry
'
;
...
...
@@ -83,6 +84,34 @@ export class TabsTitleControl extends TitleControl {
this
.
editorLabels
=
[];
}
protected
initActions
(
services
:
IInstantiationService
):
void
{
super
.
initActions
(
this
.
createScopedInstantiationService
());
}
private
createScopedInstantiationService
():
IInstantiationService
{
const
stacks
=
this
.
editorGroupService
.
getStacksModel
();
const
delegatingEditorService
=
this
.
instantiationService
.
createInstance
(
DelegatingWorkbenchEditorService
);
// We create a scoped instantiation service to override the behaviour when closing an inactive editor
// Specifically we want to move focus back to the editor when an inactive editor is closed from anywhere
// in the tabs title control (e.g. mouse middle click, context menu on tab). This is only needed for
// the inactive editors because closing the active one will always cause a tab switch that sets focus.
// We also want to block the tabs container to reveal the currently active tab because that makes it very
// hard to close multiple inactive tabs next to each other.
delegatingEditorService
.
setEditorCloseHandler
((
position
,
editor
)
=>
{
const
group
=
stacks
.
groupAt
(
position
);
if
(
group
&&
stacks
.
isActive
(
group
)
&&
!
group
.
isActive
(
editor
))
{
this
.
editorGroupService
.
focusGroup
(
group
);
}
this
.
blockRevealActiveTab
=
true
;
return
TPromise
.
as
(
void
0
);
});
return
this
.
instantiationService
.
createChild
(
new
ServiceCollection
([
IWorkbenchEditorService
,
delegatingEditorService
]));
}
public
create
(
parent
:
HTMLElement
):
void
{
super
.
create
(
parent
);
...
...
@@ -517,7 +546,7 @@ export class TabsTitleControl extends TitleControl {
this
.
tabDisposeables
.
push
(
actionRunner
);
const
bar
=
new
ActionBar
(
tabCloseContainer
,
{
ariaLabel
:
nls
.
localize
(
'
araLabelTabActions
'
,
"
Tab actions
"
),
actionRunner
});
bar
.
push
(
this
.
close
EditorAction
,
{
icon
:
true
,
label
:
false
,
keybinding
:
this
.
getKeybindingLabel
(
this
.
clos
eEditorAction
)
});
bar
.
push
(
this
.
close
OneEditorAction
,
{
icon
:
true
,
label
:
false
,
keybinding
:
this
.
getKeybindingLabel
(
this
.
closeOn
eEditorAction
)
});
// Eventing
const
disposable
=
this
.
hookTabListeners
(
tabContainer
,
index
);
...
...
@@ -636,7 +665,7 @@ export class TabsTitleControl extends TitleControl {
tab
.
blur
();
if
(
e
.
button
===
1
/* Middle Button*/
&&
!
this
.
isTabActionBar
((
e
.
target
||
e
.
srcElement
)
as
HTMLElement
))
{
this
.
closeEditorAction
.
run
({
groupId
:
this
.
context
.
id
,
editorIndex
:
index
}).
done
(
null
,
errors
.
onUnexpectedError
);
this
.
close
One
EditorAction
.
run
({
groupId
:
this
.
context
.
id
,
editorIndex
:
index
}).
done
(
null
,
errors
.
onUnexpectedError
);
}
}));
...
...
src/vs/workbench/browser/parts/editor/titleControl.ts
浏览文件 @
b6c47c23
...
...
@@ -28,7 +28,7 @@ import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
import
{
IKeybindingService
}
from
'
vs/platform/keybinding/common/keybinding
'
;
import
{
ResolvedKeybinding
}
from
'
vs/base/common/keyCodes
'
;
import
{
IContextKeyService
}
from
'
vs/platform/contextkey/common/contextkey
'
;
import
{
SplitEditorAction
,
CloseEditorAction
}
from
'
vs/workbench/browser/parts/editor/editorActions
'
;
import
{
SplitEditorAction
,
Close
One
EditorAction
}
from
'
vs/workbench/browser/parts/editor/editorActions
'
;
import
{
IDisposable
,
dispose
}
from
'
vs/base/common/lifecycle
'
;
import
{
createActionItem
,
fillInActions
}
from
'
vs/platform/actions/browser/menuItemActionItem
'
;
import
{
IMenuService
,
MenuId
,
IMenu
,
ExecuteCommandAction
}
from
'
vs/platform/actions/common/actions
'
;
...
...
@@ -65,7 +65,7 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl
protected
dragged
:
boolean
;
protected
close
EditorAction
:
Clos
eEditorAction
;
protected
close
OneEditorAction
:
CloseOn
eEditorAction
;
protected
splitEditorAction
:
SplitEditorAction
;
private
parent
:
HTMLElement
;
...
...
@@ -75,7 +75,8 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl
protected
editorActionsToolbar
:
ToolBar
;
private
mapActionsToEditors
:
{
[
editorId
:
string
]:
IToolbarActions
;
};
private
scheduler
:
RunOnceScheduler
;
private
titleAreaUpdateScheduler
:
RunOnceScheduler
;
private
titleAreaToolbarUpdateScheduler
:
RunOnceScheduler
;
private
refreshScheduled
:
boolean
;
private
resourceContext
:
ResourceContextKey
;
...
...
@@ -101,8 +102,11 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl
this
.
stacks
=
editorGroupService
.
getStacksModel
();
this
.
mapActionsToEditors
=
Object
.
create
(
null
);
this
.
scheduler
=
new
RunOnceScheduler
(()
=>
this
.
onSchedule
(),
0
);
this
.
toUnbind
.
push
(
this
.
scheduler
);
this
.
titleAreaUpdateScheduler
=
new
RunOnceScheduler
(()
=>
this
.
onSchedule
(),
0
);
this
.
toUnbind
.
push
(
this
.
titleAreaUpdateScheduler
);
this
.
titleAreaToolbarUpdateScheduler
=
new
RunOnceScheduler
(()
=>
this
.
updateEditorActionsToolbar
(),
0
);
this
.
toUnbind
.
push
(
this
.
titleAreaToolbarUpdateScheduler
);
this
.
resourceContext
=
instantiationService
.
createInstance
(
ResourceContextKey
);
...
...
@@ -166,22 +170,26 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl
public
update
(
instant
?:
boolean
):
void
{
if
(
instant
)
{
this
.
s
cheduler
.
cancel
();
this
.
titleAreaUpdateS
cheduler
.
cancel
();
this
.
onSchedule
();
}
else
{
this
.
s
cheduler
.
schedule
();
this
.
titleAreaUpdateS
cheduler
.
schedule
();
}
this
.
titleAreaToolbarUpdateScheduler
.
cancel
();
// a title area update will always refresh the toolbar too
}
public
refresh
(
instant
?:
boolean
)
{
this
.
refreshScheduled
=
true
;
if
(
instant
)
{
this
.
s
cheduler
.
cancel
();
this
.
titleAreaUpdateS
cheduler
.
cancel
();
this
.
onSchedule
();
}
else
{
this
.
s
cheduler
.
schedule
();
this
.
titleAreaUpdateS
cheduler
.
schedule
();
}
this
.
titleAreaToolbarUpdateScheduler
.
cancel
();
// a title area update will always refresh the toolbar too
}
public
create
(
parent
:
HTMLElement
):
void
{
...
...
@@ -207,7 +215,7 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl
}
protected
initActions
(
services
:
IInstantiationService
):
void
{
this
.
close
EditorAction
=
services
.
createInstance
(
CloseEditorAction
,
CloseEditorAction
.
ID
,
nls
.
localize
(
'
close
'
,
"
Close
"
)
);
this
.
close
OneEditorAction
=
services
.
createInstance
(
CloseOneEditorAction
,
CloseOneEditorAction
.
ID
,
CloseOneEditorAction
.
LABEL
);
this
.
splitEditorAction
=
services
.
createInstance
(
SplitEditorAction
,
SplitEditorAction
.
ID
,
SplitEditorAction
.
LABEL
);
}
...
...
@@ -296,7 +304,14 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl
const
codeEditor
=
isCodeEditor
(
widget
)
&&
widget
||
isDiffEditor
(
widget
)
&&
widget
.
getModifiedEditor
();
const
scopedContextKeyService
=
codeEditor
&&
codeEditor
.
invokeWithinContext
(
accessor
=>
accessor
.
get
(
IContextKeyService
))
||
this
.
contextKeyService
;
const
titleBarMenu
=
this
.
menuService
.
createMenu
(
MenuId
.
EditorTitle
,
scopedContextKeyService
);
this
.
disposeOnEditorActions
.
push
(
titleBarMenu
,
titleBarMenu
.
onDidChange
(
_
=>
this
.
update
()));
this
.
disposeOnEditorActions
.
push
(
titleBarMenu
,
titleBarMenu
.
onDidChange
(
_
=>
{
// schedule the update for the title area toolbar only if no other
// update to the title area is scheduled which will always also
// update the toolbar
if
(
!
this
.
titleAreaUpdateScheduler
.
isScheduled
())
{
this
.
titleAreaToolbarUpdateScheduler
.
schedule
();
}
}));
fillInActions
(
titleBarMenu
,
{
arg
:
this
.
resourceContext
.
get
(),
shouldForwardArgs
:
true
},
{
primary
,
secondary
},
this
.
contextMenuService
);
}
...
...
@@ -334,11 +349,10 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl
const
primaryEditorActionIds
=
primaryEditorActions
.
map
(
a
=>
a
.
id
);
if
(
!
tabOptions
.
showTabs
)
{
primaryEditorActionIds
.
push
(
this
.
closeEditorAction
.
id
);
// always show "Close" when tabs are disabled
primaryEditorActionIds
.
push
(
this
.
close
One
EditorAction
.
id
);
// always show "Close" when tabs are disabled
}
const
secondaryEditorActionIds
=
secondaryEditorActions
.
map
(
a
=>
a
.
id
);
if
(
!
arrays
.
equals
(
primaryEditorActionIds
,
this
.
currentPrimaryEditorActionIds
)
||
!
arrays
.
equals
(
secondaryEditorActionIds
,
this
.
currentSecondaryEditorActionIds
)
||
...
...
@@ -348,7 +362,7 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl
this
.
editorActionsToolbar
.
setActions
(
primaryEditorActions
,
secondaryEditorActions
)();
if
(
!
tabOptions
.
showTabs
)
{
this
.
editorActionsToolbar
.
addPrimaryAction
(
this
.
closeEditorAction
)();
this
.
editorActionsToolbar
.
addPrimaryAction
(
this
.
close
One
EditorAction
)();
}
this
.
currentPrimaryEditorActionIds
=
primaryEditorActionIds
;
...
...
@@ -416,7 +430,7 @@ export abstract class TitleControl extends Themable implements ITitleAreaControl
// Actions
[
this
.
splitEditorAction
,
this
.
closeEditorAction
this
.
close
One
EditorAction
].
forEach
((
action
)
=>
{
action
.
dispose
();
});
...
...
src/vs/workbench/services/editor/common/editorService.ts
浏览文件 @
b6c47c23
...
...
@@ -268,6 +268,10 @@ export class WorkbenchEditorService implements IWorkbenchEditorService {
}
public
closeEditor
(
position
:
Position
,
input
:
IEditorInput
):
TPromise
<
void
>
{
return
this
.
doCloseEditor
(
position
,
input
);
}
protected
doCloseEditor
(
position
:
Position
,
input
:
IEditorInput
):
TPromise
<
void
>
{
return
this
.
editorPart
.
closeEditor
(
position
,
input
);
}
...
...
@@ -396,6 +400,7 @@ export interface IEditorCloseHandler {
*/
export
class
DelegatingWorkbenchEditorService
extends
WorkbenchEditorService
{
private
editorOpenHandler
:
IEditorOpenHandler
;
private
editorCloseHandler
:
IEditorCloseHandler
;
constructor
(
@
IUntitledEditorService
untitledEditorService
:
IUntitledEditorService
,
...
...
@@ -419,6 +424,10 @@ export class DelegatingWorkbenchEditorService extends WorkbenchEditorService {
this
.
editorOpenHandler
=
handler
;
}
public
setEditorCloseHandler
(
handler
:
IEditorCloseHandler
):
void
{
this
.
editorCloseHandler
=
handler
;
}
protected
doOpenEditor
(
input
:
IEditorInput
,
options
?:
EditorOptions
,
sideBySide
?:
boolean
):
TPromise
<
IEditor
>
;
protected
doOpenEditor
(
input
:
IEditorInput
,
options
?:
EditorOptions
,
position
?:
Position
):
TPromise
<
IEditor
>
;
protected
doOpenEditor
(
input
:
IEditorInput
,
options
?:
EditorOptions
,
arg3
?:
any
):
TPromise
<
IEditor
>
{
...
...
@@ -432,4 +441,12 @@ export class DelegatingWorkbenchEditorService extends WorkbenchEditorService {
return
super
.
doOpenEditor
(
input
,
options
,
arg3
);
});
}
protected
doCloseEditor
(
position
:
Position
,
input
:
IEditorInput
):
TPromise
<
void
>
{
const
handleClose
=
this
.
editorCloseHandler
?
this
.
editorCloseHandler
(
position
,
input
)
:
TPromise
.
as
(
void
0
);
return
handleClose
.
then
(()
=>
{
return
super
.
doCloseEditor
(
position
,
input
);
});
}
}
src/vs/workbench/services/editor/test/browser/editorService.test.ts
浏览文件 @
b6c47c23
...
...
@@ -266,11 +266,18 @@ suite('WorkbenchEditorService', () => {
delegate
.
setEditorOpenHandler
((
input
:
IEditorInput
,
options
?:
EditorOptions
)
=>
{
assert
.
strictEqual
(
input
,
inp
);
return
TPromise
.
as
(
ed
);
});
delegate
.
setEditorCloseHandler
((
position
,
input
)
=>
{
assert
.
strictEqual
(
input
,
inp
);
done
();
return
TPromise
.
as
(
ed
);
return
TPromise
.
as
(
void
0
);
});
delegate
.
openEditor
(
inp
);
delegate
.
closeEditor
(
0
,
inp
);
});
});
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录