| @@ -122,6 +122,7 @@ | |||
| 18D9EBA1DAE45EEF81FD5C8F = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_MainConsoleAppTemplate.cpp"; path = "../../Source/BinaryData/jucer_MainConsoleAppTemplate.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| 193908A02BA553DB5B30D759 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ScopedLock.h"; path = "../../../../modules/juce_core/threads/juce_ScopedLock.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| 199722DD9BA0E30C0506941E = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_MouseListener.cpp"; path = "../../../../modules/juce_gui_basics/mouse/juce_MouseListener.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| 19B46FEFF7C614EB69BCDF61 = { isa = PBXFileReference; lastKnownFileType = file.svg; name = "cog_icon.svg"; path = "../../Source/BinaryData/cog_icon.svg"; sourceTree = "SOURCE_ROOT"; }; | |||
| 1A1B5A2E9F1DA2122D21F9DF = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ScopedPointer.h"; path = "../../../../modules/juce_core/memory/juce_ScopedPointer.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| 1A1C8AEC3C5AB2E972B0212E = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MD5.h"; path = "../../../../modules/juce_cryptography/hashing/juce_MD5.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| 1A79A64F47F7B5083EEBB328 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ActionListener.h"; path = "../../../../modules/juce_events/broadcasters/juce_ActionListener.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| @@ -599,9 +600,7 @@ | |||
| C85B4D62B96F4A44890F20E2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_SortedSet.h"; path = "../../../../modules/juce_core/containers/juce_SortedSet.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| C90C66C5727759D5CBD5FB07 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_AbstractFifo.cpp"; path = "../../../../modules/juce_core/containers/juce_AbstractFifo.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| C9871C46DEDD05103443DC33 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_NewLine.h"; path = "../../../../modules/juce_core/text/juce_NewLine.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| CBE0B96838EE76C9CB8E1230 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ColourGradient.cpp"; path = "../../../../modules/juce_graphics/colour/juce_ColourGradient.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| CC63B9EC2E95FD4AF7608D8E = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_CharacterFunctions.h"; path = "../../../../modules/juce_core/text/juce_CharacterFunctions.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| CD3216F23C7B273B010A8D12 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_CustomTypeface.h"; path = "../../../../modules/juce_graphics/fonts/juce_CustomTypeface.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| CF6C8BD0DA3D8CD4E99EBADA = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; | |||
| CF8011B3C67B609032974DA5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_NewCppFileTemplate.cpp"; path = "../../Source/BinaryData/jucer_NewCppFileTemplate.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| D00F311BFC3C2625C457CB9B = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; }; | |||
| @@ -617,8 +616,10 @@ | |||
| CA62F9F7C5F0D77D8E33D91F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_SplashScreen.h"; path = "../../../../modules/juce_gui_extra/misc/juce_SplashScreen.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| CB36CD7F57D0F4231DC98686 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Message.h"; path = "../../../../modules/juce_events/messages/juce_Message.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| CB48495010366C2E371BEFDB = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_SystemStats.cpp"; path = "../../../../modules/juce_core/system/juce_SystemStats.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| CBE0B96838EE76C9CB8E1230 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ColourGradient.cpp"; path = "../../../../modules/juce_graphics/colour/juce_ColourGradient.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| CC3F5263B16932FF4E74B9D8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_CodeEditorComponent.h"; path = "../../../../modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| CD140A1C0161176682F6CA29 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ResizableWindow.cpp"; path = "../../../../modules/juce_gui_basics/windows/juce_ResizableWindow.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| CD3216F23C7B273B010A8D12 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_CustomTypeface.h"; path = "../../../../modules/juce_graphics/fonts/juce_CustomTypeface.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| CD8F40A9EF6ECAD083543974 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_WildcardFileFilter.h"; path = "../../../../modules/juce_gui_basics/filebrowser/juce_WildcardFileFilter.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| CDCAF0EC777DA2884AEB2B59 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Label.cpp"; path = "../../../../modules/juce_gui_basics/widgets/juce_Label.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| CDDF5BDC75277F7B83A38885 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_PropertySet.cpp"; path = "../../../../modules/juce_core/containers/juce_PropertySet.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| @@ -817,6 +818,8 @@ | |||
| 88DFD62CB6545EE8CA5C485B = { isa = PBXGroup; children = ( | |||
| 5F4F4EAB042F2730F94A1CEA, | |||
| 7074AEDE4B0416BC898DD27A, | |||
| 19B46FEFF7C614EB69BCDF61, | |||
| B483D960309FAFC193F9CDA2, | |||
| 0075C5208947159AF2802F3B, | |||
| AFF72BA2B130F3F9AC029080, | |||
| 65F4749184C84C2FDBB4C305, | |||
| @@ -826,8 +829,7 @@ | |||
| CF8011B3C67B609032974DA5, | |||
| 53151B683E11F420203E61C2, | |||
| 087959CCC447DA59FBD5787E, | |||
| 7DF304ACC22704A1B2454B68, | |||
| B483D960309FAFC193F9CDA2 ); name = BinaryData; sourceTree = "<group>"; }; | |||
| 7DF304ACC22704A1B2454B68 ); name = BinaryData; sourceTree = "<group>"; }; | |||
| D3109994DA6AD871BE85C4E2 = { isa = PBXGroup; children = ( | |||
| ACBAFA7D92DD82AD44ABE68A, | |||
| 891F84627A03FA733F37A199, | |||
| @@ -223,6 +223,26 @@ | |||
| <Tool Name="VCCLCompilerTool"/> | |||
| </FileConfiguration> | |||
| </File> | |||
| <File RelativePath="..\..\Source\BinaryData\cog_icon.svg"> | |||
| <FileConfiguration Name="Debug|Win32" | |||
| ExcludedFromBuild="true"> | |||
| <Tool Name="VCCLCompilerTool"/> | |||
| </FileConfiguration> | |||
| <FileConfiguration Name="Release|Win32" | |||
| ExcludedFromBuild="true"> | |||
| <Tool Name="VCCLCompilerTool"/> | |||
| </FileConfiguration> | |||
| </File> | |||
| <File RelativePath="..\..\Source\BinaryData\juce_icon.png"> | |||
| <FileConfiguration Name="Debug|Win32" | |||
| ExcludedFromBuild="true"> | |||
| <Tool Name="VCCLCompilerTool"/> | |||
| </FileConfiguration> | |||
| <FileConfiguration Name="Release|Win32" | |||
| ExcludedFromBuild="true"> | |||
| <Tool Name="VCCLCompilerTool"/> | |||
| </FileConfiguration> | |||
| </File> | |||
| <File RelativePath="..\..\Source\BinaryData\jucer_AudioPluginEditorTemplate.cpp"> | |||
| <FileConfiguration Name="Debug|Win32" | |||
| ExcludedFromBuild="true"> | |||
| @@ -323,16 +343,6 @@ | |||
| <Tool Name="VCCLCompilerTool"/> | |||
| </FileConfiguration> | |||
| </File> | |||
| <File RelativePath="..\..\Source\BinaryData\juce_icon.png"> | |||
| <FileConfiguration Name="Debug|Win32" | |||
| ExcludedFromBuild="true"> | |||
| <Tool Name="VCCLCompilerTool"/> | |||
| </FileConfiguration> | |||
| <FileConfiguration Name="Release|Win32" | |||
| ExcludedFromBuild="true"> | |||
| <Tool Name="VCCLCompilerTool"/> | |||
| </FileConfiguration> | |||
| </File> | |||
| </Filter> | |||
| </Filter> | |||
| <Filter Name="Juce Modules"> | |||
| @@ -223,6 +223,26 @@ | |||
| <Tool Name="VCCLCompilerTool"/> | |||
| </FileConfiguration> | |||
| </File> | |||
| <File RelativePath="..\..\Source\BinaryData\cog_icon.svg"> | |||
| <FileConfiguration Name="Debug|Win32" | |||
| ExcludedFromBuild="true"> | |||
| <Tool Name="VCCLCompilerTool"/> | |||
| </FileConfiguration> | |||
| <FileConfiguration Name="Release|Win32" | |||
| ExcludedFromBuild="true"> | |||
| <Tool Name="VCCLCompilerTool"/> | |||
| </FileConfiguration> | |||
| </File> | |||
| <File RelativePath="..\..\Source\BinaryData\juce_icon.png"> | |||
| <FileConfiguration Name="Debug|Win32" | |||
| ExcludedFromBuild="true"> | |||
| <Tool Name="VCCLCompilerTool"/> | |||
| </FileConfiguration> | |||
| <FileConfiguration Name="Release|Win32" | |||
| ExcludedFromBuild="true"> | |||
| <Tool Name="VCCLCompilerTool"/> | |||
| </FileConfiguration> | |||
| </File> | |||
| <File RelativePath="..\..\Source\BinaryData\jucer_AudioPluginEditorTemplate.cpp"> | |||
| <FileConfiguration Name="Debug|Win32" | |||
| ExcludedFromBuild="true"> | |||
| @@ -323,16 +343,6 @@ | |||
| <Tool Name="VCCLCompilerTool"/> | |||
| </FileConfiguration> | |||
| </File> | |||
| <File RelativePath="..\..\Source\BinaryData\juce_icon.png"> | |||
| <FileConfiguration Name="Debug|Win32" | |||
| ExcludedFromBuild="true"> | |||
| <Tool Name="VCCLCompilerTool"/> | |||
| </FileConfiguration> | |||
| <FileConfiguration Name="Release|Win32" | |||
| ExcludedFromBuild="true"> | |||
| <Tool Name="VCCLCompilerTool"/> | |||
| </FileConfiguration> | |||
| </File> | |||
| </Filter> | |||
| </Filter> | |||
| <Filter Name="Juce Modules"> | |||
| @@ -1331,6 +1331,7 @@ | |||
| <ItemGroup> | |||
| <None Include="..\..\Source\BinaryData\AudioPluginXCodeScript.txt"/> | |||
| <None Include="..\..\Source\BinaryData\brushed_aluminium.png"/> | |||
| <None Include="..\..\Source\BinaryData\cog_icon.svg"/> | |||
| <None Include="..\..\Source\BinaryData\juce_icon.png"/> | |||
| <None Include="..\..\..\..\modules\juce_core\juce_module_info"/> | |||
| <None Include="..\..\..\..\modules\juce_cryptography\juce_module_info"/> | |||
| @@ -2288,6 +2288,9 @@ | |||
| <None Include="..\..\Source\BinaryData\brushed_aluminium.png"> | |||
| <Filter>The Introjucer\BinaryData</Filter> | |||
| </None> | |||
| <None Include="..\..\Source\BinaryData\cog_icon.svg"> | |||
| <Filter>The Introjucer\BinaryData</Filter> | |||
| </None> | |||
| <None Include="..\..\Source\BinaryData\juce_icon.png"> | |||
| <Filter>The Introjucer\BinaryData</Filter> | |||
| </None> | |||
| @@ -203,6 +203,8 @@ | |||
| file="Source/BinaryData/AudioPluginXCodeScript.txt"/> | |||
| <FILE id="mDywA9N" name="brushed_aluminium.png" compile="0" resource="1" | |||
| file="Source/BinaryData/brushed_aluminium.png"/> | |||
| <FILE id="bvFeOg" name="cog_icon.svg" compile="0" resource="1" file="Source/BinaryData/cog_icon.svg"/> | |||
| <FILE id="rVgowdy" name="juce_icon.png" compile="0" resource="1" file="Source/BinaryData/juce_icon.png"/> | |||
| <FILE id="8H7vztx" name="jucer_AudioPluginEditorTemplate.cpp" compile="0" | |||
| resource="1" file="Source/BinaryData/jucer_AudioPluginEditorTemplate.cpp"/> | |||
| <FILE id="908LsXi" name="jucer_AudioPluginEditorTemplate.h" compile="0" | |||
| @@ -223,7 +225,6 @@ | |||
| file="Source/BinaryData/jucer_WindowTemplate.cpp"/> | |||
| <FILE id="2WpRpdr" name="jucer_WindowTemplate.h" compile="0" resource="1" | |||
| file="Source/BinaryData/jucer_WindowTemplate.h"/> | |||
| <FILE id="rVgowdy" name="juce_icon.png" compile="0" resource="1" file="Source/BinaryData/juce_icon.png"/> | |||
| </GROUP> | |||
| </MAINGROUP> | |||
| <JUCEOPTIONS JUCE_ASIO="disabled" JUCE_WASAPI="disabled" JUCE_DIRECTSOUND="disabled" | |||
| @@ -13,6 +13,12 @@ namespace BinaryData | |||
| extern const char* brushed_aluminium_png; | |||
| const int brushed_aluminium_pngSize = 14724; | |||
| extern const char* cog_icon_svg; | |||
| const int cog_icon_svgSize = 915; | |||
| extern const char* juce_icon_png; | |||
| const int juce_icon_pngSize = 19826; | |||
| extern const char* jucer_AudioPluginEditorTemplate_cpp; | |||
| const int jucer_AudioPluginEditorTemplate_cppSize = 1008; | |||
| @@ -43,9 +49,6 @@ namespace BinaryData | |||
| extern const char* jucer_WindowTemplate_h; | |||
| const int jucer_WindowTemplate_hSize = 1216; | |||
| extern const char* juce_icon_png; | |||
| const int juce_icon_pngSize = 19826; | |||
| // If you provide the name of one of the binary resource variables above, this function will | |||
| // return the corresponding data and its size (or a null pointer if the name isn't found). | |||
| const char* getNamedResource (const char* resourceNameUTF8, int& dataSizeInBytes) throw(); | |||
| @@ -123,14 +123,21 @@ public: | |||
| void closeWindow (MainWindow* w) | |||
| { | |||
| jassert (mainWindows.contains (w)); | |||
| mainWindows.removeObject (w); | |||
| #if ! JUCE_MAC | |||
| if (mainWindows.size() == 0) | |||
| if (mainWindows.size() == 1) | |||
| { | |||
| systemRequestedQuit(); | |||
| } | |||
| else | |||
| #endif | |||
| updateRecentProjectList(); | |||
| { | |||
| if (w->closeCurrentProject()) | |||
| { | |||
| mainWindows.removeObject (w); | |||
| updateRecentProjectList(); | |||
| } | |||
| } | |||
| } | |||
| //============================================================================== | |||
| @@ -114,9 +114,6 @@ ProjectContentComponent* MainWindow::getProjectContentComponent() const | |||
| void MainWindow::closeButtonPressed() | |||
| { | |||
| if (! closeCurrentProject()) | |||
| return; | |||
| JucerApplication::getApp()->closeWindow (this); | |||
| } | |||
| @@ -0,0 +1,7 @@ | |||
| <svg width="155" height="155"> | |||
| <g> | |||
| <path | |||
| style="color:#000000;fill:#889977;fill-opacity:1;fill-rule:nonzero;stroke:#333333;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;" | |||
| d="m 336,565 c -1,0 -3,0 -5,0 l -0,0 -4,20 c -6,1 -12,4 -17,7 L 294,581 c -4,4 -8,8 -12,12 l 12,17 c -3,5 -6,11 -8,18 0,0 0,0 0,0 l -20,3 c -0,3 -1,6 0,9 0,3 0,5 0,7 l 20,3 c 1,7 4,13 8,20 l -12,16 c 3,4 7,8 12,12 l 17,-12 c 6,4 13,7 20,8 l 3,20 c 2,0 4,0 7,0 3,0 6,0 10,0 l 4,-20 c 7,-2 13,-5 19,-9 l 17,12 c 4,-4 8,-8 12,-12 l -12,-17 c 3,-6 6,-12 7,-18 l 20,-3 c 0,-2 0,-4 0,-6 0,-4 0,-7 -1,-11 l -21,-4 c -2,-6 -4,-12 -8,-17 l 12,-17 c -4,-5 -8,-8 -13,-12 l -17,12 c -5,-3 -10,-5 -16,-7 l -3,-20 c -3,0 -6,0 -9,0 -1,0 -2,0 -2,0 0,0 -1,0 -1,0 0,0 0,0 0,0 z m 3,52 c 0,0 1,0 1,0 13,0 23,10 23,23 0,13 -10,23 -23,23 -13,0 -23,-10 -23,-23 0,-12 9,-22 22,-23 z"/> | |||
| </g> | |||
| </svg> | |||
| @@ -350,10 +350,10 @@ void ProjectExporter::addNewConfiguration (const BuildConfiguration* configToCop | |||
| configs.addChild (newConfig, -1, project.getUndoManagerFor (configs)); | |||
| } | |||
| void ProjectExporter::deleteConfiguration (int index) | |||
| void ProjectExporter::BuildConfiguration::removeFromExporter() | |||
| { | |||
| ValueTree configs (getConfigurations()); | |||
| configs.removeChild (index, project.getUndoManagerFor (configs)); | |||
| ValueTree configs (config.getParent()); | |||
| configs.removeChild (config, project.getUndoManagerFor (configs)); | |||
| } | |||
| void ProjectExporter::createDefaultConfigs() | |||
| @@ -197,6 +197,8 @@ public: | |||
| Value getValue (const Identifier& name) { return config.getPropertyAsValue (name, getUndoManager()); } | |||
| UndoManager* getUndoManager() const { return project.getUndoManagerFor (config); } | |||
| void removeFromExporter(); | |||
| //============================================================================== | |||
| ValueTree config; | |||
| Project& project; | |||
| @@ -209,7 +211,6 @@ public: | |||
| }; | |||
| void addNewConfiguration (const BuildConfiguration* configToCopy); | |||
| void deleteConfiguration (int index); | |||
| bool hasConfigurationNamed (const String& name) const; | |||
| String getUniqueConfigName (String name) const; | |||
| @@ -923,12 +923,6 @@ void Project::addNewExporter (const String& exporterName) | |||
| exporters.addChild (exp->settings, -1, getUndoManagerFor (exporters)); | |||
| } | |||
| void Project::deleteExporter (int index) | |||
| { | |||
| ValueTree exporters (getExporters()); | |||
| exporters.removeChild (index, getUndoManagerFor (exporters)); | |||
| } | |||
| void Project::createDefaultExporters() | |||
| { | |||
| ValueTree exporters (getExporters()); | |||
| @@ -201,7 +201,6 @@ public: | |||
| int getNumExporters(); | |||
| ProjectExporter* createExporter (int index); | |||
| void addNewExporter (const String& exporterName); | |||
| void deleteExporter (int index); | |||
| void createDefaultExporters(); | |||
| struct ExporterIterator | |||
| @@ -31,10 +31,118 @@ | |||
| #include "../Project Saving/jucer_ProjectExporter.h" | |||
| //============================================================================== | |||
| class TreePanelBase : public Component | |||
| { | |||
| public: | |||
| TreePanelBase (const String& opennessStateKey_) | |||
| : opennessStateKey (opennessStateKey_) | |||
| { | |||
| addAndMakeVisible (&tree); | |||
| tree.setRootItemVisible (true); | |||
| tree.setDefaultOpenness (true); | |||
| tree.setColour (TreeView::backgroundColourId, Colours::transparentBlack); | |||
| tree.setIndentSize (14); | |||
| } | |||
| ~TreePanelBase() | |||
| { | |||
| tree.setRootItem (nullptr); | |||
| } | |||
| void setRoot (JucerTreeViewBase* root) | |||
| { | |||
| rootItem = root; | |||
| tree.setRootItem (root); | |||
| tree.getRootItem()->setOpen (true); | |||
| const ScopedPointer<XmlElement> treeOpenness (StoredSettings::getInstance()->getProps() | |||
| .getXmlValue (opennessStateKey)); | |||
| if (treeOpenness != nullptr) | |||
| tree.restoreOpennessState (*treeOpenness, true); | |||
| } | |||
| void saveOpenness() | |||
| { | |||
| const ScopedPointer<XmlElement> opennessState (tree.getOpennessState (true)); | |||
| if (opennessState != nullptr) | |||
| StoredSettings::getInstance()->getProps().setValue (opennessStateKey, opennessState); | |||
| } | |||
| void deleteSelectedItems() | |||
| { | |||
| if (rootItem != nullptr) | |||
| rootItem->deleteAllSelectedItems(); | |||
| } | |||
| void resized() | |||
| { | |||
| tree.setBounds (getLocalBounds()); | |||
| } | |||
| TreeView tree; | |||
| ScopedPointer<JucerTreeViewBase> rootItem; | |||
| private: | |||
| String opennessStateKey; | |||
| }; | |||
| //============================================================================== | |||
| class FileTreeTab : public TreePanelBase | |||
| { | |||
| public: | |||
| FileTreeTab (Project& project) | |||
| : TreePanelBase ("treeViewState_" + project.getProjectUID()) | |||
| { | |||
| tree.setMultiSelectEnabled (true); | |||
| setRoot (new GroupTreeViewItem (project.getMainGroup())); | |||
| } | |||
| }; | |||
| //============================================================================== | |||
| class ConfigTreeTab : public TreePanelBase | |||
| { | |||
| public: | |||
| ConfigTreeTab (Project& project) | |||
| : TreePanelBase ("settingsTreeViewState_" + project.getProjectUID()) | |||
| { | |||
| tree.setMultiSelectEnabled (false); | |||
| setRoot (createProjectConfigTreeViewRoot (project)); | |||
| #if JUCE_MAC || JUCE_WINDOWS | |||
| addAndMakeVisible (&openProjectButton); | |||
| openProjectButton.setCommandToTrigger (commandManager, CommandIDs::openInIDE, true); | |||
| openProjectButton.setButtonText (commandManager->getNameOfCommand (CommandIDs::openInIDE)); | |||
| addAndMakeVisible (&saveAndOpenButton); | |||
| saveAndOpenButton.setCommandToTrigger (commandManager, CommandIDs::saveAndOpenInIDE, true); | |||
| saveAndOpenButton.setButtonText (commandManager->getNameOfCommand (CommandIDs::saveAndOpenInIDE)); | |||
| #endif | |||
| } | |||
| void resized() | |||
| { | |||
| Rectangle<int> r (getLocalBounds()); | |||
| r.removeFromBottom (6); | |||
| if (saveAndOpenButton.isVisible()) | |||
| saveAndOpenButton.setBounds (r.removeFromBottom (28).reduced (20, 3)); | |||
| if (openProjectButton.isVisible()) | |||
| openProjectButton.setBounds (r.removeFromBottom (28).reduced (20, 3)); | |||
| tree.setBounds (r); | |||
| } | |||
| TextButton openProjectButton, saveAndOpenButton; | |||
| }; | |||
| //============================================================================== | |||
| ProjectContentComponent::ProjectContentComponent() | |||
| : project (nullptr), | |||
| currentDocument (nullptr) | |||
| currentDocument (nullptr), | |||
| treeViewTabs (TabbedButtonBar::TabsAtTop) | |||
| { | |||
| setOpaque (true); | |||
| setWantsKeyboardFocus (true); | |||
| @@ -47,7 +155,7 @@ ProjectContentComponent::~ProjectContentComponent() | |||
| { | |||
| setProject (nullptr); | |||
| contentView = nullptr; | |||
| jassert (getNumChildComponents() == 0); | |||
| jassert (getNumChildComponents() <= 1); | |||
| } | |||
| void ProjectContentComponent::paint (Graphics& g) | |||
| @@ -67,34 +175,28 @@ void ProjectContentComponent::setProject (Project* newProject) | |||
| contentView = nullptr; | |||
| resizerBar = nullptr; | |||
| if (projectTree != nullptr) | |||
| { | |||
| settings.setValue ("projectTreeviewWidth", projectTree->getWidth()); | |||
| projectTree->deleteRootItem(); | |||
| projectTree = nullptr; | |||
| } | |||
| treeViewTabs.clearTabs(); | |||
| if (treeViewTabs.isShowing() && treeViewTabs.getWidth() > 0) | |||
| settings.setValue ("projectTreeviewWidth", treeViewTabs.getWidth()); | |||
| project = newProject; | |||
| if (project != nullptr) | |||
| { | |||
| addChildAndSetID (projectTree = new TreeView(), "tree"); | |||
| projectTree->setRootItemVisible (true); | |||
| projectTree->setMultiSelectEnabled (true); | |||
| projectTree->setDefaultOpenness (true); | |||
| projectTree->setColour (TreeView::backgroundColourId, Colour::greyLevel (0.93f)); | |||
| projectTree->setIndentSize (14); | |||
| treeViewTabs.setVisible (true); | |||
| addChildAndSetID (&treeViewTabs, "tree"); | |||
| projectTree->setRootItem (new GroupTreeViewItem (project->getMainGroup())); | |||
| projectTree->getRootItem()->setOpen (true); | |||
| createProjectTabs(); | |||
| String lastTreeWidth (settings.getValue ("projectTreeviewWidth")); | |||
| if (lastTreeWidth.getIntValue() < 150) | |||
| lastTreeWidth = "250"; | |||
| projectTree->setBounds ("0, 0, left + " + lastTreeWidth + ", parent.height"); | |||
| treeViewTabs.setBounds ("0, 0, left + " + lastTreeWidth + ", parent.height"); | |||
| addChildAndSetID (resizerBar = new ResizableEdgeComponent (projectTree, &treeSizeConstrainer, ResizableEdgeComponent::rightEdge), | |||
| addChildAndSetID (resizerBar = new ResizableEdgeComponent (&treeViewTabs, &treeSizeConstrainer, | |||
| ResizableEdgeComponent::rightEdge), | |||
| "resizer"); | |||
| resizerBar->setBounds ("tree.right, 0, tree.right + 4, parent.height"); | |||
| @@ -105,24 +207,40 @@ void ProjectContentComponent::setProject (Project* newProject) | |||
| invokeDirectly (CommandIDs::showProjectSettings, true); | |||
| updateMissingFileStatuses(); | |||
| const ScopedPointer<XmlElement> treeOpenness (settings.getXmlValue ("treeViewState_" + project->getProjectUID())); | |||
| if (treeOpenness != nullptr) | |||
| projectTree->restoreOpennessState (*treeOpenness, true); | |||
| } | |||
| else | |||
| { | |||
| treeViewTabs.setVisible (false); | |||
| } | |||
| } | |||
| } | |||
| void ProjectContentComponent::createProjectTabs() | |||
| { | |||
| treeViewTabs.addTab ("Files", Colour::greyLevel (0.93f), new FileTreeTab (*project), true); | |||
| treeViewTabs.addTab ("Config", Colour::greyLevel (0.93f), new ConfigTreeTab (*project), true); | |||
| } | |||
| TreeView* ProjectContentComponent::getFilesTreeView() const | |||
| { | |||
| FileTreeTab* ft = dynamic_cast<FileTreeTab*> (treeViewTabs.getTabContentComponent (0)); | |||
| return ft != nullptr ? &(ft->tree) : nullptr; | |||
| } | |||
| ProjectTreeViewBase* ProjectContentComponent::getFilesTreeRoot() const | |||
| { | |||
| TreeView* tv = getFilesTreeView(); | |||
| return tv != nullptr ? dynamic_cast <ProjectTreeViewBase*> (tv->getRootItem()) : nullptr; | |||
| } | |||
| void ProjectContentComponent::saveTreeViewState() | |||
| { | |||
| if (projectTree != nullptr) | |||
| for (int i = treeViewTabs.getNumTabs(); --i >= 0;) | |||
| { | |||
| const ScopedPointer<XmlElement> opennessState (projectTree->getOpennessState (true)); | |||
| TreePanelBase* t = dynamic_cast<TreePanelBase*> (treeViewTabs.getTabContentComponent (i)); | |||
| if (opennessState != nullptr) | |||
| StoredSettings::getInstance()->getProps() | |||
| .setValue ("treeViewState_" + project->getProjectUID(), opennessState); | |||
| if (t != nullptr) | |||
| t->saveOpenness(); | |||
| } | |||
| } | |||
| @@ -133,12 +251,10 @@ void ProjectContentComponent::changeListenerCallback (ChangeBroadcaster*) | |||
| void ProjectContentComponent::updateMissingFileStatuses() | |||
| { | |||
| if (projectTree != nullptr) | |||
| { | |||
| ProjectTreeViewBase* p = dynamic_cast <ProjectTreeViewBase*> (projectTree->getRootItem()); | |||
| if (p != nullptr) | |||
| p->checkFileStatus(); | |||
| } | |||
| ProjectTreeViewBase* p = getFilesTreeRoot(); | |||
| if (p != nullptr) | |||
| p->checkFileStatus(); | |||
| } | |||
| bool ProjectContentComponent::showEditorForFile (const File& f) | |||
| @@ -159,15 +275,18 @@ bool ProjectContentComponent::showDocument (OpenDocumentManager::Document* doc) | |||
| return setEditorComponent (doc->createEditor(), doc); | |||
| } | |||
| void ProjectContentComponent::hideEditor() | |||
| { | |||
| currentDocument = nullptr; | |||
| contentView = nullptr; | |||
| updateMainWindowTitle(); | |||
| commandManager->commandStatusChanged(); | |||
| } | |||
| void ProjectContentComponent::hideDocument (OpenDocumentManager::Document* doc) | |||
| { | |||
| if (doc == currentDocument) | |||
| { | |||
| currentDocument = nullptr; | |||
| contentView = nullptr; | |||
| updateMainWindowTitle(); | |||
| commandManager->commandStatusChanged(); | |||
| } | |||
| hideEditor(); | |||
| } | |||
| bool ProjectContentComponent::setEditorComponent (Component* editor, OpenDocumentManager::Document* doc) | |||
| @@ -308,7 +427,7 @@ void ProjectContentComponent::getCommandInfo (const CommandID commandID, Applica | |||
| result.setInfo ("Delete", String::empty, CommandCategories::general, 0); | |||
| result.defaultKeypresses.add (KeyPress (KeyPress::deleteKey, 0, 0)); | |||
| result.defaultKeypresses.add (KeyPress (KeyPress::backspaceKey, 0, 0)); | |||
| result.setActive (projectTree != nullptr); | |||
| result.setActive (dynamic_cast<TreePanelBase*> (treeViewTabs.getCurrentContentComponent()) != nullptr); | |||
| break; | |||
| default: | |||
| @@ -384,17 +503,15 @@ bool ProjectContentComponent::perform (const InvocationInfo& info) | |||
| break; | |||
| case CommandIDs::showProjectSettings: | |||
| if (projectTree != nullptr) | |||
| projectTree->getRootItem()->setSelected (true, true); | |||
| treeViewTabs.setCurrentTabIndex (1); | |||
| break; | |||
| case StandardApplicationCommandIDs::del: | |||
| if (projectTree != nullptr) | |||
| { | |||
| ProjectTreeViewBase* p = dynamic_cast <ProjectTreeViewBase*> (projectTree->getRootItem()); | |||
| if (p != nullptr) | |||
| p->deleteAllSelectedItems(); | |||
| TreePanelBase* const tree = dynamic_cast<TreePanelBase*> (treeViewTabs.getCurrentContentComponent()); | |||
| if (tree != nullptr) | |||
| tree->deleteSelectedItems(); | |||
| } | |||
| break; | |||
| @@ -28,7 +28,7 @@ | |||
| #include "jucer_Project.h" | |||
| #include "../Application/jucer_OpenDocumentManager.h" | |||
| class ProjectTreeViewBase; | |||
| //============================================================================== | |||
| /** | |||
| @@ -51,11 +51,13 @@ public: | |||
| bool showEditorForFile (const File& f); | |||
| bool showDocument (OpenDocumentManager::Document* doc); | |||
| void hideDocument (OpenDocumentManager::Document* doc); | |||
| void hideEditor(); | |||
| bool setEditorComponent (Component* editor, OpenDocumentManager::Document* doc); | |||
| Component* getEditorComponent() const { return contentView; } | |||
| OpenDocumentManager::Document* getCurrentDocument() const { return currentDocument; } | |||
| void updateMissingFileStatuses(); | |||
| virtual void createProjectTabs(); | |||
| void changeListenerCallback (ChangeBroadcaster*); | |||
| @@ -66,11 +68,11 @@ public: | |||
| bool isCommandActive (const CommandID commandID); | |||
| bool perform (const InvocationInfo& info); | |||
| private: | |||
| protected: | |||
| Project* project; | |||
| OpenDocumentManager::Document* currentDocument; | |||
| ScopedPointer<TreeView> projectTree; | |||
| TabbedComponent treeViewTabs; | |||
| ScopedPointer<ResizableEdgeComponent> resizerBar; | |||
| ScopedPointer<Component> contentView; | |||
| @@ -79,6 +81,8 @@ private: | |||
| void updateMainWindowTitle(); | |||
| bool reinvokeCommandAfterClosingPropertyEditors (const InvocationInfo&); | |||
| bool canProjectBeLaunched() const; | |||
| TreeView* getFilesTreeView() const; | |||
| ProjectTreeViewBase* getFilesTreeRoot() const; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProjectContentComponent); | |||
| }; | |||
| @@ -1,33 +1,35 @@ | |||
| /* | |||
| ============================================================================== | |||
| This is an automatically generated file! | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-11 by Raw Material Software Ltd. | |||
| Be careful when adding custom code to these files, as only the code within | |||
| the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded | |||
| and re-saved. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||
| Public License (Version 2), as published by the Free Software Foundation. | |||
| A copy of the license is included in the JUCE distribution, or can be found | |||
| online at www.gnu.org/licenses. | |||
| Created for JUCE version: JUCE v2.0.16 | |||
| 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. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE is copyright 2004-11 by Raw Material Software ltd. | |||
| To release a closed-source product which uses JUCE, commercial licenses are | |||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||
| ============================================================================== | |||
| */ | |||
| //[CppHeaders] You can add your own extra header files here... | |||
| #include "../Project Saving/jucer_ProjectExporter.h" | |||
| #include "jucer_Module.h" | |||
| #include "../Application/jucer_JuceUpdater.h" | |||
| //[/CppHeaders] | |||
| #include "../Project/jucer_ProjectContentComponent.h" | |||
| #include "jucer_ProjectInformationComponent.h" | |||
| //[MiscUserDefs] You can add your own user definitions and misc code here... | |||
| //============================================================================== | |||
| class ModulesPanel : public PropertyComponent, | |||
| public FilenameComponentListener, | |||
| @@ -504,520 +506,522 @@ private: | |||
| ScopedPointer<ModuleSettingsPanel> settings; | |||
| }; | |||
| //============================================================================== | |||
| class ProjectSettingsComponent : public Component | |||
| struct ProjectSettingsTreeClasses | |||
| { | |||
| public: | |||
| ProjectSettingsComponent (Project& project_) | |||
| : project (project_), | |||
| exporters ("Export Targets", "Add a New Exporter...", true, false) | |||
| class PropertyGroup : public Component | |||
| { | |||
| addAndMakeVisible (&mainProjectInfoPanel); | |||
| addAndMakeVisible (&modulesPanelGroup); | |||
| addAndMakeVisible (&exporters); | |||
| public: | |||
| PropertyGroup() {} | |||
| mainProjectInfoPanel.fillBackground = true; | |||
| modulesPanelGroup.fillBackground = true; | |||
| } | |||
| void setProperties (const PropertyListBuilder& newProps) | |||
| { | |||
| properties.clear(); | |||
| properties.addArray (newProps.components); | |||
| void updateSize (int width) | |||
| { | |||
| width = jmax (550, width - 6); | |||
| for (int i = properties.size(); --i >= 0;) | |||
| addAndMakeVisible (properties.getUnchecked(i)); | |||
| } | |||
| int y = 0; | |||
| y += mainProjectInfoPanel.updateSize (y, width); | |||
| y += modulesPanelGroup.updateSize (y, width); | |||
| y += exporters.updateSize (y, width); | |||
| int updateSize (int x, int y, int width) | |||
| { | |||
| int height = 36; | |||
| setSize (width, y); | |||
| } | |||
| for (int i = 0; i < properties.size(); ++i) | |||
| { | |||
| PropertyComponent* pp = properties.getUnchecked(i); | |||
| pp->setBounds (10, height, width - 20, pp->getPreferredHeight()); | |||
| height += pp->getHeight(); | |||
| } | |||
| void parentSizeChanged() | |||
| { | |||
| updateSize (getParentWidth()); | |||
| } | |||
| height += 16; | |||
| setBounds (x, y, width, height); | |||
| return height; | |||
| } | |||
| void visibilityChanged() | |||
| { | |||
| if (isVisible()) | |||
| createAllPanels(); | |||
| } | |||
| void paint (Graphics& g) | |||
| { | |||
| g.setColour (Colours::white.withAlpha (0.3f)); | |||
| g.fillRect (0, 28, getWidth(), getHeight() - 38); | |||
| void createModulesPanel() | |||
| { | |||
| PropertyListBuilder props; | |||
| props.add (new ModulesPanel (project)); | |||
| modulesPanelGroup.setProperties (props); | |||
| modulesPanelGroup.setName ("Modules"); | |||
| } | |||
| g.setColour (Colours::black.withAlpha (0.4f)); | |||
| g.drawRect (0, 28, getWidth(), getHeight() - 38); | |||
| g.setFont (14.0f, Font::bold); | |||
| g.setColour (Colours::black); | |||
| g.drawFittedText (getName(), 12, 0, getWidth() - 16, 26, Justification::bottomLeft, 1); | |||
| } | |||
| OwnedArray<PropertyComponent> properties; | |||
| private: | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PropertyGroup); | |||
| }; | |||
| void createProjectPanel() | |||
| //============================================================================== | |||
| class PropertyPanelViewport : public Component | |||
| { | |||
| PropertyListBuilder props; | |||
| project.createPropertyEditors (props); | |||
| mainProjectInfoPanel.setProperties (props); | |||
| mainProjectInfoPanel.setName ("Project Settings"); | |||
| public: | |||
| PropertyPanelViewport (Component* content) | |||
| { | |||
| addAndMakeVisible (&viewport); | |||
| viewport.setViewedComponent (content, true); | |||
| } | |||
| lastProjectType = project.getProjectTypeValue().getValue(); | |||
| } | |||
| void paint (Graphics& g) | |||
| { | |||
| g.setTiledImageFill (ImageCache::getFromMemory (BinaryData::brushed_aluminium_png, | |||
| BinaryData::brushed_aluminium_pngSize), | |||
| 0, 0, 1.0f); | |||
| g.fillAll(); | |||
| drawRecessedShadows (g, getWidth(), getHeight(), 14); | |||
| } | |||
| void resized() | |||
| { | |||
| viewport.setBounds (getLocalBounds()); | |||
| } | |||
| Viewport viewport; | |||
| private: | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PropertyPanelViewport); | |||
| }; | |||
| void createExportersPanel() | |||
| //============================================================================== | |||
| class SettingsItemBase : public JucerTreeViewBase, | |||
| public ValueTree::Listener | |||
| { | |||
| exporters.clear(); | |||
| public: | |||
| SettingsItemBase() {} | |||
| for (Project::ExporterIterator exporter (project); exporter.next();) | |||
| void showSettingsPage (Component* content) | |||
| { | |||
| PropertyGroup* exporterGroup = exporters.createGroup(); | |||
| exporterGroup->fillBackground = true; | |||
| exporterGroup->addDeleteButton ("exporter " + String (exporter.index), "Deletes this export target."); | |||
| content->setComponentID (getUniqueName()); | |||
| PropertyListBuilder props; | |||
| exporter->createPropertyEditors (props); | |||
| ScopedPointer<Component> comp (content); | |||
| ProjectContentComponent* pcc = getProjectContentComponent(); | |||
| PropertyGroupList* configList = new PropertyGroupList ("Configurations", "Add a New Configuration", false, true); | |||
| props.add (configList); | |||
| exporterGroup->setProperties (props); | |||
| if (pcc != nullptr) | |||
| pcc->setEditorComponent (new PropertyPanelViewport (comp.release()), nullptr); | |||
| } | |||
| configList->createNewButton.setName ("newconfig " + String (exporter.index)); | |||
| void closeSettingsPage() | |||
| { | |||
| ProjectContentComponent* pcc = getProjectContentComponent(); | |||
| for (ProjectExporter::ConfigIterator config (*exporter); config.next();) | |||
| if (pcc != nullptr) | |||
| { | |||
| PropertyGroup* configGroup = configList->createGroup(); | |||
| if (exporter->getNumConfigurations() > 1) | |||
| configGroup->addDeleteButton ("config " + String (exporter.index) + "/" + String (config.index), "Deletes this configuration."); | |||
| PropertyPanelViewport* ppv = dynamic_cast<PropertyPanelViewport*> (pcc->getEditorComponent()); | |||
| PropertyListBuilder configProps; | |||
| config->createPropertyEditors (configProps); | |||
| configGroup->setProperties (configProps); | |||
| if (ppv != nullptr && ppv->viewport.getViewedComponent()->getComponentID() == getUniqueName()) | |||
| pcc->hideEditor(); | |||
| } | |||
| } | |||
| } | |||
| void createAllPanels() | |||
| { | |||
| createProjectPanel(); | |||
| createModulesPanel(); | |||
| createExportersPanel(); | |||
| updateNames(); | |||
| void deleteAllSelectedItems() | |||
| { | |||
| TreeView* const tree = getOwnerView(); | |||
| jassert (tree->getNumSelectedItems() <= 1); // multi-select should be disabled | |||
| updateSize (getWidth()); | |||
| } | |||
| if (SettingsItemBase* s = dynamic_cast <SettingsItemBase*> (tree->getSelectedItem (0))) | |||
| s->deleteItem(); | |||
| } | |||
| bool needsFullUpdate() const | |||
| { | |||
| if (exporters.groups.size() != project.getNumExporters() | |||
| || lastProjectType != project.getProjectTypeValue().getValue()) | |||
| return true; | |||
| void itemOpennessChanged (bool isNowOpen) | |||
| { | |||
| if (isNowOpen) | |||
| refreshSubItems(); | |||
| } | |||
| void valueTreePropertyChanged (ValueTree&, const Identifier&) {} | |||
| void valueTreeChildAdded (ValueTree&, ValueTree&) {} | |||
| void valueTreeChildRemoved (ValueTree&, ValueTree&) {} | |||
| void valueTreeChildOrderChanged (ValueTree&) {} | |||
| void valueTreeParentChanged (ValueTree&) {} | |||
| for (int i = exporters.groups.size(); --i >= 0;) | |||
| static void updateSizes (Component& comp, PropertyGroup* groups, int numGroups) | |||
| { | |||
| ScopedPointer <ProjectExporter> exp (project.createExporter (i)); | |||
| const int width = jmax (550, comp.getParentWidth() - 20); | |||
| jassert (exp != nullptr); | |||
| if (exp != nullptr) | |||
| { | |||
| PropertyGroupList* configList = dynamic_cast <PropertyGroupList*> (exporters.groups.getUnchecked(i)->properties.getLast()); | |||
| int y = 0; | |||
| for (int i = 0; i < numGroups; ++i) | |||
| y += groups[i].updateSize (12, y, width - 12); | |||
| if (configList != nullptr && configList->groups.size() != exp->getNumConfigurations()) | |||
| return true; | |||
| } | |||
| comp.setSize (width, y); | |||
| } | |||
| }; | |||
| return false; | |||
| } | |||
| void updateNames() | |||
| //============================================================================== | |||
| class ConfigItem : public SettingsItemBase | |||
| { | |||
| for (int i = exporters.groups.size(); --i >= 0;) | |||
| public: | |||
| ConfigItem (const ProjectExporter::BuildConfiguration::Ptr& config_, const String& exporterName_) | |||
| : config (config_), exporterName (exporterName_), configTree (config->config) | |||
| { | |||
| PropertyGroup& exporterGroup = *exporters.groups.getUnchecked(i); | |||
| ScopedPointer <ProjectExporter> exp (project.createExporter (i)); | |||
| jassert (exp != nullptr); | |||
| jassert (config != nullptr); | |||
| configTree.addListener (this); | |||
| } | |||
| bool isRoot() const { return false; } | |||
| bool isMissing() { return false; } | |||
| bool canBeSelected() const { return true; } | |||
| bool mightContainSubItems() { return false; } | |||
| String getUniqueName() const { return config->project.getProjectUID() + "_config_" + config->getName(); } | |||
| String getRenamingName() const { return getDisplayName(); } | |||
| String getDisplayName() const { return config->getName(); } | |||
| void setName (const String&) {} | |||
| const Drawable* getIcon() const { return StoredSettings::getInstance()->getCogIcon(); } | |||
| void showDocument() { showSettingsPage (new SettingsComp (config, exporterName)); } | |||
| void itemOpennessChanged (bool) {} | |||
| if (exp != nullptr) | |||
| void deleteItem() | |||
| { | |||
| if (AlertWindow::showOkCancelBox (AlertWindow::WarningIcon, "Delete Configuration", | |||
| "Are you sure you want to delete this configuration?")) | |||
| { | |||
| exporterGroup.setName (exp->getName()); | |||
| exporterGroup.repaint(); | |||
| closeSettingsPage(); | |||
| config->removeFromExporter(); | |||
| } | |||
| } | |||
| PropertyGroupList* configList = dynamic_cast <PropertyGroupList*> (exporterGroup.properties.getLast()); | |||
| void showPopupMenu() | |||
| { | |||
| PopupMenu menu; | |||
| menu.addItem (1, "Create a copy of this configuration"); | |||
| menu.addSeparator(); | |||
| menu.addItem (2, "Delete this configuration"); | |||
| launchPopupMenu (menu); | |||
| } | |||
| if (configList != nullptr) | |||
| void handlePopupMenuResult (int resultCode) | |||
| { | |||
| if (resultCode == 2) | |||
| { | |||
| deleteAllSelectedItems(); | |||
| } | |||
| else if (resultCode == 1) | |||
| { | |||
| for (Project::ExporterIterator exporter (config->project); exporter.next();) | |||
| { | |||
| for (int j = configList->groups.size(); --j >= 0;) | |||
| if (config->config.isAChildOf (exporter.exporter->settings)) | |||
| { | |||
| PropertyGroup& configGroup = *configList->groups.getUnchecked(j); | |||
| configGroup.setName ("Configuration: " + exp->getConfiguration (j)->getName().quoted()); | |||
| configGroup.repaint(); | |||
| exporter.exporter->addNewConfiguration (config); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void update() | |||
| { | |||
| if (needsFullUpdate()) | |||
| createAllPanels(); | |||
| else | |||
| updateNames(); | |||
| } | |||
| void deleteButtonClicked (const String& name) | |||
| { | |||
| if (name.startsWith ("config")) | |||
| { | |||
| int exporterIndex = name.upToLastOccurrenceOf ("/", false, false).getTrailingIntValue(); | |||
| int configIndex = name.getTrailingIntValue(); | |||
| ScopedPointer<ProjectExporter> exporter (project.createExporter (exporterIndex)); | |||
| jassert (exporter != nullptr); | |||
| if (exporter != nullptr) | |||
| exporter->deleteConfiguration (configIndex); | |||
| } | |||
| else | |||
| var getDragSourceDescription() | |||
| { | |||
| project.deleteExporter (name.getTrailingIntValue()); | |||
| return getParentItem()->getUniqueName() + "||" + config->getName(); | |||
| } | |||
| } | |||
| static void newExporterMenuItemChosen (int resultCode, ProjectSettingsComponent* settingsComp) | |||
| { | |||
| if (resultCode > 0 && settingsComp != nullptr) | |||
| settingsComp->project.addNewExporter (ProjectExporter::getExporterNames() [resultCode - 1]); | |||
| } | |||
| void valueTreePropertyChanged (ValueTree&, const Identifier&) { repaintItem(); } | |||
| void createNewExporter (TextButton& button) | |||
| { | |||
| PopupMenu menu; | |||
| private: | |||
| ProjectExporter::BuildConfiguration::Ptr config; | |||
| String exporterName; | |||
| ValueTree configTree; | |||
| const StringArray exporters (ProjectExporter::getExporterNames()); | |||
| //============================================================================== | |||
| class SettingsComp : public Component | |||
| { | |||
| public: | |||
| SettingsComp (ProjectExporter::BuildConfiguration* config, const String& exporterName) | |||
| { | |||
| addAndMakeVisible (&group); | |||
| for (int i = 0; i < exporters.size(); ++i) | |||
| menu.addItem (i + 1, "Create a new " + exporters[i] + " target"); | |||
| PropertyListBuilder props; | |||
| config->createPropertyEditors (props); | |||
| group.setProperties (props); | |||
| group.setName (exporterName + " / " + config->getName()); | |||
| parentSizeChanged(); | |||
| } | |||
| menu.showMenuAsync (PopupMenu::Options().withTargetComponent (&button), | |||
| ModalCallbackFunction::forComponent (newExporterMenuItemChosen, this)); | |||
| } | |||
| void parentSizeChanged() { updateSizes (*this, &group, 1); } | |||
| void createNewConfig (int exporterIndex) | |||
| { | |||
| ScopedPointer<ProjectExporter> exp (project.createExporter (exporterIndex)); | |||
| jassert (exp != nullptr); | |||
| private: | |||
| PropertyGroup group; | |||
| if (exp != nullptr) | |||
| exp->addNewConfiguration (nullptr); | |||
| } | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SettingsComp); | |||
| }; | |||
| void newItemButtonClicked (TextButton& button) | |||
| { | |||
| if (button.getName().containsIgnoreCase ("export")) | |||
| createNewExporter (button); | |||
| else if (button.getName().containsIgnoreCase ("newconfig")) | |||
| createNewConfig (button.getName().getTrailingIntValue()); | |||
| } | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ConfigItem); | |||
| }; | |||
| private: | |||
| //============================================================================== | |||
| class PropertyGroup : public Component, | |||
| public ButtonListener | |||
| class ExporterItem : public SettingsItemBase | |||
| { | |||
| public: | |||
| PropertyGroup() | |||
| : deleteButton ("Delete"), fillBackground (false) | |||
| ExporterItem (Project& project_, ProjectExporter* exporter_, int exporterIndex_) | |||
| : project (project_), exporter (exporter_), configListTree (exporter->getConfigurations()), | |||
| exporterIndex (exporterIndex_) | |||
| { | |||
| deleteButton.addListener (this); | |||
| configListTree.addListener (this); | |||
| jassert (exporter != nullptr); | |||
| } | |||
| void addDeleteButton (const String& name, const String& tooltip) | |||
| bool isRoot() const { return false; } | |||
| bool canBeSelected() const { return true; } | |||
| bool mightContainSubItems() { return exporter->getNumConfigurations() > 0; } | |||
| String getUniqueName() const { return project.getProjectUID() + "_exporter_" + String (exporterIndex); } | |||
| String getRenamingName() const { return getDisplayName(); } | |||
| String getDisplayName() const { return exporter->getName(); } | |||
| void setName (const String&) {} | |||
| bool isMissing() { return false; } | |||
| const Drawable* getIcon() const { return LookAndFeel::getDefaultLookAndFeel().getDefaultDocumentFileImage(); } | |||
| void showDocument() { showSettingsPage (new SettingsComp (exporter)); } | |||
| void deleteItem() | |||
| { | |||
| addAndMakeVisible (&deleteButton); | |||
| deleteButton.setBounds ("right - 55, 11, parent.width - 10, 26"); | |||
| deleteButton.setColour (TextButton::buttonColourId, Colour (0xa0fcbdbd)); | |||
| deleteButton.setColour (TextButton::textColourOffId, Colours::darkred); | |||
| deleteButton.setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnRight); | |||
| deleteButton.setName (name); | |||
| deleteButton.setTooltip (tooltip); | |||
| if (AlertWindow::showOkCancelBox (AlertWindow::WarningIcon, "Delete Exporter", | |||
| "Are you sure you want to delete this export target?")) | |||
| { | |||
| closeSettingsPage(); | |||
| ValueTree parent (exporter->settings.getParent()); | |||
| parent.removeChild (exporter->settings, project.getUndoManagerFor (parent)); | |||
| } | |||
| } | |||
| void setProperties (const PropertyListBuilder& newProps) | |||
| void addSubItems() | |||
| { | |||
| properties.clear(); | |||
| properties.addArray (newProps.components); | |||
| for (int i = properties.size(); --i >= 0;) | |||
| addAndMakeVisible (properties.getUnchecked(i)); | |||
| for (ProjectExporter::ConfigIterator config (*exporter); config.next();) | |||
| addSubItem (new ConfigItem (config.config, exporter->getName())); | |||
| } | |||
| int updateSize (int y, int width) | |||
| void showPopupMenu() | |||
| { | |||
| int height = fillBackground ? 36 : 32; | |||
| PopupMenu menu; | |||
| menu.addItem (1, "Add a new configuration"); | |||
| menu.addSeparator(); | |||
| menu.addItem (2, "Delete this exporter"); | |||
| for (int i = 0; i < properties.size(); ++i) | |||
| { | |||
| PropertyComponent* pp = properties.getUnchecked(i); | |||
| PropertyGroupList* pgl = dynamic_cast <PropertyGroupList*> (pp); | |||
| launchPopupMenu (menu); | |||
| } | |||
| if (pgl != nullptr) | |||
| pgl->updateSize (height, width - 20); | |||
| void handlePopupMenuResult (int resultCode) | |||
| { | |||
| if (resultCode == 2) | |||
| deleteAllSelectedItems(); | |||
| else if (resultCode == 1) | |||
| exporter->addNewConfiguration (nullptr); | |||
| } | |||
| pp->setBounds (10, height, width - 20, pp->getPreferredHeight()); | |||
| height += pp->getHeight(); | |||
| } | |||
| var getDragSourceDescription() | |||
| { | |||
| return getParentItem()->getUniqueName() + "/" + String (exporterIndex); | |||
| } | |||
| height += 16; | |||
| setBounds (0, y, width, height); | |||
| return height; | |||
| bool isInterestedInDragSource (const DragAndDropTarget::SourceDetails& dragSourceDetails) | |||
| { | |||
| return dragSourceDetails.description.toString().startsWith (getUniqueName()); | |||
| } | |||
| void paint (Graphics& g) | |||
| void itemDropped (const DragAndDropTarget::SourceDetails& dragSourceDetails, int insertIndex) | |||
| { | |||
| if (fillBackground) | |||
| { | |||
| g.setColour (Colours::white.withAlpha (0.3f)); | |||
| g.fillRect (0, 28, getWidth(), getHeight() - 38); | |||
| const int oldIndex = indexOfConfig (dragSourceDetails.description.toString().fromLastOccurrenceOf ("||", false, false)); | |||
| g.setColour (Colours::black.withAlpha (0.4f)); | |||
| g.drawRect (0, 28, getWidth(), getHeight() - 38); | |||
| } | |||
| if (oldIndex >= 0) | |||
| configListTree.moveChild (oldIndex, insertIndex, project.getUndoManagerFor (configListTree)); | |||
| } | |||
| g.setFont (14.0f, Font::bold); | |||
| g.setColour (Colours::black); | |||
| g.drawFittedText (getName(), 12, 0, getWidth() - 16, 26, Justification::bottomLeft, 1); | |||
| int indexOfConfig (const String& configName) | |||
| { | |||
| int i = 0; | |||
| for (ProjectExporter::ConfigIterator config (*exporter); config.next(); ++i) | |||
| if (config->getName() == configName) | |||
| return i; | |||
| return -1; | |||
| } | |||
| void buttonClicked (Button*) | |||
| //============================================================================== | |||
| void valueTreeChildAdded (ValueTree& parentTree, ValueTree&) { refreshIfNeeded (parentTree); } | |||
| void valueTreeChildRemoved (ValueTree& parentTree, ValueTree&) { refreshIfNeeded (parentTree); } | |||
| void valueTreeChildOrderChanged (ValueTree& parentTree) { refreshIfNeeded (parentTree); } | |||
| void refreshIfNeeded (ValueTree& changedTree) | |||
| { | |||
| ProjectSettingsComponent* psc = findParentComponentOfClass<ProjectSettingsComponent>(); | |||
| if (psc != nullptr) | |||
| psc->deleteButtonClicked (deleteButton.getName()); | |||
| if (changedTree == configListTree) | |||
| refreshSubItems(); | |||
| } | |||
| OwnedArray<PropertyComponent> properties; | |||
| TextButton deleteButton; | |||
| bool fillBackground; | |||
| private: | |||
| Project& project; | |||
| ScopedPointer<ProjectExporter> exporter; | |||
| ValueTree configListTree; | |||
| int exporterIndex; | |||
| //============================================================================== | |||
| class SettingsComp : public Component | |||
| { | |||
| public: | |||
| SettingsComp (ProjectExporter* exporter) | |||
| { | |||
| addAndMakeVisible (&group); | |||
| PropertyListBuilder props; | |||
| exporter->createPropertyEditors (props); | |||
| group.setProperties (props); | |||
| group.setName ("Export target: " + exporter->getName()); | |||
| parentSizeChanged(); | |||
| } | |||
| void parentSizeChanged() { updateSizes (*this, &group, 1); } | |||
| private: | |||
| PropertyGroup group; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SettingsComp); | |||
| }; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ExporterItem); | |||
| }; | |||
| //============================================================================== | |||
| class PropertyGroupList : public PropertyComponent, | |||
| public ButtonListener | |||
| class RootItem : public SettingsItemBase | |||
| { | |||
| public: | |||
| PropertyGroupList (const String& title, const String& newButtonText, | |||
| bool triggerOnMouseDown, bool hideNameAndPutButtonAtBottom) | |||
| : PropertyComponent (title), createNewButton (newButtonText), | |||
| dontDisplayName (hideNameAndPutButtonAtBottom) | |||
| RootItem (Project& project_) | |||
| : project (project_), exportersTree (project_.getExporters()) | |||
| { | |||
| addAndMakeVisible (&createNewButton); | |||
| createNewButton.setColour (TextButton::buttonColourId, Colours::lightgreen.withAlpha (0.5f)); | |||
| createNewButton.setBounds (hideNameAndPutButtonAtBottom ? "right - 140, parent.height - 25, parent.width - 10, top + 20" | |||
| : "right - 140, 30, parent.width - 10, top + 20"); | |||
| createNewButton.setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnRight); | |||
| createNewButton.addListener (this); | |||
| createNewButton.setTriggeredOnMouseDown (triggerOnMouseDown); | |||
| exportersTree.addListener (this); | |||
| } | |||
| int updateSize (int ourY, int width) | |||
| bool isRoot() const { return true; } | |||
| String getRenamingName() const { return getDisplayName(); } | |||
| String getDisplayName() const { return project.getProjectName().toString(); } | |||
| void setName (const String&) {} | |||
| bool isMissing() { return false; } | |||
| const Drawable* getIcon() const { return project.getMainGroup().getIcon(); } | |||
| void showDocument() { showSettingsPage (new SettingsComp (project)); } | |||
| bool canBeSelected() const { return true; } | |||
| bool mightContainSubItems() { return project.getNumExporters() > 0; } | |||
| String getUniqueName() const { return project.getProjectUID() + "_config_root"; } | |||
| void addSubItems() | |||
| { | |||
| int y = dontDisplayName ? 10 : 55; | |||
| int i = 0; | |||
| for (Project::ExporterIterator exporter (project); exporter.next(); ++i) | |||
| addSubItem (new ExporterItem (project, exporter.exporter.release(), i)); | |||
| } | |||
| for (int i = 0; i < groups.size(); ++i) | |||
| y += groups.getUnchecked(i)->updateSize (y, width); | |||
| void showPopupMenu() | |||
| { | |||
| PopupMenu menu; | |||
| y = jmax (y, 100); | |||
| setBounds (0, ourY, width, y); | |||
| const StringArray exporters (ProjectExporter::getExporterNames()); | |||
| if (dontDisplayName) | |||
| y += 25; | |||
| for (int i = 0; i < exporters.size(); ++i) | |||
| menu.addItem (i + 1, "Create a new " + exporters[i] + " target"); | |||
| setPreferredHeight (y); | |||
| return y; | |||
| launchPopupMenu (menu); | |||
| } | |||
| void paint (Graphics& g) | |||
| void handlePopupMenuResult (int resultCode) | |||
| { | |||
| if (! dontDisplayName) | |||
| if (resultCode > 0) | |||
| { | |||
| g.setFont (17.0f, Font::bold); | |||
| g.setColour (Colours::black); | |||
| g.drawFittedText (getName(), 0, 30, getWidth(), 20, Justification::centred, 1); | |||
| String exporterName (ProjectExporter::getExporterNames() [resultCode - 1]); | |||
| if (exporterName.isNotEmpty()) | |||
| project.addNewExporter (exporterName); | |||
| } | |||
| } | |||
| void clear() | |||
| bool isInterestedInDragSource (const DragAndDropTarget::SourceDetails& dragSourceDetails) | |||
| { | |||
| groups.clear(); | |||
| return dragSourceDetails.description.toString().startsWith (getUniqueName()); | |||
| } | |||
| void refresh() {} | |||
| PropertyGroup* createGroup() | |||
| void itemDropped (const DragAndDropTarget::SourceDetails& dragSourceDetails, int insertIndex) | |||
| { | |||
| PropertyGroup* p = new PropertyGroup(); | |||
| groups.add (p); | |||
| addAndMakeVisible (p); | |||
| return p; | |||
| int oldIndex = dragSourceDetails.description.toString().getTrailingIntValue(); | |||
| exportersTree.moveChild (oldIndex, insertIndex, project.getUndoManagerFor (exportersTree)); | |||
| } | |||
| void buttonClicked (Button*) | |||
| //============================================================================== | |||
| void valueTreeChildAdded (ValueTree& parentTree, ValueTree&) { refreshIfNeeded (parentTree); } | |||
| void valueTreeChildRemoved (ValueTree& parentTree, ValueTree&) { refreshIfNeeded (parentTree); } | |||
| void valueTreeChildOrderChanged (ValueTree& parentTree) { refreshIfNeeded (parentTree); } | |||
| void refreshIfNeeded (ValueTree& changedTree) | |||
| { | |||
| ProjectSettingsComponent* psc = findParentComponentOfClass<ProjectSettingsComponent>(); | |||
| if (psc != nullptr) | |||
| psc->newItemButtonClicked (createNewButton); | |||
| if (changedTree == exportersTree) | |||
| refreshSubItems(); | |||
| } | |||
| OwnedArray<PropertyGroup> groups; | |||
| TextButton createNewButton; | |||
| bool dontDisplayName; | |||
| }; | |||
| Project& project; | |||
| var lastProjectType; | |||
| PropertyGroup mainProjectInfoPanel, modulesPanelGroup; | |||
| PropertyGroupList exporters; | |||
| private: | |||
| Project& project; | |||
| ValueTree exportersTree; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProjectSettingsComponent); | |||
| }; | |||
| //============================================================================== | |||
| class SettingsComp : public Component, | |||
| private ChangeListener | |||
| { | |||
| public: | |||
| SettingsComp (Project& project_) | |||
| : project (project_) | |||
| { | |||
| addAndMakeVisible (&groups[0]); | |||
| addAndMakeVisible (&groups[1]); | |||
| //[/MiscUserDefs] | |||
| createAllPanels(); | |||
| project.addChangeListener (this); | |||
| } | |||
| //============================================================================== | |||
| ProjectInformationComponent::ProjectInformationComponent (Project& project_) | |||
| : project (project_) | |||
| { | |||
| //[Constructor_pre] | |||
| //[/Constructor_pre] | |||
| addChildAndSetID (&viewport, "ykdBpb"); | |||
| addChildAndSetID (&openProjectButton, "a550a652e2666ee7"); | |||
| addChildAndSetID (&saveAndOpenButton, "dRGMyYx"); | |||
| addChildAndSetID (&rollover, "QqLJBF"); | |||
| initialiseComponentState(); | |||
| openProjectButton.addListener (this); | |||
| saveAndOpenButton.addListener (this); | |||
| //[UserPreSize] | |||
| viewport.setViewedComponent (new ProjectSettingsComponent (project), true); | |||
| #if JUCE_MAC || JUCE_WINDOWS | |||
| openProjectButton.setCommandToTrigger (commandManager, CommandIDs::openInIDE, true); | |||
| openProjectButton.setButtonText (commandManager->getNameOfCommand (CommandIDs::openInIDE)); | |||
| saveAndOpenButton.setCommandToTrigger (commandManager, CommandIDs::saveAndOpenInIDE, true); | |||
| saveAndOpenButton.setButtonText (commandManager->getNameOfCommand (CommandIDs::saveAndOpenInIDE)); | |||
| #else | |||
| openProjectButton.setVisible (false); | |||
| saveAndOpenButton.setVisible (false); | |||
| #endif | |||
| //[/UserPreSize] | |||
| setSize (808, 638); | |||
| //[Constructor] | |||
| project.addChangeListener (this); | |||
| //[/Constructor] | |||
| } | |||
| ~SettingsComp() | |||
| { | |||
| project.removeChangeListener (this); | |||
| } | |||
| ProjectInformationComponent::~ProjectInformationComponent() | |||
| { | |||
| //[Destructor] | |||
| project.removeChangeListener (this); | |||
| //[/Destructor] | |||
| } | |||
| void parentSizeChanged() | |||
| { | |||
| updateSizes (*this, groups, 2); | |||
| } | |||
| //============================================================================== | |||
| void ProjectInformationComponent::buttonClicked (Button* buttonThatWasClicked) | |||
| { | |||
| //[UserbuttonClicked_Pre] | |||
| //[/UserbuttonClicked_Pre] | |||
| void createAllPanels() | |||
| { | |||
| { | |||
| PropertyListBuilder props; | |||
| project.createPropertyEditors (props); | |||
| groups[0].setProperties (props); | |||
| groups[0].setName ("Project Settings"); | |||
| if (buttonThatWasClicked == &openProjectButton) | |||
| { | |||
| //[UserButtonCode_openProjectButton] -- add your button handler code here.. | |||
| //[/UserButtonCode_openProjectButton] | |||
| } | |||
| else if (buttonThatWasClicked == &saveAndOpenButton) | |||
| { | |||
| //[UserButtonCode_saveAndOpenButton] -- add your button handler code here.. | |||
| //[/UserButtonCode_saveAndOpenButton] | |||
| } | |||
| lastProjectType = project.getProjectTypeValue().getValue(); | |||
| } | |||
| //[UserbuttonClicked_Post] | |||
| //[/UserbuttonClicked_Post] | |||
| } | |||
| PropertyListBuilder props; | |||
| props.add (new ModulesPanel (project)); | |||
| groups[1].setProperties (props); | |||
| groups[1].setName ("Modules"); | |||
| void ProjectInformationComponent::paint (Graphics& g) | |||
| { | |||
| //[UserPaint] | |||
| g.setTiledImageFill (ImageCache::getFromMemory (BinaryData::brushed_aluminium_png, BinaryData::brushed_aluminium_pngSize), | |||
| 0, 0, 1.0f); | |||
| g.fillAll(); | |||
| drawRecessedShadows (g, getWidth(), getHeight(), 14); | |||
| //[/UserPaint] | |||
| } | |||
| parentSizeChanged(); | |||
| } | |||
| //[MiscUserCode] You can add your own definitions of your custom methods or any other code here... | |||
| void ProjectInformationComponent::changeListenerCallback (ChangeBroadcaster*) | |||
| { | |||
| dynamic_cast<ProjectSettingsComponent*> (viewport.getViewedComponent())->update(); | |||
| } | |||
| //[/MiscUserCode] | |||
| void changeListenerCallback (ChangeBroadcaster*) | |||
| { | |||
| if (lastProjectType != project.getProjectTypeValue().getValue()) | |||
| createAllPanels(); | |||
| } | |||
| //============================================================================== | |||
| //======================= Jucer Information Section ========================== | |||
| //============================================================================== | |||
| #if 0 | |||
| /* This section stores the metadata for this component - edit it at your own risk! | |||
| JUCER_COMPONENT_METADATA_START | |||
| <COMPONENT id="tO9EG1a" className="ProjectInformationComponent" width="808" | |||
| height="638" background="f6f9ff" parentClasses="public Component, public ChangeListener" | |||
| constructorParams="Project& project_" memberInitialisers="project (project_)"> | |||
| <COMPONENTS> | |||
| <VIEWPORT id="ykdBpb" memberName="viewport" position="8, 8, parent.width - 8, parent.height - 74" | |||
| scrollBarV="1" scrollBarH="1" scrollbarWidth="16"/> | |||
| <TEXTBUTTON id="a550a652e2666ee7" memberName="openProjectButton" focusOrder="0" | |||
| text="Open Project in " createCallback="1" radioGroup="0" connectedLeft="0" | |||
| connectedRight="0" connectedTop="0" connectedBottom="0" backgroundColour="FFDDDDFF" | |||
| textColour="" backgroundColourOn="" textColourOn="" position="8, parent.height - 34, left + 227, top + 24"/> | |||
| <TEXTBUTTON id="dRGMyYx" name="" memberName="saveAndOpenButton" position="8, parent.height - 65, left + 227, top + 24" | |||
| text="Save And Open in" createCallback="1" radioGroup="0" connectedLeft="0" | |||
| connectedRight="0" connectedTop="0" connectedBottom="0" backgroundColour="FFDDDDFF"/> | |||
| <GENERICCOMPONENT id="QqLJBF" memberName="rollover" position="246, parent.height - 68, parent.width - 8, parent.height - 4" | |||
| class="RolloverHelpComp" canBeAggregated="1" constructorParams=""/> | |||
| </COMPONENTS> | |||
| <MARKERS_X/> | |||
| <MARKERS_Y/> | |||
| <METHODS paint="1"/> | |||
| </COMPONENT> | |||
| JUCER_COMPONENT_METADATA_END | |||
| */ | |||
| #endif | |||
| private: | |||
| Project& project; | |||
| var lastProjectType; | |||
| PropertyGroup groups[2]; | |||
| void ProjectInformationComponent::initialiseComponentState() | |||
| { | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SettingsComp); | |||
| }; | |||
| BinaryData::ImageProvider imageProvider; | |||
| ComponentBuilder::initialiseFromValueTree (*this, getComponentState(), &imageProvider); | |||
| } | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RootItem); | |||
| }; | |||
| }; | |||
| ValueTree ProjectInformationComponent::getComponentState() | |||
| JucerTreeViewBase* createProjectConfigTreeViewRoot (Project& project) | |||
| { | |||
| const unsigned char data[] = | |||
| "COMPONENT\0\x01\x08id\0\x01\t\x05tO9EG1a\0""className\0\x01\x1d\x05ProjectInformationComponent\0width\0\x01\x05\x05""808\0height\0\x01\x05\x05""638\0""background\0\x01\x08\x05""f6f9ff\0parentClasses\0\x01)\x05public Component, public ChangeListener\0" | |||
| "constructorParams\0\x01\x13\x05Project& project_\0memberInitialisers\0\x01\x14\x05project (project_)\0\x01\x04""COMPONENTS\0\0\x01\x04VIEWPORT\0\x01\x06id\0\x01\x08\x05ykdBpb\0memberName\0\x01\n\x05viewport\0position\0\x01,\x05""8, 8, parent.width - " | |||
| "8, parent.height - 74\0scrollBarV\0\x01\x03\x05""1\0scrollBarH\0\x01\x03\x05""1\0scrollbarWidth\0\x01\x04\x05""16\0\0TEXTBUTTON\0\x01\x0fid\0\x01\x12\x05""a550a652e2666ee7\0memberName\0\x01\x13\x05openProjectButton\0""focusOrder\0\x01\x03\x05""0\0tex" | |||
| "t\0\x01\x12\x05Open Project in \0""createCallback\0\x01\x03\x05""1\0radioGroup\0\x01\x03\x05""0\0""connectedLeft\0\x01\x03\x05""0\0""connectedRight\0\x01\x03\x05""0\0""connectedTop\0\x01\x03\x05""0\0""connectedBottom\0\x01\x03\x05""0\0""backgroundCol" | |||
| "our\0\x01\n\x05""FFDDDDFF\0textColour\0\x01\x02\x05\0""backgroundColourOn\0\x01\x02\x05\0textColourOn\0\x01\x02\x05\0position\0\x01-\x05""8, parent.height - 34, left + 227, top + 24\0\0TEXTBUTTON\0\x01\x0cid\0\x01\t\x05""dRGMyYx\0name\0\x01\x02\x05\0" | |||
| "memberName\0\x01\x13\x05saveAndOpenButton\0position\0\x01-\x05""8, parent.height - 65, left + 227, top + 24\0text\0\x01\x12\x05Save And Open in\0""createCallback\0\x01\x03\x05""1\0radioGroup\0\x01\x03\x05""0\0""connectedLeft\0\x01\x03\x05""0\0""conne" | |||
| "ctedRight\0\x01\x03\x05""0\0""connectedTop\0\x01\x03\x05""0\0""connectedBottom\0\x01\x03\x05""0\0""backgroundColour\0\x01\n\x05""FFDDDDFF\0\0GENERICCOMPONENT\0\x01\x06id\0\x01\x08\x05QqLJBF\0memberName\0\x01\n\x05rollover\0position\0\x01>\x05""246, p" | |||
| "arent.height - 68, parent.width - 8, parent.height - 4\0""class\0\x01\x12\x05RolloverHelpComp\0""canBeAggregated\0\x01\x03\x05""1\0""constructorParams\0\x01\x02\x05\0\0MARKERS_X\0\0\0MARKERS_Y\0\0\0METHODS\0\x01\x01paint\0\x01\x03\x05""1\0\0"; | |||
| return ValueTree::readFromData (data, sizeof (data)); | |||
| return new ProjectSettingsTreeClasses::RootItem (project); | |||
| } | |||
| @@ -1,17 +1,24 @@ | |||
| /* | |||
| ============================================================================== | |||
| This is an automatically generated file! | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-11 by Raw Material Software Ltd. | |||
| Be careful when adding custom code to these files, as only the code within | |||
| the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded | |||
| and re-saved. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||
| Public License (Version 2), as published by the Free Software Foundation. | |||
| A copy of the license is included in the JUCE distribution, or can be found | |||
| online at www.gnu.org/licenses. | |||
| Created for JUCE version: JUCE v2.0.16 | |||
| 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. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE is copyright 2004-11 by Raw Material Software ltd. | |||
| To release a closed-source product which uses JUCE, commercial licenses are | |||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||
| ============================================================================== | |||
| */ | |||
| @@ -19,52 +26,10 @@ | |||
| #ifndef __JUCER_PROJECTINFORMATIONCOMPONENT_H_30FFCD07__ | |||
| #define __JUCER_PROJECTINFORMATIONCOMPONENT_H_30FFCD07__ | |||
| //[Headers] -- You can add your own extra header files here -- | |||
| #include "jucer_Project.h" | |||
| //[/Headers] | |||
| //============================================================================== | |||
| /** | |||
| //[Comments] | |||
| Holds the tabs containing all the project info. | |||
| //[/Comments] | |||
| */ | |||
| class ProjectInformationComponent : public Component, | |||
| public ChangeListener, | |||
| public ButtonListener | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| ProjectInformationComponent (Project& project_); | |||
| ~ProjectInformationComponent(); | |||
| //============================================================================== | |||
| //[UserMethods] | |||
| void changeListenerCallback (ChangeBroadcaster*); | |||
| //[/UserMethods] | |||
| void buttonClicked (Button* buttonThatWasClicked); | |||
| void paint (Graphics& g); | |||
| private: | |||
| //============================================================================== | |||
| //[UserVariables] | |||
| Project& project; | |||
| //[/UserVariables] | |||
| //============================================================================== | |||
| Viewport viewport; | |||
| TextButton openProjectButton; | |||
| TextButton saveAndOpenButton; | |||
| RolloverHelpComp rollover; | |||
| #include "../Utility/jucer_JucerTreeViewBase.h" | |||
| void initialiseComponentState(); | |||
| static ValueTree getComponentState(); | |||
| JucerTreeViewBase* createProjectConfigTreeViewRoot (Project& project); | |||
| //============================================================================== | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProjectInformationComponent) | |||
| }; | |||
| #endif // __JUCER_PROJECTINFORMATIONCOMPONENT_H_30FFCD07__ | |||
| @@ -429,13 +429,6 @@ void ProjectTreeViewBase::addSubItems() | |||
| } | |||
| } | |||
| void ProjectTreeViewBase::refreshSubItems() | |||
| { | |||
| WholeTreeOpennessRestorer openness (*this); | |||
| clearSubItems(); | |||
| addSubItems(); | |||
| } | |||
| static void treeViewMultiSelectItemChosen (int resultCode, ProjectTreeViewBase* item) | |||
| { | |||
| switch (resultCode) | |||
| @@ -454,60 +447,6 @@ void ProjectTreeViewBase::showMultiSelectionPopupMenu() | |||
| ModalCallbackFunction::create (treeViewMultiSelectItemChosen, this)); | |||
| } | |||
| static void treeViewMenuItemChosen (int resultCode, ProjectTreeViewBase* item) | |||
| { | |||
| item->handlePopupMenuResult (resultCode); | |||
| } | |||
| void ProjectTreeViewBase::launchPopupMenu (PopupMenu& m) | |||
| { | |||
| m.showMenuAsync (PopupMenu::Options(), | |||
| ModalCallbackFunction::create (treeViewMenuItemChosen, this)); | |||
| } | |||
| void ProjectTreeViewBase::handlePopupMenuResult (int) | |||
| { | |||
| } | |||
| void ProjectTreeViewBase::itemDoubleClicked (const MouseEvent& e) | |||
| { | |||
| invokeShowDocument(); | |||
| } | |||
| class TreeviewItemSelectionTimer : public Timer | |||
| { | |||
| public: | |||
| TreeviewItemSelectionTimer (ProjectTreeViewBase& owner_) | |||
| : owner (owner_) | |||
| {} | |||
| void timerCallback() | |||
| { | |||
| owner.invokeShowDocument(); | |||
| } | |||
| private: | |||
| ProjectTreeViewBase& owner; | |||
| JUCE_DECLARE_NON_COPYABLE (TreeviewItemSelectionTimer); | |||
| }; | |||
| void ProjectTreeViewBase::itemSelectionChanged (bool isNowSelected) | |||
| { | |||
| if (isNowSelected) | |||
| { | |||
| delayedSelectionTimer = new TreeviewItemSelectionTimer (*this); | |||
| // for images, give the user longer to start dragging before assuming they're | |||
| // clicking to select it for previewing.. | |||
| delayedSelectionTimer->startTimer (item.isImageFile() ? 250 : 120); | |||
| } | |||
| else | |||
| { | |||
| delayedSelectionTimer = nullptr; | |||
| } | |||
| } | |||
| String ProjectTreeViewBase::getTooltip() | |||
| { | |||
| return String::empty; | |||
| @@ -515,14 +454,15 @@ String ProjectTreeViewBase::getTooltip() | |||
| var ProjectTreeViewBase::getDragSourceDescription() | |||
| { | |||
| delayedSelectionTimer = nullptr; | |||
| cancelDelayedSelectionTimer(); | |||
| return projectItemDragType; | |||
| } | |||
| void ProjectTreeViewBase::invokeShowDocument() | |||
| int ProjectTreeViewBase::getMillisecsAllowedForDragGesture() | |||
| { | |||
| delayedSelectionTimer = nullptr; | |||
| showDocument(); | |||
| // for images, give the user longer to start dragging before assuming they're | |||
| // clicking to select it for previewing.. | |||
| return item.isImageFile() ? 250 : JucerTreeViewBase::getMillisecsAllowedForDragGesture(); | |||
| } | |||
| //============================================================================== | |||
| @@ -530,20 +470,3 @@ ProjectTreeViewBase* ProjectTreeViewBase::getParentProjectItem() const | |||
| { | |||
| return dynamic_cast <ProjectTreeViewBase*> (getParentItem()); | |||
| } | |||
| ProjectContentComponent* ProjectTreeViewBase::getProjectContentComponent() const | |||
| { | |||
| Component* c = getOwnerView(); | |||
| while (c != nullptr) | |||
| { | |||
| ProjectContentComponent* pcc = dynamic_cast <ProjectContentComponent*> (c); | |||
| if (pcc != nullptr) | |||
| return pcc; | |||
| c = c->getParentComponent(); | |||
| } | |||
| return 0; | |||
| } | |||
| @@ -30,7 +30,6 @@ | |||
| #include "../Utility/jucer_JucerTreeViewBase.h" | |||
| #include "jucer_Project.h" | |||
| #include "../Project Saving/jucer_ResourceFile.h" | |||
| #include "jucer_ProjectContentComponent.h" | |||
| //============================================================================== | |||
| @@ -45,7 +44,7 @@ protected: | |||
| public: | |||
| //============================================================================== | |||
| virtual bool isRoot() const { return false; } | |||
| virtual bool acceptsFileDrop (const StringArray& files) const = 0; | |||
| virtual bool acceptsFileDrop (const StringArray& files) const = 0; | |||
| virtual bool acceptsDragItems (const OwnedArray <Project::Item>& selectedNodes) = 0; | |||
| //============================================================================== | |||
| @@ -58,7 +57,6 @@ public: | |||
| virtual void deleteItem(); | |||
| virtual void deleteAllSelectedItems(); | |||
| virtual void revealInFinder() const; | |||
| virtual void showDocument() = 0; | |||
| virtual void browseToAddExistingFiles(); | |||
| virtual void checkFileStatus(); // (recursive) | |||
| @@ -66,10 +64,6 @@ public: | |||
| virtual void moveSelectedItemsTo (OwnedArray <Project::Item>& selectedNodes, int insertIndex); | |||
| virtual void showMultiSelectionPopupMenu(); | |||
| void launchPopupMenu (PopupMenu&); // runs asynchronously, and produces a callback to handlePopupMenuResult(). | |||
| virtual void handlePopupMenuResult (int resultCode); | |||
| void invokeShowDocument(); | |||
| virtual ProjectTreeViewBase* findTreeViewItem (const Project::Item& itemToFind); | |||
| //============================================================================== | |||
| @@ -80,16 +74,13 @@ public: | |||
| void valueTreeParentChanged (ValueTree& tree); | |||
| //============================================================================== | |||
| // TreeViewItem stuff.. | |||
| bool mightContainSubItems(); | |||
| String getUniqueName() const; | |||
| void itemOpennessChanged (bool isNowOpen); | |||
| void refreshSubItems(); | |||
| bool canBeSelected() const { return true; } | |||
| void itemDoubleClicked (const MouseEvent& e); | |||
| void itemSelectionChanged (bool isNowSelected); | |||
| String getTooltip(); | |||
| var getDragSourceDescription(); | |||
| void addSubItems(); | |||
| //============================================================================== | |||
| // Drag-and-drop stuff.. | |||
| @@ -97,6 +88,7 @@ public: | |||
| void filesDropped (const StringArray& files, int insertIndex); | |||
| bool isInterestedInDragSource (const DragAndDropTarget::SourceDetails& dragSourceDetails); | |||
| void itemDropped (const DragAndDropTarget::SourceDetails& dragSourceDetails, int insertIndex); | |||
| int getMillisecsAllowedForDragGesture(); | |||
| static void getAllSelectedNodesInTree (Component* componentInTree, OwnedArray <Project::Item>& selectedNodes); | |||
| @@ -105,11 +97,9 @@ public: | |||
| protected: | |||
| bool isFileMissing; | |||
| ScopedPointer<Timer> delayedSelectionTimer; | |||
| //============================================================================== | |||
| void treeChildrenChanged (const ValueTree& parentTree); | |||
| virtual void addSubItems(); | |||
| virtual ProjectTreeViewBase* createSubItem (const Project::Item& node) = 0; | |||
| const Drawable* getIcon() const { return item.getIcon(); } | |||
| @@ -118,7 +108,6 @@ protected: | |||
| static void moveItems (OwnedArray <Project::Item>& selectedNodes, | |||
| Project::Item destNode, int insertIndex); | |||
| ProjectContentComponent* getProjectContentComponent() const; | |||
| ProjectTreeViewBase* getParentProjectItem() const; | |||
| }; | |||
| @@ -29,7 +29,7 @@ | |||
| #include "../Application/jucer_OpenDocumentManager.h" | |||
| #include "../Code Editor/jucer_SourceCodeEditor.h" | |||
| #include "jucer_NewFileWizard.h" | |||
| #include "jucer_ProjectContentComponent.h" | |||
| //============================================================================== | |||
| GroupTreeViewItem::GroupTreeViewItem (const Project::Item& item_) | |||
| @@ -99,13 +99,8 @@ void GroupTreeViewItem::showDocument() | |||
| { | |||
| ProjectContentComponent* pcc = getProjectContentComponent(); | |||
| if (pcc != nullptr) | |||
| { | |||
| if (isRoot()) | |||
| pcc->setEditorComponent (new ProjectInformationComponent (item.project), 0); | |||
| else | |||
| pcc->setEditorComponent (new GroupInformationComponent (item), 0); | |||
| } | |||
| if (pcc != nullptr && ! isRoot()) | |||
| pcc->setEditorComponent (new GroupInformationComponent (item), nullptr); | |||
| } | |||
| void GroupTreeViewItem::showPopupMenu() | |||
| @@ -24,6 +24,7 @@ | |||
| */ | |||
| #include "jucer_JucerTreeViewBase.h" | |||
| #include "../Project/jucer_ProjectContentComponent.h" | |||
| //============================================================================== | |||
| @@ -33,6 +34,13 @@ JucerTreeViewBase::JucerTreeViewBase() | |||
| setLinesDrawnForSubItems (false); | |||
| } | |||
| void JucerTreeViewBase::refreshSubItems() | |||
| { | |||
| WholeTreeOpennessRestorer openness (*this); | |||
| clearSubItems(); | |||
| addSubItems(); | |||
| } | |||
| Font JucerTreeViewBase::getFont() const | |||
| { | |||
| return Font (getItemHeight() * 0.6f); | |||
| @@ -175,10 +183,82 @@ void JucerTreeViewBase::itemClicked (const MouseEvent& e) | |||
| } | |||
| } | |||
| void JucerTreeViewBase::showPopupMenu() | |||
| void JucerTreeViewBase::deleteItem() {} | |||
| void JucerTreeViewBase::deleteAllSelectedItems() {} | |||
| void JucerTreeViewBase::showDocument() {} | |||
| void JucerTreeViewBase::showPopupMenu() {} | |||
| void JucerTreeViewBase::showMultiSelectionPopupMenu() {} | |||
| static void treeViewMenuItemChosen (int resultCode, JucerTreeViewBase* item) | |||
| { | |||
| item->handlePopupMenuResult (resultCode); | |||
| } | |||
| void JucerTreeViewBase::launchPopupMenu (PopupMenu& m) | |||
| { | |||
| m.showMenuAsync (PopupMenu::Options(), | |||
| ModalCallbackFunction::create (treeViewMenuItemChosen, this)); | |||
| } | |||
| void JucerTreeViewBase::handlePopupMenuResult (int) | |||
| { | |||
| } | |||
| ProjectContentComponent* JucerTreeViewBase::getProjectContentComponent() const | |||
| { | |||
| Component* c = getOwnerView(); | |||
| while (c != nullptr) | |||
| { | |||
| ProjectContentComponent* pcc = dynamic_cast <ProjectContentComponent*> (c); | |||
| if (pcc != nullptr) | |||
| return pcc; | |||
| c = c->getParentComponent(); | |||
| } | |||
| return 0; | |||
| } | |||
| //============================================================================== | |||
| class JucerTreeViewBase::ItemSelectionTimer : public Timer | |||
| { | |||
| public: | |||
| ItemSelectionTimer (JucerTreeViewBase& owner_) : owner (owner_) {} | |||
| void timerCallback() { owner.invokeShowDocument(); } | |||
| private: | |||
| JucerTreeViewBase& owner; | |||
| JUCE_DECLARE_NON_COPYABLE (ItemSelectionTimer); | |||
| }; | |||
| void JucerTreeViewBase::itemSelectionChanged (bool isNowSelected) | |||
| { | |||
| if (isNowSelected) | |||
| { | |||
| delayedSelectionTimer = new ItemSelectionTimer (*this); | |||
| delayedSelectionTimer->startTimer (getMillisecsAllowedForDragGesture()); | |||
| } | |||
| else | |||
| { | |||
| cancelDelayedSelectionTimer(); | |||
| } | |||
| } | |||
| void JucerTreeViewBase::invokeShowDocument() | |||
| { | |||
| cancelDelayedSelectionTimer(); | |||
| showDocument(); | |||
| } | |||
| void JucerTreeViewBase::itemDoubleClicked (const MouseEvent& e) | |||
| { | |||
| invokeShowDocument(); | |||
| } | |||
| void JucerTreeViewBase::showMultiSelectionPopupMenu() | |||
| void JucerTreeViewBase::cancelDelayedSelectionTimer() | |||
| { | |||
| delayedSelectionTimer = nullptr; | |||
| } | |||
| @@ -27,6 +27,7 @@ | |||
| #define __JUCER_JUCERTREEVIEWBASE_JUCEHEADER__ | |||
| #include "../jucer_Headers.h" | |||
| class ProjectContentComponent; | |||
| //============================================================================== | |||
| @@ -42,6 +43,8 @@ public: | |||
| void paintOpenCloseButton (Graphics& g, int width, int height, bool isMouseOver); | |||
| Component* createItemComponent(); | |||
| void itemClicked (const MouseEvent& e); | |||
| void itemSelectionChanged (bool isNowSelected); | |||
| void itemDoubleClicked (const MouseEvent&); | |||
| //============================================================================== | |||
| virtual Font getFont() const; | |||
| @@ -51,13 +54,20 @@ public: | |||
| virtual bool isMissing() = 0; | |||
| virtual const Drawable* getIcon() const = 0; | |||
| virtual void createLeftEdgeComponents (OwnedArray<Component>&) {} | |||
| virtual Component* createRightEdgeComponent() { return nullptr; } | |||
| virtual Component* createRightEdgeComponent() { return nullptr; } | |||
| virtual int getMillisecsAllowedForDragGesture() { return 120; }; | |||
| void refreshSubItems(); | |||
| virtual void deleteItem(); | |||
| virtual void deleteAllSelectedItems(); | |||
| virtual void showDocument(); | |||
| virtual void showPopupMenu(); | |||
| virtual void showMultiSelectionPopupMenu(); | |||
| virtual void showRenameBox(); | |||
| void launchPopupMenu (PopupMenu&); // runs asynchronously, and produces a callback to handlePopupMenuResult(). | |||
| virtual void handlePopupMenuResult (int resultCode); | |||
| //============================================================================== | |||
| // To handle situations where an item gets deleted before openness is | |||
| // restored for it, this OpennessRestorer keeps only a pointer to the | |||
| @@ -76,6 +86,18 @@ public: | |||
| }; | |||
| int textX; | |||
| protected: | |||
| ProjectContentComponent* getProjectContentComponent() const; | |||
| void cancelDelayedSelectionTimer(); | |||
| virtual void addSubItems() {} | |||
| private: | |||
| class ItemSelectionTimer; | |||
| friend class ItemSelectionTimer; | |||
| ScopedPointer<Timer> delayedSelectionTimer; | |||
| void invokeShowDocument(); | |||
| }; | |||
| @@ -206,3 +206,15 @@ const Drawable* StoredSettings::getImageFileIcon() | |||
| return imageFileIcon; | |||
| } | |||
| const Drawable* StoredSettings::getCogIcon() | |||
| { | |||
| if (cogIcon == nullptr) | |||
| { | |||
| ScopedPointer<XmlElement> svg (XmlDocument::parse (BinaryData::cog_icon_svg)); | |||
| jassert (svg != nullptr); | |||
| cogIcon = Drawable::createFromSVG (*svg); | |||
| } | |||
| return cogIcon; | |||
| } | |||
| @@ -69,13 +69,14 @@ public: | |||
| //============================================================================== | |||
| Image getFallbackImage(); | |||
| const Drawable* getImageFileIcon(); | |||
| const Drawable* getCogIcon(); | |||
| private: | |||
| ScopedPointer<PropertiesFile> props; | |||
| StringArray fontNames; | |||
| ScopedPointer<Drawable> imageFileIcon; | |||
| ScopedPointer<Drawable> imageFileIcon, cogIcon; | |||
| Image fallbackImage; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StoredSettings); | |||