Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
掘金者说
vscode
提交
5913061e
V
vscode
项目概览
掘金者说
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
5913061e
编写于
4月 16, 2020
作者:
M
Matt Bierner
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Allow a custom editor to opt out of supporting multiple instances for a single resource
#77131
上级
a565d7e2
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
123 addition
and
21 deletion
+123
-21
extensions/image-preview/src/extension.ts
extensions/image-preview/src/extension.ts
+3
-1
src/vs/vscode.proposed.d.ts
src/vs/vscode.proposed.d.ts
+13
-0
src/vs/workbench/api/browser/mainThreadWebview.ts
src/vs/workbench/api/browser/mainThreadWebview.ts
+9
-4
src/vs/workbench/api/common/extHost.api.impl.ts
src/vs/workbench/api/common/extHost.api.impl.ts
+4
-4
src/vs/workbench/api/common/extHost.protocol.ts
src/vs/workbench/api/common/extHost.protocol.ts
+1
-1
src/vs/workbench/api/common/extHostWebview.ts
src/vs/workbench/api/common/extHostWebview.ts
+3
-3
src/vs/workbench/contrib/customEditor/browser/customEditors.ts
...s/workbench/contrib/customEditor/browser/customEditors.ts
+84
-8
src/vs/workbench/contrib/customEditor/common/customEditor.ts
src/vs/workbench/contrib/customEditor/common/customEditor.ts
+6
-0
未找到文件。
extensions/image-preview/src/extension.ts
浏览文件 @
5913061e
...
...
@@ -23,7 +23,9 @@ export function activate(context: vscode.ExtensionContext) {
const
previewManager
=
new
PreviewManager
(
extensionRoot
,
sizeStatusBarEntry
,
binarySizeStatusBarEntry
,
zoomStatusBarEntry
);
context
.
subscriptions
.
push
(
vscode
.
window
.
registerCustomEditorProvider2
(
PreviewManager
.
viewType
,
previewManager
));
context
.
subscriptions
.
push
(
vscode
.
window
.
registerCustomEditorProvider2
(
PreviewManager
.
viewType
,
previewManager
,
{
supportsMultipleEditorsPerResource
:
true
,
}));
context
.
subscriptions
.
push
(
vscode
.
commands
.
registerCommand
(
'
imagePreview.zoomIn
'
,
()
=>
{
previewManager
.
activePreview
?.
zoomIn
();
...
...
src/vs/vscode.proposed.d.ts
浏览文件 @
5913061e
...
...
@@ -1401,6 +1401,19 @@ declare module 'vscode' {
provider
:
CustomEditorProvider
,
options
?:
{
readonly
webviewOptions
?:
WebviewPanelOptions
;
/**
* Indicates that the provider allows multiple editor instances to be open at the same time for
* the same resource.
*
* If not set, VS Code only allows one editor instance to be open at a time for each resource. If the
* user tries to open a second editor instance for the resource, the first one is instead moved to where
* the second one was to be opened.
*
* When set, users can split and create copies of the custom editor. The custom editor must make sure it
* can properly synchronize the states of all editor instances for a resource so that they are consistent.
*/
readonly
supportsMultipleEditorsPerResource
?:
boolean
;
}
):
Disposable
;
}
...
...
src/vs/workbench/api/browser/mainThreadWebview.ts
浏览文件 @
5913061e
...
...
@@ -152,7 +152,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
this
.
updateWebviewViewStates
(
this
.
_editorService
.
activeEditor
);
}));
// This reviver's only job is to activate
webview panel extensions
// This reviver's only job is to activate
extensions.
// This should trigger the real reviver to be registered from the extension host side.
this
.
_register
(
_webviewWorkbenchService
.
registerResolver
({
canResolve
:
(
webview
:
WebviewInput
)
=>
{
...
...
@@ -306,11 +306,11 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
}
public
$registerTextEditorProvider
(
extensionData
:
extHostProtocol
.
WebviewExtensionDescription
,
viewType
:
string
,
options
:
modes
.
IWebviewPanelOptions
,
capabilities
:
extHostProtocol
.
CustomTextEditorCapabilities
):
void
{
this
.
registerEditorProvider
(
ModelType
.
Text
,
extensionData
,
viewType
,
options
,
capabilities
);
this
.
registerEditorProvider
(
ModelType
.
Text
,
extensionData
,
viewType
,
options
,
capabilities
,
true
);
}
public
$registerCustomEditorProvider
(
extensionData
:
extHostProtocol
.
WebviewExtensionDescription
,
viewType
:
string
,
options
:
modes
.
IWebviewPanelOptions
):
void
{
this
.
registerEditorProvider
(
ModelType
.
Custom
,
extensionData
,
viewType
,
options
,
{});
public
$registerCustomEditorProvider
(
extensionData
:
extHostProtocol
.
WebviewExtensionDescription
,
viewType
:
string
,
options
:
modes
.
IWebviewPanelOptions
,
supportsMultipleEditorsPerResource
:
boolean
):
void
{
this
.
registerEditorProvider
(
ModelType
.
Custom
,
extensionData
,
viewType
,
options
,
{}
,
supportsMultipleEditorsPerResource
);
}
private
registerEditorProvider
(
...
...
@@ -319,11 +319,16 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
viewType
:
string
,
options
:
modes
.
IWebviewPanelOptions
,
capabilities
:
extHostProtocol
.
CustomTextEditorCapabilities
,
supportsMultipleEditorsPerResource
:
boolean
,
):
DisposableStore
{
if
(
this
.
_editorProviders
.
has
(
viewType
))
{
throw
new
Error
(
`Provider for
${
viewType
}
already registered`
);
}
this
.
_customEditorService
.
registerCustomEditorCapabilities
(
viewType
,
{
supportsMultipleEditorsPerResource
});
const
extension
=
reviveWebviewExtension
(
extensionData
);
const
disposables
=
new
DisposableStore
();
...
...
src/vs/workbench/api/common/extHost.api.impl.ts
浏览文件 @
5913061e
...
...
@@ -581,12 +581,12 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
registerWebviewPanelSerializer
:
(
viewType
:
string
,
serializer
:
vscode
.
WebviewPanelSerializer
)
=>
{
return
extHostWebviews
.
registerWebviewPanelSerializer
(
extension
,
viewType
,
serializer
);
},
registerCustomEditorProvider
:
(
viewType
:
string
,
provider
:
vscode
.
CustomTextEditorProvider
,
options
?:
{
webviewOptions
?:
vscode
.
WebviewPanelOptions
})
=>
{
return
extHostWebviews
.
registerCustomEditorProvider
(
extension
,
viewType
,
provider
,
options
?.
webviewOptions
);
registerCustomEditorProvider
:
(
viewType
:
string
,
provider
:
vscode
.
CustomTextEditorProvider
,
options
:
{
webviewOptions
?:
vscode
.
WebviewPanelOptions
}
=
{
})
=>
{
return
extHostWebviews
.
registerCustomEditorProvider
(
extension
,
viewType
,
provider
,
options
);
},
registerCustomEditorProvider2
:
(
viewType
:
string
,
provider
:
vscode
.
CustomEditorProvider
,
options
?:
{
webviewOptions
?:
vscode
.
WebviewPanelOptions
})
=>
{
registerCustomEditorProvider2
:
(
viewType
:
string
,
provider
:
vscode
.
CustomEditorProvider
,
options
:
{
webviewOptions
?:
vscode
.
WebviewPanelOptions
,
supportsMultipleEditorsPerResource
?:
boolean
}
=
{
})
=>
{
checkProposedApiEnabled
(
extension
);
return
extHostWebviews
.
registerCustomEditorProvider
(
extension
,
viewType
,
provider
,
options
?.
webviewOptions
);
return
extHostWebviews
.
registerCustomEditorProvider
(
extension
,
viewType
,
provider
,
options
);
},
registerDecorationProvider
(
provider
:
vscode
.
DecorationProvider
)
{
checkProposedApiEnabled
(
extension
);
...
...
src/vs/workbench/api/common/extHost.protocol.ts
浏览文件 @
5913061e
...
...
@@ -611,7 +611,7 @@ export interface MainThreadWebviewsShape extends IDisposable {
$unregisterSerializer
(
viewType
:
string
):
void
;
$registerTextEditorProvider
(
extension
:
WebviewExtensionDescription
,
viewType
:
string
,
options
:
modes
.
IWebviewPanelOptions
,
capabilities
:
CustomTextEditorCapabilities
):
void
;
$registerCustomEditorProvider
(
extension
:
WebviewExtensionDescription
,
viewType
:
string
,
options
:
modes
.
IWebviewPanelOptions
):
void
;
$registerCustomEditorProvider
(
extension
:
WebviewExtensionDescription
,
viewType
:
string
,
options
:
modes
.
IWebviewPanelOptions
,
supportsMultipleEditorsPerResource
:
boolean
):
void
;
$unregisterEditorProvider
(
viewType
:
string
):
void
;
$onDidEdit
(
resource
:
UriComponents
,
viewType
:
string
,
editId
:
number
,
label
:
string
|
undefined
):
void
;
...
...
src/vs/workbench/api/common/extHostWebview.ts
浏览文件 @
5913061e
...
...
@@ -457,17 +457,17 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape {
extension
:
IExtensionDescription
,
viewType
:
string
,
provider
:
vscode
.
CustomEditorProvider
|
vscode
.
CustomTextEditorProvider
,
options
:
vscode
.
WebviewPanelOptions
|
undefined
=
{}
options
:
{
webviewOptions
?:
vscode
.
WebviewPanelOptions
,
supportsMultipleEditorsPerResource
?:
boolean
},
):
vscode
.
Disposable
{
const
disposables
=
new
DisposableStore
();
if
(
'
resolveCustomTextEditor
'
in
provider
)
{
disposables
.
add
(
this
.
_editorProviders
.
addTextProvider
(
viewType
,
extension
,
provider
));
this
.
_proxy
.
$registerTextEditorProvider
(
toExtensionData
(
extension
),
viewType
,
options
,
{
this
.
_proxy
.
$registerTextEditorProvider
(
toExtensionData
(
extension
),
viewType
,
options
.
webviewOptions
||
{}
,
{
supportsMove
:
!!
provider
.
moveCustomTextEditor
,
});
}
else
{
disposables
.
add
(
this
.
_editorProviders
.
addCustomProvider
(
viewType
,
extension
,
provider
));
this
.
_proxy
.
$registerCustomEditorProvider
(
toExtensionData
(
extension
),
viewType
,
options
);
this
.
_proxy
.
$registerCustomEditorProvider
(
toExtensionData
(
extension
),
viewType
,
options
.
webviewOptions
||
{},
!!
options
.
supportsMultipleEditorsPerResource
);
}
return
extHostTypes
.
Disposable
.
from
(
...
...
src/vs/workbench/contrib/customEditor/browser/customEditors.ts
浏览文件 @
5913061e
...
...
@@ -3,10 +3,10 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
coalesce
}
from
'
vs/base/common/arrays
'
;
import
{
E
vent
,
Emitter
}
from
'
vs/base/common/event
'
;
import
{
coalesce
,
distinct
}
from
'
vs/base/common/arrays
'
;
import
{
E
mitter
,
Event
}
from
'
vs/base/common/event
'
;
import
{
Lazy
}
from
'
vs/base/common/lazy
'
;
import
{
Disposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
Disposable
,
IDisposable
,
toDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
basename
,
extname
,
isEqual
}
from
'
vs/base/common/resources
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
generateUuid
}
from
'
vs/base/common/uuid
'
;
...
...
@@ -23,20 +23,21 @@ import { EditorServiceImpl } from 'vs/workbench/browser/parts/editor/editor';
import
{
IWorkbenchContribution
}
from
'
vs/workbench/common/contributions
'
;
import
{
EditorInput
,
EditorOptions
,
GroupIdentifier
,
IEditorInput
,
IEditorPane
}
from
'
vs/workbench/common/editor
'
;
import
{
DiffEditorInput
}
from
'
vs/workbench/common/editor/diffEditorInput
'
;
import
{
CONTEXT_CUSTOM_EDITORS
,
CONTEXT_FOCUSED_CUSTOM_EDITOR_IS_EDITABLE
,
CustomEditorInfo
,
CustomEditorInfoCollection
,
CustomEditorPriority
,
ICustomEditorService
}
from
'
vs/workbench/contrib/customEditor/common/customEditor
'
;
import
{
CONTEXT_CUSTOM_EDITORS
,
CONTEXT_FOCUSED_CUSTOM_EDITOR_IS_EDITABLE
,
CustomEditor
Capabilities
,
CustomEditor
Info
,
CustomEditorInfoCollection
,
CustomEditorPriority
,
ICustomEditorService
}
from
'
vs/workbench/contrib/customEditor/common/customEditor
'
;
import
{
CustomEditorModelManager
}
from
'
vs/workbench/contrib/customEditor/common/customEditorModelManager
'
;
import
{
FileEditorInput
}
from
'
vs/workbench/contrib/files/common/editors/fileEditorInput
'
;
import
{
IWebviewService
,
webviewHasOwnEditFunctionsContext
}
from
'
vs/workbench/contrib/webview/browser/webview
'
;
import
{
CustomEditorAssociation
,
CustomEditorsAssociations
,
customEditorsAssociationsSettingId
}
from
'
vs/workbench/services/editor/browser/editorAssociationsSetting
'
;
import
{
IEditorGroup
,
IEditorGroupsService
}
from
'
vs/workbench/services/editor/common/editorGroupsService
'
;
import
{
I
EditorService
,
IOpenEditorOverride
,
ICustomEditorViewTypesHandler
,
ICustomEditorInfo
,
IOpenEditorOverrideEntry
}
from
'
vs/workbench/services/editor/common/editorService
'
;
import
{
I
CustomEditorInfo
,
ICustomEditorViewTypesHandler
,
IEditorService
,
IOpenEditorOverride
,
IOpenEditorOverrideEntry
}
from
'
vs/workbench/services/editor/common/editorService
'
;
import
{
ContributedCustomEditors
,
defaultCustomEditor
}
from
'
../common/contributedCustomEditors
'
;
import
{
CustomEditorInput
}
from
'
./customEditorInput
'
;
import
{
CustomEditorAssociation
,
CustomEditorsAssociations
,
customEditorsAssociationsSettingId
}
from
'
vs/workbench/services/editor/browser/editorAssociationsSetting
'
;
export
class
CustomEditorService
extends
Disposable
implements
ICustomEditorService
,
ICustomEditorViewTypesHandler
{
_serviceBrand
:
any
;
private
readonly
_contributedEditors
=
this
.
_register
(
new
ContributedCustomEditors
());
private
readonly
_editorCapabilities
=
new
Map
<
string
,
CustomEditorCapabilities
>
();
private
readonly
_models
=
new
CustomEditorModelManager
();
...
...
@@ -190,7 +191,7 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
});
}
public
openWith
(
public
async
openWith
(
resource
:
URI
,
viewType
:
string
,
options
?:
ITextEditorOptions
,
...
...
@@ -205,6 +206,14 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
return
this
.
promptOpenWith
(
resource
,
options
,
group
);
}
const
capabilities
=
this
.
getCustomEditorCapabilities
(
viewType
)
||
{};
if
(
!
capabilities
.
supportsMultipleEditorsPerResource
)
{
const
movedEditor
=
await
this
.
tryRevealExistingEditorForResourceInGroup
(
resource
,
viewType
,
options
,
group
);
if
(
movedEditor
)
{
return
movedEditor
;
}
}
const
input
=
this
.
createInput
(
resource
,
viewType
,
group
?.
id
);
return
this
.
openEditorForResource
(
resource
,
input
,
options
,
group
);
}
...
...
@@ -262,6 +271,20 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
return
this
.
editorService
.
openEditor
(
input
,
options
,
group
);
}
public
registerCustomEditorCapabilities
(
viewType
:
string
,
options
:
CustomEditorCapabilities
):
IDisposable
{
if
(
this
.
_editorCapabilities
.
has
(
viewType
))
{
throw
new
Error
(
`Capabilities for
${
viewType
}
already set`
);
}
this
.
_editorCapabilities
.
set
(
viewType
,
options
);
return
toDisposable
(()
=>
{
this
.
_editorCapabilities
.
delete
(
viewType
);
});
}
private
getCustomEditorCapabilities
(
viewType
:
string
):
CustomEditorCapabilities
|
undefined
{
return
this
.
_editorCapabilities
.
get
(
viewType
);
}
private
updateContexts
()
{
const
activeEditorPane
=
this
.
editorService
.
activeEditorPane
;
const
resource
=
activeEditorPane
?.
input
?.
resource
;
...
...
@@ -319,7 +342,7 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
}
else
{
// If there is, show a single prompt for all editors to see if the user wants to re-open them
//
// TODO: instead of prompting eagerly, it'd likly be better to replace all the editors with
// TODO: instead of prompting eagerly, it'd lik
e
ly be better to replace all the editors with
// ones that would prompt when they first become visible
await
new
Promise
(
resolve
=>
setTimeout
(
resolve
,
50
));
viewType
=
await
this
.
showOpenWithPrompt
(
newResource
);
...
...
@@ -342,6 +365,54 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
}),
group
);
}
}
private
async
tryRevealExistingEditorForResourceInGroup
(
resource
:
URI
,
viewType
:
string
,
options
?:
ITextEditorOptions
,
group
?:
IEditorGroup
,
):
Promise
<
IEditorPane
|
undefined
>
{
const
editorInfoForResource
=
this
.
findExistingEditorsForResource
(
resource
,
viewType
);
if
(
!
editorInfoForResource
.
length
)
{
return
undefined
;
}
const
editorToUse
=
editorInfoForResource
[
0
];
// Replace all other editors
for
(
const
{
editor
,
group
}
of
editorInfoForResource
)
{
if
(
editor
!==
editorToUse
.
editor
)
{
group
.
closeEditor
(
editor
);
}
}
const
targetGroup
=
group
||
this
.
editorGroupService
.
activeGroup
;
const
newEditor
=
await
this
.
openEditorForResource
(
resource
,
editorToUse
.
editor
,
{
...
options
,
ignoreOverrides
:
true
},
targetGroup
);
if
(
targetGroup
.
id
!==
editorToUse
.
group
.
id
)
{
editorToUse
.
group
.
closeEditor
(
editorToUse
.
editor
);
}
return
newEditor
;
}
private
findExistingEditorsForResource
(
resource
:
URI
,
viewType
:
string
,
):
Array
<
{
editor
:
IEditorInput
,
group
:
IEditorGroup
}
>
{
const
out
:
Array
<
{
editor
:
IEditorInput
,
group
:
IEditorGroup
}
>
=
[];
const
orderedGroups
=
distinct
([
this
.
editorGroupService
.
activeGroup
,
...
this
.
editorGroupService
.
groups
,
]);
for
(
const
group
of
orderedGroups
)
{
for
(
const
editor
of
group
.
editors
)
{
if
(
isMatchingCustomEditor
(
editor
,
viewType
,
resource
))
{
out
.
push
({
editor
,
group
});
}
}
}
return
out
;
}
}
export
class
CustomEditorContribution
extends
Disposable
implements
IWorkbenchContribution
{
...
...
@@ -549,6 +620,11 @@ export class CustomEditorContribution extends Disposable implements IWorkbenchCo
}
}
function
isMatchingCustomEditor
(
editor
:
IEditorInput
,
viewType
:
string
,
resource
:
URI
):
boolean
{
return
editor
instanceof
CustomEditorInput
&&
editor
.
viewType
===
viewType
&&
isEqual
(
editor
.
resource
,
resource
);
}
registerThemingParticipant
((
theme
,
collector
)
=>
{
const
shadow
=
theme
.
getColor
(
colorRegistry
.
scrollbarShadow
);
...
...
src/vs/workbench/contrib/customEditor/common/customEditor.ts
浏览文件 @
5913061e
...
...
@@ -21,6 +21,10 @@ export const ICustomEditorService = createDecorator<ICustomEditorService>('custo
export
const
CONTEXT_CUSTOM_EDITORS
=
new
RawContextKey
<
string
>
(
'
customEditors
'
,
''
);
export
const
CONTEXT_FOCUSED_CUSTOM_EDITOR_IS_EDITABLE
=
new
RawContextKey
<
boolean
>
(
'
focusedCustomEditorIsEditable
'
,
false
);
export
interface
CustomEditorCapabilities
{
readonly
supportsMultipleEditorsPerResource
?:
boolean
;
}
export
interface
ICustomEditorService
{
_serviceBrand
:
any
;
...
...
@@ -35,6 +39,8 @@ export interface ICustomEditorService {
openWith
(
resource
:
URI
,
customEditorViewType
:
string
,
options
?:
ITextEditorOptions
,
group
?:
IEditorGroup
):
Promise
<
IEditorPane
|
undefined
>
;
promptOpenWith
(
resource
:
URI
,
options
?:
ITextEditorOptions
,
group
?:
IEditorGroup
):
Promise
<
IEditorPane
|
undefined
>
;
registerCustomEditorCapabilities
(
viewType
:
string
,
options
:
CustomEditorCapabilities
):
IDisposable
;
}
export
interface
ICustomEditorModelManager
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录