ide: workspace: (#882) save workspace file (.ews) in json format.
[sdk] / ide / src / dialogs / NewProjectDialog.ec
index 945bfa5..0918314 100644 (file)
 import "ide"
 
-FileDialog fileDialog { type = selectDir, text = "Select project directory" };
+FileDialog fileDialog { type = selectDir, text = $"Select project directory" };
 
 class NewProjectDialog : Window
 {
-   background = activeBorder;
+   background = formColor;
    minClientSize = { 316, 170 };
    maxClientSize = { 640, 170 };
    borderStyle = sizable;
    tabCycle = true;
    hasClose = true;
-   text = "New Project";
+   text = $"New Project";
 
    char path[MAX_LOCATION];
    char name[MAX_FILENAME];
 
+   Project project;
+   Workspace workspace;
+
+   char projectLocation[MAX_LOCATION];
+   bool createFormOption;
+
    PathBox locationEditBox
    {
       this, position = { 10, 80 }, size = { 120, 22 }, anchor = { left = 10, top = 80, right = 10 };
-      hotKey = altL, text = "Location";
+      hotKey = altL, text = $"Location";
       typeExpected = directory, browseDialog = fileDialog;
 
-      //NotifyUpdate = EditBoxUpdate;
-
-      bool NotifyModified(PathBox pathBox)
-      {
-         char location[MAX_LOCATION];
-         char lastPart[MAX_FILENAME];
-         char * text = pathBox.slashPath;
-         
-         //replacing this: NotifyUpdate = EditBoxUpdate;
-         okBtn.disabled = !(text[0] && projectName.contents[0]);
-
-         GetWorkingDir(location, sizeof(location) - 1);
-         PathCatSlash(location, text);
-         
-         GetLastDirectory(path, lastPart);
-         /*if(text[0] && (!name[0] || !strcmp(lastPart, name)))
-         {
-            char newName[MAX_FILENAME];
-            GetLastDirectory(location, newName);
-            if(strcmp(newName, location))
-            {
-               strcpy(name, newName);
-               projectName.contents = name;
-            }
-         }*/
-         strcpy(path, location);
-         pathBox.path = path;
-         return true;
-      }
+      NotifyModified = NotifyModifiedLocation;
    };
    Label { this, position = { 10, 60 }, labeledWindow = locationEditBox };
 
-   DropBox targetType { this, position = { 10, 130 }, size = { 130 }, hotKey = altT, text = "Target Type" };
+   DropBox targetType { this, position = { 10, 130 }, size = { 130 }, hotKey = altT, text = $"Target Type" };
 
    Label { this, position = { 10, 110 }, labeledWindow = targetType };
 
    Button okBtn
    {
-      parent = this, isDefault = true, disabled = true, position = { 170, 130 }, size = { 60 }, text = "OK";
+      parent = this, isDefault = true, disabled = true, position = { 170, 130 }, size = { 60 }, text = $"OK";
       bool NotifyClicked(Button button, int x, int y, Modifiers mods)
       {
-         char * location = locationEditBox.slashPath;
-         char * prjName = projectName.contents;
+         const char * prjName = projectName.contents;
          char filePath[MAX_LOCATION];
-         char fileName[MAX_LOCATION];  // Windows Friendly path
          char extension[MAX_EXTENSION];
-         FileAttribs exists;
-         Project project;
-         Workspace workspace;
-         ProjectView projectWindow;
          ProjectConfig debug, release;
-         
-         if(!FileExists(location).isDirectory)
-         {
-            if(MessageBox { type = yesNo, master = this, 
-                  text = "Directory doesn't exist", contents = "Create directory?" }.Modal() == yes)
-            {
-               if(!MakeDir(location))
-               {
-                  MessageBox { type = ok, master = this, text = location, contents = "Error creating directory" }.Modal();
-                  return true;
-               }
-            }
-            else
-               return true;
-         }
 
-         strcpy(filePath, location);
+         strcpy(projectLocation, locationEditBox.slashPath);
+         strcpy(filePath, projectLocation);
          PathCatSlash(filePath, prjName);
          GetExtension(filePath, extension);
          //if(!extension[0])
             ChangeExtension(filePath, ProjectExtension, filePath);
 
-         GetSystemPathBuffer(fileName, filePath);
-         exists = FileExists(filePath);
-
-         if(exists)
-         {
-            if(MessageBox { type = yesNo, master = this, 
-                  text = "Project Already Exists", contents = "Replace existing project?" }.Modal() == no)
-               return true;
-         }
-
          debug = ProjectConfig
          {
             name = CopyString("Debug");
-            options = 
+            options =
             {
                optimization = none;
+               fastMath = false;
                debug = true;
                preprocessorDefinitions = { [ CopyString("_DEBUG") ] };
             };
@@ -124,6 +73,7 @@ class NewProjectDialog : Window
             options =
             {
                optimization = speed;
+               fastMath = true;
                debug = false;
             };
             makingModified = true;
@@ -131,11 +81,11 @@ class NewProjectDialog : Window
             linkingModified = true;
          };
 
-         /* error: too few arguments to function ‘__ecereProp_DirExpression_Set_char__PTR_’ -- debug.objDir = "debug";*/ 
+         /* error: too few arguments to function ‘__ecereProp_DirExpression_Set_char__PTR_’ -- debug.objDir = "debug";*/
 
          project = Project
          {
-            filePath = filePath;
+            property::filePath = filePath;
             moduleName = CopyString(name);
             topNode.type = NodeTypes::project;
             config = debug;
@@ -145,110 +95,161 @@ class NewProjectDialog : Window
             warnings = all;
             // TOFIX: Precomp problems withou the extra ( )
             targetType = ((TargetTypes)targetType.GetTag());
-            targetFileName = CopyString(name);
+            targetFileName = /*CopyString(*/name/*)*/;
          };
-         if(project.targetType != staticLibrary)
+         if(project.options.targetType != staticLibrary)
          {
             project.options.libraries = { [ CopyString("ecere") ] };
          }
 
-         {
-            char workspaceFile[MAX_LOCATION];
-            strcpy(workspaceFile, filePath);
-            ChangeExtension(workspaceFile, WorkspaceExtension, workspaceFile);
-            workspace = Workspace { compiler = ideSettings.defaultCompiler, workspaceFile = workspaceFile };
-         } 
-         workspace.projects.Add(project);
-
-         project.topNode.configurations = project.configurations = { [ debug, release ] };
+         project.topNode.configurations = /*project.configurations = */{ [ debug, release ] };
          project.resNode = project.topNode.Add(project, "Resources", null, resources, archiveFile, false);
 
-         if(!project.Save(filePath))
-         {
-            MessageBox { type = ok, master = this, text = filePath, contents = "Error writing project file" }.Modal();
-            delete project;
-            return true;
-         }
+         createFormOption = createForm.checked;
 
-         projectWindow = ide.CreateProjectView(workspace, fileName);
-         
-         {
-            char newWorkingDir[MAX_LOCATION];
-            StripLastDirectory(filePath, newWorkingDir);
+         Destroy(DialogResult::ok);
+         return true;
+      }
+   };
 
-            ide.ChangeFileDialogsDirectory(newWorkingDir, false);
-            
-            StripLastDirectory(newWorkingDir, newWorkingDir);
-            ide.ChangeProjectFileDialogDirectory(newWorkingDir);
-         }
+   void CreateNewProject()
+   {
+      char fileName[MAX_LOCATION];  // Windows Friendly path
+      ProjectView projectWindow;
+      Project prj = project;
 
-         if(createForm.checked)
+      if(!FileExists(projectLocation).isDirectory)
+      {
+         if(MessageBox { type = yesNo, master = ide,
+               text = $"Directory doesn't exist", contents = $"Create directory?" }.Modal() == yes)
          {
-            char className[256];
-            char varName[256];
-            CodeEditor codeEditor = projectWindow.CreateNew("Form", "form", "Window", className);
-            EditBox editBox = codeEditor.editBox;
-            strcpy(varName, className);
-            if(islower(varName[0]))
+            if(!MakeDir(projectLocation))
             {
-               memmove(varName+1, varName, strlen(varName)+1);
-               varName[0] = '_';
+               MessageBox { type = ok, master = ide, text = projectLocation, contents = $"Error creating directory" }.Modal();
+               return;
             }
-            else
-               varName[0] = (char)tolower(varName[0]);
+         }
+         else
+            return;
+      }
 
-            editBox.End();
-            editBox.Printf("\n%s %s {};\n", className, varName);
+      GetSystemPathBuffer(fileName, prj.filePath);
 
-            codeEditor.EnsureUpToDate();
+      if(FileExists(prj.filePath))
+      {
+         if(MessageBox { type = yesNo, master = ide,
+               text = $"Project Already Exists", contents = $"Replace existing project?" }.Modal() == no)
+            return;
+      }
 
-            project.Save(filePath);
+      {
+         char workspaceFile[MAX_LOCATION];
+         strcpy(workspaceFile, prj.filePath);
+         ChangeExtension(workspaceFile, WorkspaceExtension, workspaceFile);
+         workspace = Workspace { activeCompiler = ideSettings.defaultCompiler, workspaceFile = workspaceFile };
+         workspace.Init();
+      }
+      workspace.AddProject(prj, null);
+      ide.findInFilesDialog.AddProjectItem(prj);
+      ide.findInFilesDialog.mode = FindInFilesMode::project;
+      ide.findInFilesDialog.currentDirectory = prj.topNode.path;
 
-            projectWindow.modifiedDocument = false;
-            project.topNode.modified = false;
+      if(!prj.Save(prj.filePath))
+      {
+         MessageBox { type = ok, master = this, text = prj.filePath, contents = $"Error writing project file" }.Modal();
+         delete prj;
+         return;
+      }
 
-            /*
-            editBox.Printf("class FormApplication : GuiApplication\n");
-            editBox.Printf("{\n");
-            editBox.Printf("   %s %s {};\n", className, varName);
-            editBox.Printf("}\n");
-            editBox.Home();
-            */
+      projectWindow = ide.CreateProjectView(workspace, fileName);
+
+      {
+         char newWorkingDir[MAX_LOCATION];
+         StripLastDirectory(prj.filePath, newWorkingDir);
+
+         ide.ChangeFileDialogsDirectory(newWorkingDir, false);
+
+         StripLastDirectory(newWorkingDir, newWorkingDir);
+         ide.ChangeProjectFileDialogDirectory(newWorkingDir);
+      }
+      ide.toolBox.visible = true;
+
+      if(createFormOption)
+      {
+         char className[256];
+         char varName[256];
+         CodeEditor codeEditor = projectWindow.CreateNew("Form", "form", "Window", className);
+         EditBox editBox = codeEditor.editBox;
+         strcpy(varName, className);
+         if(islower(varName[0]))
+         {
+            memmove(varName+1, varName, strlen(varName)+1);
+            varName[0] = '_';
          }
+         else
+            varName[0] = (char)tolower(varName[0]);
 
-         if(project && projectWindow)
-            projectWindow.ProjectPrepareMakefile(project, force, true, true);
+         editBox.End();
+         editBox.Printf("\n%s %s {};\n", className, varName);
 
-         Destroy(0);
-         return true;
+         codeEditor.EnsureUpToDate();
+
+         prj.Save(prj.filePath);
+
+         projectWindow.modifiedDocument = false;
+         prj.topNode.modified = false;
+
+         /*
+         editBox.Printf("class FormApplication : GuiApplication\n");
+         editBox.Printf("{\n");
+         editBox.Printf("   %s %s {};\n", className, varName);
+         editBox.Printf("}\n");
+         editBox.Home();
+         */
       }
-   };
-   
+      prj.StartMonitoring();
+
+      if(prj && projectWindow)
+      {
+         CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.activeCompiler);
+         ProjectConfig config = prj.config;
+         projectWindow.ShowOutputBuildLog(true);
+         projectWindow.DisplayCompiler(compiler, false);
+         projectWindow.ProjectPrepareCompiler(prj, compiler, false);
+         projectWindow.ProjectPrepareMakefile(prj, force, compiler, config);
+         delete compiler;
+
+         ide.UpdateToolBarActiveConfigs(false);
+      }
+   }
+
    Button
    {
-      parent = this, position = { 240, 130 }, size = { 60 }, hotKey = escape, text = "Cancel";
+      parent = this, position = { 240, 130 }, size = { 60 }, hotKey = escape, text = $"Cancel";
       NotifyClicked = ButtonCloseDialog;
    };
    Button createForm
    {
-      parent = this, text = "Create Form", hotKey = altF, position = { 200, 30 };
+      parent = this, text = $"Create Form", hotKey = altF, position = { 200, 30 };
       isCheckbox = true, checked = true;
    };
