diff --git a/src/tea/editor/views/HierarchyView.ts b/src/tea/editor/views/HierarchyView.ts
index 05bbde7..31d7542 100644
--- a/src/tea/editor/views/HierarchyView.ts
+++ b/src/tea/editor/views/HierarchyView.ts
@@ -97,7 +97,7 @@ export class HierarchyView extends Vue {
var dragEvents = treeView.dragEvents;
dragEvents.dragStart = this.onDragStart;
dragEvents.dragEnd = this.onDragEnd;
- dragEvents.dragOver = this.onDragOver
+ dragEvents.dragOver = this.onDragOver;
dragEvents.dragEnter = this.onDragEnter;
dragEvents.dragLeave = this.onDragLeave;
dragEvents.drop = this.onDrop;
diff --git a/src/tea/editor/views/ProjectView.ts b/src/tea/editor/views/ProjectView.ts
index 9d4d3a2..6468a1e 100644
--- a/src/tea/editor/views/ProjectView.ts
+++ b/src/tea/editor/views/ProjectView.ts
@@ -10,6 +10,18 @@ import { EditorMenu } from "../EditorMenu";
import { FileInspector } from "./FileInspector";
import { TreeView } from "../basic/TreeView";
+class FileItemTag {
+ path: string;
+ isFolder: boolean;
+
+ static create(path: string, isFolder: boolean): FileItemTag {
+ var tag = new FileItemTag ();
+ tag.path = path;
+ tag.isFolder = isFolder;
+ return tag;
+ }
+}
+
@Component({
template: `
@@ -36,7 +48,7 @@ import { TreeView } from "../basic/TreeView";
`
})
export class ProjectView extends Vue {
- protected _dragSource: Editor.TreeViewItem;
+ protected _dragSourceFile: Editor.TreeViewItem;
get folderList(): TreeView {
return this.$refs.folderList as TreeView;
@@ -61,11 +73,15 @@ export class ProjectView extends Vue {
if (item == null) {
return null;
}
- return item.tag;
+ var tag = item.tag as FileItemTag;
+ if (tag == null) {
+ return null;
+ }
+ return tag.path;
}
getDragSource(): Editor.TreeViewItem {
- return this._dragSource;
+ return this._dragSourceFile;
}
selectParentFolder(): void {
@@ -91,15 +107,14 @@ export class ProjectView extends Vue {
var items: Array
= [];
Tea.Directory.getFiles(path, (files: Array) => {
files = this.sortFolders(files);
- files.forEach(file => {
- var item = this.createTreeViewItem(file);
+ files.forEach((file: Tea.FileInfo) => {
+ var item = this.createFolderListModel(file);
if (item == null) {
return;
}
items.push(item);
});
});
- var folderList = this.$refs.folderList as TreeView;
folderList.items = items;
if (selectedItem == null) {
return;
@@ -131,6 +146,10 @@ export class ProjectView extends Vue {
updateFileList(path: string): void {
var fileList = this.$refs.fileList as TreeView;
Tea.Directory.getFiles(path, (files: Tea.FileInfo[]) => {
+ if (files == null) {
+ this.clearFileList();
+ return;
+ }
var items = [];
files = files.sort((a: Tea.FileInfo, b: Tea.FileInfo): number => {
var folderA = a.isDirectory ? 2 : 0;
@@ -139,26 +158,14 @@ export class ProjectView extends Vue {
var fileB = b.name.toLocaleLowerCase();
return (folderB - folderA) + (fileB > fileA ? 0 : 1);
});
- files.forEach((file) => {
+ files.forEach((file: Tea.FileInfo) => {
/*if (file.isDirectory) {
return;
}*/
if (file.name === ".DS_Store") {
return;
}
- var iconUrl = this.getFileIconUrl(file);
- var icon: string = null;
- if (iconUrl !== "") {
- icon = "";
- }
- var item: TreeView.Model = {
- text: file.name,
- isFolder: false,
- icon: icon,
- indent: "1.7em",
- tag: file.fullName,
- children: []
- };
+ var item = this.createFileListModel(file);
//console.log(file.fullName);
items.push(item);
});
@@ -196,15 +203,26 @@ export class ProjectView extends Vue {
folderList.openIcon = "";
folderList.closeIcon = "";
+ folderList.draggable = true;
+ var dragEvents = folderList.dragEvents;
+ dragEvents.dragStart = this.onFolderDragStart;
+ dragEvents.dragOver = this.onFolderDragOver;
+ dragEvents.dragEnter = this.onFolderDragEnter;
+ dragEvents.dragLeave = this.onFolderDragLeave;
+ dragEvents.drop = this.onFolderDrop;
+
fileList.draggable = true;
-
- var dragEvents = fileList.dragEvents;
- dragEvents.dragStart = this.onDragStart;
- dragEvents.dragEnd = this.onDragEnd;
+ dragEvents = fileList.dragEvents;
+ dragEvents.dragStart = this.onFileDragStart;
+ dragEvents.dragEnd = this.onFileDragEnd;
+ dragEvents.dragOver = this.onFileDragOver;
+ dragEvents.dragEnter = this.onFileDragEnter;
+ dragEvents.dragLeave = this.onFileDragLeave;
+ dragEvents.drop = this.onFileDrop;
this.openFolder(process.cwd());
}
- protected createTreeViewItem(file: Tea.FileInfo): TreeView.Model {
+ protected createFolderListModel(file: Tea.FileInfo): TreeView.Model {
if (file == null || file.exists === false) {
return null;
}
@@ -220,6 +238,32 @@ export class ProjectView extends Vue {
return item;
}
+ protected createFileListModel(file: Tea.FileInfo): TreeView.Model {
+ var iconUrl = this.getFileIconUrl(file);
+ var icon: string = null;
+ if (iconUrl !== "") {
+ icon = "";
+ }
+ var item: TreeView.Model = {
+ text: file.name,
+ isFolder: false,
+ icon: icon,
+ indent: "1.7em",
+ tag: FileItemTag.create(
+ file.fullName,
+ file.isDirectory
+ ),
+ children: []
+ };
+ return item;
+ }
+
+ protected clearFileList(): void {
+ var fileList = this.$refs.fileList as TreeView;
+ fileList.unselect();
+ fileList.items = [];
+ }
+
protected sortFolders(files: Array): Array {
if (files == null || files.length <= 0) {
return files;
@@ -231,16 +275,19 @@ export class ProjectView extends Vue {
});
}
- protected setChildFolderItems(item: Editor.TreeViewItem): void {
+ protected setFolderListChildItems(item: Editor.TreeViewItem): void {
var i = item.model;
if (i == null || i.children.length > 0) {
return;
}
var items: Array = [];
var files = Tea.Directory.getFilesSync(item.tag);
+ if (files == null) {
+ return;
+ }
files = this.sortFolders(files);
- files.forEach(file => {
- var item = this.createTreeViewItem(file);
+ files.forEach((file: Tea.FileInfo) => {
+ var item = this.createFolderListModel(file);
if (item == null) {
return;
}
@@ -296,6 +343,16 @@ export class ProjectView extends Vue {
Electron.shell.openItem(path);
}
+ protected moveFile(path: string, target: string): void {
+ var stat = fs.statSync(target);
+ if (stat == null || stat.isDirectory() === false) {
+ return;
+ }
+ var name = nodePath.basename(path);
+ target = nodePath.join(target, name);
+ fs.renameSync(path, target);
+ }
+
protected openFileInspector(path: string): void {
if (path == null) {
return;
@@ -340,9 +397,62 @@ export class ProjectView extends Vue {
}
}
- protected onDragStart(e: DragEvent, item: Editor.TreeViewItem): void {
+ protected onFolderDragStart(e: DragEvent, item: Editor.TreeViewItem): void {
+ //console.log("onDragStart");
+ e.preventDefault();
+ }
+
+ protected onFolderDragOver(e: DragEvent, item: Editor.TreeViewItem): void {
+ if (this._dragSourceFile == null) {
+ return;
+ }
+ e.preventDefault();
+ e.dataTransfer.dropEffect = "move";
+ }
+
+ protected onFolderDragEnter(e: DragEvent, item: Editor.TreeViewItem): void {
+ //console.log("dragEnter", item.model.text, this._dragSourceFile);
+ if (this._dragSourceFile == null) {
+ return;
+ }
+ var el = e.currentTarget as HTMLElement;
+ el.classList.add("dragEnter");
+ }
+
+ protected onFolderDragLeave(e: DragEvent, item: Editor.TreeViewItem): void {
+ //console.log("dragLeave", this, e);
+ var el = e.currentTarget as HTMLElement;
+ el.classList.remove("dragEnter");
+ }
+
+ protected onFolderDrop(e: DragEvent, item: Editor.TreeViewItem): void {
+ //console.log("drop", item);
+ if (this._dragSourceFile == null) {
+ return;
+ }
+ var el = e.currentTarget as HTMLElement;
+ if (el.classList.contains("dragEnter") === false) {
+ return;
+ }
+ el.classList.remove("dragEnter");
+ var tagSrc = this._dragSourceFile.model.tag as FileItemTag;
+ var targetPath = item.model.tag;
+ this._dragSourceFile = null;
+ if (tagSrc == null || targetPath == null) {
+ return;
+ }
+ //console.log(tagSrc, targetPath);
+ this.moveFile(tagSrc.path, targetPath);
+ var path = nodePath.dirname(tagSrc.path);
+ this.updateFileList(path);
+ if (tagSrc.isFolder) {
+ this.openFolder(process.cwd());
+ }
+ }
+
+ protected onFileDragStart(e: DragEvent, item: Editor.TreeViewItem): void {
//console.log("onDragStart");
- this._dragSource = item;
+ this._dragSourceFile = item;
e.dataTransfer.effectAllowed = "move";
//e.dataTransfer.dropEffect = "move";
@@ -352,25 +462,79 @@ export class ProjectView extends Vue {
e.dataTransfer.setDragImage(dragImage, 0, 0);
}
- protected onDragEnd(e: DragEvent, item: Editor.TreeViewItem): void {
- this._dragSource = null;
+ protected onFileDragEnd(e: DragEvent, item: Editor.TreeViewItem): void {
+ this._dragSourceFile = null;
+ }
+
+ protected onFileDragOver(e: DragEvent, item: Editor.TreeViewItem): void {
+ if (this._dragSourceFile == null) {
+ return;
+ }
+ var tag = item.tag as FileItemTag;
+ if (tag == null || tag.isFolder === false) {
+ return;
+ }
+ e.preventDefault();
+ e.dataTransfer.dropEffect = "move";
+ }
+
+ protected onFileDragEnter(e: DragEvent, item: Editor.TreeViewItem): void {
+ //console.log("dragEnter", item.model.text, this._dragSource);
+ if (this._dragSourceFile == null) {
+ return;
+ }
+ var tag = item.tag as FileItemTag;
+ if (tag == null || tag.isFolder === false) {
+ return;
+ }
+ var el = e.currentTarget as HTMLElement;
+ el.classList.add("dragEnter");
+ }
+
+ protected onFileDragLeave(e: DragEvent, item: Editor.TreeViewItem): void {
+ //console.log("dragLeave", this, e);
+ var el = e.currentTarget as HTMLElement;
+ el.classList.remove("dragEnter");
+ }
+
+ protected onFileDrop(e: DragEvent, item: Editor.TreeViewItem): void {
+ //console.log("drop", item);
+ if (this._dragSourceFile == null) {
+ return;
+ }
+ var el = e.currentTarget as HTMLElement;
+ if (el.classList.contains("dragEnter") === false) {
+ return;
+ }
+ el.classList.remove("dragEnter");
+ var tagSrc = this._dragSourceFile.model.tag as FileItemTag;
+ var tagDst = item.model.tag as FileItemTag;
+ this._dragSourceFile = null;
+ if (tagSrc == null || tagDst == null || tagSrc == tagDst) {
+ return;
+ }
+ //console.log(tagSrc, tagDst);
+ this.moveFile(tagSrc.path, tagDst.path);
+ var path = nodePath.dirname(tagSrc.path);
+ this.updateFileList(path);
+ if (tagSrc.isFolder) {
+ this.openFolder(process.cwd());
+ }
}
protected onExpandFolderList(item: Editor.TreeViewItem): void {
//console.log("expand", item);
- this.setChildFolderItems(item);
+ this.setFolderListChildItems(item);
}
protected onSelectFolder(item: Editor.TreeViewItem): void {
- var fileList = this.$refs.fileList as TreeView;
if (item == null) {
- fileList.unselect();
- fileList.items = [];
+ this.clearFileList();
return;
}
//console.log("select", item.tag);
var path = item.tag;
- this.setChildFolderItems(item);
+ this.setFolderListChildItems(item);
this.updateFileList(path);
}
@@ -402,8 +566,8 @@ export class ProjectView extends Vue {
inspectorView.hide();
return;
}
- var path = item.tag;
- this.openFileInspector(path);
+ var tag = item.tag as FileItemTag;
+ this.openFileInspector(tag.path);
}
protected onFileListKeyDown(e: KeyboardEvent): void {
@@ -437,12 +601,13 @@ export class ProjectView extends Vue {
}
protected onRenameFile(item: Editor.TreeViewItem, value: string): void {
- var oldPath = item.tag;
+ var tag = item.tag as FileItemTag;
+ var oldPath = tag.path;
var basePath = nodePath.dirname(oldPath);
var newPath = nodePath.join(basePath, value);
fs.renameSync(oldPath, newPath);
item.model.text = value;
- item.model.tag = newPath;
+ tag.path = newPath;
var file = new Tea.FileInfo(newPath);
var iconUrl = this.getFileIconUrl(file);
@@ -458,7 +623,7 @@ export class ProjectView extends Vue {
var item = folderList.findItemByTag(basePath);
if (item && item.model) {
item.model.children = [];
- this.setChildFolderItems(item);
+ this.setFolderListChildItems(item);
}
}
}