diff --git a/extras/Introjucer/Builds/CodeBlocks/The Introjucer.cbp b/extras/Introjucer/Builds/CodeBlocks/The Introjucer.cbp
index 4ff7b821fd..4199254cff 100644
--- a/extras/Introjucer/Builds/CodeBlocks/The Introjucer.cbp
+++ b/extras/Introjucer/Builds/CodeBlocks/The Introjucer.cbp
@@ -122,11 +122,6 @@
-
-
-
-
-
diff --git a/extras/Introjucer/Builds/Linux/Makefile b/extras/Introjucer/Builds/Linux/Makefile
index 780a084747..7c9b13bd06 100644
--- a/extras/Introjucer/Builds/Linux/Makefile
+++ b/extras/Introjucer/Builds/Linux/Makefile
@@ -52,7 +52,6 @@ OBJECTS := \
$(OBJDIR)/jucer_AppearanceSettings_788d9889.o \
$(OBJDIR)/jucer_CommandLine_f35de107.o \
$(OBJDIR)/jucer_DocumentEditorComponent_695dff1d.o \
- $(OBJDIR)/jucer_JuceUpdater_cf7865c4.o \
$(OBJDIR)/jucer_Main_f8488f5b.o \
$(OBJDIR)/jucer_MainWindow_1e163aeb.o \
$(OBJDIR)/jucer_OpenDocumentManager_4c72d210.o \
@@ -134,11 +133,6 @@ $(OBJDIR)/jucer_DocumentEditorComponent_695dff1d.o: ../../Source/Application/juc
@echo "Compiling jucer_DocumentEditorComponent.cpp"
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
-$(OBJDIR)/jucer_JuceUpdater_cf7865c4.o: ../../Source/Application/jucer_JuceUpdater.cpp
- -@mkdir -p $(OBJDIR)
- @echo "Compiling jucer_JuceUpdater.cpp"
- @$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
-
$(OBJDIR)/jucer_Main_f8488f5b.o: ../../Source/Application/jucer_Main.cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling jucer_Main.cpp"
diff --git a/extras/Introjucer/Builds/MacOSX/The Introjucer.xcodeproj/project.pbxproj b/extras/Introjucer/Builds/MacOSX/The Introjucer.xcodeproj/project.pbxproj
index 5ec4438098..9cec215099 100644
--- a/extras/Introjucer/Builds/MacOSX/The Introjucer.xcodeproj/project.pbxproj
+++ b/extras/Introjucer/Builds/MacOSX/The Introjucer.xcodeproj/project.pbxproj
@@ -16,7 +16,6 @@
357A6AA6960EF95D92929BEE = { isa = PBXBuildFile; fileRef = 441CFEA771BAA50E187342E9; };
954A036F5DDB375DB23FFB3E = { isa = PBXBuildFile; fileRef = 0400CB0E056A1D840304D2DE; };
3EB3D569250C4BA4CA9AF578 = { isa = PBXBuildFile; fileRef = C7608A3967D9AB9481848F2B; };
- B1A786B525176BEE309998EA = { isa = PBXBuildFile; fileRef = BE94248CF8069E6707174CDB; };
95B44E6C74B1DED31DBE37EB = { isa = PBXBuildFile; fileRef = 8C52A3DDA62A746AA7A68535; };
AA9D0B8E23F3D87A23DE9F8A = { isa = PBXBuildFile; fileRef = 9069981E414A631B036CC9AC; };
244BA1BDA5FAA465EA3F9C6D = { isa = PBXBuildFile; fileRef = 2247EE920DF0610CAF9F4513; };
@@ -599,7 +598,6 @@
A513D5453FF52483D13BA026 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_PropertyPanel.h"; path = "../../../../modules/juce_gui_basics/properties/juce_PropertyPanel.h"; sourceTree = "SOURCE_ROOT"; };
A5864A527A761F92C237EB7C = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ScopedXLock.h"; path = "../../../../modules/juce_events/native/juce_ScopedXLock.h"; sourceTree = "SOURCE_ROOT"; };
A5D2E5A77E6A67E35440BF3B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_FileOutputStream.cpp"; path = "../../../../modules/juce_core/files/juce_FileOutputStream.cpp"; sourceTree = "SOURCE_ROOT"; };
- A5E171104E49595BD9485DFD = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_JuceUpdater.h"; path = "../../Source/Application/jucer_JuceUpdater.h"; sourceTree = "SOURCE_ROOT"; };
A60E4D1A58B70887556782F4 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ImageFileFormat.cpp"; path = "../../../../modules/juce_graphics/images/juce_ImageFileFormat.cpp"; sourceTree = "SOURCE_ROOT"; };
A63DA2EB2FA9E6F88F63A09A = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_SparseSet.h"; path = "../../../../modules/juce_core/containers/juce_SparseSet.h"; sourceTree = "SOURCE_ROOT"; };
A6D36E0244150AFBF63C1162 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_FileChooserDialogBox.cpp"; path = "../../../../modules/juce_gui_basics/filebrowser/juce_FileChooserDialogBox.cpp"; sourceTree = "SOURCE_ROOT"; };
@@ -676,7 +674,6 @@
BDE24BA8FEAE654645079B84 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Variant.cpp"; path = "../../../../modules/juce_core/containers/juce_Variant.cpp"; sourceTree = "SOURCE_ROOT"; };
BDEBB0AC32DDA8C16FFE6011 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TooltipClient.h"; path = "../../../../modules/juce_gui_basics/mouse/juce_TooltipClient.h"; sourceTree = "SOURCE_ROOT"; };
BE90AA37929461DF6F6A9E13 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_OldSchoolLookAndFeel.h"; path = "../../../../modules/juce_gui_extra/lookandfeel/juce_OldSchoolLookAndFeel.h"; sourceTree = "SOURCE_ROOT"; };
- BE94248CF8069E6707174CDB = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_JuceUpdater.cpp"; path = "../../Source/Application/jucer_JuceUpdater.cpp"; sourceTree = "SOURCE_ROOT"; };
BE97579323E97AF084D41476 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_DirectoryContentsList.cpp"; path = "../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp"; sourceTree = "SOURCE_ROOT"; };
BF171B0762D5550B797869F2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Expression.h"; path = "../../../../modules/juce_core/maths/juce_Expression.h"; sourceTree = "SOURCE_ROOT"; };
BF3CEF080FA013E2778DCE90 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_Project.h"; path = "../../Source/Project/jucer_Project.h"; sourceTree = "SOURCE_ROOT"; };
@@ -726,12 +723,12 @@
CDDF5BDC75277F7B83A38885 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_PropertySet.cpp"; path = "../../../../modules/juce_core/containers/juce_PropertySet.cpp"; sourceTree = "SOURCE_ROOT"; };
CDF8F65F9079B2C14A740F0F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ImageButton.h"; path = "../../../../modules/juce_gui_basics/buttons/juce_ImageButton.h"; sourceTree = "SOURCE_ROOT"; };
CE1DFE4E3908943656E180AD = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_UnitTest.cpp"; path = "../../../../modules/juce_core/unit_tests/juce_UnitTest.cpp"; sourceTree = "SOURCE_ROOT"; };
+ CF0615A1AF1A514A60322B50 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MouseCursor.h"; path = "../../../../modules/juce_gui_basics/mouse/juce_MouseCursor.h"; sourceTree = "SOURCE_ROOT"; };
CF21D9DB3AEC0A4DCAB36A99 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_Icons.cpp"; path = "../../Source/Utility/jucer_Icons.cpp"; 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; };
D041043D3B554B88F855C174 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_HighResolutionTimer.h"; path = "../../../../modules/juce_core/threads/juce_HighResolutionTimer.h"; sourceTree = "SOURCE_ROOT"; };
- D0D8B580D0689FFF4B9B823B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_StrokeType.h"; path = "../../Source/ComponentEditor/paintelements/jucer_StrokeType.h"; sourceTree = "SOURCE_ROOT"; };
D0F1614CC861E8E0B59B7A06 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_linux_Messaging.cpp"; path = "../../../../modules/juce_events/native/juce_linux_Messaging.cpp"; sourceTree = "SOURCE_ROOT"; };
D10D51A0A2D63F38B4D86A60 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_ResourceFile.cpp"; path = "../../Source/Project Saving/jucer_ResourceFile.cpp"; sourceTree = "SOURCE_ROOT"; };
D141433D3FE81F20490DE928 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Desktop.h"; path = "../../../../modules/juce_gui_basics/components/juce_Desktop.h"; sourceTree = "SOURCE_ROOT"; };
@@ -742,7 +739,6 @@
D374DC78AAC02504576AA9B3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_GroupComponentHandler.h"; path = "../../Source/ComponentEditor/components/jucer_GroupComponentHandler.h"; sourceTree = "SOURCE_ROOT"; };
D376B9B54EC944E766AFEC45 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_PopupMenu.cpp"; path = "../../../../modules/juce_gui_basics/menus/juce_PopupMenu.cpp"; sourceTree = "SOURCE_ROOT"; };
D3E139185095C486DD3D61F2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_TranslationTool.h"; path = "../../Source/Utility/jucer_TranslationTool.h"; sourceTree = "SOURCE_ROOT"; };
- D4444EC6342A2A7BC4F7BC46 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_ComponentTextProperty.h"; path = "../../Source/ComponentEditor/properties/jucer_ComponentTextProperty.h"; sourceTree = "SOURCE_ROOT"; };
D4697A0232AECE5DAC5E332E = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ChoicePropertyComponent.cpp"; path = "../../../../modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
D4E56676E2EF83404EDCBA8C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_TextEditor.cpp"; path = "../../../../modules/juce_gui_basics/widgets/juce_TextEditor.cpp"; sourceTree = "SOURCE_ROOT"; };
D4F2D42C58F4D86E00E76F31 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ApplicationCommandID.h"; path = "../../../../modules/juce_gui_basics/commands/juce_ApplicationCommandID.h"; sourceTree = "SOURCE_ROOT"; };
@@ -757,15 +753,30 @@
D782DA091AD3ECE158FC6A5F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ButtonPropertyComponent.h"; path = "../../../../modules/juce_gui_basics/properties/juce_ButtonPropertyComponent.h"; sourceTree = "SOURCE_ROOT"; };
D7A7F1AA9F313B0CCAAA73A0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MathsFunctions.h"; path = "../../../../modules/juce_core/maths/juce_MathsFunctions.h"; sourceTree = "SOURCE_ROOT"; };
D800DE818BEDBF4579D15B1D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_mac_AppleRemote.mm"; path = "../../../../modules/juce_gui_extra/native/juce_mac_AppleRemote.mm"; sourceTree = "SOURCE_ROOT"; };
- D87FC8F6834E9DC9C8E88B94 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_JustificationProperty.h"; path = "../../Source/ComponentEditor/properties/jucer_JustificationProperty.h"; sourceTree = "SOURCE_ROOT"; };
D926E13AB5AD647A7A00F486 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_linux_Network.cpp"; path = "../../../../modules/juce_core/native/juce_linux_Network.cpp"; sourceTree = "SOURCE_ROOT"; };
- D92A6E9404A30EED32DCE4ED = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_RelativePositionedRectangle.h"; path = "../../Source/ComponentEditor/ui/jucer_RelativePositionedRectangle.h"; sourceTree = "SOURCE_ROOT"; };
D9342535EA61901A1AD816C6 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_linux_WebBrowserComponent.cpp"; path = "../../../../modules/juce_gui_extra/native/juce_linux_WebBrowserComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
D95D7B49EC6C6BDCB5A1B988 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_ios_MessageManager.mm"; path = "../../../../modules/juce_events/native/juce_ios_MessageManager.mm"; sourceTree = "SOURCE_ROOT"; };
+ D9B077E2ECDDA94961E134D7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_StringPairArray.h"; path = "../../../../modules/juce_core/text/juce_StringPairArray.h"; sourceTree = "SOURCE_ROOT"; };
D9E59DE07A815AB303A297D9 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_data_structures.mm"; path = "../../../../modules/juce_data_structures/juce_data_structures.mm"; sourceTree = "SOURCE_ROOT"; };
+ DAF84A553D264705FA6EB6FF = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_TreeViewHandler.h"; path = "../../Source/ComponentEditor/components/jucer_TreeViewHandler.h"; sourceTree = "SOURCE_ROOT"; };
DB20268A566DABEAE3F2CBEE = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_RectanglePlacement.cpp"; path = "../../../../modules/juce_graphics/placement/juce_RectanglePlacement.cpp"; sourceTree = "SOURCE_ROOT"; };
+ DB876F7873F42DC685A58CA7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_JPEGLoader.cpp"; path = "../../../../modules/juce_graphics/image_formats/juce_JPEGLoader.cpp"; sourceTree = "SOURCE_ROOT"; };
DBE0CDE1B017190ABBFF557C = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_ProjectExport_CodeBlocks.h"; path = "../../Source/Project Saving/jucer_ProjectExport_CodeBlocks.h"; sourceTree = "SOURCE_ROOT"; };
DC5E7FF30B01118F6DAEC38F = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Time.cpp"; path = "../../../../modules/juce_core/time/juce_Time.cpp"; sourceTree = "SOURCE_ROOT"; };
+ DD985A60FB76E976AF91852D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_SHA256.h"; path = "../../../../modules/juce_cryptography/hashing/juce_SHA256.h"; sourceTree = "SOURCE_ROOT"; };
+ DF7BB5B6B394EDEEF5F5B4B8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_CallbackMessage.h"; path = "../../../../modules/juce_events/messages/juce_CallbackMessage.h"; sourceTree = "SOURCE_ROOT"; };
+ E0F9CA57E44F7F7E7E217E47 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_ComponentUndoableAction.h"; path = "../../Source/ComponentEditor/components/jucer_ComponentUndoableAction.h"; sourceTree = "SOURCE_ROOT"; };
+ E4BB22E27C5AA4B666F265BD = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_TextButtonHandler.h"; path = "../../Source/ComponentEditor/components/jucer_TextButtonHandler.h"; sourceTree = "SOURCE_ROOT"; };
+ E5D6C36496F5BC84D7213BE8 = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
+ E60E28D1B7491047DEA236AE = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_ProjectContentComponent.h"; path = "../../Source/Project/jucer_ProjectContentComponent.h"; sourceTree = "SOURCE_ROOT"; };
+ E65A820D34BF39478B7C5925 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_DocumentEditorComponent.h"; path = "../../Source/Application/jucer_DocumentEditorComponent.h"; sourceTree = "SOURCE_ROOT"; };
+ E96597BBC6A98255B51B94DC = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
+ 25F52316D256B4534BED16D1 = { isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Introjucer.app; sourceTree = "BUILT_PRODUCTS_DIR"; };
+ D0D8B580D0689FFF4B9B823B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_StrokeType.h"; path = "../../Source/ComponentEditor/paintelements/jucer_StrokeType.h"; sourceTree = "SOURCE_ROOT"; };
+ D4444EC6342A2A7BC4F7BC46 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_ComponentTextProperty.h"; path = "../../Source/ComponentEditor/properties/jucer_ComponentTextProperty.h"; sourceTree = "SOURCE_ROOT"; };
+ D87FC8F6834E9DC9C8E88B94 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_JustificationProperty.h"; path = "../../Source/ComponentEditor/properties/jucer_JustificationProperty.h"; sourceTree = "SOURCE_ROOT"; };
+ D92A6E9404A30EED32DCE4ED = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_RelativePositionedRectangle.h"; path = "../../Source/ComponentEditor/ui/jucer_RelativePositionedRectangle.h"; sourceTree = "SOURCE_ROOT"; };
+ DA345D5B9DABD049F90DC96F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_GeneratedCode.h"; path = "../../Source/ComponentEditor/jucer_GeneratedCode.h"; sourceTree = "SOURCE_ROOT"; };
DC922C6A65D260C18E888E49 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_ComponentTemplate.cpp"; path = "../../Source/BinaryData/jucer_ComponentTemplate.cpp"; sourceTree = "SOURCE_ROOT"; };
DCCB75165B7C73A589498E87 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_linux_Windowing.cpp"; path = "../../../../modules/juce_gui_basics/native/juce_linux_Windowing.cpp"; sourceTree = "SOURCE_ROOT"; };
DD00494140C86144306A9356 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Array.h"; path = "../../../../modules/juce_core/containers/juce_Array.h"; sourceTree = "SOURCE_ROOT"; };
@@ -776,34 +787,19 @@
DEF579B1433EB8DEE7AB50F8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Drawable.cpp"; path = "../../../../modules/juce_gui_basics/drawables/juce_Drawable.cpp"; sourceTree = "SOURCE_ROOT"; };
DF725A596B7BCD7520CC0A9F = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_ResourceEditorPanel.cpp"; path = "../../Source/ComponentEditor/ui/jucer_ResourceEditorPanel.cpp"; sourceTree = "SOURCE_ROOT"; };
DFC6364D81D9C60BD4CA9D12 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_RelativeTime.cpp"; path = "../../../../modules/juce_core/time/juce_RelativeTime.cpp"; sourceTree = "SOURCE_ROOT"; };
- E0F9CA57E44F7F7E7E217E47 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_ComponentUndoableAction.h"; path = "../../Source/ComponentEditor/components/jucer_ComponentUndoableAction.h"; sourceTree = "SOURCE_ROOT"; };
+ E07C56267CBB46FC44EF2026 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Image.cpp"; path = "../../../../modules/juce_graphics/images/juce_Image.cpp"; sourceTree = "SOURCE_ROOT"; };
+ E1C16C872E34BCB144B469F9 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_EdgeTable.h"; path = "../../../../modules/juce_graphics/geometry/juce_EdgeTable.h"; sourceTree = "SOURCE_ROOT"; };
E2374E15D65425C4101237E2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_NewComponentTemplate.h"; path = "../../Source/BinaryData/jucer_NewComponentTemplate.h"; sourceTree = "SOURCE_ROOT"; };
+ E27F0860F27023BAA9798B46 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Rectangle.h"; path = "../../../../modules/juce_graphics/geometry/juce_Rectangle.h"; sourceTree = "SOURCE_ROOT"; };
E284B565DBD647DC0830D23B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ButtonPropertyComponent.cpp"; path = "../../../../modules/juce_gui_basics/properties/juce_ButtonPropertyComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
E2C1C995D554A3F0A363CE58 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Thread.h"; path = "../../../../modules/juce_core/threads/juce_Thread.h"; sourceTree = "SOURCE_ROOT"; };
E2DBA3307837B64AFCCD8F8D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_File.cpp"; path = "../../../../modules/juce_core/files/juce_File.cpp"; sourceTree = "SOURCE_ROOT"; };
- E446FFE889CD490FDE3F0F2B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ThreadWithProgressWindow.cpp"; path = "../../../../modules/juce_gui_basics/windows/juce_ThreadWithProgressWindow.cpp"; sourceTree = "SOURCE_ROOT"; };
- E4BB22E27C5AA4B666F265BD = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_TextButtonHandler.h"; path = "../../Source/ComponentEditor/components/jucer_TextButtonHandler.h"; sourceTree = "SOURCE_ROOT"; };
- E530742870F07704E9616358 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ToolbarItemComponent.h"; path = "../../../../modules/juce_gui_basics/widgets/juce_ToolbarItemComponent.h"; sourceTree = "SOURCE_ROOT"; };
- E5D6C36496F5BC84D7213BE8 = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
- E65A820D34BF39478B7C5925 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_DocumentEditorComponent.h"; path = "../../Source/Application/jucer_DocumentEditorComponent.h"; sourceTree = "SOURCE_ROOT"; };
- E7E1C4F416CFA44BE7DD1A74 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_KeyboardFocusTraverser.h"; path = "../../../../modules/juce_gui_basics/keyboard/juce_KeyboardFocusTraverser.h"; sourceTree = "SOURCE_ROOT"; };
- E96597BBC6A98255B51B94DC = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
- 25F52316D256B4534BED16D1 = { isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Introjucer.app; sourceTree = "BUILT_PRODUCTS_DIR"; };
- CF0615A1AF1A514A60322B50 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MouseCursor.h"; path = "../../../../modules/juce_gui_basics/mouse/juce_MouseCursor.h"; sourceTree = "SOURCE_ROOT"; };
- D9B077E2ECDDA94961E134D7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_StringPairArray.h"; path = "../../../../modules/juce_core/text/juce_StringPairArray.h"; sourceTree = "SOURCE_ROOT"; };
- DA345D5B9DABD049F90DC96F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_GeneratedCode.h"; path = "../../Source/ComponentEditor/jucer_GeneratedCode.h"; sourceTree = "SOURCE_ROOT"; };
- DAF84A553D264705FA6EB6FF = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_TreeViewHandler.h"; path = "../../Source/ComponentEditor/components/jucer_TreeViewHandler.h"; sourceTree = "SOURCE_ROOT"; };
- DB876F7873F42DC685A58CA7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_JPEGLoader.cpp"; path = "../../../../modules/juce_graphics/image_formats/juce_JPEGLoader.cpp"; sourceTree = "SOURCE_ROOT"; };
- DD985A60FB76E976AF91852D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_SHA256.h"; path = "../../../../modules/juce_cryptography/hashing/juce_SHA256.h"; sourceTree = "SOURCE_ROOT"; };
- DF7BB5B6B394EDEEF5F5B4B8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_CallbackMessage.h"; path = "../../../../modules/juce_events/messages/juce_CallbackMessage.h"; sourceTree = "SOURCE_ROOT"; };
- E07C56267CBB46FC44EF2026 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Image.cpp"; path = "../../../../modules/juce_graphics/images/juce_Image.cpp"; sourceTree = "SOURCE_ROOT"; };
- E1C16C872E34BCB144B469F9 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_EdgeTable.h"; path = "../../../../modules/juce_graphics/geometry/juce_EdgeTable.h"; sourceTree = "SOURCE_ROOT"; };
- E27F0860F27023BAA9798B46 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Rectangle.h"; path = "../../../../modules/juce_graphics/geometry/juce_Rectangle.h"; sourceTree = "SOURCE_ROOT"; };
E3FF16862AA1B2F943DC616C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ImageCache.cpp"; path = "../../../../modules/juce_graphics/images/juce_ImageCache.cpp"; sourceTree = "SOURCE_ROOT"; };
+ E446FFE889CD490FDE3F0F2B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ThreadWithProgressWindow.cpp"; path = "../../../../modules/juce_gui_basics/windows/juce_ThreadWithProgressWindow.cpp"; sourceTree = "SOURCE_ROOT"; };
E4E74B2BC3F3CB5A4F4DC55E = { isa = PBXFileReference; lastKnownFileType = file; name = "juce_module_info"; path = "../../../../modules/juce_gui_basics/juce_module_info"; sourceTree = "SOURCE_ROOT"; };
+ E530742870F07704E9616358 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ToolbarItemComponent.h"; path = "../../../../modules/juce_gui_basics/widgets/juce_ToolbarItemComponent.h"; sourceTree = "SOURCE_ROOT"; };
E54D0994D31E20A0A05EBA2B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_SystemTrayIconComponent.h"; path = "../../../../modules/juce_gui_extra/misc/juce_SystemTrayIconComponent.h"; sourceTree = "SOURCE_ROOT"; };
E570E57CC1FCEF78B54A7084 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FileOutputStream.h"; path = "../../../../modules/juce_core/files/juce_FileOutputStream.h"; sourceTree = "SOURCE_ROOT"; };
- E60E28D1B7491047DEA236AE = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_ProjectContentComponent.h"; path = "../../Source/Project/jucer_ProjectContentComponent.h"; sourceTree = "SOURCE_ROOT"; };
E642193A9990C48CFB6479A9 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FileListComponent.h"; path = "../../../../modules/juce_gui_basics/filebrowser/juce_FileListComponent.h"; sourceTree = "SOURCE_ROOT"; };
E654E3A3CD45A888C5F773DF = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MenuBarModel.h"; path = "../../../../modules/juce_gui_basics/menus/juce_MenuBarModel.h"; sourceTree = "SOURCE_ROOT"; };
E6F5CEC32EDC917B054467EF = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ReadWriteLock.cpp"; path = "../../../../modules/juce_core/threads/juce_ReadWriteLock.cpp"; sourceTree = "SOURCE_ROOT"; };
@@ -814,6 +810,7 @@
E7B6A0CBA0D27A095E83F5B7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_win32_WebBrowserComponent.cpp"; path = "../../../../modules/juce_gui_extra/native/juce_win32_WebBrowserComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
E7D09B860F4D4A13D4312C38 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_PropertiesFile.cpp"; path = "../../../../modules/juce_data_structures/app_properties/juce_PropertiesFile.cpp"; sourceTree = "SOURCE_ROOT"; };
E7E122AE104E79BB641B07B3 = { isa = PBXFileReference; lastKnownFileType = file; name = "juce_module_info"; path = "../../../../modules/juce_data_structures/juce_module_info"; sourceTree = "SOURCE_ROOT"; };
+ E7E1C4F416CFA44BE7DD1A74 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_KeyboardFocusTraverser.h"; path = "../../../../modules/juce_gui_basics/keyboard/juce_KeyboardFocusTraverser.h"; sourceTree = "SOURCE_ROOT"; };
E7E1D60BC7AEF79AA7B65B7C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_String.cpp"; path = "../../../../modules/juce_core/text/juce_String.cpp"; sourceTree = "SOURCE_ROOT"; };
E82C9EF1A74D867BBFF2090D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_RSAKey.cpp"; path = "../../../../modules/juce_cryptography/encryption/juce_RSAKey.cpp"; sourceTree = "SOURCE_ROOT"; };
E99F5A31373E9BDEAC40792F = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_FileChooser.cpp"; path = "../../../../modules/juce_gui_basics/native/juce_android_FileChooser.cpp"; sourceTree = "SOURCE_ROOT"; };
@@ -893,8 +890,6 @@
E65A820D34BF39478B7C5925,
D526C38D581425949BA0E4AC,
F03E2BDD36E6F4F53AB767A8,
- BE94248CF8069E6707174CDB,
- A5E171104E49595BD9485DFD,
8C52A3DDA62A746AA7A68535,
9069981E414A631B036CC9AC,
2CD34A70B4032C0426F7AA10,
@@ -1954,7 +1949,6 @@
357A6AA6960EF95D92929BEE,
954A036F5DDB375DB23FFB3E,
3EB3D569250C4BA4CA9AF578,
- B1A786B525176BEE309998EA,
95B44E6C74B1DED31DBE37EB,
AA9D0B8E23F3D87A23DE9F8A,
244BA1BDA5FAA465EA3F9C6D,
diff --git a/extras/Introjucer/Builds/VisualStudio2005/The Introjucer.vcproj b/extras/Introjucer/Builds/VisualStudio2005/The Introjucer.vcproj
index 1e6f8cc511..cbbfac1f1f 100644
--- a/extras/Introjucer/Builds/VisualStudio2005/The Introjucer.vcproj
+++ b/extras/Introjucer/Builds/VisualStudio2005/The Introjucer.vcproj
@@ -139,8 +139,6 @@
-
-
diff --git a/extras/Introjucer/Builds/VisualStudio2008/The Introjucer.vcproj b/extras/Introjucer/Builds/VisualStudio2008/The Introjucer.vcproj
index df844bda5d..46d115aac2 100644
--- a/extras/Introjucer/Builds/VisualStudio2008/The Introjucer.vcproj
+++ b/extras/Introjucer/Builds/VisualStudio2008/The Introjucer.vcproj
@@ -139,8 +139,6 @@
-
-
diff --git a/extras/Introjucer/Builds/VisualStudio2010/The Introjucer.vcxproj b/extras/Introjucer/Builds/VisualStudio2010/The Introjucer.vcxproj
index 60cc76ec38..3100db2bc8 100644
--- a/extras/Introjucer/Builds/VisualStudio2010/The Introjucer.vcxproj
+++ b/extras/Introjucer/Builds/VisualStudio2010/The Introjucer.vcxproj
@@ -130,7 +130,6 @@
-
@@ -1015,7 +1014,6 @@
-
diff --git a/extras/Introjucer/Builds/VisualStudio2010/The Introjucer.vcxproj.filters b/extras/Introjucer/Builds/VisualStudio2010/The Introjucer.vcxproj.filters
index b111e8769d..fc5c2e3fd2 100644
--- a/extras/Introjucer/Builds/VisualStudio2010/The Introjucer.vcxproj.filters
+++ b/extras/Introjucer/Builds/VisualStudio2010/The Introjucer.vcxproj.filters
@@ -256,9 +256,6 @@
The Introjucer\Application
-
- The Introjucer\Application
-
The Introjucer\Application
@@ -1311,9 +1308,6 @@
The Introjucer\Application
-
- The Introjucer\Application
-
The Introjucer\Application
diff --git a/extras/Introjucer/Builds/VisualStudio2012/The Introjucer.vcxproj b/extras/Introjucer/Builds/VisualStudio2012/The Introjucer.vcxproj
index 320a643956..435a58f22a 100644
--- a/extras/Introjucer/Builds/VisualStudio2012/The Introjucer.vcxproj
+++ b/extras/Introjucer/Builds/VisualStudio2012/The Introjucer.vcxproj
@@ -136,7 +136,6 @@
-
@@ -1021,7 +1020,6 @@
-
diff --git a/extras/Introjucer/Builds/VisualStudio2012/The Introjucer.vcxproj.filters b/extras/Introjucer/Builds/VisualStudio2012/The Introjucer.vcxproj.filters
index b111e8769d..fc5c2e3fd2 100644
--- a/extras/Introjucer/Builds/VisualStudio2012/The Introjucer.vcxproj.filters
+++ b/extras/Introjucer/Builds/VisualStudio2012/The Introjucer.vcxproj.filters
@@ -256,9 +256,6 @@
The Introjucer\Application
-
- The Introjucer\Application
-
The Introjucer\Application
@@ -1311,9 +1308,6 @@
The Introjucer\Application
-
- The Introjucer\Application
-
The Introjucer\Application
diff --git a/extras/Introjucer/Introjucer.jucer b/extras/Introjucer/Introjucer.jucer
index 54489bf2af..945d85f5dc 100644
--- a/extras/Introjucer/Introjucer.jucer
+++ b/extras/Introjucer/Introjucer.jucer
@@ -14,67 +14,126 @@
companyName="Raw Material Software Ltd." includeBinaryInAppConfig="1">
+ documentExtensions=".jucer" objCExtraSuffix="zNNCr" bigIcon="rVgowdy"
+ extraCompilerFlags="-Wall -Wshadow -Wno-missing-field-initializers -Wshadow -Wshorten-64-to-32 -Wstrict-aliasing">
+
+
+
+
+
+
+
+
+
+ rtasFolder="c:\SDKs\PT_80_SDK" libraryType="1" bigIcon="rVgowdy">
+
+
+
+
+
+
+
+
+
+ rtasFolder="c:\SDKs\PT_80_SDK" libraryType="1" bigIcon="rVgowdy">
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+ rtasFolder="c:\SDKs\PT_80_SDK" libraryType="1" bigIcon="rVgowdy">
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
@@ -101,10 +160,6 @@
resource="0" file="Source/Application/jucer_FilePreviewComponent.h"/>
-
-
@@ -129,7 +184,7 @@
-
@@ -456,12 +511,10 @@
JUCE_LOG_ASSERTIONS="enabled"/>
+
+
-
-
-
-
diff --git a/extras/Introjucer/Source/Application/jucer_Application.h b/extras/Introjucer/Source/Application/jucer_Application.h
index b6c5c3e649..3d65ab3dc9 100644
--- a/extras/Introjucer/Source/Application/jucer_Application.h
+++ b/extras/Introjucer/Source/Application/jucer_Application.h
@@ -27,7 +27,6 @@
#include "../jucer_Headers.h"
#include "jucer_MainWindow.h"
-#include "jucer_JuceUpdater.h"
#include "jucer_CommandLine.h"
#include "../Code Editor/jucer_SourceCodeEditor.h"
@@ -92,19 +91,6 @@ public:
#if JUCE_MAC
MenuBarModel::setMacMainMenu (menuModel, nullptr, "Open Recent");
#endif
-
- struct ModuleFolderChecker : public CallbackMessage
- {
- ModuleFolderChecker() {}
-
- void messageCallback() override
- {
- if (IntrojucerApp* const app = dynamic_cast (JUCEApplication::getInstance()))
- app->makeSureUserHasSelectedModuleFolder();
- }
- };
-
- (new ModuleFolderChecker())->post();
}
void shutdown() override
@@ -324,7 +310,6 @@ public:
virtual void createToolsMenu (PopupMenu& menu)
{
- menu.addCommandItem (commandManager, CommandIDs::updateModules);
menu.addCommandItem (commandManager, CommandIDs::showUTF8Tool);
menu.addCommandItem (commandManager, CommandIDs::showTranslationTool);
}
@@ -362,7 +347,6 @@ public:
CommandIDs::open,
CommandIDs::closeAllDocuments,
CommandIDs::saveAll,
- CommandIDs::updateModules,
CommandIDs::showAppearanceSettings,
CommandIDs::showUTF8Tool };
@@ -397,10 +381,6 @@ public:
result.setActive (openDocumentManager.anyFilesNeedSaving());
break;
- case CommandIDs::updateModules:
- result.setInfo ("Download the latest JUCE modules", "Checks online for any JUCE modules updates and installs them", CommandCategories::general, 0);
- break;
-
case CommandIDs::showUTF8Tool:
result.setInfo ("UTF-8 String-Literal Helper", "Shows the UTF-8 string literal utility", CommandCategories::general, 0);
break;
@@ -421,7 +401,6 @@ public:
case CommandIDs::closeAllDocuments: closeAllDocuments (true); break;
case CommandIDs::showUTF8Tool: showUTF8ToolWindow (utf8Window); break;
case CommandIDs::showAppearanceSettings: AppearanceSettings::showEditorWindow (appearanceEditorWindow); break;
- case CommandIDs::updateModules: runModuleUpdate (String::empty); break;
default: return JUCEApplication::perform (info);
}
@@ -431,12 +410,9 @@ public:
//==============================================================================
void createNewProject()
{
- if (makeSureUserHasSelectedModuleFolder())
- {
- MainWindow* mw = mainWindowList.getOrCreateEmptyWindow();
- mw->showNewProjectWizard();
- mainWindowList.avoidSuperimposedWindows (mw);
- }
+ MainWindow* mw = mainWindowList.getOrCreateEmptyWindow();
+ mw->showNewProjectWizard();
+ mainWindowList.avoidSuperimposedWindows (mw);
}
virtual void updateNewlyOpenedProject (Project&) {}
@@ -464,44 +440,6 @@ public:
return mainWindowList.askAllWindowsToClose();
}
- bool makeSureUserHasSelectedModuleFolder()
- {
- if (! AvailableModuleList::isLocalModulesFolderValid())
- {
- if (! runModuleUpdate ("Please select a location to store your local set of JUCE modules,\n"
- "and download the ones that you'd like to use!"))
- {
- AlertWindow::showMessageBox (AlertWindow::WarningIcon,
- "Introjucer",
- "Unless you create a local JUCE folder containing some modules, you'll be unable to save any projects correctly!\n\n"
- "Use the option on the 'Tools' menu to set this up!");
-
- return false;
- }
- }
-
- if (AvailableModuleList().isLibraryNewerThanIntrojucer())
- {
- AlertWindow::showMessageBox (AlertWindow::WarningIcon,
- "Introjucer",
- "This version of the introjucer is out-of-date!"
- "\n\n"
- "Always make sure that you're running the very latest version, preferably compiled directly from the juce tree that you're working with!");
- }
-
- return true;
- }
-
- bool runModuleUpdate (const String& message)
- {
- AvailableModuleList list;
- list.rescan (AvailableModuleList::getDefaultModulesFolder (mainWindowList.getFrontmostProject()));
- JuceUpdater::show (list, mainWindowList.windows[0], message);
-
- AvailableModuleList::setLocalModulesFolder (list.getModulesFolder());
- return AvailableModuleList::isJuceOrModulesFolder (list.getModulesFolder());
- }
-
//==============================================================================
void initialiseLogger (const char* filePrefix)
{
diff --git a/extras/Introjucer/Source/Application/jucer_CommandIDs.h b/extras/Introjucer/Source/Application/jucer_CommandIDs.h
index ec0ebc9b99..8faa4df613 100644
--- a/extras/Introjucer/Source/Application/jucer_CommandIDs.h
+++ b/extras/Introjucer/Source/Application/jucer_CommandIDs.h
@@ -41,7 +41,6 @@ namespace CommandIDs
openInIDE = 0x200072,
saveAndOpenInIDE = 0x200073,
- updateModules = 0x200075,
showUTF8Tool = 0x200076,
showAppearanceSettings = 0x200077,
showConfigPanel = 0x200074,
diff --git a/extras/Introjucer/Source/Application/jucer_CommandLine.cpp b/extras/Introjucer/Source/Application/jucer_CommandLine.cpp
index 598deeb16b..31ba11b8fc 100644
--- a/extras/Introjucer/Source/Application/jucer_CommandLine.cpp
+++ b/extras/Introjucer/Source/Application/jucer_CommandLine.cpp
@@ -113,7 +113,7 @@ namespace
jassert (targetFolder.isDirectory());
const File moduleFolderParent (moduleFolder.getParentDirectory());
- LibraryModule module (moduleFolder.getChildFile (LibraryModule::getInfoFileName()));
+ LibraryModule module (moduleFolder.getChildFile (ModuleDescription::getManifestFileName()));
if (! module.isValid())
{
@@ -174,7 +174,7 @@ namespace
while (i.next())
{
- LibraryModule module (i.getFile().getChildFile (LibraryModule::getInfoFileName()));
+ LibraryModule module (i.getFile().getChildFile (ModuleDescription::getManifestFileName()));
if (module.isValid())
{
@@ -185,7 +185,7 @@ namespace
var moduleInfo (new DynamicObject());
moduleInfo.getDynamicObject()->setProperty ("file", getModulePackageName (module));
- moduleInfo.getDynamicObject()->setProperty ("info", module.moduleInfo);
+ moduleInfo.getDynamicObject()->setProperty ("info", module.moduleInfo.moduleInfo);
infoList.append (moduleInfo);
}
}
@@ -230,7 +230,7 @@ namespace
<< "Name: " << proj.getTitle() << std::endl
<< "UID: " << proj.getProjectUID() << std::endl;
- EnabledModuleList modules (proj.getModules());
+ EnabledModuleList& modules = proj.getModules();
const int numModules = modules.getNumModules();
if (numModules > 0)
diff --git a/extras/Introjucer/Source/Application/jucer_JuceUpdater.cpp b/extras/Introjucer/Source/Application/jucer_JuceUpdater.cpp
deleted file mode 100644
index b01ee22c6f..0000000000
--- a/extras/Introjucer/Source/Application/jucer_JuceUpdater.cpp
+++ /dev/null
@@ -1,439 +0,0 @@
-/*
- ==============================================================================
-
- This file is part of the JUCE library.
- Copyright (c) 2013 - Raw Material Software Ltd.
-
- Permission is granted to use this software under the terms of either:
- a) the GPL v2 (or any later version)
- b) the Affero GPL v3
-
- Details of these licenses can be found at: www.gnu.org/licenses
-
- JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- ------------------------------------------------------------------------------
-
- To release a closed-source product which uses JUCE, commercial licenses are
- available: visit www.juce.com for more information.
-
- ==============================================================================
-*/
-
-#include "../jucer_Headers.h"
-#include "jucer_JuceUpdater.h"
-#include "../Project/jucer_Module.h"
-
-
-//==============================================================================
-JuceUpdater::JuceUpdater (AvailableModuleList& l, const String& message)
- : moduleList (l),
- messageLabel (String::empty, message),
- filenameComp ("Juce Folder", AvailableModuleList::getLocalModulesFolder (nullptr),
- true, true, false, "*", String::empty, "Select your Juce folder"),
- 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")
-{
- messageLabel.setJustificationType (Justification::centred);
- addAndMakeVisible (&messageLabel);
-
- addAndMakeVisible (&label);
- addAndMakeVisible (¤tVersionLabel);
- addAndMakeVisible (&filenameComp);
- addAndMakeVisible (&checkNowButton);
- addAndMakeVisible (&installButton);
- addAndMakeVisible (&selectAllButton);
- checkNowButton.addListener (this);
- installButton.addListener (this);
- selectAllButton.addListener (this);
- filenameComp.addListener (this);
-
- currentVersionLabel.setFont (Font (14.0f, Font::italic));
- label.setFont (Font (12.0f));
- label.setText ("Local modules folder:", dontSendNotification);
-
- addAndMakeVisible (&availableVersionsList);
- availableVersionsList.setModel (this);
- availableVersionsList.setColour (ListBox::backgroundColourId, Colours::white.withAlpha (0.4f));
-
- updateInstallButtonStatus();
- versionsToDownload = ValueTree ("modules");
- versionsToDownload.addListener (this);
-
- setSize (600, 500);
-}
-
-JuceUpdater::~JuceUpdater()
-{
- checkNowButton.removeListener (this);
- filenameComp.removeListener (this);
-}
-
-void JuceUpdater::show (AvailableModuleList& moduleList, Component* mainWindow, const String& message)
-{
- DialogWindow::LaunchOptions o;
- o.content.setOwned (new JuceUpdater (moduleList, message));
- o.dialogTitle = "JUCE Module Updater";
- o.dialogBackgroundColour = Colours::lightgrey;
- o.componentToCentreAround = mainWindow;
- o.escapeKeyTriggersCloseButton = true;
- o.useNativeTitleBar = true;
- o.resizable = true;
-
- o.runModal();
-}
-
-void JuceUpdater::resized()
-{
- messageLabel.setBounds (20, 10, getWidth() - 40, messageLabel.getText().isEmpty() ? 0 : 30);
-
- filenameComp.setBounds (20, messageLabel.getBottom() + 20, getWidth() - 40, 22);
- label.setBounds (filenameComp.getX(), filenameComp.getY() - 18, filenameComp.getWidth(), 18);
- currentVersionLabel.setBounds (filenameComp.getX(), filenameComp.getBottom(), filenameComp.getWidth(), 25);
- 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)
-{
- g.setGradientFill (ColourGradient (Colour::greyLevel (0.85f), 0, 0,
- Colour::greyLevel (0.65f), 0, (float) getHeight(), false));
- g.fillAll();
-}
-
-void JuceUpdater::buttonClicked (Button* b)
-{
- if (b == &installButton)
- install();
- else if (b == &selectAllButton)
- selectAll();
- else
- checkNow();
-}
-
-void JuceUpdater::refresh()
-{
- availableVersionsList.updateContent();
- availableVersionsList.repaint();
-}
-
-class WebsiteContacterThread : public Thread,
- private AsyncUpdater
-{
-public:
- WebsiteContacterThread (JuceUpdater& owner_, const AvailableModuleList& latestList)
- : Thread ("Module updater"),
- owner (owner_),
- downloaded (latestList)
- {
- startThread();
- }
-
- ~WebsiteContacterThread()
- {
- stopThread (10000);
- }
-
- void run() override
- {
- if (downloaded.loadFromWebsite())
- triggerAsyncUpdate();
- else
- AlertWindow::showMessageBox (AlertWindow::InfoIcon,
- "Module Update",
- "Couldn't connect to the JUCE webserver!");
- }
-
- void handleAsyncUpdate() override
- {
- owner.backgroundUpdateComplete (downloaded);
- }
-
-private:
- JuceUpdater& owner;
- AvailableModuleList downloaded;
-};
-
-void JuceUpdater::checkNow()
-{
- websiteContacterThread = nullptr;
- websiteContacterThread = new WebsiteContacterThread (*this, latestList);
-}
-
-void JuceUpdater::backgroundUpdateComplete (const AvailableModuleList& newList)
-{
- latestList = newList;
- websiteContacterThread = nullptr;
-
- if (latestList == moduleList)
- AlertWindow::showMessageBox (AlertWindow::InfoIcon,
- "Module Update",
- "No new modules are available");
- refresh();
-}
-
-int JuceUpdater::getNumCheckedModules() const
-{
- int numChecked = 0;
-
- for (int i = latestList.modules.size(); --i >= 0;)
- if (versionsToDownload [latestList.modules.getUnchecked(i)->uid])
- ++numChecked;
-
- return numChecked;
-}
-
-bool JuceUpdater::isLatestVersion (const String& moduleID) const
-{
- const AvailableModuleList::Module* m1 = moduleList.findModuleInfo (moduleID);
- const AvailableModuleList::Module* m2 = latestList.findModuleInfo (moduleID);
-
- return m1 != nullptr && m2 != nullptr && m1->version == m2->version;
-}
-
-void JuceUpdater::updateInstallButtonStatus()
-{
- const int numChecked = getNumCheckedModules();
- installButton.setEnabled (numChecked > 0);
- selectAllButton.setToggleState (numChecked > latestList.modules.size() / 2, dontSendNotification);
-}
-
-void JuceUpdater::filenameComponentChanged (FilenameComponent*)
-{
- moduleList.rescan (filenameComp.getCurrentFile());
- filenameComp.setCurrentFile (moduleList.getModulesFolder(), true, dontSendNotification);
-
- if (! AvailableModuleList::isModulesFolder (moduleList.getModulesFolder()))
- currentVersionLabel.setText ("(Not a Juce folder)", dontSendNotification);
- else
- currentVersionLabel.setText (String::empty, dontSendNotification);
-
- refresh();
-}
-
-void JuceUpdater::selectAll()
-{
- 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);
- }
-}
-
-//==============================================================================
-int JuceUpdater::getNumRows()
-{
- return latestList.modules.size();
-}
-
-void JuceUpdater::paintListBoxItem (int /*rowNumber*/, Graphics& g, int /*width*/, int /*height*/, bool rowIsSelected)
-{
- if (rowIsSelected)
- g.fillAll (findColour (TextEditor::highlightColourId));
-}
-
-class UpdateListComponent : public Component
-{
-public:
- UpdateListComponent()
- {
- addChildComponent (&toggle);
- toggle.setWantsKeyboardFocus (false);
- setInterceptsMouseClicks (false, true);
- }
-
- void setModule (const AvailableModuleList::Module* newModule,
- const AvailableModuleList::Module* existingModule,
- const Value& value)
- {
- 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: " << existingModule->version << ")";
- toggle.setEnabled (false);
- }
- }
- else
- {
- name = status = String::empty;
- toggle.setVisible (false);
- }
- }
-
- void paint (Graphics& g)
- {
- g.setColour (Colours::black);
- g.setFont (getHeight() * 0.7f);
-
- g.drawText (name, toggle.getRight() + 4, 0, getWidth() / 2 - toggle.getRight() - 4, getHeight(),
- Justification::centredLeft, true);
-
- g.drawText (status, getWidth() / 2, 0, getWidth() / 2, getHeight(),
- Justification::centredLeft, true);
- }
-
- void resized()
- {
- toggle.setBounds (2, 2, getHeight() - 4, getHeight() - 4);
- }
-
-private:
- ToggleButton toggle;
- String name, status;
-};
-
-Component* JuceUpdater::refreshComponentForRow (int rowNumber, bool /*isRowSelected*/, Component* existingComponentToUpdate)
-{
- UpdateListComponent* c = dynamic_cast (existingComponentToUpdate);
- if (c == nullptr)
- c = new UpdateListComponent();
-
- if (AvailableModuleList::Module* m = latestList.modules [rowNumber])
- c->setModule (m,
- moduleList.findModuleInfo (m->uid),
- versionsToDownload.getPropertyAsValue (m->uid, nullptr));
- else
- c->setModule (nullptr, nullptr, Value());
-
- return c;
-}
-
-//==============================================================================
-class InstallThread : public ThreadWithProgressWindow
-{
-public:
- InstallThread (const AvailableModuleList& target,
- const AvailableModuleList& l, const StringArray& itemsToInstall_)
- : ThreadWithProgressWindow ("Installing New Modules", true, true),
- result (Result::ok()),
- targetList (target),
- list (l),
- itemsToInstall (itemsToInstall_)
- {
- }
-
- void run() override
- {
- for (int i = 0; i < itemsToInstall.size(); ++i)
- {
- const AvailableModuleList::Module* m = list.findModuleInfo (itemsToInstall[i]);
-
- jassert (m != nullptr);
- if (m != nullptr)
- {
- setProgress (i / (double) itemsToInstall.size());
-
- MemoryBlock downloaded;
- result = download (*m, downloaded);
-
- if (result.failed())
- break;
-
- if (threadShouldExit())
- break;
-
- result = unzip (*m, downloaded);
-
- if (result.failed())
- break;
- }
-
- if (threadShouldExit())
- break;
- }
- }
-
- Result download (const AvailableModuleList::Module& m, MemoryBlock& dest)
- {
- setStatusMessage ("Downloading " + m.uid + "...");
-
- if (m.url.readEntireBinaryStream (dest, false))
- return Result::ok();
-
- return Result::fail ("Failed to download from: " + m.url.toString (false));
- }
-
- Result unzip (const AvailableModuleList::Module& m, const MemoryBlock& data)
- {
- setStatusMessage ("Installing " + m.uid + "...");
-
- MemoryInputStream input (data, false);
- ZipFile zip (input);
-
- if (zip.getNumEntries() == 0)
- return Result::fail ("The downloaded file wasn't a valid module file!");
-
- return zip.uncompressTo (targetList.getModulesFolder(), true);
- }
-
- Result result;
-
-private:
- AvailableModuleList targetList, list;
- StringArray itemsToInstall;
-};
-
-void JuceUpdater::install()
-{
- if (! moduleList.getModulesFolder().createDirectory())
- {
- AlertWindow::showMessageBox (AlertWindow::WarningIcon,
- "Module Update",
- "Couldn't create the target folder!");
- return;
- }
-
- StringArray itemsWanted;
-
- for (int i = latestList.modules.size(); --i >= 0;)
- if (versionsToDownload [latestList.modules.getUnchecked(i)->uid])
- itemsWanted.add (latestList.modules.getUnchecked(i)->uid);
-
- {
- InstallThread thread (moduleList, latestList, itemsWanted);
- thread.runThread();
- }
-
- 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&) {}
diff --git a/extras/Introjucer/Source/Application/jucer_JuceUpdater.h b/extras/Introjucer/Source/Application/jucer_JuceUpdater.h
deleted file mode 100644
index 391dccba80..0000000000
--- a/extras/Introjucer/Source/Application/jucer_JuceUpdater.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- ==============================================================================
-
- This file is part of the JUCE library.
- Copyright (c) 2013 - Raw Material Software Ltd.
-
- Permission is granted to use this software under the terms of either:
- a) the GPL v2 (or any later version)
- b) the Affero GPL v3
-
- Details of these licenses can be found at: www.gnu.org/licenses
-
- JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- ------------------------------------------------------------------------------
-
- To release a closed-source product which uses JUCE, commercial licenses are
- available: visit www.juce.com for more information.
-
- ==============================================================================
-*/
-
-#ifndef __JUCER_JUCEUPDATER_JUCEHEADER__
-#define __JUCER_JUCEUPDATER_JUCEHEADER__
-
-#include "../Project/jucer_Module.h"
-
-
-//==============================================================================
-class JuceUpdater : public Component,
- private ButtonListener,
- private FilenameComponentListener,
- private ListBoxModel,
- private ValueTree::Listener
-{
-public:
- JuceUpdater (AvailableModuleList&, const String& message);
- ~JuceUpdater();
-
- static void show (AvailableModuleList&, Component* mainWindow, const String& message);
-
- //==============================================================================
- void resized();
- void paint (Graphics& g);
- void buttonClicked (Button*);
- void filenameComponentChanged (FilenameComponent* fileComponentThatHasChanged);
-
- int getNumRows();
- void paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected);
- Component* refreshComponentForRow (int rowNumber, bool isRowSelected, Component* existingComponentToUpdate);
-
- void backgroundUpdateComplete (const AvailableModuleList& newList);
-
-private:
- AvailableModuleList& moduleList;
- AvailableModuleList latestList;
-
- Label messageLabel, label, currentVersionLabel;
- FilenameComponent filenameComp;
- TextButton checkNowButton;
- ListBox availableVersionsList;
- ValueTree versionsToDownload;
- TextButton installButton;
- ToggleButton selectAllButton;
- ScopedPointer 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&) override;
- void valueTreeChildAdded (ValueTree&, ValueTree&) override;
- void valueTreeChildRemoved (ValueTree&, ValueTree&) override;
- void valueTreeChildOrderChanged (ValueTree&) override;
- void valueTreeParentChanged (ValueTree&) override;
-
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceUpdater)
-};
-
-#endif // __JUCER_JUCEUPDATER_JUCEHEADER__
diff --git a/extras/Introjucer/Source/Application/jucer_MainWindow.cpp b/extras/Introjucer/Source/Application/jucer_MainWindow.cpp
index dbaa9b9b7d..8c7ecde7b7 100644
--- a/extras/Introjucer/Source/Application/jucer_MainWindow.cpp
+++ b/extras/Introjucer/Source/Application/jucer_MainWindow.cpp
@@ -189,7 +189,7 @@ bool MainWindow::openFile (const File& file)
if (file.hasFileExtension (Project::projectFileExtension))
{
- ScopedPointer newDoc (new Project (file));
+ ScopedPointer newDoc (new Project (file));
if (newDoc->loadFrom (file, true)
&& closeCurrentProject())
diff --git a/extras/Introjucer/Source/Project Saving/jucer_ProjectExporter.cpp b/extras/Introjucer/Source/Project Saving/jucer_ProjectExporter.cpp
index 7a0629fd3f..77f9abf658 100644
--- a/extras/Introjucer/Source/Project Saving/jucer_ProjectExporter.cpp
+++ b/extras/Introjucer/Source/Project Saving/jucer_ProjectExporter.cpp
@@ -81,15 +81,8 @@ ProjectExporter* ProjectExporter::createNewExporter (Project& project, const int
default: jassertfalse; return 0;
}
- File juceFolder (AvailableModuleList::getLocalModulesFolder (&project));
- File target (exp->getTargetFolder());
-
- if (FileHelpers::shouldPathsBeRelative (juceFolder.getFullPathName(), project.getFile().getFullPathName()))
- exp->getJuceFolderValue() = FileHelpers::getRelativePathFrom (juceFolder, project.getFile().getParentDirectory());
- else
- exp->getJuceFolderValue() = juceFolder.getFullPathName();
-
exp->createDefaultConfigs();
+ exp->createDefaultModulePaths();
return exp;
}
@@ -158,7 +151,7 @@ ProjectExporter::ProjectExporter (Project& p, const ValueTree& settings_)
project (p),
projectType (p.getProjectType()),
projectName (p.getTitle()),
- projectFolder (p.getFile().getParentDirectory()),
+ projectFolder (p.getProjectFolder()),
modulesGroup (nullptr)
{
}
@@ -172,19 +165,9 @@ File ProjectExporter::getTargetFolder() const
return project.resolveFilename (getTargetLocationString());
}
-RelativePath ProjectExporter::getJucePathFromProjectFolder() const
-{
- return RelativePath (getJuceFolderString(), RelativePath::projectFolder);
-}
-
-RelativePath ProjectExporter::getJucePathFromTargetFolder() const
-{
- return rebaseFromProjectFolderToBuildTarget (getJucePathFromProjectFolder());
-}
-
RelativePath ProjectExporter::rebaseFromProjectFolderToBuildTarget (const RelativePath& path) const
{
- return path.rebased (project.getFile().getParentDirectory(), getTargetFolder(), RelativePath::buildTargetFolder);
+ return path.rebased (project.getProjectFolder(), getTargetFolder(), RelativePath::buildTargetFolder);
}
bool ProjectExporter::shouldFileBeCompiledByDefault (const RelativePath& file) const
@@ -198,15 +181,9 @@ void ProjectExporter::createPropertyEditors (PropertyListBuilder& props)
"The location of the folder in which the " + name + " project will be created. "
"This path can be absolute, but it's much more sensible to make it relative to the jucer project directory.");
- props.add (new TextPropertyComponent (getJuceFolderValue(), "Local JUCE folder", 1024, false),
- "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 modules;
- AvailableModuleList moduleList;
- moduleList.rescan (AvailableModuleList::getDefaultModulesFolder (&project));
- project.getModules().createRequiredModules (moduleList, modules);
+ project.getModules().createRequiredModules (modules);
+
for (int i = 0; i < modules.size(); ++i)
modules.getUnchecked(i)->createPropertyEditors (*this, props);
@@ -304,14 +281,121 @@ void ProjectExporter::addToExtraSearchPaths (const RelativePath& pathFromProject
extraSearchPaths.addIfNotAlreadyThere (path, false);
}
+Value ProjectExporter::getPathForModuleValue (const String& moduleID)
+{
+ UndoManager* um = project.getUndoManagerFor (settings);
+
+ ValueTree paths (settings.getOrCreateChildWithName (Ids::MODULEPATHS, um));
+ ValueTree m (paths.getChildWithProperty (Ids::ID, moduleID));
+
+ if (! m.isValid())
+ {
+ m = ValueTree (Ids::MODULEPATH);
+ m.setProperty (Ids::ID, moduleID, um);
+ paths.addChild (m, -1, um);
+ }
+
+ return m.getPropertyAsValue (Ids::path, um);
+}
+
+String ProjectExporter::getPathForModuleString (const String& moduleID) const
+{
+ return settings.getChildWithName (Ids::MODULEPATHS)
+ .getChildWithProperty (Ids::ID, moduleID) [Ids::path].toString();
+}
+
+void ProjectExporter::removePathForModule (const String& moduleID)
+{
+ ValueTree paths (settings.getChildWithName (Ids::MODULEPATHS));
+ ValueTree m (paths.getChildWithProperty (Ids::ID, moduleID));
+ paths.removeChild (m, project.getUndoManagerFor (settings));
+}
+
+RelativePath ProjectExporter::getModuleFolderRelativeToProject (const String& moduleID, ProjectSaver& projectSaver) const
+{
+ if (project.getModules().shouldCopyModuleFilesLocally (moduleID).getValue())
+ return RelativePath (project.getRelativePathForFile (projectSaver.getLocalModuleFolder (moduleID)),
+ RelativePath::projectFolder);
+
+ String path (getPathForModuleString (moduleID));
+
+ if (path.isEmpty())
+ return getLegacyModulePath (moduleID).getChildFile (moduleID);
+
+ return RelativePath (path, RelativePath::projectFolder).getChildFile (moduleID);
+}
+
+String ProjectExporter::getLegacyModulePath() const
+{
+ return getSettingString ("juceFolder");
+}
+
+RelativePath ProjectExporter::getLegacyModulePath (const String& moduleID) const
+{
+ if (project.getModules().state.getChildWithProperty (Ids::ID, moduleID) ["useLocalCopy"])
+ return RelativePath (project.getRelativePathForFile (project.getGeneratedCodeFolder()
+ .getChildFile ("modules")
+ .getChildFile (moduleID)), RelativePath::projectFolder);
+
+ String oldJucePath (getLegacyModulePath());
+
+ if (oldJucePath.isEmpty())
+ return RelativePath();
+
+ RelativePath p (oldJucePath, RelativePath::projectFolder);
+ if (p.getFileName() != "modules")
+ p = p.getChildFile ("modules");
+
+ return p.getChildFile (moduleID);
+}
+
+void ProjectExporter::updateOldModulePaths()
+{
+ String oldPath (getLegacyModulePath());
+
+ if (oldPath.isNotEmpty())
+ {
+ for (int i = project.getModules().getNumModules(); --i >= 0;)
+ {
+ String modID (project.getModules().getModuleID(i));
+ getPathForModuleValue (modID) = getLegacyModulePath (modID).getParentDirectory().toUnixStyle();
+ }
+
+ settings.removeProperty ("juceFolder", nullptr);
+ }
+}
+
+static bool areCompatibleExporters (const ProjectExporter& p1, const ProjectExporter& p2)
+{
+ return (p1.isVisualStudio() && p2.isVisualStudio())
+ || (p1.isXcode() && p2.isXcode())
+ || (p1.isLinux() && p2.isLinux())
+ || (p1.isAndroid() && p2.isAndroid())
+ || (p1.isCodeBlocks() && p2.isCodeBlocks());
+}
+
+void ProjectExporter::createDefaultModulePaths()
+{
+ for (Project::ExporterIterator exporter (project); exporter.next();)
+ {
+ if (areCompatibleExporters (*this, *exporter))
+ {
+ for (int i = project.getModules().getNumModules(); --i >= 0;)
+ {
+ String modID (project.getModules().getModuleID(i));
+
+ getPathForModuleValue (modID) = exporter->getPathForModuleValue (modID).getValue();
+ }
+
+ break;
+ }
+ }
+}
//==============================================================================
-const Identifier ProjectExporter::configurations ("CONFIGURATIONS");
-const Identifier ProjectExporter::configuration ("CONFIGURATION");
-
ValueTree ProjectExporter::getConfigurations() const
{
- return settings.getChildWithName (configurations);
+ return settings.getChildWithName (Ids::CONFIGURATIONS);
}
int ProjectExporter::getNumConfigurations() const
@@ -358,11 +442,11 @@ void ProjectExporter::addNewConfiguration (const BuildConfiguration* configToCop
if (! configs.isValid())
{
- settings.addChild (ValueTree (configurations), 0, project.getUndoManagerFor (settings));
+ settings.addChild (ValueTree (Ids::CONFIGURATIONS), 0, project.getUndoManagerFor (settings));
configs = getConfigurations();
}
- ValueTree newConfig (configuration);
+ ValueTree newConfig (Ids::CONFIGURATION);
if (configToCopy != nullptr)
newConfig = configToCopy->config.createCopy();
@@ -379,7 +463,7 @@ void ProjectExporter::BuildConfiguration::removeFromExporter()
void ProjectExporter::createDefaultConfigs()
{
- settings.getOrCreateChildWithName (configurations, nullptr);
+ settings.getOrCreateChildWithName (Ids::CONFIGURATIONS, nullptr);
for (int i = 0; i < 2; ++i)
{
diff --git a/extras/Introjucer/Source/Project Saving/jucer_ProjectExporter.h b/extras/Introjucer/Source/Project Saving/jucer_ProjectExporter.h
index 38e9846fc6..99f0c7f9b5 100644
--- a/extras/Introjucer/Source/Project Saving/jucer_ProjectExporter.h
+++ b/extras/Introjucer/Source/Project Saving/jucer_ProjectExporter.h
@@ -28,7 +28,7 @@
#include "../jucer_Headers.h"
#include "../Project/jucer_Project.h"
#include "../Project/jucer_ProjectType.h"
-
+class ProjectSaver;
//==============================================================================
class ProjectExporter
@@ -74,9 +74,6 @@ public:
Value getSetting (const Identifier& nm) { return settings.getPropertyAsValue (nm, project.getUndoManagerFor (settings)); }
String getSettingString (const Identifier& nm) const { return settings [nm]; }
- Value getJuceFolderValue() { return getSetting (Ids::juceFolder); }
- String getJuceFolderString() const { return getSettingString (Ids::juceFolder); }
-
Value getTargetLocationValue() { return getSetting (Ids::targetFolder); }
String getTargetLocationString() const { return getSettingString (Ids::targetFolder); }
@@ -91,6 +88,17 @@ public:
Value getUserNotes() { return getSetting (Ids::userNotes); }
+ Value getPathForModuleValue (const String& moduleID);
+ String getPathForModuleString (const String& moduleID) const;
+ void removePathForModule (const String& moduleID);
+
+ RelativePath getLegacyModulePath (const String& moduleID) const;
+ String getLegacyModulePath() const;
+
+ // Returns a path to the actual module folder itself
+ RelativePath getModuleFolderRelativeToProject (const String& moduleID, ProjectSaver& projectSaver) const;
+ void updateOldModulePaths();
+
RelativePath rebaseFromProjectFolderToBuildTarget (const RelativePath& path) const;
void addToExtraSearchPaths (const RelativePath& pathFromProjectFolder);
@@ -120,9 +128,6 @@ public:
String message;
};
- RelativePath getJucePathFromTargetFolder() const;
- RelativePath getJucePathFromProjectFolder() const;
-
void createPropertyEditors (PropertyListBuilder& props);
//==============================================================================
@@ -262,8 +267,7 @@ public:
ValueTree getConfigurations() const;
void createDefaultConfigs();
-
- static const Identifier configurations, configuration;
+ void createDefaultModulePaths();
//==============================================================================
Value getExporterPreprocessorDefs() { return getSetting (Ids::extraDefs); }
diff --git a/extras/Introjucer/Source/Project Saving/jucer_ProjectSaver.h b/extras/Introjucer/Source/Project Saving/jucer_ProjectSaver.h
index ae74a32cac..9c6c816d66 100644
--- a/extras/Introjucer/Source/Project Saving/jucer_ProjectSaver.h
+++ b/extras/Introjucer/Source/Project Saving/jucer_ProjectSaver.h
@@ -44,8 +44,6 @@ public:
generatedFilesGroup.setID (getGeneratedGroupID());
}
- Project& getProject() noexcept { return project; }
-
struct SaveThread : public ThreadWithProgressWindow
{
public:
@@ -83,16 +81,7 @@ public:
writeMainProjectFile();
OwnedArray modules;
-
- {
- AvailableModuleList moduleList;
- Result scanResult (moduleList.rescan (AvailableModuleList::getDefaultModulesFolder (&project)));
-
- if (scanResult.failed())
- return scanResult;
-
- project.getModules().createRequiredModules (moduleList, modules);
- }
+ project.getModules().createRequiredModules (modules);
if (errors.size() == 0) writeAppConfigFile (modules, appConfigUserContent);
if (errors.size() == 0) writeBinaryDataFiles();
@@ -165,13 +154,14 @@ public:
<< newLine;
}
- static const char* getGeneratedGroupID() noexcept { return "__jucelibfiles"; }
- Project::Item& getGeneratedCodeGroup() { return generatedFilesGroup; }
+ static const char* getGeneratedGroupID() noexcept { return "__jucelibfiles"; }
+ Project::Item& getGeneratedCodeGroup() { return generatedFilesGroup; }
- static String getJuceCodeGroupName() { return "Juce Library Code"; }
+ static String getJuceCodeGroupName() { return "Juce Library Code"; }
- File getGeneratedCodeFolder() const { return generatedCodeFolder; }
- File getLocalModuleFolder (const LibraryModule& m) const { return generatedCodeFolder.getChildFile ("modules").getChildFile (m.getID()); }
+ File getGeneratedCodeFolder() const { return generatedCodeFolder; }
+ File getLocalModulesFolder() const { return generatedCodeFolder.getChildFile ("modules"); }
+ File getLocalModuleFolder (const String& moduleID) const { return getLocalModulesFolder().getChildFile (moduleID); }
bool replaceFileIfDifferent (const File& f, const MemoryOutputStream& newData)
{
@@ -214,8 +204,9 @@ public:
return false;
}
-private:
Project& project;
+
+private:
const File projectFile, generatedCodeFolder;
Project::Item generatedFilesGroup;
String extraAppConfigContent;
@@ -363,7 +354,7 @@ private:
for (int j = 0; j < modules.size(); ++j)
{
LibraryModule* const m = modules.getUnchecked(j);
- OwnedArray flags;
+ OwnedArray flags;
m->getConfigFlags (project, flags);
if (flags.size() > 0)
diff --git a/extras/Introjucer/Source/Project/jucer_AudioPluginModule.h b/extras/Introjucer/Source/Project/jucer_AudioPluginModule.h
index bf177ddab8..86b22470db 100644
--- a/extras/Introjucer/Source/Project/jucer_AudioPluginModule.h
+++ b/extras/Introjucer/Source/Project/jucer_AudioPluginModule.h
@@ -115,7 +115,7 @@ namespace
void writePluginCharacteristicsFile (ProjectSaver& projectSaver)
{
- Project& project = projectSaver.getProject();
+ Project& project = projectSaver.project;
StringPairArray flags;
//flags.set ("JUCE_MODAL_LOOPS_PERMITTED", "0");
@@ -364,7 +364,7 @@ namespace RTASHelpers
}
}
- static inline void prepareExporter (ProjectExporter& exporter, ProjectSaver& projectSaver, const File& /*moduleFolder*/)
+ static inline void prepareExporter (ProjectExporter& exporter, ProjectSaver& projectSaver)
{
if (isExporterSupported (exporter))
{
@@ -380,29 +380,28 @@ namespace RTASHelpers
createRebasedPath (exporter,
rtasFolder.getChildFile ("WinBag")));
- RelativePath juceFolder (exporter.getJucePathFromTargetFolder());
- if (juceFolder.getFileName() != "modules")
- juceFolder = juceFolder.getChildFile ("modules");
-
- String msvcPathToRTASFolder (juceFolder.getChildFile ("juce_audio_plugin_client/RTAS")
- .toWindowsStyle() + "\\");
-
exporter.msvcDelayLoadedDLLs = "DAE.dll; DigiExt.dll; DSI.dll; PluginLib.dll; "
"DSPManager.dll; DSPManager.dll; DSPManagerClientLib.dll; RTASClientLib.dll";
if (! exporter.getExtraLinkerFlagsString().contains ("/FORCE:multiple"))
exporter.getExtraLinkerFlags() = exporter.getExtraLinkerFlags().toString() + " /FORCE:multiple";
+ RelativePath modulePath (exporter.rebaseFromProjectFolderToBuildTarget (RelativePath (exporter.getPathForModuleString ("juce_audio_plugin_client"),
+ RelativePath::projectFolder)
+ .getChildFile ("RTAS")));
+
for (ProjectExporter::ConfigIterator config (exporter); config.next();)
{
- config->getValue (Ids::msvcModuleDefinitionFile) = msvcPathToRTASFolder + "juce_RTAS_WinExports.def";
+ config->getValue (Ids::msvcModuleDefinitionFile) = modulePath.getChildFile ("juce_RTAS_WinExports.def").toWindowsStyle();
if (config->getValue (Ids::useRuntimeLibDLL).getValue().isVoid())
config->getValue (Ids::useRuntimeLibDLL) = true;
if (config->getValue (Ids::postbuildCommand).toString().isEmpty())
- config->getValue (Ids::postbuildCommand) = "copy /Y \"" + msvcPathToRTASFolder + "juce_RTAS_WinResources.rsr"
- + "\" \"$(TargetPath)\".rsr";
+ config->getValue (Ids::postbuildCommand)
+ = "copy /Y "
+ + modulePath.getChildFile ("juce_RTAS_WinResources.rsr").toWindowsStyle().quoted()
+ + " \"$(TargetPath)\".rsr";
}
}
else
@@ -568,7 +567,7 @@ namespace AAXHelpers
exporter.addToExtraSearchPaths (aaxFolder.getChildFile ("Interfaces").getChildFile ("ACF"));
}
- static inline void prepareExporter (ProjectExporter& exporter, ProjectSaver& projectSaver, const File& /*moduleFolder*/)
+ static inline void prepareExporter (ProjectExporter& exporter, ProjectSaver& projectSaver)
{
if (isExporterSupported (exporter))
{
diff --git a/extras/Introjucer/Source/Project/jucer_ConfigTree_Base.h b/extras/Introjucer/Source/Project/jucer_ConfigTree_Base.h
index c497352321..425444f769 100644
--- a/extras/Introjucer/Source/Project/jucer_ConfigTree_Base.h
+++ b/extras/Introjucer/Source/Project/jucer_ConfigTree_Base.h
@@ -187,7 +187,7 @@ public:
void addSubItems() override
{
- addSubItem (new ModulesItem (project));
+ addSubItem (new EnabledModulesItem (project));
IntrojucerApp::getApp().addExtraConfigItems (project, *this);
int i = 0;
diff --git a/extras/Introjucer/Source/Project/jucer_ConfigTree_Exporter.h b/extras/Introjucer/Source/Project/jucer_ConfigTree_Exporter.h
index 2a6a8cb5c4..222c51cb17 100644
--- a/extras/Introjucer/Source/Project/jucer_ConfigTree_Exporter.h
+++ b/extras/Introjucer/Source/Project/jucer_ConfigTree_Exporter.h
@@ -43,7 +43,7 @@ public:
Icon getIcon() const override { return Icon (getIcons().exporter, getContrastingColour (0.5f)); }
void showDocument() override { showSettingsPage (new SettingsComp (exporter)); }
- void deleteItem()
+ void deleteItem() override
{
if (AlertWindow::showOkCancelBox (AlertWindow::WarningIcon, "Delete Exporter",
"Are you sure you want to delete this export target?"))
@@ -54,13 +54,13 @@ public:
}
}
- void addSubItems()
+ void addSubItems() override
{
for (ProjectExporter::ConfigIterator config (*exporter); config.next();)
addSubItem (new ConfigItem (config.config, exporter->getName()));
}
- void showPopupMenu()
+ void showPopupMenu() override
{
PopupMenu menu;
menu.addItem (1, "Add a new configuration");
@@ -70,7 +70,7 @@ public:
launchPopupMenu (menu);
}
- void handlePopupMenuResult (int resultCode)
+ void handlePopupMenuResult (int resultCode) override
{
if (resultCode == 2)
deleteAllSelectedItems();
@@ -78,17 +78,17 @@ public:
exporter->addNewConfiguration (nullptr);
}
- var getDragSourceDescription()
+ var getDragSourceDescription() override
{
return getParentItem()->getUniqueName() + "/" + String (exporterIndex);
}
- bool isInterestedInDragSource (const DragAndDropTarget::SourceDetails& dragSourceDetails)
+ bool isInterestedInDragSource (const DragAndDropTarget::SourceDetails& dragSourceDetails) override
{
return dragSourceDetails.description.toString().startsWith (getUniqueName());
}
- void itemDropped (const DragAndDropTarget::SourceDetails& dragSourceDetails, int insertIndex)
+ void itemDropped (const DragAndDropTarget::SourceDetails& dragSourceDetails, int insertIndex) override
{
const int oldIndex = indexOfConfig (dragSourceDetails.description.toString().fromLastOccurrenceOf ("||", false, false));
@@ -203,9 +203,9 @@ public:
{
for (Project::ExporterIterator exporter (config->project); exporter.next();)
{
- if (config->config.isAChildOf (exporter.exporter->settings))
+ if (config->config.isAChildOf (exporter->settings))
{
- exporter.exporter->addNewConfiguration (config);
+ exporter->addNewConfiguration (config);
break;
}
}
diff --git a/extras/Introjucer/Source/Project/jucer_ConfigTree_Modules.h b/extras/Introjucer/Source/Project/jucer_ConfigTree_Modules.h
index aa2951cab9..3ce98f4ee0 100644
--- a/extras/Introjucer/Source/Project/jucer_ConfigTree_Modules.h
+++ b/extras/Introjucer/Source/Project/jucer_ConfigTree_Modules.h
@@ -22,52 +22,354 @@
==============================================================================
*/
-class ModulesItem : public ConfigTreeItemBase
+
+class ModuleItem : public ConfigTreeItemBase
{
public:
- ModulesItem (Project& p) : project (p) {}
+ ModuleItem (Project& p, const String& modID)
+ : project (p), moduleID (modID)
+ {
+ }
+
+ bool canBeSelected() const override { return true; }
+ bool mightContainSubItems() override { return false; }
+ String getUniqueName() const override { return "module_" + moduleID; }
+ String getDisplayName() const override { return moduleID; }
+ String getRenamingName() const override { return getDisplayName(); }
+ void setName (const String&) override {}
+ bool isMissing() override { return hasMissingDependencies(); }
+ Icon getIcon() const override { return Icon (getIcons().jigsaw, getContrastingColour (Colours::red, 0.5f)); }
+ void showDocument() override { showSettingsPage (new ModuleSettingsPanel (project, moduleID)); }
+ void deleteItem() override { project.getModules().removeModule (moduleID); }
+
+ void showPopupMenu() override
+ {
+ PopupMenu menu;
+ menu.addItem (1, "Remove this module");
+ launchPopupMenu (menu);
+ }
+
+ void handlePopupMenuResult (int resultCode) override
+ {
+ if (resultCode == 1)
+ project.getModules().removeModule (moduleID);
+ }
+
+ Project& project;
+ String moduleID;
+
+private:
+ bool hasMissingDependencies() const
+ {
+ return project.getModules().getExtraDependenciesNeeded (moduleID).size() > 0;
+ }
+
+ //==============================================================================
+ class ModuleSettingsPanel : public Component
+ {
+ public:
+ ModuleSettingsPanel (Project& p, const String& modID)
+ : project (p), moduleID (modID)
+ {
+ addAndMakeVisible (&group);
+ group.setName ("Module: " + moduleID);
+ refresh();
+ }
+
+ void refresh()
+ {
+ setEnabled (project.getModules().isModuleEnabled (moduleID));
+
+ PropertyListBuilder props;
+
+ props.add (new ModuleInfoComponent (project, moduleID));
+
+ if (project.getModules().getExtraDependenciesNeeded (moduleID).size() > 0)
+ props.add (new MissingDependenciesComponent (project, moduleID));
+
+ for (Project::ExporterIterator exporter (project); exporter.next();)
+ props.add (new TextPropertyComponent (exporter->getPathForModuleValue (moduleID),
+ "Path for " + exporter->getName().quoted(), 1024, false),
+ "A path to the folder that contains the " + moduleID + " module when compiling the "
+ + exporter->getName().quoted() + " target. "
+ "This can be an absolute path, or relative to the jucer project folder, but it "
+ "must be valid on the filesystem of the target machine that will be performing this build.");
+
+ props.add (new BooleanPropertyComponent (project.getModules().shouldCopyModuleFilesLocally (moduleID),
+ "Create local copy", "Copy the module into the project folder"),
+ "If this is enabled, then a local copy of the entire module will be made inside your project (in the auto-generated JuceLibraryFiles folder), "
+ "so that your project will be self-contained, and won't need to contain any references to files in other folders. "
+ "This also means that you can check the module into your source-control system to make sure it is always in sync with your own code.");
+
+ props.add (new BooleanPropertyComponent (project.getModules().shouldShowAllModuleFilesInProject (moduleID),
+ "Add source to project", "Make module files browsable in projects"),
+ "If this is enabled, then the entire source tree from this module will be shown inside your project, "
+ "making it easy to browse/edit the module's classes. If disabled, then only the minimum number of files "
+ "required to compile it will appear inside your project.");
+
+ StringArray possibleValues;
+ possibleValues.add ("(Use Default)");
+ possibleValues.add ("Enabled");
+ possibleValues.add ("Disabled");
+
+ Array mappings;
+ mappings.add (Project::configFlagDefault);
+ mappings.add (Project::configFlagEnabled);
+ mappings.add (Project::configFlagDisabled);
+
+ ModuleDescription info (project.getModules().getModuleInfo (moduleID));
+
+ if (info.isValid())
+ {
+ OwnedArray configFlags;
+ LibraryModule (info).getConfigFlags (project, configFlags);
+
+ for (int i = 0; i < configFlags.size(); ++i)
+ {
+ ChoicePropertyComponent* c = new ChoicePropertyComponent (configFlags[i]->value,
+ configFlags[i]->symbol,
+ possibleValues, mappings);
+ c->setTooltip (configFlags[i]->description);
+ props.add (c);
+ }
+ }
+
+ group.setProperties (props);
+ parentSizeChanged();
+ }
+
+ void parentSizeChanged() override { updateSize (*this, group); }
+
+ private:
+ PropertyGroupComponent group;
+ Project& project;
+ String moduleID;
+
+ //==============================================================================
+ class ModuleInfoComponent : public PropertyComponent
+ {
+ public:
+ ModuleInfoComponent (Project& p, const String& modID)
+ : PropertyComponent ("Module", 150), project (p), moduleID (modID)
+ {
+ }
+
+ void refresh() {}
+
+ void paint (Graphics& g)
+ {
+ g.setColour (Colours::white.withAlpha (0.4f));
+ g.fillRect (0, 0, getWidth(), getHeight() - 1);
+
+ AttributedString s;
+ s.setJustification (Justification::topLeft);
+
+ Font f (14.0f);
+
+ ModuleDescription info (project.getModules().getModuleInfo (moduleID));
+
+ if (info.isValid())
+ {
+ s.append (info.getName() + "\n\n", f.boldened());
+ s.append ("Version: " + info.getVersion()
+ + "\nLicense: " + info.getLicense() + "\n", f.italicised());
+ s.append ("\n" + info.getDescription(), f);
+ }
+ else
+ {
+ s.append ("Cannot find this module at the specified path!", f.boldened());
+ s.setColour (Colours::darkred);
+ }
+
+ s.draw (g, getLocalBounds().reduced (6, 5).toFloat());
+ }
+
+ private:
+ Project& project;
+ String moduleID;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ModuleInfoComponent)
+ };
+
+ //==============================================================================
+ class MissingDependenciesComponent : public PropertyComponent,
+ public ButtonListener
+ {
+ public:
+ MissingDependenciesComponent (Project& p, const String& modID)
+ : PropertyComponent ("Dependencies", 100),
+ project (p), moduleID (modID),
+ missingDependencies (project.getModules().getExtraDependenciesNeeded (modID)),
+ fixButton ("Add Required Modules")
+ {
+ addAndMakeVisible (&fixButton);
+ fixButton.setColour (TextButton::buttonColourId, Colours::red);
+ fixButton.setColour (TextButton::textColourOffId, Colours::white);
+ fixButton.addListener (this);
+ }
+
+ void refresh() {}
+
+ void paint (Graphics& g)
+ {
+ g.setColour (Colours::white.withAlpha (0.4f));
+ g.fillRect (0, 0, getWidth(), getHeight() - 1);
+
+ String text ("This module has missing dependencies!\n\n"
+ "To build correctly, it requires the following modules to be added:\n");
+ text << missingDependencies.joinIntoString (", ");
+
+ AttributedString s;
+ s.setJustification (Justification::topLeft);
+ s.append (text, Font (13.0f), Colours::red.darker());
+ s.draw (g, getLocalBounds().reduced (4, 16).toFloat());
+ }
+
+ void buttonClicked (Button*)
+ {
+ bool anyFailed = false;
+
+ ModuleList list;
+ list.scanAllKnownFolders (project);
+
+ for (int i = missingDependencies.size(); --i >= 0;)
+ {
+ if (const ModuleDescription* info = list.getModuleWithID (missingDependencies[i]))
+ project.getModules().addModule (info->manifestFile, project.getModules().areMostModulesCopiedLocally());
+ else
+ anyFailed = true;
+ }
+
+ if (ModuleSettingsPanel* p = findParentComponentOfClass())
+ p->refresh();
+
+ if (anyFailed)
+ AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
+ "Adding Missing Dependencies",
+ "Couldn't locate some of these modules - you'll beed to find their "
+ "folders manually and add them to the list.");
+ }
+
+ void resized()
+ {
+ fixButton.setBounds (getWidth() - 168, getHeight() - 26, 160, 22);
+ }
+
+ private:
+ Project& project;
+ String moduleID;
+ StringArray missingDependencies;
+ TextButton fixButton;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MissingDependenciesComponent)
+ };
+ };
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ModuleItem)
+};
+
+//==============================================================================
+class EnabledModulesItem : public ConfigTreeItemBase
+{
+public:
+ EnabledModulesItem (Project& p)
+ : project (p),
+ moduleListTree (p.getModules().state)
+ {
+ moduleListTree.addListener (this);
+ }
bool isModulesList() const override { return true; }
bool canBeSelected() const override { return true; }
- bool mightContainSubItems() override { return false; }
+ bool mightContainSubItems() override { return true; }
String getUniqueName() const override { return "modules"; }
String getRenamingName() const override { return getDisplayName(); }
String getDisplayName() const override { return "Modules"; }
void setName (const String&) override {}
bool isMissing() override { return false; }
Icon getIcon() const override { return Icon (getIcons().graph, getContrastingColour (Colours::red, 0.5f)); }
- void showDocument() override { showSettingsPage (new SettingsComp (project)); }
+
+ void showDocument()
+ {
+ if (ProjectContentComponent* pcc = getProjectContentComponent())
+ pcc->setEditorComponent (new ModulesPanel (project), nullptr);
+ }
+
+ bool isInterestedInFileDrag (const StringArray& files) override
+ {
+ for (int i = files.size(); --i >= 0;)
+ if (ModuleDescription (File (files[i]).getChildFile (ModuleDescription::getManifestFileName())).isValid())
+ return true;
+
+ return false;
+ }
+
+ void filesDropped (const StringArray& files, int insertIndex) override
+ {
+ Array modules;
+
+ for (int i = files.size(); --i >= 0;)
+ {
+ ModuleDescription m (File (files[i]).getChildFile (ModuleDescription::getManifestFileName()));
+ if (m.isValid())
+ modules.add (m);
+ }
+
+ for (int i = 0; i < modules.size(); ++i)
+ project.getModules().addModule (modules.getReference(i).manifestFile,
+ project.getModules().areMostModulesCopiedLocally());
+ }
+
+ void addSubItems() override
+ {
+ for (int i = 0; i < project.getModules().getNumModules(); ++i)
+ addSubItem (new ModuleItem (project, project.getModules().getModuleID (i)));
+ }
+
+ void showPopupMenu() override
+ {
+ PopupMenu menu, knownModules, copyModeMenu;
+
+ const StringArray modules (getAvailableModules());
+ for (int i = 0; i < modules.size(); ++i)
+ knownModules.addItem (1 + i, modules[i], ! project.getModules().isModuleEnabled (modules[i]));
+
+ menu.addSubMenu ("Add a module", knownModules);
+ menu.addSeparator();
+ menu.addItem (1001, "Add a module from a specified folder...");
+
+ launchPopupMenu (menu);
+ }
+
+ void handlePopupMenuResult (int resultCode) override
+ {
+ if (resultCode == 1001)
+ project.getModules().addModuleFromUserSelectedFile();
+ else if (resultCode > 0)
+ project.getModules().addModuleInteractive (getAvailableModules() [resultCode - 1]);
+ }
+
+ StringArray getAvailableModules()
+ {
+ ModuleList list;
+ list.scanAllKnownFolders (project);
+ return list.getIDs();
+ }
+
+ //==============================================================================
+ void valueTreeChildAdded (ValueTree& parentTree, ValueTree&) override { refreshIfNeeded (parentTree); }
+ void valueTreeChildRemoved (ValueTree& parentTree, ValueTree&) override { refreshIfNeeded (parentTree); }
+ void valueTreeChildOrderChanged (ValueTree& parentTree) override { refreshIfNeeded (parentTree); }
+
+ void refreshIfNeeded (ValueTree& changedTree)
+ {
+ if (changedTree == moduleListTree)
+ refreshSubItems();
+ }
private:
Project& project;
+ ValueTree moduleListTree;
- class SettingsComp : public Component
- {
- public:
- SettingsComp (Project& p) : project (p)
- {
- addAndMakeVisible (&group);
-
- PropertyListBuilder props;
- props.add (new ModulesPanel (project));
- group.setProperties (props);
- group.setName ("Modules");
-
- parentSizeChanged();
- }
-
- void parentSizeChanged() override
- {
- updateSize (*this, group);
- }
-
- private:
- Project& project;
- var lastProjectType;
- PropertyGroupComponent group;
-
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SettingsComp)
- };
-
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ModulesItem)
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EnabledModulesItem)
};
diff --git a/extras/Introjucer/Source/Project/jucer_Module.cpp b/extras/Introjucer/Source/Project/jucer_Module.cpp
index a99c009ffd..31f230557c 100644
--- a/extras/Introjucer/Source/Project/jucer_Module.cpp
+++ b/extras/Introjucer/Source/Project/jucer_Module.cpp
@@ -29,419 +29,229 @@
#include "jucer_AudioPluginModule.h"
-//==============================================================================
-AvailableModuleList::AvailableModuleList()
+ModuleDescription::ModuleDescription (const File& manifest)
+ : moduleInfo (JSON::parse (manifest)), manifestFile (manifest)
{
-}
-
-AvailableModuleList::AvailableModuleList (const AvailableModuleList& other)
- : moduleFolder (other.moduleFolder)
-{
- modules.addCopiesOf (other.modules);
-}
-
-AvailableModuleList& AvailableModuleList::operator= (const AvailableModuleList& other)
-{
- moduleFolder = other.moduleFolder;
- modules.clear();
- modules.addCopiesOf (other.modules);
-
- return *this;
-}
-
-bool AvailableModuleList::operator== (const AvailableModuleList& other) const
-{
- if (modules.size() != other.modules.size())
- return false;
-
- for (int i = modules.size(); --i >= 0;)
+ if (moduleInfo.isVoid() && manifestFile.exists())
{
- const Module* m1 = modules.getUnchecked(i);
- const Module* m2 = other.findModuleInfo (m1->uid);
+ var json;
+ Result r (JSON::parse (manifestFile.loadFileAsString(), json));
- if (m2 == nullptr || *m1 != *m2)
- return false;
- }
-
- return true;
-}
-
-bool AvailableModuleList::isLocalModulesFolderValid()
-{
- return isModulesFolder (getModulesFolderForJuceOrModulesFolder (getLocalModulesFolder (nullptr)));
-}
-
-static int getVersionElement (const String& v, int index)
-{
- StringArray parts;
- parts.addTokens (v, "., ", String::empty);
-
- return parts [parts.size() - index - 1].getIntValue();
-}
-
-static int getJuceVersion (const String& v)
-{
- return getVersionElement (v, 2) * 100000
- + getVersionElement (v, 1) * 1000
- + getVersionElement (v, 0);
-}
-
-static int getBuiltJuceVersion()
-{
- return JUCE_MAJOR_VERSION * 100000
- + JUCE_MINOR_VERSION * 1000
- + JUCE_BUILDNUMBER;
-}
-
-bool AvailableModuleList::isLibraryNewerThanIntrojucer()
-{
- AvailableModuleList list;
- list.rescan (getModulesFolderForJuceOrModulesFolder (getLocalModulesFolder (nullptr)));
-
- for (int i = list.modules.size(); --i >= 0;)
- {
- const Module* m = list.modules.getUnchecked(i);
-
- if (m->uid.startsWith ("juce_")
- && getJuceVersion (m->version) > getBuiltJuceVersion())
- return true;
- }
-
- return false;
-}
-
-bool AvailableModuleList::isJuceFolder (const File& folder)
-{
- return folder.getFileName().containsIgnoreCase ("juce")
- && isModulesFolder (folder.getChildFile ("modules"));
-}
-
-bool AvailableModuleList::isModulesFolder (const File& folder)
-{
- return folder.getFileName().equalsIgnoreCase ("modules")
- && folder.isDirectory();
-}
-
-bool AvailableModuleList::isJuceOrModulesFolder (const File& folder)
-{
- return isJuceFolder (folder) || isModulesFolder (folder);
-}
-
-File AvailableModuleList::getModulesFolderForJuceOrModulesFolder (const File& f)
-{
- if (f.getFileName() != "modules" && f.isDirectory() && f.getChildFile ("modules").isDirectory())
- return f.getChildFile ("modules");
-
- return f;
-}
-
-File AvailableModuleList::getModulesFolderForExporter (const ProjectExporter& exporter)
-{
- File f (exporter.getProject().resolveFilename (exporter.getJuceFolderString()));
- return getModulesFolderForJuceOrModulesFolder (f);
-}
-
-File AvailableModuleList::getDefaultModulesFolder (Project* project)
-{
- if (project != nullptr)
- {
- for (Project::ExporterIterator exporter (*project); exporter.next();)
+ if (r.failed() && manifestFile.loadFileAsString().isNotEmpty())
{
- const File f (getModulesFolderForExporter (*exporter));
-
- if (AvailableModuleList::isModulesFolder (f))
- return f;
+ DBG (r.getErrorMessage());
+ jassertfalse; // broken JSON in a module manifest.
}
}
-
- // Fall back to a default..
- #if JUCE_WINDOWS
- return File::getSpecialLocation (File::userDocumentsDirectory)
- #else
- return File::getSpecialLocation (File::userHomeDirectory)
- #endif
- .getChildFile ("juce")
- .getChildFile ("modules");
}
-File AvailableModuleList::getLocalModulesFolder (Project* project)
+//==============================================================================
+ModuleList::ModuleList()
{
- File defaultJuceFolder (getDefaultModulesFolder (project));
-
- File f (getGlobalProperties().getValue ("lastJuceFolder", defaultJuceFolder.getFullPathName()));
- f = getModulesFolderForJuceOrModulesFolder (f);
-
- if ((! AvailableModuleList::isModulesFolder (f)) && AvailableModuleList::isModulesFolder (defaultJuceFolder))
- f = defaultJuceFolder;
-
- return f;
}
-void AvailableModuleList::setLocalModulesFolder (const File& file)
+ModuleList::ModuleList (const ModuleList& other)
{
- //jassert (FileHelpers::isJuceFolder (file));
- getGlobalProperties().setValue ("lastJuceFolder", file.getFullPathName());
+ modules.addCopiesOf (other.modules);
+}
+
+const ModuleDescription* ModuleList::getModuleWithID (const String& moduleID) const
+{
+ for (int i = 0; i < modules.size(); ++i)
+ {
+ ModuleDescription* m = modules.getUnchecked(i);
+ if (m->getID() == moduleID)
+ return m;
+ }
+
+ return nullptr;
}
struct ModuleSorter
{
- static int compareElements (const AvailableModuleList::Module* m1, const AvailableModuleList::Module* m2)
+ static int compareElements (const ModuleDescription* m1, const ModuleDescription* m2)
{
- return m1->uid.compareIgnoreCase (m2->uid);
+ return m1->getID().compareIgnoreCase (m2->getID());
}
};
-void AvailableModuleList::sort()
+void ModuleList::sort()
{
ModuleSorter sorter;
modules.sort (sorter);
}
-void AvailableModuleList::rescan()
+StringArray ModuleList::getIDs() const
{
- rescan (moduleFolder);
+ StringArray results;
+
+ for (int i = 0; i < modules.size(); ++i)
+ results.add (modules.getUnchecked(i)->getID());
+
+ results.sort (true);
+ return results;
}
-Result AvailableModuleList::rescan (const File& newModulesFolder)
+Result ModuleList::addAllModulesInFolder (const File& path)
{
- modules.clear();
- moduleFolder = getModulesFolderForJuceOrModulesFolder (newModulesFolder);
+ const File moduleDef (path.getChildFile (ModuleDescription::getManifestFileName()));
- if (moduleFolder.isDirectory())
+ if (moduleDef.exists())
{
- DirectoryIterator iter (moduleFolder, false, "*", File::findDirectories);
+ ModuleDescription m (moduleDef);
- while (iter.next())
+ if (! m.isValid())
+ return Result::fail ("Failed to load module manifest: " + moduleDef.getFullPathName());
+
+ modules.add (new ModuleDescription (m));
+ }
+ else
+ {
+ for (DirectoryIterator iter (path, false, "*", File::findDirectories); iter.next();)
{
- const File moduleDef (iter.getFile().getLinkedTarget()
- .getChildFile (LibraryModule::getInfoFileName()));
-
- if (moduleDef.exists())
- {
- LibraryModule m (moduleDef);
-
- if (! m.isValid())
- return Result::fail ("Failed to load module manifest: " + moduleDef.getFullPathName());
-
- 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->license = m.moduleInfo ["license"];
- info->file = moduleDef;
- }
+ Result r = addAllModulesInFolder (iter.getFile().getLinkedTarget());
+ if (r.failed())
+ return r;
}
}
- sort();
return Result::ok();
}
-bool AvailableModuleList::loadFromWebsite()
+static Array getAllPossibleModulePaths (Project& project)
+{
+ StringArray paths;
+
+ for (Project::ExporterIterator exporter (project); exporter.next();)
+ {
+ if (exporter->canLaunchProject())
+ {
+ for (int i = 0; i < project.getModules().getNumModules(); ++i)
+ {
+ const String path (exporter->getPathForModuleString (project.getModules().getModuleID (i)));
+
+ if (path.isNotEmpty())
+ paths.addIfNotAlreadyThere (path);
+ }
+
+ String oldPath (exporter->getLegacyModulePath());
+
+ if (oldPath.isNotEmpty())
+ paths.addIfNotAlreadyThere (oldPath);
+ }
+ }
+
+ Array files;
+
+ for (int i = 0; i < paths.size(); ++i)
+ {
+ const File f (project.resolveFilename (paths[i]));
+
+ if (f.isDirectory())
+ {
+ files.add (f);
+
+ if (f.getChildFile ("modules").isDirectory())
+ files.addIfNotAlreadyThere (f.getChildFile ("modules"));
+ }
+ }
+
+ return files;
+}
+
+Result ModuleList::scanAllKnownFolders (Project& project)
+{
+ modules.clear();
+ Result result (Result::ok());
+
+ const Array modulePaths (getAllPossibleModulePaths (project));
+
+ for (int i = 0; i < modulePaths.size(); ++i)
+ {
+ result = addAllModulesInFolder (modulePaths.getReference(i));
+
+ if (result.failed())
+ break;
+ }
+
+ sort();
+ return result;
+}
+
+bool ModuleList::loadFromWebsite()
{
modules.clear();
URL baseURL ("http://www.juce.com/juce/modules");
URL url (baseURL.getChildURL ("modulelist.php"));
- var infoList (JSON::parse (url.readEntireTextStream (false)));
+ const ScopedPointer in (url.createInputStream (false, nullptr, nullptr, String::empty, 10000));
- if (infoList.isArray())
+ if (in == nullptr)
+ return false;
+
+ var infoList (JSON::parse (in->readEntireStreamAsString()));
+
+ if (! infoList.isArray())
+ return false;
+
+ const Array* moduleList = infoList.getArray();
+
+ for (int i = 0; i < moduleList->size(); ++i)
{
- const Array* moduleList = infoList.getArray();
+ const var& m = moduleList->getReference(i);
+ const String file (m [Ids::file].toString());
- for (int i = 0; i < moduleList->size(); ++i)
+ if (file.isNotEmpty())
{
- const var& m = moduleList->getReference(i);
- const String file (m ["file"].toString());
+ ModuleDescription lm (m [Ids::info]);
- if (file.isNotEmpty())
+ if (lm.isValid())
{
- var moduleInfo (m ["info"]);
- LibraryModule lm (moduleInfo);
-
- if (lm.isValid())
- {
- Module* info = new Module();
- modules.add (info);
-
- info->uid = lm.getID();
- info->version = lm.getVersion();
- info->name = lm.getName();
- info->description = lm.getDescription();
- info->license = lm.getLicense();
- info->url = baseURL.getChildURL (file);
- }
+ lm.url = baseURL.getChildURL (file);
+ modules.add (new ModuleDescription (lm));
}
}
}
sort();
- return infoList.isArray();
-}
-
-LibraryModule* AvailableModuleList::Module::create() const
-{
- return new LibraryModule (file);
-}
-
-bool AvailableModuleList::Module::operator== (const Module& other) const
-{
- return uid == other.uid
- && version == other.version
- && name == other.name
- && description == other.description
- && license == other.license
- && file == other.file
- && url == other.url;
-}
-
-bool AvailableModuleList::Module::operator!= (const Module& other) const
-{
- return ! operator== (other);
-}
-
-LibraryModule* AvailableModuleList::loadModule (const String& uid) const
-{
- if (const Module* const m = findModuleInfo (uid))
- return m->create();
-
- return nullptr;
-}
-
-const AvailableModuleList::Module* AvailableModuleList::findModuleInfo (const String& uid) const
-{
- for (int i = modules.size(); --i >= 0;)
- if (modules.getUnchecked(i)->uid == uid)
- return modules.getUnchecked(i);
-
- return nullptr;
-}
-
-void AvailableModuleList::getDependencies (const String& moduleID, StringArray& dependencies) const
-{
- ScopedPointer m (loadModule (moduleID));
-
- if (m != nullptr)
- {
- const var depsArray (m->moduleInfo ["dependencies"]);
-
- if (const Array* const deps = depsArray.getArray())
- {
- for (int i = 0; i < deps->size(); ++i)
- {
- const var& d = deps->getReference(i);
-
- String uid (d ["id"].toString());
- String version (d ["version"].toString());
-
- if (! dependencies.contains (uid, true))
- {
- dependencies.add (uid);
- getDependencies (uid, dependencies);
- }
- }
- }
- }
-}
-
-void AvailableModuleList::createDependencies (const String& moduleID, OwnedArray&) const
-{
- ScopedPointer m (loadModule (moduleID));
-
- if (m != nullptr)
- {
- const var depsArray (m->moduleInfo ["dependencies"]);
-
- if (const Array* const deps = depsArray.getArray())
- {
- for (int i = 0; i < deps->size(); ++i)
- {
- const var& d = deps->getReference(i);
-
- String uid (d ["id"].toString());
- String version (d ["version"].toString());
-
- //xxx to do - also need to find version conflicts
- jassertfalse;
- }
- }
- }
-}
-
-StringArray AvailableModuleList::getExtraDependenciesNeeded (Project& project, const AvailableModuleList::Module& m)
-{
- StringArray dependencies, extraDepsNeeded;
- getDependencies (m.uid, dependencies);
-
- for (int i = 0; i < dependencies.size(); ++i)
- if ((! project.getModules().isModuleEnabled (dependencies[i])) && dependencies[i] != m.uid)
- extraDepsNeeded.add (dependencies[i]);
-
- return extraDepsNeeded;
+ return true;
}
//==============================================================================
-LibraryModule::LibraryModule (const File& file)
- : moduleInfo (JSON::parse (file)),
- moduleFile (file),
- moduleFolder (file.getParentDirectory())
+LibraryModule::LibraryModule (const ModuleDescription& d)
+ : moduleInfo (d)
{
}
-LibraryModule::LibraryModule (const var& info)
- : moduleInfo (info)
-{
-}
-
-bool LibraryModule::isValid() const { return getID().isNotEmpty(); }
-
-bool LibraryModule::isPluginClient() const { return getID() == "juce_audio_plugin_client"; }
bool LibraryModule::isAUPluginHost (const Project& project) const { return getID() == "juce_audio_processors" && project.isConfigFlagEnabled ("JUCE_PLUGINHOST_AU"); }
bool LibraryModule::isVSTPluginHost (const Project& project) const { return getID() == "juce_audio_processors" && project.isConfigFlagEnabled ("JUCE_PLUGINHOST_VST"); }
-File LibraryModule::getInclude (const File& folder) const
+File LibraryModule::getModuleHeaderFile (const File& folder) const
{
- return folder.getChildFile (moduleInfo ["include"].toString());
-}
-
-RelativePath LibraryModule::getModuleRelativeToProject (ProjectExporter& exporter) const
-{
- RelativePath p (exporter.getJuceFolderString(), RelativePath::projectFolder);
- if (p.getFileName() != "modules")
- p = p.getChildFile ("modules");
-
- return p.getChildFile (getID());
-}
-
-RelativePath LibraryModule::getModuleOrLocalCopyRelativeToProject (ProjectExporter& exporter, const File& localModuleFolder) const
-{
- if (exporter.getProject().getModules().shouldCopyModuleFilesLocally (getID()).getValue())
- return RelativePath (exporter.getProject().getRelativePathForFile (localModuleFolder), RelativePath::projectFolder);
-
- return getModuleRelativeToProject (exporter);
+ return folder.getChildFile (moduleInfo.getHeaderName());
}
//==============================================================================
void LibraryModule::writeIncludes (ProjectSaver& projectSaver, OutputStream& out)
{
- const File localModuleFolder (projectSaver.getLocalModuleFolder (*this));
- const File localHeader (getInclude (localModuleFolder));
+ const File localModuleFolder (projectSaver.getLocalModuleFolder (getID()));
+ const File localHeader (getModuleHeaderFile (localModuleFolder));
- if (projectSaver.getProject().getModules().shouldCopyModuleFilesLocally (getID()).getValue())
+ localModuleFolder.createDirectory();
+
+ if (projectSaver.project.getModules().shouldCopyModuleFilesLocally (getID()).getValue())
{
- projectSaver.copyFolder (moduleFolder, localModuleFolder);
+ projectSaver.copyFolder (moduleInfo.getFolder(), localModuleFolder);
}
else
{
localModuleFolder.createDirectory();
- createLocalHeaderWrapper (projectSaver, getInclude (moduleFolder), localHeader);
+ createLocalHeaderWrapper (projectSaver, getModuleHeaderFile (moduleInfo.getFolder()), localHeader);
}
- out << CodeHelpers::createIncludeStatement (localHeader, projectSaver.getGeneratedCodeFolder().getChildFile ("AppConfig.h")) << newLine;
+ out << CodeHelpers::createIncludeStatement (localHeader, projectSaver.getGeneratedCodeFolder()
+ .getChildFile ("AppConfig.h")) << newLine;
}
static void writeGuardedInclude (OutputStream& out, StringArray paths, StringArray guards)
@@ -481,7 +291,7 @@ static void writeGuardedInclude (OutputStream& out, StringArray paths, StringArr
void LibraryModule::createLocalHeaderWrapper (ProjectSaver& projectSaver, const File& originalHeader, const File& localHeader) const
{
- Project& project = projectSaver.getProject();
+ Project& project = projectSaver.project;
MemoryOutputStream out;
@@ -493,10 +303,10 @@ void LibraryModule::createLocalHeaderWrapper (ProjectSaver& projectSaver, const
for (Project::ExporterIterator exporter (project); exporter.next();)
{
- const RelativePath headerFromProject (getModuleRelativeToProject (*exporter)
+ const RelativePath headerFromProject (exporter->getModuleFolderRelativeToProject (getID(), projectSaver)
.getChildFile (originalHeader.getFileName()));
- const RelativePath fileFromHere (headerFromProject.rebased (project.getFile().getParentDirectory(),
+ const RelativePath fileFromHere (headerFromProject.rebased (project.getProjectFolder(),
localHeader.getParentDirectory(), RelativePath::unknown));
paths.add (fileFromHere.toUnixStyle().quoted());
@@ -510,28 +320,16 @@ void LibraryModule::createLocalHeaderWrapper (ProjectSaver& projectSaver, const
}
//==============================================================================
-File LibraryModule::getLocalFolderFor (Project& project) const
-{
- if (project.getModules().shouldCopyModuleFilesLocally (getID()).getValue())
- return project.getGeneratedCodeFolder().getChildFile ("modules").getChildFile (getID());
-
- return moduleFolder;
-}
-
void LibraryModule::prepareExporter (ProjectExporter& exporter, ProjectSaver& projectSaver) const
{
Project& project = exporter.getProject();
- File localFolder (moduleFolder);
- if (project.getModules().shouldCopyModuleFilesLocally (getID()).getValue())
- localFolder = projectSaver.getLocalModuleFolder (*this);
-
{
Array compiled;
- findAndAddCompiledCode (exporter, projectSaver, localFolder, compiled);
+ findAndAddCompiledCode (exporter, projectSaver, moduleInfo.getFolder(), compiled);
if (project.getModules().shouldShowAllModuleFilesInProject (getID()).getValue())
- addBrowsableCode (exporter, compiled, localFolder);
+ addBrowsableCode (exporter, projectSaver, compiled, moduleInfo.getFolder());
}
if (isVSTPluginHost (project))
@@ -542,12 +340,12 @@ void LibraryModule::prepareExporter (ProjectExporter& exporter, ProjectSaver& pr
if (isAUPluginHost (project))
exporter.xcodeFrameworks.addTokens ("AudioUnit CoreAudioKit", false);
- const String frameworks (moduleInfo [exporter.isOSX() ? "OSXFrameworks" : "iOSFrameworks"].toString());
+ const String frameworks (moduleInfo.moduleInfo [exporter.isOSX() ? "OSXFrameworks" : "iOSFrameworks"].toString());
exporter.xcodeFrameworks.addTokens (frameworks, ", ", String::empty);
}
else if (exporter.isLinux())
{
- const String libs (moduleInfo ["LinuxLibs"].toString());
+ const String libs (moduleInfo.moduleInfo ["LinuxLibs"].toString());
exporter.linuxLibs.addTokens (libs, ", ", String::empty);
exporter.linuxLibs.trim();
exporter.linuxLibs.sort (false);
@@ -555,29 +353,29 @@ void LibraryModule::prepareExporter (ProjectExporter& exporter, ProjectSaver& pr
}
else if (exporter.isCodeBlocks())
{
- const String libs (moduleInfo ["mingwLibs"].toString());
+ const String libs (moduleInfo.moduleInfo ["mingwLibs"].toString());
exporter.mingwLibs.addTokens (libs, ", ", String::empty);
exporter.mingwLibs.trim();
exporter.mingwLibs.sort (false);
exporter.mingwLibs.removeDuplicates (false);
}
- if (isPluginClient())
+ if (moduleInfo.isPluginClient())
{
if (shouldBuildVST (project).getValue()) VSTHelpers::prepareExporter (exporter, projectSaver);
if (shouldBuildAU (project).getValue()) AUHelpers::prepareExporter (exporter, projectSaver);
- if (shouldBuildAAX (project).getValue()) AAXHelpers::prepareExporter (exporter, projectSaver, localFolder);
- if (shouldBuildRTAS (project).getValue()) RTASHelpers::prepareExporter (exporter, projectSaver, localFolder);
+ if (shouldBuildAAX (project).getValue()) AAXHelpers::prepareExporter (exporter, projectSaver);
+ if (shouldBuildRTAS (project).getValue()) RTASHelpers::prepareExporter (exporter, projectSaver);
}
}
void LibraryModule::createPropertyEditors (ProjectExporter& exporter, PropertyListBuilder& props) const
{
if (isVSTPluginHost (exporter.getProject())
- && ! (isPluginClient() && shouldBuildVST (exporter.getProject()).getValue()))
+ && ! (moduleInfo.isPluginClient() && shouldBuildVST (exporter.getProject()).getValue()))
VSTHelpers::createVSTPathEditor (exporter, props);
- if (isPluginClient())
+ if (moduleInfo.isPluginClient())
{
if (shouldBuildVST (exporter.getProject()).getValue()) VSTHelpers::createPropertyEditors (exporter, props);
if (shouldBuildRTAS (exporter.getProject()).getValue()) RTASHelpers::createPropertyEditors (exporter, props);
@@ -587,7 +385,7 @@ void LibraryModule::createPropertyEditors (ProjectExporter& exporter, PropertyLi
void LibraryModule::getConfigFlags (Project& project, OwnedArray& flags) const
{
- const File header (getInclude (moduleFolder));
+ const File header (getModuleHeaderFile (moduleInfo.getFolder()));
jassert (header.exists());
StringArray lines;
@@ -656,6 +454,14 @@ bool LibraryModule::fileTargetMatches (ProjectExporter& exporter, const String&
return target.isEmpty();
}
+struct FileSorter
+{
+ static int compareElements (const File& f1, const File& f2)
+ {
+ return f1.getFileName().compareIgnoreCase (f2.getFileName());
+ }
+};
+
void LibraryModule::findWildcardMatches (const File& localModuleFolder, const String& wildcardPath, Array& result) const
{
String path (wildcardPath.upToLastOccurrenceOf ("/", false, false));
@@ -677,7 +483,7 @@ void LibraryModule::findWildcardMatches (const File& localModuleFolder, const St
void LibraryModule::findAndAddCompiledCode (ProjectExporter& exporter, ProjectSaver& projectSaver,
const File& localModuleFolder, Array& result) const
{
- const var compileArray (moduleInfo ["compile"]); // careful to keep this alive while the array is in use!
+ const var compileArray (moduleInfo.moduleInfo ["compile"]); // careful to keep this alive while the array is in use!
if (const Array* const files = compileArray.getArray())
{
@@ -706,7 +512,7 @@ void LibraryModule::findAndAddCompiledCode (ProjectExporter& exporter, ProjectSa
void LibraryModule::getLocalCompiledFiles (const File& localModuleFolder, Array& result) const
{
- const var compileArray (moduleInfo ["compile"]); // careful to keep this alive while the array is in use!
+ const var compileArray (moduleInfo.moduleInfo ["compile"]); // careful to keep this alive while the array is in use!
if (const Array* const files = compileArray.getArray())
{
@@ -752,21 +558,22 @@ static void addFileWithGroups (Project::Item& group, const RelativePath& file, c
void LibraryModule::findBrowseableFiles (const File& localModuleFolder, Array& filesFound) const
{
- const var filesArray (moduleInfo ["browse"]);
+ const var filesArray (moduleInfo.moduleInfo ["browse"]);
if (const Array* const files = filesArray.getArray())
for (int i = 0; i < files->size(); ++i)
findWildcardMatches (localModuleFolder, files->getReference(i), filesFound);
}
-void LibraryModule::addBrowsableCode (ProjectExporter& exporter, const Array& compiled, const File& localModuleFolder) const
+void LibraryModule::addBrowsableCode (ProjectExporter& exporter, ProjectSaver& projectSaver,
+ const Array& compiled, const File& localModuleFolder) const
{
if (sourceFiles.size() == 0)
findBrowseableFiles (localModuleFolder, sourceFiles);
Project::Item sourceGroup (Project::Item::createGroup (exporter.getProject(), getID(), "__mainsourcegroup" + getID()));
- const RelativePath moduleFromProject (getModuleOrLocalCopyRelativeToProject (exporter, localModuleFolder));
+ const RelativePath moduleFromProject (exporter.getModuleFolderRelativeToProject (getID(), projectSaver));
for (int i = 0; i < sourceFiles.size(); ++i)
{
@@ -780,8 +587,9 @@ void LibraryModule::addBrowsableCode (ProjectExporter& exporter, const ArraycanLaunchProject())
+ {
+ const String path (exporter->getPathForModuleString (moduleID));
+
+ if (path.isNotEmpty())
+ {
+ const File moduleFolder (project.resolveFilename (path));
+
+ File f (moduleFolder.getChildFile (ModuleDescription::getManifestFileName()));
+
+ if (f.exists())
+ return f;
+
+ f = moduleFolder.getChildFile (moduleID)
+ .getChildFile (ModuleDescription::getManifestFileName());
+
+ if (f.exists())
+ return f;
+
+ f = moduleFolder.getChildFile ("modules")
+ .getChildFile (moduleID)
+ .getChildFile (ModuleDescription::getManifestFileName());
+
+ if (f.exists())
+ return f;
+ }
+ }
+ }
+
+ return File::nonexistent;
+}
+
+File EnabledModuleList::getModuleFolder (const String& moduleID)
+{
+ const File infoFile (getModuleInfoFile (moduleID));
+
+ return infoFile.exists() ? infoFile.getParentDirectory()
+ : File::nonexistent;
+}
+
+struct ModuleTreeSorter
+{
+ static int compareElements (const ValueTree& m1, const ValueTree& m2)
+ {
+ return m1[Ids::ID].toString().compareIgnoreCase (m2[Ids::ID]);
+ }
+};
+
+void EnabledModuleList::sortAlphabetically()
+{
+ ModuleTreeSorter sorter;
+ state.sort (sorter, getUndoManager(), false);
+}
+
Value EnabledModuleList::shouldCopyModuleFilesLocally (const String& moduleID)
{
return state.getChildWithProperty (Ids::ID, moduleID)
.getPropertyAsValue (Ids::useLocalCopy, getUndoManager());
}
-void EnabledModuleList::addModule (const String& moduleID, bool shouldCopyFilesLocally)
+void EnabledModuleList::addModule (const File& moduleManifestFile, bool copyLocally)
{
- if (! isModuleEnabled (moduleID))
+ ModuleDescription info (moduleManifestFile);
+
+ if (info.isValid())
{
- ValueTree module (moduleTag);
- module.setProperty (Ids::ID, moduleID, nullptr);
+ const String moduleID (info.getID());
- state.addChild (module, -1, getUndoManager());
+ if (! isModuleEnabled (moduleID))
+ {
+ ValueTree module (Ids::MODULES);
+ module.setProperty (Ids::ID, moduleID, nullptr);
- shouldShowAllModuleFilesInProject (moduleID) = true;
+ state.addChild (module, -1, getUndoManager());
+ sortAlphabetically();
+
+ shouldShowAllModuleFilesInProject (moduleID) = true;
+ shouldCopyModuleFilesLocally (moduleID) = copyLocally;
+
+ String path (moduleManifestFile.getParentDirectory().getParentDirectory()
+ .getRelativePathFrom (project.getProjectFolder()));
+
+ for (Project::ExporterIterator exporter (project); exporter.next();)
+ exporter->getPathForModuleValue (moduleID) = path;
+ }
}
-
- if (shouldCopyFilesLocally)
- shouldCopyModuleFilesLocally (moduleID) = true;
}
void EnabledModuleList::removeModule (const String& moduleID)
@@ -873,12 +724,146 @@ void EnabledModuleList::removeModule (const String& moduleID)
for (int i = 0; i < state.getNumChildren(); ++i)
if (state.getChild(i) [Ids::ID] == moduleID)
state.removeChild (i, getUndoManager());
+
+ for (Project::ExporterIterator exporter (project); exporter.next();)
+ exporter->removePathForModule (moduleID);
}
-void EnabledModuleList::createRequiredModules (const AvailableModuleList& availableModules,
- OwnedArray& modules) const
+void EnabledModuleList::createRequiredModules (OwnedArray& modules)
{
- for (int i = 0; i < availableModules.modules.size(); ++i)
- if (isModuleEnabled (availableModules.modules.getUnchecked(i)->uid))
- modules.add (availableModules.modules.getUnchecked(i)->create());
+ for (int i = 0; i < getNumModules(); ++i)
+ {
+ ModuleDescription info (getModuleInfo (getModuleID (i)));
+
+ if (info.isValid())
+ modules.add (new LibraryModule (info));
+ }
+}
+
+StringArray EnabledModuleList::getAllModules() const
+{
+ StringArray moduleIDs;
+
+ for (int i = 0; i < getNumModules(); ++i)
+ moduleIDs.add (getModuleID(i));
+
+ return moduleIDs;
+}
+
+static void getDependencies (Project& project, const String& moduleID, StringArray& dependencies)
+{
+ ModuleDescription info (project.getModules().getModuleInfo (moduleID));
+
+ if (info.isValid())
+ {
+ const var depsArray (info.moduleInfo ["dependencies"]);
+
+ if (const Array* const deps = depsArray.getArray())
+ {
+ for (int i = 0; i < deps->size(); ++i)
+ {
+ const var& d = deps->getReference(i);
+
+ String uid (d [Ids::ID].toString());
+ String version (d [Ids::version].toString());
+
+ if (! dependencies.contains (uid, true))
+ {
+ dependencies.add (uid);
+ getDependencies (project, uid, dependencies);
+ }
+ }
+ }
+ }
+}
+
+StringArray EnabledModuleList::getExtraDependenciesNeeded (const String& moduleID) const
+{
+ StringArray dependencies, extraDepsNeeded;
+ getDependencies (project, moduleID, dependencies);
+
+ for (int i = 0; i < dependencies.size(); ++i)
+ if ((! project.getModules().isModuleEnabled (dependencies[i])) && dependencies[i] != moduleID)
+ extraDepsNeeded.add (dependencies[i]);
+
+ return extraDepsNeeded;
+}
+
+bool EnabledModuleList::areMostModulesCopiedLocally() const
+{
+ int numYes = 0, numNo = 0;
+
+ for (int i = project.getModules().getNumModules(); --i >= 0;)
+ {
+ if (project.getModules().shouldCopyModuleFilesLocally (project.getModules().getModuleID (i)).getValue())
+ ++numYes;
+ else
+ ++numNo;
+ }
+
+ return numYes > numNo;
+}
+
+File EnabledModuleList::findDefaultModulesFolder (Project& project)
+{
+ ModuleList available;
+ available.scanAllKnownFolders (project);
+
+ for (int i = available.modules.size(); --i >= 0;)
+ {
+ File f (available.modules.getUnchecked(i)->getFolder());
+
+ if (f.isDirectory())
+ return f.getParentDirectory();
+ }
+
+ return File::getCurrentWorkingDirectory();
+}
+
+void EnabledModuleList::addModuleFromUserSelectedFile()
+{
+ static File lastLocation (findDefaultModulesFolder (project));
+
+ FileChooser fc ("Select a module to add...", lastLocation, String::empty, false);
+
+ if (fc.browseForDirectory())
+ {
+ lastLocation = fc.getResult();
+ addModuleOfferingToCopy (lastLocation);
+ }
+}
+
+void EnabledModuleList::addModuleInteractive (const String& moduleID)
+{
+ ModuleList list;
+ list.scanAllKnownFolders (project);
+
+ if (const ModuleDescription* info = list.getModuleWithID (moduleID))
+ addModule (info->manifestFile, areMostModulesCopiedLocally());
+ else
+ addModuleFromUserSelectedFile();
+}
+
+void EnabledModuleList::addModuleOfferingToCopy (const File& f)
+{
+ ModuleDescription m (f);
+
+ if (! m.isValid())
+ m = ModuleDescription (f.getChildFile (ModuleDescription::getManifestFileName()));
+
+ if (! m.isValid())
+ {
+ AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon,
+ "Add Module", "This wasn't a valid module folder!");
+ return;
+ }
+
+ if (isModuleEnabled (m.getID()))
+ {
+ AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon,
+ "Add Module", "The project already contains this module!");
+ return;
+ }
+
+ addModule (m.manifestFile, areMostModulesCopiedLocally());
}
diff --git a/extras/Introjucer/Source/Project/jucer_Module.h b/extras/Introjucer/Source/Project/jucer_Module.h
index 236324e7e9..b7740cbb48 100644
--- a/extras/Introjucer/Source/Project/jucer_Module.h
+++ b/extras/Introjucer/Source/Project/jucer_Module.h
@@ -30,21 +30,64 @@
class ProjectExporter;
class ProjectSaver;
+//==============================================================================
+struct ModuleDescription
+{
+ ModuleDescription() {}
+ ModuleDescription (const File& manifest);
+ ModuleDescription (const var& info) : moduleInfo (info) {}
+
+ bool isValid() const { return getID().isNotEmpty(); }
+
+ String getID() const { return moduleInfo [Ids::ID].toString(); }
+ String getVersion() const { return moduleInfo [Ids::version].toString(); }
+ String getName() const { return moduleInfo [Ids::name].toString(); }
+ String getDescription() const { return moduleInfo [Ids::description].toString(); }
+ String getLicense() const { return moduleInfo [Ids::license].toString(); }
+ String getHeaderName() const { return moduleInfo [Ids::include].toString(); }
+
+ File getFolder() const { jassert (manifestFile != File::nonexistent); return manifestFile.getParentDirectory(); }
+
+ bool isPluginClient() const { return getID() == "juce_audio_plugin_client"; }
+
+ static const char* getManifestFileName() { return "juce_module_info"; }
+
+ var moduleInfo;
+ File manifestFile;
+ URL url;
+};
+
+//==============================================================================
+struct ModuleList
+{
+ ModuleList();
+ ModuleList (const ModuleList&);
+
+ const ModuleDescription* getModuleWithID (const String& moduleID) const;
+ StringArray getIDs() const;
+ void sort();
+
+ Result addAllModulesInFolder (const File&);
+ Result scanAllKnownFolders (Project&);
+ bool loadFromWebsite();
+
+ OwnedArray modules;
+};
+
//==============================================================================
class LibraryModule
{
public:
- LibraryModule (const File& file);
- LibraryModule (const var& moduleInfo);
+ LibraryModule (const ModuleDescription&);
- bool isValid() const;
+ bool isValid() const { return moduleInfo.isValid(); }
+ String getID() const { return moduleInfo.getID(); }
+ String getVersion() const { return moduleInfo.getVersion(); }
+ String getName() const { return moduleInfo.getName(); }
+ String getDescription() const { return moduleInfo.getDescription(); }
+ String getLicense() const { return moduleInfo.getLicense(); }
- String getID() const { return moduleInfo ["id"].toString(); }
- String getVersion() const { return moduleInfo ["version"].toString(); }
- String getName() const { return moduleInfo ["name"].toString(); }
- String getDescription() const { return moduleInfo ["description"].toString(); }
- String getLicense() const { return moduleInfo ["license"].toString(); }
- const File& getFolder() const { return moduleFolder; }
+ File getFolder() const { return moduleInfo.getFolder(); }
void writeIncludes (ProjectSaver&, OutputStream&);
void prepareExporter (ProjectExporter&, ProjectSaver&) const;
@@ -52,132 +95,65 @@ public:
void getConfigFlags (Project&, OwnedArray& flags) const;
void getLocalCompiledFiles (const File& localModuleFolder, Array& files) const;
void findBrowseableFiles (const File& localModuleFolder, Array& files) const;
- File getLocalFolderFor (Project&) const;
- static String getInfoFileName() { return "juce_module_info"; }
-
- var moduleInfo;
+ ModuleDescription moduleInfo;
private:
- File moduleFile, moduleFolder;
mutable Array sourceFiles;
- File getInclude (const File& folder) const;
+ File getModuleHeaderFile (const File& folder) const;
static bool fileTargetMatches (ProjectExporter& exporter, const String& target);
- struct FileSorter
- {
- static int compareElements (const File& f1, const File& f2)
- {
- return f1.getFileName().compareIgnoreCase (f2.getFileName());
- }
- };
-
void findWildcardMatches (const File& localModuleFolder, const String& wildcardPath, Array& result) const;
void findAndAddCompiledCode (ProjectExporter&, ProjectSaver&, const File& localModuleFolder, Array& result) const;
- void addBrowsableCode (ProjectExporter&, const Array& compiled, const File& localModuleFolder) const;
+ void addBrowsableCode (ProjectExporter&, ProjectSaver&, const Array& compiled, const File& localModuleFolder) const;
void createLocalHeaderWrapper (ProjectSaver&, const File& originalHeader, const File& localHeader) const;
- RelativePath getModuleRelativeToProject (ProjectExporter&) const;
- RelativePath getModuleOrLocalCopyRelativeToProject (ProjectExporter&, const File& localModuleFolder) const;
- bool isPluginClient() const;
bool isAUPluginHost (const Project&) const;
bool isVSTPluginHost (const Project&) const;
};
-//==============================================================================
-class AvailableModuleList
-{
-public:
- AvailableModuleList();
- AvailableModuleList (const AvailableModuleList&);
- AvailableModuleList& operator= (const AvailableModuleList&);
-
- //==============================================================================
- Result rescan (const File& newModulesFolder);
- void rescan();
- File getModulesFolder() const { return moduleFolder; }
-
- bool loadFromWebsite();
-
- LibraryModule* loadModule (const String& uid) const;
-
- void getDependencies (const String& moduleID, StringArray& dependencies) const;
- void createDependencies (const String& moduleID, OwnedArray& modules) const;
-
- //==============================================================================
- struct Module
- {
- LibraryModule* create() const;
-
- String uid, version, name, description, license;
- File file;
- URL url;
-
- bool operator== (const Module&) const;
- bool operator!= (const Module&) const;
- };
-
- const Module* findModuleInfo (const String& uid) const;
-
- bool operator== (const AvailableModuleList&) const;
-
- //==============================================================================
- static bool isJuceFolder (const File& folder);
- static bool isModulesFolder (const File& folder);
- static bool isJuceOrModulesFolder (const File& folder);
-
- static File getDefaultModulesFolder (Project*);
- static bool isLocalModulesFolderValid();
- static bool isLibraryNewerThanIntrojucer();
-
- static File getLocalModulesFolder (Project*);
- static void setLocalModulesFolder (const File& newFile);
-
- static File getModulesFolderForJuceOrModulesFolder (const File& f);
- static File getModulesFolderForExporter (const ProjectExporter&);
-
- StringArray getExtraDependenciesNeeded (Project&, const Module&);
-
- //==============================================================================
- OwnedArray modules;
-
-private:
- File moduleFolder;
-
- void sort();
-};
-
//==============================================================================
class EnabledModuleList
{
public:
EnabledModuleList (Project&, const ValueTree&);
- EnabledModuleList (const EnabledModuleList&);
bool isModuleEnabled (const String& moduleID) const;
Value shouldShowAllModuleFilesInProject (const String& moduleID);
Value shouldCopyModuleFilesLocally (const String& moduleID);
- void addModule (const String& moduleID, bool shouldCopyFilesLocally);
void removeModule (const String& moduleID);
- void addDefaultModules (bool shouldCopyFilesLocally);
bool isAudioPluginModuleMissing() const;
- void createRequiredModules (const AvailableModuleList& availableModules,
- OwnedArray& modules) const;
+ ModuleDescription getModuleInfo (const String& moduleID);
+
+ File getModuleInfoFile (const String& moduleID);
+ File getModuleFolder (const String& moduleID);
+
+ void addModule (const File& moduleManifestFile, bool copyLocally);
+ void addModuleInteractive (const String& moduleID);
+ void addModuleFromUserSelectedFile();
+ void addModuleOfferingToCopy (const File&);
+
+ StringArray getAllModules() const;
+ StringArray getExtraDependenciesNeeded (const String& moduleID) const;
+ void createRequiredModules (OwnedArray& modules);
int getNumModules() const { return state.getNumChildren(); }
String getModuleID (int index) const { return state.getChild (index) [Ids::ID].toString(); }
- static const Identifier modulesGroupTag, moduleTag;
+ bool areMostModulesCopiedLocally() const;
+ void sortAlphabetically();
+
+ static File findDefaultModulesFolder (Project&);
-private:
Project& project;
ValueTree state;
+private:
UndoManager* getUndoManager() const { return project.getUndoManagerFor (state); }
- EnabledModuleList& operator= (const EnabledModuleList&) JUCE_DELETED_FUNCTION;
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EnabledModuleList)
};
diff --git a/extras/Introjucer/Source/Project/jucer_ModulesPanel.h b/extras/Introjucer/Source/Project/jucer_ModulesPanel.h
index 49723722b0..af60c871db 100644
--- a/extras/Introjucer/Source/Project/jucer_ModulesPanel.h
+++ b/extras/Introjucer/Source/Project/jucer_ModulesPanel.h
@@ -22,493 +22,442 @@
==============================================================================
*/
-#ifndef __JUCER_MODULESPANEL_JUCEHEADER__
-#define __JUCER_MODULESPANEL_JUCEHEADER__
-
-class ModulesPanel : public PropertyComponent,
- public FilenameComponentListener,
- public ButtonListener
+class ModulesPanel : public Component,
+ private TableListBoxModel,
+ private ValueTree::Listener,
+ private Button::Listener
{
public:
ModulesPanel (Project& p)
- : PropertyComponent ("Modules", 500),
- project (p),
- modulesLocation ("modules", AvailableModuleList::getLocalModulesFolder (&project),
- true, true, false, "*", String::empty,
- "Select a folder containing your JUCE modules..."),
- modulesLabel (String::empty, "Module source folder:"),
- updateModulesButton ("Check for module updates..."),
- moduleListBox (moduleList),
- copyingMessage (p, moduleList)
+ : project (p),
+ modulesValueTree (p.getModules().state),
+ addWebModuleButton ("Download and add a module..."),
+ updateModuleButton ("Install updates to modules...")
{
- moduleList.rescan (AvailableModuleList::getLocalModulesFolder (&project));
+ table.getHeader().addColumn ("Module", nameCol, 180, 100, 400, TableHeaderComponent::notSortable);
+ table.getHeader().addColumn ("Installed Version", versionCol, 100, 100, 100, TableHeaderComponent::notSortable);
+ table.getHeader().addColumn ("Available Version", updateCol, 100, 100, 100, TableHeaderComponent::notSortable);
+ table.getHeader().addColumn ("Make Local Copy", copyCol, 100, 100, 100, TableHeaderComponent::notSortable);
+ table.getHeader().addColumn ("Paths", pathCol, 250, 100, 600, TableHeaderComponent::notSortable);
- addAndMakeVisible (&modulesLocation);
- modulesLocation.addListener (this);
+ table.setModel (this);
+ table.setColour (TableListBox::backgroundColourId, Colours::transparentBlack);
+ addAndMakeVisible (&table);
+ table.updateContent();
+ table.setRowHeight (20);
- modulesLabel.attachToComponent (&modulesLocation, true);
+ addAndMakeVisible (&addWebModuleButton);
+ addAndMakeVisible (&updateModuleButton);
+ addWebModuleButton.addListener (this);
+ updateModuleButton.addListener (this);
+ updateModuleButton.setEnabled (false);
- addAndMakeVisible (&updateModulesButton);
- updateModulesButton.addListener (this);
-
- moduleListBox.setOwner (this);
- addAndMakeVisible (&moduleListBox);
-
- addAndMakeVisible (©ingMessage);
- copyingMessage.refresh();
+ modulesValueTree.addListener (this);
+ lookAndFeelChanged();
}
- void filenameComponentChanged (FilenameComponent*)
+ void paint (Graphics& g) override
{
- moduleList.rescan (modulesLocation.getCurrentFile());
- modulesLocation.setCurrentFile (moduleList.getModulesFolder(), false, dontSendNotification);
- AvailableModuleList::setLocalModulesFolder (moduleList.getModulesFolder());
- moduleListBox.refresh();
+ if (webUpdateThread == nullptr)
+ webUpdateThread = new WebsiteUpdateFetchThread (*this);
+
+ IntrojucerLookAndFeel::fillWithBackgroundTexture (*this, g);
}
- void buttonClicked (Button*)
+ void resized() override
{
- JuceUpdater::show (moduleList, getTopLevelComponent(), "");
+ Rectangle r (getLocalBounds().reduced (5, 4));
- filenameComponentChanged (nullptr);
+ table.setBounds (r.removeFromTop (table.getRowPosition (getNumRows() - 1, true).getBottom() + 20));
+
+ Rectangle buttonRow (r.removeFromTop (32).removeFromBottom (28));
+ addWebModuleButton.setBounds (buttonRow.removeFromLeft (jmin (260, r.getWidth() / 2)));
+ buttonRow.removeFromLeft (8);
+ updateModuleButton.setBounds (buttonRow.removeFromLeft (jmin (260, r.getWidth() / 2)));
}
- bool isEnabled (const AvailableModuleList::Module* m) const
+ int getNumRows() override
{
- return project.getModules().isModuleEnabled (m->uid);
+ return project.getModules().getNumModules();
}
- void setEnabled (const AvailableModuleList::Module* m, bool enable)
+ void paintRowBackground (Graphics& g, int /*rowNumber*/, int width, int height, bool rowIsSelected) override
{
- if (enable)
- project.getModules().addModule (m->uid, true);
- else
- project.getModules().removeModule (m->uid);
-
- refresh();
+ g.setColour (rowIsSelected ? Colours::lightblue.withAlpha (0.4f)
+ : Colours::white.withAlpha (0.4f));
+ g.fillRect (0, 0, width, height - 1);
}
- bool areDependenciesMissing (const AvailableModuleList::Module* m)
+ void paintCell (Graphics& g, int rowNumber, int columnId, int width, int height, bool rowIsSelected) override
{
- return moduleList.getExtraDependenciesNeeded (project, *m).size() > 0;
- }
+ String text;
+ const String moduleID (project.getModules().getModuleID (rowNumber));
- void selectionChanged (const AvailableModuleList::Module* selectedModule)
- {
- settings = nullptr;
-
- if (selectedModule != nullptr)
- addAndMakeVisible (settings = new ModuleSettingsPanel (project, moduleList, selectedModule->uid));
-
- copyingMessage.refresh();
- resized();
- }
-
- void refresh()
- {
- moduleListBox.refresh();
-
- if (settings != nullptr)
- settings->refreshAll();
-
- copyingMessage.refresh();
- }
-
- void paint (Graphics& g) // (overridden to avoid drawing the name)
- {
- getLookAndFeel().drawPropertyComponentBackground (g, getWidth(), getHeight(), *this);
- }
-
- void resized()
- {
- modulesLocation.setBounds (150, 3, getWidth() - 180 - 150, 25);
- updateModulesButton.setBounds (modulesLocation.getRight() + 6, 3, getWidth() - modulesLocation.getRight() - 12, 25);
- moduleListBox.setBounds (5, 34, getWidth() / 3, getHeight() - 72);
- copyingMessage.setBounds (5, moduleListBox.getBottom() + 2, getWidth() - 10, getHeight() - moduleListBox.getBottom() - 4);
-
- if (settings != nullptr)
- settings->setBounds (moduleListBox.getRight() + 5, moduleListBox.getY(),
- getWidth() - moduleListBox.getRight() - 9, moduleListBox.getHeight());
- }
-
- //==============================================================================
- class ModuleSelectionListBox : public ListBox,
- public ListBoxModel
- {
- public:
- ModuleSelectionListBox (AvailableModuleList& ml)
- : list (ml), owner (nullptr)
+ if (columnId == nameCol)
{
- setColour (ListBox::backgroundColourId, Colours::white.withAlpha (0.4f));
- setTooltip ("Use this list to select which modules should be included in your app.\n"
- "Any modules which have missing dependencies will be shown in red.");
+ text = moduleID;
}
-
- void setOwner (ModulesPanel* newOwner)
+ else if (columnId == versionCol)
{
- owner = newOwner;
- setModel (this);
+ text = project.getModules().getModuleInfo (moduleID).getVersion();
+
+ if (text.isEmpty())
+ text = "?";
}
-
- void refresh()
+ else if (columnId == updateCol)
{
- updateContent();
- repaint();
- }
-
- int getNumRows()
- {
- return list.modules.size();
- }
-
- void paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected)
- {
- if (rowIsSelected)
- g.fillAll (findColour (TextEditor::highlightColourId));
-
- if (const AvailableModuleList::Module* const m = list.modules [rowNumber])
+ if (listFromWebsite != nullptr)
{
- const float tickSize = height * 0.7f;
-
- getLookAndFeel().drawTickBox (g, *this, (height - tickSize) / 2, (height - tickSize) / 2, tickSize, tickSize,
- owner->isEnabled (m), true, false, false);
-
- if (owner->isEnabled (m) && owner->areDependenciesMissing (m))
- g.setColour (Colours::red);
- else
- g.setColour (Colours::black);
-
- g.setFont (Font (height * 0.7f, Font::bold));
- g.drawFittedText (m->uid, height, 0, width - height, height, Justification::centredLeft, 1);
- }
- }
-
- void listBoxItemClicked (int row, const MouseEvent& e)
- {
- if (e.x < getRowHeight())
- flipRow (row);
- }
-
- void listBoxItemDoubleClicked (int row, const MouseEvent&)
- {
- flipRow (row);
- }
-
- void returnKeyPressed (int row)
- {
- flipRow (row);
- }
-
- void selectedRowsChanged (int row)
- {
- owner->selectionChanged (list.modules [row]);
- }
-
- void flipRow (int row)
- {
- if (const AvailableModuleList::Module* const m = list.modules [row])
- owner->setEnabled (m, ! owner->isEnabled (m));
- }
-
- private:
- AvailableModuleList& list;
- ModulesPanel* owner;
- };
-
- //==============================================================================
- class ModuleSettingsPanel : public PropertyPanel
- {
- public:
- ModuleSettingsPanel (Project& p, AvailableModuleList& list, const String& modID)
- : project (p), moduleList (list), moduleID (modID)
- {
- refreshAll();
- }
-
- void refreshAll()
- {
- setEnabled (project.getModules().isModuleEnabled (moduleID));
-
- clear();
- PropertyListBuilder props;
-
- ScopedPointer module (moduleList.loadModule (moduleID));
-
- if (module != nullptr)
- {
- props.add (new ModuleInfoComponent (moduleList, moduleID));
-
- if (project.getModules().isModuleEnabled (moduleID))
+ if (const ModuleDescription* m = listFromWebsite->getModuleWithID (moduleID))
{
- if (const AvailableModuleList::Module* m = moduleList.findModuleInfo (moduleID))
- if (moduleList.getExtraDependenciesNeeded (project, *m).size() > 0)
- props.add (new MissingDependenciesComponent (project, moduleList, moduleID));
- }
-
- props.add (new BooleanPropertyComponent (project.getModules().shouldShowAllModuleFilesInProject (moduleID),
- "Add source to project", "Make module files browsable in projects"),
- "If this is enabled, then the entire source tree from this module will be shown inside your project, "
- "making it easy to browse/edit the module's classes. If disabled, then only the minimum number of files "
- "required to compile it will appear inside your project.");
-
- props.add (new BooleanPropertyComponent (project.getModules().shouldCopyModuleFilesLocally (moduleID),
- "Create local copy", "Copy the module into the project folder"),
- "If this is enabled, then a local copy of the entire module will be made inside your project (in the auto-generated JuceLibraryFiles folder), "
- "so that your project will be self-contained, and won't need to contain any references to files in other folders. "
- "This also means that you can check the module into your source-control system to make sure it is always in sync with your own code.");
-
- StringArray possibleValues;
- possibleValues.add ("(Use Default)");
- possibleValues.add ("Enabled");
- possibleValues.add ("Disabled");
-
- Array mappings;
- mappings.add (Project::configFlagDefault);
- mappings.add (Project::configFlagEnabled);
- mappings.add (Project::configFlagDisabled);
-
- OwnedArray configFlags;
- module->getConfigFlags (project, configFlags);
-
- for (int i = 0; i < configFlags.size(); ++i)
- {
- ChoicePropertyComponent* c = new ChoicePropertyComponent (configFlags[i]->value,
- configFlags[i]->symbol,
- possibleValues, mappings);
- c->setTooltip (configFlags[i]->description);
- props.add (c);
- }
- }
-
- addProperties (props.components);
- }
-
- private:
- Project& project;
- AvailableModuleList& moduleList;
- String moduleID;
-
- //==============================================================================
- class ModuleInfoComponent : public PropertyComponent
- {
- public:
- ModuleInfoComponent (AvailableModuleList& list, const String& modID)
- : PropertyComponent ("Module", 100), moduleList (list), moduleID (modID)
- {
- }
-
- void refresh() {}
-
- void paint (Graphics& g)
- {
- g.setColour (Colours::white.withAlpha (0.4f));
- g.fillRect (0, 0, getWidth(), getHeight() - 1);
-
- if (const AvailableModuleList::Module* module = moduleList.findModuleInfo (moduleID))
- {
- AttributedString s;
- s.setJustification (Justification::topLeft);
-
- Font f (13.0f);
-
- s.append (module->name + "\n", f.boldened());
- s.append ("Version: " + module->version
- + " License: " + module->license + "\n", f.italicised());
- s.append ("\n" + module->description, f);
-
- s.draw (g, getLocalBounds().reduced (4, 2).toFloat());
- }
- }
-
- private:
- AvailableModuleList& moduleList;
- String moduleID;
-
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ModuleInfoComponent)
- };
-
- //==============================================================================
- class MissingDependenciesComponent : public PropertyComponent,
- public ButtonListener
- {
- public:
- MissingDependenciesComponent (Project& p, AvailableModuleList& list, const String& modID)
- : PropertyComponent ("Dependencies", 100),
- project (p), moduleList (list), moduleID (modID),
- fixButton ("Enable Required Modules")
- {
- if (const AvailableModuleList::Module* module = moduleList.findModuleInfo (moduleID))
- missingDependencies = moduleList.getExtraDependenciesNeeded (project, *module);
-
- addAndMakeVisible (&fixButton);
- fixButton.setColour (TextButton::buttonColourId, Colours::red);
- fixButton.setColour (TextButton::textColourOffId, Colours::white);
- fixButton.addListener (this);
- }
-
- void refresh() {}
-
- void paint (Graphics& g)
- {
- g.setColour (Colours::white.withAlpha (0.4f));
- g.fillRect (0, 0, getWidth(), getHeight() - 1);
-
- String text ("This module requires the following dependencies:\n");
- text << missingDependencies.joinIntoString (", ");
-
- AttributedString s;
- s.setJustification (Justification::topLeft);
- s.append (text, Font (13.0f), Colours::red);
- s.draw (g, getLocalBounds().reduced (4, 16).toFloat());
- }
-
- void buttonClicked (Button*)
- {
- bool isModuleCopiedLocally = project.getModules().shouldCopyModuleFilesLocally (moduleID).getValue();
-
- for (int i = missingDependencies.size(); --i >= 0;)
- project.getModules().addModule (missingDependencies[i], isModuleCopiedLocally);
-
- if (ModulesPanel* mp = findParentComponentOfClass())
- mp->refresh();
- }
-
- void resized()
- {
- fixButton.setBounds (getWidth() - 168, getHeight() - 26, 160, 22);
- }
-
- private:
- Project& project;
- AvailableModuleList& moduleList;
- String moduleID;
- StringArray missingDependencies;
- TextButton fixButton;
-
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MissingDependenciesComponent)
- };
- };
-
- //==============================================================================
- class ModuleCopyingInfo : public Component,
- public ButtonListener,
- public Timer
- {
- public:
- ModuleCopyingInfo (Project& p, AvailableModuleList& modules)
- : project (p), list (modules),
- copyModeButton ("Set Copying Mode...")
- {
- addAndMakeVisible (©ModeButton);
- copyModeButton.addListener (this);
-
- startTimer (1500);
- }
-
- void paint (Graphics& g)
- {
- g.setFont (11.0f);
- g.setColour (Colours::darkred);
- g.drawFittedText (getName(), copyModeButton.getRight() + 10, 0,
- getWidth() - copyModeButton.getRight() - 16, getHeight(),
- Justification::centredRight, 4);
- }
-
- void resized()
- {
- copyModeButton.setBounds (0, getHeight() / 2 - 10, 160, 20);
- }
-
- void refresh()
- {
- int numCopied, numNonCopied;
- countCopiedModules (numCopied, numNonCopied);
-
- String newName;
-
- if (numCopied > 0 && numNonCopied > 0)
- newName = "Warning! Some of your modules are set to use local copies, and others are using remote references.\n"
- "This may create problems if some modules expect to share the same parent folder, so you may "
- "want to make sure that they are all either copied or not.";
-
- if (project.getModules().isAudioPluginModuleMissing())
- newName = "Warning! Your project is an audio plugin, but you haven't enabled the 'juce_audio_plugin_client' module!";
-
- if (newName != getName())
- {
- setName (newName);
- repaint();
- }
- }
-
- void countCopiedModules (int& numCopied, int& numNonCopied)
- {
- numCopied = numNonCopied = 0;
-
- for (int i = list.modules.size(); --i >= 0;)
- {
- const String moduleID (list.modules.getUnchecked(i)->uid);
-
- if (project.getModules().isModuleEnabled (moduleID))
- {
- if (project.getModules().shouldCopyModuleFilesLocally (moduleID).getValue())
- ++numCopied;
+ if (m->getVersion() != project.getModules().getModuleInfo (moduleID).getVersion())
+ text = m->getVersion() + " available";
else
- ++numNonCopied;
+ text = "Up-to-date";
}
+ else
+ text = "?";
}
- }
-
- void buttonClicked (Button*)
- {
- PopupMenu menu;
- menu.addItem (1, "Enable local copying for all modules");
- menu.addItem (2, "Disable local copying for all modules");
-
- menu.showMenuAsync (PopupMenu::Options().withTargetComponent (©ModeButton),
- ModalCallbackFunction::forComponent (copyMenuItemChosen, this));
- }
-
- static void copyMenuItemChosen (int resultCode, ModuleCopyingInfo* comp)
- {
- if (resultCode > 0 && comp != nullptr)
- comp->setCopyModeForAllModules (resultCode == 1);
- }
-
- void setCopyModeForAllModules (bool copyEnabled)
- {
- for (int i = list.modules.size(); --i >= 0;)
+ else
{
- const String moduleID (list.modules.getUnchecked(i)->uid);
-
- if (project.getModules().isModuleEnabled (moduleID))
- project.getModules().shouldCopyModuleFilesLocally (moduleID) = copyEnabled;
+ text = "-";
}
-
- refresh();
}
-
- void timerCallback() override
+ else if (columnId == copyCol)
{
- refresh();
+ text = project.getModules().shouldCopyModuleFilesLocally (moduleID).getValue()
+ ? "Yes" : "No";
+ }
+ else if (columnId == pathCol)
+ {
+ StringArray paths;
+
+ for (Project::ExporterIterator exporter (project); exporter.next();)
+ paths.addIfNotAlreadyThere (exporter->getPathForModuleString (moduleID).trim());
+
+ text = paths.joinIntoString (", ");
}
- private:
- Project& project;
- AvailableModuleList& list;
- TextButton copyModeButton;
- };
+ g.setColour (Colours::black);
+ g.setFont (height * 0.65f);
+ g.drawText (text, Rectangle (width, height).reduced (4, 0), Justification::centredLeft, true);
+ }
+
+ void cellDoubleClicked (int rowNumber, int, const MouseEvent&) override
+ {
+ const String moduleID (project.getModules().getModuleID (rowNumber));
+
+ if (moduleID.isNotEmpty())
+ if (ProjectContentComponent* pcc = findParentComponentOfClass())
+ pcc->showModule (moduleID);
+ }
+
+ void deleteKeyPressed (int row) override
+ {
+ project.getModules().removeModule (project.getModules().getModuleID (row));
+ }
+
+ void webUpdateFinished (const ModuleList& newList)
+ {
+ listFromWebsite = new ModuleList (newList);
+ webUpdateThread = nullptr;
+
+ table.updateContent();
+ table.repaint();
+
+ updateModuleButton.setEnabled (getUpdatableModules().size() != 0);
+ }
+
+ void buttonClicked (Button* b)
+ {
+ if (b == &addWebModuleButton)
+ showAddModuleMenu();
+ else if (b == &updateModuleButton)
+ showUpdateModulesMenu();
+ }
private:
+ enum
+ {
+ nameCol = 1,
+ versionCol,
+ updateCol,
+ copyCol,
+ pathCol
+ };
+
Project& project;
- AvailableModuleList moduleList;
- FilenameComponent modulesLocation;
- Label modulesLabel;
- TextButton updateModulesButton;
- ModuleSelectionListBox moduleListBox;
- ModuleCopyingInfo copyingMessage;
- ScopedPointer settings;
+ ValueTree modulesValueTree;
+ TableListBox table;
+ TextButton addWebModuleButton, updateModuleButton;
+ ScopedPointer listFromWebsite;
+
+ void valueTreePropertyChanged (ValueTree&, const Identifier&) override { itemChanged(); }
+ void valueTreeChildAdded (ValueTree&, ValueTree&) override { itemChanged(); }
+ void valueTreeChildRemoved (ValueTree&, ValueTree&) override { itemChanged(); }
+ void valueTreeChildOrderChanged (ValueTree&) override { itemChanged(); }
+ void valueTreeParentChanged (ValueTree&) override { itemChanged(); }
+
+ void itemChanged()
+ {
+ table.updateContent();
+ resized();
+ repaint();
+ }
+
+ StringArray getUpdatableModules() const
+ {
+ StringArray result;
+
+ if (listFromWebsite != nullptr)
+ {
+ for (int i = 0; i < listFromWebsite->modules.size(); ++i)
+ {
+ const ModuleDescription* m = listFromWebsite->modules.getUnchecked(i);
+ const String v1 (m->getVersion());
+ const String v2 (project.getModules().getModuleInfo (m->getID()).getVersion());
+
+ if (v1 != v2 && v1.isNotEmpty() && v2.isNotEmpty())
+ result.add (m->getID());
+ }
+ }
+
+ return result;
+ }
+
+ StringArray getAddableModules() const
+ {
+ StringArray result;
+
+ if (listFromWebsite != nullptr)
+ {
+ for (int i = 0; i < listFromWebsite->modules.size(); ++i)
+ {
+ const ModuleDescription* m = listFromWebsite->modules.getUnchecked(i);
+
+ if (! project.getModules().isModuleEnabled (m->getID()))
+ result.add (m->getID());
+ }
+ }
+
+ return result;
+ }
+
+ void showUpdateModulesMenu()
+ {
+ StringArray mods (getUpdatableModules());
+
+ PopupMenu m;
+ m.addItem (1000, "Update all modules");
+ m.addSeparator();
+
+ for (int i = 0; i < mods.size(); ++i)
+ m.addItem (1 + i, "Update " + mods[i]);
+
+ int res = m.showAt (&updateModuleButton);
+
+ if (res > 0 && listFromWebsite != nullptr)
+ {
+ if (res != 1000)
+ mods = StringArray (mods[res - 1]);
+
+ Array modsToUpdate;
+
+ for (int i = 0; i < mods.size(); ++i)
+ {
+ if (const ModuleDescription* md = listFromWebsite->getModuleWithID (mods[i]))
+ {
+ ModuleDescription modToUpdate (*md);
+ modToUpdate.manifestFile = project.getModules().getModuleInfo (modToUpdate.getID()).manifestFile;
+ modsToUpdate.add (modToUpdate);
+ }
+ }
+
+ DownloadAndInstallThread::updateModulesFromWeb (project, modsToUpdate);
+ }
+ }
+
+ void showAddModuleMenu()
+ {
+ if (listFromWebsite == nullptr)
+ {
+ AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
+ "Couldn't contact the website!",
+ "Failed to get the latest module list from juce.com - "
+ "maybe network or server problems - try again soon!");
+ return;
+ }
+
+ StringArray mods (getAddableModules());
+
+ if (mods.size() == 0)
+ {
+ AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
+ "No modules to add!",
+ "Couldn't find any new modules that aren't already in your project!");
+ return;
+ }
+
+ PopupMenu m;
+
+ for (int i = 0; i < mods.size(); ++i)
+ m.addItem (i + 1, "Install " + mods[i]);
+
+ int res = m.showAt (&addWebModuleButton);
+
+ if (res > 0 && listFromWebsite != nullptr)
+ if (const ModuleDescription* md = listFromWebsite->getModuleWithID (mods[res - 1]))
+ DownloadAndInstallThread::addModuleFromWebsite (project, *md);
+ }
+
+ struct WebsiteUpdateFetchThread : private Thread,
+ private AsyncUpdater
+ {
+ WebsiteUpdateFetchThread (ModulesPanel& p) : Thread ("Web Updater"), panel (p)
+ {
+ startThread (3);
+ }
+
+ ~WebsiteUpdateFetchThread()
+ {
+ stopThread (15000);
+ }
+
+ void run() override
+ {
+ if (list.loadFromWebsite() && ! threadShouldExit())
+ triggerAsyncUpdate();
+ }
+
+ void handleAsyncUpdate() override
+ {
+ panel.webUpdateFinished (list);
+ }
+
+ private:
+ ModuleList list;
+ ModulesPanel& panel;
+ };
+
+ ScopedPointer webUpdateThread;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ModulesPanel)
};
-#endif // __JUCER_MODULESPANEL_JUCEHEADER__
+//==============================================================================
+class DownloadAndInstallThread : public ThreadWithProgressWindow
+{
+public:
+ DownloadAndInstallThread (const Array& modulesToInstall)
+ : ThreadWithProgressWindow ("Installing New Modules", true, true),
+ result (Result::ok()),
+ modules (modulesToInstall)
+ {
+ }
+
+ static void updateModulesFromWeb (Project& project, const Array& mods)
+ {
+ DownloadAndInstallThread d (mods);
+
+ if (d.runThread())
+ {
+ if (d.result.failed())
+ {
+ AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
+ "Module Install Failed",
+ d.result.getErrorMessage());
+ }
+ else
+ {
+ for (int i = 0; i < d.modules.size(); ++i)
+ project.getModules().addModule (d.modules.getReference(i).manifestFile,
+ project.getModules().areMostModulesCopiedLocally());
+ }
+ }
+ }
+
+ static void addModuleFromWebsite (Project& project, const ModuleDescription& module)
+ {
+ Array mods;
+ mods.add (module);
+
+ static File lastLocation (EnabledModuleList::findDefaultModulesFolder (project));
+
+ FileChooser fc ("Select the parent folder for the new module...", lastLocation, String::empty, false);
+
+ if (fc.browseForDirectory())
+ {
+ lastLocation = fc.getResult();
+
+ if (lastLocation.getChildFile (ModuleDescription::getManifestFileName()).exists())
+ {
+ AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
+ "Adding Module",
+ "You chose a folder that appears to be a module.\n\n"
+ "You need to select the *parent* folder inside which the new modules will be created.");
+ return;
+ }
+
+ for (int i = 0; i < mods.size(); ++i)
+ mods.getReference(i).manifestFile = lastLocation.getChildFile (mods.getReference(i).getID())
+ .getChildFile (ModuleDescription::getManifestFileName());
+
+ updateModulesFromWeb (project, mods);
+ }
+ }
+
+ void run() override
+ {
+ for (int i = 0; i < modules.size(); ++i)
+ {
+ const ModuleDescription& m = modules.getReference(i);
+
+ setProgress (i / (double) modules.size());
+
+ MemoryBlock downloaded;
+ result = download (m, downloaded);
+
+ if (result.failed() || threadShouldExit())
+ break;
+
+ result = unzip (m, downloaded);
+
+ if (result.failed() || threadShouldExit())
+ break;
+ }
+ }
+
+ Result download (const ModuleDescription& m, MemoryBlock& dest)
+ {
+ setStatusMessage ("Downloading " + m.getID() + "...");
+
+ const ScopedPointer in (m.url.createInputStream (false, nullptr, nullptr, String::empty, 10000));
+
+ if (in != nullptr && in->readIntoMemoryBlock (dest))
+ return Result::ok();
+
+ return Result::fail ("Failed to download from: " + m.url.toString (false));
+ }
+
+ Result unzip (const ModuleDescription& m, const MemoryBlock& data)
+ {
+ setStatusMessage ("Installing " + m.getID() + "...");
+
+ MemoryInputStream input (data, false);
+ ZipFile zip (input);
+
+ if (zip.getNumEntries() == 0)
+ return Result::fail ("The downloaded file wasn't a valid module file!");
+
+ if (! m.getFolder().deleteRecursively())
+ return Result::fail ("Couldn't delete the existing folder:\n" + m.getFolder().getFullPathName());
+
+ return zip.uncompressTo (m.getFolder().getParentDirectory(), true);
+ }
+
+ Result result;
+ Array modules;
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DownloadAndInstallThread)
+};
diff --git a/extras/Introjucer/Source/Project/jucer_NewProjectWizard.cpp b/extras/Introjucer/Source/Project/jucer_NewProjectWizard.cpp
index cd1b430329..f2091adcf7 100644
--- a/extras/Introjucer/Source/Project/jucer_NewProjectWizard.cpp
+++ b/extras/Introjucer/Source/Project/jucer_NewProjectWizard.cpp
@@ -98,6 +98,29 @@ struct NewProjectWizardClasses
virtual bool initialiseProject (Project& project) = 0;
+ virtual StringArray getDefaultModules()
+ {
+ const char* mods[] =
+ {
+ "juce_core",
+ "juce_events",
+ "juce_graphics",
+ "juce_data_structures",
+ "juce_gui_basics",
+ "juce_gui_extra",
+ "juce_cryptography",
+ "juce_video",
+ "juce_opengl",
+ "juce_audio_basics",
+ "juce_audio_devices",
+ "juce_audio_formats",
+ "juce_audio_processors",
+ nullptr
+ };
+
+ return StringArray (mods);
+ }
+
String appTitle;
File targetFolder, projectFile;
Component* ownerWindow;
@@ -131,7 +154,7 @@ struct NewProjectWizardClasses
.withFileExtension (Project::projectFileExtension);
ScopedPointer project (new Project (projectFile));
- project->getModules().addDefaultModules (true);
+ addDefaultModules (*project);
if (failedFiles.size() == 0)
{
@@ -150,11 +173,11 @@ struct NewProjectWizardClasses
if (failedFiles.size() > 0)
{
- AlertWindow::showMessageBox (AlertWindow::WarningIcon,
- TRANS("Errors in Creating Project!"),
- TRANS("The following files couldn't be written:")
- + "\n\n"
- + failedFiles.joinIntoString ("\n", 0, 10));
+ AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
+ TRANS("Errors in Creating Project!"),
+ TRANS("The following files couldn't be written:")
+ + "\n\n"
+ + failedFiles.joinIntoString ("\n", 0, 10));
return nullptr;
}
@@ -172,6 +195,18 @@ struct NewProjectWizardClasses
if (! getSourceFilesFolder().createDirectory())
failedFiles.add (getSourceFilesFolder().getFullPathName());
}
+
+ void addDefaultModules (Project& project)
+ {
+ StringArray mods (getDefaultModules());
+
+ ModuleList list;
+ list.scanAllKnownFolders (project);
+
+ for (int i = 0; i < mods.size(); ++i)
+ if (const ModuleDescription* info = list.getModuleWithID (mods[i]))
+ project.getModules().addModule (info->manifestFile, true);
+ }
};
//==============================================================================
@@ -342,10 +377,17 @@ struct NewProjectWizardClasses
{
AudioPluginAppWizard() {}
- String getName() { return TRANS("Audio Plug-In"); }
- String getDescription() { return TRANS("Creates an audio plugin project"); }
+ String getName() override { return TRANS("Audio Plug-In"); }
+ String getDescription() override { return TRANS("Creates an audio plugin project"); }
- bool initialiseProject (Project& project)
+ StringArray getDefaultModules() override
+ {
+ StringArray s (NewProjectWizard::getDefaultModules());
+ s.add ("juce_audio_plugin_client");
+ return s;
+ }
+
+ bool initialiseProject (Project& project) override
{
createSourceFolder();
@@ -359,7 +401,6 @@ struct NewProjectWizardClasses
File editorHFile = editorCppFile.withFileExtension (".h");
project.getProjectTypeValue() = ProjectType::getAudioPluginTypeName();
- project.getModules().addModule ("juce_audio_plugin_client", true);
Project::Item sourceGroup (createSourceGroup (project));
project.getConfigFlag ("JUCE_QUICKTIME") = Project::configFlagDisabled; // disabled because it interferes with RTAS build on PC
@@ -419,10 +460,10 @@ struct NewProjectWizardClasses
{
StaticLibraryWizard() {}
- String getName() { return TRANS("Static Library"); }
- String getDescription() { return TRANS("Creates a static library"); }
+ String getName() override { return TRANS("Static Library"); }
+ String getDescription() override { return TRANS("Creates a static library"); }
- bool initialiseProject (Project& project)
+ bool initialiseProject (Project& project) override
{
createSourceFolder();
project.getProjectTypeValue() = ProjectType::getStaticLibTypeName();
@@ -439,10 +480,10 @@ struct NewProjectWizardClasses
{
DynamicLibraryWizard() {}
- String getName() { return TRANS("Dynamic Library"); }
- String getDescription() { return TRANS("Creates a dynamic library"); }
+ String getName() override { return TRANS("Dynamic Library"); }
+ String getDescription() override { return TRANS("Creates a dynamic library"); }
- bool initialiseProject (Project& project)
+ bool initialiseProject (Project& project) override
{
createSourceFolder();
project.getProjectTypeValue() = ProjectType::getDynamicLibTypeName();
@@ -509,12 +550,12 @@ struct NewProjectWizardClasses
updateCreateButton();
}
- void paint (Graphics& g)
+ void paint (Graphics& g) override
{
g.fillAll (Colour::greyLevel (0.93f));
}
- void buttonClicked (Button* b)
+ void buttonClicked (Button* b) override
{
if (b == &createButton)
{
@@ -564,12 +605,12 @@ struct NewProjectWizardClasses
wizard->addSetupItems (*this, customItems);
}
- void comboBoxChanged (ComboBox*)
+ void comboBoxChanged (ComboBox*) override
{
updateCustomItems();
}
- void textEditorTextChanged (TextEditor&)
+ void textEditorTextChanged (TextEditor&) override
{
updateCreateButton();
diff --git a/extras/Introjucer/Source/Project/jucer_Project.cpp b/extras/Introjucer/Source/Project/jucer_Project.cpp
index 1fcd985bdd..30c2b1ef71 100644
--- a/extras/Introjucer/Source/Project/jucer_Project.cpp
+++ b/extras/Introjucer/Source/Project/jucer_Project.cpp
@@ -29,31 +29,18 @@
#include "../Application/jucer_OpenDocumentManager.h"
#include "../Application/jucer_Application.h"
-
-//==============================================================================
-namespace Tags
-{
- const Identifier projectRoot ("JUCERPROJECT");
- const Identifier projectMainGroup ("MAINGROUP");
- const Identifier group ("GROUP");
- const Identifier file ("FILE");
- const Identifier exporters ("EXPORTFORMATS");
- const Identifier configGroup ("JUCEOPTIONS");
-}
-
-const char* Project::projectFileExtension = ".jucer";
-
//==============================================================================
Project::Project (const File& f)
: FileBasedDocument (projectFileExtension,
String ("*") + projectFileExtension,
"Choose a Jucer project to load",
"Save Jucer project"),
- projectRoot (Tags::projectRoot)
+ projectRoot (Ids::JUCERPROJECT)
{
Logger::writeToLog ("Loading project: " + f.getFullPathName());
setFile (f);
removeDefunctExporters();
+ updateOldModulePaths();
setMissingDefaultValues();
setChangedFlag (false);
@@ -67,6 +54,8 @@ Project::~Project()
IntrojucerApp::getApp().openDocumentManager.closeAllDocumentsUsingProject (*this, false);
}
+const char* Project::projectFileExtension = ".jucer";
+
//==============================================================================
void Project::setTitle (const String& newTitle)
{
@@ -76,7 +65,7 @@ void Project::setTitle (const String& newTitle)
String Project::getTitle() const
{
- return projectRoot.getChildWithName (Tags::projectMainGroup) [Ids::name];
+ return projectRoot.getChildWithName (Ids::MAINGROUP) [Ids::name];
}
String Project::getDocumentTitle()
@@ -96,9 +85,9 @@ void Project::setMissingDefaultValues()
projectRoot.setProperty (Ids::ID, createAlphaNumericUID(), nullptr);
// Create main file group if missing
- if (! projectRoot.getChildWithName (Tags::projectMainGroup).isValid())
+ if (! projectRoot.getChildWithName (Ids::MAINGROUP).isValid())
{
- Item mainGroup (*this, ValueTree (Tags::projectMainGroup));
+ Item mainGroup (*this, ValueTree (Ids::MAINGROUP));
projectRoot.addChild (mainGroup.state, 0, 0);
}
@@ -119,8 +108,7 @@ void Project::setMissingDefaultValues()
getProjectType().setMissingProjectProperties (*this);
- if (! projectRoot.getChildWithName (EnabledModuleList::modulesGroupTag).isValid())
- getModules().addDefaultModules (false);
+ getModules().sortAlphabetically();
if (getBundleIdentifier().toString().isEmpty())
getBundleIdentifier() = getDefaultBundleIdentifier();
@@ -133,7 +121,7 @@ void Project::setMissingDefaultValues()
void Project::updateOldStyleConfigList()
{
- ValueTree deprecatedConfigsList (projectRoot.getChildWithName (ProjectExporter::configurations));
+ ValueTree deprecatedConfigsList (projectRoot.getChildWithName (Ids::CONFIGURATIONS));
if (deprecatedConfigsList.isValid())
{
@@ -176,7 +164,7 @@ void Project::moveOldPropertyFromProjectToAllExporters (Identifier name)
void Project::removeDefunctExporters()
{
- ValueTree exporters (projectRoot.getChildWithName (Tags::exporters));
+ ValueTree exporters (projectRoot.getChildWithName (Ids::EXPORTFORMATS));
for (;;)
{
@@ -189,18 +177,69 @@ void Project::removeDefunctExporters()
}
}
-File Project::getBinaryDataCppFile (int index) const
+void Project::updateOldModulePaths()
{
- const File cpp (getGeneratedCodeFolder().getChildFile ("BinaryData.cpp"));
-
- if (index > 0)
- return cpp.getSiblingFile (cpp.getFileNameWithoutExtension() + String (index + 1))
- .withFileExtension (cpp.getFileExtension());
-
- return cpp;
+ for (Project::ExporterIterator exporter (*this); exporter.next();)
+ exporter->updateOldModulePaths();
}
//==============================================================================
+static int getVersionElement (const String& v, int index)
+{
+ StringArray parts;
+ parts.addTokens (v, "., ", String::empty);
+
+ return parts [parts.size() - index - 1].getIntValue();
+}
+
+static int getJuceVersion (const String& v)
+{
+ return getVersionElement (v, 2) * 100000
+ + getVersionElement (v, 1) * 1000
+ + getVersionElement (v, 0);
+}
+
+static int getBuiltJuceVersion()
+{
+ return JUCE_MAJOR_VERSION * 100000
+ + JUCE_MINOR_VERSION * 1000
+ + JUCE_BUILDNUMBER;
+}
+
+static bool isAnyModuleNewerThanIntrojucer (const OwnedArray& modules)
+{
+ for (int i = modules.size(); --i >= 0;)
+ {
+ const ModuleDescription* m = modules.getUnchecked(i);
+
+ if (m->getID().startsWith ("juce_")
+ && getJuceVersion (m->getVersion()) > getBuiltJuceVersion())
+ return true;
+ }
+
+ return false;
+}
+
+void Project::warnAboutOldIntrojucerVersion()
+{
+ ModuleList available;
+ available.scanAllKnownFolders (*this);
+
+ if (isAnyModuleNewerThanIntrojucer (available.modules))
+ AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
+ "Introjucer",
+ "This version of the introjucer is out-of-date!"
+ "\n\n"
+ "Always make sure that you're running the very latest version, "
+ "preferably compiled directly from the JUCE repository that you're working with!");
+}
+
+//==============================================================================
+static File lastDocumentOpened;
+
+File Project::getLastDocumentOpened() { return lastDocumentOpened; }
+void Project::setLastDocumentOpened (const File& file) { lastDocumentOpened = file; }
+
static void registerRecentFile (const File& file)
{
RecentlyOpenedFilesList::registerRecentFileNatively (file);
@@ -208,24 +247,28 @@ static void registerRecentFile (const File& file)
getAppSettings().flush();
}
+//==============================================================================
Result Project::loadDocument (const File& file)
{
ScopedPointer xml (XmlDocument::parse (file));
- if (xml == nullptr || ! xml->hasTagName (Tags::projectRoot.toString()))
+ if (xml == nullptr || ! xml->hasTagName (Ids::JUCERPROJECT.toString()))
return Result::fail ("Not a valid Jucer project!");
ValueTree newTree (ValueTree::fromXml (*xml));
- if (! newTree.hasType (Tags::projectRoot))
+ if (! newTree.hasType (Ids::JUCERPROJECT))
return Result::fail ("The document contains errors and couldn't be parsed!");
registerRecentFile (file);
+ enabledModulesList = nullptr;
projectRoot = newTree;
removeDefunctExporters();
setMissingDefaultValues();
+ updateOldModulePaths();
setChangedFlag (false);
+ warnAboutOldIntrojucerVersion();
return Result::ok();
}
@@ -253,12 +296,6 @@ Result Project::saveResourcesOnly (const File& file)
return saver.saveResourcesOnly();
}
-//==============================================================================
-static File lastDocumentOpened;
-
-File Project::getLastDocumentOpened() { return lastDocumentOpened; }
-void Project::setLastDocumentOpened (const File& file) { lastDocumentOpened = file; }
-
//==============================================================================
void Project::valueTreePropertyChanged (ValueTree&, const Identifier& property)
{
@@ -389,6 +426,7 @@ void Project::createPropertyEditors (PropertyListBuilder& props)
"Extra comments: This field is not used for code or project generation, it's just a space where you can express your thoughts.");
}
+//==============================================================================
static StringArray getConfigs (const Project& p)
{
StringArray configs;
@@ -422,10 +460,25 @@ StringPairArray Project::getPreprocessorDefs() const
return parsePreprocessorDefs (projectRoot [Ids::defines]);
}
-//==============================================================================
+File Project::getBinaryDataCppFile (int index) const
+{
+ const File cpp (getGeneratedCodeFolder().getChildFile ("BinaryData.cpp"));
+
+ if (index > 0)
+ return cpp.getSiblingFile (cpp.getFileNameWithoutExtension() + String (index + 1))
+ .withFileExtension (cpp.getFileExtension());
+
+ return cpp;
+}
+
Project::Item Project::getMainGroup()
{
- return Item (*this, projectRoot.getChildWithName (Tags::projectMainGroup));
+ return Item (*this, projectRoot.getChildWithName (Ids::MAINGROUP));
+}
+
+PropertiesFile& Project::getStoredProperties() const
+{
+ return getAppSettings().getProjectProperties (getProjectUID());
}
static void findImages (const Project::Item& item, OwnedArray& found)
@@ -470,16 +523,16 @@ Image Project::Item::loadAsImageFile() const
Project::Item Project::Item::createGroup (Project& project, const String& name, const String& uid)
{
- Item group (project, ValueTree (Tags::group));
+ Item group (project, ValueTree (Ids::GROUP));
group.setID (uid);
group.initialiseMissingProperties();
group.getNameValue() = name;
return group;
}
-bool Project::Item::isFile() const { return state.hasType (Tags::file); }
-bool Project::Item::isGroup() const { return state.hasType (Tags::group) || isMainGroup(); }
-bool Project::Item::isMainGroup() const { return state.hasType (Tags::projectMainGroup); }
+bool Project::Item::isFile() const { return state.hasType (Ids::FILE); }
+bool Project::Item::isGroup() const { return state.hasType (Ids::GROUP) || isMainGroup(); }
+bool Project::Item::isMainGroup() const { return state.hasType (Ids::MAINGROUP); }
bool Project::Item::isImageFile() const { return isFile() && ImageFileFormat::findImageFormatForFileExtension (getFile()) != nullptr; }
Project::Item Project::Item::findItemWithID (const String& targetId) const
@@ -618,7 +671,7 @@ File Project::Item::determineGroupFolder() const
}
else
{
- f = project.getFile().getParentDirectory();
+ f = project.getProjectFolder();
if (f.getChildFile ("Source").isDirectory())
f = f.getChildFile ("Source");
@@ -683,8 +736,8 @@ struct ItemSorterWithGroupsAtStart
{
static int compareElements (const ValueTree& first, const ValueTree& second)
{
- const bool firstIsGroup = first.hasType (Tags::group);
- const bool secondIsGroup = second.hasType (Tags::group);
+ const bool firstIsGroup = first.hasType (Ids::GROUP);
+ const bool secondIsGroup = second.hasType (Ids::GROUP);
if (firstIsGroup == secondIsGroup)
return first [Ids::name].toString().compareIgnoreCase (second [Ids::name].toString());
@@ -712,7 +765,7 @@ Project::Item Project::Item::getOrCreateSubGroup (const String& name)
for (int i = state.getNumChildren(); --i >= 0;)
{
const ValueTree child (state.getChild (i));
- if (child.getProperty (Ids::name) == name && child.hasType (Tags::group))
+ if (child.getProperty (Ids::name) == name && child.hasType (Ids::GROUP))
return Item (project, child);
}
@@ -764,7 +817,7 @@ bool Project::Item::addFile (const File& file, int insertIndex, const bool shoul
void Project::Item::addFileUnchecked (const File& file, int insertIndex, const bool shouldCompile)
{
- Item item (project, ValueTree (Tags::file));
+ Item item (project, ValueTree (Ids::FILE));
item.initialiseMissingProperties();
item.getNameValue() = file.getFileName();
item.getShouldCompileValue() = shouldCompile && file.hasFileExtension ("cpp;mm;c;m;cc;cxx;r");
@@ -779,7 +832,7 @@ void Project::Item::addFileUnchecked (const File& file, int insertIndex, const b
bool Project::Item::addRelativeFile (const RelativePath& file, int insertIndex, bool shouldCompile)
{
- Item item (project, ValueTree (Tags::file));
+ Item item (project, ValueTree (Ids::FILE));
item.initialiseMissingProperties();
item.getNameValue() = file.getFileName();
item.getShouldCompileValue() = shouldCompile;
@@ -824,7 +877,7 @@ bool Project::Item::isIconCrossedOut() const
//==============================================================================
ValueTree Project::getConfigNode()
{
- return projectRoot.getOrCreateChildWithName (Tags::configGroup, nullptr);
+ return projectRoot.getOrCreateChildWithName (Ids::JUCEOPTIONS, nullptr);
}
const char* const Project::configFlagDefault = "default";
@@ -844,7 +897,7 @@ Value Project::getConfigFlag (const String& name)
bool Project::isConfigFlagEnabled (const String& name) const
{
- return projectRoot.getChildWithName (Tags::configGroup).getProperty (name) == configFlagEnabled;
+ return projectRoot.getChildWithName (Ids::JUCEOPTIONS).getProperty (name) == configFlagEnabled;
}
void Project::sanitiseConfigFlags()
@@ -861,15 +914,18 @@ void Project::sanitiseConfigFlags()
}
//==============================================================================
-EnabledModuleList Project::getModules()
+EnabledModuleList& Project::getModules()
{
- return EnabledModuleList (*this, projectRoot.getOrCreateChildWithName (EnabledModuleList::modulesGroupTag, nullptr));
+ if (enabledModulesList == nullptr)
+ enabledModulesList = new EnabledModuleList (*this, projectRoot.getOrCreateChildWithName (Ids::MODULES, nullptr));
+
+ return *enabledModulesList;
}
//==============================================================================
ValueTree Project::getExporters()
{
- return projectRoot.getOrCreateChildWithName (Tags::exporters, nullptr);
+ return projectRoot.getOrCreateChildWithName (Ids::EXPORTFORMATS, nullptr);
}
int Project::getNumExporters()
@@ -930,8 +986,3 @@ bool Project::ExporterIterator::next()
return true;
}
-
-PropertiesFile& Project::getStoredProperties() const
-{
- return getAppSettings().getProjectProperties (getProjectUID());
-}
diff --git a/extras/Introjucer/Source/Project/jucer_Project.h b/extras/Introjucer/Source/Project/jucer_Project.h
index 3b389cac01..b48eb545dc 100644
--- a/extras/Introjucer/Source/Project/jucer_Project.h
+++ b/extras/Introjucer/Source/Project/jucer_Project.h
@@ -28,7 +28,6 @@
#include "../jucer_Headers.h"
class ProjectExporter;
class ProjectType;
-class AvailableModuleList;
class LibraryModule;
class EnabledModuleList;
@@ -54,6 +53,7 @@ public:
void setTitle (const String& newTitle);
//==============================================================================
+ File getProjectFolder() const { return getFile().getParentDirectory(); }
ValueTree getProjectRoot() const { return projectRoot; }
String getTitle() const;
Value getProjectNameValue() { return getMainGroup().getNameValue(); }
@@ -243,7 +243,7 @@ public:
bool isConfigFlagEnabled (const String& name) const;
//==============================================================================
- EnabledModuleList getModules();
+ EnabledModuleList& getModules();
//==============================================================================
String getFileTemplate (const String& templateName);
@@ -267,6 +267,7 @@ public:
private:
friend class Item;
ValueTree projectRoot;
+ ScopedPointer enabledModulesList;
void updateProjectSettings();
void sanitiseConfigFlags();
@@ -277,6 +278,8 @@ private:
void updateOldStyleConfigList();
void moveOldPropertyFromProjectToAllExporters (Identifier name);
void removeDefunctExporters();
+ void updateOldModulePaths();
+ void warnAboutOldIntrojucerVersion();
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Project)
};
diff --git a/extras/Introjucer/Source/Project/jucer_ProjectContentComponent.cpp b/extras/Introjucer/Source/Project/jucer_ProjectContentComponent.cpp
index d8a52ee386..83c424bc8e 100644
--- a/extras/Introjucer/Source/Project/jucer_ProjectContentComponent.cpp
+++ b/extras/Introjucer/Source/Project/jucer_ProjectContentComponent.cpp
@@ -23,6 +23,7 @@
*/
#include "jucer_ProjectContentComponent.h"
+#include "jucer_Module.h"
#include "../Application/jucer_MainWindow.h"
#include "../Application/jucer_Application.h"
#include "../Code Editor/jucer_SourceCodeEditor.h"
@@ -31,7 +32,6 @@
#include "../Utility/jucer_JucerTreeViewBase.h"
#include "jucer_NewFileWizard.h"
#include "jucer_GroupInformationComponent.h"
-#include "jucer_ModulesPanel.h"
//==============================================================================
class FileTreePanel : public TreePanelBase
@@ -107,11 +107,21 @@ public:
void showModules()
{
- if (ConfigTreeItemBase* root = dynamic_cast (rootItem.get()))
- if (root->isProjectSettings())
- if (ConfigTreeItemBase* mods = dynamic_cast (root->getSubItem (0)))
- if (mods->isModulesList())
- mods->setSelected (true, true);
+ if (ConfigTreeItemBase* mods = getModulesItem())
+ mods->setSelected (true, true);
+ }
+
+ void showModule (const String& moduleID)
+ {
+ if (ConfigTreeItemBase* mods = getModulesItem())
+ {
+ mods->setOpen (true);
+
+ for (int i = mods->getNumSubItems(); --i >= 0;)
+ if (ModuleItem* m = dynamic_cast (mods->getSubItem (i)))
+ if (m->moduleID == moduleID)
+ m->setSelected (true, true);
+ }
}
TextButton openProjectButton, saveAndOpenButton;
@@ -120,6 +130,18 @@ private:
#include "jucer_ConfigTree_Base.h"
#include "jucer_ConfigTree_Modules.h"
#include "jucer_ConfigTree_Exporter.h"
+ #include "jucer_ModulesPanel.h"
+
+ ConfigTreeItemBase* getModulesItem()
+ {
+ if (ConfigTreeItemBase* root = dynamic_cast (rootItem.get()))
+ if (root->isProjectSettings())
+ if (ConfigTreeItemBase* mods = dynamic_cast (root->getSubItem (0)))
+ if (mods->isModulesList())
+ return mods;
+
+ return nullptr;
+ }
};
//==============================================================================
@@ -537,6 +559,14 @@ void ProjectContentComponent::showModules()
tree->showModules();
}
+void ProjectContentComponent::showModule (const String& moduleID)
+{
+ showConfigTab();
+
+ if (ConfigTreePanel* const tree = dynamic_cast (treeViewTabs.getCurrentContentComponent()))
+ tree->showModule (moduleID);
+}
+
StringArray ProjectContentComponent::getExportersWhichCanLaunch() const
{
StringArray s;
diff --git a/extras/Introjucer/Source/Project/jucer_ProjectContentComponent.h b/extras/Introjucer/Source/Project/jucer_ProjectContentComponent.h
index 92e39c9463..b19195bdce 100644
--- a/extras/Introjucer/Source/Project/jucer_ProjectContentComponent.h
+++ b/extras/Introjucer/Source/Project/jucer_ProjectContentComponent.h
@@ -77,6 +77,7 @@ public:
void showConfigTab();
void showProjectSettings();
void showModules();
+ void showModule (const String& moduleID);
void deleteSelectedTreeItems();
diff --git a/extras/Introjucer/Source/Project/jucer_ProjectTree_File.h b/extras/Introjucer/Source/Project/jucer_ProjectTree_File.h
index e8cf0f11e1..6bfaf5e2ba 100644
--- a/extras/Introjucer/Source/Project/jucer_ProjectTree_File.h
+++ b/extras/Introjucer/Source/Project/jucer_ProjectTree_File.h
@@ -30,10 +30,10 @@ public:
{
}
- bool acceptsFileDrop (const StringArray&) const { return false; }
- bool acceptsDragItems (const OwnedArray &) { return false; }
+ bool acceptsFileDrop (const StringArray&) const override { return false; }
+ bool acceptsDragItems (const OwnedArray &) override { return false; }
- String getDisplayName() const
+ String getDisplayName() const override
{
return getFile().getFileName();
}
@@ -48,7 +48,7 @@ public:
return File::nonexistent;
}
- void setName (const String& newName)
+ void setName (const String& newName) override
{
if (newName != File::createLegalFileName (newName))
{
@@ -95,13 +95,13 @@ public:
}
}
- ProjectTreeItemBase* createSubItem (const Project::Item&)
+ ProjectTreeItemBase* createSubItem (const Project::Item&) override
{
jassertfalse;
return nullptr;
}
- void showDocument()
+ void showDocument() override
{
const File f (getFile());
@@ -110,7 +110,7 @@ public:
pcc->showEditorForFile (f, false);
}
- void showPopupMenu()
+ void showPopupMenu() override
{
PopupMenu m;
@@ -135,7 +135,7 @@ public:
launchPopupMenu (m);
}
- void handlePopupMenuResult (int resultCode)
+ void handlePopupMenuResult (int resultCode) override
{
switch (resultCode)
{
diff --git a/extras/Introjucer/Source/Project/jucer_ProjectTree_Group.h b/extras/Introjucer/Source/Project/jucer_ProjectTree_Group.h
index 809c52019d..f502ddf12b 100644
--- a/extras/Introjucer/Source/Project/jucer_ProjectTree_Group.h
+++ b/extras/Introjucer/Source/Project/jucer_ProjectTree_Group.h
@@ -30,8 +30,8 @@ public:
{
}
- bool isRoot() const { return item.isMainGroup(); }
- bool acceptsFileDrop (const StringArray&) const { return true; }
+ bool isRoot() const override { return item.isMainGroup(); }
+ bool acceptsFileDrop (const StringArray&) const override { return true; }
void addNewGroup()
{
@@ -39,7 +39,7 @@ public:
triggerAsyncRename (newGroup);
}
- bool acceptsDragItems (const OwnedArray& selectedNodes)
+ bool acceptsDragItems (const OwnedArray& selectedNodes) override
{
for (int i = selectedNodes.size(); --i >= 0;)
if (item.canContain (*selectedNodes.getUnchecked(i)))
@@ -48,7 +48,7 @@ public:
return false;
}
- void addFiles (const StringArray& files, int insertIndex)
+ void addFiles (const StringArray& files, int insertIndex) override
{
for (int i = 0; i < files.size(); ++i)
{
@@ -59,19 +59,19 @@ public:
}
}
- void moveSelectedItemsTo (OwnedArray& selectedNodes, int insertIndex)
+ void moveSelectedItemsTo (OwnedArray& selectedNodes, int insertIndex) override
{
moveItems (selectedNodes, item, insertIndex);
}
- void checkFileStatus()
+ void checkFileStatus() override
{
for (int i = 0; i < getNumSubItems(); ++i)
if (ProjectTreeItemBase* p = dynamic_cast (getSubItem(i)))
p->checkFileStatus();
}
- ProjectTreeItemBase* createSubItem (const Project::Item& child)
+ ProjectTreeItemBase* createSubItem (const Project::Item& child) override
{
if (child.isGroup()) return new GroupItem (child);
if (child.isFile()) return new SourceFileItem (child);
@@ -80,7 +80,7 @@ public:
return nullptr;
}
- void showDocument()
+ void showDocument() override
{
if (ProjectContentComponent* pcc = getProjectContentComponent())
pcc->setEditorComponent (new GroupInformationComponent (item), nullptr);
@@ -104,7 +104,7 @@ public:
setFilesToCompile (item.getChild (i), shouldCompile);
}
- void showPopupMenu()
+ void showPopupMenu() override
{
PopupMenu m;
addCreateFileMenuItems (m);
@@ -132,7 +132,7 @@ public:
launchPopupMenu (m);
}
- void handlePopupMenuResult (int resultCode)
+ void handlePopupMenuResult (int resultCode) override
{
switch (resultCode)
{
diff --git a/extras/Introjucer/Source/Utility/jucer_PresetIDs.h b/extras/Introjucer/Source/Utility/jucer_PresetIDs.h
index ba43e6e3cc..96517d43b6 100644
--- a/extras/Introjucer/Source/Utility/jucer_PresetIDs.h
+++ b/extras/Introjucer/Source/Utility/jucer_PresetIDs.h
@@ -36,6 +36,10 @@ namespace Ids
DECLARE_ID (path);
DECLARE_ID (text);
DECLARE_ID (version);
+ DECLARE_ID (license);
+ DECLARE_ID (include);
+ DECLARE_ID (info);
+ DECLARE_ID (description);
DECLARE_ID (companyName);
DECLARE_ID (position);
DECLARE_ID (source);
diff --git a/extras/Introjucer/Source/Utility/jucer_TranslationTool.h b/extras/Introjucer/Source/Utility/jucer_TranslationTool.h
index f731705e18..d16a9f4402 100644
--- a/extras/Introjucer/Source/Utility/jucer_TranslationTool.h
+++ b/extras/Introjucer/Source/Utility/jucer_TranslationTool.h
@@ -170,16 +170,12 @@ struct TranslationHelpers
{
scanFilesForTranslations (strings, project.getMainGroup());
- const File modulesFolder (AvailableModuleList::getDefaultModulesFolder (&project));
-
OwnedArray modules;
- AvailableModuleList moduleList;
- moduleList.rescan (modulesFolder);
- project.getModules().createRequiredModules (moduleList, modules);
+ project.getModules().createRequiredModules (modules);
for (int j = 0; j < modules.size(); ++j)
{
- const File localFolder (modules.getUnchecked(j)->getLocalFolderFor (project));
+ const File localFolder (modules.getUnchecked(j)->getFolder());
Array files;
modules.getUnchecked(j)->findBrowseableFiles (localFolder, files);
diff --git a/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel.cpp b/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel.cpp
index 6e3a22af09..6915a0be8f 100644
--- a/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel.cpp
+++ b/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel.cpp
@@ -2403,7 +2403,7 @@ void LookAndFeel::drawTableHeaderColumn (Graphics& g, const String& columnName,
g.setColour (Colour (0x99000000));
g.fillPath (sortArrow, RectanglePlacement (RectanglePlacement::centred)
.getTransformToFit (sortArrow.getBounds(),
- area.removeFromRight (height * 0.5f).reduced (2).toFloat()));
+ area.removeFromRight (height / 2).reduced (2).toFloat()));
}
g.setColour (Colours::black);