Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
9887d9ba
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,发现更多精彩内容 >>
提交
9887d9ba
编写于
3月 03, 2020
作者:
R
rebornix
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
NotebookViewModel and tests
上级
c5f08080
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
403 addition
and
148 deletion
+403
-148
src/vs/workbench/contrib/notebook/browser/notebookActions.ts
src/vs/workbench/contrib/notebook/browser/notebookActions.ts
+1
-1
src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts
src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts
+4
-4
src/vs/workbench/contrib/notebook/browser/notebookEditor.ts
src/vs/workbench/contrib/notebook/browser/notebookEditor.ts
+101
-130
src/vs/workbench/contrib/notebook/browser/notebookViewModel.ts
...s/workbench/contrib/notebook/browser/notebookViewModel.ts
+119
-0
src/vs/workbench/contrib/notebook/browser/renderers/cellRenderer.ts
...kbench/contrib/notebook/browser/renderers/cellRenderer.ts
+7
-7
src/vs/workbench/contrib/notebook/browser/renderers/codeCell.ts
.../workbench/contrib/notebook/browser/renderers/codeCell.ts
+6
-6
src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts
...workbench/contrib/notebook/test/notebookViewModel.test.ts
+165
-0
未找到文件。
src/vs/workbench/contrib/notebook/browser/notebookActions.ts
浏览文件 @
9887d9ba
...
...
@@ -124,7 +124,7 @@ registerAction2(class extends Action2 {
let
activeCell
=
editor
.
getActiveCell
();
if
(
activeCell
)
{
editor
.
editNotebookCell
(
undefined
,
activeCell
);
editor
.
editNotebookCell
(
activeCell
);
}
}
});
...
...
src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts
浏览文件 @
9887d9ba
...
...
@@ -16,10 +16,10 @@ export const KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED = new RawContextKey
export
interface
INotebookEditor
{
viewType
:
string
|
undefined
;
insertEmptyNotebookCell
(
index
:
number
|
undefined
,
cell
:
CellViewModel
,
type
:
'
markdown
'
|
'
code
'
,
direction
:
'
above
'
|
'
below
'
):
Promise
<
void
>
;
deleteNotebookCell
(
index
:
number
|
undefined
,
cell
:
CellViewModel
):
void
;
editNotebookCell
(
index
:
number
|
undefined
,
cell
:
CellViewModel
):
void
;
saveNotebookCell
(
index
:
number
|
undefined
,
cell
:
CellViewModel
):
void
;
insertEmptyNotebookCell
(
cell
:
CellViewModel
,
type
:
'
markdown
'
|
'
code
'
,
direction
:
'
above
'
|
'
below
'
):
Promise
<
void
>
;
deleteNotebookCell
(
cell
:
CellViewModel
):
void
;
editNotebookCell
(
cell
:
CellViewModel
):
void
;
saveNotebookCell
(
cell
:
CellViewModel
):
void
;
focusNotebookCell
(
cell
:
CellViewModel
,
focusEditor
:
boolean
):
void
;
getActiveCell
():
CellViewModel
|
undefined
;
layoutNotebookCell
(
cell
:
CellViewModel
,
height
:
number
):
void
;
...
...
src/vs/workbench/contrib/notebook/browser/notebookEditor.ts
浏览文件 @
9887d9ba
...
...
@@ -38,6 +38,7 @@ import { IResourceEditorInput } from 'vs/platform/editor/common/editor';
import
{
Emitter
,
Event
}
from
'
vs/base/common/event
'
;
import
{
NotebookCellList
}
from
'
vs/workbench/contrib/notebook/browser/notebookCellList
'
;
import
{
NotebookFindWidget
,
NotebookFindDelegate
,
CellFindMatch
}
from
'
vs/workbench/contrib/notebook/browser/notebookFindWidget
'
;
import
{
NotebookViewModel
}
from
'
vs/workbench/contrib/notebook/browser/notebookViewModel
'
;
const
$
=
DOM
.
$
;
const
NOTEBOOK_EDITOR_VIEW_STATE_PREFERENCE_KEY
=
'
NotebookEditorViewState
'
;
...
...
@@ -112,19 +113,14 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor, Noteb
static
readonly
ID
:
string
=
'
workbench.editor.notebook
'
;
private
rootElement
!
:
HTMLElement
;
private
body
!
:
HTMLElement
;
private
contentWidgets
!
:
HTMLElement
;
private
webview
:
BackLayerWebView
|
null
=
null
;
private
list
:
NotebookCellList
<
CellViewModel
>
|
undefined
;
private
control
:
ICompositeCodeEditor
|
undefined
;
private
renderedEditors
:
Map
<
CellViewModel
,
ICodeEditor
|
undefined
>
=
new
Map
();
private
model
:
NotebookEditorModel
|
undefined
;
viewType
:
string
|
undefined
;
private
viewCells
:
CellViewModel
[]
=
[];
private
notebookViewModel
:
NotebookViewModel
|
undefined
;
private
localStore
:
DisposableStore
=
this
.
_register
(
new
DisposableStore
());
private
editorMemento
:
IEditorMemento
<
INotebookEditorViewState
>
;
private
fontInfo
:
BareFontInfo
|
undefined
;
// private relayoutDisposable: IDisposable | null = null;
private
dimension
:
DOM
.
Dimension
|
null
=
null
;
private
editorFocus
:
IContextKey
<
boolean
>
|
null
=
null
;
private
outputRenderer
:
OutputRenderer
;
...
...
@@ -157,6 +153,8 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor, Noteb
set
minimumWidth
(
value
:
number
)
{
/*noop*/
}
set
maximumWidth
(
value
:
number
)
{
/*noop*/
}
get
viewType
()
{
return
this
.
notebookViewModel
?.
viewType
;
}
//#region Editor
...
...
@@ -184,10 +182,6 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor, Noteb
DOM
.
addClass
(
this
.
body
,
'
cell-list-container
'
);
this
.
createCellList
();
DOM
.
append
(
parent
,
this
.
body
);
this
.
contentWidgets
=
document
.
createElement
(
'
div
'
);
DOM
.
addClass
(
this
.
contentWidgets
,
'
notebook-content-widgets
'
);
DOM
.
append
(
this
.
body
,
this
.
contentWidgets
);
DOM
.
append
(
this
.
body
,
this
.
findWidget
.
getDomNode
());
}
...
...
@@ -255,10 +249,9 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor, Noteb
this
.
list
?.
splice
(
0
,
this
.
list
?.
length
);
if
(
this
.
model
&&
!
this
.
model
.
isDirty
())
{
this
.
notebookService
.
destoryNotebookDocument
(
this
.
viewType
!
,
this
.
model
!
.
notebook
!
);
this
.
model
=
undefined
;
this
.
viewType
=
undefined
;
if
(
this
.
notebookViewModel
&&
!
this
.
notebookViewModel
.
isDirty
())
{
this
.
notebookService
.
destoryNotebookDocument
(
this
.
viewType
!
,
this
.
notebookViewModel
!
.
notebookDocument
);
this
.
notebookViewModel
=
undefined
;
}
super
.
onHide
();
...
...
@@ -267,11 +260,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor, Noteb
setVisible
(
visible
:
boolean
,
group
?:
IEditorGroup
):
void
{
super
.
setVisible
(
visible
,
group
);
if
(
!
visible
)
{
this
.
viewCells
.
forEach
(
cell
=>
{
if
(
cell
.
getText
()
!==
''
)
{
cell
.
isEditing
=
false
;
}
});
this
.
notebookViewModel
?.
hide
();
}
}
...
...
@@ -280,97 +269,91 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor, Noteb
this
.
editorFocus
?.
set
(
true
);
}
setInput
(
input
:
NotebookEditorInput
,
options
:
EditorOptions
|
undefined
,
token
:
CancellationToken
):
Promise
<
void
>
{
async
setInput
(
input
:
NotebookEditorInput
,
options
:
EditorOptions
|
undefined
,
token
:
CancellationToken
):
Promise
<
void
>
{
if
(
this
.
input
instanceof
NotebookEditorInput
)
{
this
.
saveTextEditorViewState
(
this
.
input
);
}
return
super
.
setInput
(
input
,
options
,
token
)
.
then
(()
=>
{
return
input
.
resolve
();
})
.
then
(
async
model
=>
{
if
(
this
.
model
!==
undefined
&&
this
.
model
===
model
&&
this
.
webview
!==
null
)
{
return
;
}
await
super
.
setInput
(
input
,
options
,
token
);
const
model
=
await
input
.
resolve
();
this
.
localStore
.
clear
();
this
.
viewCells
.
forEach
(
cell
=>
{
cell
.
save
();
});
if
(
this
.
notebookViewModel
!==
undefined
&&
this
.
notebookViewModel
.
equal
(
model
)
&&
this
.
webview
!==
null
)
{
return
;
}
if
(
this
.
webview
)
{
this
.
webview
?.
clearInsets
();
this
.
webview
?.
clearPreloadsCache
();
}
else
{
this
.
webview
=
new
BackLayerWebView
(
this
.
webviewService
,
this
.
notebookService
,
this
,
this
.
environmentSerice
);
this
.
list
?.
rowsContainer
.
insertAdjacentElement
(
'
afterbegin
'
,
this
.
webview
!
.
element
);
}
this
.
detachModel
();
await
this
.
attachModel
(
input
,
model
);
}
this
.
model
=
model
;
this
.
localStore
.
add
(
this
.
model
.
onDidChangeCells
((
e
)
=>
{
this
.
updateViewCells
(
e
);
}));
private
detachModel
()
{
this
.
localStore
.
clear
();
this
.
notebookViewModel
?.
dispose
();
this
.
notebookViewModel
=
undefined
;
this
.
webview
?.
clearInsets
();
this
.
webview
?.
clearPreloadsCache
();
}
let
viewState
=
this
.
loadTextEditorViewState
(
input
);
this
.
webview
.
updateRendererPreloads
(
this
.
model
!
.
notebook
.
renderers
);
this
.
viewType
=
input
.
viewType
;
this
.
viewCells
=
await
Promise
.
all
(
this
.
model
!
.
notebook
!
.
cells
.
map
(
async
cell
=>
{
const
isEditing
=
viewState
&&
viewState
.
editingCells
[
cell
.
handle
];
const
viewCell
=
this
.
instantiationService
.
createInstance
(
CellViewModel
,
input
.
viewType
!
,
this
.
model
!
.
notebook
!
.
handle
,
cell
,
!!
isEditing
);
this
.
localStore
.
add
(
viewCell
);
return
viewCell
;
}));
private
async
attachModel
(
input
:
NotebookEditorInput
,
model
:
NotebookEditorModel
)
{
if
(
!
this
.
webview
)
{
this
.
webview
=
new
BackLayerWebView
(
this
.
webviewService
,
this
.
notebookService
,
this
,
this
.
environmentSerice
);
this
.
list
?.
rowsContainer
.
insertAdjacentElement
(
'
afterbegin
'
,
this
.
webview
!
.
element
);
}
const
updateScrollPosition
=
()
=>
{
const
scrollTop
=
this
.
list
?.
scrollTop
||
0
;
const
scrollHeight
=
this
.
list
?.
scrollHeight
||
0
;
this
.
webview
!
.
element
.
style
.
height
=
`
${
scrollHeight
}
px`
;
let
updateItems
:
{
cell
:
CellViewModel
,
output
:
IOutput
,
cellTop
:
number
}[]
=
[];
// const date = new Date();
if
(
this
.
webview
?.
insetMapping
)
{
this
.
webview
?.
insetMapping
.
forEach
((
value
,
key
)
=>
{
let
cell
=
value
.
cell
;
let
index
=
this
.
model
!
.
getNotebook
().
cells
.
indexOf
(
cell
.
cell
);
let
cellTop
=
this
.
list
?.
getAbsoluteTop
(
index
)
||
0
;
if
(
this
.
webview
!
.
shouldUpdateInset
(
cell
,
key
,
cellTop
))
{
updateItems
.
push
({
cell
:
cell
,
output
:
key
,
cellTop
:
cellTop
});
}
});
this
.
notebookViewModel
=
this
.
instantiationService
.
createInstance
(
NotebookViewModel
,
input
.
viewType
!
,
model
);
const
viewState
=
this
.
loadTextEditorViewState
(
input
);
await
this
.
notebookViewModel
.
initialize
(
viewState
);
if
(
updateItems
.
length
)
{
// console.log('----- did scroll ---- ', date.getMinutes() + ':' + date.getSeconds() + ':' + date.getMilliseconds());
this
.
webview
?.
updateViewScrollTop
(
-
scrollTop
,
updateItems
);
}
}
};
this
.
localStore
.
add
(
this
.
list
!
.
onWillScroll
(
e
=>
{
// const date = new Date();
// console.log('----- will scroll ---- ', date.getMinutes() + ':' + date.getSeconds() + ':' + date.getMilliseconds());
this
.
webview
!
.
updateViewScrollTop
(
-
e
.
scrollTop
,
[]);
}));
this
.
localStore
.
add
(
this
.
list
!
.
onDidChangeContentHeight
(()
=>
updateScrollPosition
()));
this
.
localStore
.
add
(
this
.
list
!
.
onFocusChange
((
e
)
=>
{
if
(
e
.
elements
.
length
>
0
)
{
this
.
notebookService
.
updateNotebookActiveCell
(
input
.
viewType
!
,
input
.
resource
!
,
e
.
elements
[
0
].
cell
.
handle
);
this
.
localStore
.
add
(
this
.
notebookViewModel
.
onDidChangeCells
((
e
)
=>
{
this
.
updateViewCells
(
e
);
}));
this
.
webview
?.
updateRendererPreloads
(
this
.
notebookViewModel
.
renderers
);
this
.
localStore
.
add
(
this
.
list
!
.
onWillScroll
(
e
=>
{
this
.
webview
!
.
updateViewScrollTop
(
-
e
.
scrollTop
,
[]);
}));
this
.
localStore
.
add
(
this
.
list
!
.
onDidChangeContentHeight
(()
=>
{
const
scrollTop
=
this
.
list
?.
scrollTop
||
0
;
const
scrollHeight
=
this
.
list
?.
scrollHeight
||
0
;
this
.
webview
!
.
element
.
style
.
height
=
`
${
scrollHeight
}
px`
;
let
updateItems
:
{
cell
:
CellViewModel
,
output
:
IOutput
,
cellTop
:
number
}[]
=
[];
if
(
this
.
webview
?.
insetMapping
)
{
this
.
webview
?.
insetMapping
.
forEach
((
value
,
key
)
=>
{
let
cell
=
value
.
cell
;
let
index
=
this
.
notebookViewModel
!
.
getViewCellIndex
(
cell
);
let
cellTop
=
this
.
list
?.
getAbsoluteTop
(
index
)
||
0
;
if
(
this
.
webview
!
.
shouldUpdateInset
(
cell
,
key
,
cellTop
))
{
updateItems
.
push
({
cell
:
cell
,
output
:
key
,
cellTop
:
cellTop
});
}
})
)
;
});
this
.
list
?.
splice
(
0
,
this
.
list
?.
length
);
this
.
list
?.
splice
(
0
,
0
,
this
.
viewCells
);
this
.
list
?.
layout
();
});
if
(
updateItems
.
length
)
{
this
.
webview
?.
updateViewScrollTop
(
-
scrollTop
,
updateItems
);
}
}
}));
this
.
localStore
.
add
(
this
.
list
!
.
onFocusChange
((
e
)
=>
{
if
(
e
.
elements
.
length
>
0
)
{
this
.
notebookService
.
updateNotebookActiveCell
(
input
.
viewType
!
,
input
.
resource
!
,
e
.
elements
[
0
].
cell
.
handle
);
}
}));
this
.
list
?.
splice
(
0
,
this
.
list
?.
length
);
this
.
list
?.
splice
(
0
,
0
,
this
.
notebookViewModel
!
.
viewCells
);
this
.
list
?.
layout
();
}
private
saveTextEditorViewState
(
input
:
NotebookEditorInput
):
void
{
if
(
this
.
group
)
{
let
state
:
{
[
key
:
number
]:
boolean
}
=
{};
this
.
viewCells
.
filter
(
cell
=>
cell
.
isEditing
).
forEach
(
cell
=>
state
[
cell
.
cell
.
handle
]
=
true
);
this
.
notebookViewModel
!
.
viewCells
.
filter
(
cell
=>
cell
.
isEditing
).
forEach
(
cell
=>
state
[
cell
.
cell
.
handle
]
=
true
);
this
.
editorMemento
.
saveEditorState
(
this
.
group
,
input
,
{
editingCells
:
state
});
...
...
@@ -406,7 +389,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor, Noteb
//#region Find Delegate
startFind
(
value
:
string
):
CellFindMatch
[]
{
let
matches
:
CellFindMatch
[]
=
[];
this
.
viewCells
.
forEach
(
cell
=>
{
this
.
notebookViewModel
!
.
viewCells
.
forEach
(
cell
=>
{
let
cellMatches
=
cell
.
startFind
(
value
);
matches
.
push
(...
cellMatches
);
});
...
...
@@ -419,7 +402,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor, Noteb
focusNext
(
match
:
CellFindMatch
)
{
let
cell
=
match
.
cell
;
let
index
=
this
.
viewCells
.
indexOf
(
cell
);
let
index
=
this
.
notebookViewModel
!
.
viewCells
.
indexOf
(
cell
);
this
.
list
?.
reveal
(
index
);
}
...
...
@@ -437,7 +420,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor, Noteb
//#region Cell operations
layoutNotebookCell
(
cell
:
CellViewModel
,
height
:
number
)
{
let
relayout
=
(
cell
:
CellViewModel
,
height
:
number
)
=>
{
let
index
=
this
.
model
!
.
getNotebook
().
cells
.
indexOf
(
cell
.
cell
);
let
index
=
this
.
notebookViewModel
!
.
getViewCellIndex
(
cell
);
if
(
index
>=
0
)
{
this
.
list
?.
updateElementHeight
(
index
,
height
);
}
...
...
@@ -445,38 +428,28 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor, Noteb
DOM
.
scheduleAtNextAnimationFrame
(()
=>
{
relayout
(
cell
,
height
);
// this.relayoutDisposable = null;
});
}
updateViewCells
(
splices
:
NotebookCellsSplice
[])
{
let
update
=
()
=>
{
DOM
.
scheduleAtNextAnimationFrame
(
()
=>
{
splices
.
reverse
().
forEach
((
diff
)
=>
{
this
.
list
?.
splice
(
diff
[
0
],
diff
[
1
],
diff
[
2
].
map
(
cell
=>
{
return
this
.
instantiationService
.
createInstance
(
CellViewModel
,
this
.
viewType
!
,
this
.
model
!
.
notebook
!
.
handle
,
cell
,
false
);
return
this
.
instantiationService
.
createInstance
(
CellViewModel
,
this
.
viewType
!
,
this
.
notebookViewModel
!
.
handle
,
cell
,
false
);
}));
});
};
DOM
.
scheduleAtNextAnimationFrame
(()
=>
{
update
();
});
}
async
insertEmptyNotebookCell
(
listIndex
:
number
|
undefined
,
cell
:
CellViewModel
,
type
:
'
code
'
|
'
markdown
'
,
direction
:
'
above
'
|
'
below
'
):
Promise
<
void
>
{
let
newLanguages
=
this
.
model
!
.
notebook
!
.
languages
;
let
language
=
'
markdown
'
;
if
(
newLanguages
&&
newLanguages
.
length
)
{
language
=
newLanguages
[
0
];
}
let
index
=
listIndex
?
listIndex
:
this
.
model
!
.
getNotebook
().
cells
.
indexOf
(
cell
.
cell
);
async
insertEmptyNotebookCell
(
cell
:
CellViewModel
,
type
:
'
code
'
|
'
markdown
'
,
direction
:
'
above
'
|
'
below
'
):
Promise
<
void
>
{
const
newLanguages
=
this
.
notebookViewModel
!
.
languages
;
const
language
=
newLanguages
&&
newLanguages
.
length
?
newLanguages
[
0
]
:
'
markdown
'
;
const
index
=
this
.
notebookViewModel
!
.
getViewCellIndex
(
cell
);
const
insertIndex
=
direction
===
'
above
'
?
index
:
index
+
1
;
const
newModeCell
=
await
this
.
notebookService
.
createNotebookCell
(
this
.
viewType
!
,
this
.
notebookViewModel
!
.
uri
,
insertIndex
,
language
,
type
);
const
newCell
=
this
.
instantiationService
.
createInstance
(
CellViewModel
,
this
.
viewType
!
,
this
.
notebookViewModel
!
.
handle
,
newModeCell
!
,
false
);
let
newModeCell
=
await
this
.
notebookService
.
createNotebookCell
(
this
.
viewType
!
,
this
.
model
!
.
notebook
!
.
uri
,
insertIndex
,
language
,
type
);
let
newCell
=
this
.
instantiationService
.
createInstance
(
CellViewModel
,
this
.
viewType
!
,
this
.
model
!
.
notebook
!
.
handle
,
newModeCell
!
,
false
);
this
.
viewCells
!
.
splice
(
insertIndex
,
0
,
newCell
);
this
.
notebookViewModel
!
.
insertCell
(
insertIndex
,
newCell
);
this
.
list
?.
splice
(
insertIndex
,
0
,
[
newCell
]);
this
.
list
?.
setFocus
([
insertIndex
]);
...
...
@@ -489,11 +462,18 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor, Noteb
});
}
editNotebookCell
(
listIndex
:
number
|
undefined
,
cell
:
CellViewModel
):
void
{
async
deleteNotebookCell
(
cell
:
CellViewModel
):
Promise
<
void
>
{
const
index
=
this
.
notebookViewModel
!
.
getViewCellIndex
(
cell
);
await
this
.
notebookService
.
deleteNotebookCell
(
this
.
viewType
!
,
this
.
notebookViewModel
!
.
uri
,
index
);
this
.
notebookViewModel
!
.
deleteCell
(
index
);
this
.
list
?.
splice
(
index
,
1
);
}
editNotebookCell
(
cell
:
CellViewModel
):
void
{
cell
.
isEditing
=
true
;
}
saveNotebookCell
(
listIndex
:
number
|
undefined
,
cell
:
CellViewModel
):
void
{
saveNotebookCell
(
cell
:
CellViewModel
):
void
{
cell
.
isEditing
=
false
;
}
...
...
@@ -508,7 +488,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor, Noteb
}
focusNotebookCell
(
cell
:
CellViewModel
,
focusEditor
:
boolean
)
{
let
index
=
this
.
model
!
.
getNotebook
().
cells
.
indexOf
(
cell
.
cell
);
const
index
=
this
.
notebookViewModel
!
.
getViewCellIndex
(
cell
);
if
(
focusEditor
)
{
...
...
@@ -525,15 +505,6 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor, Noteb
this
.
list
?.
focusView
();
}
async
deleteNotebookCell
(
listIndex
:
number
|
undefined
,
cell
:
CellViewModel
):
Promise
<
void
>
{
let
index
=
this
.
model
!
.
getNotebook
().
cells
.
indexOf
(
cell
.
cell
);
// await this.notebookService.createNotebookCell(this.viewType!, this.model!.notebook!.uri, insertIndex, language, type);
await
this
.
notebookService
.
deleteNotebookCell
(
this
.
viewType
!
,
this
.
model
!
.
notebook
!
.
uri
,
index
);
this
.
viewCells
!
.
splice
(
index
,
1
);
this
.
list
?.
splice
(
index
,
1
);
}
//#endregion
//#region MISC
...
...
@@ -555,15 +526,15 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor, Noteb
return
;
}
let
preloads
=
this
.
model
!
.
notebook
!
.
renderers
;
let
preloads
=
this
.
notebookViewModel
!
.
renderers
;
if
(
!
this
.
webview
!
.
insetMapping
.
has
(
output
))
{
let
index
=
this
.
model
!
.
getNotebook
().
cells
.
indexOf
(
cell
.
cell
);
let
index
=
this
.
notebookViewModel
!
.
getViewCellIndex
(
cell
);
let
cellTop
=
this
.
list
?.
getAbsoluteTop
(
index
)
||
0
;
this
.
webview
!
.
createInset
(
cell
,
output
,
cellTop
,
offset
,
shadowContent
,
preloads
);
}
else
{
let
index
=
this
.
model
!
.
getNotebook
().
cells
.
indexOf
(
cell
.
cell
);
let
index
=
this
.
notebookViewModel
!
.
getViewCellIndex
(
cell
);
let
cellTop
=
this
.
list
?.
getAbsoluteTop
(
index
)
||
0
;
let
scrollTop
=
this
.
list
?.
scrollTop
||
0
;
...
...
src/vs/workbench/contrib/notebook/browser/notebookViewModel.ts
0 → 100644
浏览文件 @
9887d9ba
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
NotebookEditorModel
}
from
'
vs/workbench/contrib/notebook/browser/notebookEditorInput
'
;
import
{
CellViewModel
}
from
'
vs/workbench/contrib/notebook/browser/renderers/cellViewModel
'
;
import
{
DisposableStore
,
Disposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
Emitter
,
Event
}
from
'
vs/base/common/event
'
;
import
{
NotebookCellsSplice
}
from
'
vs/workbench/contrib/notebook/common/notebookCommon
'
;
import
{
CellFindMatch
}
from
'
vs/workbench/contrib/notebook/browser/notebookFindWidget
'
;
export
interface
INotebookEditorViewState
{
editingCells
:
{
[
key
:
number
]:
boolean
};
}
export
class
NotebookViewModel
extends
Disposable
{
private
_localStore
:
DisposableStore
=
this
.
_register
(
new
DisposableStore
());
private
_viewCells
:
CellViewModel
[]
=
[];
get
viewCells
()
{
return
this
.
_viewCells
;
}
get
notebookDocument
()
{
return
this
.
_model
.
notebook
;
}
get
renderers
()
{
return
this
.
_model
.
notebook
!
.
renderers
;
}
get
handle
()
{
return
this
.
_model
.
notebook
.
handle
;
}
get
languages
()
{
return
this
.
_model
.
notebook
.
languages
;
}
get
uri
()
{
return
this
.
_model
.
notebook
.
uri
;
}
private
readonly
_onDidChangeCells
=
new
Emitter
<
NotebookCellsSplice
[]
>
();
get
onDidChangeCells
():
Event
<
NotebookCellsSplice
[]
>
{
return
this
.
_onDidChangeCells
.
event
;
}
constructor
(
public
viewType
:
string
,
private
_model
:
NotebookEditorModel
,
@
IInstantiationService
private
readonly
instantiationService
:
IInstantiationService
,
)
{
super
();
this
.
_register
(
this
.
_model
.
onDidChangeCells
(
e
=>
this
.
_onDidChangeCells
.
fire
(
e
)));
}
initialize
(
viewState
:
INotebookEditorViewState
|
undefined
)
{
this
.
_viewCells
=
this
.
_model
!
.
notebook
!
.
cells
.
map
(
cell
=>
{
const
isEditing
=
viewState
&&
viewState
.
editingCells
[
cell
.
handle
];
const
viewCell
=
this
.
instantiationService
.
createInstance
(
CellViewModel
,
this
.
viewType
,
this
.
_model
!
.
notebook
!
.
handle
,
cell
,
!!
isEditing
);
this
.
_localStore
.
add
(
viewCell
);
return
viewCell
;
});
return
;
}
isDirty
()
{
return
this
.
_model
.
isDirty
();
}
hide
()
{
this
.
viewCells
.
forEach
(
cell
=>
{
if
(
cell
.
getText
()
!==
''
)
{
cell
.
isEditing
=
false
;
}
});
}
getViewCellIndex
(
cell
:
CellViewModel
)
{
return
this
.
viewCells
.
indexOf
(
cell
);
}
find
(
value
:
string
):
CellFindMatch
[]
{
let
matches
:
CellFindMatch
[]
=
[];
this
.
viewCells
.
forEach
(
cell
=>
{
let
cellMatches
=
cell
.
startFind
(
value
);
matches
.
push
(...
cellMatches
);
});
return
matches
;
}
insertCell
(
index
:
number
,
newCell
:
CellViewModel
)
{
this
.
viewCells
!
.
splice
(
index
,
0
,
newCell
);
this
.
_model
.
insertCell
(
newCell
.
cell
,
index
);
}
deleteCell
(
index
:
number
)
{
let
viewCell
=
this
.
viewCells
[
index
];
this
.
viewCells
.
splice
(
index
,
1
);
this
.
_model
.
deleteCell
(
viewCell
.
cell
);
}
equal
(
model
:
NotebookEditorModel
)
{
return
this
.
_model
===
model
;
}
dispose
()
{
this
.
_localStore
.
clear
();
this
.
_viewCells
.
forEach
(
cell
=>
{
cell
.
save
();
});
super
.
dispose
();
}
}
src/vs/workbench/contrib/notebook/browser/renderers/cellRenderer.ts
浏览文件 @
9887d9ba
...
...
@@ -89,7 +89,7 @@ class AbstractCellRenderer {
undefined
,
true
,
async
()
=>
{
await
this
.
notebookEditor
.
insertEmptyNotebookCell
(
listIndex
,
element
,
'
code
'
,
'
above
'
);
await
this
.
notebookEditor
.
insertEmptyNotebookCell
(
element
,
'
code
'
,
'
above
'
);
}
);
actions
.
push
(
insertAbove
);
...
...
@@ -100,7 +100,7 @@ class AbstractCellRenderer {
undefined
,
true
,
async
()
=>
{
await
this
.
notebookEditor
.
insertEmptyNotebookCell
(
listIndex
,
element
,
'
code
'
,
'
below
'
);
await
this
.
notebookEditor
.
insertEmptyNotebookCell
(
element
,
'
code
'
,
'
below
'
);
}
);
actions
.
push
(
insertBelow
);
...
...
@@ -111,7 +111,7 @@ class AbstractCellRenderer {
undefined
,
true
,
async
()
=>
{
await
this
.
notebookEditor
.
insertEmptyNotebookCell
(
listIndex
,
element
,
'
markdown
'
,
'
above
'
);
await
this
.
notebookEditor
.
insertEmptyNotebookCell
(
element
,
'
markdown
'
,
'
above
'
);
}
);
actions
.
push
(
insertMarkdownAbove
);
...
...
@@ -122,7 +122,7 @@ class AbstractCellRenderer {
undefined
,
true
,
async
()
=>
{
await
this
.
notebookEditor
.
insertEmptyNotebookCell
(
listIndex
,
element
,
'
markdown
'
,
'
below
'
);
await
this
.
notebookEditor
.
insertEmptyNotebookCell
(
element
,
'
markdown
'
,
'
below
'
);
}
);
actions
.
push
(
insertMarkdownBelow
);
...
...
@@ -134,7 +134,7 @@ class AbstractCellRenderer {
undefined
,
true
,
async
()
=>
{
this
.
notebookEditor
.
editNotebookCell
(
listIndex
,
element
);
this
.
notebookEditor
.
editNotebookCell
(
element
);
}
);
...
...
@@ -146,7 +146,7 @@ class AbstractCellRenderer {
undefined
,
true
,
async
()
=>
{
this
.
notebookEditor
.
saveNotebookCell
(
listIndex
,
element
);
this
.
notebookEditor
.
saveNotebookCell
(
element
);
}
);
...
...
@@ -159,7 +159,7 @@ class AbstractCellRenderer {
undefined
,
true
,
async
()
=>
{
this
.
notebookEditor
.
deleteNotebookCell
(
listIndex
,
element
);
this
.
notebookEditor
.
deleteNotebookCell
(
element
);
}
);
...
...
src/vs/workbench/contrib/notebook/browser/renderers/codeCell.ts
浏览文件 @
9887d9ba
...
...
@@ -104,7 +104,7 @@ export class CodeCell extends Disposable {
this
.
_register
(
templateData
.
editor
!
.
onDidContentSizeChange
((
e
)
=>
{
if
(
e
.
contentHeightChanged
)
{
if
(
viewCell
.
editorHeight
!==
e
.
contentHeight
)
{
if
(
this
.
viewCell
.
editorHeight
!==
e
.
contentHeight
)
{
templateData
.
editor
?.
layout
(
{
width
:
e
.
contentWidth
,
...
...
@@ -112,13 +112,13 @@ export class CodeCell extends Disposable {
}
);
viewCell
.
editorHeight
=
e
.
contentHeight
;
this
.
viewCell
.
editorHeight
=
e
.
contentHeight
;
if
(
viewCell
.
outputs
.
length
)
{
let
outputHeight
=
viewCell
.
getOutputTotalHeight
();
notebookEditor
.
layoutNotebookCell
(
viewCell
,
viewCell
.
editorHeight
+
32
+
outputHeight
);
if
(
this
.
viewCell
.
outputs
.
length
)
{
let
outputHeight
=
this
.
viewCell
.
getOutputTotalHeight
();
notebookEditor
.
layoutNotebookCell
(
this
.
viewCell
,
viewCell
.
editorHeight
+
32
+
outputHeight
);
}
else
{
notebookEditor
.
layoutNotebookCell
(
viewCell
,
viewCell
.
editorHeight
+
32
);
notebookEditor
.
layoutNotebookCell
(
this
.
viewCell
,
viewCell
.
editorHeight
+
32
);
}
}
...
...
src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts
0 → 100644
浏览文件 @
9887d9ba
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
*
as
assert
from
'
assert
'
;
import
{
Emitter
,
Event
}
from
'
vs/base/common/event
'
;
import
{
Disposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
PieceTreeTextBufferFactory
}
from
'
vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder
'
;
import
{
TestInstantiationService
}
from
'
vs/platform/instantiation/test/common/instantiationServiceMock
'
;
import
{
NotebookEditorModel
}
from
'
vs/workbench/contrib/notebook/browser/notebookEditorInput
'
;
import
{
NotebookViewModel
}
from
'
vs/workbench/contrib/notebook/browser/notebookViewModel
'
;
import
{
generateCellPath
,
ICell
,
INotebook
,
IOutput
,
NotebookCellOutputsSplice
,
NotebookCellsSplice
}
from
'
vs/workbench/contrib/notebook/common/notebookCommon
'
;
import
{
CellViewModel
}
from
'
vs/workbench/contrib/notebook/browser/renderers/cellViewModel
'
;
class
MockCell
implements
ICell
{
uri
:
URI
;
private
_onDidChangeOutputs
=
new
Emitter
<
NotebookCellOutputsSplice
[]
>
();
onDidChangeOutputs
:
Event
<
NotebookCellOutputsSplice
[]
>
=
this
.
_onDidChangeOutputs
.
event
;
private
_isDirty
:
boolean
=
false
;
private
_outputs
:
IOutput
[];
get
outputs
():
IOutput
[]
{
return
this
.
_outputs
;
}
get
isDirty
()
{
return
this
.
_isDirty
;
}
set
isDirty
(
newState
:
boolean
)
{
this
.
_isDirty
=
newState
;
}
constructor
(
public
viewType
:
string
,
public
handle
:
number
,
public
source
:
string
[],
public
language
:
string
,
public
cell_type
:
'
markdown
'
|
'
code
'
,
outputs
:
IOutput
[]
)
{
this
.
_outputs
=
outputs
;
this
.
uri
=
URI
.
from
({
scheme
:
'
vscode-notebook
'
,
authority
:
viewType
,
path
:
generateCellPath
(
cell_type
,
handle
),
query
:
''
});
}
resolveTextBufferFactory
():
PieceTreeTextBufferFactory
{
throw
new
Error
(
'
Method not implemented.
'
);
}
}
class
MockNotebook
extends
Disposable
implements
INotebook
{
private
readonly
_onDidChangeCells
=
new
Emitter
<
NotebookCellsSplice
[]
>
();
get
onDidChangeCells
():
Event
<
NotebookCellsSplice
[]
>
{
return
this
.
_onDidChangeCells
.
event
;
}
private
_onDidChangeDirtyState
=
new
Emitter
<
boolean
>
();
onDidChangeDirtyState
:
Event
<
boolean
>
=
this
.
_onDidChangeDirtyState
.
event
;
private
readonly
_onWillDispose
:
Emitter
<
void
>
=
this
.
_register
(
new
Emitter
<
void
>
());
readonly
onWillDispose
:
Event
<
void
>
=
this
.
_onWillDispose
.
event
;
cells
:
MockCell
[];
activeCell
:
MockCell
|
undefined
;
languages
:
string
[]
=
[];
renderers
=
new
Set
<
number
>
();
constructor
(
public
handle
:
number
,
public
viewType
:
string
,
public
uri
:
URI
)
{
super
();
this
.
cells
=
[];
}
save
():
Promise
<
boolean
>
{
throw
new
Error
(
'
Method not implemented.
'
);
}
}
suite
(
'
NotebookViewModel
'
,
()
=>
{
const
instantiationService
=
new
TestInstantiationService
();
const
createCellViewModel
=
(
viewType
:
string
,
notebookHandle
:
number
,
cellhandle
:
number
,
source
:
string
[],
language
:
string
,
cell_type
:
'
markdown
'
|
'
code
'
,
outputs
:
IOutput
[])
=>
{
const
mockCell
=
new
MockCell
(
viewType
,
cellhandle
,
source
,
language
,
cell_type
,
outputs
);
return
instantiationService
.
createInstance
(
CellViewModel
,
viewType
,
notebookHandle
,
mockCell
,
false
);
};
const
withNotebookDocument
=
(
cells
:
[
string
[],
string
,
'
markdown
'
|
'
code
'
,
IOutput
[]][],
callback
:
(
viewModel
:
NotebookViewModel
)
=>
void
)
=>
{
const
viewType
=
'
notebook
'
;
const
notebook
=
new
MockNotebook
(
0
,
viewType
,
URI
.
parse
(
'
test
'
));
notebook
.
cells
=
cells
.
map
((
cell
,
index
)
=>
{
return
new
MockCell
(
viewType
,
index
,
cell
[
0
],
cell
[
1
],
cell
[
2
],
cell
[
3
]);
});
const
model
=
new
NotebookEditorModel
(
notebook
);
const
viewModel
=
new
NotebookViewModel
(
viewType
,
model
,
instantiationService
);
viewModel
.
initialize
(
undefined
);
callback
(
viewModel
);
viewModel
.
dispose
();
return
;
};
test
(
'
ctor
'
,
function
()
{
const
notebook
=
new
MockNotebook
(
0
,
'
notebook
'
,
URI
.
parse
(
'
test
'
));
const
model
=
new
NotebookEditorModel
(
notebook
);
const
viewModel
=
new
NotebookViewModel
(
'
notebook
'
,
model
,
instantiationService
);
assert
.
equal
(
viewModel
.
viewType
,
'
notebook
'
);
});
test
(
'
insert/delete
'
,
function
()
{
withNotebookDocument
(
[
[[
'
var a = 1;
'
],
'
javascript
'
,
'
code
'
,
[]],
[[
'
var b = 2;
'
],
'
javascript
'
,
'
code
'
,
[]]
],
(
viewModel
)
=>
{
const
cell
=
createCellViewModel
(
viewModel
.
viewType
,
viewModel
.
handle
,
0
,
[
'
var c = 3;
'
],
'
javascript
'
,
'
code
'
,
[]);
viewModel
.
insertCell
(
1
,
cell
);
assert
.
equal
(
viewModel
.
viewCells
.
length
,
3
);
assert
.
equal
(
viewModel
.
notebookDocument
.
cells
.
length
,
3
);
assert
.
equal
(
viewModel
.
getViewCellIndex
(
cell
),
1
);
viewModel
.
deleteCell
(
1
);
assert
.
equal
(
viewModel
.
viewCells
.
length
,
2
);
assert
.
equal
(
viewModel
.
notebookDocument
.
cells
.
length
,
2
);
assert
.
equal
(
viewModel
.
getViewCellIndex
(
cell
),
-
1
);
}
);
});
test
(
'
index
'
,
function
()
{
withNotebookDocument
(
[
[[
'
var a = 1;
'
],
'
javascript
'
,
'
code
'
,
[]],
[[
'
var b = 2;
'
],
'
javascript
'
,
'
code
'
,
[]]
],
(
viewModel
)
=>
{
const
firstViewCell
=
viewModel
.
viewCells
[
0
];
const
lastViewCell
=
viewModel
.
viewCells
[
viewModel
.
viewCells
.
length
-
1
];
const
insertIndex
=
viewModel
.
getViewCellIndex
(
firstViewCell
)
+
1
;
const
cell
=
createCellViewModel
(
viewModel
.
viewType
,
viewModel
.
handle
,
3
,
[
'
var c = 3;
'
],
'
javascript
'
,
'
code
'
,
[]);
viewModel
.
insertCell
(
insertIndex
,
cell
);
const
addedCellIndex
=
viewModel
.
getViewCellIndex
(
cell
);
viewModel
.
deleteCell
(
addedCellIndex
);
const
secondInsertIndex
=
viewModel
.
getViewCellIndex
(
lastViewCell
)
+
1
;
const
cell2
=
createCellViewModel
(
viewModel
.
viewType
,
viewModel
.
handle
,
4
,
[
'
var d = 4;
'
],
'
javascript
'
,
'
code
'
,
[]);
viewModel
.
insertCell
(
secondInsertIndex
,
cell2
);
assert
.
equal
(
viewModel
.
viewCells
.
length
,
3
);
assert
.
equal
(
viewModel
.
notebookDocument
.
cells
.
length
,
3
);
assert
.
equal
(
viewModel
.
getViewCellIndex
(
cell2
),
2
);
}
);
});
});
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录