Browse Source

Introjucer update to provide downloading of new modules directly from the website.

tags/2021-05-28
Julian Storer 13 years ago
parent
commit
2d56bedab5
18 changed files with 606 additions and 400 deletions
  1. +49
    -6
      extras/Introjucer/Source/Application/jucer_Application.h
  2. +1
    -1
      extras/Introjucer/Source/Application/jucer_CommandLine.cpp
  3. +1
    -1
      extras/Introjucer/Source/Application/jucer_CommonHeaders.h
  4. +299
    -252
      extras/Introjucer/Source/Application/jucer_JuceUpdater.cpp
  5. +33
    -23
      extras/Introjucer/Source/Application/jucer_JuceUpdater.h
  6. +1
    -1
      extras/Introjucer/Source/Application/jucer_MainWindow.cpp
  7. +11
    -12
      extras/Introjucer/Source/Project Saving/jucer_ProjectExporter.cpp
  8. +1
    -1
      extras/Introjucer/Source/Project Saving/jucer_ProjectSaver.h
  9. +129
    -20
      extras/Introjucer/Source/Project/jucer_Module.cpp
  10. +22
    -2
      extras/Introjucer/Source/Project/jucer_Module.h
  11. +2
    -1
      extras/Introjucer/Source/Project/jucer_NewProjectWizard.cpp
  12. +0
    -12
      extras/Introjucer/Source/Project/jucer_Project.cpp
  13. +46
    -31
      extras/Introjucer/Source/Project/jucer_ProjectInformationComponent.cpp
  14. +8
    -15
      extras/Introjucer/Source/Utility/jucer_FileHelpers.cpp
  15. +2
    -1
      extras/Introjucer/Source/Utility/jucer_FileHelpers.h
  16. +0
    -17
      extras/Introjucer/Source/Utility/jucer_StoredSettings.cpp
  17. +0
    -3
      extras/Introjucer/Source/Utility/jucer_StoredSettings.h
  18. +1
    -1
      modules/juce_core/system/juce_StandardHeader.h

+ 49
- 6
extras/Introjucer/Source/Application/jucer_Application.h View File

@@ -38,7 +38,10 @@ class JucerApplication : public JUCEApplication
{ {
public: public:
//============================================================================== //==============================================================================
JucerApplication() {}
JucerApplication()
{
}
~JucerApplication() {} ~JucerApplication() {}
//============================================================================== //==============================================================================
@@ -96,12 +99,18 @@ public:
mainWindows.clear(); mainWindows.clear();
OpenDocumentManager::deleteInstance(); OpenDocumentManager::deleteInstance();
deleteAndZero (commandManager);
commandManager = nullptr;
} }
//============================================================================== //==============================================================================
void systemRequestedQuit() void systemRequestedQuit()
{ {
if (cancelAnyModalComponents())
{
new AsyncQuitRetrier();
return;
}
while (mainWindows.size() > 0) while (mainWindows.size() > 0)
{ {
if (! mainWindows[0]->closeCurrentProject()) if (! mainWindows[0]->closeCurrentProject())
@@ -139,11 +148,11 @@ public:
bool moreThanOneInstanceAllowed() bool moreThanOneInstanceAllowed()
{ {
#ifndef JUCE_LINUX
#ifndef JUCE_LINUX
return false; return false;
#else
#else
return true; //xxx should be false but doesn't work on linux.. return true; //xxx should be false but doesn't work on linux..
#endif
#endif
} }
void anotherInstanceStarted (const String& commandLine) void anotherInstanceStarted (const String& commandLine)
@@ -352,7 +361,12 @@ public:
case CommandIDs::showPrefs: showPrefsPanel(); break; case CommandIDs::showPrefs: showPrefsPanel(); break;
case CommandIDs::saveAll: OpenDocumentManager::getInstance()->saveAll(); break; case CommandIDs::saveAll: OpenDocumentManager::getInstance()->saveAll(); break;
case CommandIDs::closeAllDocuments: closeAllDocuments (true); break; case CommandIDs::closeAllDocuments: closeAllDocuments (true); break;
case CommandIDs::showJuceVersion: JuceUpdater::show (mainWindows[0]); break;
case CommandIDs::showJuceVersion:
{
ModuleList list (ModuleList::getDefaultModulesFolder (nullptr));
JuceUpdater::show (list, mainWindows[0]);
break;
}
default: return JUCEApplication::perform (info); default: return JUCEApplication::perform (info);
} }
@@ -503,6 +517,35 @@ private:
return createNewMainWindow(); return createNewMainWindow();
} }
//==============================================================================
static bool cancelAnyModalComponents()
{
const int numModal = ModalComponentManager::getInstance()->getNumModalComponents();
for (int i = numModal; --i >= 0;)
if (ModalComponentManager::getInstance()->getModalComponent(i) != nullptr)
ModalComponentManager::getInstance()->getModalComponent(i)->exitModalState (0);
return numModal > 0;
}
class AsyncQuitRetrier : public Timer
{
public:
AsyncQuitRetrier() { startTimer (500); }
void timerCallback()
{
stopTimer();
delete this;
if (JUCEApplication::getInstance() != nullptr)
JUCEApplication::getInstance()->systemRequestedQuit();
}
JUCE_DECLARE_NON_COPYABLE (AsyncQuitRetrier);
};
}; };


+ 1
- 1
extras/Introjucer/Source/Application/jucer_CommandLine.cpp View File

