- clean working copy for leaving SVN

This commit is contained in:
2022-06-28 19:04:46 +02:00
parent 62a2d47cb3
commit 762b8f0e7d
1966 changed files with 699872 additions and 126 deletions
@@ -0,0 +1,265 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found 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.juce.com for more information.
==============================================================================
*/
#include "jucer_NewFileWizard.h"
NewFileWizard::Type* createGUIComponentWizard();
//==============================================================================
namespace
{
static String fillInBasicTemplateFields (const File& file, const Project::Item& item, const char* templateName)
{
return item.project.getFileTemplate (templateName)
.replace ("FILENAME", file.getFileName(), false)
.replace ("DATE", Time::getCurrentTime().toString (true, true, true), false)
.replace ("AUTHOR", SystemStats::getFullUserName(), false)
.replace ("HEADERGUARD", CodeHelpers::makeHeaderGuardName (file), false)
.replace ("INCLUDE_CORRESPONDING_HEADER", CodeHelpers::createIncludeStatement (file.withFileExtension (".h"), file));
}
static bool fillInNewCppFileTemplate (const File& file, const Project::Item& item, const char* templateName)
{
return FileHelpers::overwriteFileWithNewDataIfDifferent (file, fillInBasicTemplateFields (file, item, templateName));
}
const int menuBaseID = 0x12d83f0;
}
//==============================================================================
class NewCppFileWizard : public NewFileWizard::Type
{
public:
NewCppFileWizard() {}
String getName() { return "CPP File"; }
void createNewFile (Project::Item parent)
{
const File newFile (askUserToChooseNewFile ("SourceCode.cpp", "*.cpp", parent));
if (newFile != File::nonexistent)
create (parent, newFile, "jucer_NewCppFileTemplate_cpp");
}
static bool create (Project::Item parent, const File& newFile, const char* templateName)
{
if (fillInNewCppFileTemplate (newFile, parent, templateName))
{
parent.addFile (newFile, 0, true);
return true;
}
showFailedToWriteMessage (newFile);
return false;
}
};
//==============================================================================
class NewHeaderFileWizard : public NewFileWizard::Type
{
public:
NewHeaderFileWizard() {}
String getName() { return "Header File"; }
void createNewFile (Project::Item parent)
{
const File newFile (askUserToChooseNewFile ("SourceCode.h", "*.h", parent));
if (newFile != File::nonexistent)
create (parent, newFile, "jucer_NewCppFileTemplate_h");
}
static bool create (Project::Item parent, const File& newFile, const char* templateName)
{
if (fillInNewCppFileTemplate (newFile, parent, templateName))
{
parent.addFile (newFile, 0, true);
return true;
}
showFailedToWriteMessage (newFile);
return false;
}
};
//==============================================================================
class NewCppAndHeaderFileWizard : public NewFileWizard::Type
{
public:
NewCppAndHeaderFileWizard() {}
String getName() { return "CPP & Header File"; }
void createNewFile (Project::Item parent)
{
const File newFile (askUserToChooseNewFile ("SourceCode.h", "*.h;*.cpp", parent));
if (newFile != File::nonexistent)
{
if (NewCppFileWizard::create (parent, newFile.withFileExtension ("h"), "jucer_NewCppFileTemplate_h"))
NewCppFileWizard::create (parent, newFile.withFileExtension ("cpp"), "jucer_NewCppFileTemplate_cpp");
}
}
};
//==============================================================================
class NewComponentFileWizard : public NewFileWizard::Type
{
public:
NewComponentFileWizard() {}
String getName() { return "Component class (split between a CPP & header)"; }
void createNewFile (Project::Item parent)
{
for (;;)
{
AlertWindow aw (TRANS ("Create new Component class"),
TRANS ("Please enter the name for the new class"),
AlertWindow::NoIcon, nullptr);
aw.addTextEditor (getClassNameFieldName(), String::empty, String::empty, false);
aw.addButton (TRANS ("Create Files"), 1, KeyPress (KeyPress::returnKey));
aw.addButton (TRANS ("Cancel"), 0, KeyPress (KeyPress::escapeKey));
if (aw.runModalLoop() == 0)
break;
const String className (aw.getTextEditorContents (getClassNameFieldName()).trim());
if (className == CodeHelpers::makeValidIdentifier (className, false, true, false))
{
const File newFile (askUserToChooseNewFile (className + ".h", "*.h;*.cpp", parent));
if (newFile != File::nonexistent)
createFiles (parent, className, newFile);
break;
}
}
}
static bool create (const String& className, Project::Item parent,
const File& newFile, const char* templateName)
{
String content = fillInBasicTemplateFields (newFile, parent, templateName)
.replace ("COMPONENTCLASS", className)
.replace ("INCLUDE_JUCE", CodeHelpers::createIncludeStatement (parent.project.getAppIncludeFile(), newFile));
if (FileHelpers::overwriteFileWithNewDataIfDifferent (newFile, content))
{
parent.addFile (newFile, 0, true);
return true;
}
showFailedToWriteMessage (newFile);
return false;
}
private:
virtual void createFiles (Project::Item parent, const String& className, const File& newFile)
{
if (create (className, parent, newFile.withFileExtension ("h"), "jucer_NewComponentTemplate_h"))
create (className, parent, newFile.withFileExtension ("cpp"), "jucer_NewComponentTemplate_cpp");
}
static String getClassNameFieldName() { return "Class Name"; }
};
//==============================================================================
class NewSingleFileComponentFileWizard : public NewComponentFileWizard
{
public:
NewSingleFileComponentFileWizard() {}
String getName() { return "Component class (in a single source file)"; }
void createFiles (Project::Item parent, const String& className, const File& newFile)
{
create (className, parent, newFile.withFileExtension ("h"), "jucer_NewInlineComponentTemplate_h");
}
};
//==============================================================================
void NewFileWizard::Type::showFailedToWriteMessage (const File& file)
{
AlertWindow::showMessageBox (AlertWindow::WarningIcon,
"Failed to Create File!",
"Couldn't write to the file: " + file.getFullPathName());
}
File NewFileWizard::Type::askUserToChooseNewFile (const String& suggestedFilename, const String& wildcard,
const Project::Item& projectGroupToAddTo)
{
FileChooser fc ("Select File to Create",
projectGroupToAddTo.determineGroupFolder()
.getChildFile (suggestedFilename)
.getNonexistentSibling(),
wildcard);
if (fc.browseForFileToSave (true))
return fc.getResult();
return File::nonexistent;
}
//==============================================================================
NewFileWizard::NewFileWizard()
{
registerWizard (new NewCppFileWizard());
registerWizard (new NewHeaderFileWizard());
registerWizard (new NewCppAndHeaderFileWizard());
registerWizard (new NewComponentFileWizard());
registerWizard (new NewSingleFileComponentFileWizard());
registerWizard (createGUIComponentWizard());
}
NewFileWizard::~NewFileWizard()
{
}
void NewFileWizard::addWizardsToMenu (PopupMenu& m) const
{
for (int i = 0; i < wizards.size(); ++i)
m.addItem (menuBaseID + i, "Add New " + wizards.getUnchecked(i)->getName() + "...");
}
bool NewFileWizard::runWizardFromMenu (int chosenMenuItemID, const Project::Item& projectGroupToAddTo) const
{
if (Type* wiz = wizards [chosenMenuItemID - menuBaseID])
{
wiz->createNewFile (projectGroupToAddTo);
return true;
}
return false;
}
void NewFileWizard::registerWizard (Type* newWizard)
{
wizards.add (newWizard);
}
@@ -0,0 +1,70 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found 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.juce.com for more information.
==============================================================================
*/
#ifndef __JUCER_NEWFILEWIZARD_JUCEHEADER__
#define __JUCER_NEWFILEWIZARD_JUCEHEADER__
#include "../jucer_Headers.h"
#include "../Project/jucer_Project.h"
//==============================================================================
class NewFileWizard
{
public:
//==============================================================================
NewFileWizard();
~NewFileWizard();
//==============================================================================
class Type
{
public:
Type() {}
virtual ~Type() {}
//==============================================================================
virtual String getName() = 0;
virtual void createNewFile (Project::Item projectGroupToAddTo) = 0;
protected:
//==============================================================================
File askUserToChooseNewFile (const String& suggestedFilename, const String& wildcard,
const Project::Item& projectGroupToAddTo);
static void showFailedToWriteMessage (const File& file);
};
//==============================================================================
void addWizardsToMenu (PopupMenu&) const;
bool runWizardFromMenu (int chosenMenuItemID, const Project::Item& projectGroupToAddTo) const;
void registerWizard (Type*);
private:
OwnedArray<Type> wizards;
};
#endif // __JUCER_NEWFILEWIZARD_JUCEHEADER__
@@ -0,0 +1,229 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found 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.juce.com for more information.
==============================================================================
*/
#ifndef JUCER_NEWPROJECTWIZARD_H_INCLUDED
#define JUCER_NEWPROJECTWIZARD_H_INCLUDED
//==============================================================================
static ComboBox& createFileCreationOptionComboBox (Component& setupComp,
OwnedArray<Component>& itemsCreated,
const StringArray& fileOptions)
{
ComboBox* c = new ComboBox();
itemsCreated.add (c);
setupComp.addChildAndSetID (c, "filesToCreate");
c->addItemList (fileOptions, 1);
c->setSelectedId (1, dontSendNotification);
Label* l = new Label (String::empty, TRANS("Files to Auto-Generate") + ":");
l->attachToComponent (c, true);
itemsCreated.add (l);
c->setBounds ("parent.width / 2 + 160, 30, parent.width - 30, top + 22");
return *c;
}
static int getFileCreationComboResult (WizardComp& setupComp)
{
if (ComboBox* cb = dynamic_cast<ComboBox*> (setupComp.findChildWithID ("filesToCreate")))
return cb->getSelectedItemIndex();
jassertfalse;
return 0;
}
static void setExecutableNameForAllTargets (Project& project, const String& exeName)
{
for (Project::ExporterIterator exporter (project); exporter.next();)
for (ProjectExporter::ConfigIterator config (*exporter); config.next();)
config->getTargetBinaryName() = exeName;
}
static Project::Item createSourceGroup (Project& project)
{
return project.getMainGroup().addNewSubGroup ("Source", 0);
}
static File& getLastWizardFolder()
{
#if JUCE_WINDOWS
static File lastFolder (File::getSpecialLocation (File::userDocumentsDirectory));
#else
static File lastFolder (File::getSpecialLocation (File::userHomeDirectory));
#endif
return lastFolder;
}
//==============================================================================
struct NewProjectWizard
{
NewProjectWizard() {}
virtual ~NewProjectWizard() {}
//==============================================================================
virtual String getName() const = 0;
virtual String getDescription() const = 0;
virtual const char* getIcon() const = 0;
virtual void addSetupItems (Component&, OwnedArray<Component>&) {}
virtual Result processResultsFromSetupItems (WizardComp&) { return Result::ok(); }
virtual bool initialiseProject (Project& project) = 0;
virtual StringArray getDefaultModules()
{
static const char* mods[] =
{
"juce_core",
"juce_events",
"juce_graphics",
"juce_data_structures",
"juce_gui_basics",
"juce_gui_extra",
"juce_cryptography",
"juce_video",
"juce_opengl",
"juce_audio_basics",
"juce_audio_devices",
"juce_audio_formats",
"juce_audio_processors",
nullptr
};
return StringArray (mods);
}
String appTitle;
File targetFolder, projectFile, modulesFolder;
WizardComp* ownerWizardComp;
StringArray failedFiles;
bool selectJuceFolder()
{
return ModulesFolderPathBox::selectJuceFolder (modulesFolder);
}
//==============================================================================
Project* runWizard (WizardComp& wc,
const String& projectName,
const File& target)
{
ownerWizardComp = &wc;
appTitle = projectName;
targetFolder = target;
if (! targetFolder.exists())
{
if (! targetFolder.createDirectory())
failedFiles.add (targetFolder.getFullPathName());
}
else if (FileHelpers::containsAnyNonHiddenFiles (targetFolder))
{
if (! AlertWindow::showOkCancelBox (AlertWindow::InfoIcon,
TRANS("New JUCE Project"),
TRANS("You chose the folder:\n\nXFLDRX\n\n").replace ("XFLDRX", targetFolder.getFullPathName())
+ TRANS("This folder isn't empty - are you sure you want to create the project there?")
+ "\n\n"
+ TRANS("Any existing files with the same names may be overwritten by the new files.")))
return nullptr;
}
projectFile = targetFolder.getChildFile (File::createLegalFileName (appTitle))
.withFileExtension (Project::projectFileExtension);
ScopedPointer<Project> project (new Project (projectFile));
if (failedFiles.size() == 0)
{
project->setFile (projectFile);
project->setTitle (appTitle);
project->getBundleIdentifier() = project->getDefaultBundleIdentifier();
if (! initialiseProject (*project))
return nullptr;
addExporters (*project, wc);
addDefaultModules (*project, false);
if (project->save (false, true) != FileBasedDocument::savedOk)
return nullptr;
project->setChangedFlag (false);
}
if (failedFiles.size() > 0)
{
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
TRANS("Errors in Creating Project!"),
TRANS("The following files couldn't be written:")
+ "\n\n"
+ failedFiles.joinIntoString ("\n", 0, 10));
return nullptr;
}
return project.release();
}
//==============================================================================
File getSourceFilesFolder() const
{
return projectFile.getSiblingFile ("Source");
}
void createSourceFolder()
{
if (! getSourceFilesFolder().createDirectory())
failedFiles.add (getSourceFilesFolder().getFullPathName());
}
void addDefaultModules (Project& project, bool areModulesCopiedLocally)
{
StringArray mods (getDefaultModules());
ModuleList list;
list.addAllModulesInFolder (modulesFolder);
for (int i = 0; i < mods.size(); ++i)
if (const ModuleDescription* info = list.getModuleWithID (mods[i]))
project.getModules().addModule (info->manifestFile, areModulesCopiedLocally);
}
void addExporters (Project& project, WizardComp& wizardComp)
{
StringArray types (wizardComp.platformTargets.getSelectedPlatforms());
for (int i = 0; i < types.size(); ++i)
project.addNewExporter (types[i]);
if (project.getNumExporters() == 0)
project.createExporterForCurrentPlatform();
}
};
#endif // JUCER_NEWPROJECTWIZARD_H_INCLUDED
@@ -0,0 +1,95 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found 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.juce.com for more information.
==============================================================================
*/
#include "../jucer_Headers.h"
#include "jucer_NewProjectWizardClasses.h"
#include "../Project/jucer_ProjectType.h"
#include "../Project/jucer_Module.h"
#include "../Project Saving/jucer_ProjectExporter.h"
#include "../Application/jucer_Application.h"
#include "../Application/jucer_MainWindow.h"
#include "../Utility/jucer_SlidingPanelComponent.h"
struct NewProjectWizardClasses
{
class WizardComp;
#include "jucer_NewProjectWizard.h"
#include "jucer_ProjectWizard_GUIApp.h"
#include "jucer_ProjectWizard_Console.h"
#include "jucer_ProjectWizard_AudioPlugin.h"
#include "jucer_ProjectWizard_StaticLibrary.h"
#include "jucer_ProjectWizard_DLL.h"
#include "jucer_ProjectWizard_openGL.h"
#include "jucer_ProjectWizard_Animated.h"
#include "jucer_ProjectWizard_AudioApp.h"
#include "jucer_ProjectWizard_Blank.h"
#include "jucer_NewProjectWizardComponent.h"
#include "jucer_TemplateThumbnailsComponent.h"
#include "jucer_StartPageComponent.h"
//==============================================================================
static int getNumWizards() noexcept
{
return 9;
}
static NewProjectWizard* createWizardType (int index)
{
switch (index)
{
case 0: return new NewProjectWizardClasses::GUIAppWizard();
case 1: return new NewProjectWizardClasses::AnimatedAppWizard();
case 2: return new NewProjectWizardClasses::OpenGLAppWizard();
case 3: return new NewProjectWizardClasses::ConsoleAppWizard();
case 4: return new NewProjectWizardClasses::AudioAppWizard();
case 5: return new NewProjectWizardClasses::AudioPluginAppWizard();
case 6: return new NewProjectWizardClasses::StaticLibraryWizard();
case 7: return new NewProjectWizardClasses::DynamicLibraryWizard();
case 8: return new NewProjectWizardClasses::BlankAppWizard();
default: jassertfalse; break;
}
return nullptr;
}
static StringArray getWizardNames()
{
StringArray s;
for (int i = 0; i < getNumWizards(); ++i)
{
ScopedPointer<NewProjectWizard> wiz (createWizardType (i));
s.add (wiz->getName());
}
return s;
}
};
Component* createNewProjectWizardComponent()
{
return new NewProjectWizardClasses::StartPageComponent();
}
@@ -0,0 +1,26 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found 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.juce.com for more information.
==============================================================================
*/
Component* createNewProjectWizardComponent();
@@ -0,0 +1,437 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found 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.juce.com for more information.
==============================================================================
*/
#ifndef NEWPROJECTWIZARDCOMPONENTS_H_INCLUDED
#define NEWPROJECTWIZARDCOMPONENTS_H_INCLUDED
class ModulesFolderPathBox : public Component,
private ButtonListener,
private ComboBoxListener
{
public:
ModulesFolderPathBox (File initialFileOrDirectory)
: currentPathBox ("currentPathBox"),
openFolderButton (TRANS("...")),
modulesLabel (String::empty, TRANS("Modules Folder") + ":")
{
if (initialFileOrDirectory == File::nonexistent)
initialFileOrDirectory = findDefaultModulesFolder();
setModulesFolder (initialFileOrDirectory);
addAndMakeVisible (currentPathBox);
currentPathBox.setEditableText (true);
currentPathBox.addListener (this);
addAndMakeVisible (openFolderButton);
openFolderButton.addListener (this);
openFolderButton.setTooltip (TRANS ("Select JUCE modules folder"));
addAndMakeVisible (modulesLabel);
modulesLabel.attachToComponent (&currentPathBox, true);
}
void resized() override
{
Rectangle<int> bounds = getLocalBounds();
modulesLabel.setBounds (bounds.removeFromLeft (110));
openFolderButton.setBounds (bounds.removeFromRight (40));
bounds.removeFromRight (5);
currentPathBox.setBounds (bounds);
}
static bool selectJuceFolder (File& result)
{
for (;;)
{
FileChooser fc ("Select your JUCE modules folder...",
findDefaultModulesFolder(),
"*");
if (! fc.browseForDirectory())
return false;
if (isJuceModulesFolder (fc.getResult()))
{
result = fc.getResult();
return true;
}
AlertWindow::showMessageBox (AlertWindow::WarningIcon,
"Not a valid JUCE modules folder!",
"Please select the folder containing your juce_* modules!\n\n"
"This is required so that the new project can be given some essential core modules.");
}
}
void selectJuceFolder()
{
File result;
if (selectJuceFolder (result))
setModulesFolder (result);
}
void setModulesFolder (const File& newFolder)
{
if (modulesFolder != newFolder)
{
modulesFolder = newFolder;
currentPathBox.setText (modulesFolder.getFullPathName(), dontSendNotification);
}
}
void buttonClicked (Button*) override
{
selectJuceFolder();
}
void comboBoxChanged (ComboBox*) override
{
setModulesFolder (File::getCurrentWorkingDirectory().getChildFile (currentPathBox.getText()));
}
File modulesFolder;
private:
ComboBox currentPathBox;
TextButton openFolderButton;
Label modulesLabel;
};
/** The target platforms chooser for the chosen template. */
class PlatformTargetsComp : public Component,
private ListBoxModel
{
public:
PlatformTargetsComp()
{
setOpaque (false);
const Array<ProjectExporter::ExporterTypeInfo> types (ProjectExporter::getExporterTypes());
for (int i = 0; i < types.size(); ++i)
{
const ProjectExporter::ExporterTypeInfo& type = types.getReference (i);
platforms.add (new PlatformType (ImageCache::getFromMemory (type.iconData, type.iconDataSize), type.name));
}
listBox.setRowHeight (35);
listBox.setModel (this);
listBox.setOpaque (false);
listBox.setMultipleSelectionEnabled (true);
listBox.setClickingTogglesRowSelection (true);
listBox.setColour (ListBox::backgroundColourId, Colours::white.withAlpha (0.0f));
addAndMakeVisible (listBox);
selectDefaultExporterIfNoneSelected();
}
StringArray getSelectedPlatforms() const
{
StringArray list;
for (int i = 0; i < platforms.size(); ++i)
if (listBox.isRowSelected (i))
list.add (platforms.getUnchecked(i)->name);
return list;
}
void selectDefaultExporterIfNoneSelected()
{
if (listBox.getNumSelectedRows() == 0)
{
for (int i = platforms.size(); --i >= 0;)
{
if (platforms.getUnchecked(i)->name == ProjectExporter::getCurrentPlatformExporterName())
{
listBox.selectRow (i);
break;
}
}
}
}
void resized() override
{
listBox.setBounds (getLocalBounds());
}
int getNumRows() override
{
return platforms.size();
}
void paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected) override
{
if (PlatformType* platform = platforms[rowNumber])
{
if (rowIsSelected)
g.fillAll (Colour (0x99f29000));
Rectangle<float> dotSelect ((float) height, (float) height);
dotSelect.reduce (12, 12);
g.setColour (Colour (0x33ffffff));
g.fillEllipse (dotSelect);
if (rowIsSelected)
{
const float tx = dotSelect.getCentreX();
const float ty = dotSelect.getCentreY() + 1.0f;
Path tick;
tick.startNewSubPath (tx - 5.0f, ty - 6.0f);
tick.lineTo (tx, ty);
tick.lineTo (tx + 8.0f, ty - 13.0f);
g.setColour (Colours::white);
g.strokePath (tick, PathStrokeType (3.0f));
}
g.setColour (Colours::black);
g.drawImageWithin (platform->icon, 40, 0, height, height, RectanglePlacement::stretchToFit);
g.drawText (platform->name, 90, 0, width, height, Justification::left);
}
}
void selectedRowsChanged (int) override
{
selectDefaultExporterIfNoneSelected();
}
private:
struct PlatformType
{
PlatformType (const Image& platformIcon, const String& platformName)
: icon (platformIcon), name (platformName)
{
}
Image icon;
String name;
};
ListBox listBox;
OwnedArray<PlatformType> platforms;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PlatformTargetsComp)
};
//==============================================================================
/**
The Component for project creation.
Features a file browser to select project destination and
a list box of platform targets to generate.
*/
class WizardComp : public Component,
private ButtonListener,
private ComboBoxListener,
private TextEditorListener
{
public:
WizardComp()
: platformTargets(),
projectName (TRANS("Project name")),
nameLabel (String::empty, TRANS("Project Name") + ":"),
typeLabel (String::empty, TRANS("Project Type") + ":"),
fileBrowser (FileBrowserComponent::saveMode | FileBrowserComponent::canSelectDirectories,
NewProjectWizardClasses::getLastWizardFolder(), nullptr, nullptr),
fileOutline (String::empty, TRANS("Project Folder") + ":"),
targetsOutline (String::empty, TRANS("Target Platforms") + ":"),
createButton (TRANS("Create") + "..."),
cancelButton (TRANS("Cancel")),
modulesPathBox (findDefaultModulesFolder())
{
setOpaque (false);
addChildAndSetID (&projectName, "projectName");
projectName.setText ("NewProject");
projectName.setBounds ("120, 34, parent.width / 2 - 10, top + 22");
nameLabel.attachToComponent (&projectName, true);
projectName.addListener (this);
addChildAndSetID (&projectType, "projectType");
projectType.addItemList (getWizardNames(), 1);
projectType.setSelectedId (1, dontSendNotification);
projectType.setBounds ("120, projectName.bottom + 4, projectName.right, top + 22");
typeLabel.attachToComponent (&projectType, true);
projectType.addListener (this);
addChildAndSetID (&fileOutline, "fileOutline");
fileOutline.setColour (GroupComponent::outlineColourId, Colours::black.withAlpha (0.2f));
fileOutline.setTextLabelPosition (Justification::centred);
fileOutline.setBounds ("30, projectType.bottom + 20, projectType.right, parent.height - 30");
addChildAndSetID (&targetsOutline, "targetsOutline");
targetsOutline.setColour (GroupComponent::outlineColourId, Colours::black.withAlpha (0.2f));
targetsOutline.setTextLabelPosition (Justification::centred);
targetsOutline.setBounds ("fileOutline.right + 20, projectType.bottom + 20, parent.width - 30, parent.height - 70");
addChildAndSetID (&platformTargets, "platformTargets");
platformTargets.setBounds ("targetsOutline.left + 15, projectType.bottom + 45, parent.width - 40, parent.height - 90");
addChildAndSetID (&fileBrowser, "fileBrowser");
fileBrowser.setBounds ("fileOutline.left + 10, fileOutline.top + 20, fileOutline.right - 10, fileOutline.bottom - 32");
fileBrowser.setFilenameBoxLabel ("Folder:");
addChildAndSetID (&createButton, "createButton");
createButton.setBounds ("right - 130, bottom - 34, parent.width - 30, parent.height - 30");
createButton.addListener (this);
addChildAndSetID (&cancelButton, "cancelButton");
cancelButton.addShortcut (KeyPress (KeyPress::escapeKey));
cancelButton.setBounds ("right - 130, createButton.top, createButton.left - 10, createButton.bottom");
cancelButton.addListener (this);
addChildAndSetID (&modulesPathBox, "modulesPathBox");
modulesPathBox.setBounds ("targetsOutline.left, targetsOutline.top - 45, targetsOutline.right, targetsOutline.top - 20");
updateCustomItems();
updateCreateButton();
}
void paint (Graphics& g) override
{
Rectangle<int> rect = getLocalBounds().reduced (10, 10);
g.setColour (Colours::white.withAlpha (0.3f));
g.fillRect (rect);
g.fillRect (rect.reduced (10, 10));
}
void buttonClicked (Button* b) override
{
if (b == &createButton)
{
createProject();
}
else if (b == &cancelButton)
{
returnToTemplatesPage();
}
}
void returnToTemplatesPage()
{
if (SlidingPanelComponent* parent = findParentComponentOfClass<SlidingPanelComponent>())
{
if (parent->getNumTabs() > 0)
parent->goToTab (parent->getCurrentTabIndex() - 1);
}
else
{
jassertfalse;
}
}
void createProject()
{
MainWindow* mw = Component::findParentComponentOfClass<MainWindow>();
jassert (mw != nullptr);
ScopedPointer<NewProjectWizardClasses::NewProjectWizard> wizard (createWizard());
if (wizard != nullptr)
{
Result result (wizard->processResultsFromSetupItems (*this));
if (result.failed())
{
AlertWindow::showMessageBox (AlertWindow::WarningIcon,
TRANS("Create Project"),
result.getErrorMessage());
return;
}
wizard->modulesFolder = modulesPathBox.modulesFolder;
if (! isJuceModulesFolder (wizard->modulesFolder))
if (! wizard->selectJuceFolder())
return;
ScopedPointer<Project> project (wizard->runWizard (*this, projectName.getText(),
fileBrowser.getSelectedFile (0)));
if (project != nullptr)
mw->setProject (project.release());
}
}
void updateCustomItems()
{
customItems.clear();
ScopedPointer<NewProjectWizardClasses::NewProjectWizard> wizard (createWizard());
if (wizard != nullptr)
wizard->addSetupItems (*this, customItems);
}
void comboBoxChanged (ComboBox*) override
{
updateCustomItems();
}
void textEditorTextChanged (TextEditor&) override
{
updateCreateButton();
fileBrowser.setFileName (File::createLegalFileName (projectName.getText()));
}
ComboBox projectType;
PlatformTargetsComp platformTargets;
private:
TextEditor projectName;
Label nameLabel, typeLabel;
FileBrowserComponent fileBrowser;
GroupComponent fileOutline;
GroupComponent targetsOutline;
TextButton createButton, cancelButton;
OwnedArray<Component> customItems;
ModulesFolderPathBox modulesPathBox;
NewProjectWizardClasses::NewProjectWizard* createWizard()
{
return createWizardType (projectType.getSelectedItemIndex());
}
void updateCreateButton()
{
createButton.setEnabled (projectName.getText().trim().isNotEmpty());
}
};
#endif // NEWPROJECTWIZARDCOMPONENTS_H_INCLUDED
@@ -0,0 +1,78 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found 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.juce.com for more information.
==============================================================================
*/
struct AnimatedAppWizard : public NewProjectWizard
{
AnimatedAppWizard() {}
String getName() const override { return TRANS("Animated Application"); }
String getDescription() const override { return TRANS("Creates an application which draws an animated graphical display."); }
const char* getIcon() const override { return BinaryData::wizard_AnimatedApp_svg; }
bool initialiseProject (Project& project) override
{
createSourceFolder();
File mainCppFile = getSourceFilesFolder().getChildFile ("Main.cpp");
File contentCompCpp = getSourceFilesFolder().getChildFile ("MainComponent.cpp");
File contentCompH = contentCompCpp.withFileExtension (".h");
String contentCompName = "MainContentComponent";
project.getProjectTypeValue() = ProjectType::getGUIAppTypeName();
Project::Item sourceGroup (createSourceGroup (project));
setExecutableNameForAllTargets (project, File::createLegalFileName (appTitle));
String appHeaders (CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), mainCppFile));
// create main window
String windowCpp = project.getFileTemplate ("jucer_AnimatedComponentTemplate_cpp")
.replace ("INCLUDE_JUCE", CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), contentCompCpp), false);
if (! FileHelpers::overwriteFileWithNewDataIfDifferent (contentCompCpp, windowCpp))
failedFiles.add (contentCompCpp.getFullPathName());
sourceGroup.addFile (contentCompCpp, -1, true);
// create main cpp
String mainCpp = project.getFileTemplate ("jucer_MainTemplate_SimpleWindow_cpp")
.replace ("APPHEADERS", appHeaders, false)
.replace ("APPCLASSNAME", CodeHelpers::makeValidIdentifier (appTitle + "Application", false, true, false), false)
.replace ("APPNAME", CppTokeniserFunctions::addEscapeChars (appTitle), false)
.replace ("CONTENTCOMPCLASS", contentCompName, false)
.replace ("ALLOWMORETHANONEINSTANCE", "true", false);
if (! FileHelpers::overwriteFileWithNewDataIfDifferent (mainCppFile, mainCpp))
failedFiles.add (mainCppFile.getFullPathName());
sourceGroup.addFile (mainCppFile, -1, true);
return true;
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AnimatedAppWizard)
};
@@ -0,0 +1,85 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found 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.juce.com for more information.
==============================================================================
*/
struct AudioAppWizard : public NewProjectWizard
{
AudioAppWizard() {}
String getName() const override { return TRANS("Audio Application"); }
String getDescription() const override { return TRANS("Creates a JUCE application with a single window component and audio and MIDI in/out functions."); }
const char* getIcon() const override { return BinaryData::wizard_AudioApp_svg; }
bool initialiseProject (Project& project) override
{
createSourceFolder();
File mainCppFile = getSourceFilesFolder().getChildFile ("Main.cpp");
File contentCompCpp = getSourceFilesFolder().getChildFile ("MainComponent.cpp");
File contentCompH = contentCompCpp.withFileExtension (".h");
String contentCompName = "MainContentComponent";
project.getProjectTypeValue() = ProjectType::getGUIAppTypeName();
Project::Item sourceGroup (createSourceGroup (project));
setExecutableNameForAllTargets (project, File::createLegalFileName (appTitle));
String appHeaders (CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), mainCppFile));
// create main window
String windowCpp = project.getFileTemplate ("jucer_AudioComponentTemplate_cpp")
.replace ("INCLUDE_JUCE", CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), contentCompCpp), false);
if (! FileHelpers::overwriteFileWithNewDataIfDifferent (contentCompCpp, windowCpp))
failedFiles.add (contentCompCpp.getFullPathName());
sourceGroup.addFile (contentCompCpp, -1, true);
// create main cpp
String mainCpp = project.getFileTemplate ("jucer_MainTemplate_SimpleWindow_cpp")
.replace ("APPHEADERS", appHeaders, false)
.replace ("APPCLASSNAME", CodeHelpers::makeValidIdentifier (appTitle + "Application", false, true, false), false)
.replace ("APPNAME", CppTokeniserFunctions::addEscapeChars (appTitle), false)
.replace ("CONTENTCOMPCLASS", contentCompName, false)
.replace ("ALLOWMORETHANONEINSTANCE", "true", false);
if (! FileHelpers::overwriteFileWithNewDataIfDifferent (mainCppFile, mainCpp))
failedFiles.add (mainCppFile.getFullPathName());
sourceGroup.addFile (mainCppFile, -1, true);
return true;
}
StringArray getDefaultModules() override
{
StringArray s (NewProjectWizard::getDefaultModules());
s.addIfNotAlreadyThere ("juce_audio_utils");
return s;
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioAppWizard)
};
@@ -0,0 +1,107 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found 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.juce.com for more information.
==============================================================================
*/
struct AudioPluginAppWizard : public NewProjectWizard
{
AudioPluginAppWizard() {}
String getName() const override { return TRANS("Audio Plug-In"); }
String getDescription() const override { return TRANS("Creates a VST/AU/RTAS/AAX audio plug-in. This template features a single window GUI and Audio/MIDI IO functions."); }
const char* getIcon() const override { return BinaryData::wizard_AudioPlugin_svg; }
StringArray getDefaultModules() override
{
StringArray s (NewProjectWizard::getDefaultModules());
s.add ("juce_audio_plugin_client");
return s;
}
bool initialiseProject (Project& project) override
{
createSourceFolder();
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::Item sourceGroup (createSourceGroup (project));
project.getConfigFlag ("JUCE_QUICKTIME") = Project::configFlagDisabled; // disabled because it interferes with RTAS build on PC
setExecutableNameForAllTargets (project, 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;
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioPluginAppWizard)
};
@@ -0,0 +1,45 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found 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.juce.com for more information.
==============================================================================
*/
struct BlankAppWizard : public NewProjectWizard
{
BlankAppWizard() {}
String getName() const override { return TRANS("Empty Application"); }
String getDescription() const override { return TRANS("Creates a blank JUCE GUI application."); }
const char* getIcon() const override { return BinaryData::wizard_GUI_svg; }
bool initialiseProject (Project& project)
{
createSourceFolder();
project.getProjectTypeValue() = ProjectType::getGUIAppTypeName();
Project::Item sourceGroup (createSourceGroup (project));
setExecutableNameForAllTargets (project, File::createLegalFileName (appTitle));
return true;
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BlankAppWizard)
};
@@ -0,0 +1,88 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found 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.juce.com for more information.
==============================================================================
*/
struct ConsoleAppWizard : public NewProjectWizard
{
ConsoleAppWizard() {}
String getName() const override { return TRANS("Console Application"); }
String getDescription() const override { return TRANS("Creates a command-line application without GUI support."); }
const char* getIcon() const override { return BinaryData::wizard_ConsoleApp_svg; }
void addSetupItems (Component& setupComp, OwnedArray<Component>& itemsCreated)
{
const String fileOptions[] = { TRANS("Create a Main.cpp file"),
TRANS("Don't create any files") };
createFileCreationOptionComboBox (setupComp, itemsCreated,
StringArray (fileOptions, numElementsInArray (fileOptions)));
}
Result processResultsFromSetupItems (WizardComp& setupComp)
{
createMainCpp = false;
switch (getFileCreationComboResult (setupComp))
{
case 0: createMainCpp = true; break;
case 1: break;
default: jassertfalse; break;
}
return Result::ok();
}
bool initialiseProject (Project& project)
{
createSourceFolder();
project.getProjectTypeValue() = ProjectType::getConsoleAppTypeName();
Project::Item sourceGroup (createSourceGroup (project));
setExecutableNameForAllTargets (project, File::createLegalFileName (appTitle));
if (createMainCpp)
{
File mainCppFile = getSourceFilesFolder().getChildFile ("Main.cpp");
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;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ConsoleAppWizard)
};
@@ -0,0 +1,45 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found 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.juce.com for more information.
==============================================================================
*/
struct DynamicLibraryWizard : public NewProjectWizard
{
DynamicLibraryWizard() {}
String getName() const override { return TRANS("Dynamic Library"); }
String getDescription() const override { return TRANS("Creates a Dynamic Library template with support for all JUCE features."); }
const char* getIcon() const override { return BinaryData::wizard_DLL_svg; }
bool initialiseProject (Project& project) override
{
createSourceFolder();
project.getProjectTypeValue() = ProjectType::getDynamicLibTypeName();
createSourceGroup (project);
setExecutableNameForAllTargets (project, File::createLegalFileName (appTitle));
return true;
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DynamicLibraryWizard)
};
@@ -0,0 +1,124 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found 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.juce.com for more information.
==============================================================================
*/
struct GUIAppWizard : public NewProjectWizard
{
GUIAppWizard() {}
String getName() const override { return TRANS("GUI Application"); }
String getDescription() const override { return TRANS("Creates a blank JUCE application with a single window component."); }
const char* getIcon() const override { return BinaryData::wizard_GUI_svg; }
void addSetupItems (Component& setupComp, OwnedArray<Component>& itemsCreated)
{
const String fileOptions[] = { TRANS("Create a Main.cpp file"),
TRANS("Create a Main.cpp file and a basic window"),
TRANS("Don't create any files") };
createFileCreationOptionComboBox (setupComp, itemsCreated,
StringArray (fileOptions, numElementsInArray (fileOptions)))
.setSelectedId (2);
}
Result processResultsFromSetupItems (WizardComp& setupComp)
{
createMainCpp = createWindow = false;
switch (getFileCreationComboResult (setupComp))
{
case 0: createMainCpp = true; break;
case 1: createMainCpp = createWindow = true; break;
case 2: break;
default: jassertfalse; break;
}
return Result::ok();
}
bool initialiseProject (Project& project)
{
createSourceFolder();
File mainCppFile = getSourceFilesFolder().getChildFile ("Main.cpp");
File contentCompCpp = getSourceFilesFolder().getChildFile ("MainComponent.cpp");
File contentCompH = contentCompCpp.withFileExtension (".h");
String contentCompName = "MainContentComponent";
project.getProjectTypeValue() = ProjectType::getGUIAppTypeName();
Project::Item sourceGroup (createSourceGroup (project));
setExecutableNameForAllTargets (project, File::createLegalFileName (appTitle));
String appHeaders (CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), mainCppFile));
if (createWindow)
{
appHeaders << newLine << CodeHelpers::createIncludeStatement (contentCompH, mainCppFile);
String windowH = project.getFileTemplate ("jucer_ContentCompTemplate_h")
.replace ("INCLUDE_JUCE", CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), contentCompH), false)
.replace ("CONTENTCOMPCLASS", contentCompName, false)
.replace ("HEADERGUARD", CodeHelpers::makeHeaderGuardName (contentCompH), false);
String windowCpp = project.getFileTemplate ("jucer_ContentCompTemplate_cpp")
.replace ("INCLUDE_JUCE", CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), contentCompCpp), false)
.replace ("INCLUDE_CORRESPONDING_HEADER", CodeHelpers::createIncludeStatement (contentCompH, contentCompCpp), false)
.replace ("CONTENTCOMPCLASS", contentCompName, false);
if (! FileHelpers::overwriteFileWithNewDataIfDifferent (contentCompH, windowH))
failedFiles.add (contentCompH.getFullPathName());
if (! FileHelpers::overwriteFileWithNewDataIfDifferent (contentCompCpp, windowCpp))
failedFiles.add (contentCompCpp.getFullPathName());
sourceGroup.addFile (contentCompCpp, -1, true);
sourceGroup.addFile (contentCompH, -1, false);
}
if (createMainCpp)
{
String mainCpp = project.getFileTemplate (createWindow ? "jucer_MainTemplate_Window_cpp"
: "jucer_MainTemplate_NoWindow_cpp")
.replace ("APPHEADERS", appHeaders, false)
.replace ("APPCLASSNAME", CodeHelpers::makeValidIdentifier (appTitle + "Application", false, true, false), false)
.replace ("APPNAME", CppTokeniserFunctions::addEscapeChars (appTitle), false)
.replace ("CONTENTCOMPCLASS", contentCompName, false)
.replace ("ALLOWMORETHANONEINSTANCE", "true", false);
if (! FileHelpers::overwriteFileWithNewDataIfDifferent (mainCppFile, mainCpp))
failedFiles.add (mainCppFile.getFullPathName());
sourceGroup.addFile (mainCppFile, -1, true);
}
return true;
}
private:
bool createMainCpp, createWindow;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GUIAppWizard)
};
@@ -0,0 +1,45 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found 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.juce.com for more information.
==============================================================================
*/
struct StaticLibraryWizard : public NewProjectWizard
{
StaticLibraryWizard() {}
String getName() const override { return TRANS("Static Library"); }
String getDescription() const override { return TRANS("Creates a static library."); }
const char* getIcon() const override { return BinaryData::wizard_StaticLibrary_svg; }
bool initialiseProject (Project& project) override
{
createSourceFolder();
project.getProjectTypeValue() = ProjectType::getStaticLibTypeName();
createSourceGroup (project);
setExecutableNameForAllTargets (project, File::createLegalFileName (appTitle));
return true;
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StaticLibraryWizard)
};
@@ -0,0 +1,78 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found 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.juce.com for more information.
==============================================================================
*/
struct OpenGLAppWizard : public NewProjectWizard
{
OpenGLAppWizard() {}
String getName() const override { return TRANS("OpenGL Application"); }
String getDescription() const override { return TRANS("Creates a blank JUCE application with a single window component. This component supports openGL drawing features including 3D model import and GLSL shaders."); }
const char* getIcon() const override { return BinaryData::wizard_OpenGL_svg; }
bool initialiseProject (Project& project) override
{
createSourceFolder();
File mainCppFile = getSourceFilesFolder().getChildFile ("Main.cpp");
File contentCompCpp = getSourceFilesFolder().getChildFile ("MainComponent.cpp");
File contentCompH = contentCompCpp.withFileExtension (".h");
String contentCompName = "MainContentComponent";
project.getProjectTypeValue() = ProjectType::getGUIAppTypeName();
Project::Item sourceGroup (createSourceGroup (project));
setExecutableNameForAllTargets (project, File::createLegalFileName (appTitle));
String appHeaders (CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), mainCppFile));
// create main window
String windowCpp = project.getFileTemplate ("jucer_OpenGLComponentTemplate_cpp")
.replace ("INCLUDE_JUCE", CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), contentCompCpp), false);
if (! FileHelpers::overwriteFileWithNewDataIfDifferent (contentCompCpp, windowCpp))
failedFiles.add (contentCompCpp.getFullPathName());
sourceGroup.addFile (contentCompCpp, -1, true);
// create main cpp
String mainCpp = project.getFileTemplate ("jucer_MainTemplate_SimpleWindow_cpp")
.replace ("APPHEADERS", appHeaders, false)
.replace ("APPCLASSNAME", CodeHelpers::makeValidIdentifier (appTitle + "Application", false, true, false), false)
.replace ("APPNAME", CppTokeniserFunctions::addEscapeChars (appTitle), false)
.replace ("CONTENTCOMPCLASS", contentCompName, false)
.replace ("ALLOWMORETHANONEINSTANCE", "true", false);
if (! FileHelpers::overwriteFileWithNewDataIfDifferent (mainCppFile, mainCpp))
failedFiles.add (mainCppFile.getFullPathName());
sourceGroup.addFile (mainCppFile, -1, true);
return true;
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLAppWizard)
};
@@ -0,0 +1,55 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found 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.juce.com for more information.
==============================================================================
*/
class StartPageComponent : public Component
{
public:
StartPageComponent()
{
setSize (900, 650);
WizardComp* projectWizard = new WizardComp();
panel.addTab ("Create New Project", new TemplateTileBrowser (projectWizard), true);
panel.addTab ("New Project Options", projectWizard, true);
addAndMakeVisible (panel);
}
void paint (Graphics& g) override
{
IntrojucerLookAndFeel::fillWithBackgroundTexture (*this, g);
}
void resized() override
{
panel.setBounds (getLocalBounds());
}
private:
SlidingPanelComponent panel;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StartPageComponent)
};
@@ -0,0 +1,284 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found 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.juce.com for more information.
==============================================================================
*/
#ifndef JUCER_TEMPLATETHUMBNAILSCOMPONENT_H_INCLUDED
#define JUCER_TEMPLATETHUMBNAILSCOMPONENT_H_INCLUDED
//=====================================================================================================
/**
Template option tile button.
The drawable button object class for the tile icons and buttons in the TemplateTileBrowser
*/
class TemplateOptionButton : public DrawableButton
{
public:
TemplateOptionButton (const String& buttonName, ButtonStyle buttonStyle, const char* thumbSvg)
: DrawableButton (buttonName, buttonStyle)
{
// svg for thumbnail icon
ScopedPointer<XmlElement> svg (XmlDocument::parse (thumbSvg));
jassert (svg != nullptr);
thumb = Drawable::createFromSVG (*svg);
// svg for thumbnail background highlight
ScopedPointer<XmlElement> backSvg (XmlDocument::parse (BinaryData::wizard_Highlight_svg));
jassert (backSvg != nullptr);
hoverBackground = Drawable::createFromSVG (*backSvg);
name = buttonName;
description = "<insert description>";
}
void paintButton (Graphics& g, bool isMouseOverButton, bool /*isButtonDown*/) override
{
const Rectangle<float> bounds (getLocalBounds().toFloat());
const Colour buttonColour (0xfff29300);
if (isMouseOverButton)
{
if (getStyle() == ImageFitted)
{
hoverBackground->drawWithin (g, bounds, RectanglePlacement::centred, 1.0);
thumb->drawWithin (g, bounds, RectanglePlacement::centred, 1.0);
}
else
{
g.setColour (buttonColour.withAlpha (0.3f));
g.fillRoundedRectangle (bounds.reduced (2.0f, 2.0f), 10.0f);
g.setColour (buttonColour);
g.drawRoundedRectangle (bounds.reduced (2.0f, 2.0f), 10.0f, 2.0f);
}
}
else
{
if (getStyle() == ImageFitted)
{
thumb->drawWithin (g, bounds, RectanglePlacement::centred, 1.0);
}
else
{
g.setColour (buttonColour);
g.drawRoundedRectangle (bounds.reduced (2.0f, 2.0f), 10.0f, 2.0f);
}
}
Rectangle<float> textTarget;
// center the text for the text buttons or position the text in the image buttons
if (getStyle() != ImageFitted)
{
textTarget = getLocalBounds().toFloat();
}
else
{
textTarget = RectanglePlacement (RectanglePlacement::centred).appliedTo (thumb->getDrawableBounds(), bounds);
textTarget = textTarget.removeFromBottom (textTarget.getHeight() * 0.3f);
}
g.setColour (Colours::white);
g.drawText (name, textTarget, Justification::centred, true);
}
void resized() override
{
thumb->setBoundsToFit (0, 0, getWidth(), getHeight(), Justification::centred, false);
}
void setDescription (String descript) noexcept
{
description = descript;
}
String getDescription() const noexcept
{
return description;
}
private:
ScopedPointer<Drawable> thumb, hoverBackground;
String name, description;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TemplateOptionButton)
};
//=====================================================================================================
/**
Project Template Component for front page.
Features multiple icon buttons to select the type of project template
*/
class TemplateTileBrowser : public Component,
private Button::Listener
{
public:
TemplateTileBrowser (WizardComp* projectWizard)
{
const int numWizardButtons = getNumWizards() - 1; // ( - 1 because the last one is blank)
for (int i = 0; i < numWizardButtons; ++i)
{
ScopedPointer<NewProjectWizard> wizard (createWizardType (i));
TemplateOptionButton* b = new TemplateOptionButton (wizard->getName(),
TemplateOptionButton::ImageFitted,
wizard->getIcon());
optionButtons.add (b);
addAndMakeVisible (b);
b->setDescription (wizard->getDescription());
b->addListener (this);
}
// Handle Open Project button functionality
ApplicationCommandManager& commandManager = IntrojucerApp::getCommandManager();
addAndMakeVisible (blankProjectButton = new TemplateOptionButton ("Create Blank Project", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg));
addAndMakeVisible (exampleProjectButton = new TemplateOptionButton ("Open Example Project", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg));
addAndMakeVisible (openProjectButton = new TemplateOptionButton ("Open Existing Project", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg));
blankProjectButton->addListener (this);
exampleProjectButton->addListener (this);
openProjectButton->setCommandToTrigger (&commandManager, CommandIDs::open, true);
newProjectWizard = projectWizard;
}
void paint (Graphics& g) override
{
g.setColour (Colours::black.withAlpha (0.2f));
g.fillRect (getLocalBounds().removeFromTop (60));
g.setColour (Colours::white);
g.setFont (20.0f);
g.drawText ("Create New Project", 0, 0, getWidth(), 60, Justification::centred, true);
// draw the descriptions of each template if hovered;
// (repaint is called by the button listener on change state)
Rectangle<int> descriptionBox (getLocalBounds().reduced (30).removeFromBottom (50));
g.setColour (Colours::white.withAlpha (0.4f));
g.setFont (15.0f);
for (int i = 0; i < optionButtons.size(); ++i)
if (optionButtons.getUnchecked(i)->isOver())
g.drawFittedText (optionButtons.getUnchecked(i)->getDescription(), descriptionBox, Justification::centred, 5, 1.0f);
}
void resized() override
{
Rectangle<int> allOpts = getLocalBounds().reduced (40, 60);
allOpts.removeFromBottom (allOpts.getHeight() / 4);
const int numHorizIcons = 4;
const int optStep = allOpts.getWidth() / numHorizIcons;
for (int i = 0; i < optionButtons.size(); ++i)
{
const int yShift = i < numHorizIcons ? 0 : 1;
optionButtons.getUnchecked(i)->setBounds (Rectangle<int> (allOpts.getX() + (i % numHorizIcons) * optStep,
allOpts.getY() + yShift * allOpts.getHeight() / 2,
optStep, allOpts.getHeight() / 2)
.reduced (10, 10));
}
Rectangle<int> openButtonBounds = getLocalBounds();
openButtonBounds.removeFromBottom (proportionOfHeight (0.12f));
openButtonBounds = openButtonBounds.removeFromBottom (120);
openButtonBounds.reduce (50, 40);
blankProjectButton->setBounds (openButtonBounds.removeFromLeft (optStep - 20));
exampleProjectButton->setBounds (openButtonBounds.removeFromRight (optStep - 20));
openProjectButton->setBounds (openButtonBounds.reduced (18, 0));
}
void showWizard (const String& name)
{
newProjectWizard->projectType.setText (name);
if (SlidingPanelComponent* parent = findParentComponentOfClass<SlidingPanelComponent>())
parent->goToTab (1);
else
jassertfalse;
}
void createBlankProject()
{
showWizard (BlankAppWizard().getName());
}
void openExampleProject()
{
FileChooser fc ("Open File", findExamplesFolder());
if (fc.browseForFileToOpen())
IntrojucerApp::getApp().openFile (fc.getResult());
}
static File findExamplesFolder()
{
File appFolder (File::getSpecialLocation (File::currentApplicationFile));
while (appFolder.exists()
&& appFolder.getParentDirectory() != appFolder)
{
File examples (appFolder.getSiblingFile ("examples"));
if (examples.exists())
return examples;
appFolder = appFolder.getParentDirectory();
}
return File::nonexistent;
}
private:
OwnedArray<TemplateOptionButton> optionButtons;
NewProjectWizardClasses::WizardComp* newProjectWizard;
ScopedPointer<TemplateOptionButton> blankProjectButton, openProjectButton, exampleProjectButton;
void buttonClicked (Button* b) override
{
if (b == blankProjectButton)
createBlankProject();
else if (b == exampleProjectButton)
openExampleProject();
else if (dynamic_cast<TemplateOptionButton*> (b) != nullptr)
showWizard (b->getButtonText());
}
void buttonStateChanged (Button*) override
{
repaint();
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TemplateTileBrowser)
};
#endif // JUCER_TEMPLATETHUMBNAILSCOMPONENT_H_INCLUDED