diff --git a/src/dlangide/ui/commands.d b/src/dlangide/ui/commands.d index 163df66..4cd2773 100644 --- a/src/dlangide/ui/commands.d +++ b/src/dlangide/ui/commands.d @@ -41,10 +41,12 @@ enum IDEActions : int { ProjectFolderRemoveItem, ProjectFolderOpenItem, ProjectFolderRenameItem, + ProjectFolderRefresh, GoToDefinition, GetCompletionSuggestions, InsertCompletion, FindText, + CloseWorkspace, } __gshared static this() { @@ -57,6 +59,8 @@ __gshared static this() { const Action ACTION_PROJECT_FOLDER_OPEN_ITEM = new Action(IDEActions.ProjectFolderOpenItem, "MENU_PROJECT_FOLDER_OPEN_ITEM"c); const Action ACTION_PROJECT_FOLDER_REMOVE_ITEM = new Action(IDEActions.ProjectFolderRemoveItem, "MENU_PROJECT_FOLDER_REMOVE_ITEM"c); const Action ACTION_PROJECT_FOLDER_RENAME_ITEM = new Action(IDEActions.ProjectFolderRenameItem, "MENU_PROJECT_FOLDER_RENAME_ITEM"c); +const Action ACTION_PROJECT_FOLDER_REFRESH = new Action(IDEActions.ProjectFolderRefresh, "MENU_PROJECT_FOLDER_REFRESH"c); +const Action ACTION_FILE_WORKSPACE_CLOSE = new Action(IDEActions.CloseWorkspace, "MENU_FILE_WORKSPACE_CLOSE"c); const Action ACTION_FILE_NEW_SOURCE_FILE = new Action(IDEActions.FileNew, "MENU_FILE_NEW_SOURCE_FILE"c, "document-new", KeyCode.KEY_N, KeyFlag.Control); const Action ACTION_FILE_NEW_PROJECT = new Action(IDEActions.FileNewProject, "MENU_FILE_NEW_PROJECT"c); diff --git a/src/dlangide/ui/frame.d b/src/dlangide/ui/frame.d index aac9946..cff5322 100644 --- a/src/dlangide/ui/frame.d +++ b/src/dlangide/ui/frame.d @@ -234,6 +234,19 @@ class IDEFrame : AppFrame { } } + /// close editor tabs for which files are removed from filesystem + void closeRemovedDocuments() { + import std.file; + for (int i = _tabs.tabCount - 1; i >= 0; i--) { + DSourceEdit ed = cast(DSourceEdit)_tabs.tabBody(i); + if (ed) { + if (!exists(ed.id) || !isFile(ed.id)) { + closeTab(ed.id); + } + } + } + } + /// returns first unsaved document protected DSourceEdit hasUnsavedEdits() { for (int i = _tabs.tabCount - 1; i >= 0; i--) { @@ -369,7 +382,7 @@ class IDEFrame : AppFrame { fileNewItem.add(ACTION_FILE_NEW_SOURCE_FILE, ACTION_FILE_NEW_WORKSPACE, ACTION_FILE_NEW_PROJECT); fileItem.add(fileNewItem); fileItem.add(ACTION_FILE_OPEN_WORKSPACE, ACTION_FILE_OPEN, - ACTION_FILE_SAVE, ACTION_FILE_SAVE_AS, ACTION_FILE_SAVE_ALL, ACTION_FILE_EXIT); + ACTION_FILE_SAVE, ACTION_FILE_SAVE_AS, ACTION_FILE_SAVE_ALL, ACTION_FILE_WORKSPACE_CLOSE, ACTION_FILE_EXIT); MenuItem editItem = new MenuItem(new Action(2, "MENU_EDIT")); editItem.add(ACTION_EDIT_COPY, ACTION_EDIT_PASTE, @@ -637,6 +650,15 @@ class IDEFrame : AppFrame { return true; case IDEActions.FileNew: addProjectItem(a.objectParam); + return true; + case IDEActions.ProjectFolderRemoveItem: + removeProjectItem(a.objectParam); + return true; + case IDEActions.ProjectFolderRefresh: + refreshProjectItem(a.objectParam); + return true; + case IDEActions.CloseWorkspace: + closeWorkspace(); return true; default: return super.handleAction(a); @@ -653,6 +675,71 @@ class IDEFrame : AppFrame { return null; } + void closeWorkspace() { + askForUnsavedEdits(delegate() { + setWorkspace(null); + showHomeScreen(); + }); + } + + void refreshProjectItem(const Object obj) { + if (currentWorkspace is null) + return; + Project project; + ProjectFolder folder; + if (cast(Project)obj) { + project = cast(Project)obj; + } else if (cast(ProjectFolder)obj) { + folder = cast(ProjectFolder)obj; + project = folder.project; + } else if (cast(ProjectSourceFile)obj) { + ProjectSourceFile srcfile = cast(ProjectSourceFile)obj; + folder = cast(ProjectFolder)srcfile.parent; + project = srcfile.project; + } else { + ProjectSourceFile srcfile = currentEditorSourceFile; + if (srcfile) { + folder = cast(ProjectFolder)srcfile.parent; + project = srcfile.project; + } + } + if (project) { + project.refresh(); + refreshWorkspace(); + } + } + + void removeProjectItem(const Object obj) { + if (currentWorkspace is null) + return; + ProjectSourceFile srcfile = cast(ProjectSourceFile)obj; + if (!srcfile) + return; + Project project = srcfile.project; + if (!project) + return; + window.showMessageBox(UIString("Remove file"d), + UIString("Do you want to remove file "d ~ srcfile.name ~ "?"), + [ACTION_YES, ACTION_NO], + 1, delegate(const Action result) { + if (result == StandardAction.Yes) { + // save and close + try { + import std.file : remove; + closeTab(srcfile.filename); + remove(srcfile.filename); + project.refresh(); + refreshWorkspace(); + } catch (Exception e) { + Log.e("Error while removing file"); + } + } + // else ignore + return true; + }); + + } + void addProjectItem(const Object obj) { if (currentWorkspace is null) return; @@ -818,6 +905,7 @@ class IDEFrame : AppFrame { void refreshWorkspace() { _logPanel.logLine("Refreshing workspace"); _wsPanel.reloadItems(); + closeRemovedDocuments(); } void createNewWorkspaceForExistingProject(Project project) { diff --git a/src/dlangide/ui/wspanel.d b/src/dlangide/ui/wspanel.d index 8fa8828..3c343a4 100644 --- a/src/dlangide/ui/wspanel.d +++ b/src/dlangide/ui/wspanel.d @@ -75,18 +75,27 @@ class WorkspacePanel : DockWindow { _tree.popupMenu = &onTreeItemPopupMenu; _workspacePopupMenu = new MenuItem(); - _workspacePopupMenu.add(ACTION_FILE_NEW_SOURCE_FILE.clone()); + _workspacePopupMenu.add(ACTION_FILE_NEW_SOURCE_FILE, ACTION_FILE_WORKSPACE_CLOSE); _projectPopupMenu = new MenuItem(); - _projectPopupMenu.add(ACTION_FILE_NEW_SOURCE_FILE, ACTION_PROJECT_FOLDER_OPEN_ITEM, - ACTION_PROJECT_FOLDER_REMOVE_ITEM); + _projectPopupMenu.add(ACTION_FILE_NEW_SOURCE_FILE, + ACTION_PROJECT_FOLDER_REFRESH, + ACTION_PROJECT_FOLDER_OPEN_ITEM, + //ACTION_PROJECT_FOLDER_REMOVE_ITEM + ); _folderPopupMenu = new MenuItem(); - _folderPopupMenu.add(ACTION_FILE_NEW_SOURCE_FILE, ACTION_PROJECT_FOLDER_OPEN_ITEM, - ACTION_PROJECT_FOLDER_REMOVE_ITEM, ACTION_PROJECT_FOLDER_RENAME_ITEM); + _folderPopupMenu.add(ACTION_FILE_NEW_SOURCE_FILE, ACTION_PROJECT_FOLDER_REFRESH, ACTION_PROJECT_FOLDER_OPEN_ITEM, + //ACTION_PROJECT_FOLDER_REMOVE_ITEM, + //ACTION_PROJECT_FOLDER_RENAME_ITEM + ); + _filePopupMenu = new MenuItem(); - _filePopupMenu.add(ACTION_FILE_NEW_SOURCE_FILE, ACTION_PROJECT_FOLDER_OPEN_ITEM, - ACTION_PROJECT_FOLDER_REMOVE_ITEM, ACTION_PROJECT_FOLDER_RENAME_ITEM); + _filePopupMenu.add(ACTION_FILE_NEW_SOURCE_FILE, ACTION_PROJECT_FOLDER_REFRESH, + ACTION_PROJECT_FOLDER_OPEN_ITEM, + ACTION_PROJECT_FOLDER_REMOVE_ITEM, + //ACTION_PROJECT_FOLDER_RENAME_ITEM + ); return _tree; } diff --git a/src/dlangide/workspace/project.d b/src/dlangide/workspace/project.d index c76255a..c507d06 100644 --- a/src/dlangide/workspace/project.d +++ b/src/dlangide/workspace/project.d @@ -176,7 +176,10 @@ class ProjectFolder : ProjectItem { string relativeToAbsolutePath(string path) { if (isAbsolute(path)) return path; - return buildNormalizedPath(_filename, path); + string fn = _filename; + if (exists(fn) && isFile(fn)) + fn = dirName(fn); + return buildNormalizedPath(fn, path); } override void refresh() { @@ -456,7 +459,10 @@ class Project : WorkspaceItem { } void refresh() { - _items.refresh(); + for (int i = _items._children.count - 1; i >= 0; i--) { + if (_items._children[i].isFolder) + _items._children[i].refresh(); + } } void findMainSourceFile() { diff --git a/views/res/i18n/en.ini b/views/res/i18n/en.ini index 59b8987..f21f46f 100644 --- a/views/res/i18n/en.ini +++ b/views/res/i18n/en.ini @@ -74,3 +74,6 @@ MENU_PROJECT_FOLDER_ADD_ITEM=Add... MENU_PROJECT_FOLDER_OPEN_ITEM=Open MENU_PROJECT_FOLDER_REMOVE_ITEM=Remove MENU_PROJECT_FOLDER_RENAME_ITEM=Rename... +MENU_PROJECT_FOLDER_REFRESH=Refresh + +MENU_FILE_WORKSPACE_CLOSE=Close Workspace diff --git a/views/res/i18n/es.ini b/views/res/i18n/es.ini index 36024f7..a4c0d7d 100644 --- a/views/res/i18n/es.ini +++ b/views/res/i18n/es.ini @@ -75,3 +75,4 @@ MENU_PROJECT_FOLDER_ADD_ITEM=AƱadir... MENU_PROJECT_FOLDER_OPEN_ITEM=Abrir MENU_PROJECT_FOLDER_REMOVE_ITEM=Remover MENU_PROJECT_FOLDER_RENAME_ITEM=Renombrar... +MENU_PROJECT_FOLDER_REFRESH=Refresh