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