-   
+
    EditBox projectName
    {
       parent = this, textHorzScroll = true, position = { 10, 30 }, size = { 160 };
-      hotKey = altP, text = "Project Name";
+      hotKey = altP, text = $"Project Name";
       NotifyUpdate = EditBoxUpdate;
 
       bool NotifyModified(EditBox editBox)
       {
          char name[MAX_FILENAME];
+         char tmp[MAX_FILENAME];
          char lastPart[MAX_LOCATION];
-         char * text = editBox.contents;
+         const char * text = editBox.contents;
 
          // drop leading path stuff that has no business here
-         GetLastDirectory(text, name);
+         GetLastDirectory(text, tmp);
+         ValidProjectNameBufCopy(name, tmp);
 
          GetLastDirectory(path, lastPart);
          if(name[0] && (!strcmp(path, lastPart) || !path[0] || !strcmp(this.name, lastPart)))
@@ -281,14 +282,43 @@ class NewProjectDialog : Window
       okBtn.disabled = !(locationEditBox.path[0] && projectName.contents[0]);
    }
 
+   bool NotifyModifiedLocation(PathBox pathBox)
+   {
+      char location[MAX_LOCATION];
+      char lastPart[MAX_FILENAME];
+      char * text;
+
+      BasicValidatePathBoxPath(pathBox);
+
+      text = pathBox.slashPath;
+
+      //replacing this: NotifyUpdate = EditBoxUpdate;
+      okBtn.disabled = !(text[0] && projectName.contents[0]);
+
+      strcpy(location, ideSettings.ideProjectFileDialogLocation);
+      PathCatSlash(location, text);
+
+      GetLastDirectory(path, lastPart);
+      /*if(text[0] && (!name[0] || !strcmp(lastPart, name)))
+      {
+         char newName[MAX_FILENAME];
+         GetLastDirectory(location, newName);
+         if(strcmp(newName, location))
+         {
+            strcpy(name, newName);
+            projectName.contents = name;
+         }
+      }*/
+      strcpy(path, location);
+      pathBox.path = path;
+      return true;
+   }
+
    NewProjectDialog()
    {
       char location[MAX_LOCATION];
 
-      if(ideSettings.ideProjectFileDialogLocation)
-         strcpy(location, ideSettings.ideProjectFileDialogLocation);
-      else
-         GetWorkingDir(location, sizeof(location) - 1);
+      strcpy(location, ideSettings.ideProjectFileDialogLocation);
 
       locationEditBox.path = location;
       strcpy(path, location);
@@ -300,15 +330,15 @@ class NewProjectDialog : Window
 
          row = targetType.AddRow();
          row.tag = TargetTypes::executable;
-         row.SetData(null, "Executable");
+         row.SetData(null, $"Executable");
 
          row = targetType.AddRow();
          row.tag = TargetTypes::sharedLibrary;
-         row.SetData(null, "Shared Library");
+         row.SetData(null, $"Shared Library");
 
          row = targetType.AddRow();
          row.tag = TargetTypes::staticLibrary;
-         row.SetData(null, "Static Library");
+         row.SetData(null, $"Static Library");
 
          targetType.currentRow = targetType.FindRow(TargetTypes::executable);
       }
@@ -317,25 +347,25 @@ class NewProjectDialog : Window
 
 class QuickProjectDialog : Window
 {
-   background = activeBorder;
+   background = formColor;
    minClientSize = { 316, 110 };
    maxClientSize = { 640, 110 };
    borderStyle = sizable;
    tabCycle = true;
    hasClose = true;
-   text = "Quick Project";
+   text = $"Quick Project";
 
    char path[MAX_LOCATION];
    char name[MAX_FILENAME];
 
-   Label message { this, position = { 10, 10 }, size = { 200 }, text = "Do you want to quickly create a temporary project?" };
+   Label message { this, position = { 10, 10 }, text = $"Do you want to quickly create a temporary project?" };
 
-   DropBox targetType { this, position = { 10, 70 }, size = { 130 }, hotKey = altT, text = "Target Type" };
+   DropBox targetType { this, position = { 10, 70 }, size = { 130 }, hotKey = altT, text = $"Target Type" };
    Label { this, position = { 10, 50 }, labeledWindow = targetType };
 
    Button okBtn
    {
-      parent = this, isDefault = true, position = { 170, 70 }, size = { 60 }, text = "OK";
+      parent = this, isDefault = true, position = { 170, 70 }, size = { 60 }, text = $"OK";
       bool NotifyClicked(Button button, int x, int y, Modifiers mods)
       {
          char tempDir[MAX_LOCATION] = "";
@@ -361,10 +391,10 @@ class QuickProjectDialog : Window
 
          if(!FileExists(tempDir).isDirectory)
          {
-            MessageBox { type = ok, master = this, text = tempDir, contents = "Temporary directory does not exist." }.Modal();
+            MessageBox { type = ok, master = this, text = tempDir, contents = $"Temporary directory does not exist." }.Modal();
             return true;
          }
-         
+
          ide.tmpPrjDir = tempDir;
 
          strcpy(filePath, tempDir);
@@ -377,9 +407,10 @@ class QuickProjectDialog : Window
          debug = ProjectConfig
          {
             name = CopyString("Debug");
-            options = 
+            options =
             {
                optimization = none;
+               fastMath = false;
                debug = true;
                preprocessorDefinitions = { [ CopyString("_DEBUG") ] };
             };
@@ -394,6 +425,7 @@ class QuickProjectDialog : Window
             options =
             {
                optimization = speed;
+               fastMath = true;
                debug = false;
             };
             makingModified = true;
@@ -413,10 +445,10 @@ class QuickProjectDialog : Window
             warnings = all;
             // TOFIX: Precomp problems withou the extra ( )
             targetType = ((TargetTypes)targetType.GetTag());
-            targetFileName = CopyString(prjName);
+            targetFileName = /*CopyString(*/prjName/*)*/;
          };
 
-         if(project.targetType != staticLibrary)
+         if(project.options.targetType != staticLibrary)
          {
             project.options.libraries = { [ CopyString("ecere") ] };
          }
@@ -425,17 +457,22 @@ class QuickProjectDialog : Window
             char workspaceFile[MAX_LOCATION];
             strcpy(workspaceFile, filePath);
             ChangeExtension(workspaceFile, WorkspaceExtension, workspaceFile);
-            workspace = Workspace { compiler = ideSettings.defaultCompiler, workspaceFile = workspaceFile };
-         } 
+            workspace = Workspace { activeCompiler = ideSettings.defaultCompiler, workspaceFile = workspaceFile };
+         }
+
+         workspace.AddProject(project, null);
+         ide.findInFilesDialog.AddProjectItem(project);
+         ide.findInFilesDialog.mode = FindInFilesMode::project;
+         ide.findInFilesDialog.currentDirectory = project.topNode.path;
 
-         workspace.projects.Add(project);
+         // *** Don't set this directly on project, it must be set on top ProjectNode ***
+         project.topNode.configurations = { [ debug, release ] };
 
-         project.topNode.configurations = project.configurations = { [ debug, release ] };
          project.resNode = project.topNode.Add(project, "Resources", null, resources, archiveFile, false);
 
          if(!project.Save(filePath))
          {
-            MessageBox { type = ok, master = this, text = filePath, contents = "Error writing project file" }.Modal();
+            MessageBox { type = ok, master = this, text = filePath, contents = $"Error writing project file" }.Modal();
             delete project;
             delete workspace;
             ide.DestroyTemporaryProjectDir();
@@ -445,20 +482,45 @@ class QuickProjectDialog : Window
          projectWindow = ide.CreateProjectView(workspace, filePath);
 
          {
-            char extension[MAX_EXTENSION];
             Window document = null;
             for(document = ide.firstChild; document; document = document.next)
             {
-               char * fileName = document.fileName;
-               if(document.isDocument && document._class == class(CodeEditor) && document.created && fileName)
+               if(document.created && document.isDocument && document._class == class(CodeEditor))
                {
-                  CodeEditor codeEditor = (CodeEditor)document;
-                  ide.projectView.AddFile(project.topNode, fileName, false, false);
-                  codeEditor.DebugMenusDisabled();
+                  const char * fileName = document.fileName;
+                  if(strstr(fileName, "http://") == fileName)
+                  {
+                     char name[MAX_LOCATION];
+                     char newFileName[MAX_LOCATION];
+                     GetLastDirectory(fileName, name);
+                     strcpy(newFileName, tempDir);
+                     PathCat(newFileName, name);
+
+                     // TODO: this should be in Windows::SaveAs(char* asFileName)
+                     // start
+                     //document.saving = true;
+                     if(document.OnSaveFile(newFileName))
+                     {
+                        document.fileName = newFileName;
+                        document.NotifySaved(document.master, /*this*/document, newFileName);
+                     }
+                     //document.saving = false;
+                     // end
+                     // TODO else MessageBox unable to save and cancel the whole project creation thing
+                     fileName = document.fileName;
+                  }
+                  if(fileName)
+                  {
+                     CodeEditor codeEditor = (CodeEditor)document;
+                     ide.projectView.AddFile(project.topNode, fileName, false, false);
+                     codeEditor.AdjustDebugMenus();
+                  }
                }
             }
          }
 
+         ide.toolBox.visible = true;
+
          if(project.topNode.modified)
          {
             project.Save(filePath);
@@ -467,6 +529,7 @@ class QuickProjectDialog : Window
          }
          else
          {
+            // TOCHECK: Why is the Quick project creating a form???
             char className[256];
             char varName[256];
             CodeEditor codeEditor = projectWindow.CreateNew("Form", "form", "Window", className);
@@ -491,11 +554,20 @@ class QuickProjectDialog : Window
             projectWindow.modifiedDocument = false;
             project.topNode.modified = false;
          }
+         project.StartMonitoring();
 
          visible = false;
 
          if(project && projectWindow)
-            projectWindow.ProjectPrepareMakefile(project, force, true, true);
+         {
+            CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.activeCompiler);
+            ProjectConfig config = project.config;
+            projectWindow.ShowOutputBuildLog(true);
+            projectWindow.DisplayCompiler(compiler, false);
+            projectWindow.ProjectPrepareCompiler(project, compiler, false);
+            projectWindow.ProjectPrepareMakefile(project, force, compiler, config);
+            delete compiler;
+         }
 
          ide.projectView.ProjectBuild(null, Modifiers { });
 
@@ -503,29 +575,49 @@ class QuickProjectDialog : Window
          return true;
       }
    };
