aab390575b78e985bab3c7d99bd13baac438627d
[sdk] / ide / src / dialogs / NewProjectDialog.ec
1 import "ide"
2
3 FileDialog fileDialog { type = selectDir, text = $"Select project directory" };
4
5 class NewProjectDialog : Window
6 {
7    background = formColor;
8    minClientSize = { 316, 170 };
9    maxClientSize = { 640, 170 };
10    borderStyle = sizable;
11    tabCycle = true;
12    hasClose = true;
13    text = $"New Project";
14
15    char path[MAX_LOCATION];
16    char name[MAX_FILENAME];
17
18    PathBox locationEditBox
19    {
20       this, position = { 10, 80 }, size = { 120, 22 }, anchor = { left = 10, top = 80, right = 10 };
21       hotKey = altL, text = $"Location";
22       typeExpected = directory, browseDialog = fileDialog;
23
24       NotifyModified = NotifyModifiedLocation;
25    };
26    Label { this, position = { 10, 60 }, labeledWindow = locationEditBox };
27
28    DropBox targetType { this, position = { 10, 130 }, size = { 130 }, hotKey = altT, text = $"Target Type" };
29
30    Label { this, position = { 10, 110 }, labeledWindow = targetType };
31
32    Button okBtn
33    {
34       parent = this, isDefault = true, disabled = true, position = { 170, 130 }, size = { 60 }, text = $"OK";
35       bool NotifyClicked(Button button, int x, int y, Modifiers mods)
36       {
37          char * location = locationEditBox.slashPath;
38          char * prjName = projectName.contents;
39          char filePath[MAX_LOCATION];
40          char fileName[MAX_LOCATION];  // Windows Friendly path
41          char extension[MAX_EXTENSION];
42          FileAttribs exists;
43          Project project;
44          Workspace workspace;
45          ProjectView projectWindow;
46          ProjectConfig debug, release;
47          
48          if(!FileExists(location).isDirectory)
49          {
50             if(MessageBox { type = yesNo, master = this, 
51                   text = $"Directory doesn't exist", contents = $"Create directory?" }.Modal() == yes)
52             {
53                if(!MakeDir(location))
54                {
55                   MessageBox { type = ok, master = this, text = location, contents = $"Error creating directory" }.Modal();
56                   return true;
57                }
58             }
59             else
60                return true;
61          }
62
63          strcpy(filePath, location);
64          PathCatSlash(filePath, prjName);
65          GetExtension(filePath, extension);
66          //if(!extension[0])
67             ChangeExtension(filePath, ProjectExtension, filePath);
68
69          GetSystemPathBuffer(fileName, filePath);
70          exists = FileExists(filePath);
71
72          if(exists)
73          {
74             if(MessageBox { type = yesNo, master = this, 
75                   text = $"Project Already Exists", contents = $"Replace existing project?" }.Modal() == no)
76                return true;
77          }
78
79          debug = ProjectConfig
80          {
81             name = CopyString("Debug");
82             options = 
83             {
84                optimization = none;
85                fastMath = false;
86                debug = true;
87                preprocessorDefinitions = { [ CopyString("_DEBUG") ] };
88             };
89             makingModified = true;
90             compilingModified = true;
91             linkingModified = true;
92          };
93
94          release = ProjectConfig
95          {
96             name = CopyString("Release");
97             options =
98             {
99                optimization = speed;
100                fastMath = true;
101                debug = false;
102             };
103             makingModified = true;
104             compilingModified = true;
105             linkingModified = true;
106          };
107
108          /* error: too few arguments to function ‘__ecereProp_DirExpression_Set_char__PTR_’ -- debug.objDir = "debug";*/ 
109
110          project = Project
111          {
112             filePath = filePath;
113             moduleName = CopyString(name);
114             topNode.type = NodeTypes::project;
115             config = debug;
116          };
117          /*project.topNode.options = */project.options =
118          {
119             warnings = all;
120             // TOFIX: Precomp problems withou the extra ( )
121             targetType = ((TargetTypes)targetType.GetTag());
122             targetFileName = /*CopyString(*/name/*)*/;
123          };
124          if(project.options.targetType != staticLibrary)
125          {
126             project.options.libraries = { [ CopyString("ecere") ] };
127          }
128
129          {
130             char workspaceFile[MAX_LOCATION];
131             strcpy(workspaceFile, filePath);
132             ChangeExtension(workspaceFile, WorkspaceExtension, workspaceFile);
133             workspace = Workspace { compiler = ideSettings.defaultCompiler, workspaceFile = workspaceFile };
134          } 
135          workspace.projects.Add(project);
136
137          project.topNode.configurations = /*project.configurations = */{ [ debug, release ] };
138          project.resNode = project.topNode.Add(project, "Resources", null, resources, archiveFile, false);
139
140          if(!project.Save(filePath))
141          {
142             MessageBox { type = ok, master = this, text = filePath, contents = $"Error writing project file" }.Modal();
143             delete project;
144             return true;
145          }
146
147          projectWindow = ide.CreateProjectView(workspace, fileName);
148          
149          {
150             char newWorkingDir[MAX_LOCATION];
151             StripLastDirectory(filePath, newWorkingDir);
152
153             ide.ChangeFileDialogsDirectory(newWorkingDir, false);
154             
155             StripLastDirectory(newWorkingDir, newWorkingDir);
156             ide.ChangeProjectFileDialogDirectory(newWorkingDir);
157          }
158
159          if(createForm.checked)
160          {
161             char className[256];
162             char varName[256];
163             CodeEditor codeEditor = projectWindow.CreateNew("Form", "form", "Window", className);
164             EditBox editBox = codeEditor.editBox;
165             strcpy(varName, className);
166             if(islower(varName[0]))
167             {
168                memmove(varName+1, varName, strlen(varName)+1);
169                varName[0] = '_';
170             }
171             else
172                varName[0] = (char)tolower(varName[0]);
173
174             editBox.End();
175             editBox.Printf("\n%s %s {};\n", className, varName);
176
177             codeEditor.EnsureUpToDate();
178
179             project.Save(filePath);
180
181             projectWindow.modifiedDocument = false;
182             project.topNode.modified = false;
183
184             /*
185             editBox.Printf("class FormApplication : GuiApplication\n");
186             editBox.Printf("{\n");
187             editBox.Printf("   %s %s {};\n", className, varName);
188             editBox.Printf("}\n");
189             editBox.Home();
190             */
191          }
192          project.StartMonitoring();
193
194          if(project && projectWindow)
195          {
196             CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
197             ProjectConfig config = project.config;
198             projectWindow.ShowOutputBuildLog(true);
199             projectWindow.DisplayCompiler(compiler, false);
200             projectWindow.ProjectPrepareCompiler(project, compiler);
201             projectWindow.ProjectPrepareMakefile(project, force, compiler, config);
202             delete compiler;
203
204             ide.UpdateToolBarActiveConfigs(false);
205          }
206
207          Destroy(0);
208          return true;
209       }
210    };
211    
212    Button
213    {
214       parent = this, position = { 240, 130 }, size = { 60 }, hotKey = escape, text = $"Cancel";
215       NotifyClicked = ButtonCloseDialog;
216    };
217    Button createForm
218    {
219       parent = this, text = $"Create Form", hotKey = altF, position = { 200, 30 };
220       isCheckbox = true, checked = true;
221    };
222    
223    EditBox projectName
224    {
225       parent = this, textHorzScroll = true, position = { 10, 30 }, size = { 160 };
226       hotKey = altP, text = $"Project Name";
227       NotifyUpdate = EditBoxUpdate;
228
229       bool NotifyModified(EditBox editBox)
230       {
231          char name[MAX_FILENAME];
232          char lastPart[MAX_LOCATION];
233          char * text = editBox.contents;
234
235          // drop leading path stuff that has no business here
236          GetLastDirectory(text, name);
237
238          GetLastDirectory(path, lastPart);
239          if(name[0] && (!strcmp(path, lastPart) || !path[0] || !strcmp(this.name, lastPart)))
240          {
241             if(strcmp(path, lastPart))
242                StripLastDirectory(path, path);
243             PathCatSlash(path, name);
244             locationEditBox.path = path;
245          }
246          else if(!name[0] && !strcmp(this.name, lastPart))
247          {
248             if(strcmp(path, lastPart))
249                StripLastDirectory(path, path);
250             locationEditBox.path = path;
251          }
252          else if(strcmp(name, lastPart))
253          {
254             PathCatSlash(path, name);
255             locationEditBox.path = path;
256          }
257          strcpy(this.name, name);
258          editBox.contents = name;
259          return true;
260       }
261    };
262    Label { this, position = { 10, 10 }, labeledWindow = projectName };
263
264    void EditBoxUpdate(EditBox editBox)
265    {
266       okBtn.disabled = !(locationEditBox.path[0] && projectName.contents[0]);
267    }
268
269    bool NotifyModifiedLocation(PathBox pathBox)
270    {
271       char location[MAX_LOCATION];
272       char lastPart[MAX_FILENAME];
273       char * text = pathBox.slashPath;
274
275       //replacing this: NotifyUpdate = EditBoxUpdate;
276       okBtn.disabled = !(text[0] && projectName.contents[0]);
277
278       GetWorkingDir(location, sizeof(location) - 1);
279       PathCatSlash(location, text);
280
281       GetLastDirectory(path, lastPart);
282       /*if(text[0] && (!name[0] || !strcmp(lastPart, name)))
283       {
284          char newName[MAX_FILENAME];
285          GetLastDirectory(location, newName);
286          if(strcmp(newName, location))
287          {
288             strcpy(name, newName);
289             projectName.contents = name;
290          }
291       }*/
292       strcpy(path, location);
293       pathBox.path = path;
294       return true;
295    }
296
297    NewProjectDialog()
298    {
299       char location[MAX_LOCATION];
300
301       if(ideSettings.ideProjectFileDialogLocation)
302          strcpy(location, ideSettings.ideProjectFileDialogLocation);
303       else
304          GetWorkingDir(location, sizeof(location) - 1);
305
306       locationEditBox.path = location;
307       strcpy(path, location);
308
309       {
310          DataRow row;
311
312          //targetType.AddField("String", null, 0);
313
314          row = targetType.AddRow();
315          row.tag = TargetTypes::executable;
316          row.SetData(null, $"Executable");
317
318          row = targetType.AddRow();
319          row.tag = TargetTypes::sharedLibrary;
320          row.SetData(null, $"Shared Library");
321
322          row = targetType.AddRow();
323          row.tag = TargetTypes::staticLibrary;
324          row.SetData(null, $"Static Library");
325
326          targetType.currentRow = targetType.FindRow(TargetTypes::executable);
327       }
328    }
329 }
330
331 class QuickProjectDialog : Window
332 {
333    background = formColor;
334    minClientSize = { 316, 110 };
335    maxClientSize = { 640, 110 };
336    borderStyle = sizable;
337    tabCycle = true;
338    hasClose = true;
339    text = $"Quick Project";
340
341    char path[MAX_LOCATION];
342    char name[MAX_FILENAME];
343
344    Label message { this, position = { 10, 10 }, text = $"Do you want to quickly create a temporary project?" };
345
346    DropBox targetType { this, position = { 10, 70 }, size = { 130 }, hotKey = altT, text = $"Target Type" };
347    Label { this, position = { 10, 50 }, labeledWindow = targetType };
348
349    Button okBtn
350    {
351       parent = this, isDefault = true, position = { 170, 70 }, size = { 60 }, text = $"OK";
352       bool NotifyClicked(Button button, int x, int y, Modifiers mods)
353       {
354          char tempDir[MAX_LOCATION] = "";
355          char filePath[MAX_LOCATION];
356          char prjName[MAX_LOCATION] = "quick_project";
357          Project project;
358          Workspace workspace;
359          ProjectView projectWindow;
360          ProjectConfig debug, release;
361
362          /*if(!*/CreateTemporaryDir(tempDir, "ecereide");/*)
363          {
364             MessageBox { type = ok, master = this, text = tempDir, contents = "Error creating temporary directory." }.Modal();
365             return true;
366          }*/
367
368          GetLastDirectory(tempDir, prjName);
369          {
370             char * dot;
371             if((dot = strstr(prjName, ".")))
372                dot[0] = '_';
373          }
374
375          if(!FileExists(tempDir).isDirectory)
376          {
377             MessageBox { type = ok, master = this, text = tempDir, contents = $"Temporary directory does not exist." }.Modal();
378             return true;
379          }
380          
381          ide.tmpPrjDir = tempDir;
382
383          strcpy(filePath, tempDir);
384          PathCatSlash(filePath, prjName);
385          //GetExtension(filePath, extension);
386          //if(!extension[0])
387             ChangeExtension(filePath, ProjectExtension, filePath);
388          GetSystemPathBuffer(filePath, filePath);
389
390          debug = ProjectConfig
391          {
392             name = CopyString("Debug");
393             options = 
394             {
395                optimization = none;
396                fastMath = false;
397                debug = true;
398                preprocessorDefinitions = { [ CopyString("_DEBUG") ] };
399             };
400             makingModified = true;
401             compilingModified = true;
402             linkingModified = true;
403          };
404
405          release = ProjectConfig
406          {
407             name = CopyString("Release");
408             options =
409             {
410                optimization = speed;
411                fastMath = true;
412                debug = false;
413             };
414             makingModified = true;
415             compilingModified = true;
416             linkingModified = true;
417          };
418
419          project = Project
420          {
421             filePath = filePath;
422             moduleName = CopyString(prjName);
423             topNode.type = NodeTypes::project;
424             config = debug;
425          };
426          /*project.topNode.options = */project.options =
427          {
428             warnings = all;
429             // TOFIX: Precomp problems withou the extra ( )
430             targetType = ((TargetTypes)targetType.GetTag());
431             targetFileName = /*CopyString(*/prjName/*)*/;
432          };
433
434          if(project.options.targetType != staticLibrary)
435          {
436             project.options.libraries = { [ CopyString("ecere") ] };
437          }
438
439          {
440             char workspaceFile[MAX_LOCATION];
441             strcpy(workspaceFile, filePath);
442             ChangeExtension(workspaceFile, WorkspaceExtension, workspaceFile);
443             workspace = Workspace { compiler = ideSettings.defaultCompiler, workspaceFile = workspaceFile };
444          } 
445
446          workspace.projects.Add(project);
447
448          // *** Don't set this directly on project, it must be set on top ProjectNode ***
449          project.topNode.configurations = { [ debug, release ] };
450
451          project.resNode = project.topNode.Add(project, "Resources", null, resources, archiveFile, false);
452
453          if(!project.Save(filePath))
454          {
455             MessageBox { type = ok, master = this, text = filePath, contents = $"Error writing project file" }.Modal();
456             delete project;
457             delete workspace;
458             ide.DestroyTemporaryProjectDir();
459             return true;
460          }
461
462          projectWindow = ide.CreateProjectView(workspace, filePath);
463
464          {
465             char extension[MAX_EXTENSION];
466             Window document = null;
467             for(document = ide.firstChild; document; document = document.next)
468             {
469                if(document.created && document.isDocument && document._class == class(CodeEditor))
470                {
471                   char * fileName = document.fileName;
472                   if(strstr(fileName, "http://") == fileName)
473                   {
474                      char name[MAX_LOCATION];
475                      char newFileName[MAX_LOCATION];
476                      GetLastDirectory(fileName, name);
477                      strcpy(newFileName, tempDir);
478                      PathCat(newFileName, name);
479
480                      // TODO: this should be in Windows::SaveAs(char* asFileName)
481                      // start
482                      //document.saving = true;
483                      if(document.OnSaveFile(newFileName))
484                      {
485                         document.fileName = newFileName;
486                         document.NotifySaved(document.master, /*this*/document, newFileName);
487                      }
488                      //document.saving = false;
489                      // end
490                      // TODO else MessageBox unable to save and cancel the whole project creation thing
491                      fileName = document.fileName;
492                   }
493                   if(fileName)
494                   {
495                      CodeEditor codeEditor = (CodeEditor)document;
496                      ide.projectView.AddFile(project.topNode, fileName, false, false);
497                      codeEditor.DebugMenusDisabled();
498                   }
499                }
500             }
501          }
502
503          if(project.topNode.modified)
504          {
505             project.Save(filePath);
506             projectWindow.modifiedDocument = false;
507             project.topNode.modified = false;
508          }
509          else
510          {
511             // TOCHECK: Why is the Quick project creating a form???
512             char className[256];
513             char varName[256];
514             CodeEditor codeEditor = projectWindow.CreateNew("Form", "form", "Window", className);
515             EditBox editBox = codeEditor.editBox;
516             strcpy(varName, className);
517             if(islower(varName[0]))
518             {
519                memmove(varName+1, varName, strlen(varName)+1);
520                varName[0] = '_';
521             }
522             else
523                varName[0] = (char)tolower(varName[0]);
524
525             editBox.End();
526             editBox.Printf("\n%s %s {};\n", className, varName);
527
528             codeEditor.EnsureUpToDate();
529
530             // TODO: how to save that new file?
531
532             project.Save(filePath);
533             projectWindow.modifiedDocument = false;
534             project.topNode.modified = false;
535          }
536          project.StartMonitoring();
537
538          visible = false;
539
540          if(project && projectWindow)
541          {
542             CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
543             ProjectConfig config = project.config;
544             projectWindow.ShowOutputBuildLog(true);
545             projectWindow.DisplayCompiler(compiler, false);
546             projectWindow.ProjectPrepareCompiler(project, compiler);
547             projectWindow.ProjectPrepareMakefile(project, force, compiler, config);
548             delete compiler;
549          }
550
551          ide.projectView.ProjectBuild(null, Modifiers { });
552
553          Destroy(0);
554          return true;
555       }
556    };
557    
558    Button
559    {
560       parent = this, position = { 240, 70 }, size = { 60 }, hotKey = escape, text = $"Cancel";
561       NotifyClicked = ButtonCloseDialog;
562    };
563    
564    QuickProjectDialog()
565    {
566       DataRow row;
567
568       row = targetType.AddRow();
569       row.tag = TargetTypes::executable;
570       row.SetData(null, $"Executable");
571
572       row = targetType.AddRow();
573       row.tag = TargetTypes::sharedLibrary;
574       row.SetData(null, $"Shared Library");
575
576       row = targetType.AddRow();
577       row.tag = TargetTypes::staticLibrary;
578       row.SetData(null, $"Static Library");
579
580       targetType.currentRow = targetType.FindRow(TargetTypes::executable);
581    }
582 }