1 module dlangide.ui.newfolder;
2 
3 import std.array : empty;
4 import std.file : mkdir, exists;
5 import std.path : buildPath, buildNormalizedPath;
6 import std.utf : toUTF32;
7 
8 import dlangui.core.logger;
9 import dlangui.core.stdaction;
10 import dlangui.dialogs.dialog;
11 import dlangui.dml.parser;
12 import dlangui.widgets.controls;
13 import dlangui.widgets.editors;
14 import dlangui.widgets.widget;
15 
16 import dlangide.ui.commands;
17 import dlangide.ui.frame;
18 import dlangide.ui.newfile;
19 import dlangide.workspace.project;
20 
21 class NewFolderDialog : Dialog {
22     private {
23         IDEFrame _ide;
24         Project _project;
25         ProjectFolder _folder;
26         string _location;
27     }
28 
29     
30     this(IDEFrame parent, Project currentProject, ProjectFolder folder) {
31         super(UIString.fromId("OPTION_NEW_SOURCE_FILE"c), parent.window, 
32             DialogFlag.Modal | DialogFlag.Popup, 800, 0);
33         layoutWidth = FILL_PARENT;
34         _ide = parent;
35         _icon = "dlangui-logo1";
36         this._project = currentProject;
37         this._folder = folder;
38         if (folder){
39             _location = folder.filename;
40         } 
41         else {
42             _location = currentProject.dir;
43         }
44     }
45 
46     override void initialize() {
47         super.initialize();
48         Widget content;
49         try {
50             content = parseML(q{
51                     VerticalLayout {
52                     id: vlayout
53                         padding: Rect { 5, 5, 5, 5 }
54                     layoutWidth: fill; layoutHeight: wrap
55                         TableLayout {
56                         margins: 5
57                                 colCount: 2
58                                     layoutWidth: fill; layoutHeight: wrap
59                             TextWidget { text: NAME }
60                             EditLine { id: fileName; text: "newfolder"; layoutWidth: fill }
61                             CheckBox { id: makePackage }
62                             TextWidget { text: OPTION_MAKE_PACKAGE}
63                         }
64                         TextWidget { id: statusText; text: ""; layoutWidth: fill; textColor: 0xFF0000 }
65                     }
66                 });
67         } catch (Exception e) {
68             Log.e("Exceptin while parsing DML", e);
69             throw e;
70         }
71         _edFileName = content.childById!EditLine("fileName");
72         _edMakePackage = content.childById!CheckBox("makePackage");
73         _statusText = content.childById!TextWidget("statusText");
74 
75         _edFileName.enterKey.connect(&onEnterKey);
76 
77         _edFileName.setDefaultPopupMenu();
78 
79         _edFileName.contentChange = delegate (EditableContent source) {
80             updateValues(source.text);
81             validate();
82         };
83 
84         addChild(content);
85         addChild(createButtonsPanel([ACTION_FILE_NEW_DIRECTORY, ACTION_CANCEL], 0, 0));
86 
87         updateValues(_edFileName.text);
88     }
89 
90     override void onShow() {
91         super.onShow();
92         _edFileName.selectAll();
93         _edFileName.setFocus();
94     }
95 
96     protected bool onEnterKey(EditWidgetBase editor) {
97         if (!validate())
98             return false;
99         close(_buttonActions[0]);
100         return true;
101     }
102 
103     private bool validate() {
104         if (!isValidModuleName(_fileName))
105             return setError("Invalid folder name");
106         return setError(null);
107     }
108 
109     private void updateValues(dstring fileName) {
110         _fileName = toUTF8(fileName);
111     }
112 
113     private bool setError(dstring msg) {
114         _statusText.text = msg;
115         return msg.empty;
116     }
117 
118     private {
119         EditLine _edFileName;
120         CheckBox _edMakePackage;
121         TextWidget _statusText;
122 
123         string _fileName = "newfile";
124         FileCreationResult _result;
125         bool shouldMakePackage() @property {
126             return _edMakePackage.checked;
127         }
128         string fullPathName() @property {
129             return buildNormalizedPath(_location, _fileName);
130         }
131     }
132 
133     private bool createItem() {
134         string fullPathName = this.fullPathName;
135         if(exists(fullPathName))
136             return setError("Folder already exists");
137 
138         if(!makeDirectory(fullPathName)) return false;
139         if(shouldMakePackage) {
140             if(!makePackageFile(fullPathName)) {
141                 return false;
142             }
143         }
144         _result = new FileCreationResult(_project, fullPathName);
145         return true;
146     }
147 
148     private bool makeDirectory(string fullPathName) {
149         try {
150             mkdir(fullPathName);
151             return true;
152         } catch (Exception e) {
153             Log.e("Cannot create folder", e);
154             return setError("Cannot create folder");
155         }
156     }
157 
158     private bool makePackageFile(string fullPathName) {
159         string packageName = getPackageName(fullPathName, _project.sourcePaths);
160         if(packageName.empty) {
161             Log.e("Could not determing package name for ", fullPathName);
162             return false;
163         }
164         if(!createFile(fullPathName.buildPath("package.d"), FileKind.PACKAGE, packageName, null)) {
165             Log.e("Could not create package file in folder ", fullPathName);
166             return false;
167         }
168         return true;
169     }
170 
171     override void close(const Action action) {
172         Action newaction = action.clone();
173         if (action.id == IDEActions.FileNewDirectory) {
174             if (!validate()) {
175                 window.showMessageBox(UIString.fromId("ERROR"c), UIString.fromId("ERROR_INVALID_PARAMETERS"c));
176                 return;
177             }
178             if (!createItem()) {
179                 window.showMessageBox(UIString.fromId("ERROR"c), UIString.fromId("ERROR_INVALID_PARAMETERS"c));
180                 return;
181             }
182             newaction.objectParam = _result;
183         }
184         super.close(newaction);
185     }
186 }