-   
+
    Button
    {
-      parent = this, position = { 240, 70 }, size = { 60 }, hotKey = escape, text = "Cancel";
+      parent = this, position = { 240, 70 }, size = { 60 }, hotKey = escape, text = $"Cancel";
       NotifyClicked = ButtonCloseDialog;
    };
-   
+
    QuickProjectDialog()
    {
       DataRow row;
 
       row = targetType.AddRow();
       row.tag = TargetTypes::executable;
-      row.SetData(null, "Executable");
+      row.SetData(null, $"Executable");
 
       row = targetType.AddRow();
       row.tag = TargetTypes::sharedLibrary;
-      row.SetData(null, "Shared Library");
+      row.SetData(null, $"Shared Library");
 
       row = targetType.AddRow();
       row.tag = TargetTypes::staticLibrary;
-      row.SetData(null, "Static Library");
+      row.SetData(null, $"Static Library");
 
       targetType.currentRow = targetType.FindRow(TargetTypes::executable);
    }
+
+   bool OnPostCreate()
+   {
+      okBtn.Activate();
+      return true;
+   }
+}
+
+void ValidProjectNameBufCopy(char *output, const char *input)
+{
+   strcpy(output, input);
+   TrimLSpaces(output, output);
+   TrimRSpaces(output, output);
+   {
+      // todo: support '&', '.' and ' ' in project name on windows so that it may be used by all platforms.
+      const char * chars = "*|:\",<>?\\/&. ";
+      char ch, * s = output, * o = output;
+      while((ch = *s++)) { if(!strchr(chars, ch)) *o++ = ch; }
+      *o = '\0';
+   }
 }