@@ -192,7 +192,7 @@ namespace
int listModules() int listModules()
{ {
std::cout << "Downloading list of available modules..." << std::endl; std::cout << "Downloading list of available modules..." << std::endl;
ModuleList list;
ModuleList list (File::nonexistent);
list.loadFromWebsite(); list.loadFromWebsite();
for (int i = 0; i < list.modules.size(); ++i) for (int i = 0; i < list.modules.size(); ++i)


+ 1
- 1
extras/Introjucer/Source/Application/jucer_CommonHeaders.h View File

@@ -37,7 +37,7 @@
#include "jucer_CommandIDs.h" #include "jucer_CommandIDs.h"
//============================================================================== //==============================================================================
extern ApplicationCommandManager* commandManager;
extern ScopedPointer<ApplicationCommandManager> commandManager;
//============================================================================== //==============================================================================
const char* const projectItemDragType = "Project Items"; const char* const projectItemDragType = "Project Items";


+ 299
- 252
extras/Introjucer/Source/Application/jucer_JuceUpdater.cpp View File

@@ -25,30 +25,45 @@
#include "../jucer_Headers.h" #include "../jucer_Headers.h"
#include "jucer_JuceUpdater.h" #include "jucer_JuceUpdater.h"
#include "../Project/jucer_Module.h"
//============================================================================== //==============================================================================
JuceUpdater::JuceUpdater()
: filenameComp ("Juce Folder", StoredSettings::getInstance()->getLastKnownJuceFolder(),
JuceUpdater::JuceUpdater (ModuleList& moduleList_)
: moduleList (moduleList_),
latestList (File::nonexistent),
filenameComp ("Juce Folder", ModuleList::getLocalModulesFolder (nullptr),
true, true, false, "*", String::empty, "Select your Juce folder"), true, true, false, "*", String::empty, "Select your Juce folder"),
checkNowButton ("Check Online for Available Updates...",
"Contacts the website to see if this version is up-to-date")
checkNowButton ("Check for available updates on the JUCE website...",
"Contacts the website to see if new modules are available"),
installButton ("Download and install selected modules..."),
selectAllButton ("Select/Deselect All")
{ {
addAndMakeVisible (&label); addAndMakeVisible (&label);
addAndMakeVisible (&currentVersionLabel);
addAndMakeVisible (&filenameComp); addAndMakeVisible (&filenameComp);
addAndMakeVisible (&checkNowButton); addAndMakeVisible (&checkNowButton);
addAndMakeVisible (&currentVersionLabel);
addAndMakeVisible (&installButton);
addAndMakeVisible (&selectAllButton);
checkNowButton.addListener (this); checkNowButton.addListener (this);
installButton.addListener (this);
selectAllButton.addListener (this);
filenameComp.addListener (this); filenameComp.addListener (this);
currentVersionLabel.setFont (Font (14.0f, Font::italic)); currentVersionLabel.setFont (Font (14.0f, Font::italic));
label.setFont (Font (12.0f)); label.setFont (Font (12.0f));
label.setText ("Destination folder:", false);
label.setText ("Local modules folder:", false);
addAndMakeVisible (&availableVersionsList); addAndMakeVisible (&availableVersionsList);
availableVersionsList.setModel (this); availableVersionsList.setModel (this);
setSize (600, 300);
updateInstallButtonStatus();
versionsToDownload = ValueTree ("modules");
versionsToDownload.addListener (this);
setSize (600, 500);
checkNow();
} }
JuceUpdater::~JuceUpdater() JuceUpdater::~JuceUpdater()
@@ -57,12 +72,32 @@ JuceUpdater::~JuceUpdater()
filenameComp.removeListener (this); filenameComp.removeListener (this);
} }
void JuceUpdater::show (Component* mainWindow)
//==============================================================================
class UpdateDialogWindow : public DialogWindow
{ {
JuceUpdater updater;
DialogWindow::showModalDialog ("Juce Update...", &updater, mainWindow,
Colours::lightgrey,
true, false, false);
public:
UpdateDialogWindow (JuceUpdater* updater, Component* componentToCentreAround)
: DialogWindow ("JUCE Module Updater",
Colours::lightgrey, true, true)
{
setContentOwned (updater, true);
centreAroundComponent (componentToCentreAround, getWidth(), getHeight());
setResizable (true, true);
}
void closeButtonPressed()
{
setVisible (false);
}
private:
JUCE_DECLARE_NON_COPYABLE (UpdateDialogWindow);
};
void JuceUpdater::show (ModuleList& moduleList, Component* mainWindow)
{
UpdateDialogWindow w (new JuceUpdater (moduleList), mainWindow);
w.runModalLoop();
} }
void JuceUpdater::resized() void JuceUpdater::resized()
@@ -70,9 +105,16 @@ void JuceUpdater::resized()
filenameComp.setBounds (20, 40, getWidth() - 40, 22); filenameComp.setBounds (20, 40, getWidth() - 40, 22);
label.setBounds (filenameComp.getX(), filenameComp.getY() - 18, filenameComp.getWidth(), 18); label.setBounds (filenameComp.getX(), filenameComp.getY() - 18, filenameComp.getWidth(), 18);
currentVersionLabel.setBounds (filenameComp.getX(), filenameComp.getBottom(), filenameComp.getWidth(), 25); currentVersionLabel.setBounds (filenameComp.getX(), filenameComp.getBottom(), filenameComp.getWidth(), 25);
checkNowButton.changeWidthToFitText (20);
checkNowButton.setCentrePosition (getWidth() / 2, filenameComp.getBottom() + 40);
availableVersionsList.setBounds (filenameComp.getX(), checkNowButton.getBottom() + 20, filenameComp.getWidth(), getHeight() - (checkNowButton.getBottom() + 20));
checkNowButton.changeWidthToFitText (22);
checkNowButton.setCentrePosition (getWidth() / 2, filenameComp.getBottom() + 20);
availableVersionsList.setBounds (filenameComp.getX(), checkNowButton.getBottom() + 20,
filenameComp.getWidth(),
getHeight() - 30 - (checkNowButton.getBottom() + 20));
installButton.changeWidthToFitText (22);
installButton.setTopRightPosition (availableVersionsList.getRight(), getHeight() - 28);
selectAllButton.setBounds (availableVersionsList.getX(),
availableVersionsList.getBottom() + 4,
installButton.getX() - availableVersionsList.getX() - 20, 22);
} }
void JuceUpdater::paint (Graphics& g) void JuceUpdater::paint (Graphics& g)
@@ -80,325 +122,330 @@ void JuceUpdater::paint (Graphics& g)
g.fillAll (Colours::white); g.fillAll (Colours::white);
} }
String findVersionNum (const String& file, const String& token)
void JuceUpdater::buttonClicked (Button* b)
{ {
return file.fromFirstOccurrenceOf (token, false, false)
.upToFirstOccurrenceOf ("\n", false, false)
.trim();
if (b == &installButton)
install();
else if (b == &selectAllButton)
selectAll();
else
checkNow();
} }
String JuceUpdater::getCurrentVersion()
void JuceUpdater::refresh()
{ {
const String header (filenameComp.getCurrentFile()
.getChildFile ("src/core/juce_StandardHeader.h").loadFileAsString());
availableVersionsList.updateContent();
availableVersionsList.repaint();
}
const String v1 (findVersionNum (header, "JUCE_MAJOR_VERSION"));
const String v2 (findVersionNum (header, "JUCE_MINOR_VERSION"));
const String v3 (findVersionNum (header, "JUCE_BUILDNUMBER"));
class WebsiteContacterThread : public Thread,
private AsyncUpdater
{
public:
WebsiteContacterThread (JuceUpdater& owner_, const ModuleList& latestList)
: Thread ("Module updater"),
owner (owner_),
downloaded (latestList)
{
startThread();
}
if ((v1 + v2 + v3).isEmpty())
return String::empty;
~WebsiteContacterThread()
{
stopThread (10000);
}
void run()
{
if (downloaded.loadFromWebsite())
triggerAsyncUpdate();
else
AlertWindow::showMessageBox (AlertWindow::InfoIcon,
"Module Update",
"Couldn't connect to the website!");
}
void handleAsyncUpdate()
{
owner.backgroundUpdateComplete (downloaded);
}
private:
JuceUpdater& owner;
ModuleList downloaded;
};
return v1 + "." + v2 + "." + v3;
void JuceUpdater::checkNow()
{
websiteContacterThread = nullptr;
websiteContacterThread = new WebsiteContacterThread (*this, latestList);
} }
XmlElement* JuceUpdater::downloadVersionList()
void JuceUpdater::backgroundUpdateComplete (const ModuleList& newList)
{ {
return URL ("http://www.rawmaterialsoftware.com/juce/downloads/juce_versions.php").readEntireXmlStream();
latestList = newList;
websiteContacterThread = nullptr;
if (latestList == moduleList)
AlertWindow::showMessageBox (AlertWindow::InfoIcon,
"Module Update",
"No new modules are available");
refresh();
} }
void JuceUpdater::updateVersions (const XmlElement& xml)
int JuceUpdater::getNumCheckedModules() const
{ {
availableVersions.clear();
int numChecked = 0;
forEachXmlChildElementWithTagName (xml, v, "VERSION")
{
VersionInfo* vi = new VersionInfo();
vi->url = URL (v->getStringAttribute ("url"));
vi->desc = v->getStringAttribute ("desc");
vi->version = v->getStringAttribute ("version");
vi->date = v->getStringAttribute ("date");
availableVersions.add (vi);
}
for (int i = latestList.modules.size(); --i >= 0;)
if (versionsToDownload [latestList.modules.getUnchecked(i)->uid])
++numChecked;
availableVersionsList.updateContent();
return numChecked;
} }
void JuceUpdater::buttonClicked (Button*)
bool JuceUpdater::isLatestVersion (const String& moduleID) const
{ {
ScopedPointer<XmlElement> xml (downloadVersionList());
const ModuleList::Module* m1 = moduleList.findModuleInfo (moduleID);
const ModuleList::Module* m2 = latestList.findModuleInfo (moduleID);
if (xml == nullptr || xml->hasTagName ("html"))
{
AlertWindow::showMessageBox (AlertWindow::WarningIcon, "Connection Problems...",
"Couldn't connect to the Raw Material Software website!");
return m1 != nullptr && m2 != nullptr && m1->version == m2->version;
}
return;
}
void JuceUpdater::updateInstallButtonStatus()
{
const int numChecked = getNumCheckedModules();
installButton.setEnabled (numChecked > 0);
selectAllButton.setToggleState (numChecked > latestList.modules.size() / 2, false);
}
if (! xml->hasTagName ("JUCEVERSIONS"))
{
AlertWindow::showMessageBox (AlertWindow::WarningIcon, "Update Problems...",
"This version of the Introjucer may be too old to receive automatic updates!\n\n"
"Please visit www.rawmaterialsoftware.com and get the latest version manually!");
return;
}
void JuceUpdater::filenameComponentChanged (FilenameComponent*)
{
moduleList.rescan (filenameComp.getCurrentFile());
filenameComp.setCurrentFile (moduleList.getModulesFolder(), true, false);
const String currentVersion (getCurrentVersion());
if (! FileHelpers::isModulesFolder (moduleList.getModulesFolder()))
currentVersionLabel.setText ("(Not a Juce folder)", false);
else
currentVersionLabel.setText (String::empty, false);
OwnedArray<VersionInfo> versions;
updateVersions (*xml);
refresh();
} }
//==============================================================================
class NewVersionDownloader : public ThreadWithProgressWindow
void JuceUpdater::selectAll()
{ {
public:
NewVersionDownloader (const String& title, const URL& url_, const File& target_)
: ThreadWithProgressWindow (title, true, true),
url (url_), target (target_)
bool enable = getNumCheckedModules() < latestList.modules.size() / 2;
versionsToDownload.removeAllProperties (nullptr);
if (enable)
{ {
for (int i = latestList.modules.size(); --i >= 0;)
if (! isLatestVersion (latestList.modules.getUnchecked(i)->uid))
versionsToDownload.setProperty (latestList.modules.getUnchecked(i)->uid, true, nullptr);
} }
}
void run()
{
setStatusMessage ("Contacting website...");
//==============================================================================
int JuceUpdater::getNumRows()
{
return latestList.modules.size();
}
ScopedPointer<InputStream> input (url.createInputStream (false));
void JuceUpdater::paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected)
{
if (rowIsSelected)
g.fillAll (findColour (TextEditor::highlightColourId));
}
if (input == nullptr)
Component* JuceUpdater::refreshComponentForRow (int rowNumber, bool isRowSelected, Component* existingComponentToUpdate)
{
class UpdateListComponent : public Component
{
public:
UpdateListComponent (JuceUpdater& updater_)
: updater (updater_)
{ {
error = "Couldn't connect to the website...";
return;
addChildComponent (&toggle);
toggle.setBounds ("2, 2, parent.height - 2, parent.height - 2");
toggle.setWantsKeyboardFocus (false);
setInterceptsMouseClicks (false, true);
} }
if (! target.deleteFile())
void setModule (const ModuleList::Module* newModule,
const ModuleList::Module* existingModule,
const Value& value)
{ {
error = "Couldn't delete the destination file...";
return;
if (newModule != nullptr)
{
toggle.getToggleStateValue().referTo (value);
toggle.setVisible (true);
toggle.setEnabled (true);
name = newModule->uid;
status = String::empty;
if (existingModule == nullptr)
{
status << " (not currently installed)";
}
else if (existingModule->version != newModule->version)
{
status << " installed: " << existingModule->version
<< ", available: " << newModule->version;
}
else
{
status << " (latest version already installed)";
toggle.setEnabled (false);
}
}
else
{
name = status = String::empty;
toggle.setVisible (false);
}
} }
ScopedPointer<OutputStream> output (target.createOutputStream (32768));
if (output == nullptr)
void paint (Graphics& g)
{ {
error = "Couldn't write to the destination file...";
return;
}
g.setColour (Colours::green.withAlpha (0.12f));
setStatusMessage ("Downloading...");
g.fillRect (0, 1, getWidth(), getHeight() - 2);
g.setColour (Colours::black);
g.setFont (getHeight() * 0.7f);
int totalBytes = (int) input->getTotalLength();
int bytesSoFar = 0;
g.drawText (name, toggle.getRight() + 4, 0, getWidth() / 2 - toggle.getRight() - 4, getHeight(),
Justification::centredLeft, true);
while (! (input->isExhausted() || threadShouldExit()))
{
HeapBlock<char> buffer (8192);
const int num = input->read (buffer, 8192);
g.drawText (status, getWidth() / 2, 0, getWidth() / 2, getHeight(),
Justification::centredLeft, true);
}
if (num == 0)
break;
private:
JuceUpdater& updater;
ToggleButton toggle;
String name, status;
};
output->write (buffer, num);
bytesSoFar += num;
UpdateListComponent* c = dynamic_cast <UpdateListComponent*> (existingComponentToUpdate);
if (c == nullptr)
c = new UpdateListComponent (*this);
setProgress (totalBytes > 0 ? bytesSoFar / (double) totalBytes : -1.0);
}
}
ModuleList::Module* m = latestList.modules [rowNumber];
String error;
if (m != nullptr)
c->setModule (m,
moduleList.findModuleInfo (m->uid),
versionsToDownload.getPropertyAsValue (m->uid, nullptr));
else
c->setModule (nullptr, nullptr, Value());
private:
URL url;
File target;
};
return c;
}
//============================================================================== //==============================================================================
class Unzipper : public ThreadWithProgressWindow
class InstallThread : public ThreadWithProgressWindow
{ {
public: public:
Unzipper (ZipFile& zipFile_, const File& targetDir_)
: ThreadWithProgressWindow ("Unzipping...", true, true),
worked (true), zipFile (zipFile_), targetDir (targetDir_)
InstallThread (const ModuleList& targetList_,
const ModuleList& list_, const StringArray& itemsToInstall_)
: ThreadWithProgressWindow ("Installing New Modules", true, true),
result (Result::ok()),
targetList (targetList_),
list (list_),
itemsToInstall (itemsToInstall_)
{ {
} }
void run() void run()
{ {
for (int i = 0; i < zipFile.getNumEntries(); ++i)
for (int i = 0; i < itemsToInstall.size(); ++i)
{ {
if (threadShouldExit())
break;
const ModuleList::Module* m = list.findModuleInfo (itemsToInstall[i]);
const ZipFile::ZipEntry* e = zipFile.getEntry (i);
setStatusMessage ("Unzipping " + e->filename + "...");
setProgress (i / (double) zipFile.getNumEntries());
worked = zipFile.uncompressEntry (i, targetDir, true) && worked;
}
}
jassert (m != nullptr);
if (m != nullptr)
{
setProgress (i / (double) itemsToInstall.size());
bool worked;
MemoryBlock downloaded;
result = download (*m, downloaded);
private:
ZipFile& zipFile;
File targetDir;
};
if (result.failed())
break;
//==============================================================================
void JuceUpdater::applyVersion (VersionInfo* version)
{
File destDir (filenameComp.getCurrentFile());
if (threadShouldExit())
break;
const bool destDirExisted = destDir.isDirectory();
result = unzip (*m, downloaded);
if (destDirExisted && destDir.getNumberOfChildFiles (File::findFilesAndDirectories, "*") > 0)
{
int r = AlertWindow::showYesNoCancelBox (AlertWindow::WarningIcon, "Folder already exists",
"The folder " + destDir.getFullPathName() + "\nalready contains some files...\n\n"
"Do you want to delete everything in the folder and replace it entirely, or just merge the new files into the existing folder?",
"Delete and replace entire folder",
"Add and overwrite existing files",
"Cancel");
if (r == 0)
return;
if (r == 1)
{
if (! destDir.deleteRecursively())
{
AlertWindow::showMessageBox (AlertWindow::WarningIcon, "Problems...",
"Couldn't delete the existing folder!");
return;
if (result.failed())
break;
} }
if (threadShouldExit())
break;
} }
} }
if (! (destDir.isDirectory() || destDir.createDirectory()))
Result download (const ModuleList::Module& m, MemoryBlock& dest)
{ {
AlertWindow::showMessageBox (AlertWindow::WarningIcon, "Problems...",
"Couldn't create that target folder..");
return;
}
File zipFile (destDir.getNonexistentChildFile ("juce_download", ".tar.gz", false));
setStatusMessage ("Downloading " + m.uid + "...");
bool worked = false;
if (m.url.readEntireBinaryStream (dest, false))
return Result::ok();
{
NewVersionDownloader downloader ("Downloading Version " + version->version + "...",
version->url, zipFile);
worked = downloader.runThread();
return Result::fail ("Failed to download from: " + m.url.toString (false));
} }
if (worked)
Result unzip (const ModuleList::Module& m, const MemoryBlock& data)
{ {
ZipFile zip (zipFile);
Unzipper unzipper (zip, destDir);
worked = unzipper.runThread() && unzipper.worked;
}
zipFile.deleteFile();
setStatusMessage ("Installing " + m.uid + "...");
if ((! destDirExisted) && (destDir.getNumberOfChildFiles (File::findFilesAndDirectories, "*") == 0 || ! worked))
destDir.deleteRecursively();
MemoryInputStream input (data, false);
ZipFile zip (input);
filenameComponentChanged (&filenameComp);
}
void JuceUpdater::filenameComponentChanged (FilenameComponent*)
{
const String version (getCurrentVersion());
if (zip.getNumEntries() == 0)
return Result::fail ("The downloaded file wasn't a valid module file!");
if (version.isEmpty())
currentVersionLabel.setText ("(Not a Juce folder)", false);
else
currentVersionLabel.setText ("(Current version in this folder: " + version + ")", false);
}
return zip.uncompressTo (targetList.getModulesFolder(), true);
}
//==============================================================================
int JuceUpdater::getNumRows()
{
return availableVersions.size();
}
Result result;
void JuceUpdater::paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected)
{
if (rowIsSelected)
g.fillAll (findColour (TextEditor::highlightColourId));
}
private:
ModuleList targetList, list;
StringArray itemsToInstall;
};
Component* JuceUpdater::refreshComponentForRow (int rowNumber, bool isRowSelected, Component* existingComponentToUpdate)
void JuceUpdater::install()
{ {
class UpdateListComponent : public Component,
public ButtonListener
if (! moduleList.getModulesFolder().createDirectory())
{ {
public:
UpdateListComponent (JuceUpdater& updater_)
: updater (updater_),
version (nullptr),
applyButton ("Install this version...")
{
addAndMakeVisible (&applyButton);
applyButton.addListener (this);
setInterceptsMouseClicks (false, true);
}
~UpdateListComponent()
{
applyButton.removeListener (this);
}
void setVersion (VersionInfo* v)
{
if (version != v)
{
version = v;
repaint();
resized();
}
}
void paint (Graphics& g)
{
if (version != nullptr)
{
g.setColour (Colours::green.withAlpha (0.12f));
g.fillRect (0, 1, getWidth(), getHeight() - 2);
g.setColour (Colours::black);
g.setFont (getHeight() * 0.7f);
String s;
s << "Version " << version->version << " - " << version->desc << " - " << version->date;
g.drawText (s, 4, 0, applyButton.getX() - 4, getHeight(), Justification::centredLeft, true);
}
}
void resized()
{
applyButton.changeWidthToFitText (getHeight() - 4);
applyButton.setTopRightPosition (getWidth(), 2);
applyButton.setVisible (version != nullptr);
}
AlertWindow::showMessageBox (AlertWindow::WarningIcon,
"Module Update",
"Couldn't create the target folder!");
return;
}
void buttonClicked (Button*)
{
updater.applyVersion (version);
}
StringArray itemsWanted;
private:
JuceUpdater& updater;
VersionInfo* version;
TextButton applyButton;
};
for (int i = latestList.modules.size(); --i >= 0;)
if (versionsToDownload [latestList.modules.getUnchecked(i)->uid])
itemsWanted.add (latestList.modules.getUnchecked(i)->uid);
UpdateListComponent* c = dynamic_cast <UpdateListComponent*> (existingComponentToUpdate);
if (c == nullptr)
c = new UpdateListComponent (*this);
{
InstallThread thread (moduleList, latestList, itemsWanted);
thread.runThread();
}
c->setVersion (availableVersions [rowNumber]);
return c;
moduleList.rescan();
refresh();
} }
void JuceUpdater::valueTreePropertyChanged (ValueTree&, const Identifier&) { updateInstallButtonStatus(); }
void JuceUpdater::valueTreeChildAdded (ValueTree&, ValueTree&) {}
void JuceUpdater::valueTreeChildRemoved (ValueTree&, ValueTree&) {}
void JuceUpdater::valueTreeChildOrderChanged (ValueTree&) {}
void JuceUpdater::valueTreeParentChanged (ValueTree&) {}

