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 }