Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
7cd87957
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,发现更多精彩内容 >>
提交
7cd87957
编写于
3月 20, 2018
作者:
C
Christof Marti
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Input box and checkbox list (#45589)
上级
ea1e57b3
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
282 addition
and
82 deletion
+282
-82
src/vs/workbench/browser/parts/quickinput/quickInput.css
src/vs/workbench/browser/parts/quickinput/quickInput.css
+4
-0
src/vs/workbench/browser/parts/quickinput/quickInput.ts
src/vs/workbench/browser/parts/quickinput/quickInput.ts
+21
-82
src/vs/workbench/browser/parts/quickinput/quickInputBox.ts
src/vs/workbench/browser/parts/quickinput/quickInputBox.ts
+63
-0
src/vs/workbench/browser/parts/quickinput/quickInputCheckboxList.ts
...kbench/browser/parts/quickinput/quickInputCheckboxList.ts
+194
-0
未找到文件。
src/vs/workbench/browser/parts/quickinput/quickInput.css
浏览文件 @
7cd87957
...
...
@@ -12,6 +12,10 @@
margin-left
:
-300px
;
}
.quick-input-box
{
margin
:
6px
;
}
.quick-input-actions
{
padding
:
3px
;
}
...
...
src/vs/workbench/browser/parts/quickinput/quickInput.ts
浏览文件 @
7cd87957
...
...
@@ -10,10 +10,7 @@ import { Component } from 'vs/workbench/common/component';
import
{
IQuickInputService
}
from
'
vs/platform/quickInput/common/quickInput
'
;
import
{
IPartService
}
from
'
vs/workbench/services/part/common/partService
'
;
import
{
Dimension
}
from
'
vs/base/browser/builder
'
;
import
{
IDelegate
,
IRenderer
}
from
'
vs/base/browser/ui/list/list
'
;
import
*
as
dom
from
'
vs/base/browser/dom
'
;
import
{
dispose
,
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
WorkbenchList
}
from
'
vs/platform/list/browser/listService
'
;
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
registerThemingParticipant
,
ITheme
,
ICssStyleCollector
,
IThemeService
}
from
'
vs/platform/theme/common/themeService
'
;
import
{
buttonBackground
,
buttonForeground
,
contrastBorder
,
buttonHoverBackground
,
widgetShadow
}
from
'
vs/platform/theme/common/colorRegistry
'
;
...
...
@@ -21,70 +18,11 @@ import { SIDE_BAR_BACKGROUND, SIDE_BAR_FOREGROUND } from 'vs/workbench/common/th
import
{
IPickOpenEntry
,
IPickOptions
}
from
'
vs/platform/quickOpen/common/quickOpen
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
import
{
QuickInputCheckboxList
}
from
'
./quickInputCheckboxList
'
;
import
{
QuickInputBox
}
from
'
./quickInputBox
'
;
const
$
=
dom
.
$
;
export
interface
ISelectedElement
{
item
:
object
;
label
:
string
;
selected
:
boolean
;
}
interface
ISelectedElementTemplateData
{
element
:
HTMLElement
;
name
:
HTMLElement
;
checkbox
:
HTMLInputElement
;
context
:
ISelectedElement
;
toDispose
:
IDisposable
[];
}
class
SelectedElementRenderer
implements
IRenderer
<
ISelectedElement
,
ISelectedElementTemplateData
>
{
static
readonly
ID
=
'
selectedelement
'
;
get
templateId
()
{
return
SelectedElementRenderer
.
ID
;
}
renderTemplate
(
container
:
HTMLElement
):
ISelectedElementTemplateData
{
const
data
:
ISelectedElementTemplateData
=
Object
.
create
(
null
);
data
.
element
=
dom
.
append
(
container
,
$
(
'
.selected_element
'
));
data
.
checkbox
=
<
HTMLInputElement
>
$
(
'
input
'
);
data
.
checkbox
.
type
=
'
checkbox
'
;
data
.
toDispose
=
[];
data
.
toDispose
.
push
(
dom
.
addStandardDisposableListener
(
data
.
checkbox
,
'
change
'
,
(
e
)
=>
data
.
context
.
selected
=
!
data
.
context
.
selected
));
dom
.
append
(
data
.
element
,
data
.
checkbox
);
data
.
name
=
dom
.
append
(
data
.
element
,
$
(
'
span.label
'
));
return
data
;
}
renderElement
(
element
:
ISelectedElement
,
index
:
number
,
data
:
ISelectedElementTemplateData
):
void
{
data
.
context
=
element
;
data
.
name
.
textContent
=
element
.
label
;
data
.
element
.
title
=
data
.
name
.
textContent
;
data
.
checkbox
.
checked
=
element
.
selected
;
}
disposeTemplate
(
templateData
:
ISelectedElementTemplateData
):
void
{
dispose
(
templateData
.
toDispose
);
}
}
class
SelectedElementDelegate
implements
IDelegate
<
ISelectedElement
>
{
getHeight
(
element
:
ISelectedElement
):
number
{
return
22
;
}
getTemplateId
(
element
:
ISelectedElement
):
string
{
return
SelectedElementRenderer
.
ID
;
}
}
export
class
QuickInputService
extends
Component
implements
IQuickInputService
{
public
_serviceBrand
:
any
;
...
...
@@ -95,9 +33,9 @@ export class QuickInputService extends Component implements IQuickInputService {
private
layoutDimensions
:
Dimension
;
private
container
:
HTMLElement
;
private
list
:
WorkbenchList
<
ISelectedElement
>
;
private
inputBox
:
QuickInputBox
;
private
checkboxList
:
QuickInputCheckboxList
;
private
elements
:
ISelectedElement
[]
=
[];
private
resolve
:
(
value
?:
object
[]
|
Thenable
<
object
[]
>
)
=>
void
;
constructor
(
...
...
@@ -117,12 +55,13 @@ export class QuickInputService extends Component implements IQuickInputService {
this
.
container
=
dom
.
append
(
workbench
,
$
(
'
.quick-input-widget
'
));
this
.
container
.
style
.
display
=
'
none
'
;
const
listContainer
=
dom
.
append
(
this
.
container
,
$
(
'
.quick-input-list
'
));
const
delegate
=
new
SelectedElementDelegate
();
this
.
list
=
this
.
instantiationService
.
createInstance
(
WorkbenchList
,
listContainer
,
delegate
,
[
new
SelectedElementRenderer
()],
{
identityProvider
:
element
=>
element
.
label
,
multipleSelectionSupport
:
false
})
as
WorkbenchList
<
ISelectedElement
>
;
this
.
inputBox
=
new
QuickInputBox
(
this
.
container
);
this
.
inputBox
.
style
(
this
.
themeService
.
getTheme
());
this
.
inputBox
.
onInput
(
value
=>
{
this
.
checkboxList
.
filter
(
value
);
});
this
.
checkboxList
=
this
.
instantiationService
.
createInstance
(
QuickInputCheckboxList
,
this
.
container
);
const
buttonContainer
=
dom
.
append
(
this
.
container
,
$
(
'
.quick-input-actions
'
));
const
cancel
=
dom
.
append
(
buttonContainer
,
$
(
'
button
'
));
...
...
@@ -144,7 +83,7 @@ export class QuickInputService extends Component implements IQuickInputService {
private
close
(
ok
:
boolean
)
{
if
(
ok
)
{
this
.
resolve
(
this
.
elements
.
filter
(
e
=>
e
.
selected
).
map
(
e
=>
e
.
item
));
this
.
resolve
(
this
.
checkboxList
.
getSelectedElements
(
));
}
else
{
this
.
resolve
();
}
...
...
@@ -154,18 +93,13 @@ export class QuickInputService extends Component implements IQuickInputService {
async
pick
<
T
extends
IPickOpenEntry
>
(
picks
:
TPromise
<
T
[]
>
,
options
?:
IPickOptions
,
token
?:
CancellationToken
):
TPromise
<
T
[]
>
{
this
.
create
();
this
.
inputBox
.
setPlaceholder
(
options
.
placeHolder
||
''
);
// TODO: Progress indication.
this
.
elements
=
(
await
picks
).
map
(
item
=>
({
item
,
label
:
item
.
label
,
selected
:
!!
item
.
selected
}));
this
.
list
.
splice
(
0
,
this
.
list
.
length
,
this
.
elements
);
this
.
checkboxList
.
setElements
(
await
picks
);
this
.
container
.
style
.
display
=
null
;
this
.
updateLayout
();
this
.
list
.
focusFirst
();
this
.
list
.
domFocus
();
this
.
inputBox
.
setFocus
();
return
new
TPromise
<
T
[]
>
(
resolve
=>
this
.
resolve
=
resolve
);
}
...
...
@@ -185,9 +119,14 @@ export class QuickInputService extends Component implements IQuickInputService {
style
.
width
=
width
+
'
px
'
;
style
.
marginLeft
=
'
-
'
+
(
width
/
2
)
+
'
px
'
;
this
.
list
.
layout
();
this
.
inputBox
.
layout
();
this
.
checkboxList
.
layout
();
}
}
protected
updateStyles
()
{
this
.
inputBox
.
style
(
this
.
themeService
.
getTheme
());
}
}
registerThemingParticipant
((
theme
:
ITheme
,
collector
:
ICssStyleCollector
)
=>
{
...
...
src/vs/workbench/browser/parts/quickinput/quickInputBox.ts
0 → 100644
浏览文件 @
7cd87957
/*---------------------------------------------------------------------------------------------
* 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!./quickInput
'
;
import
*
as
dom
from
'
vs/base/browser/dom
'
;
import
{
InputBox
}
from
'
vs/base/browser/ui/inputbox/inputBox
'
;
import
*
as
nls
from
'
vs/nls
'
;
import
{
inputBackground
,
inputForeground
,
inputBorder
}
from
'
vs/platform/theme/common/colorRegistry
'
;
import
{
ITheme
}
from
'
vs/platform/theme/common/themeService
'
;
import
{
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
const
$
=
dom
.
$
;
const
DEFAULT_INPUT_ARIA_LABEL
=
nls
.
localize
(
'
quickInputBoxAriaLabel
'
,
"
Type to narrow down results.
"
);
export
class
QuickInputBox
{
public
container
:
HTMLElement
;
private
inputBox
:
InputBox
;
constructor
(
private
parent
:
HTMLElement
)
{
this
.
container
=
dom
.
append
(
this
.
parent
,
$
(
'
.quick-input-box
'
));
this
.
inputBox
=
new
InputBox
(
this
.
container
,
null
,
{
ariaLabel
:
DEFAULT_INPUT_ARIA_LABEL
});
// ARIA
const
inputElement
=
this
.
inputBox
.
inputElement
;
inputElement
.
setAttribute
(
'
role
'
,
'
combobox
'
);
inputElement
.
setAttribute
(
'
aria-haspopup
'
,
'
false
'
);
inputElement
.
setAttribute
(
'
aria-autocomplete
'
,
'
list
'
);
}
onInput
(
handler
:
(
event
:
string
)
=>
void
):
IDisposable
{
return
this
.
inputBox
.
onDidChange
(
handler
);
}
setPlaceholder
(
placeholder
:
string
)
{
this
.
inputBox
.
setPlaceHolder
(
placeholder
);
}
setFocus
():
void
{
this
.
inputBox
.
focus
();
}
layout
():
void
{
this
.
inputBox
.
layout
();
}
style
(
theme
:
ITheme
)
{
this
.
inputBox
.
style
({
inputForeground
:
theme
.
getColor
(
inputForeground
),
inputBackground
:
theme
.
getColor
(
inputBackground
),
inputBorder
:
theme
.
getColor
(
inputBorder
)
});
}
}
src/vs/workbench/browser/parts/quickinput/quickInputCheckboxList.ts
0 → 100644
浏览文件 @
7cd87957
/*---------------------------------------------------------------------------------------------
* 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!./quickInput
'
;
import
{
IDelegate
,
IRenderer
}
from
'
vs/base/browser/ui/list/list
'
;
import
*
as
dom
from
'
vs/base/browser/dom
'
;
import
{
dispose
,
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
WorkbenchList
}
from
'
vs/platform/list/browser/listService
'
;
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
IPickOpenEntry
}
from
'
vs/platform/quickOpen/common/quickOpen
'
;
import
{
IMatch
}
from
'
vs/base/common/filters
'
;
import
{
matchesFuzzyOcticonAware
,
parseOcticons
}
from
'
vs/base/common/octicon
'
;
import
{
compareAnything
}
from
'
vs/base/common/comparers
'
;
const
$
=
dom
.
$
;
export
interface
ISelectedElement
{
index
:
number
;
item
:
object
;
label
:
string
;
shouldAlwaysShow
?:
boolean
;
hidden
?:
boolean
;
selected
?:
boolean
;
labelHighlights
?:
IMatch
[];
descriptionHighlights
?:
IMatch
[];
detailHighlights
?:
IMatch
[];
}
interface
ISelectedElementTemplateData
{
element
:
HTMLElement
;
name
:
HTMLElement
;
checkbox
:
HTMLInputElement
;
context
:
ISelectedElement
;
toDispose
:
IDisposable
[];
}
class
SelectedElementRenderer
implements
IRenderer
<
ISelectedElement
,
ISelectedElementTemplateData
>
{
static
readonly
ID
=
'
selectedelement
'
;
get
templateId
()
{
return
SelectedElementRenderer
.
ID
;
}
renderTemplate
(
container
:
HTMLElement
):
ISelectedElementTemplateData
{
const
data
:
ISelectedElementTemplateData
=
Object
.
create
(
null
);
data
.
element
=
dom
.
append
(
container
,
$
(
'
.selected_element
'
));
data
.
checkbox
=
<
HTMLInputElement
>
$
(
'
input
'
);
data
.
checkbox
.
type
=
'
checkbox
'
;
data
.
toDispose
=
[];
data
.
toDispose
.
push
(
dom
.
addStandardDisposableListener
(
data
.
checkbox
,
'
change
'
,
(
e
)
=>
data
.
context
.
selected
=
!
data
.
context
.
selected
));
dom
.
append
(
data
.
element
,
data
.
checkbox
);
data
.
name
=
dom
.
append
(
data
.
element
,
$
(
'
span.label
'
));
return
data
;
}
renderElement
(
element
:
ISelectedElement
,
index
:
number
,
data
:
ISelectedElementTemplateData
):
void
{
data
.
context
=
element
;
data
.
name
.
textContent
=
element
.
label
;
data
.
element
.
title
=
data
.
name
.
textContent
;
data
.
checkbox
.
checked
=
element
.
selected
;
}
disposeTemplate
(
templateData
:
ISelectedElementTemplateData
):
void
{
dispose
(
templateData
.
toDispose
);
}
}
class
SelectedElementDelegate
implements
IDelegate
<
ISelectedElement
>
{
getHeight
(
element
:
ISelectedElement
):
number
{
return
22
;
}
getTemplateId
(
element
:
ISelectedElement
):
string
{
return
SelectedElementRenderer
.
ID
;
}
}
export
class
QuickInputCheckboxList
{
container
:
HTMLElement
;
private
list
:
WorkbenchList
<
ISelectedElement
>
;
private
elements
:
ISelectedElement
[]
=
[];
constructor
(
private
parent
:
HTMLElement
,
@
IInstantiationService
private
instantiationService
:
IInstantiationService
)
{
this
.
container
=
dom
.
append
(
this
.
parent
,
$
(
'
.quick-input-checkbox-list
'
));
const
delegate
=
new
SelectedElementDelegate
();
this
.
list
=
this
.
instantiationService
.
createInstance
(
WorkbenchList
,
this
.
container
,
delegate
,
[
new
SelectedElementRenderer
()],
{
identityProvider
:
element
=>
element
.
label
,
multipleSelectionSupport
:
false
})
as
WorkbenchList
<
ISelectedElement
>
;
}
setElements
(
elements
:
IPickOpenEntry
[]):
void
{
this
.
elements
=
elements
.
map
((
item
,
index
)
=>
({
index
,
item
,
label
:
item
.
label
,
selected
:
!!
item
.
selected
}));
this
.
list
.
splice
(
0
,
this
.
list
.
length
,
this
.
elements
);
}
getSelectedElements
()
{
return
this
.
elements
.
filter
(
e
=>
e
.
selected
)
.
map
(
e
=>
e
.
item
);
}
setFocus
():
void
{
this
.
list
.
focusFirst
();
this
.
list
.
domFocus
();
}
layout
():
void
{
this
.
list
.
layout
();
}
filter
(
query
:
string
)
{
query
=
query
.
trim
();
// Reset filtering
if
(
!
query
)
{
this
.
elements
.
forEach
(
element
=>
{
element
.
labelHighlights
=
undefined
;
element
.
descriptionHighlights
=
undefined
;
element
.
detailHighlights
=
undefined
;
element
.
hidden
=
false
;
});
}
// Filter by value (since we support octicons, use octicon aware fuzzy matching)
else
{
this
.
elements
.
forEach
(
element
=>
{
const
labelHighlights
=
matchesFuzzyOcticonAware
(
query
,
parseOcticons
(
element
.
label
));
const
descriptionHighlights
=
undefined
;
// TODO matchesFuzzyOcticonAware(query, parseOcticons(element.description));
const
detailHighlights
=
undefined
;
// TODO matchesFuzzyOcticonAware(query, parseOcticons(element.detail));
if
(
element
.
shouldAlwaysShow
||
labelHighlights
||
descriptionHighlights
||
detailHighlights
)
{
element
.
labelHighlights
=
labelHighlights
;
element
.
descriptionHighlights
=
descriptionHighlights
;
element
.
detailHighlights
=
detailHighlights
;
element
.
hidden
=
false
;
}
else
{
element
.
labelHighlights
=
undefined
;
element
.
descriptionHighlights
=
undefined
;
element
.
detailHighlights
=
undefined
;
element
.
hidden
=
true
;
}
});
}
// Sort by value
const
normalizedSearchValue
=
query
.
toLowerCase
();
this
.
elements
.
sort
((
a
,
b
)
=>
{
if
(
!
query
)
{
return
a
.
index
-
b
.
index
;
// restore natural order
}
return
compareEntries
(
a
,
b
,
normalizedSearchValue
);
});
this
.
list
.
splice
(
0
,
this
.
list
.
length
,
this
.
elements
.
filter
(
element
=>
!
element
.
hidden
));
this
.
list
.
layout
();
if
(
query
)
{
this
.
list
.
focusFirst
();
}
}
}
function
compareEntries
(
elementA
:
ISelectedElement
,
elementB
:
ISelectedElement
,
lookFor
:
string
):
number
{
const
labelHighlightsA
=
elementA
.
labelHighlights
||
[];
const
labelHighlightsB
=
elementB
.
labelHighlights
||
[];
if
(
labelHighlightsA
.
length
&&
!
labelHighlightsB
.
length
)
{
return
-
1
;
}
if
(
!
labelHighlightsA
.
length
&&
labelHighlightsB
.
length
)
{
return
1
;
}
return
compareAnything
(
elementA
.
label
,
elementB
.
label
,
lookFor
);
}
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录