Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
7a9f0350
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,发现更多精彩内容 >>
提交
7a9f0350
编写于
9月 19, 2017
作者:
J
Joao Moreno
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'scm-viewlet'
上级
d5d4deea
7195502e
变更
27
展开全部
隐藏空白更改
内联
并排
Showing
27 changed file
with
1942 addition
and
149 deletion
+1942
-149
extensions/git/src/repository.ts
extensions/git/src/repository.ts
+1
-3
src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts
src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts
+4
-5
src/vs/base/browser/ui/inputbox/inputBox.ts
src/vs/base/browser/ui/inputbox/inputBox.ts
+7
-1
src/vs/base/browser/ui/list/listWidget.ts
src/vs/base/browser/ui/list/listWidget.ts
+1
-1
src/vs/base/browser/ui/octiconLabel/octiconLabel.mock.ts
src/vs/base/browser/ui/octiconLabel/octiconLabel.mock.ts
+4
-7
src/vs/base/browser/ui/octiconLabel/octiconLabel.ts
src/vs/base/browser/ui/octiconLabel/octiconLabel.ts
+7
-6
src/vs/base/browser/ui/sash/sash.ts
src/vs/base/browser/ui/sash/sash.ts
+4
-0
src/vs/base/browser/ui/splitview/panelview.css
src/vs/base/browser/ui/splitview/panelview.css
+86
-0
src/vs/base/browser/ui/splitview/panelview.ts
src/vs/base/browser/ui/splitview/panelview.ts
+398
-0
src/vs/base/browser/ui/splitview/splitview2.css
src/vs/base/browser/ui/splitview/splitview2.css
+23
-0
src/vs/base/browser/ui/splitview/splitview2.ts
src/vs/base/browser/ui/splitview/splitview2.ts
+342
-0
src/vs/base/common/arrays.ts
src/vs/base/common/arrays.ts
+35
-3
src/vs/base/common/event.ts
src/vs/base/common/event.ts
+19
-1
src/vs/base/common/numbers.ts
src/vs/base/common/numbers.ts
+5
-0
src/vs/base/test/browser/ui/splitview/splitview.test.ts
src/vs/base/test/browser/ui/splitview/splitview.test.ts
+314
-0
src/vs/platform/theme/common/styler.ts
src/vs/platform/theme/common/styler.ts
+6
-2
src/vs/vscode.d.ts
src/vs/vscode.d.ts
+7
-1
src/vs/workbench/api/electron-browser/mainThreadSCM.ts
src/vs/workbench/api/electron-browser/mainThreadSCM.ts
+5
-9
src/vs/workbench/api/node/extHost.api.impl.ts
src/vs/workbench/api/node/extHost.api.impl.ts
+2
-2
src/vs/workbench/api/node/extHost.protocol.ts
src/vs/workbench/api/node/extHost.protocol.ts
+1
-1
src/vs/workbench/api/node/extHostSCM.ts
src/vs/workbench/api/node/extHostSCM.ts
+8
-3
src/vs/workbench/browser/parts/views/views.ts
src/vs/workbench/browser/parts/views/views.ts
+7
-2
src/vs/workbench/browser/parts/views/views2.ts
src/vs/workbench/browser/parts/views/views2.ts
+271
-0
src/vs/workbench/parts/scm/electron-browser/media/scmViewlet.css
...workbench/parts/scm/electron-browser/media/scmViewlet.css
+29
-1
src/vs/workbench/parts/scm/electron-browser/scmActivity.ts
src/vs/workbench/parts/scm/electron-browser/scmActivity.ts
+6
-1
src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts
src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts
+349
-100
src/vs/workbench/services/scm/common/scm.ts
src/vs/workbench/services/scm/common/scm.ts
+1
-0
未找到文件。
extensions/git/src/repository.ts
浏览文件 @
7a9f0350
...
...
@@ -382,9 +382,7 @@ export class Repository implements Disposable {
const
onRelevantGitChange
=
filterEvent
(
onRelevantRepositoryChange
,
uri
=>
/
\/\.
git
\/
/
.
test
(
uri
.
path
));
onRelevantGitChange
(
this
.
_onDidChangeRepository
.
fire
,
this
.
_onDidChangeRepository
,
this
.
disposables
);
const
label
=
`
${
path
.
basename
(
repository
.
root
)}
(Git)`
;
this
.
_sourceControl
=
scm
.
createSourceControl
(
'
git
'
,
label
);
this
.
_sourceControl
=
scm
.
createSourceControl
(
'
git
'
,
'
Git
'
,
Uri
.
parse
(
repository
.
root
));
this
.
_sourceControl
.
acceptInputCommand
=
{
command
:
'
git.commitWithInput
'
,
title
:
localize
(
'
commit
'
,
"
Commit
"
),
arguments
:
[
this
.
_sourceControl
]
};
this
.
_sourceControl
.
quickDiffProvider
=
this
;
this
.
disposables
.
push
(
this
.
_sourceControl
);
...
...
src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts
浏览文件 @
7a9f0350
...
...
@@ -4,11 +4,10 @@
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
{
escape
}
from
'
vs/base/common/strings
'
;
import
{
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
*
as
dom
from
'
vs/base/browser/dom
'
;
import
*
as
objects
from
'
vs/base/common/objects
'
;
import
{
expand
as
expand
Octicons
}
from
'
vs/base/browser/ui/octiconLabel/octiconLabel
'
;
import
{
render
as
render
Octicons
}
from
'
vs/base/browser/ui/octiconLabel/octiconLabel
'
;
export
interface
IHighlight
{
start
:
number
;
...
...
@@ -64,19 +63,19 @@ export class HighlightedLabel implements IDisposable {
}
if
(
pos
<
highlight
.
start
)
{
htmlContent
.
push
(
'
<span>
'
);
htmlContent
.
push
(
expandOcticons
(
escape
(
this
.
text
.
substring
(
pos
,
highlight
.
start
)
)));
htmlContent
.
push
(
renderOcticons
(
this
.
text
.
substring
(
pos
,
highlight
.
start
)));
htmlContent
.
push
(
'
</span>
'
);
pos
=
highlight
.
end
;
}
htmlContent
.
push
(
'
<span class="highlight">
'
);
htmlContent
.
push
(
expandOcticons
(
escape
(
this
.
text
.
substring
(
highlight
.
start
,
highlight
.
end
)
)));
htmlContent
.
push
(
renderOcticons
(
this
.
text
.
substring
(
highlight
.
start
,
highlight
.
end
)));
htmlContent
.
push
(
'
</span>
'
);
pos
=
highlight
.
end
;
}
if
(
pos
<
this
.
text
.
length
)
{
htmlContent
.
push
(
'
<span>
'
);
htmlContent
.
push
(
expandOcticons
(
escape
(
this
.
text
.
substring
(
pos
)
)));
htmlContent
.
push
(
renderOcticons
(
this
.
text
.
substring
(
pos
)));
htmlContent
.
push
(
'
</span>
'
);
}
...
...
src/vs/base/browser/ui/inputbox/inputBox.ts
浏览文件 @
7a9f0350
...
...
@@ -179,7 +179,13 @@ export class InputBox extends Widget {
});
}
setTimeout
(()
=>
this
.
updateMirror
(),
0
);
setTimeout
(()
=>
{
if
(
!
this
.
input
)
{
return
;
}
this
.
updateMirror
();
},
0
);
// Support actions
if
(
this
.
options
.
actions
)
{
...
...
src/vs/base/browser/ui/list/listWidget.ts
浏览文件 @
7a9f0350
...
...
@@ -398,7 +398,7 @@ class MouseController<T> implements IDisposable {
if
(
isSelectionRangeChangeEvent
(
e
)
&&
reference
!==
undefined
)
{
const
min
=
Math
.
min
(
reference
,
focus
);
const
max
=
Math
.
max
(
reference
,
focus
);
const
rangeSelection
=
range
(
m
ax
+
1
,
min
);
const
rangeSelection
=
range
(
m
in
,
max
+
1
);
const
selection
=
this
.
list
.
getSelection
();
const
contiguousRange
=
getContiguousRangeContaining
(
disjunction
(
selection
,
[
reference
]),
reference
);
...
...
src/vs/base/browser/ui/octiconLabel/octiconLabel.mock.ts
浏览文件 @
7a9f0350
...
...
@@ -5,8 +5,8 @@
import
octiconLabel
=
require
(
'
vs/base/browser/ui/octiconLabel/octiconLabel
'
);
import
{
escape
}
from
'
vs/base/common/strings
'
;
function
expand
(
text
:
string
):
string
{
return
text
;
function
render
(
text
:
string
):
string
{
return
escape
(
text
)
;
}
class
MockOcticonLabel
{
...
...
@@ -18,16 +18,13 @@ class MockOcticonLabel {
}
set
text
(
text
:
string
)
{
let
innerHTML
=
text
||
''
;
innerHTML
=
escape
(
innerHTML
);
innerHTML
=
expand
(
innerHTML
);
this
.
_container
.
innerHTML
=
innerHTML
;
this
.
_container
.
innerHTML
=
render
(
text
||
''
);
}
}
var
mock
:
typeof
octiconLabel
=
{
expand
:
expand
,
render
:
render
,
OcticonLabel
:
<
any
>
MockOcticonLabel
};
export
=
mock
;
\ No newline at end of file
src/vs/base/browser/ui/octiconLabel/octiconLabel.ts
浏览文件 @
7a9f0350
...
...
@@ -8,12 +8,16 @@ import 'vs/css!./octicons/octicons';
import
'
vs/css!./octicons/octicons-animations
'
;
import
{
escape
}
from
'
vs/base/common/strings
'
;
export
function
expand
(
text
:
string
):
string
{
function
expand
(
text
:
string
):
string
{
return
text
.
replace
(
/
\$\(((
.+
?)(
~
(
.*
?))?)\)
/g
,
(
match
,
g1
,
name
,
g3
,
animation
)
=>
{
return
`<span class="octicon octicon-
${
name
}
${
animation
?
`octicon-animation-
${
animation
}
`
:
''
}
"></span>`
;
});
}
export
function
render
(
label
:
string
):
string
{
return
expand
(
escape
(
label
));
}
export
class
OcticonLabel
{
private
_container
:
HTMLElement
;
...
...
@@ -23,13 +27,10 @@ export class OcticonLabel {
}
set
text
(
text
:
string
)
{
let
innerHTML
=
text
||
''
;
innerHTML
=
escape
(
innerHTML
);
innerHTML
=
expand
(
innerHTML
);
this
.
_container
.
innerHTML
=
innerHTML
;
this
.
_container
.
innerHTML
=
render
(
text
||
''
);
}
set
title
(
title
:
string
)
{
this
.
_container
.
title
=
title
;
}
}
}
\ No newline at end of file
src/vs/base/browser/ui/sash/sash.ts
浏览文件 @
7a9f0350
...
...
@@ -268,6 +268,10 @@ export class Sash extends EventEmitter {
this
.
isDisabled
=
true
;
}
get
enabled
():
boolean
{
return
!
this
.
isDisabled
;
}
public
dispose
():
void
{
if
(
this
.
$e
)
{
this
.
$e
.
destroy
();
...
...
src/vs/base/browser/ui/splitview/panelview.css
0 → 100644
浏览文件 @
7a9f0350
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-panel-view
{
width
:
100%
;
height
:
100%
;
}
.monaco-panel-view
.panel
{
overflow
:
hidden
;
width
:
100%
;
height
:
100%
;
display
:
flex
;
flex-direction
:
column
;
}
.monaco-panel-view
.panel
>
.panel-header
{
font-size
:
11px
;
font-weight
:
bold
;
text-transform
:
uppercase
;
padding-left
:
20px
;
overflow
:
hidden
;
display
:
flex
;
cursor
:
pointer
;
}
.monaco-panel-view
.panel
>
.panel-header
{
background-image
:
url('arrow-collapse.svg')
;
background-position
:
2px
center
;
background-repeat
:
no-repeat
;
}
.monaco-panel-view
.panel
>
.panel-header.expanded
{
background-image
:
url('arrow-expand.svg')
;
background-position
:
2px
center
;
background-repeat
:
no-repeat
;
}
.vs-dark
.monaco-panel-view
.panel
>
.panel-header
{
background-image
:
url('arrow-collapse-dark.svg')
;
}
.vs-dark
.monaco-panel-view
.panel
>
.panel-header.expanded
{
background-image
:
url('arrow-expand-dark.svg')
;
}
/* TODO: actions should be part of the panel, but they aren't yet */
.monaco-panel-view
.panel
>
.panel-header
>
.actions
{
display
:
none
;
flex
:
1
;
}
/* TODO: actions should be part of the panel, but they aren't yet */
.monaco-panel-view
.panel
:hover
>
.panel-header
>
.actions
,
.monaco-panel-view
.panel
>
.panel-header.focused
>
.actions
{
display
:
initial
;
}
/* TODO: actions should be part of the panel, but they aren't yet */
.monaco-panel-view
.panel
>
.panel-header
>
.actions
.action-label
{
width
:
28px
;
height
:
22px
;
background-size
:
16px
;
background-position
:
center
center
;
background-repeat
:
no-repeat
;
margin-right
:
0
;
}
/* Bold font style does not go well with CJK fonts */
.monaco-panel-view
:lang
(
zh-Hans
)
.panel
>
.panel-header
,
.monaco-panel-view
:lang
(
zh-Hant
)
.panel
>
.panel-header
,
.monaco-panel-view
:lang
(
ja
)
.panel
>
.panel-header
,
.monaco-panel-view
:lang
(
ko
)
.panel
>
.panel-header
{
font-weight
:
normal
;
}
.monaco-panel-view
.panel
>
.panel-header.hidden
{
display
:
none
;
}
.monaco-panel-view
.panel
>
.panel-body
{
overflow
:
hidden
;
flex
:
1
;
}
\ No newline at end of file
src/vs/base/browser/ui/splitview/panelview.ts
0 → 100644
浏览文件 @
7a9f0350
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
'
vs/css!./panelview
'
;
import
{
IDisposable
,
dispose
,
combinedDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
Event
,
{
Emitter
,
chain
}
from
'
vs/base/common/event
'
;
import
{
domEvent
}
from
'
vs/base/browser/event
'
;
import
{
StandardKeyboardEvent
}
from
'
vs/base/browser/keyboardEvent
'
;
import
{
KeyCode
}
from
'
vs/base/common/keyCodes
'
;
import
{
$
,
append
,
addClass
,
removeClass
,
toggleClass
,
trackFocus
}
from
'
vs/base/browser/dom
'
;
import
{
firstIndex
}
from
'
vs/base/common/arrays
'
;
import
{
Color
,
RGBA
}
from
'
vs/base/common/color
'
;
import
{
SplitView
,
IView
}
from
'
./splitview2
'
;
export
interface
IPanelOptions
{
ariaHeaderLabel
?:
string
;
minimumBodySize
?:
number
;
maximumBodySize
?:
number
;
expanded
?:
boolean
;
}
export
interface
IPanelStyles
{
dropBackground
?:
Color
;
headerForeground
?:
Color
;
headerBackground
?:
Color
;
headerHighContrastBorder
?:
Color
;
}
export
abstract
class
Panel
implements
IView
{
private
static
HEADER_SIZE
=
22
;
private
_expanded
:
boolean
;
private
_headerVisible
=
true
;
private
_onDidChange
=
new
Emitter
<
void
>
();
private
_minimumBodySize
:
number
;
private
_maximumBodySize
:
number
;
private
ariaHeaderLabel
:
string
;
private
header
:
HTMLElement
;
protected
disposables
:
IDisposable
[]
=
[];
get
draggable
():
HTMLElement
{
return
this
.
header
;
}
private
_dropBackground
:
Color
|
undefined
;
get
dropBackground
():
Color
|
undefined
{
return
this
.
_dropBackground
;
}
get
minimumBodySize
():
number
{
return
this
.
_minimumBodySize
;
}
set
minimumBodySize
(
size
:
number
)
{
this
.
_minimumBodySize
=
size
;
this
.
_onDidChange
.
fire
();
}
get
maximumBodySize
():
number
{
return
this
.
_maximumBodySize
;
}
set
maximumBodySize
(
size
:
number
)
{
this
.
_maximumBodySize
=
size
;
this
.
_onDidChange
.
fire
();
}
private
get
headerSize
():
number
{
return
this
.
headerVisible
?
Panel
.
HEADER_SIZE
:
0
;
}
get
minimumSize
():
number
{
const
headerSize
=
this
.
headerSize
;
const
expanded
=
!
this
.
headerVisible
||
this
.
expanded
;
const
minimumBodySize
=
expanded
?
this
.
_minimumBodySize
:
0
;
return
headerSize
+
minimumBodySize
;
}
get
maximumSize
():
number
{
const
headerSize
=
this
.
headerSize
;
const
expanded
=
!
this
.
headerVisible
||
this
.
expanded
;
const
maximumBodySize
=
expanded
?
this
.
_maximumBodySize
:
0
;
return
headerSize
+
maximumBodySize
;
}
readonly
onDidChange
:
Event
<
void
>
=
this
.
_onDidChange
.
event
;
constructor
(
options
:
IPanelOptions
=
{})
{
this
.
_expanded
=
typeof
options
.
expanded
===
'
undefined
'
?
true
:
!!
options
.
expanded
;
this
.
ariaHeaderLabel
=
options
.
ariaHeaderLabel
||
''
;
this
.
_minimumBodySize
=
typeof
options
.
minimumBodySize
===
'
number
'
?
options
.
minimumBodySize
:
120
;
this
.
_maximumBodySize
=
typeof
options
.
maximumBodySize
===
'
number
'
?
options
.
maximumBodySize
:
Number
.
POSITIVE_INFINITY
;
this
.
header
=
$
(
'
.panel-header
'
);
}
get
expanded
():
boolean
{
return
this
.
_expanded
;
}
set
expanded
(
expanded
:
boolean
)
{
if
(
this
.
_expanded
===
!!
expanded
)
{
return
;
}
this
.
_expanded
=
!!
expanded
;
this
.
updateHeader
();
this
.
_onDidChange
.
fire
();
}
get
headerVisible
():
boolean
{
return
this
.
_headerVisible
;
}
set
headerVisible
(
visible
:
boolean
)
{
if
(
this
.
_headerVisible
===
!!
visible
)
{
return
;
}
this
.
_headerVisible
=
!!
visible
;
this
.
updateHeader
();
this
.
_onDidChange
.
fire
();
}
render
(
container
:
HTMLElement
):
void
{
const
panel
=
append
(
container
,
$
(
'
.panel
'
));
append
(
panel
,
this
.
header
);
this
.
header
.
setAttribute
(
'
tabindex
'
,
'
0
'
);
this
.
header
.
setAttribute
(
'
role
'
,
'
toolbar
'
);
this
.
header
.
setAttribute
(
'
aria-label
'
,
this
.
ariaHeaderLabel
);
this
.
renderHeader
(
this
.
header
);
const
focusTracker
=
trackFocus
(
this
.
header
);
focusTracker
.
addFocusListener
(()
=>
addClass
(
this
.
header
,
'
focused
'
));
focusTracker
.
addBlurListener
(()
=>
removeClass
(
this
.
header
,
'
focused
'
));
this
.
updateHeader
();
const
onHeaderKeyDown
=
chain
(
domEvent
(
this
.
header
,
'
keydown
'
))
.
map
(
e
=>
new
StandardKeyboardEvent
(
e
));
onHeaderKeyDown
.
filter
(
e
=>
e
.
keyCode
===
KeyCode
.
Enter
||
e
.
keyCode
===
KeyCode
.
Space
)
.
event
(()
=>
this
.
expanded
=
!
this
.
expanded
,
null
,
this
.
disposables
);
onHeaderKeyDown
.
filter
(
e
=>
e
.
keyCode
===
KeyCode
.
LeftArrow
)
.
event
(()
=>
this
.
expanded
=
false
,
null
,
this
.
disposables
);
onHeaderKeyDown
.
filter
(
e
=>
e
.
keyCode
===
KeyCode
.
RightArrow
)
.
event
(()
=>
this
.
expanded
=
true
,
null
,
this
.
disposables
);
domEvent
(
this
.
header
,
'
click
'
)
(()
=>
this
.
expanded
=
!
this
.
expanded
,
null
,
this
.
disposables
);
// TODO@Joao move this down to panelview
// onHeaderKeyDown.filter(e => e.keyCode === KeyCode.UpArrow)
// .event(focusPrevious, this, this.disposables);
// onHeaderKeyDown.filter(e => e.keyCode === KeyCode.DownArrow)
// .event(focusNext, this, this.disposables);
const
body
=
append
(
panel
,
$
(
'
.panel-body
'
));
this
.
renderBody
(
body
);
}
layout
(
size
:
number
):
void
{
const
headerSize
=
this
.
headerVisible
?
Panel
.
HEADER_SIZE
:
0
;
this
.
layoutBody
(
size
-
headerSize
);
}
style
(
styles
:
IPanelStyles
):
void
{
this
.
header
.
style
.
color
=
styles
.
headerForeground
?
styles
.
headerForeground
.
toString
()
:
null
;
this
.
header
.
style
.
backgroundColor
=
styles
.
headerBackground
?
styles
.
headerBackground
.
toString
()
:
null
;
this
.
header
.
style
.
borderTop
=
styles
.
headerHighContrastBorder
?
`1px solid
${
styles
.
headerHighContrastBorder
}
`
:
null
;
this
.
_dropBackground
=
styles
.
dropBackground
;
}
private
updateHeader
():
void
{
const
expanded
=
!
this
.
headerVisible
||
this
.
expanded
;
this
.
header
.
style
.
height
=
`
${
this
.
headerSize
}
px`
;
this
.
header
.
style
.
lineHeight
=
`
${
this
.
headerSize
}
px`
;
toggleClass
(
this
.
header
,
'
hidden
'
,
!
this
.
headerVisible
);
toggleClass
(
this
.
header
,
'
expanded
'
,
expanded
);
this
.
header
.
setAttribute
(
'
aria-expanded
'
,
String
(
expanded
));
}
protected
abstract
renderHeader
(
container
:
HTMLElement
):
void
;
protected
abstract
renderBody
(
container
:
HTMLElement
):
void
;
protected
abstract
layoutBody
(
size
:
number
):
void
;
dispose
():
void
{
this
.
disposables
=
dispose
(
this
.
disposables
);
}
}
interface
IDndContext
{
draggable
:
PanelDraggable
|
null
;
}
class
PanelDraggable
implements
IDisposable
{
private
static
DefaultDragOverBackgroundColor
=
new
Color
(
new
RGBA
(
128
,
128
,
128
,
0.5
));
// see https://github.com/Microsoft/vscode/issues/14470
private
dragOverCounter
=
0
;
private
disposables
:
IDisposable
[]
=
[];
private
_onDidDrop
=
new
Emitter
<
{
from
:
Panel
,
to
:
Panel
}
>
();
readonly
onDidDrop
=
this
.
_onDidDrop
.
event
;
constructor
(
private
panel
:
Panel
,
private
context
:
IDndContext
)
{
domEvent
(
panel
.
draggable
,
'
dragstart
'
)(
this
.
onDragStart
,
this
,
this
.
disposables
);
domEvent
(
panel
.
draggable
,
'
dragenter
'
)(
this
.
onDragEnter
,
this
,
this
.
disposables
);
domEvent
(
panel
.
draggable
,
'
dragleave
'
)(
this
.
onDragLeave
,
this
,
this
.
disposables
);
domEvent
(
panel
.
draggable
,
'
dragend
'
)(
this
.
onDragEnd
,
this
,
this
.
disposables
);
domEvent
(
panel
.
draggable
,
'
drop
'
)(
this
.
onDrop
,
this
,
this
.
disposables
);
}
private
onDragStart
(
e
:
DragEvent
):
void
{
e
.
dataTransfer
.
effectAllowed
=
'
move
'
;
const
dragImage
=
append
(
document
.
body
,
$
(
'
.monaco-panel-drag-image
'
,
{},
this
.
panel
.
draggable
.
textContent
));
e
.
dataTransfer
.
setDragImage
(
dragImage
,
-
10
,
-
10
);
setTimeout
(()
=>
document
.
body
.
removeChild
(
dragImage
),
0
);
this
.
context
.
draggable
=
this
;
}
private
onDragEnter
(
e
:
DragEvent
):
void
{
if
(
!
this
.
context
.
draggable
||
this
.
context
.
draggable
===
this
)
{
return
;
}
this
.
dragOverCounter
++
;
this
.
renderHeader
();
}
private
onDragLeave
(
e
:
DragEvent
):
void
{
if
(
!
this
.
context
.
draggable
||
this
.
context
.
draggable
===
this
)
{
return
;
}
this
.
dragOverCounter
--
;
if
(
this
.
dragOverCounter
===
0
)
{
this
.
renderHeader
();
}
}
private
onDragEnd
(
e
:
DragEvent
):
void
{
if
(
!
this
.
context
.
draggable
)
{
return
;
}
this
.
dragOverCounter
=
0
;
this
.
renderHeader
();
this
.
context
.
draggable
=
null
;
}
private
onDrop
(
e
:
DragEvent
):
void
{
if
(
!
this
.
context
.
draggable
)
{
return
;
}
this
.
dragOverCounter
=
0
;
this
.
renderHeader
();
if
(
this
.
context
.
draggable
!==
this
)
{
this
.
_onDidDrop
.
fire
({
from
:
this
.
context
.
draggable
.
panel
,
to
:
this
.
panel
});
}
this
.
context
.
draggable
=
null
;
}
private
renderHeader
():
void
{
let
backgroundColor
:
string
=
null
;
if
(
this
.
dragOverCounter
>
0
)
{
backgroundColor
=
(
this
.
panel
.
dropBackground
||
PanelDraggable
.
DefaultDragOverBackgroundColor
).
toString
();
}
this
.
panel
.
draggable
.
style
.
backgroundColor
=
backgroundColor
;
}
dispose
():
void
{
this
.
disposables
=
dispose
(
this
.
disposables
);
}
}
export
class
IPanelViewOptions
{
dnd
?:
boolean
;
}
interface
IPanelItem
{
panel
:
Panel
;
disposable
:
IDisposable
;
}
export
class
PanelView
implements
IDisposable
{
private
dnd
:
boolean
;
private
dndContext
:
IDndContext
=
{
draggable
:
null
};
private
el
:
HTMLElement
;
private
panelItems
:
IPanelItem
[]
=
[];
private
splitview
:
SplitView
;
private
animationTimer
:
number
|
null
=
null
;
private
_onDidDrop
=
new
Emitter
<
{
from
:
Panel
,
to
:
Panel
}
>
();
readonly
onDidDrop
:
Event
<
{
from
:
Panel
,
to
:
Panel
}
>
=
this
.
_onDidDrop
.
event
;
constructor
(
private
container
:
HTMLElement
,
options
:
IPanelViewOptions
=
{})
{
this
.
dnd
=
!!
options
.
dnd
;
this
.
el
=
append
(
container
,
$
(
'
.monaco-panel-view
'
));
this
.
splitview
=
new
SplitView
(
this
.
el
);
}
addPanel
(
panel
:
Panel
,
size
:
number
,
index
=
this
.
splitview
.
length
):
void
{
const
disposables
:
IDisposable
[]
=
[];
panel
.
onDidChange
(
this
.
setupAnimation
,
this
,
disposables
);
if
(
this
.
dnd
)
{
const
draggable
=
new
PanelDraggable
(
panel
,
this
.
dndContext
);
disposables
.
push
(
draggable
);
draggable
.
onDidDrop
(
this
.
_onDidDrop
.
fire
,
this
.
_onDidDrop
,
disposables
);
}
const
panelItem
=
{
panel
,
disposable
:
combinedDisposable
(
disposables
)
};
this
.
panelItems
.
splice
(
index
,
0
,
panelItem
);
this
.
splitview
.
addView
(
panel
,
size
,
index
);
}
removePanel
(
panel
:
Panel
):
void
{
const
index
=
firstIndex
(
this
.
panelItems
,
item
=>
item
.
panel
===
panel
);
if
(
index
===
-
1
)
{
return
;
}
this
.
splitview
.
removeView
(
index
);
const
panelItem
=
this
.
panelItems
.
splice
(
index
,
1
)[
0
];
panelItem
.
disposable
.
dispose
();
}
movePanel
(
from
:
Panel
,
to
:
Panel
):
void
{
const
fromIndex
=
firstIndex
(
this
.
panelItems
,
item
=>
item
.
panel
===
from
);
const
toIndex
=
firstIndex
(
this
.
panelItems
,
item
=>
item
.
panel
===
to
);
if
(
fromIndex
===
-
1
||
toIndex
===
-
1
)
{
return
;
}
const
[
panelItem
]
=
this
.
panelItems
.
splice
(
fromIndex
,
1
);
this
.
panelItems
.
splice
(
toIndex
<
fromIndex
?
toIndex
:
toIndex
-
1
,
0
,
panelItem
);
this
.
splitview
.
moveView
(
fromIndex
,
toIndex
);
}
resizePanel
(
panel
:
Panel
,
size
:
number
):
void
{
const
index
=
firstIndex
(
this
.
panelItems
,
item
=>
item
.
panel
===
panel
);
if
(
index
===
-
1
)
{
return
;
}
this
.
splitview
.
resizeView
(
index
,
size
);
}
layout
(
size
:
number
):
void
{
this
.
splitview
.
layout
(
size
);
}
private
setupAnimation
():
void
{
if
(
typeof
this
.
animationTimer
===
'
number
'
)
{
window
.
clearTimeout
(
this
.
animationTimer
);
}
addClass
(
this
.
el
,
'
animated
'
);
this
.
animationTimer
=
window
.
setTimeout
(()
=>
{
this
.
animationTimer
=
null
;
removeClass
(
this
.
el
,
'
animated
'
);
},
200
);
}
dispose
():
void
{
this
.
panelItems
.
forEach
(
i
=>
i
.
disposable
.
dispose
());
this
.
splitview
.
dispose
();
}
}
src/vs/base/browser/ui/splitview/splitview2.css
0 → 100644
浏览文件 @
7a9f0350
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-split-view2
{
position
:
relative
;
overflow
:
hidden
;
width
:
100%
;
height
:
100%
;
}
.monaco-split-view2
>
.split-view-view
{
overflow
:
hidden
;
}
.monaco-split-view2.vertical
>
.split-view-view
{
width
:
100%
;
}
.monaco-split-view2.horizontal
>
.split-view-view
{
height
:
100%
;
}
src/vs/base/browser/ui/splitview/splitview2.ts
0 → 100644
浏览文件 @
7a9f0350
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
'
vs/css!./splitview2
'
;
import
{
IDisposable
,
combinedDisposable
,
toDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
Event
,
{
fromEventEmitter
,
mapEvent
}
from
'
vs/base/common/event
'
;
import
types
=
require
(
'
vs/base/common/types
'
);
import
dom
=
require
(
'
vs/base/browser/dom
'
);
import
{
clamp
}
from
'
vs/base/common/numbers
'
;
import
{
range
,
firstIndex
}
from
'
vs/base/common/arrays
'
;
import
{
Sash
,
Orientation
,
ISashEvent
as
IBaseSashEvent
}
from
'
vs/base/browser/ui/sash/sash
'
;
export
{
Orientation
}
from
'
vs/base/browser/ui/sash/sash
'
;
export
interface
ISplitViewOptions
{
orientation
?:
Orientation
;
// default Orientation.VERTICAL
}
export
interface
IView
{
readonly
minimumSize
:
number
;
readonly
maximumSize
:
number
;
readonly
onDidChange
:
Event
<
void
>
;
render
(
container
:
HTMLElement
,
orientation
:
Orientation
):
void
;
layout
(
size
:
number
,
orientation
:
Orientation
):
void
;
}
interface
ISashEvent
{
sash
:
Sash
;
start
:
number
;
current
:
number
;
}
interface
IViewItem
{
view
:
IView
;
size
:
number
;
container
:
HTMLElement
;
disposable
:
IDisposable
;
layout
():
void
;
}
interface
ISashItem
{
sash
:
Sash
;
disposable
:
IDisposable
;
}
interface
ISashDragState
{
index
:
number
;
start
:
number
;
sizes
:
number
[];
minDelta
:
number
;
maxDelta
:
number
;
}
export
class
SplitView
implements
IDisposable
{
private
orientation
:
Orientation
;
private
el
:
HTMLElement
;
private
size
=
0
;
private
contentSize
=
0
;
private
viewItems
:
IViewItem
[]
=
[];
private
sashItems
:
ISashItem
[]
=
[];
private
sashDragState
:
ISashDragState
;
get
length
():
number
{
return
this
.
viewItems
.
length
;
}
constructor
(
private
container
:
HTMLElement
,
options
:
ISplitViewOptions
=
{})
{
this
.
orientation
=
types
.
isUndefined
(
options
.
orientation
)
?
Orientation
.
VERTICAL
:
options
.
orientation
;
this
.
el
=
document
.
createElement
(
'
div
'
);
dom
.
addClass
(
this
.
el
,
'
monaco-split-view2
'
);
dom
.
addClass
(
this
.
el
,
this
.
orientation
===
Orientation
.
VERTICAL
?
'
vertical
'
:
'
horizontal
'
);
container
.
appendChild
(
this
.
el
);
}
addView
(
view
:
IView
,
size
:
number
,
index
=
this
.
viewItems
.
length
):
void
{
// Add view
const
container
=
dom
.
$
(
'
.split-view-view
'
);
if
(
this
.
viewItems
.
length
===
1
)
{
this
.
el
.
appendChild
(
container
);
}
else
{
this
.
el
.
insertBefore
(
container
,
this
.
el
.
children
.
item
(
index
));
}
const
onChangeDisposable
=
mapEvent
(
view
.
onDidChange
,
()
=>
item
)(
this
.
onViewChange
,
this
);
const
containerDisposable
=
toDisposable
(()
=>
this
.
el
.
removeChild
(
container
));
const
disposable
=
combinedDisposable
([
onChangeDisposable
,
containerDisposable
]);
const
layoutContainer
=
this
.
orientation
===
Orientation
.
VERTICAL
?
size
=>
item
.
container
.
style
.
height
=
`
${
item
.
size
}
px`
:
size
=>
item
.
container
.
style
.
width
=
`
${
item
.
size
}
px`
;
const
layout
=
()
=>
{
layoutContainer
(
item
.
size
);
item
.
view
.
layout
(
item
.
size
,
this
.
orientation
);
};
size
=
Math
.
round
(
size
);
const
item
:
IViewItem
=
{
view
,
container
,
size
,
layout
,
disposable
};
this
.
viewItems
.
splice
(
index
,
0
,
item
);
// Add sash
if
(
this
.
viewItems
.
length
>
1
)
{
const
orientation
=
this
.
orientation
===
Orientation
.
VERTICAL
?
Orientation
.
HORIZONTAL
:
Orientation
.
VERTICAL
;
const
layoutProvider
=
this
.
orientation
===
Orientation
.
VERTICAL
?
{
getHorizontalSashTop
:
sash
=>
this
.
getSashPosition
(
sash
)
}
:
{
getVerticalSashLeft
:
sash
=>
this
.
getSashPosition
(
sash
)
};
const
sash
=
new
Sash
(
this
.
el
,
layoutProvider
,
{
orientation
});
const
sashEventMapper
=
this
.
orientation
===
Orientation
.
VERTICAL
?
(
e
:
IBaseSashEvent
)
=>
({
sash
,
start
:
e
.
startY
,
current
:
e
.
currentY
})
:
(
e
:
IBaseSashEvent
)
=>
({
sash
,
start
:
e
.
startX
,
current
:
e
.
currentX
});
const
onStart
=
mapEvent
(
fromEventEmitter
<
IBaseSashEvent
>
(
sash
,
'
start
'
),
sashEventMapper
);
const
onStartDisposable
=
onStart
(
this
.
onSashStart
,
this
);
const
onChange
=
mapEvent
(
fromEventEmitter
<
IBaseSashEvent
>
(
sash
,
'
change
'
),
sashEventMapper
);
const
onSashChangeDisposable
=
onChange
(
this
.
onSashChange
,
this
);
const
disposable
=
combinedDisposable
([
onStartDisposable
,
onSashChangeDisposable
,
sash
]);
const
sashItem
:
ISashItem
=
{
sash
,
disposable
};
this
.
sashItems
.
splice
(
index
-
1
,
0
,
sashItem
);
}
view
.
render
(
container
,
this
.
orientation
);
this
.
relayout
();
}
removeView
(
index
:
number
):
void
{
if
(
index
<
0
||
index
>=
this
.
viewItems
.
length
)
{
return
;
}
// Remove view
const
viewItem
=
this
.
viewItems
.
splice
(
index
,
1
)[
0
];
viewItem
.
disposable
.
dispose
();
// Remove sash
if
(
this
.
viewItems
.
length
>=
1
)
{
const
sashIndex
=
Math
.
max
(
index
-
1
,
0
);
const
sashItem
=
this
.
sashItems
.
splice
(
sashIndex
,
1
)[
0
];
sashItem
.
disposable
.
dispose
();
}
this
.
relayout
();
}
moveView
(
from
:
number
,
to
:
number
):
void
{
if
(
from
<
0
||
from
>=
this
.
viewItems
.
length
)
{
return
;
}
if
(
to
<
0
||
to
>=
this
.
viewItems
.
length
)
{
return
;
}
if
(
from
===
to
)
{
return
;
}
const
viewItem
=
this
.
viewItems
.
splice
(
from
,
1
)[
0
];
this
.
viewItems
.
splice
(
to
,
0
,
viewItem
);
this
.
layoutViews
();
}
private
relayout
():
void
{
const
contentSize
=
this
.
viewItems
.
reduce
((
r
,
i
)
=>
r
+
i
.
size
,
0
);
this
.
resize
(
this
.
viewItems
.
length
-
1
,
this
.
contentSize
-
contentSize
);
}
layout
(
size
:
number
):
void
{
const
previousSize
=
Math
.
max
(
this
.
size
,
this
.
contentSize
);
this
.
size
=
size
;
this
.
resize
(
this
.
viewItems
.
length
-
1
,
size
-
previousSize
);
}
private
onSashStart
({
sash
,
start
}:
ISashEvent
):
void
{
const
index
=
firstIndex
(
this
.
sashItems
,
item
=>
item
.
sash
===
sash
);
const
sizes
=
this
.
viewItems
.
map
(
i
=>
i
.
size
);
const
upIndexes
=
range
(
index
,
-
1
);
const
collapseUp
=
upIndexes
.
reduce
((
r
,
i
)
=>
r
+
(
sizes
[
i
]
-
this
.
viewItems
[
i
].
view
.
minimumSize
),
0
);
const
expandUp
=
upIndexes
.
reduce
((
r
,
i
)
=>
r
+
(
this
.
viewItems
[
i
].
view
.
maximumSize
-
sizes
[
i
]),
0
);
const
downIndexes
=
range
(
index
+
1
,
this
.
viewItems
.
length
);
const
collapseDown
=
downIndexes
.
reduce
((
r
,
i
)
=>
r
+
(
sizes
[
i
]
-
this
.
viewItems
[
i
].
view
.
minimumSize
),
0
);
const
expandDown
=
downIndexes
.
reduce
((
r
,
i
)
=>
r
+
(
this
.
viewItems
[
i
].
view
.
maximumSize
-
sizes
[
i
]),
0
);
const
minDelta
=
-
Math
.
min
(
collapseUp
,
expandDown
);
const
maxDelta
=
Math
.
min
(
collapseDown
,
expandUp
);
this
.
sashDragState
=
{
start
,
index
,
sizes
,
minDelta
,
maxDelta
};
}
private
onSashChange
({
sash
,
current
}:
ISashEvent
):
void
{
const
{
index
,
start
,
sizes
,
minDelta
,
maxDelta
}
=
this
.
sashDragState
;
const
delta
=
clamp
(
current
-
start
,
minDelta
,
maxDelta
);
this
.
resize
(
index
,
delta
,
sizes
);
}
private
onViewChange
(
item
:
IViewItem
):
void
{
const
index
=
this
.
viewItems
.
indexOf
(
item
);
if
(
index
<
0
||
index
>=
this
.
viewItems
.
length
)
{
return
;
}
const
size
=
clamp
(
item
.
size
,
item
.
view
.
minimumSize
,
item
.
view
.
maximumSize
);
item
.
size
=
size
;
this
.
relayout
();
}
resizeView
(
index
:
number
,
size
:
number
):
void
{
if
(
index
<
0
||
index
>=
this
.
viewItems
.
length
)
{
return
;
}
const
item
=
this
.
viewItems
[
index
];
size
=
Math
.
round
(
size
);
size
=
clamp
(
size
,
item
.
view
.
minimumSize
,
item
.
view
.
maximumSize
);
let
delta
=
size
-
item
.
size
;
if
(
delta
!==
0
&&
index
<
this
.
viewItems
.
length
-
1
)
{
const
downIndexes
=
range
(
index
+
1
,
this
.
viewItems
.
length
);
const
collapseDown
=
downIndexes
.
reduce
((
r
,
i
)
=>
r
+
(
this
.
viewItems
[
i
].
size
-
this
.
viewItems
[
i
].
view
.
minimumSize
),
0
);
const
expandDown
=
downIndexes
.
reduce
((
r
,
i
)
=>
r
+
(
this
.
viewItems
[
i
].
view
.
maximumSize
-
this
.
viewItems
[
i
].
size
),
0
);
const
deltaDown
=
clamp
(
delta
,
-
expandDown
,
collapseDown
);
this
.
resize
(
index
,
deltaDown
);
delta
-=
deltaDown
;
}
if
(
delta
!==
0
&&
index
>
0
)
{
const
upIndexes
=
range
(
index
-
1
,
-
1
);
const
collapseUp
=
upIndexes
.
reduce
((
r
,
i
)
=>
r
+
(
this
.
viewItems
[
i
].
size
-
this
.
viewItems
[
i
].
view
.
minimumSize
),
0
);
const
expandUp
=
upIndexes
.
reduce
((
r
,
i
)
=>
r
+
(
this
.
viewItems
[
i
].
view
.
maximumSize
-
this
.
viewItems
[
i
].
size
),
0
);
const
deltaUp
=
clamp
(
-
delta
,
-
collapseUp
,
expandUp
);
this
.
resize
(
index
-
1
,
deltaUp
);
}
}
private
resize
(
index
:
number
,
delta
:
number
,
sizes
=
this
.
viewItems
.
map
(
i
=>
i
.
size
)):
void
{
if
(
index
<
0
||
index
>=
this
.
viewItems
.
length
)
{
return
;
}
if
(
delta
!==
0
)
{
const
upIndexes
=
range
(
index
,
-
1
);
const
up
=
upIndexes
.
map
(
i
=>
this
.
viewItems
[
i
]);
const
upSizes
=
upIndexes
.
map
(
i
=>
sizes
[
i
]);
const
downIndexes
=
range
(
index
+
1
,
this
.
viewItems
.
length
);
const
down
=
downIndexes
.
map
(
i
=>
this
.
viewItems
[
i
]);
const
downSizes
=
downIndexes
.
map
(
i
=>
sizes
[
i
]);
for
(
let
i
=
0
,
deltaUp
=
delta
;
deltaUp
!==
0
&&
i
<
up
.
length
;
i
++
)
{
const
item
=
up
[
i
];
const
size
=
clamp
(
upSizes
[
i
]
+
deltaUp
,
item
.
view
.
minimumSize
,
item
.
view
.
maximumSize
);
const
viewDelta
=
size
-
upSizes
[
i
];
deltaUp
-=
viewDelta
;
item
.
size
=
size
;
}
for
(
let
i
=
0
,
deltaDown
=
delta
;
deltaDown
!==
0
&&
i
<
down
.
length
;
i
++
)
{
const
item
=
down
[
i
];
const
size
=
clamp
(
downSizes
[
i
]
-
deltaDown
,
item
.
view
.
minimumSize
,
item
.
view
.
maximumSize
);
const
viewDelta
=
size
-
downSizes
[
i
];
deltaDown
+=
viewDelta
;
item
.
size
=
size
;
}
}
let
contentSize
=
this
.
viewItems
.
reduce
((
r
,
i
)
=>
r
+
i
.
size
,
0
);
let
emptyDelta
=
this
.
size
-
contentSize
;
for
(
let
i
=
this
.
viewItems
.
length
-
1
;
emptyDelta
>
0
&&
i
>=
0
;
i
--
)
{
const
item
=
this
.
viewItems
[
i
];
const
size
=
clamp
(
item
.
size
+
emptyDelta
,
item
.
view
.
minimumSize
,
item
.
view
.
maximumSize
);
const
viewDelta
=
size
-
item
.
size
;
emptyDelta
-=
viewDelta
;
item
.
size
=
size
;
}
this
.
contentSize
=
this
.
viewItems
.
reduce
((
r
,
i
)
=>
r
+
i
.
size
,
0
);
this
.
layoutViews
();
}
private
layoutViews
():
void
{
this
.
viewItems
.
forEach
(
item
=>
item
.
layout
());
this
.
sashItems
.
forEach
(
item
=>
item
.
sash
.
layout
());
// Update sashes enablement
let
previous
=
false
;
const
collapsesDown
=
this
.
viewItems
.
map
(
i
=>
previous
=
(
i
.
size
-
i
.
view
.
minimumSize
>
0
)
||
previous
);
previous
=
false
;
const
expandsDown
=
this
.
viewItems
.
map
(
i
=>
previous
=
(
i
.
view
.
maximumSize
-
i
.
size
>
0
)
||
previous
);
const
reverseViews
=
[...
this
.
viewItems
].
reverse
();
previous
=
false
;
const
collapsesUp
=
reverseViews
.
map
(
i
=>
previous
=
(
i
.
size
-
i
.
view
.
minimumSize
>
0
)
||
previous
).
reverse
();
previous
=
false
;
const
expandsUp
=
reverseViews
.
map
(
i
=>
previous
=
(
i
.
view
.
maximumSize
-
i
.
size
>
0
)
||
previous
).
reverse
();
this
.
sashItems
.
forEach
((
s
,
i
)
=>
{
if
((
collapsesDown
[
i
]
&&
expandsUp
[
i
+
1
])
||
(
expandsDown
[
i
]
&&
collapsesUp
[
i
+
1
]))
{
s
.
sash
.
enable
();
}
else
{
s
.
sash
.
disable
();
}
});
}
private
getSashPosition
(
sash
:
Sash
):
number
{
let
position
=
0
;
for
(
let
i
=
0
;
i
<
this
.
sashItems
.
length
;
i
++
)
{
position
+=
this
.
viewItems
[
i
].
size
;
if
(
this
.
sashItems
[
i
].
sash
===
sash
)
{
return
position
;
}
}
return
0
;
}
dispose
():
void
{
this
.
viewItems
.
forEach
(
i
=>
i
.
disposable
.
dispose
());
this
.
viewItems
=
[];
this
.
sashItems
.
forEach
(
i
=>
i
.
disposable
.
dispose
());
this
.
sashItems
=
[];
}
}
src/vs/base/common/arrays.ts
浏览文件 @
7a9f0350
...
...
@@ -325,11 +325,43 @@ export function flatten<T>(arr: T[][]): T[] {
return
arr
.
reduce
((
r
,
v
)
=>
r
.
concat
(
v
),
[]);
}
export
function
range
(
to
:
number
,
from
=
0
):
number
[]
{
export
function
range
(
to
:
number
):
number
[];
export
function
range
(
from
:
number
,
to
:
number
):
number
[];
export
function
range
(
arg
:
number
,
to
?:
number
):
number
[]
{
let
from
=
typeof
to
===
'
number
'
?
arg
:
0
;
if
(
typeof
to
===
'
number
'
)
{
from
=
arg
;
}
else
{
from
=
0
;
to
=
arg
;
}
const
result
:
number
[]
=
[];
for
(
let
i
=
from
;
i
<
to
;
i
++
)
{
result
.
push
(
i
);
if
(
from
<=
to
)
{
for
(
let
i
=
from
;
i
<
to
;
i
++
)
{
result
.
push
(
i
);
}
}
else
{
for
(
let
i
=
from
;
i
>
to
;
i
--
)
{
result
.
push
(
i
);
}
}
return
result
;
}
export
function
weave
<
T
>
(
a
:
T
[],
b
:
T
[]):
T
[]
{
const
result
:
T
[]
=
[];
let
ai
=
0
,
bi
=
0
;
for
(
let
i
=
0
,
length
=
a
.
length
+
b
.
length
;
i
<
length
;
i
++
)
{
if
((
i
%
2
===
0
&&
ai
<
a
.
length
)
||
bi
>=
b
.
length
)
{
result
.
push
(
a
[
ai
++
]);
}
else
{
result
.
push
(
b
[
bi
++
]);
}
}
return
result
;
...
...
src/vs/base/common/event.ts
浏览文件 @
7a9f0350
...
...
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
{
IDisposable
,
toDisposable
,
combinedDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
IDisposable
,
toDisposable
,
combinedDisposable
,
empty
as
EmptyDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
CallbackList
from
'
vs/base/common/callbackList
'
;
import
{
EventEmitter
}
from
'
vs/base/common/eventEmitter
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
...
...
@@ -528,3 +528,21 @@ export function echo<T>(event: Event<T>, nextTick = false, buffer: T[] = []): Ev
return
emitter
.
event
;
}
export
class
Relay
<
T
>
implements
IDisposable
{
private
emitter
=
new
Emitter
<
T
>
();
readonly
output
:
Event
<
T
>
=
this
.
emitter
.
event
;
private
disposable
:
IDisposable
=
EmptyDisposable
;
set
input
(
event
:
Event
<
T
>
)
{
this
.
disposable
.
dispose
();
this
.
disposable
=
event
(
this
.
emitter
.
fire
,
this
.
emitter
);
}
dispose
()
{
this
.
disposable
.
dispose
();
this
.
emitter
.
dispose
();
}
}
\ No newline at end of file
src/vs/base/common/numbers.ts
浏览文件 @
7a9f0350
...
...
@@ -46,3 +46,8 @@ export function countToArray(fromOrTo: number, to?: number): number[] {
return
result
;
}
export
function
clamp
(
value
:
number
,
min
:
number
,
max
:
number
):
number
{
return
Math
.
min
(
Math
.
max
(
value
,
min
),
max
);
}
\ No newline at end of file
src/vs/base/test/browser/ui/splitview/splitview.test.ts
0 → 100644
浏览文件 @
7a9f0350
/*---------------------------------------------------------------------------------------------
* 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
}
from
'
vs/base/common/event
'
;
import
{
SplitView
,
IView
,
Orientation
}
from
'
vs/base/browser/ui/splitview/splitview2
'
;
import
{
Sash
}
from
'
vs/base/browser/ui/sash/sash
'
;
class
TestView
implements
IView
{
private
_onDidChange
=
new
Emitter
<
void
>
();
readonly
onDidChange
=
this
.
_onDidChange
.
event
;
get
minimumSize
():
number
{
return
this
.
_minimumSize
;
}
set
minimumSize
(
size
:
number
)
{
this
.
_minimumSize
=
size
;
this
.
_onDidChange
.
fire
();
}
get
maximumSize
():
number
{
return
this
.
_maximumSize
;
}
set
maximumSize
(
size
:
number
)
{
this
.
_maximumSize
=
size
;
this
.
_onDidChange
.
fire
();
}
private
_onDidRender
=
new
Emitter
<
{
container
:
HTMLElement
;
orientation
:
Orientation
}
>
();
readonly
onDidRender
=
this
.
_onDidRender
.
event
;
private
_size
=
0
;
get
size
():
number
{
return
this
.
_size
;
}
private
_onDidLayout
=
new
Emitter
<
{
size
:
number
;
orientation
:
Orientation
}
>
();
readonly
onDidLayout
=
this
.
_onDidLayout
.
event
;
private
_onDidFocus
=
new
Emitter
<
void
>
();
readonly
onDidFocus
=
this
.
_onDidFocus
.
event
;
constructor
(
private
_minimumSize
:
number
,
private
_maximumSize
:
number
)
{
assert
(
_minimumSize
<=
_maximumSize
,
'
splitview view minimum size must be <= maximum size
'
);
}
render
(
container
:
HTMLElement
,
orientation
:
Orientation
):
void
{
this
.
_onDidRender
.
fire
({
container
,
orientation
});
}
layout
(
size
:
number
,
orientation
:
Orientation
):
void
{
this
.
_size
=
size
;
this
.
_onDidLayout
.
fire
({
size
,
orientation
});
}
focus
():
void
{
this
.
_onDidFocus
.
fire
();
}
dispose
():
void
{
this
.
_onDidChange
.
dispose
();
this
.
_onDidRender
.
dispose
();
this
.
_onDidLayout
.
dispose
();
this
.
_onDidFocus
.
dispose
();
}
}
function
getSashes
(
splitview
:
SplitView
):
Sash
[]
{
return
(
splitview
as
any
).
sashItems
.
map
(
i
=>
i
.
sash
)
as
Sash
[];
}
suite
(
'
Splitview
'
,
()
=>
{
let
container
:
HTMLElement
;
setup
(()
=>
{
container
=
document
.
createElement
(
'
div
'
);
container
.
style
.
position
=
'
absolute
'
;
container
.
style
.
width
=
`
${
200
}
px`
;
container
.
style
.
height
=
`
${
200
}
px`
;
});
teardown
(()
=>
{
container
=
null
;
});
test
(
'
empty splitview has empty DOM
'
,
()
=>
{
const
splitview
=
new
SplitView
(
container
);
assert
.
equal
(
container
.
firstElementChild
.
childElementCount
,
0
,
'
split view should be empty
'
);
splitview
.
dispose
();
});
test
(
'
has views and sashes as children
'
,
()
=>
{
const
view1
=
new
TestView
(
20
,
20
);
const
view2
=
new
TestView
(
20
,
20
);
const
view3
=
new
TestView
(
20
,
20
);
const
splitview
=
new
SplitView
(
container
);
splitview
.
addView
(
view1
,
20
);
splitview
.
addView
(
view2
,
20
);
splitview
.
addView
(
view3
,
20
);
let
viewQuery
=
container
.
querySelectorAll
(
'
.monaco-split-view2 > .split-view-view
'
);
assert
.
equal
(
viewQuery
.
length
,
3
,
'
split view should have 3 views
'
);
let
sashQuery
=
container
.
querySelectorAll
(
'
.monaco-split-view2 > .monaco-sash
'
);
assert
.
equal
(
sashQuery
.
length
,
2
,
'
split view should have 2 sashes
'
);
splitview
.
removeView
(
2
);
viewQuery
=
container
.
querySelectorAll
(
'
.monaco-split-view2 > .split-view-view
'
);
assert
.
equal
(
viewQuery
.
length
,
2
,
'
split view should have 2 views
'
);
sashQuery
=
container
.
querySelectorAll
(
'
.monaco-split-view2 > .monaco-sash
'
);
assert
.
equal
(
sashQuery
.
length
,
1
,
'
split view should have 1 sash
'
);
splitview
.
removeView
(
0
);
viewQuery
=
container
.
querySelectorAll
(
'
.monaco-split-view2 > .split-view-view
'
);
assert
.
equal
(
viewQuery
.
length
,
1
,
'
split view should have 1 view
'
);
sashQuery
=
container
.
querySelectorAll
(
'
.monaco-split-view2 > .monaco-sash
'
);
assert
.
equal
(
sashQuery
.
length
,
0
,
'
split view should have no sashes
'
);
splitview
.
removeView
(
0
);
viewQuery
=
container
.
querySelectorAll
(
'
.monaco-split-view2 > .split-view-view
'
);
assert
.
equal
(
viewQuery
.
length
,
0
,
'
split view should have no views
'
);
sashQuery
=
container
.
querySelectorAll
(
'
.monaco-split-view2 > .monaco-sash
'
);
assert
.
equal
(
sashQuery
.
length
,
0
,
'
split view should have no sashes
'
);
splitview
.
dispose
();
view1
.
dispose
();
view2
.
dispose
();
view3
.
dispose
();
});
test
(
'
calls view methods on addView and removeView
'
,
()
=>
{
const
view
=
new
TestView
(
20
,
20
);
const
splitview
=
new
SplitView
(
container
);
let
didLayout
=
false
;
const
layoutDisposable
=
view
.
onDidLayout
(()
=>
didLayout
=
true
);
let
didRender
=
false
;
const
renderDisposable
=
view
.
onDidRender
(()
=>
didRender
=
true
);
splitview
.
addView
(
view
,
20
);
assert
.
equal
(
view
.
size
,
20
,
'
view has right size
'
);
assert
(
didLayout
,
'
layout is called
'
);
assert
(
didLayout
,
'
render is called
'
);
splitview
.
dispose
();
layoutDisposable
.
dispose
();
renderDisposable
.
dispose
();
view
.
dispose
();
});
test
(
'
stretches view to viewport
'
,
()
=>
{
const
view
=
new
TestView
(
20
,
Number
.
POSITIVE_INFINITY
);
const
splitview
=
new
SplitView
(
container
);
splitview
.
layout
(
200
);
splitview
.
addView
(
view
,
20
);
assert
.
equal
(
view
.
size
,
200
,
'
view is stretched
'
);
splitview
.
layout
(
200
);
assert
.
equal
(
view
.
size
,
200
,
'
view stayed the same
'
);
splitview
.
layout
(
100
);
assert
.
equal
(
view
.
size
,
100
,
'
view is collapsed
'
);
splitview
.
layout
(
20
);
assert
.
equal
(
view
.
size
,
20
,
'
view is collapsed
'
);
splitview
.
layout
(
10
);
assert
.
equal
(
view
.
size
,
20
,
'
view is clamped
'
);
splitview
.
layout
(
200
);
assert
.
equal
(
view
.
size
,
200
,
'
view is stretched
'
);
splitview
.
dispose
();
view
.
dispose
();
});
test
(
'
can resize views
'
,
()
=>
{
const
view1
=
new
TestView
(
20
,
Number
.
POSITIVE_INFINITY
);
const
view2
=
new
TestView
(
20
,
Number
.
POSITIVE_INFINITY
);
const
view3
=
new
TestView
(
20
,
Number
.
POSITIVE_INFINITY
);
const
splitview
=
new
SplitView
(
container
);
splitview
.
layout
(
200
);
splitview
.
addView
(
view1
,
20
);
splitview
.
addView
(
view2
,
20
);
splitview
.
addView
(
view3
,
20
);
assert
.
equal
(
view1
.
size
,
160
,
'
view1 is stretched
'
);
assert
.
equal
(
view2
.
size
,
20
,
'
view2 size is 20
'
);
assert
.
equal
(
view3
.
size
,
20
,
'
view3 size is 20
'
);
splitview
.
resizeView
(
1
,
40
);
assert
.
equal
(
view1
.
size
,
140
,
'
view1 is collapsed
'
);
assert
.
equal
(
view2
.
size
,
40
,
'
view2 is stretched
'
);
assert
.
equal
(
view3
.
size
,
20
,
'
view3 stays the same
'
);
splitview
.
resizeView
(
0
,
70
);
assert
.
equal
(
view1
.
size
,
70
,
'
view1 is collapsed
'
);
assert
.
equal
(
view2
.
size
,
110
,
'
view2 is expanded
'
);
assert
.
equal
(
view3
.
size
,
20
,
'
view3 stays the same
'
);
splitview
.
resizeView
(
2
,
40
);
assert
.
equal
(
view1
.
size
,
70
,
'
view1 stays the same
'
);
assert
.
equal
(
view2
.
size
,
90
,
'
view2 is collapsed
'
);
assert
.
equal
(
view3
.
size
,
40
,
'
view3 is stretched
'
);
splitview
.
dispose
();
view3
.
dispose
();
view2
.
dispose
();
view1
.
dispose
();
});
test
(
'
reacts to view changes
'
,
()
=>
{
const
view1
=
new
TestView
(
20
,
Number
.
POSITIVE_INFINITY
);
const
view2
=
new
TestView
(
20
,
Number
.
POSITIVE_INFINITY
);
const
view3
=
new
TestView
(
20
,
Number
.
POSITIVE_INFINITY
);
const
splitview
=
new
SplitView
(
container
);
splitview
.
layout
(
200
);
splitview
.
addView
(
view1
,
20
);
splitview
.
addView
(
view2
,
20
);
splitview
.
addView
(
view3
,
20
);
assert
.
equal
(
view1
.
size
,
160
,
'
view1 is stretched
'
);
assert
.
equal
(
view2
.
size
,
20
,
'
view2 size is 20
'
);
assert
.
equal
(
view3
.
size
,
20
,
'
view3 size is 20
'
);
view1
.
maximumSize
=
20
;
assert
.
equal
(
view1
.
size
,
20
,
'
view1 is collapsed
'
);
assert
.
equal
(
view2
.
size
,
20
,
'
view2 stays the same
'
);
assert
.
equal
(
view3
.
size
,
160
,
'
view3 is stretched
'
);
view3
.
maximumSize
=
40
;
assert
.
equal
(
view1
.
size
,
20
,
'
view1 stays the same
'
);
assert
.
equal
(
view2
.
size
,
140
,
'
view2 is stretched
'
);
assert
.
equal
(
view3
.
size
,
40
,
'
view3 is collapsed
'
);
view2
.
maximumSize
=
200
;
assert
.
equal
(
view1
.
size
,
20
,
'
view1 stays the same
'
);
assert
.
equal
(
view2
.
size
,
140
,
'
view2 stays the same
'
);
assert
.
equal
(
view3
.
size
,
40
,
'
view3 stays the same
'
);
view3
.
maximumSize
=
Number
.
POSITIVE_INFINITY
;
view3
.
minimumSize
=
100
;
assert
.
equal
(
view1
.
size
,
20
,
'
view1 is collapsed
'
);
assert
.
equal
(
view2
.
size
,
80
,
'
view2 is collapsed
'
);
assert
.
equal
(
view3
.
size
,
100
,
'
view3 is stretched
'
);
splitview
.
dispose
();
view3
.
dispose
();
view2
.
dispose
();
view1
.
dispose
();
});
test
(
'
sashes are properly enabled/disabled
'
,
()
=>
{
const
view1
=
new
TestView
(
20
,
Number
.
POSITIVE_INFINITY
);
const
view2
=
new
TestView
(
20
,
Number
.
POSITIVE_INFINITY
);
const
view3
=
new
TestView
(
20
,
Number
.
POSITIVE_INFINITY
);
const
splitview
=
new
SplitView
(
container
);
splitview
.
layout
(
200
);
splitview
.
addView
(
view1
,
20
);
splitview
.
addView
(
view2
,
20
);
splitview
.
addView
(
view3
,
20
);
let
sashes
=
getSashes
(
splitview
);
assert
.
equal
(
sashes
.
length
,
2
,
'
there are two sashes
'
);
assert
.
equal
(
sashes
[
0
].
enabled
,
true
,
'
first sash is enabled
'
);
assert
.
equal
(
sashes
[
1
].
enabled
,
true
,
'
second sash is enabled
'
);
splitview
.
layout
(
60
);
assert
.
equal
(
sashes
[
0
].
enabled
,
false
,
'
first sash is disabled
'
);
assert
.
equal
(
sashes
[
1
].
enabled
,
false
,
'
second sash is disabled
'
);
splitview
.
layout
(
20
);
assert
.
equal
(
sashes
[
0
].
enabled
,
false
,
'
first sash is disabled
'
);
assert
.
equal
(
sashes
[
1
].
enabled
,
false
,
'
second sash is disabled
'
);
splitview
.
layout
(
200
);
assert
.
equal
(
sashes
[
0
].
enabled
,
true
,
'
first sash is enabled
'
);
assert
.
equal
(
sashes
[
1
].
enabled
,
true
,
'
second sash is enabled
'
);
view1
.
maximumSize
=
20
;
assert
.
equal
(
sashes
[
0
].
enabled
,
false
,
'
first sash is disabled
'
);
assert
.
equal
(
sashes
[
1
].
enabled
,
true
,
'
second sash is enabled
'
);
view2
.
maximumSize
=
20
;
assert
.
equal
(
sashes
[
0
].
enabled
,
false
,
'
first sash is disabled
'
);
assert
.
equal
(
sashes
[
1
].
enabled
,
false
,
'
second sash is disabled
'
);
view1
.
maximumSize
=
300
;
assert
.
equal
(
sashes
[
0
].
enabled
,
true
,
'
first sash is enabled
'
);
assert
.
equal
(
sashes
[
1
].
enabled
,
true
,
'
second sash is enabled
'
);
view2
.
maximumSize
=
200
;
assert
.
equal
(
sashes
[
0
].
enabled
,
true
,
'
first sash is enabled
'
);
assert
.
equal
(
sashes
[
1
].
enabled
,
true
,
'
second sash is enabled
'
);
splitview
.
dispose
();
view3
.
dispose
();
view2
.
dispose
();
view1
.
dispose
();
});
});
\ No newline at end of file
src/vs/platform/theme/common/styler.ts
浏览文件 @
7a9f0350
...
...
@@ -15,11 +15,15 @@ export interface IThemable {
style
:
styleFn
;
}
export
function
attachStyler
(
themeService
:
IThemeService
,
optionsMapping
:
{
[
optionsKey
:
string
]:
ColorIdentifier
|
ColorFunction
},
widgetOrCallback
:
IThemable
|
styleFn
):
IDisposable
{
export
interface
IColorMapping
{
[
optionsKey
:
string
]:
ColorIdentifier
|
ColorFunction
|
undefined
;
}
export
function
attachStyler
<
T
extends
IColorMapping
>
(
themeService
:
IThemeService
,
optionsMapping
:
T
,
widgetOrCallback
:
IThemable
|
styleFn
):
IDisposable
{
function
applyStyles
(
theme
:
ITheme
):
void
{
const
styles
=
Object
.
create
(
null
);
for
(
let
key
in
optionsMapping
)
{
const
value
=
optionsMapping
[
key
];
const
value
=
optionsMapping
[
key
as
string
];
if
(
typeof
value
===
'
string
'
)
{
styles
[
key
]
=
theme
.
getColor
(
value
);
}
else
if
(
typeof
value
===
'
function
'
)
{
...
...
src/vs/vscode.d.ts
浏览文件 @
7a9f0350
...
...
@@ -5506,6 +5506,11 @@ declare module 'vscode' {
*/
readonly
label
:
string
;
/**
* The (optional) Uri of the root of this source control.
*/
readonly
rootUri
:
Uri
|
undefined
;
/**
* The [input box](#SourceControlInputBox) for this source control.
*/
...
...
@@ -5574,9 +5579,10 @@ declare module 'vscode' {
*
* @param id An `id` for the source control. Something short, eg: `git`.
* @param label A human-readable string for the source control. Eg: `Git`.
* @param rootUri An optional Uri of the root of the source control. Eg: `Uri.parse(workspaceRoot)`.
* @return An instance of [source control](#SourceControl).
*/
export
function
createSourceControl
(
id
:
string
,
label
:
string
):
SourceControl
;
export
function
createSourceControl
(
id
:
string
,
label
:
string
,
rootUri
?:
Uri
):
SourceControl
;
}
/**
...
...
src/vs/workbench/api/electron-browser/mainThreadSCM.ts
浏览文件 @
7a9f0350
...
...
@@ -100,18 +100,17 @@ class MainThreadSCMProvider implements ISCMProvider {
get
handle
():
number
{
return
this
.
_handle
;
}
get
label
():
string
{
return
this
.
_label
;
}
get
rootUri
():
URI
|
undefined
{
return
this
.
_rootUri
;
}
get
contextValue
():
string
{
return
this
.
_contextValue
;
}
get
commitTemplate
():
string
|
undefined
{
return
this
.
features
.
commitTemplate
;
}
get
acceptInputCommand
():
Command
|
undefined
{
return
this
.
features
.
acceptInputCommand
;
}
get
statusBarCommands
():
Command
[]
|
undefined
{
return
this
.
features
.
statusBarCommands
;
}
get
count
():
number
|
undefined
{
return
this
.
features
.
count
;
}
private
_onDidChangeCommitTemplate
=
new
Emitter
<
string
>
();
get
onDidChangeCommitTemplate
():
Event
<
string
>
{
return
this
.
_onDidChangeCommitTemplate
.
event
;
}
private
_count
:
number
|
undefined
=
undefined
;
get
count
():
number
|
undefined
{
return
this
.
_count
;
}
private
_onDidChange
=
new
Emitter
<
void
>
();
get
onDidChange
():
Event
<
void
>
{
return
this
.
_onDidChange
.
event
;
}
...
...
@@ -120,15 +119,12 @@ class MainThreadSCMProvider implements ISCMProvider {
private
_handle
:
number
,
private
_contextValue
:
string
,
private
_label
:
string
,
private
_rootUri
:
URI
|
undefined
,
@
ISCMService
scmService
:
ISCMService
,
@
ICommandService
private
commandService
:
ICommandService
)
{
}
$updateSourceControl
(
features
:
SCMProviderFeatures
):
void
{
if
(
'
count
'
in
features
)
{
this
.
_count
=
features
.
count
;
}
this
.
features
=
assign
(
this
.
features
,
features
);
this
.
_onDidChange
.
fire
();
...
...
@@ -275,8 +271,8 @@ export class MainThreadSCM implements MainThreadSCMShape {
this
.
_disposables
=
dispose
(
this
.
_disposables
);
}
$registerSourceControl
(
handle
:
number
,
id
:
string
,
label
:
string
):
void
{
const
provider
=
new
MainThreadSCMProvider
(
this
.
_proxy
,
handle
,
id
,
label
,
this
.
scmService
,
this
.
commandService
);
$registerSourceControl
(
handle
:
number
,
id
:
string
,
label
:
string
,
rootUri
:
string
|
undefined
):
void
{
const
provider
=
new
MainThreadSCMProvider
(
this
.
_proxy
,
handle
,
id
,
label
,
rootUri
&&
URI
.
parse
(
rootUri
),
this
.
scmService
,
this
.
commandService
);
const
repository
=
this
.
scmService
.
registerSCMProvider
(
provider
);
this
.
_repositories
[
handle
]
=
repository
;
...
...
src/vs/workbench/api/node/extHost.api.impl.ts
浏览文件 @
7a9f0350
...
...
@@ -486,14 +486,14 @@ export function createApiFactory(
get
inputBox
()
{
return
extHostSCM
.
getLastInputBox
(
extension
);
},
createSourceControl
(
id
:
string
,
label
:
string
)
{
createSourceControl
(
id
:
string
,
label
:
string
,
rootUri
?:
vscode
.
Uri
)
{
mainThreadTelemetry
.
$publicLog
(
'
registerSCMProvider
'
,
{
extensionId
:
extension
.
id
,
providerId
:
id
,
providerLabel
:
label
});
return
extHostSCM
.
createSourceControl
(
extension
,
id
,
label
);
return
extHostSCM
.
createSourceControl
(
extension
,
id
,
label
,
rootUri
);
}
};
...
...
src/vs/workbench/api/node/extHost.protocol.ts
浏览文件 @
7a9f0350
...
...
@@ -363,7 +363,7 @@ export type SCMRawResourceSplices = [
];
export
interface
MainThreadSCMShape
extends
IDisposable
{
$registerSourceControl
(
handle
:
number
,
id
:
string
,
label
:
string
):
void
;
$registerSourceControl
(
handle
:
number
,
id
:
string
,
label
:
string
,
rootUri
:
string
|
undefined
):
void
;
$updateSourceControl
(
handle
:
number
,
features
:
SCMProviderFeatures
):
void
;
$unregisterSourceControl
(
handle
:
number
):
void
;
...
...
src/vs/workbench/api/node/extHostSCM.ts
浏览文件 @
7a9f0350
...
...
@@ -287,6 +287,10 @@ class ExtHostSourceControl implements vscode.SourceControl {
return
this
.
_label
;
}
get
rootUri
():
vscode
.
Uri
|
undefined
{
return
this
.
_rootUri
;
}
private
_inputBox
:
ExtHostSCMInputBox
;
get
inputBox
():
ExtHostSCMInputBox
{
return
this
.
_inputBox
;
}
...
...
@@ -356,9 +360,10 @@ class ExtHostSourceControl implements vscode.SourceControl {
private
_commands
:
ExtHostCommands
,
private
_id
:
string
,
private
_label
:
string
,
private
_rootUri
?:
vscode
.
Uri
)
{
this
.
_inputBox
=
new
ExtHostSCMInputBox
(
this
.
_proxy
,
this
.
handle
);
this
.
_proxy
.
$registerSourceControl
(
this
.
handle
,
_id
,
_label
);
this
.
_proxy
.
$registerSourceControl
(
this
.
handle
,
_id
,
_label
,
_rootUri
&&
_rootUri
.
toString
()
);
}
private
updatedResourceGroups
=
new
Set
<
ExtHostSourceControlResourceGroup
>
();
...
...
@@ -468,9 +473,9 @@ export class ExtHostSCM {
});
}
createSourceControl
(
extension
:
IExtensionDescription
,
id
:
string
,
label
:
string
):
vscode
.
SourceControl
{
createSourceControl
(
extension
:
IExtensionDescription
,
id
:
string
,
label
:
string
,
rootUri
:
vscode
.
Uri
|
undefined
):
vscode
.
SourceControl
{
const
handle
=
ExtHostSCM
.
_handlePool
++
;
const
sourceControl
=
new
ExtHostSourceControl
(
this
.
_proxy
,
this
.
_commands
,
id
,
label
);
const
sourceControl
=
new
ExtHostSourceControl
(
this
.
_proxy
,
this
.
_commands
,
id
,
label
,
rootUri
);
this
.
_sourceControls
.
set
(
handle
,
sourceControl
);
const
sourceControls
=
this
.
_sourceControlsByExtension
.
get
(
extension
.
id
)
||
[];
...
...
src/vs/workbench/browser/parts/views/views.ts
浏览文件 @
7a9f0350
...
...
@@ -414,9 +414,14 @@ export class ViewsViewlet extends Viewlet {
}
}
private
toggleViewVisibility
(
id
:
string
):
void
{
toggleViewVisibility
(
id
:
string
,
visible
?:
boolean
):
void
{
const
view
=
this
.
getView
(
id
);
let
viewState
=
this
.
viewsStates
.
get
(
id
);
if
((
visible
===
true
&&
view
)
||
(
visible
===
false
&&
!
view
))
{
return
;
}
if
(
view
)
{
viewState
=
viewState
||
this
.
createViewState
(
view
);
viewState
.
isHidden
=
true
;
...
...
@@ -557,7 +562,7 @@ export class ViewsViewlet extends Viewlet {
private
canBeVisible
(
viewDescriptor
:
IViewDescriptor
):
boolean
{
const
viewstate
=
this
.
viewsStates
.
get
(
viewDescriptor
.
id
);
if
(
view
Descriptor
.
canToggleVisibility
&&
view
state
&&
viewstate
.
isHidden
)
{
if
(
viewstate
&&
viewstate
.
isHidden
)
{
return
false
;
}
return
this
.
contextKeyService
.
contextMatchesRules
(
viewDescriptor
.
when
);
...
...
src/vs/workbench/browser/parts/views/views2.ts
0 → 100644
浏览文件 @
7a9f0350
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
*
as
nls
from
'
vs/nls
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
Event
,
{
Emitter
}
from
'
vs/base/common/event
'
;
import
{
ColorIdentifier
,
contrastBorder
}
from
'
vs/platform/theme/common/colorRegistry
'
;
import
{
attachStyler
,
IColorMapping
,
IThemable
}
from
'
vs/platform/theme/common/styler
'
;
import
{
SIDE_BAR_DRAG_AND_DROP_BACKGROUND
,
SIDE_BAR_SECTION_HEADER_FOREGROUND
,
SIDE_BAR_SECTION_HEADER_BACKGROUND
}
from
'
vs/workbench/common/theme
'
;
import
{
Dimension
,
Builder
}
from
'
vs/base/browser/builder
'
;
import
{
append
,
$
}
from
'
vs/base/browser/dom
'
;
import
{
IDisposable
,
combinedDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
firstIndex
}
from
'
vs/base/common/arrays
'
;
import
{
IAction
,
IActionRunner
}
from
'
vs/base/common/actions
'
;
import
{
IActionItem
,
ActionsOrientation
}
from
'
vs/base/browser/ui/actionbar/actionbar
'
;
import
{
Registry
}
from
'
vs/platform/registry/common/platform
'
;
import
{
prepareActions
}
from
'
vs/workbench/browser/actions
'
;
import
{
Viewlet
,
ViewletRegistry
,
Extensions
}
from
'
vs/workbench/browser/viewlet
'
;
import
{
ToolBar
}
from
'
vs/base/browser/ui/toolbar/toolbar
'
;
import
{
IKeybindingService
}
from
'
vs/platform/keybinding/common/keybinding
'
;
import
{
IContextMenuService
}
from
'
vs/platform/contextview/browser/contextView
'
;
import
{
ITelemetryService
}
from
'
vs/platform/telemetry/common/telemetry
'
;
import
{
IThemeService
}
from
'
vs/platform/theme/common/themeService
'
;
import
{
PanelView
,
IPanelOptions
,
Panel
}
from
'
vs/base/browser/ui/splitview/panelview
'
;
export
interface
IPanelColors
extends
IColorMapping
{
dropBackground
?:
ColorIdentifier
;
headerForeground
?:
ColorIdentifier
;
headerBackground
?:
ColorIdentifier
;
headerHighContrastBorder
?:
ColorIdentifier
;
}
export
function
attachPanelStyler
(
widget
:
IThemable
,
themeService
:
IThemeService
)
{
return
attachStyler
<
IPanelColors
>
(
themeService
,
{
headerForeground
:
SIDE_BAR_SECTION_HEADER_FOREGROUND
,
headerBackground
:
SIDE_BAR_SECTION_HEADER_BACKGROUND
,
headerHighContrastBorder
:
contrastBorder
,
dropBackground
:
SIDE_BAR_DRAG_AND_DROP_BACKGROUND
},
widget
);
}
export
interface
IViewletPanelOptions
extends
IPanelOptions
{
actionRunner
?:
IActionRunner
;
}
export
abstract
class
ViewletPanel
extends
Panel
{
private
_onDidFocus
=
new
Emitter
<
void
>
();
readonly
onDidFocus
:
Event
<
void
>
=
this
.
_onDidFocus
.
event
;
private
actionRunner
:
IActionRunner
;
private
toolbar
:
ToolBar
;
constructor
(
readonly
title
:
string
,
options
:
IViewletPanelOptions
,
@
IKeybindingService
protected
keybindingService
:
IKeybindingService
,
@
IContextMenuService
protected
contextMenuService
:
IContextMenuService
)
{
super
(
options
);
this
.
actionRunner
=
options
.
actionRunner
;
}
protected
renderHeader
(
container
:
HTMLElement
):
void
{
this
.
renderHeaderTitle
(
container
);
const
actions
=
append
(
container
,
$
(
'
.actions
'
));
this
.
toolbar
=
new
ToolBar
(
actions
,
this
.
contextMenuService
,
{
orientation
:
ActionsOrientation
.
HORIZONTAL
,
actionItemProvider
:
action
=>
this
.
getActionItem
(
action
),
ariaLabel
:
nls
.
localize
(
'
viewToolbarAriaLabel
'
,
"
{0} actions
"
,
this
.
title
),
getKeyBinding
:
action
=>
this
.
keybindingService
.
lookupKeybinding
(
action
.
id
),
actionRunner
:
this
.
actionRunner
});
this
.
disposables
.
push
(
this
.
toolbar
);
this
.
updateActions
();
}
protected
renderHeaderTitle
(
container
:
HTMLElement
):
void
{
append
(
container
,
$
(
'
.title
'
,
null
,
this
.
title
));
}
focus
():
void
{
this
.
_onDidFocus
.
fire
();
}
protected
updateActions
():
void
{
this
.
toolbar
.
setActions
(
prepareActions
(
this
.
getActions
()),
prepareActions
(
this
.
getSecondaryActions
()))();
this
.
toolbar
.
context
=
this
.
getActionsContext
();
}
getActions
():
IAction
[]
{
return
[];
}
getSecondaryActions
():
IAction
[]
{
return
[];
}
getActionItem
(
action
:
IAction
):
IActionItem
{
return
null
;
}
getActionsContext
():
any
{
return
undefined
;
}
getOptimalWidth
():
number
{
return
0
;
}
}
export
interface
IViewsViewletOptions
{
showHeaderInTitleWhenSingleView
:
boolean
;
}
interface
IViewletPanelItem
{
panel
:
ViewletPanel
;
disposable
:
IDisposable
;
}
export
class
PanelViewlet
extends
Viewlet
{
protected
lastFocusedPanel
:
ViewletPanel
|
undefined
;
private
panelItems
:
IViewletPanelItem
[]
=
[];
private
panelview
:
PanelView
;
protected
get
isSingleView
():
boolean
{
return
this
.
options
.
showHeaderInTitleWhenSingleView
&&
this
.
panelItems
.
length
===
1
;
}
protected
get
length
():
number
{
return
this
.
panelItems
.
length
;
}
constructor
(
id
:
string
,
private
options
:
Partial
<
IViewsViewletOptions
>
,
@
ITelemetryService
telemetryService
:
ITelemetryService
,
@
IThemeService
themeService
:
IThemeService
)
{
super
(
id
,
telemetryService
,
themeService
);
}
async
create
(
parent
:
Builder
):
TPromise
<
void
>
{
super
.
create
(
parent
);
const
container
=
parent
.
getHTMLElement
();
this
.
panelview
=
this
.
_register
(
new
PanelView
(
container
));
}
getTitle
():
string
{
let
title
=
Registry
.
as
<
ViewletRegistry
>
(
Extensions
.
Viewlets
).
getViewlet
(
this
.
getId
()).
name
;
if
(
this
.
isSingleView
)
{
title
+=
'
:
'
+
this
.
panelItems
[
0
].
panel
.
title
;
}
return
title
;
}
getActions
():
IAction
[]
{
if
(
this
.
isSingleView
)
{
return
this
.
panelItems
[
0
].
panel
.
getActions
();
}
return
[];
}
getSecondaryActions
():
IAction
[]
{
if
(
this
.
isSingleView
)
{
return
this
.
panelItems
[
0
].
panel
.
getSecondaryActions
();
}
return
[];
}
focus
():
void
{
super
.
focus
();
if
(
this
.
lastFocusedPanel
)
{
this
.
lastFocusedPanel
.
focus
();
}
else
if
(
this
.
panelItems
.
length
>
0
)
{
this
.
panelItems
[
0
].
panel
.
focus
();
}
}
layout
(
dimension
:
Dimension
):
void
{
this
.
panelview
.
layout
(
dimension
.
height
);
}
getOptimalWidth
():
number
{
const
sizes
=
this
.
panelItems
.
map
(
panelItem
=>
panelItem
.
panel
.
getOptimalWidth
()
||
0
);
return
Math
.
max
(...
sizes
);
}
addPanel
(
panel
:
ViewletPanel
,
size
:
number
,
index
=
this
.
panelItems
.
length
-
1
):
void
{
const
disposables
:
IDisposable
[]
=
[];
const
onDidFocus
=
panel
.
onDidFocus
(()
=>
this
.
lastFocusedPanel
=
panel
,
null
,
disposables
);
const
styler
=
attachPanelStyler
(
panel
,
this
.
themeService
);
const
disposable
=
combinedDisposable
([
onDidFocus
,
styler
]);
const
panelItem
:
IViewletPanelItem
=
{
panel
,
disposable
};
this
.
panelItems
.
splice
(
index
,
0
,
panelItem
);
this
.
panelview
.
addPanel
(
panel
,
size
,
index
);
this
.
updateViewHeaders
();
this
.
updateTitleArea
();
}
removePanel
(
panel
:
ViewletPanel
):
void
{
const
index
=
firstIndex
(
this
.
panelItems
,
i
=>
i
.
panel
===
panel
);
if
(
index
===
-
1
)
{
return
;
}
if
(
this
.
lastFocusedPanel
===
panel
)
{
this
.
lastFocusedPanel
=
undefined
;
}
this
.
panelview
.
removePanel
(
panel
);
const
[
panelItem
]
=
this
.
panelItems
.
splice
(
index
,
1
);
panelItem
.
disposable
.
dispose
();
this
.
updateViewHeaders
();
this
.
updateTitleArea
();
}
movePanel
(
from
:
ViewletPanel
,
to
:
ViewletPanel
):
void
{
const
fromIndex
=
firstIndex
(
this
.
panelItems
,
item
=>
item
.
panel
===
from
);
const
toIndex
=
firstIndex
(
this
.
panelItems
,
item
=>
item
.
panel
===
to
);
if
(
fromIndex
<
0
||
fromIndex
>=
this
.
panelItems
.
length
)
{
return
;
}
if
(
toIndex
<
0
||
toIndex
>=
this
.
panelItems
.
length
)
{
return
;
}
const
[
panelItem
]
=
this
.
panelItems
.
splice
(
fromIndex
,
1
);
this
.
panelItems
.
splice
(
toIndex
<
fromIndex
?
toIndex
:
toIndex
-
1
,
0
,
panelItem
);
this
.
panelview
.
movePanel
(
from
,
to
);
}
resizePanel
(
panel
:
ViewletPanel
,
size
:
number
):
void
{
this
.
panelview
.
resizePanel
(
panel
,
size
);
}
private
updateViewHeaders
():
void
{
if
(
this
.
isSingleView
)
{
this
.
panelItems
[
0
].
panel
.
headerVisible
=
false
;
}
else
{
this
.
panelItems
.
forEach
(
i
=>
i
.
panel
.
headerVisible
=
true
);
}
}
dispose
():
void
{
super
.
dispose
();
this
.
panelItems
.
forEach
(
i
=>
i
.
disposable
.
dispose
());
this
.
panelview
.
dispose
();
}
}
\ No newline at end of file
src/vs/workbench/parts/scm/electron-browser/media/scmViewlet.css
浏览文件 @
7a9f0350
...
...
@@ -19,7 +19,7 @@
}
.scm-viewlet
:not
(
.empty
)
.empty-message
,
.scm-viewlet.empty
.monaco-
split-view
{
.scm-viewlet.empty
.monaco-
panel-view
{
display
:
none
;
}
...
...
@@ -27,6 +27,30 @@
height
:
100%
;
}
.scm-viewlet
.monaco-list-row
>
.scm-provider
{
display
:
flex
;
align-items
:
center
;
flex-wrap
:
wrap
;
}
.scm-viewlet
.monaco-list-row
>
.scm-provider
>
input
{
flex-shrink
:
0
;
}
.scm-viewlet
.scm-provider
>
.count
{
margin
:
0
0.5em
;
}
.scm-viewlet
.scm-provider
>
.count.hidden
{
display
:
none
;
}
.scm-viewlet
.scm-provider
>
.name
>
.type
{
opacity
:
0.7
;
margin-left
:
0.5em
;
font-size
:
0.9em
;
}
.scm-viewlet
.monaco-list-row
{
padding
:
0
12px
0
20px
;
line-height
:
22px
;
...
...
@@ -125,4 +149,8 @@
.scm-viewlet
.scm-editor.scroll
>
.monaco-inputbox
>
.wrapper
>
textarea
.input
{
overflow-y
:
scroll
;
}
.scm-viewlet
.spacer
{
flex
:
1
;
}
\ No newline at end of file
src/vs/workbench/parts/scm/electron-browser/scmActivity.ts
浏览文件 @
7a9f0350
...
...
@@ -6,6 +6,7 @@
'
use strict
'
;
import
{
localize
}
from
'
vs/nls
'
;
import
{
basename
}
from
'
vs/base/common/paths
'
;
import
{
IDisposable
,
dispose
,
empty
as
EmptyDisposable
,
combinedDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
filterEvent
,
any
as
anyEvent
}
from
'
vs/base/common/event
'
;
import
{
VIEWLET_ID
}
from
'
vs/workbench/parts/scm/common/scm
'
;
...
...
@@ -139,9 +140,13 @@ export class StatusBarController implements IWorkbenchContribution {
this
.
statusBarDisposable
.
dispose
();
const
commands
=
repository
.
provider
.
statusBarCommands
||
[];
const
label
=
repository
.
provider
.
rootUri
?
`
${
basename
(
repository
.
provider
.
rootUri
.
fsPath
)}
(
${
repository
.
provider
.
label
}
)`
:
repository
.
provider
.
label
;
const
disposables
=
commands
.
map
(
c
=>
this
.
statusbarService
.
addEntry
({
text
:
c
.
title
,
tooltip
:
`
${
repository
.
provider
.
label
}
-
${
c
.
tooltip
}
`
,
tooltip
:
`
${
label
}
-
${
c
.
tooltip
}
`
,
command
:
c
.
id
,
arguments
:
c
.
arguments
},
MainThreadStatusBarAlignment
.
LEFT
,
10000
));
...
...
src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts
浏览文件 @
7a9f0350
此差异已折叠。
点击以展开。
src/vs/workbench/services/scm/common/scm.ts
浏览文件 @
7a9f0350
...
...
@@ -60,6 +60,7 @@ export interface ISCMProvider extends IDisposable {
readonly
resources
:
ISCMResourceGroup
[];
readonly
onDidChangeResources
:
Event
<
void
>
;
readonly
rootUri
?:
URI
;
readonly
count
?:
number
;
readonly
commitTemplate
?:
string
;
readonly
onDidChangeCommitTemplate
?:
Event
<
string
>
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录