Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
徽霖
Vscode
提交
2b2cdae1
V
Vscode
项目概览
徽霖
/
Vscode
通知
9
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
Vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
2b2cdae1
编写于
1月 09, 2019
作者:
J
Joao Moreno
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
list: drag and drop almost working
上级
e87692c6
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
330 addition
and
181 deletion
+330
-181
src/vs/base/browser/ui/list/list.ts
src/vs/base/browser/ui/list/list.ts
+5
-5
src/vs/base/browser/ui/list/listView.ts
src/vs/base/browser/ui/list/listView.ts
+267
-25
src/vs/base/browser/ui/list/listWidget.ts
src/vs/base/browser/ui/list/listWidget.ts
+42
-140
src/vs/base/browser/ui/tree/abstractTree.ts
src/vs/base/browser/ui/tree/abstractTree.ts
+3
-3
src/vs/base/browser/ui/tree/asyncDataTree.ts
src/vs/base/browser/ui/tree/asyncDataTree.ts
+3
-3
src/vs/platform/list/browser/listService.ts
src/vs/platform/list/browser/listService.ts
+6
-4
src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts
src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts
+4
-1
未找到文件。
src/vs/base/browser/ui/list/list.ts
浏览文件 @
2b2cdae1
...
...
@@ -7,7 +7,6 @@ import { GestureEvent } from 'vs/base/browser/touch';
import
{
IKeyboardEvent
}
from
'
vs/base/browser/keyboardEvent
'
;
import
{
Event
}
from
'
vs/base/common/event
'
;
import
{
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
DragMouseEvent
}
from
'
vs/base/browser/mouseEvent
'
;
export
interface
IListVirtualDelegate
<
T
>
{
getHeight
(
element
:
T
):
number
;
...
...
@@ -82,6 +81,7 @@ export const enum DragOverEffect {
export
interface
IDragOverReaction
{
accept
:
boolean
;
effect
?:
DragOverEffect
;
feedback
?:
number
[];
// use -1 for entire list
// bubble?: DragOverBubble;
// autoExpand?: boolean;
}
...
...
@@ -96,16 +96,16 @@ export const DragOverReactions = {
};
export
interface
IDragAndDropData
{
update
(
event
:
DragMouseEvent
):
void
;
update
(
dataTransfer
:
DataTransfer
):
void
;
getData
():
any
;
}
export
interface
IDragAndDrop
<
T
>
{
getDragURI
(
element
:
T
):
string
|
null
;
getDragLabel
?(
elements
:
T
[]):
string
;
onDragStart
(
data
:
IDragAndDropData
,
originalEvent
:
Drag
Mouse
Event
):
void
;
onDragOver
(
data
:
IDragAndDropData
,
targetElement
:
T
,
originalEvent
:
DragMouse
Event
):
boolean
|
IDragOverReaction
;
drop
(
data
:
IDragAndDropData
,
targetElement
:
T
,
originalEvent
:
DragMouse
Event
):
void
;
onDragStart
(
data
:
IDragAndDropData
,
originalEvent
:
DragEvent
):
void
;
onDragOver
(
data
:
IDragAndDropData
,
targetElement
:
T
|
undefined
,
targetIndex
:
number
|
undefined
,
originalEvent
:
Drag
Event
):
boolean
|
IDragOverReaction
;
drop
(
data
:
IDragAndDropData
,
targetElement
:
T
|
undefined
,
originalEvent
:
Drag
Event
):
void
;
}
/**
...
...
src/vs/base/browser/ui/list/listView.ts
浏览文件 @
2b2cdae1
...
...
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import
{
getOrDefault
}
from
'
vs/base/common/objects
'
;
import
{
IDisposable
,
dispose
,
Disposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
IDisposable
,
dispose
,
Disposable
,
toDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
Gesture
,
EventType
as
TouchEventType
,
GestureEvent
}
from
'
vs/base/browser/touch
'
;
import
*
as
DOM
from
'
vs/base/browser/dom
'
;
import
{
Event
,
Emitter
}
from
'
vs/base/common/event
'
;
...
...
@@ -12,14 +12,15 @@ import { domEvent } from 'vs/base/browser/event';
import
{
ScrollableElement
}
from
'
vs/base/browser/ui/scrollbar/scrollableElement
'
;
import
{
ScrollEvent
,
ScrollbarVisibility
,
INewScrollDimensions
}
from
'
vs/base/common/scrollable
'
;
import
{
RangeMap
,
shift
}
from
'
./rangeMap
'
;
import
{
IListVirtualDelegate
,
IListRenderer
,
IListMouseEvent
,
IListTouchEvent
,
IListGestureEvent
,
I
DragAndDrop
,
IListDragEvent
}
from
'
./list
'
;
import
{
IListVirtualDelegate
,
IListRenderer
,
IListMouseEvent
,
IListTouchEvent
,
IListGestureEvent
,
I
ListDragEvent
,
IDragAndDrop
,
IDragAndDropData
}
from
'
./list
'
;
import
{
RowCache
,
IRow
}
from
'
./rowCache
'
;
import
{
isWindows
}
from
'
vs/base/common/platform
'
;
import
*
as
browser
from
'
vs/base/browser/browser
'
;
import
{
ISpliceable
}
from
'
vs/base/common/sequence
'
;
import
{
memoize
}
from
'
vs/base/common/decorators
'
;
import
{
DragMouseEvent
}
from
'
vs/base/browser/mouseEvent
'
;
import
{
Range
,
IRange
}
from
'
vs/base/common/range
'
;
import
{
equals
,
distinct
}
from
'
vs/base/common/arrays
'
;
import
{
DataTransfers
}
from
'
vs/base/browser/dnd
'
;
function
canUseTranslate3d
():
boolean
{
if
(
browser
.
isFirefox
)
{
...
...
@@ -42,11 +43,16 @@ interface IItem<T> {
hasDynamicHeight
:
boolean
;
renderWidth
:
number
|
undefined
;
uri
:
string
|
undefined
;
dropTarget
:
boolean
;
dragStartDisposable
:
IDisposable
;
}
export
interface
IListViewDragAndDrop
<
T
>
extends
IDragAndDrop
<
T
>
{
getDragElements
(
element
:
T
):
T
[];
}
export
interface
IListViewOptions
<
T
>
{
readonly
dnd
?:
IDragAndDrop
<
T
>
;
readonly
dnd
?:
I
ListView
DragAndDrop
<
T
>
;
readonly
useShadows
?:
boolean
;
readonly
verticalScrollMode
?:
ScrollbarVisibility
;
readonly
setRowLineHeight
?:
boolean
;
...
...
@@ -60,6 +66,7 @@ const DefaultOptions = {
setRowLineHeight
:
true
,
supportDynamicHeights
:
false
,
dnd
:
{
getDragElements
(
e
)
{
return
[
e
];
},
getDragURI
()
{
return
null
;
},
onDragStart
():
void
{
},
onDragOver
()
{
return
false
;
},
...
...
@@ -67,8 +74,88 @@ const DefaultOptions = {
}
};
export
class
ElementsDragAndDropData
<
T
>
implements
IDragAndDropData
{
private
elements
:
T
[];
constructor
(
elements
:
T
[])
{
this
.
elements
=
elements
;
}
public
update
(
dataTransfer
:
DataTransfer
):
void
{
// no-op
}
public
getData
():
any
{
return
this
.
elements
;
}
}
export
class
ExternalElementsDragAndDropData
<
T
>
implements
IDragAndDropData
{
private
elements
:
T
[];
constructor
(
elements
:
T
[])
{
this
.
elements
=
elements
;
}
public
update
(
dataTransfer
:
DataTransfer
):
void
{
// no-op
}
public
getData
():
any
{
return
this
.
elements
;
}
}
export
class
DesktopDragAndDropData
implements
IDragAndDropData
{
private
types
:
any
[];
private
files
:
any
[];
constructor
()
{
this
.
types
=
[];
this
.
files
=
[];
}
public
update
(
dataTransfer
:
DataTransfer
):
void
{
if
(
dataTransfer
.
types
)
{
this
.
types
=
[...
dataTransfer
.
types
];
}
if
(
dataTransfer
.
files
)
{
this
.
files
=
[];
for
(
let
i
=
0
;
i
<
dataTransfer
.
files
.
length
;
i
++
)
{
const
file
=
dataTransfer
.
files
.
item
(
i
);
if
(
file
&&
(
file
.
size
||
file
.
type
))
{
this
.
files
.
push
(
file
);
}
}
}
}
public
getData
():
any
{
return
{
types
:
this
.
types
,
files
:
this
.
files
};
}
}
function
equalsDragFeedback
(
f1
:
number
[]
|
undefined
,
f2
:
number
[]
|
undefined
):
boolean
{
if
(
Array
.
isArray
(
f1
)
&&
Array
.
isArray
(
f2
))
{
return
equals
(
f1
,
f2
!
);
}
return
f1
===
f2
;
}
export
class
ListView
<
T
>
implements
ISpliceable
<
T
>
,
IDisposable
{
private
static
currentExternalDragAndDropData
:
IDragAndDropData
|
undefined
;
readonly
domNode
:
HTMLElement
;
private
items
:
IItem
<
T
>
[];
...
...
@@ -90,18 +177,26 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
private
dragOverMouseY
:
number
;
private
setRowLineHeight
:
boolean
;
private
supportDynamicHeights
:
boolean
;
private
readonly
dnd
:
IDragAndDrop
<
T
>
;
private
dnd
:
IListViewDragAndDrop
<
T
>
;
private
currentDragData
:
IDragAndDropData
|
undefined
;
private
currentDragFeedback
:
number
[]
|
undefined
;
private
currentDragFeedbackDisposable
:
IDisposable
=
Disposable
.
None
;
private
onDragLeaveTimeout
:
IDisposable
=
Disposable
.
None
;
private
disposables
:
IDisposable
[];
private
_onDidChangeContentHeight
=
new
Emitter
<
number
>
();
readonly
onDidChangeContentHeight
:
Event
<
number
>
=
Event
.
latch
(
this
.
_onDidChangeContentHeight
.
event
);
get
contentHeight
():
number
{
return
this
.
rangeMap
.
size
;
}
private
_onDragStart
=
new
Emitter
<
{
element
:
T
,
uri
:
string
,
event
:
DragMouse
Event
}
>
();
readonly
onDragStart
=
this
.
_onDragStart
.
event
;
// private _onDragStart = new Emitter<{ element: T, uri: string, event: Drag
Event }>();
//
readonly onDragStart = this._onDragStart.event;
readonly
onDragOver
:
Event
<
IListDragEvent
<
T
>>
;
readonly
onDragLeave
:
Event
<
void
>
;
// readonly onDragOver: Event<IListDragEvent<T>>;
// readonly onDragLeave: Event<void>;
// readonly onDrop: Event<IListDragEvent<T>>;
// readonly onDragEnd: Event<void>;
constructor
(
container
:
HTMLElement
,
...
...
@@ -150,18 +245,14 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
domEvent
(
this
.
scrollableElement
.
getDomNode
(),
'
scroll
'
)
(
e
=>
(
e
.
target
as
HTMLElement
).
scrollTop
=
0
,
null
,
this
.
disposables
);
const
onDragOver
=
Event
.
map
(
domEvent
(
this
.
domNode
,
'
dragover
'
),
e
=>
new
DragMouseEvent
(
e
));
onDragOver
(
this
.
onDidDragOver
,
this
,
this
.
disposables
);
this
.
onDragOver
=
Event
.
map
(
domEvent
(
this
.
domNode
,
'
dragover
'
),
e
=>
this
.
toDragEvent
(
e
));
this
.
onDragLeave
=
Event
.
signal
(
domEvent
(
this
.
domNode
,
'
dragleave
'
));
const
onDragEnd
=
Event
.
map
(
domEvent
(
document
,
'
dragend
'
),
e
=>
new
DragMouseEvent
(
e
));
onDragEnd
(
this
.
_onDragEnd
,
this
,
this
.
disposables
);
Event
.
map
(
domEvent
(
this
.
domNode
,
'
dragover
'
),
e
=>
this
.
toDragEvent
(
e
))(
this
.
onDragOver
,
this
,
this
.
disposables
);
Event
.
map
(
domEvent
(
this
.
domNode
,
'
drop
'
),
e
=>
this
.
toDragEvent
(
e
))(
this
.
onDrop
,
this
,
this
.
disposables
);
domEvent
(
this
.
domNode
,
'
dragleave
'
)(
this
.
onDragLeave
,
this
,
this
.
disposables
);
domEvent
(
window
,
'
dragend
'
)(
this
.
onDragEnd
,
this
,
this
.
disposables
);
this
.
setRowLineHeight
=
getOrDefault
(
options
,
o
=>
o
.
setRowLineHeight
,
DefaultOptions
.
setRowLineHeight
);
this
.
supportDynamicHeights
=
getOrDefault
(
options
,
o
=>
o
.
supportDynamicHeights
,
DefaultOptions
.
supportDynamicHeights
);
this
.
dnd
=
getOrDefault
<
IListViewOptions
<
T
>
,
IDragAndDrop
<
T
>>
(
options
,
o
=>
o
.
dnd
,
DefaultOptions
.
dnd
);
this
.
dnd
=
getOrDefault
<
IListViewOptions
<
T
>
,
I
ListView
DragAndDrop
<
T
>>
(
options
,
o
=>
o
.
dnd
,
DefaultOptions
.
dnd
);
this
.
layout
();
}
...
...
@@ -203,6 +294,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
renderWidth
:
undefined
,
row
:
null
,
uri
:
undefined
,
dropTarget
:
false
,
dragStartDisposable
:
Disposable
.
None
}));
...
...
@@ -385,8 +477,8 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
if
(
uri
)
{
item
.
row
.
domNode
!
.
draggable
=
true
;
const
onDragStart
=
Event
.
map
(
domEvent
(
item
.
row
.
domNode
!
,
'
dragstart
'
),
e
=>
new
DragMouseEvent
(
e
)
);
item
.
dragStartDisposable
=
onDragStart
(
event
=>
this
.
_onDragStart
.
fire
({
element
:
item
.
element
,
uri
,
event
}),
this
);
const
onDragStart
=
domEvent
(
item
.
row
.
domNode
!
,
'
dragstart
'
);
item
.
dragStartDisposable
=
onDragStart
(
event
=>
this
.
onDragStart
(
item
.
element
,
uri
,
event
)
);
}
}
...
...
@@ -402,6 +494,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
item
.
row
!
.
domNode
!
.
setAttribute
(
'
data-last-element
'
,
index
===
this
.
length
-
1
?
'
true
'
:
'
false
'
);
item
.
row
!
.
domNode
!
.
setAttribute
(
'
aria-setsize
'
,
`
${
this
.
length
}
`
);
item
.
row
!
.
domNode
!
.
setAttribute
(
'
aria-posinset
'
,
`
${
index
+
1
}
`
);
DOM
.
toggleClass
(
item
.
row
!
.
domNode
!
,
'
drop-target
'
,
item
.
dropTarget
);
}
private
removeItemFromDOM
(
index
:
number
):
void
{
...
...
@@ -509,7 +602,154 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
// DND
private
onDidDragOver
(
event
:
DragMouseEvent
):
void
{
private
onDragStart
(
element
:
T
,
uri
:
string
,
event
:
DragEvent
):
void
{
if
(
!
event
.
dataTransfer
)
{
return
;
}
const
elements
=
this
.
dnd
.
getDragElements
(
element
);
event
.
dataTransfer
.
effectAllowed
=
'
copyMove
'
;
event
.
dataTransfer
.
setData
(
DataTransfers
.
RESOURCES
,
JSON
.
stringify
([
uri
]));
if
(
event
.
dataTransfer
.
setDragImage
)
{
let
label
:
string
;
if
(
this
.
dnd
.
getDragLabel
)
{
label
=
this
.
dnd
.
getDragLabel
(
elements
);
}
else
{
label
=
String
(
elements
.
length
);
}
const
dragImage
=
DOM
.
$
(
'
.monaco-list-drag-image
'
);
dragImage
.
textContent
=
label
;
document
.
body
.
appendChild
(
dragImage
);
event
.
dataTransfer
.
setDragImage
(
dragImage
,
-
10
,
-
10
);
setTimeout
(()
=>
document
.
body
.
removeChild
(
dragImage
),
0
);
}
this
.
currentDragData
=
new
ElementsDragAndDropData
(
elements
);
ListView
.
currentExternalDragAndDropData
=
new
ExternalElementsDragAndDropData
(
elements
);
this
.
dnd
.
onDragStart
(
this
.
currentDragData
,
event
);
}
private
onDragOver
(
event
:
IListDragEvent
<
T
>
):
boolean
{
console
.
log
(
'
DRAG OVER
'
);
this
.
onDragLeaveTimeout
.
dispose
();
this
.
setupDragAndDropScrollTopAnimation
(
event
.
browserEvent
);
if
(
!
event
.
browserEvent
.
dataTransfer
)
{
return
false
;
}
// Drag over from outside
if
(
!
this
.
currentDragData
)
{
if
(
ListView
.
currentExternalDragAndDropData
)
{
// Drag over from another list
this
.
currentDragData
=
ListView
.
currentExternalDragAndDropData
;
}
else
{
// Drag over from the desktop
if
(
!
event
.
browserEvent
.
dataTransfer
.
types
)
{
return
false
;
}
this
.
currentDragData
=
new
DesktopDragAndDropData
();
}
}
const
result
=
this
.
dnd
.
onDragOver
(
this
.
currentDragData
,
event
.
element
,
event
.
index
,
event
.
browserEvent
);
const
canDrop
=
typeof
result
===
'
boolean
'
?
result
:
result
.
accept
;
// const reaction = (typeof result !== 'boolean' && result.effect === DragOverEffect.Copy) ? 'copy' : 'move';
if
(
!
canDrop
)
{
return
false
;
}
let
feedback
:
number
[];
if
(
typeof
result
!==
'
boolean
'
&&
result
.
feedback
)
{
feedback
=
result
.
feedback
;
}
else
{
if
(
typeof
event
.
index
===
'
undefined
'
)
{
feedback
=
[
-
1
];
}
else
{
feedback
=
[
event
.
index
];
}
}
// sanitize feedback list
feedback
=
distinct
(
feedback
).
filter
(
i
=>
i
>=
-
1
&&
i
<
this
.
length
).
sort
();
feedback
=
feedback
[
0
]
===
-
1
?
[
-
1
]
:
feedback
;
if
(
feedback
.
length
===
0
)
{
throw
new
Error
(
'
Invalid empty feedback list
'
);
}
if
(
equalsDragFeedback
(
this
.
currentDragFeedback
,
feedback
))
{
return
true
;
}
console
.
log
(
this
.
currentDragFeedback
,
feedback
);
this
.
currentDragFeedback
=
feedback
;
this
.
currentDragFeedbackDisposable
.
dispose
();
if
(
feedback
[
0
]
===
-
1
)
{
// entire list feedback
DOM
.
addClass
(
this
.
domNode
,
'
drop-target
'
);
this
.
currentDragFeedbackDisposable
=
toDisposable
(()
=>
DOM
.
removeClass
(
this
.
domNode
,
'
drop-target
'
));
}
else
{
for
(
const
index
of
feedback
)
{
const
item
=
this
.
items
[
index
]
!
;
item
.
dropTarget
=
true
;
if
(
item
.
row
&&
item
.
row
.
domNode
)
{
DOM
.
addClass
(
item
.
row
.
domNode
,
'
drop-target
'
);
}
}
this
.
currentDragFeedbackDisposable
=
toDisposable
(()
=>
{
for
(
const
index
of
feedback
)
{
const
item
=
this
.
items
[
index
]
!
;
item
.
dropTarget
=
false
;
if
(
item
.
row
&&
item
.
row
.
domNode
)
{
DOM
.
removeClass
(
item
.
row
.
domNode
,
'
drop-target
'
);
}
}
});
}
return
true
;
}
private
onDragLeave
(
event
:
DragEvent
):
void
{
console
.
log
(
'
LEAVE
'
);
this
.
onDragLeaveTimeout
=
DOM
.
timeout
(()
=>
this
.
clearDragOverFeedback
(),
100
);
}
private
onDrop
(
e
:
IListDragEvent
<
T
>
):
void
{
console
.
log
(
'
DROP
'
);
this
.
teardownDragAndDropScrollTopAnimation
();
this
.
clearDragOverFeedback
();
}
private
onDragEnd
():
void
{
console
.
log
(
'
DRAG END
'
);
this
.
teardownDragAndDropScrollTopAnimation
();
this
.
clearDragOverFeedback
();
}
private
clearDragOverFeedback
():
void
{
this
.
currentDragFeedback
=
undefined
;
this
.
currentDragFeedbackDisposable
.
dispose
();
}
// DND scroll top animation
private
setupDragAndDropScrollTopAnimation
(
event
:
DragEvent
):
void
{
if
(
!
this
.
dragOverAnimationDisposable
)
{
const
viewTop
=
DOM
.
getTopLeftOffset
(
this
.
domNode
).
top
;
this
.
dragOverAnimationDisposable
=
DOM
.
animate
(
this
.
animateDragAndDropScrollTop
.
bind
(
this
,
viewTop
));
...
...
@@ -517,11 +757,13 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
this
.
dragOverAnimationStopDisposable
.
dispose
();
this
.
dragOverAnimationStopDisposable
=
DOM
.
timeout
(()
=>
{
this
.
dragOverAnimationDisposable
.
dispose
();
this
.
dragOverAnimationDisposable
=
undefined
;
if
(
this
.
dragOverAnimationDisposable
)
{
this
.
dragOverAnimationDisposable
.
dispose
();
this
.
dragOverAnimationDisposable
=
undefined
;
}
},
1000
);
this
.
dragOverMouseY
=
event
.
p
osy
;
this
.
dragOverMouseY
=
event
.
p
ageY
;
}
private
animateDragAndDropScrollTop
(
viewTop
:
number
):
void
{
...
...
@@ -539,7 +781,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
}
}
private
_onDragEnd
():
void
{
private
teardownDragAndDropScrollTopAnimation
():
void
{
this
.
dragOverAnimationStopDisposable
.
dispose
();
if
(
this
.
dragOverAnimationDisposable
)
{
...
...
src/vs/base/browser/ui/list/listWidget.ts
浏览文件 @
2b2cdae1
...
...
@@ -16,17 +16,15 @@ import { KeyCode } from 'vs/base/common/keyCodes';
import
{
StandardKeyboardEvent
,
IKeyboardEvent
}
from
'
vs/base/browser/keyboardEvent
'
;
import
{
Event
,
Emitter
,
EventBufferer
}
from
'
vs/base/common/event
'
;
import
{
domEvent
}
from
'
vs/base/browser/event
'
;
import
{
IListVirtualDelegate
,
IListRenderer
,
IListEvent
,
IListContextMenuEvent
,
IListMouseEvent
,
IListTouchEvent
,
IListGestureEvent
,
IIdentityProvider
,
IKeyboardNavigationLabelProvider
,
IDragAndDrop
,
IDragAndDropData
,
IListDragEvent
}
from
'
./list
'
;
import
{
IListVirtualDelegate
,
IListRenderer
,
IListEvent
,
IListContextMenuEvent
,
IListMouseEvent
,
IListTouchEvent
,
IListGestureEvent
,
IIdentityProvider
,
IKeyboardNavigationLabelProvider
,
IDragAndDrop
}
from
'
./list
'
;
import
{
ListView
,
IListViewOptions
}
from
'
./listView
'
;
import
{
Color
}
from
'
vs/base/common/color
'
;
import
{
mixin
,
getOrDefault
}
from
'
vs/base/common/objects
'
;
import
{
mixin
}
from
'
vs/base/common/objects
'
;
import
{
ScrollbarVisibility
}
from
'
vs/base/common/scrollable
'
;
import
{
ISpliceable
}
from
'
vs/base/common/sequence
'
;
import
{
CombinedSpliceable
}
from
'
vs/base/browser/ui/list/splice
'
;
import
{
clamp
}
from
'
vs/base/common/numbers
'
;
import
{
matchesPrefix
}
from
'
vs/base/common/filters
'
;
import
{
DragMouseEvent
}
from
'
vs/base/browser/mouseEvent
'
;
import
{
DataTransfers
}
from
'
vs/base/browser/dnd
'
;
interface
ITraitChangeEvent
{
indexes
:
number
[];
...
...
@@ -214,7 +212,7 @@ class TraitSpliceable<T> implements ISpliceable<T> {
splice
(
start
:
number
,
deleteCount
:
number
,
elements
:
T
[]):
void
{
if
(
!
this
.
identityProvider
)
{
return
this
.
trait
.
splice
(
start
,
deleteCount
,
elements
.
map
(
e
=>
false
));
return
this
.
trait
.
splice
(
start
,
deleteCount
,
elements
.
map
(
()
=>
false
));
}
const
pastElementsWithTrait
=
this
.
trait
.
get
().
map
(
i
=>
this
.
identityProvider
!
.
getId
(
this
.
view
.
element
(
i
)).
toString
());
...
...
@@ -714,13 +712,12 @@ export class DefaultStyleController implements IStyleController {
content
.
push
(
`.monaco-list
${
suffix
}
.monaco-list-row:hover { outline: 1px dashed
${
styles
.
listHoverOutline
}
; outline-offset: -1px; }`
);
}
// TODO
// if (styles.listDropBackground) {
// content.push(`
// .monaco-tree${suffix} .monaco-tree-wrapper.drop-target,
// .monaco-tree${suffix} .monaco-tree-rows > .monaco-tree-row.drop-target { background-color: ${styles.listDropBackground} !important; color: inherit !important; }
// `);
// }
if
(
styles
.
listDropBackground
)
{
content
.
push
(
`
.monaco-list
${
suffix
}
.drop-target,
.monaco-list
${
suffix
}
.monaco-list-row.drop-target { background-color:
${
styles
.
listDropBackground
}
!important; color: inherit !important; }
`
);
}
const
newStyles
=
content
.
join
(
'
\n
'
);
if
(
newStyles
!==
this
.
styleElement
.
innerHTML
)
{
...
...
@@ -729,19 +726,24 @@ export class DefaultStyleController implements IStyleController {
}
}
export
interface
IListOptions
<
T
>
extends
IListViewOptions
<
T
>
,
IListStyles
{
identityProvider
?:
IIdentityProvider
<
T
>
;
dnd
?:
IDragAndDrop
<
T
>
;
keyboardNavigationLabelProvider
?:
IKeyboardNavigationLabelProvider
<
T
>
;
ariaLabel
?:
string
;
mouseSupport
?:
boolean
;
keyboardSupport
?:
boolean
;
verticalScrollMode
?:
ScrollbarVisibility
;
multipleSelectionSupport
?:
boolean
;
multipleSelectionController
?:
IMultipleSelectionController
<
T
>
;
openController
?:
IOpenController
;
styleController
?:
IStyleController
;
accessibilityProvider
?:
IAccessibilityProvider
<
T
>
;
export
interface
IListOptions
<
T
>
extends
IListStyles
{
readonly
identityProvider
?:
IIdentityProvider
<
T
>
;
readonly
dnd
?:
IDragAndDrop
<
T
>
;
readonly
keyboardNavigationLabelProvider
?:
IKeyboardNavigationLabelProvider
<
T
>
;
readonly
ariaLabel
?:
string
;
readonly
keyboardSupport
?:
boolean
;
readonly
multipleSelectionSupport
?:
boolean
;
readonly
multipleSelectionController
?:
IMultipleSelectionController
<
T
>
;
readonly
openController
?:
IOpenController
;
readonly
styleController
?:
IStyleController
;
readonly
accessibilityProvider
?:
IAccessibilityProvider
<
T
>
;
// list view options
readonly
useShadows
?:
boolean
;
readonly
verticalScrollMode
?:
ScrollbarVisibility
;
readonly
setRowLineHeight
?:
boolean
;
readonly
supportDynamicHeights
?:
boolean
;
readonly
mouseSupport
?:
boolean
;
}
export
interface
IListStyles
{
...
...
@@ -774,7 +776,7 @@ const defaultStyles: IListStyles = {
listDropBackground
:
Color
.
fromHex
(
'
#383B3D
'
)
};
const
DefaultOptions
:
IListOptions
<
any
>
=
{
const
DefaultOptions
=
{
keyboardSupport
:
true
,
mouseSupport
:
true
,
multipleSelectionSupport
:
true
,
...
...
@@ -938,73 +940,8 @@ class AccessibiltyRenderer<T> implements IListRenderer<T, HTMLElement> {
}
}
export
class
ElementsDragAndDropData
<
T
>
implements
IDragAndDropData
{
private
elements
:
T
[];
constructor
(
elements
:
T
[])
{
this
.
elements
=
elements
;
}
public
update
(
event
:
DragMouseEvent
):
void
{
// no-op
}
public
getData
():
any
{
return
this
.
elements
;
}
}
export
class
ExternalElementsDragAndDropData
<
T
>
implements
IDragAndDropData
{
private
elements
:
T
[];
constructor
(
elements
:
T
[])
{
this
.
elements
=
elements
;
}
public
update
(
event
:
DragMouseEvent
):
void
{
// no-op
}
public
getData
():
any
{
return
this
.
elements
;
}
}
export
class
DesktopDragAndDropData
implements
IDragAndDropData
{
private
types
:
any
[];
private
files
:
any
[];
constructor
()
{
this
.
types
=
[];
this
.
files
=
[];
}
public
update
(
event
:
DragMouseEvent
):
void
{
if
(
event
.
dataTransfer
.
types
)
{
this
.
types
=
[...
event
.
dataTransfer
.
types
];
}
if
(
event
.
dataTransfer
.
files
)
{
this
.
files
=
[...
event
.
dataTransfer
.
files
];
this
.
files
=
this
.
files
.
filter
(
f
=>
f
.
size
||
f
.
type
);
}
}
public
getData
():
any
{
return
{
types
:
this
.
types
,
files
:
this
.
files
};
}
}
export
class
List
<
T
>
implements
ISpliceable
<
T
>
,
IDisposable
{
private
static
currentExternalDragAndDropData
:
IDragAndDropData
|
undefined
;
private
static
InstanceCount
=
0
;
private
idPrefix
=
`list_id_
${
++
List
.
InstanceCount
}
`
;
...
...
@@ -1016,9 +953,6 @@ export class List<T> implements ISpliceable<T>, IDisposable {
private
styleElement
:
HTMLStyleElement
;
private
styleController
:
IStyleController
;
private
readonly
dnd
:
IDragAndDrop
<
T
>
;
private
currentDragAndDropData
:
IDragAndDropData
|
undefined
;
protected
disposables
:
IDisposable
[];
@
memoize
get
onFocusChange
():
Event
<
IListEvent
<
T
>>
{
...
...
@@ -1104,7 +1038,6 @@ export class List<T> implements ISpliceable<T>, IDisposable {
)
{
this
.
focus
=
new
FocusTrait
(
i
=>
this
.
getElementDomId
(
i
));
this
.
selection
=
new
Trait
(
'
selected
'
);
this
.
dnd
=
getOrDefault
<
IListOptions
<
T
>
,
IDragAndDrop
<
T
>>
(
options
,
o
=>
o
.
dnd
,
DefaultOptions
.
dnd
);
mixin
(
options
,
defaultStyles
,
false
);
...
...
@@ -1116,7 +1049,20 @@ export class List<T> implements ISpliceable<T>, IDisposable {
renderers
=
renderers
.
map
(
r
=>
new
PipelineRenderer
(
r
.
templateId
,
[...
baseRenderers
,
r
]));
this
.
view
=
new
ListView
(
container
,
virtualDelegate
,
renderers
,
options
);
const
that
=
this
;
const
viewOptions
:
IListViewOptions
<
T
>
=
{
...
options
,
dnd
:
options
.
dnd
&&
{
...
options
.
dnd
,
getDragElements
(
element
)
{
const
selection
=
that
.
getSelectedElements
();
const
elements
=
selection
.
indexOf
(
element
)
>
-
1
?
selection
:
[
element
];
return
elements
;
}
}
};
this
.
view
=
new
ListView
(
container
,
virtualDelegate
,
renderers
,
viewOptions
);
this
.
view
.
domNode
.
setAttribute
(
'
role
'
,
'
tree
'
);
DOM
.
addClass
(
this
.
view
.
domNode
,
this
.
idPrefix
);
this
.
view
.
domNode
.
tabIndex
=
0
;
...
...
@@ -1152,11 +1098,6 @@ export class List<T> implements ISpliceable<T>, IDisposable {
this
.
disposables
.
push
(
new
MouseController
(
this
,
this
.
view
,
options
));
}
this
.
view
.
onDragStart
(
this
.
onDragStart
,
this
,
this
.
disposables
);
this
.
view
.
onDragOver
(
this
.
onDragOver
,
this
,
this
.
disposables
);
this
.
view
.
onDragLeave
(
this
.
onDragLeave
,
this
,
this
.
disposables
);
this
.
onFocusChange
(
this
.
_onFocusChange
,
this
,
this
.
disposables
);
this
.
onSelectionChange
(
this
.
_onSelectionChange
,
this
,
this
.
disposables
);
...
...
@@ -1443,45 +1384,6 @@ export class List<T> implements ISpliceable<T>, IDisposable {
DOM
.
toggleClass
(
this
.
view
.
domNode
,
'
selection-multiple
'
,
selection
.
length
>
1
);
}
// DND
private
onDragStart
({
element
,
uri
,
event
}:
{
element
:
T
,
uri
:
string
,
event
:
DragMouseEvent
}):
void
{
const
selection
=
this
.
getSelectedElements
();
const
elements
=
selection
.
indexOf
(
element
)
>
-
1
?
selection
:
[
element
];
event
.
dataTransfer
.
effectAllowed
=
'
copyMove
'
;
event
.
dataTransfer
.
setData
(
DataTransfers
.
RESOURCES
,
JSON
.
stringify
([
uri
]));
if
(
event
.
dataTransfer
.
setDragImage
)
{
let
label
:
string
;
if
(
this
.
dnd
.
getDragLabel
)
{
label
=
this
.
dnd
.
getDragLabel
(
elements
);
}
else
{
label
=
String
(
elements
.
length
);
}
const
dragImage
=
DOM
.
$
(
'
.monaco-list-drag-image
'
);
dragImage
.
textContent
=
label
;
document
.
body
.
appendChild
(
dragImage
);
event
.
dataTransfer
.
setDragImage
(
dragImage
,
-
10
,
-
10
);
setTimeout
(()
=>
document
.
body
.
removeChild
(
dragImage
),
0
);
}
this
.
currentDragAndDropData
=
new
ElementsDragAndDropData
(
elements
);
List
.
currentExternalDragAndDropData
=
new
ExternalElementsDragAndDropData
(
elements
);
this
.
dnd
.
onDragStart
(
this
.
currentDragAndDropData
,
event
);
}
private
onDragOver
(
event
:
IListDragEvent
<
T
>
):
void
{
console
.
log
(
event
);
}
private
onDragLeave
():
void
{
console
.
log
(
'
LEAVE
'
);
}
dispose
():
void
{
this
.
_onDidDispose
.
fire
();
this
.
disposables
=
dispose
(
this
.
disposables
);
...
...
src/vs/base/browser/ui/tree/abstractTree.ts
浏览文件 @
2b2cdae1
...
...
@@ -32,11 +32,11 @@ function asListOptions<T, TFilterData>(options?: IAbstractTreeOptions<T, TFilter
onDragStart
(
data
,
originalEvent
)
{
return
options
.
dnd
!
.
onDragStart
(
data
,
originalEvent
);
},
onDragOver
(
data
,
targetNode
,
originalEvent
)
{
return
options
.
dnd
!
.
onDragOver
(
data
,
targetNode
.
element
,
originalEvent
);
onDragOver
(
data
,
targetNode
,
targetIndex
,
originalEvent
)
{
return
options
.
dnd
!
.
onDragOver
(
data
,
targetNode
&&
targetNode
.
element
,
targetIndex
,
originalEvent
);
},
drop
(
data
,
targetNode
,
originalEvent
)
{
return
options
.
dnd
!
.
drop
(
data
,
targetNode
.
element
,
originalEvent
);
return
options
.
dnd
!
.
drop
(
data
,
targetNode
&&
targetNode
.
element
,
originalEvent
);
}
},
multipleSelectionController
:
options
.
multipleSelectionController
&&
{
...
...
src/vs/base/browser/ui/tree/asyncDataTree.ts
浏览文件 @
2b2cdae1
...
...
@@ -140,11 +140,11 @@ function asObjectTreeOptions<TInput, T, TFilterData>(options?: IAsyncDataTreeOpt
onDragStart
(
data
,
originalEvent
)
{
return
options
.
dnd
!
.
onDragStart
(
data
,
originalEvent
);
},
onDragOver
(
data
,
targetNode
,
originalEvent
)
{
return
options
.
dnd
!
.
onDragOver
(
data
,
targetNode
.
element
as
T
,
originalEvent
);
onDragOver
(
data
,
targetNode
,
targetIndex
,
originalEvent
)
{
return
options
.
dnd
!
.
onDragOver
(
data
,
targetNode
&&
targetNode
.
element
as
T
,
targetIndex
,
originalEvent
);
},
drop
(
data
,
targetNode
,
originalEvent
)
{
return
options
.
dnd
!
.
drop
(
data
,
targetNode
.
element
as
T
,
originalEvent
);
return
options
.
dnd
!
.
drop
(
data
,
targetNode
&&
targetNode
.
element
as
T
,
originalEvent
);
}
},
multipleSelectionController
:
options
.
multipleSelectionController
&&
{
...
...
src/vs/platform/list/browser/listService.ts
浏览文件 @
2b2cdae1
...
...
@@ -162,22 +162,24 @@ class WorkbenchOpenController implements IOpenController {
}
function
toWorkbenchListOptions
<
T
>
(
options
:
IListOptions
<
T
>
,
configurationService
:
IConfigurationService
,
keybindingService
:
IKeybindingService
):
IListOptions
<
T
>
{
const
result
=
{
...
options
};
if
(
options
.
multipleSelectionSupport
!==
false
&&
!
options
.
multipleSelectionController
)
{
options
.
multipleSelectionController
=
new
MultipleSelectionController
(
configurationService
);
result
.
multipleSelectionController
=
new
MultipleSelectionController
(
configurationService
);
}
options
.
openController
=
new
WorkbenchOpenController
(
configurationService
,
options
.
openController
);
result
.
openController
=
new
WorkbenchOpenController
(
configurationService
,
options
.
openController
);
if
(
options
.
keyboardNavigationLabelProvider
)
{
const
tlp
=
options
.
keyboardNavigationLabelProvider
;
options
.
keyboardNavigationLabelProvider
=
{
result
.
keyboardNavigationLabelProvider
=
{
getKeyboardNavigationLabel
(
e
)
{
return
tlp
.
getKeyboardNavigationLabel
(
e
);
},
mightProducePrintableCharacter
(
e
)
{
return
keybindingService
.
mightProducePrintableCharacter
(
e
);
}
};
}
return
options
;
return
result
;
}
let
sharedListStyleSheet
:
HTMLStyleElement
;
...
...
src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts
浏览文件 @
2b2cdae1
...
...
@@ -878,6 +878,7 @@ export class RepositoryPanel extends ViewletPanel {
new
ResourceRenderer
(
this
.
listLabels
,
actionItemProvider
,
()
=>
this
.
getSelectedResources
(),
this
.
themeService
,
this
.
menus
)
];
const
that
=
this
;
this
.
list
=
this
.
instantiationService
.
createInstance
(
WorkbenchList
,
this
.
listContainer
,
delegate
,
renderers
,
{
identityProvider
:
scmResourceIdentityProvider
,
keyboardNavigationLabelProvider
:
scmKeyboardNavigationLabelProvider
,
...
...
@@ -885,7 +886,9 @@ export class RepositoryPanel extends ViewletPanel {
getDragURI
(
element
)
{
return
'
file:///foo
'
;
},
// getDragLabel(elements) { return 'dragging'; },
onDragStart
(
data
,
originalEvent
)
{
},
onDragOver
(
data
,
targetElement
,
originalEvent
)
{
return
true
;
},
onDragOver
(
data
,
targetElement
,
targetIndex
,
originalEvent
)
{
return
{
accept
:
true
,
feedback
:
typeof
targetIndex
===
'
undefined
'
?
undefined
:
[
targetIndex
-
1
,
targetIndex
,
targetIndex
+
1
].
filter
(
i
=>
i
>=
0
&&
i
<
that
.
list
.
length
)
};
},
drop
(
data
,
targetElement
,
originalEvent
)
{
}
}
})
as
WorkbenchList
<
ISCMResourceGroup
|
ISCMResource
>
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录