+ 33
- 23
extras/Introjucer/Source/Application/jucer_JuceUpdater.h View File

@@ -26,18 +26,21 @@
#ifndef __JUCER_JUCEUPDATER_JUCEHEADER__ #ifndef __JUCER_JUCEUPDATER_JUCEHEADER__
#define __JUCER_JUCEUPDATER_JUCEHEADER__ #define __JUCER_JUCEUPDATER_JUCEHEADER__
#include "../Project/jucer_Module.h"
//============================================================================== //==============================================================================
class JuceUpdater : public Component, class JuceUpdater : public Component,
public ButtonListener,
public FilenameComponentListener,
public ListBoxModel
private ButtonListener,
private FilenameComponentListener,
private ListBoxModel,
private ValueTree::Listener
{ {
public: public:
JuceUpdater();
JuceUpdater (ModuleList& moduleList);
~JuceUpdater(); ~JuceUpdater();
static void show (Component* mainWindow);
static void show (ModuleList& moduleList, Component* mainWindow);
//============================================================================== //==============================================================================
void resized(); void resized();
@@ -49,29 +52,36 @@ public:
void paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected); void paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected);
Component* refreshComponentForRow (int rowNumber, bool isRowSelected, Component* existingComponentToUpdate); Component* refreshComponentForRow (int rowNumber, bool isRowSelected, Component* existingComponentToUpdate);
void backgroundUpdateComplete (const ModuleList& newList);
private: private:
ModuleList& moduleList;
ModuleList latestList;
Label label, currentVersionLabel; Label label, currentVersionLabel;
FilenameComponent filenameComp; FilenameComponent filenameComp;
TextButton checkNowButton; TextButton checkNowButton;
ListBox availableVersionsList; ListBox availableVersionsList;
XmlElement* downloadVersionList();
String getCurrentVersion();
bool isAlreadyUpToDate();
struct VersionInfo
{
URL url;
String desc;
String version;
String date;
};
OwnedArray<VersionInfo> availableVersions;
void updateVersions (const XmlElement& xml);
void applyVersion (VersionInfo* version);
ValueTree versionsToDownload;
TextButton installButton;
ToggleButton selectAllButton;
ScopedPointer<Thread> websiteContacterThread;
void checkNow();
void install();
void updateInstallButtonStatus();
void refresh();
void selectAll();
int getNumCheckedModules() const;
bool isLatestVersion (const String& moduleID) const;
void valueTreePropertyChanged (ValueTree&, const Identifier&);
void valueTreeChildAdded (ValueTree&, ValueTree&);
void valueTreeChildRemoved (ValueTree&, ValueTree&);
void valueTreeChildOrderChanged (ValueTree&);
void valueTreeParentChanged (ValueTree&);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceUpdater);
}; };
#endif // __JUCER_JUCEUPDATER_JUCEHEADER__ #endif // __JUCER_JUCEUPDATER_JUCEHEADER__

