/* ============================================================================== This file is part of the JUCE library - "Jules' Utility Class Extensions" Copyright 2004-11 by Raw Material Software Ltd. ------------------------------------------------------------------------------ JUCE can be redistributed and/or modified under the terms of the GNU General Public License (Version 2), as published by the Free Software Foundation. A copy of the license is included in the JUCE distribution, or can be found online at www.gnu.org/licenses. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ------------------------------------------------------------------------------ To release a closed-source product which uses JUCE, commercial licenses are available: visit www.rawmaterialsoftware.com/juce for more information. ============================================================================== */ #include "jucer_NewProjectWizard.h" #include "jucer_ProjectType.h" //============================================================================== class GUIAppWizard : public NewProjectWizard { public: GUIAppWizard() {} String getName() { return "GUI Application"; } String getDescription() { return "Creates a standard application"; } void addItemsToAlertWindow (AlertWindow& aw) { const char* fileOptions[] = { "Create a Main.cpp file", "Create a Main.cpp file and a basic window", "Don't create any files", 0 }; aw.addComboBox ("files", StringArray (fileOptions), "Files to Auto-Generate"); } String processResultsFromAlertWindow (AlertWindow& aw) { createMainCpp = createWindow = false; switch (aw.getComboBoxComponent ("files")->getSelectedItemIndex()) { case 0: createMainCpp = true; break; case 1: createMainCpp = createWindow = true; break; case 2: break; default: jassertfalse; break; } return String::empty; } bool initialiseProject (Project& project) { if (! getSourceFilesFolder().createDirectory()) failedFiles.add (getSourceFilesFolder().getFullPathName()); File mainCppFile = getSourceFilesFolder().getChildFile ("Main.cpp"); File mainWindowCpp = getSourceFilesFolder().getChildFile ("MainWindow.cpp"); File mainWindowH = mainWindowCpp.withFileExtension (".h"); String windowClassName = "MainAppWindow"; project.getProjectTypeValue() = ProjectType::getGUIAppTypeName(); Project::Item sourceGroup (project.getMainGroup().addNewSubGroup ("Source", 0)); for (int i = project.getNumConfigurations(); --i >= 0;) project.getConfiguration(i).getTargetBinaryName() = File::createLegalFileName (appTitle); String appHeaders (CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), mainCppFile)); String initCode, shutdownCode, anotherInstanceStartedCode, privateMembers, memberInitialisers; if (createWindow) { appHeaders << newLine << CodeHelpers::createIncludeStatement (mainWindowH, mainCppFile); initCode = "mainWindow = new " + windowClassName + "();"; shutdownCode = "mainWindow = 0;"; privateMembers = "ScopedPointer <" + windowClassName + "> mainWindow;"; String windowH = project.getFileTemplate ("jucer_WindowTemplate_h") .replace ("INCLUDES", CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), mainWindowH), false) .replace ("WINDOWCLASS", windowClassName, false) .replace ("HEADERGUARD", CodeHelpers::makeHeaderGuardName (mainWindowH), false); String windowCpp = project.getFileTemplate ("jucer_WindowTemplate_cpp") .replace ("INCLUDES", CodeHelpers::createIncludeStatement (mainWindowH, mainWindowCpp), false) .replace ("WINDOWCLASS", windowClassName, false); if (! FileHelpers::overwriteFileWithNewDataIfDifferent (mainWindowH, windowH)) failedFiles.add (mainWindowH.getFullPathName()); if (! FileHelpers::overwriteFileWithNewDataIfDifferent (mainWindowCpp, windowCpp)) failedFiles.add (mainWindowCpp.getFullPathName()); sourceGroup.addFile (mainWindowCpp, -1, true); sourceGroup.addFile (mainWindowH, -1, false); } if (createMainCpp) { String mainCpp = project.getFileTemplate ("jucer_MainTemplate_cpp") .replace ("APPHEADERS", appHeaders, false) .replace ("APPCLASSNAME", CodeHelpers::makeValidIdentifier (appTitle + "Application", false, true, false), false) .replace ("MEMBERINITIALISERS", memberInitialisers, false) .replace ("APPINITCODE", initCode, false) .replace ("APPSHUTDOWNCODE", shutdownCode, false) .replace ("APPNAME", CodeHelpers::addEscapeChars (appTitle), false) .replace ("APPVERSION", "1.0", false) .replace ("ALLOWMORETHANONEINSTANCE", "true", false) .replace ("ANOTHERINSTANCECODE", anotherInstanceStartedCode, false) .replace ("PRIVATEMEMBERS", privateMembers, false); if (! FileHelpers::overwriteFileWithNewDataIfDifferent (mainCppFile, mainCpp)) failedFiles.add (mainCppFile.getFullPathName()); sourceGroup.addFile (mainCppFile, -1, true); } return true; } private: bool createMainCpp, createWindow; }; //============================================================================== class ConsoleAppWizard : public NewProjectWizard { public: ConsoleAppWizard() {} String getName() { return "Console Application"; } String getDescription() { return "Creates a command-line application with no GUI features"; } void addItemsToAlertWindow (AlertWindow& aw) { const char* fileOptions[] = { "Create a Main.cpp file", "Don't create any files", 0 }; aw.addComboBox ("files", StringArray (fileOptions), "Files to Auto-Generate"); } String processResultsFromAlertWindow (AlertWindow& aw) { createMainCpp = false; switch (aw.getComboBoxComponent ("files")->getSelectedItemIndex()) { case 0: createMainCpp = true; break; case 1: break; default: jassertfalse; break; } return String::empty; } bool initialiseProject (Project& project) { if (! getSourceFilesFolder().createDirectory()) failedFiles.add (getSourceFilesFolder().getFullPathName()); File mainCppFile = getSourceFilesFolder().getChildFile ("Main.cpp"); project.getProjectTypeValue() = ProjectType::getConsoleAppTypeName(); Project::Item sourceGroup (project.getMainGroup().addNewSubGroup ("Source", 0)); for (int i = project.getNumConfigurations(); --i >= 0;) project.getConfiguration(i).getTargetBinaryName() = File::createLegalFileName (appTitle); if (createMainCpp) { String appHeaders (CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), mainCppFile)); String mainCpp = project.getFileTemplate ("jucer_MainConsoleAppTemplate_cpp") .replace ("APPHEADERS", appHeaders, false); if (! FileHelpers::overwriteFileWithNewDataIfDifferent (mainCppFile, mainCpp)) failedFiles.add (mainCppFile.getFullPathName()); sourceGroup.addFile (mainCppFile, -1, true); } return true; } private: bool createMainCpp; }; //============================================================================== class AudioPluginAppWizard : public NewProjectWizard { public: AudioPluginAppWizard() {} String getName() { return "Audio Plug-In"; } String getDescription() { return "Creates an audio plugin project"; } void addItemsToAlertWindow (AlertWindow& aw) { } String processResultsFromAlertWindow (AlertWindow& aw) { return String::empty; } bool initialiseProject (Project& project) { if (! getSourceFilesFolder().createDirectory()) failedFiles.add (getSourceFilesFolder().getFullPathName()); String filterClassName = CodeHelpers::makeValidIdentifier (appTitle, true, true, false) + "AudioProcessor"; filterClassName = filterClassName.substring (0, 1).toUpperCase() + filterClassName.substring (1); String editorClassName = filterClassName + "Editor"; File filterCppFile = getSourceFilesFolder().getChildFile ("PluginProcessor.cpp"); File filterHFile = filterCppFile.withFileExtension (".h"); File editorCppFile = getSourceFilesFolder().getChildFile ("PluginEditor.cpp"); File editorHFile = editorCppFile.withFileExtension (".h"); project.getProjectTypeValue() = ProjectType::getAudioPluginTypeName(); project.addModule ("juce_audio_plugin_client"); Project::Item sourceGroup (project.getMainGroup().addNewSubGroup ("Source", 0)); project.getConfigFlag ("JUCE_QUICKTIME") = Project::configFlagDisabled; // disabled because it interferes with RTAS build on PC for (int i = project.getNumConfigurations(); --i >= 0;) project.getConfiguration(i).getTargetBinaryName() = File::createLegalFileName (appTitle); String appHeaders (CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), filterCppFile)); String filterCpp = project.getFileTemplate ("jucer_AudioPluginFilterTemplate_cpp") .replace ("FILTERHEADERS", CodeHelpers::createIncludeStatement (filterHFile, filterCppFile) + newLine + CodeHelpers::createIncludeStatement (editorHFile, filterCppFile), false) .replace ("FILTERCLASSNAME", filterClassName, false) .replace ("EDITORCLASSNAME", editorClassName, false); String filterH = project.getFileTemplate ("jucer_AudioPluginFilterTemplate_h") .replace ("APPHEADERS", appHeaders, false) .replace ("FILTERCLASSNAME", filterClassName, false) .replace ("HEADERGUARD", CodeHelpers::makeHeaderGuardName (filterHFile), false); String editorCpp = project.getFileTemplate ("jucer_AudioPluginEditorTemplate_cpp") .replace ("EDITORCPPHEADERS", CodeHelpers::createIncludeStatement (filterHFile, filterCppFile) + newLine + CodeHelpers::createIncludeStatement (editorHFile, filterCppFile), false) .replace ("FILTERCLASSNAME", filterClassName, false) .replace ("EDITORCLASSNAME", editorClassName, false); String editorH = project.getFileTemplate ("jucer_AudioPluginEditorTemplate_h") .replace ("EDITORHEADERS", appHeaders + newLine + CodeHelpers::createIncludeStatement (filterHFile, filterCppFile), false) .replace ("FILTERCLASSNAME", filterClassName, false) .replace ("EDITORCLASSNAME", editorClassName, false) .replace ("HEADERGUARD", CodeHelpers::makeHeaderGuardName (editorHFile), false); if (! FileHelpers::overwriteFileWithNewDataIfDifferent (filterCppFile, filterCpp)) failedFiles.add (filterCppFile.getFullPathName()); if (! FileHelpers::overwriteFileWithNewDataIfDifferent (filterHFile, filterH)) failedFiles.add (filterHFile.getFullPathName()); if (! FileHelpers::overwriteFileWithNewDataIfDifferent (editorCppFile, editorCpp)) failedFiles.add (editorCppFile.getFullPathName()); if (! FileHelpers::overwriteFileWithNewDataIfDifferent (editorHFile, editorH)) failedFiles.add (editorHFile.getFullPathName()); sourceGroup.addFile (filterCppFile, -1, true); sourceGroup.addFile (filterHFile, -1, false); sourceGroup.addFile (editorCppFile, -1, true); sourceGroup.addFile (editorHFile, -1, false); return true; } }; //============================================================================== /*class BrowserPluginAppWizard : public NewProjectWizard { public: BrowserPluginAppWizard() {} ~BrowserPluginAppWizard() {} String getName() { return "Browser Plug-In"; } String getDescription() { return "Creates an audio plugin project"; } void addItemsToAlertWindow (AlertWindow& aw) { } String processResultsFromAlertWindow (AlertWindow& aw) { return String::empty; } bool initialiseProject (Project& project) { return true; } };*/ //============================================================================== //============================================================================== NewProjectWizard::NewProjectWizard() {} NewProjectWizard::~NewProjectWizard() {} StringArray NewProjectWizard::getWizards() { StringArray s; for (int i = 0; i < getNumWizards(); ++i) { ScopedPointer wiz (createWizard (i)); s.add (wiz->getName()); } return s; } int NewProjectWizard::getNumWizards() { return 3; } NewProjectWizard* NewProjectWizard::createWizard (int index) { switch (index) { case 0: return new GUIAppWizard(); case 1: return new ConsoleAppWizard(); case 2: return new AudioPluginAppWizard(); //case 3: return new BrowserPluginAppWizard(); default: jassertfalse; break; } return 0; } //============================================================================== Project* NewProjectWizard::runWizard (Component* ownerWindow_) { ownerWindow = ownerWindow_; { static File newProjectFolder; FileChooser fc ("New Juce Project", newProjectFolder, "*"); if (! fc.browseForDirectory()) return 0; targetFolder = newProjectFolder = fc.getResult(); if (! newProjectFolder.exists()) { if (! newProjectFolder.createDirectory()) failedFiles.add (newProjectFolder.getFullPathName()); } if (FileHelpers::containsAnyNonHiddenFiles (newProjectFolder)) { if (! AlertWindow::showOkCancelBox (AlertWindow::InfoIcon, "New Juce Project", "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.")) return 0; } } if (failedFiles.size() == 0) { AlertWindow aw ("New " + getName(), "Please choose some basic project options...", AlertWindow::NoIcon, ownerWindow); aw.addTextEditor ("name", "", "Project Name", false); addItemsToAlertWindow (aw); aw.addButton ("Create Project", 1, KeyPress (KeyPress::returnKey)); aw.addButton ("Cancel", 0, KeyPress (KeyPress::escapeKey)); for (;;) { if (aw.runModalLoop() == 0) return 0; appTitle = aw.getTextEditorContents ("name").trim(); String error (processResultsFromAlertWindow (aw)); if (error.isEmpty() && appTitle.isEmpty()) error = "Please enter a sensible project title!"; if (error.isEmpty()) break; aw.setColour (AlertWindow::textColourId, Colours::red); aw.setMessage (error); } } projectFile = targetFolder.getChildFile (File::createLegalFileName (appTitle)) .withFileExtension (Project::projectFileExtension); ScopedPointer project (new Project (projectFile)); if (failedFiles.size() == 0) { project->setFile (projectFile); project->setTitle (appTitle); project->setBundleIdentifierToDefault(); if (! initialiseProject (*project)) return 0; if (project->save (false, true) != FileBasedDocument::savedOk) return 0; project->setChangedFlag (false); } if (failedFiles.size() > 0) { AlertWindow::showMessageBox (AlertWindow::WarningIcon, "Errors in Creating Project!", "The following files couldn't be written:\n\n" + failedFiles.joinIntoString ("\n", 0, 10)); return 0; } return project.release(); } Project* NewProjectWizard::runNewProjectWizard (Component* ownerWindow) { ScopedPointer wizard; { AlertWindow aw ("New Juce Project", "Select the type of project to create, and the location of your Juce folder", AlertWindow::NoIcon, ownerWindow); aw.addComboBox ("type", getWizards(), "Project Type"); FilenameComponent juceFolderSelector ("Juce Library Location", StoredSettings::getInstance()->getLastKnownJuceFolder(), true, true, false, "*", String::empty, "(Please select the folder containing Juce!)"); juceFolderSelector.setSize (350, 22); aw.addCustomComponent (&juceFolderSelector); aw.addButton ("Next", 1, KeyPress (KeyPress::returnKey)); aw.addButton ("Cancel", 0, KeyPress (KeyPress::escapeKey)); for (;;) { if (aw.runModalLoop() == 0) return 0; if (FileHelpers::isJuceFolder (juceFolderSelector.getCurrentFile())) { wizard = createWizard (aw.getComboBoxComponent ("type")->getSelectedItemIndex()); break; } aw.setColour (AlertWindow::textColourId, Colours::red); aw.setMessage ("Please select a valid Juce folder for the project to use!"); } } return wizard != nullptr ? wizard->runWizard (ownerWindow) : 0; }