1 module dlangide.ui.wspanel; 2 3 import dlangui.all; 4 import dlangide.workspace.workspace; 5 import dlangide.workspace.project; 6 import dlangide.ui.commands; 7 8 enum ProjectItemType : int { 9 None, 10 SourceFile, 11 SourceFolder, 12 Project, 13 Workspace 14 } 15 16 interface SourceFileSelectionHandler { 17 bool onSourceFileSelected(ProjectSourceFile file, bool activate); 18 } 19 20 class WorkspacePanel : DockWindow { 21 protected Workspace _workspace; 22 protected TreeWidget _tree; 23 24 /// handle source file selection change 25 Signal!SourceFileSelectionHandler sourceFileSelectionListener; 26 27 this(string id) { 28 super(id); 29 workspace = null; 30 //layoutWidth = 200; 31 _caption.text = "Workspace Explorer"d; 32 } 33 34 bool selectItem(ProjectItem projectItem) { 35 if (projectItem) { 36 TreeItem item = _tree.findItemById(projectItem.filename); 37 if (item) { 38 _tree.selectItem(item); 39 return true; 40 } 41 } else { 42 _tree.clearSelection(); 43 return true; 44 } 45 return false; 46 } 47 48 void onTreeItemSelected(TreeItems source, TreeItem selectedItem, bool activated) { 49 if (!selectedItem) 50 return; 51 if (selectedItem.intParam == ProjectItemType.SourceFile) { 52 // file selected 53 if (sourceFileSelectionListener.assigned) { 54 ProjectSourceFile sourceFile = cast(ProjectSourceFile)selectedItem.objectParam; 55 if (sourceFile) { 56 sourceFileSelectionListener(sourceFile, activated); 57 } 58 } 59 } else if (selectedItem.intParam == ProjectItemType.SourceFolder) { 60 // folder selected 61 } 62 } 63 64 override protected Widget createBodyWidget() { 65 _tree = new TreeWidget("wstree"); 66 _tree.layoutHeight(FILL_PARENT).layoutHeight(FILL_PARENT); 67 _tree.selectionListener = &onTreeItemSelected; 68 _tree.fontSize = 16; 69 _tree.noCollapseForSingleTopLevelItem = true; 70 _tree.popupMenuListener = &onTreeItemPopupMenu; 71 72 _workspacePopupMenu = new MenuItem(); 73 _workspacePopupMenu.add(ACTION_PROJECT_FOLDER_ADD_ITEM); 74 75 _projectPopupMenu = new MenuItem(); 76 _projectPopupMenu.add(ACTION_PROJECT_FOLDER_ADD_ITEM, ACTION_PROJECT_FOLDER_OPEN_ITEM, 77 ACTION_PROJECT_FOLDER_REMOVE_ITEM); 78 79 _folderPopupMenu = new MenuItem(); 80 _folderPopupMenu.add(ACTION_PROJECT_FOLDER_ADD_ITEM, ACTION_PROJECT_FOLDER_OPEN_ITEM, 81 ACTION_PROJECT_FOLDER_REMOVE_ITEM, ACTION_PROJECT_FOLDER_RENAME_ITEM); 82 _filePopupMenu = new MenuItem(); 83 _filePopupMenu.add(ACTION_PROJECT_FOLDER_ADD_ITEM, ACTION_PROJECT_FOLDER_OPEN_ITEM, 84 ACTION_PROJECT_FOLDER_REMOVE_ITEM, ACTION_PROJECT_FOLDER_RENAME_ITEM); 85 return _tree; 86 } 87 88 protected MenuItem _workspacePopupMenu; 89 protected MenuItem _projectPopupMenu; 90 protected MenuItem _folderPopupMenu; 91 protected MenuItem _filePopupMenu; 92 protected string _popupMenuSelectedItemId; 93 protected void onPopupMenuItem(MenuItem item) { 94 if (item.action) 95 handleAction(item.action); 96 } 97 98 protected MenuItem onTreeItemPopupMenu(TreeItems source, TreeItem selectedItem) { 99 MenuItem menu = null; 100 _popupMenuSelectedItemId = selectedItem.id; 101 if (selectedItem.intParam == ProjectItemType.SourceFolder) { 102 menu = _folderPopupMenu; 103 } else if (selectedItem.intParam == ProjectItemType.SourceFile) { 104 menu = _filePopupMenu; 105 } else if (selectedItem.intParam == ProjectItemType.Project) { 106 menu = _projectPopupMenu; 107 } else if (selectedItem.intParam == ProjectItemType.Workspace) { 108 menu = _workspacePopupMenu; 109 } 110 if (menu && menu.subitemCount) { 111 menu.onMenuItem = &onPopupMenuItem; 112 menu.updateActionState(this); 113 return menu; 114 } 115 return null; 116 } 117 118 @property Workspace workspace() { 119 return _workspace; 120 } 121 122 ProjectSourceFile findSourceFileItem(string filename, bool fullFileName=true) { 123 if (_workspace) 124 return _workspace.findSourceFileItem(filename, fullFileName); 125 return null; 126 } 127 128 void addProjectItems(TreeItem root, ProjectItem items) { 129 for (int i = 0; i < items.childCount; i++) { 130 ProjectItem child = items.child(i); 131 if (child.isFolder) { 132 TreeItem p = root.newChild(child.filename, child.name, "folder"); 133 p.intParam = ProjectItemType.SourceFolder; 134 p.objectParam = child; 135 addProjectItems(p, child); 136 } else { 137 TreeItem p = root.newChild(child.filename, child.name, "text-d"); 138 p.intParam = ProjectItemType.SourceFile; 139 p.objectParam = child; 140 } 141 } 142 } 143 144 void reloadItems() { 145 _tree.clearAllItems(); 146 if (_workspace) { 147 TreeItem root = _tree.items.newChild(_workspace.filename, _workspace.name, "project-development"); 148 root.intParam = ProjectItemType.Workspace; 149 foreach(project; _workspace.projects) { 150 TreeItem p = root.newChild(project.filename, project.name, "project-d"); 151 p.intParam = ProjectItemType.Project; 152 addProjectItems(p, project.items); 153 } 154 } else { 155 _tree.items.newChild("none", "No workspace"d, "project-development"); 156 } 157 _tree.onTreeContentChange(null); 158 } 159 160 @property void workspace(Workspace w) { 161 _workspace = w; 162 reloadItems(); 163 } 164 }