+ 1
- 1
extras/Introjucer/Source/Application/jucer_MainWindow.cpp View File

@@ -30,7 +30,7 @@
#include "../Code Editor/jucer_SourceCodeEditor.h" #include "../Code Editor/jucer_SourceCodeEditor.h"
#include "../Project/jucer_NewProjectWizard.h" #include "../Project/jucer_NewProjectWizard.h"
ApplicationCommandManager* commandManager = nullptr;
ScopedPointer<ApplicationCommandManager> commandManager;
//============================================================================== //==============================================================================


+ 11
- 12
extras/Introjucer/Source/Project Saving/jucer_ProjectExporter.cpp View File

@@ -66,18 +66,18 @@ ProjectExporter* ProjectExporter::createNewExporter (Project& project, const int
switch (index) switch (index)
{ {
case 0: exp = new XCodeProjectExporter (project, ValueTree (XCodeProjectExporter::getValueTreeTypeName (false)), false); break;
case 1: exp = new XCodeProjectExporter (project, ValueTree (XCodeProjectExporter::getValueTreeTypeName (true)), true); break;
case 2: exp = new MSVCProjectExporterVC6 (project, ValueTree (MSVCProjectExporterVC6::getValueTreeTypeName())); break;
case 0: exp = new XCodeProjectExporter (project, ValueTree (XCodeProjectExporter ::getValueTreeTypeName (false)), false); break;
case 1: exp = new XCodeProjectExporter (project, ValueTree (XCodeProjectExporter ::getValueTreeTypeName (true)), true); break;
case 2: exp = new MSVCProjectExporterVC6 (project, ValueTree (MSVCProjectExporterVC6 ::getValueTreeTypeName())); break;
case 3: exp = new MSVCProjectExporterVC2005 (project, ValueTree (MSVCProjectExporterVC2005::getValueTreeTypeName())); break; case 3: exp = new MSVCProjectExporterVC2005 (project, ValueTree (MSVCProjectExporterVC2005::getValueTreeTypeName())); break;
case 4: exp = new MSVCProjectExporterVC2008 (project, ValueTree (MSVCProjectExporterVC2008::getValueTreeTypeName())); break; case 4: exp = new MSVCProjectExporterVC2008 (project, ValueTree (MSVCProjectExporterVC2008::getValueTreeTypeName())); break;
case 5: exp = new MSVCProjectExporterVC2010 (project, ValueTree (MSVCProjectExporterVC2010::getValueTreeTypeName())); break; case 5: exp = new MSVCProjectExporterVC2010 (project, ValueTree (MSVCProjectExporterVC2010::getValueTreeTypeName())); break;
case 6: exp = new MakefileProjectExporter (project, ValueTree (MakefileProjectExporter::getValueTreeTypeName())); break;
case 7: exp = new AndroidProjectExporter (project, ValueTree (AndroidProjectExporter::getValueTreeTypeName())); break;
case 6: exp = new MakefileProjectExporter (project, ValueTree (MakefileProjectExporter ::getValueTreeTypeName())); break;
case 7: exp = new AndroidProjectExporter (project, ValueTree (AndroidProjectExporter ::getValueTreeTypeName())); break;
default: jassertfalse; return 0; default: jassertfalse; return 0;
} }
File juceFolder (StoredSettings::getInstance()->getLastKnownJuceFolder());
File juceFolder (ModuleList::getLocalModulesFolder (&project));
File target (exp->getTargetFolder()); File target (exp->getTargetFolder());
if (FileHelpers::shouldPathsBeRelative (juceFolder.getFullPathName(), project.getFile().getFullPathName())) if (FileHelpers::shouldPathsBeRelative (juceFolder.getFullPathName(), project.getFile().getFullPathName()))
@@ -95,13 +95,13 @@ ProjectExporter* ProjectExporter::createNewExporter (Project& project, const Str
ProjectExporter* ProjectExporter::createExporter (Project& project, const ValueTree& settings) ProjectExporter* ProjectExporter::createExporter (Project& project, const ValueTree& settings)
{ {
ProjectExporter* exp = MSVCProjectExporterVC6::createForSettings (project, settings);
ProjectExporter* exp = MSVCProjectExporterVC6 ::createForSettings (project, settings);
if (exp == nullptr) exp = MSVCProjectExporterVC2005::createForSettings (project, settings); if (exp == nullptr) exp = MSVCProjectExporterVC2005::createForSettings (project, settings);
if (exp == nullptr) exp = MSVCProjectExporterVC2008::createForSettings (project, settings); if (exp == nullptr) exp = MSVCProjectExporterVC2008::createForSettings (project, settings);
if (exp == nullptr) exp = MSVCProjectExporterVC2010::createForSettings (project, settings); if (exp == nullptr) exp = MSVCProjectExporterVC2010::createForSettings (project, settings);
if (exp == nullptr) exp = XCodeProjectExporter::createForSettings (project, settings);
if (exp == nullptr) exp = MakefileProjectExporter::createForSettings (project, settings);
if (exp == nullptr) exp = AndroidProjectExporter::createForSettings (project, settings);
if (exp == nullptr) exp = XCodeProjectExporter ::createForSettings (project, settings);
if (exp == nullptr) exp = MakefileProjectExporter ::createForSettings (project, settings);
if (exp == nullptr) exp = AndroidProjectExporter ::createForSettings (project, settings);
jassert (exp != nullptr); jassert (exp != nullptr);
return exp; return exp;
@@ -115,7 +115,6 @@ ProjectExporter* ProjectExporter::createPlatformDefaultExporter (Project& projec
for (int i = 0; i < project.getNumExporters(); ++i) for (int i = 0; i < project.getNumExporters(); ++i)
{ {
ScopedPointer <ProjectExporter> exp (project.createExporter (i)); ScopedPointer <ProjectExporter> exp (project.createExporter (i));
const int pref = exp->getLaunchPreferenceOrderForCurrentOS(); const int pref = exp->getLaunchPreferenceOrderForCurrentOS();
if (pref > bestPref) if (pref > bestPref)
@@ -210,7 +209,7 @@ void ProjectExporter::createPropertyEditors (Array <PropertyComponent*>& props)
props.getLast()->setTooltip ("The location of the Juce library folder that the " + name + " project will use to when compiling. This can be an absolute path, or relative to the jucer project folder, but it must be valid on the filesystem of the machine you use to actually do the compiling."); props.getLast()->setTooltip ("The location of the Juce library folder that the " + name + " project will use to when compiling. This can be an absolute path, or relative to the jucer project folder, but it must be valid on the filesystem of the machine you use to actually do the compiling.");
OwnedArray<LibraryModule> modules; OwnedArray<LibraryModule> modules;
ModuleList moduleList;
ModuleList moduleList (ModuleList::getDefaultModulesFolder (&project));
project.createRequiredModules (moduleList, modules); project.createRequiredModules (moduleList, modules);
for (int i = 0; i < modules.size(); ++i) for (int i = 0; i < modules.size(); ++i)
modules.getUnchecked(i)->createPropertyEditors (*this, props); modules.getUnchecked(i)->createPropertyEditors (*this, props);


+ 1
- 1
extras/Introjucer/Source/Project Saving/jucer_ProjectSaver.h View File

@@ -61,7 +61,7 @@ public:
OwnedArray<LibraryModule> modules; OwnedArray<LibraryModule> modules;
{ {
ModuleList moduleList;
ModuleList moduleList (ModuleList::getDefaultModulesFolder (&project));
project.createRequiredModules (moduleList, modules); project.createRequiredModules (moduleList, modules);
} }


+ 129
- 20
extras/Introjucer/Source/Project/jucer_Module.cpp View File

@@ -31,9 +31,94 @@
//============================================================================== //==============================================================================
ModuleList::ModuleList()
ModuleList::ModuleList (const File& modulesFolder_)
{ {
rescan();
rescan (modulesFolder_);
}
ModuleList::ModuleList (const ModuleList& other)
: moduleFolder (other.moduleFolder)
{
modules.addCopiesOf (other.modules);
}
ModuleList& ModuleList::operator= (const ModuleList& other)
{
moduleFolder = other.moduleFolder;
modules.clear();
modules.addCopiesOf (other.modules);
return *this;
}
bool ModuleList::operator== (const ModuleList& other) const
{
if (modules.size() != other.modules.size())
return false;
for (int i = modules.size(); --i >= 0;)
{
const Module* m1 = modules.getUnchecked(i);
const Module* m2 = other.findModuleInfo (m1->uid);
if (m2 == nullptr || *m1 != *m2)
return false;
}
return true;
}
File ModuleList::getModulesFolderForJuceOrModulesFolder (const File& f)
{
if (f.getFileName() != "modules" && f.isDirectory() && f.getChildFile ("modules").isDirectory())
return f.getChildFile ("modules");
return f;
}
File ModuleList::getDefaultModulesFolder (Project* project)
{
if (project != nullptr)
{
ScopedPointer <ProjectExporter> exp (ProjectExporter::createPlatformDefaultExporter (*project));
if (exp != nullptr)
{
File f (project->resolveFilename (exp->getJuceFolder().toString()));
f = getModulesFolderForJuceOrModulesFolder (f);
if (FileHelpers::isModulesFolder (f))
return f;
}
}
return File::getSpecialLocation (File::userHomeDirectory)
.getChildFile ("juce")
.getChildFile ("modules");
}
File ModuleList::getLocalModulesFolder (Project* project)
{
File defaultJuceFolder (getDefaultModulesFolder (project));
File f (StoredSettings::getInstance()->getProps().getValue ("lastJuceFolder", defaultJuceFolder.getFullPathName()));
f = getModulesFolderForJuceOrModulesFolder (f);
if ((! FileHelpers::isModulesFolder (f)) && FileHelpers::isModulesFolder (defaultJuceFolder))
f = defaultJuceFolder;
return f;
}
File ModuleList::getModuleFolder (const String& uid) const
{
return getModulesFolder().getChildFile (uid);
}
void ModuleList::setLocalModulesFolder (const File& file)
{
//jassert (FileHelpers::isJuceFolder (file));
StoredSettings::getInstance()->getProps().setValue ("lastJuceFolder", file.getFullPathName());
} }
struct ModuleSorter struct ModuleSorter
@@ -52,30 +137,38 @@ void ModuleList::sort()
void ModuleList::rescan() void ModuleList::rescan()
{ {
modules.clear();
moduleFolder = StoredSettings::getInstance()->getLastKnownJuceFolder().getChildFile ("modules");
rescan (moduleFolder);
}
DirectoryIterator iter (moduleFolder, false, "*", File::findDirectories);
void ModuleList::rescan (const File& newModulesFolder)
{
modules.clear();
moduleFolder = getModulesFolderForJuceOrModulesFolder (newModulesFolder);
while (iter.next())
if (moduleFolder.isDirectory())
{ {
const File moduleDef (iter.getFile().getChildFile (LibraryModule::getInfoFileName()));
DirectoryIterator iter (moduleFolder, false, "*", File::findDirectories);
if (moduleDef.exists())
while (iter.next())
{ {
LibraryModule m (moduleDef);
jassert (m.isValid());
const File moduleDef (iter.getFile().getChildFile (LibraryModule::getInfoFileName()));
if (m.isValid())
if (moduleDef.exists())
{ {
Module* info = new Module();
modules.add (info);
info->uid = m.getID();
info->version = m.getVersion();
info->name = m.moduleInfo ["name"];
info->description = m.moduleInfo ["description"];
info->file = moduleDef;
LibraryModule m (moduleDef);
jassert (m.isValid());
if (m.isValid())
{
Module* info = new Module();
modules.add (info);
info->uid = m.getID();
info->version = m.getVersion();
info->name = m.moduleInfo ["name"];
info->description = m.moduleInfo ["description"];
info->file = moduleDef;
}
} }
} }
} }
@@ -83,7 +176,7 @@ void ModuleList::rescan()
sort(); sort();
} }
void ModuleList::loadFromWebsite()
bool ModuleList::loadFromWebsite()
{ {
modules.clear(); modules.clear();
@@ -122,6 +215,7 @@ void ModuleList::loadFromWebsite()
} }
sort(); sort();
return infoList.isArray();
} }
LibraryModule* ModuleList::Module::create() const LibraryModule* ModuleList::Module::create() const
@@ -129,6 +223,21 @@ LibraryModule* ModuleList::Module::create() const
return new LibraryModule (file); return new LibraryModule (file);
} }
bool ModuleList::Module::operator== (const Module& other) const
{
return uid == other.uid
&& version == other.version
&& name == other.name
&& description == other.description
&& file == other.file
&& url == other.url;
}
bool ModuleList::Module::operator!= (const Module& other) const
{
return ! operator== (other);
}
LibraryModule* ModuleList::loadModule (const String& uid) const LibraryModule* ModuleList::loadModule (const String& uid) const
{ {
const Module* const m = findModuleInfo (uid); const Module* const m = findModuleInfo (uid);


+ 22
- 2
extras/Introjucer/Source/Project/jucer_Module.h View File

@@ -86,11 +86,17 @@ private:
class ModuleList class ModuleList
{ {
public: public:
ModuleList();
ModuleList (const File& modulesFolder);
ModuleList (const ModuleList&);
ModuleList& operator= (const ModuleList&);
//============================================================================== //==============================================================================
void rescan (const File& newModulesFolder);
void rescan(); void rescan();
void loadFromWebsite();
File getModulesFolder() const { return moduleFolder; }
File getModuleFolder (const String& uid) const;
bool loadFromWebsite();
LibraryModule* loadModule (const String& uid) const; LibraryModule* loadModule (const String& uid) const;
@@ -105,10 +111,24 @@ public:
String uid, version, name, description; String uid, version, name, description;
File file; File file;
URL url; URL url;
bool operator== (const Module&) const;
bool operator!= (const Module&) const;
}; };
const Module* findModuleInfo (const String& uid) const; const Module* findModuleInfo (const String& uid) const;
bool operator== (const ModuleList&) const;
//==============================================================================
static File getDefaultModulesFolder (Project* project);
static File getLocalModulesFolder (Project* project);
static void setLocalModulesFolder (const File& newFile);
static File getModulesFolderForJuceOrModulesFolder (const File& f);
//==============================================================================
OwnedArray<Module> modules; OwnedArray<Module> modules;
private: private:


+ 2
- 1
extras/Introjucer/Source/Project/jucer_NewProjectWizard.cpp View File

@@ -25,6 +25,7 @@
#include "jucer_NewProjectWizard.h" #include "jucer_NewProjectWizard.h"
#include "jucer_ProjectType.h" #include "jucer_ProjectType.h"
#include "jucer_Module.h"
//============================================================================== //==============================================================================
class GUIAppWizard : public NewProjectWizard class GUIAppWizard : public NewProjectWizard
@@ -451,7 +452,7 @@ Project* NewProjectWizard::runNewProjectWizard (Component* ownerWindow)
aw.addComboBox ("type", getWizards(), "Project Type"); aw.addComboBox ("type", getWizards(), "Project Type");
FilenameComponent juceFolderSelector ("Juce Library Location", StoredSettings::getInstance()->getLastKnownJuceFolder(),
FilenameComponent juceFolderSelector ("Juce Library Location", ModuleList::getLocalModulesFolder (nullptr),
true, true, false, "*", String::empty, "(Please select the folder containing Juce!)"); true, true, false, "*", String::empty, "(Please select the folder containing Juce!)");
juceFolderSelector.setSize (350, 22); juceFolderSelector.setSize (350, 22);


+ 0
- 12
extras/Introjucer/Source/Project/jucer_Project.cpp View File

@@ -177,18 +177,6 @@ const String Project::saveDocument (const File& file)
updateProjectSettings(); updateProjectSettings();
sanitiseConfigFlags(); sanitiseConfigFlags();
{
ScopedPointer <ProjectExporter> exp (ProjectExporter::createPlatformDefaultExporter (*this));
if (exp != nullptr)
{
File f (resolveFilename (exp->getJuceFolder().toString()));
if (FileHelpers::isJuceFolder (f))
StoredSettings::getInstance()->setLastKnownJuceFolder (f.getFullPathName());
}
}
StoredSettings::getInstance()->recentFiles.addFile (file); StoredSettings::getInstance()->recentFiles.addFile (file);
ProjectSaver saver (*this, file); ProjectSaver saver (*this, file);


+ 46
- 31
extras/Introjucer/Source/Project/jucer_ProjectInformationComponent.cpp View File

@@ -19,6 +19,7 @@
//[CppHeaders] You can add your own extra header files here... //[CppHeaders] You can add your own extra header files here...
#include "../Project Saving/jucer_ProjectExporter.h" #include "../Project Saving/jucer_ProjectExporter.h"
#include "jucer_Module.h" #include "jucer_Module.h"
#include "../Application/jucer_JuceUpdater.h"
//[/CppHeaders] //[/CppHeaders]
#include "jucer_ProjectInformationComponent.h" #include "jucer_ProjectInformationComponent.h"
@@ -126,7 +127,7 @@ public:
ModuleSettingsPanel (Project& project_, ModuleList& moduleList_, const String& moduleID_) ModuleSettingsPanel (Project& project_, ModuleList& moduleList_, const String& moduleID_)
: PanelBase (project_), moduleList (moduleList_), moduleID (moduleID_) : PanelBase (project_), moduleList (moduleList_), moduleID (moduleID_)
{ {
setBounds ("parent.width / 2 + 1, 3, parent.width - 3, parent.height - 3");
setBounds ("parent.width / 2 + 1, 31, parent.width - 3, parent.height - 3");
} }
void rebuildProperties (Array <PropertyComponent*>& props) void rebuildProperties (Array <PropertyComponent*>& props)
@@ -207,7 +208,7 @@ private:
if (module != nullptr) if (module != nullptr)
{ {
String text; String text;
text << module->name << newLine << newLine
text << module->name << newLine << "Version: " << module->version << newLine << newLine
<< module->description; << module->description;
GlyphArrangement ga; GlyphArrangement ga;
@@ -279,16 +280,34 @@ private:
//============================================================================== //==============================================================================
class ModulesPanel : public Component, class ModulesPanel : public Component,
public ListBoxModel
public ListBoxModel,
public FilenameComponentListener,
public ButtonListener
{ {
public: public:
ModulesPanel (Project& project_) ModulesPanel (Project& project_)
: project (project_)
: project (project_),
moduleList (ModuleList::getLocalModulesFolder (&project)),
modulesLocation ("modules", moduleList.getModulesFolder(),
true, true, false, "*", String::empty,
"Select a folder containing your JUCE modules..."),
modulesLabel (String::empty, "Module source folder:"),
updateModulesButton ("Check for module updates...")
{ {
addAndMakeVisible (&modulesLocation);
modulesLocation.setBounds ("150, 3, parent.width - 180, 28");
modulesLocation.addListener (this);
modulesLabel.attachToComponent (&modulesLocation, true);
addAndMakeVisible (&updateModulesButton);
updateModulesButton.setBounds ("parent.width - 175, 3, parent.width - 4, 28");
updateModulesButton.addListener (this);
modulesList.setModel (this); modulesList.setModel (this);
modulesList.setColour (ListBox::backgroundColourId, Colours::white.withAlpha (0.4f)); modulesList.setColour (ListBox::backgroundColourId, Colours::white.withAlpha (0.4f));
addAndMakeVisible (&modulesList); addAndMakeVisible (&modulesList);
modulesList.setBounds ("4, 3, parent.width / 2 - 4, parent.height - 3");
modulesList.setBounds ("4, 31, parent.width / 2 - 4, parent.height - 3");
} }
int getNumRows() int getNumRows()
@@ -330,36 +349,29 @@ public:
if (m != nullptr) if (m != nullptr)
{ {
if (project.isModuleEnabled (m->uid)) if (project.isModuleEnabled (m->uid))
{
project.removeModule (m->uid); project.removeModule (m->uid);
}
else else
{
const StringArray extraDepsNeeded (getExtraDependenciesNeeded (project, moduleList, *m));
/* if (extraDepsNeeded.size() > 0)
{
if (AlertWindow::showOkCancelBox (AlertWindow::NoIcon,
"Module Dependencies",
"The '" + m->uid + "' module requires the following dependencies:\n"
+ extraDepsNeeded.joinIntoString (", ") + "\n\nDo you want to add all these to your project?"))
{
project.addModule (m->uid);
for (int i = extraDepsNeeded.size(); --i >= 0;)
project.addModule (extraDepsNeeded[i]);
}
}
else*/
{
project.addModule (m->uid);
}
}
project.addModule (m->uid);
} }
refresh(); refresh();
} }
void filenameComponentChanged (FilenameComponent*)
{
moduleList.rescan (modulesLocation.getCurrentFile());
modulesLocation.setCurrentFile (moduleList.getModulesFolder(), false, false);
ModuleList::setLocalModulesFolder (moduleList.getModulesFolder());
modulesList.updateContent();
}
void buttonClicked (Button*)
{
JuceUpdater::show (moduleList, getTopLevelComponent());
filenameComponentChanged (nullptr);
}
void listBoxItemClicked (int row, const MouseEvent& e) void listBoxItemClicked (int row, const MouseEvent& e)
{ {
if (e.x < modulesList.getRowHeight()) if (e.x < modulesList.getRowHeight())
@@ -397,6 +409,9 @@ public:
private: private:
Project& project; Project& project;
ModuleList moduleList; ModuleList moduleList;
FilenameComponent modulesLocation;
Label modulesLabel;
TextButton updateModulesButton;
ListBox modulesList; ListBox modulesList;
ScopedPointer<ModuleSettingsPanel> settings; ScopedPointer<ModuleSettingsPanel> settings;
}; };
@@ -440,16 +455,16 @@ ProjectInformationComponent::ProjectInformationComponent (Project& project_)
//[UserPreSize] //[UserPreSize]
rebuildConfigTabs(); rebuildConfigTabs();
#if JUCE_MAC || JUCE_WINDOWS
#if JUCE_MAC || JUCE_WINDOWS
openProjectButton.setCommandToTrigger (commandManager, CommandIDs::openInIDE, true); openProjectButton.setCommandToTrigger (commandManager, CommandIDs::openInIDE, true);
openProjectButton.setButtonText (commandManager->getNameOfCommand (CommandIDs::openInIDE)); openProjectButton.setButtonText (commandManager->getNameOfCommand (CommandIDs::openInIDE));
saveAndOpenButton.setCommandToTrigger (commandManager, CommandIDs::saveAndOpenInIDE, true); saveAndOpenButton.setCommandToTrigger (commandManager, CommandIDs::saveAndOpenInIDE, true);
saveAndOpenButton.setButtonText (commandManager->getNameOfCommand (CommandIDs::saveAndOpenInIDE)); saveAndOpenButton.setButtonText (commandManager->getNameOfCommand (CommandIDs::saveAndOpenInIDE));
#else
#else
openProjectButton.setVisible (false); openProjectButton.setVisible (false);
saveAndOpenButton.setVisible (false); saveAndOpenButton.setVisible (false);
#endif
#endif
//[/UserPreSize] //[/UserPreSize]
setSize (836, 427); setSize (836, 427);


+ 8
- 15
extras/Introjucer/Source/Utility/jucer_FileHelpers.cpp View File

@@ -150,10 +150,16 @@ namespace FileHelpers
bool isJuceFolder (const File& folder) bool isJuceFolder (const File& folder)
{ {
return folder.getFileName().containsIgnoreCase ("juce") return folder.getFileName().containsIgnoreCase ("juce")
&& folder.getChildFile ("modules").isDirectory();
&& isModulesFolder (folder.getChildFile ("modules"));
} }
static File lookInFolderForJuceFolder (const File& folder)
bool isModulesFolder (const File& folder)
{
return folder.getFileName().equalsIgnoreCase ("modules")
&& folder.isDirectory();
}
File lookInFolderForJuceFolder (const File& folder)
{ {
for (DirectoryIterator di (folder, false, "*juce*", File::findDirectories); di.next();) for (DirectoryIterator di (folder, false, "*juce*", File::findDirectories); di.next();)
{ {
@@ -182,17 +188,4 @@ namespace FileHelpers
return File::nonexistent; return File::nonexistent;
} }
File findDefaultJuceFolder()
{
File f = findParentJuceFolder (File::getSpecialLocation (File::currentApplicationFile));
if (! f.exists())
f = lookInFolderForJuceFolder (File::getSpecialLocation (File::userHomeDirectory));
if (! f.exists())
f = lookInFolderForJuceFolder (File::getSpecialLocation (File::userDocumentsDirectory));
return f;
}
} }

+ 2
- 1
extras/Introjucer/Source/Utility/jucer_FileHelpers.h View File

@@ -46,8 +46,9 @@ namespace FileHelpers
//============================================================================== //==============================================================================
bool isJuceFolder (const File& folder); bool isJuceFolder (const File& folder);
bool isModulesFolder (const File& folder);
File findParentJuceFolder (const File& file); File findParentJuceFolder (const File& file);
File findDefaultJuceFolder();
File lookInFolderForJuceFolder (const File& folder);
} }
//============================================================================== //==============================================================================


+ 0
- 17
extras/Introjucer/Source/Utility/jucer_StoredSettings.cpp View File

@@ -143,23 +143,6 @@ void StoredSettings::setLastProjects (const Array<File>& files)
props->setValue ("lastProjects", s.joinIntoString ("|")); props->setValue ("lastProjects", s.joinIntoString ("|"));
} }
File StoredSettings::getLastKnownJuceFolder() const
{
File defaultJuceFolder (FileHelpers::findDefaultJuceFolder());
File f (props->getValue ("lastJuceFolder", defaultJuceFolder.getFullPathName()));
if ((! FileHelpers::isJuceFolder (f)) && FileHelpers::isJuceFolder (defaultJuceFolder))
f = defaultJuceFolder;
return f;
}
void StoredSettings::setLastKnownJuceFolder (const File& file)
{
jassert (FileHelpers::isJuceFolder (file));
props->setValue ("lastJuceFolder", file.getFullPathName());
}
const StringArray& StoredSettings::getFontNames() const StringArray& StoredSettings::getFontNames()
{ {
if (fontNames.size() == 0) if (fontNames.size() == 0)


+ 0
- 3
extras/Introjucer/Source/Utility/jucer_StoredSettings.h View File

@@ -50,9 +50,6 @@ public:
Array<File> getLastProjects() const; Array<File> getLastProjects() const;
void setLastProjects (const Array<File>& files); void setLastProjects (const Array<File>& files);
File getLastKnownJuceFolder() const;
void setLastKnownJuceFolder (const File& file);
const StringArray& getFontNames(); const StringArray& getFontNames();
//============================================================================== //==============================================================================


+ 1
- 1
modules/juce_core/system/juce_StandardHeader.h View File

@@ -33,7 +33,7 @@
*/ */
#define JUCE_MAJOR_VERSION 2 #define JUCE_MAJOR_VERSION 2
#define JUCE_MINOR_VERSION 0 #define JUCE_MINOR_VERSION 0
#define JUCE_BUILDNUMBER 4
#define JUCE_BUILDNUMBER 5
/** Current Juce version number. /** Current Juce version number.


Loading…
Cancel
Save