Add remaining files
[juce-lv2.git] / juce / source / extras / Introjucer / Source / Project / jucer_NewProjectWizard.cpp
blob14f60fb412273d6b98f61ee9e90fefdebf5f172e
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-10 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "jucer_NewProjectWizard.h"
29 //==============================================================================
30 class GUIAppWizard : public NewProjectWizard
32 public:
33 GUIAppWizard() {}
34 ~GUIAppWizard() {}
36 const String getName() { return "GUI Application"; }
37 const String getDescription() { return "Creates a standard application"; }
39 void addItemsToAlertWindow (AlertWindow& aw)
41 const char* fileOptions[] = { "Create a Main.cpp file",
42 "Create a Main.cpp file and a basic window",
43 "Don't create any files", 0 };
45 aw.addComboBox ("files", StringArray (fileOptions), "Files to Auto-Generate");
48 const String processResultsFromAlertWindow (AlertWindow& aw)
50 createMainCpp = createWindow = false;
52 switch (aw.getComboBoxComponent ("files")->getSelectedItemIndex())
54 case 0: createMainCpp = true; break;
55 case 1: createMainCpp = createWindow = true; break;
56 case 2: break;
57 default: jassertfalse; break;
60 return String::empty;
63 bool initialiseProject (Project& project)
65 if (! getSourceFilesFolder().createDirectory())
66 failedFiles.add (getSourceFilesFolder().getFullPathName());
68 File mainCppFile = getSourceFilesFolder().getChildFile ("Main.cpp");
69 File mainWindowCpp = getSourceFilesFolder().getChildFile ("MainWindow.cpp");
70 File mainWindowH = mainWindowCpp.withFileExtension (".h");
71 String windowClassName = "MainAppWindow";
73 project.getProjectType() = Project::application;
75 Project::Item group (project.createNewGroup());
76 project.getMainGroup().addChild (group, 0);
77 group.getName() = "Source";
79 for (int i = project.getNumConfigurations(); --i >= 0;)
80 project.getConfiguration(i).getTargetBinaryName() = File::createLegalFileName (appTitle);
82 String appHeaders (CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), mainCppFile));
83 String initCode, shutdownCode, anotherInstanceStartedCode, privateMembers, memberInitialisers;
85 if (createWindow)
87 appHeaders << newLine << CodeHelpers::createIncludeStatement (mainWindowH, mainCppFile);
88 initCode = "mainWindow = new " + windowClassName + "();";
89 shutdownCode = "mainWindow = 0;";
90 privateMembers = "ScopedPointer <" + windowClassName + "> mainWindow;";
92 String windowH = project.getFileTemplate ("jucer_WindowTemplate_h")
93 .replace ("INCLUDES", CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), mainWindowH), false)
94 .replace ("WINDOWCLASS", windowClassName, false)
95 .replace ("HEADERGUARD", CodeHelpers::makeHeaderGuardName (mainWindowH), false);
97 String windowCpp = project.getFileTemplate ("jucer_WindowTemplate_cpp")
98 .replace ("INCLUDES", CodeHelpers::createIncludeStatement (mainWindowH, mainWindowCpp), false)
99 .replace ("WINDOWCLASS", windowClassName, false);
101 if (! FileHelpers::overwriteFileWithNewDataIfDifferent (mainWindowH, windowH))
102 failedFiles.add (mainWindowH.getFullPathName());
104 if (! FileHelpers::overwriteFileWithNewDataIfDifferent (mainWindowCpp, windowCpp))
105 failedFiles.add (mainWindowCpp.getFullPathName());
107 group.addFile (mainWindowCpp, -1);
108 group.addFile (mainWindowH, -1);
111 if (createMainCpp)
113 String mainCpp = project.getFileTemplate ("jucer_MainTemplate_cpp")
114 .replace ("APPHEADERS", appHeaders, false)
115 .replace ("APPCLASSNAME", CodeHelpers::makeValidIdentifier (appTitle + "Application", false, true, false), false)
116 .replace ("MEMBERINITIALISERS", memberInitialisers, false)
117 .replace ("APPINITCODE", initCode, false)
118 .replace ("APPSHUTDOWNCODE", shutdownCode, false)
119 .replace ("APPNAME", CodeHelpers::addEscapeChars (appTitle), false)
120 .replace ("APPVERSION", "1.0", false)
121 .replace ("ALLOWMORETHANONEINSTANCE", "true", false)
122 .replace ("ANOTHERINSTANCECODE", anotherInstanceStartedCode, false)
123 .replace ("PRIVATEMEMBERS", privateMembers, false);
125 if (! FileHelpers::overwriteFileWithNewDataIfDifferent (mainCppFile, mainCpp))
126 failedFiles.add (mainCppFile.getFullPathName());
128 group.addFile (mainCppFile, -1);
131 return true;
134 private:
135 bool createMainCpp, createWindow;
138 //==============================================================================
139 class ConsoleAppWizard : public NewProjectWizard
141 public:
142 ConsoleAppWizard() {}
143 ~ConsoleAppWizard() {}
145 const String getName() { return "Console Application"; }
146 const String getDescription() { return "Creates a command-line application with no GUI features"; }
148 void addItemsToAlertWindow (AlertWindow& aw)
150 const char* fileOptions[] = { "Create a Main.cpp file",
151 "Don't create any files", 0 };
153 aw.addComboBox ("files", StringArray (fileOptions), "Files to Auto-Generate");
156 const String processResultsFromAlertWindow (AlertWindow& aw)
158 createMainCpp = false;
160 switch (aw.getComboBoxComponent ("files")->getSelectedItemIndex())
162 case 0: createMainCpp = true; break;
163 case 1: break;
164 default: jassertfalse; break;
167 return String::empty;
170 bool initialiseProject (Project& project)
172 if (! getSourceFilesFolder().createDirectory())
173 failedFiles.add (getSourceFilesFolder().getFullPathName());
175 File mainCppFile = getSourceFilesFolder().getChildFile ("Main.cpp");
177 project.getProjectType() = Project::commandLineApp;
179 Project::Item group (project.createNewGroup());
180 project.getMainGroup().addChild (group, 0);
181 group.getName() = "Source";
183 for (int i = project.getNumConfigurations(); --i >= 0;)
184 project.getConfiguration(i).getTargetBinaryName() = File::createLegalFileName (appTitle);
186 if (createMainCpp)
188 String appHeaders (CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), mainCppFile));
190 String mainCpp = project.getFileTemplate ("jucer_MainConsoleAppTemplate_cpp")
191 .replace ("APPHEADERS", appHeaders, false);
193 if (! FileHelpers::overwriteFileWithNewDataIfDifferent (mainCppFile, mainCpp))
194 failedFiles.add (mainCppFile.getFullPathName());
196 group.addFile (mainCppFile, -1);
199 return true;
202 private:
203 bool createMainCpp;
206 //==============================================================================
207 class AudioPluginAppWizard : public NewProjectWizard
209 public:
210 AudioPluginAppWizard() {}
211 ~AudioPluginAppWizard() {}
213 const String getName() { return "Audio Plug-In"; }
214 const String getDescription() { return "Creates an audio plugin project"; }
216 void addItemsToAlertWindow (AlertWindow& aw)
220 const String processResultsFromAlertWindow (AlertWindow& aw)
222 return String::empty;
225 bool initialiseProject (Project& project)
227 if (! getSourceFilesFolder().createDirectory())
228 failedFiles.add (getSourceFilesFolder().getFullPathName());
230 String filterClassName = CodeHelpers::makeValidIdentifier (appTitle, true, true, false) + "AudioProcessor";
231 filterClassName = filterClassName.substring (0, 1).toUpperCase() + filterClassName.substring (1);
232 String editorClassName = filterClassName + "Editor";
234 File filterCppFile = getSourceFilesFolder().getChildFile ("PluginProcessor.cpp");
235 File filterHFile = filterCppFile.withFileExtension (".h");
236 File editorCppFile = getSourceFilesFolder().getChildFile ("PluginEditor.cpp");
237 File editorHFile = editorCppFile.withFileExtension (".h");
239 project.getProjectType() = Project::audioPlugin;
241 Project::Item group (project.createNewGroup());
242 project.getMainGroup().addChild (group, 0);
243 group.getName() = "Source";
244 project.getJuceConfigFlag ("JUCE_QUICKTIME") = Project::configFlagDisabled; // disabled because it interferes with RTAS build on PC
246 for (int i = project.getNumConfigurations(); --i >= 0;)
247 project.getConfiguration(i).getTargetBinaryName() = File::createLegalFileName (appTitle);
249 String appHeaders (CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), filterCppFile));
250 appHeaders << newLine << CodeHelpers::createIncludeStatement (project.getPluginCharacteristicsFile(), filterCppFile);
252 String filterCpp = project.getFileTemplate ("jucer_AudioPluginFilterTemplate_cpp")
253 .replace ("FILTERHEADERS", CodeHelpers::createIncludeStatement (filterHFile, filterCppFile)
254 + newLine + CodeHelpers::createIncludeStatement (editorHFile, filterCppFile), false)
255 .replace ("FILTERCLASSNAME", filterClassName, false)
256 .replace ("EDITORCLASSNAME", editorClassName, false);
258 String filterH = project.getFileTemplate ("jucer_AudioPluginFilterTemplate_h")
259 .replace ("APPHEADERS", appHeaders, false)
260 .replace ("FILTERCLASSNAME", filterClassName, false)
261 .replace ("HEADERGUARD", CodeHelpers::makeHeaderGuardName (filterHFile), false);
263 String editorCpp = project.getFileTemplate ("jucer_AudioPluginEditorTemplate_cpp")
264 .replace ("EDITORCPPHEADERS", CodeHelpers::createIncludeStatement (filterHFile, filterCppFile)
265 + newLine + CodeHelpers::createIncludeStatement (editorHFile, filterCppFile), false)
266 .replace ("FILTERCLASSNAME", filterClassName, false)
267 .replace ("EDITORCLASSNAME", editorClassName, false);
269 String editorH = project.getFileTemplate ("jucer_AudioPluginEditorTemplate_h")
270 .replace ("EDITORHEADERS", appHeaders + newLine + CodeHelpers::createIncludeStatement (filterHFile, filterCppFile), false)
271 .replace ("FILTERCLASSNAME", filterClassName, false)
272 .replace ("EDITORCLASSNAME", editorClassName, false)
273 .replace ("HEADERGUARD", CodeHelpers::makeHeaderGuardName (editorHFile), false);
275 if (! FileHelpers::overwriteFileWithNewDataIfDifferent (filterCppFile, filterCpp))
276 failedFiles.add (filterCppFile.getFullPathName());
278 if (! FileHelpers::overwriteFileWithNewDataIfDifferent (filterHFile, filterH))
279 failedFiles.add (filterHFile.getFullPathName());
281 if (! FileHelpers::overwriteFileWithNewDataIfDifferent (editorCppFile, editorCpp))
282 failedFiles.add (editorCppFile.getFullPathName());
284 if (! FileHelpers::overwriteFileWithNewDataIfDifferent (editorHFile, editorH))
285 failedFiles.add (editorHFile.getFullPathName());
287 group.addFile (filterCppFile, -1);
288 group.addFile (filterHFile, -1);
289 group.addFile (editorCppFile, -1);
290 group.addFile (editorHFile, -1);
292 return true;
296 //==============================================================================
297 /*class BrowserPluginAppWizard : public NewProjectWizard
299 public:
300 BrowserPluginAppWizard() {}
301 ~BrowserPluginAppWizard() {}
303 const String getName() { return "Browser Plug-In"; }
304 const String getDescription() { return "Creates an audio plugin project"; }
306 void addItemsToAlertWindow (AlertWindow& aw)
310 const String processResultsFromAlertWindow (AlertWindow& aw)
312 return String::empty;
315 bool initialiseProject (Project& project)
317 return true;
319 };*/
321 //==============================================================================
322 //==============================================================================
323 NewProjectWizard::NewProjectWizard()
327 NewProjectWizard::~NewProjectWizard()
331 const StringArray NewProjectWizard::getWizards()
333 StringArray s;
335 for (int i = 0; i < getNumWizards(); ++i)
337 ScopedPointer <NewProjectWizard> wiz (createWizard (i));
338 s.add (wiz->getName());
341 return s;
344 int NewProjectWizard::getNumWizards()
346 return 3;
349 NewProjectWizard* NewProjectWizard::createWizard (int index)
351 switch (index)
353 case 0: return new GUIAppWizard();
354 case 1: return new ConsoleAppWizard();
355 case 2: return new AudioPluginAppWizard();
356 //case 3: return new BrowserPluginAppWizard();
357 default: jassertfalse; break;
360 return 0;
363 //==============================================================================
364 Project* NewProjectWizard::runWizard (Component* ownerWindow_)
366 ownerWindow = ownerWindow_;
369 static File newProjectFolder;
370 FileChooser fc ("New Juce Project", newProjectFolder, "*");
372 if (! fc.browseForDirectory())
373 return 0;
375 targetFolder = newProjectFolder = fc.getResult();
377 if (! newProjectFolder.exists())
379 if (! newProjectFolder.createDirectory())
380 failedFiles.add (newProjectFolder.getFullPathName());
383 if (FileHelpers::containsAnyNonHiddenFiles (newProjectFolder))
385 if (! AlertWindow::showOkCancelBox (AlertWindow::InfoIcon, "New Juce Project",
386 "The folder you chose isn't empty - are you sure you want to create the project there?\n\nAny existing files with the same names may be overwritten by the new files."))
387 return 0;
391 if (failedFiles.size() == 0)
393 AlertWindow aw ("New " + getName(),
394 "Please choose some basic project options...",
395 AlertWindow::NoIcon, ownerWindow);
397 aw.addTextEditor ("name", "", "Project Name", false);
399 addItemsToAlertWindow (aw);
401 aw.addButton ("Create Project", 1, KeyPress (KeyPress::returnKey));
402 aw.addButton ("Cancel", 0, KeyPress (KeyPress::escapeKey));
404 for (;;)
406 if (aw.runModalLoop() == 0)
407 return 0;
409 appTitle = aw.getTextEditorContents ("name").trim();
411 String error (processResultsFromAlertWindow (aw));
413 if (error.isEmpty() && appTitle.isEmpty())
414 error = "Please enter a sensible project title!";
416 if (error.isEmpty())
417 break;
419 aw.setColour (AlertWindow::textColourId, Colours::red);
420 aw.setMessage (error);
424 projectFile = targetFolder.getChildFile (File::createLegalFileName (appTitle))
425 .withFileExtension (Project::projectFileExtension);
427 ScopedPointer <Project> project (new Project (projectFile));
429 if (failedFiles.size() == 0)
431 project->setFile (projectFile);
432 project->setTitle (appTitle);
433 project->setBundleIdentifierToDefault();
435 if (! initialiseProject (*project))
436 return 0;
438 if (project->save (false, true) != FileBasedDocument::savedOk)
439 return 0;
441 project->setChangedFlag (false);
444 if (failedFiles.size() > 0)
446 AlertWindow::showMessageBox (AlertWindow::WarningIcon,
447 "Errors in Creating Project!",
448 "The following files couldn't be written:\n\n"
449 + failedFiles.joinIntoString ("\n", 0, 10));
450 return 0;
453 return project.release();
456 Project* NewProjectWizard::runNewProjectWizard (Component* ownerWindow)
458 ScopedPointer <NewProjectWizard> wizard;
461 AlertWindow aw ("New Juce Project",
462 "Select the type of project to create, and the location of your Juce folder",
463 AlertWindow::NoIcon,
464 ownerWindow);
466 aw.addComboBox ("type", getWizards(), "Project Type");
468 FilenameComponent juceFolderSelector ("Juce Library Location", StoredSettings::getInstance()->getLastKnownJuceFolder(),
469 true, true, false, "*", String::empty, "(Please select the folder containing Juce!)");
470 juceFolderSelector.setSize (350, 22);
472 aw.addCustomComponent (&juceFolderSelector);
474 aw.addButton ("Next", 1, KeyPress (KeyPress::returnKey));
475 aw.addButton ("Cancel", 0, KeyPress (KeyPress::escapeKey));
477 for (;;)
479 if (aw.runModalLoop() == 0)
480 return 0;
482 if (FileHelpers::isJuceFolder (juceFolderSelector.getCurrentFile()))
484 wizard = createWizard (aw.getComboBoxComponent ("type")->getSelectedItemIndex());
485 break;
488 aw.setColour (AlertWindow::textColourId, Colours::red);
489 aw.setMessage ("Please select a valid Juce folder for the project to use!");
493 return wizard != nullptr ? wizard->runWizard (ownerWindow) : 0;