| @@ -68,7 +68,6 @@ OBJECTS := \ | |||||
| $(OBJDIR)/jucer_ProjectTreeViewBase.o \ | $(OBJDIR)/jucer_ProjectTreeViewBase.o \ | ||||
| $(OBJDIR)/jucer_TreeViewTypes.o \ | $(OBJDIR)/jucer_TreeViewTypes.o \ | ||||
| $(OBJDIR)/jucer_CodeHelpers.o \ | $(OBJDIR)/jucer_CodeHelpers.o \ | ||||
| $(OBJDIR)/jucer_Coordinate.o \ | |||||
| $(OBJDIR)/jucer_FileHelpers.o \ | $(OBJDIR)/jucer_FileHelpers.o \ | ||||
| $(OBJDIR)/jucer_StoredSettings.o \ | $(OBJDIR)/jucer_StoredSettings.o \ | ||||
| $(OBJDIR)/jucer_MiscUtilities.o \ | $(OBJDIR)/jucer_MiscUtilities.o \ | ||||
| @@ -96,177 +95,172 @@ clean: | |||||
| $(OBJDIR)/jucer_CodeGenerator.o: ../../Source/model/Component/jucer_CodeGenerator.cpp | $(OBJDIR)/jucer_CodeGenerator.o: ../../Source/model/Component/jucer_CodeGenerator.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_CodeGenerator.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_ComponentDocument.o: ../../Source/model/Component/jucer_ComponentDocument.cpp | $(OBJDIR)/jucer_ComponentDocument.o: ../../Source/model/Component/jucer_ComponentDocument.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_ComponentDocument.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_ComponentTypeManager.o: ../../Source/model/Component/Types/jucer_ComponentTypeManager.cpp | $(OBJDIR)/jucer_ComponentTypeManager.o: ../../Source/model/Component/Types/jucer_ComponentTypeManager.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_ComponentTypeManager.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_DrawableDocument.o: ../../Source/model/Drawable/jucer_DrawableDocument.cpp | $(OBJDIR)/jucer_DrawableDocument.o: ../../Source/model/Drawable/jucer_DrawableDocument.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_DrawableDocument.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_NewFileWizard.o: ../../Source/model/Project/jucer_NewFileWizard.cpp | $(OBJDIR)/jucer_NewFileWizard.o: ../../Source/model/Project/jucer_NewFileWizard.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_NewFileWizard.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_Project.o: ../../Source/model/Project/jucer_Project.cpp | $(OBJDIR)/jucer_Project.o: ../../Source/model/Project/jucer_Project.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_Project.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_ProjectExporter.o: ../../Source/model/Project/jucer_ProjectExporter.cpp | $(OBJDIR)/jucer_ProjectExporter.o: ../../Source/model/Project/jucer_ProjectExporter.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_ProjectExporter.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_ProjectWizard.o: ../../Source/model/Project/jucer_ProjectWizard.cpp | $(OBJDIR)/jucer_ProjectWizard.o: ../../Source/model/Project/jucer_ProjectWizard.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_ProjectWizard.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_ResourceFile.o: ../../Source/model/Project/jucer_ResourceFile.cpp | $(OBJDIR)/jucer_ResourceFile.o: ../../Source/model/Project/jucer_ResourceFile.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_ResourceFile.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_SourceCodeEditor.o: ../../Source/ui/Code\ Editor/jucer_SourceCodeEditor.cpp | $(OBJDIR)/jucer_SourceCodeEditor.o: ../../Source/ui/Code\ Editor/jucer_SourceCodeEditor.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_SourceCodeEditor.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_ComponentEditor.o: ../../Source/ui/Component\ Editor/jucer_ComponentEditor.cpp | $(OBJDIR)/jucer_ComponentEditor.o: ../../Source/ui/Component\ Editor/jucer_ComponentEditor.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_ComponentEditor.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_ComponentViewer.o: ../../Source/ui/Component\ Editor/jucer_ComponentViewer.cpp | $(OBJDIR)/jucer_ComponentViewer.o: ../../Source/ui/Component\ Editor/jucer_ComponentViewer.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_ComponentViewer.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_DrawableEditor.o: ../../Source/ui/Drawable\ Editor/jucer_DrawableEditor.cpp | $(OBJDIR)/jucer_DrawableEditor.o: ../../Source/ui/Drawable\ Editor/jucer_DrawableEditor.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_DrawableEditor.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_EditorCanvas.o: ../../Source/ui/Editor\ Base/jucer_EditorCanvas.cpp | $(OBJDIR)/jucer_EditorCanvas.o: ../../Source/ui/Editor\ Base/jucer_EditorCanvas.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_EditorCanvas.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_DocumentEditorComponent.o: ../../Source/ui/jucer_DocumentEditorComponent.cpp | $(OBJDIR)/jucer_DocumentEditorComponent.o: ../../Source/ui/jucer_DocumentEditorComponent.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_DocumentEditorComponent.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_JucerTreeViewBase.o: ../../Source/ui/jucer_JucerTreeViewBase.cpp | $(OBJDIR)/jucer_JucerTreeViewBase.o: ../../Source/ui/jucer_JucerTreeViewBase.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_JucerTreeViewBase.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_MainWindow.o: ../../Source/ui/jucer_MainWindow.cpp | $(OBJDIR)/jucer_MainWindow.o: ../../Source/ui/jucer_MainWindow.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_MainWindow.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_OpenDocumentManager.o: ../../Source/ui/jucer_OpenDocumentManager.cpp | $(OBJDIR)/jucer_OpenDocumentManager.o: ../../Source/ui/jucer_OpenDocumentManager.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_OpenDocumentManager.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_GroupInformationComponent.o: ../../Source/ui/Project\ Editor/jucer_GroupInformationComponent.cpp | $(OBJDIR)/jucer_GroupInformationComponent.o: ../../Source/ui/Project\ Editor/jucer_GroupInformationComponent.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_GroupInformationComponent.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_ItemPreviewComponent.o: ../../Source/ui/Project\ Editor/jucer_ItemPreviewComponent.cpp | $(OBJDIR)/jucer_ItemPreviewComponent.o: ../../Source/ui/Project\ Editor/jucer_ItemPreviewComponent.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_ItemPreviewComponent.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_ProjectContentComponent.o: ../../Source/ui/Project\ Editor/jucer_ProjectContentComponent.cpp | $(OBJDIR)/jucer_ProjectContentComponent.o: ../../Source/ui/Project\ Editor/jucer_ProjectContentComponent.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_ProjectContentComponent.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_ProjectInformationComponent.o: ../../Source/ui/Project\ Editor/jucer_ProjectInformationComponent.cpp | $(OBJDIR)/jucer_ProjectInformationComponent.o: ../../Source/ui/Project\ Editor/jucer_ProjectInformationComponent.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_ProjectInformationComponent.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_ProjectTreeViewBase.o: ../../Source/ui/Project\ Editor/jucer_ProjectTreeViewBase.cpp | $(OBJDIR)/jucer_ProjectTreeViewBase.o: ../../Source/ui/Project\ Editor/jucer_ProjectTreeViewBase.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_ProjectTreeViewBase.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_TreeViewTypes.o: ../../Source/ui/Project\ Editor/jucer_TreeViewTypes.cpp | $(OBJDIR)/jucer_TreeViewTypes.o: ../../Source/ui/Project\ Editor/jucer_TreeViewTypes.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_TreeViewTypes.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_CodeHelpers.o: ../../Source/utility/jucer_CodeHelpers.cpp | $(OBJDIR)/jucer_CodeHelpers.o: ../../Source/utility/jucer_CodeHelpers.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | |||||
| $(OBJDIR)/jucer_Coordinate.o: ../../Source/utility/jucer_Coordinate.cpp | |||||
| -@mkdir -p $(OBJDIR) | |||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_CodeHelpers.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_FileHelpers.o: ../../Source/utility/jucer_FileHelpers.cpp | $(OBJDIR)/jucer_FileHelpers.o: ../../Source/utility/jucer_FileHelpers.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_FileHelpers.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_StoredSettings.o: ../../Source/utility/jucer_StoredSettings.cpp | $(OBJDIR)/jucer_StoredSettings.o: ../../Source/utility/jucer_StoredSettings.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_StoredSettings.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_MiscUtilities.o: ../../Source/utility/jucer_MiscUtilities.cpp | $(OBJDIR)/jucer_MiscUtilities.o: ../../Source/utility/jucer_MiscUtilities.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_MiscUtilities.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/jucer_Main.o: ../../Source/jucer_Main.cpp | $(OBJDIR)/jucer_Main.o: ../../Source/jucer_Main.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling jucer_Main.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/BinaryData.o: ../../JuceLibraryCode/BinaryData.cpp | $(OBJDIR)/BinaryData.o: ../../JuceLibraryCode/BinaryData.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling BinaryData.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/JuceLibraryCode1.o: ../../JuceLibraryCode/JuceLibraryCode1.cpp | $(OBJDIR)/JuceLibraryCode1.o: ../../JuceLibraryCode/JuceLibraryCode1.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling JuceLibraryCode1.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/JuceLibraryCode2.o: ../../JuceLibraryCode/JuceLibraryCode2.cpp | $(OBJDIR)/JuceLibraryCode2.o: ../../JuceLibraryCode/JuceLibraryCode2.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling JuceLibraryCode2.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/JuceLibraryCode3.o: ../../JuceLibraryCode/JuceLibraryCode3.cpp | $(OBJDIR)/JuceLibraryCode3.o: ../../JuceLibraryCode/JuceLibraryCode3.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling JuceLibraryCode3.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/JuceLibraryCode4.o: ../../JuceLibraryCode/JuceLibraryCode4.cpp | $(OBJDIR)/JuceLibraryCode4.o: ../../JuceLibraryCode/JuceLibraryCode4.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling JuceLibraryCode4.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| -include $(OBJECTS:%.o=%.d) | -include $(OBJECTS:%.o=%.d) | ||||
| @@ -42,7 +42,6 @@ | |||||
| 984444E3B2947675DC7D65DA = { isa = PBXBuildFile; fileRef = 1FDE55685608689765ADC578; }; | 984444E3B2947675DC7D65DA = { isa = PBXBuildFile; fileRef = 1FDE55685608689765ADC578; }; | ||||
| 58BF60E87F9A8EDCACC5D1AE = { isa = PBXBuildFile; fileRef = 939E2A7946081DB4D21B89B6; }; | 58BF60E87F9A8EDCACC5D1AE = { isa = PBXBuildFile; fileRef = 939E2A7946081DB4D21B89B6; }; | ||||
| 28B94C4BB7B572E6F5419E5D = { isa = PBXBuildFile; fileRef = 78E0309CB6D5E7E80B5BED7D; }; | 28B94C4BB7B572E6F5419E5D = { isa = PBXBuildFile; fileRef = 78E0309CB6D5E7E80B5BED7D; }; | ||||
| 5BF87265418D736250283182 = { isa = PBXBuildFile; fileRef = C7ADB43F83A83FFC08921A12; }; | |||||
| 12C1D006503C664FF07F476F = { isa = PBXBuildFile; fileRef = 5533704F0D30A9C62058FEC7; }; | 12C1D006503C664FF07F476F = { isa = PBXBuildFile; fileRef = 5533704F0D30A9C62058FEC7; }; | ||||
| DDAB225ABE572196882C3524 = { isa = PBXBuildFile; fileRef = 7A1CD936BD306A6E0BEFB046; }; | DDAB225ABE572196882C3524 = { isa = PBXBuildFile; fileRef = 7A1CD936BD306A6E0BEFB046; }; | ||||
| 92612DD3884793248F1EC45A = { isa = PBXBuildFile; fileRef = 49A1C43070A68985C25F34C7; }; | 92612DD3884793248F1EC45A = { isa = PBXBuildFile; fileRef = 49A1C43070A68985C25F34C7; }; | ||||
| @@ -85,6 +84,7 @@ | |||||
| E894E1F6D582678EE1F02763 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_Viewport.h; path = ../../Source/model/Component/Types/jucer_Viewport.h; sourceTree = SOURCE_ROOT; }; | E894E1F6D582678EE1F02763 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_Viewport.h; path = ../../Source/model/Component/Types/jucer_Viewport.h; sourceTree = SOURCE_ROOT; }; | ||||
| B1471E8698D193FBCF0DD13D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = jucer_DrawableDocument.cpp; path = ../../Source/model/Drawable/jucer_DrawableDocument.cpp; sourceTree = SOURCE_ROOT; }; | B1471E8698D193FBCF0DD13D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = jucer_DrawableDocument.cpp; path = ../../Source/model/Drawable/jucer_DrawableDocument.cpp; sourceTree = SOURCE_ROOT; }; | ||||
| 739F94CA6213B43D867AB0FD = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_DrawableDocument.h; path = ../../Source/model/Drawable/jucer_DrawableDocument.h; sourceTree = SOURCE_ROOT; }; | 739F94CA6213B43D867AB0FD = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_DrawableDocument.h; path = ../../Source/model/Drawable/jucer_DrawableDocument.h; sourceTree = SOURCE_ROOT; }; | ||||
| BDE8CD9273E1B0D0E500D283 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_DrawableTypeHandler.h; path = ../../Source/model/Drawable/jucer_DrawableTypeHandler.h; sourceTree = SOURCE_ROOT; }; | |||||
| 9DCB32BBD7053ACCB598CE79 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = jucer_NewFileWizard.cpp; path = ../../Source/model/Project/jucer_NewFileWizard.cpp; sourceTree = SOURCE_ROOT; }; | 9DCB32BBD7053ACCB598CE79 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = jucer_NewFileWizard.cpp; path = ../../Source/model/Project/jucer_NewFileWizard.cpp; sourceTree = SOURCE_ROOT; }; | ||||
| 201DF0B7B4AA3E03B1AA5144 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_NewFileWizard.h; path = ../../Source/model/Project/jucer_NewFileWizard.h; sourceTree = SOURCE_ROOT; }; | 201DF0B7B4AA3E03B1AA5144 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_NewFileWizard.h; path = ../../Source/model/Project/jucer_NewFileWizard.h; sourceTree = SOURCE_ROOT; }; | ||||
| 4179D4C7BF616A4A3C3E11CA = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = jucer_Project.cpp; path = ../../Source/model/Project/jucer_Project.cpp; sourceTree = SOURCE_ROOT; }; | 4179D4C7BF616A4A3C3E11CA = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = jucer_Project.cpp; path = ../../Source/model/Project/jucer_Project.cpp; sourceTree = SOURCE_ROOT; }; | ||||
| @@ -143,8 +143,6 @@ | |||||
| 9C58E022906C193862372BC1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_CodeHelpers.h; path = ../../Source/utility/jucer_CodeHelpers.h; sourceTree = SOURCE_ROOT; }; | 9C58E022906C193862372BC1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_CodeHelpers.h; path = ../../Source/utility/jucer_CodeHelpers.h; sourceTree = SOURCE_ROOT; }; | ||||
| AAF3C58696944A256CA61730 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_ColourEditorComponent.h; path = ../../Source/utility/jucer_ColourEditorComponent.h; sourceTree = SOURCE_ROOT; }; | AAF3C58696944A256CA61730 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_ColourEditorComponent.h; path = ../../Source/utility/jucer_ColourEditorComponent.h; sourceTree = SOURCE_ROOT; }; | ||||
| 9736236B5C4D6A16FC7E03AC = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_Colours.h; path = ../../Source/utility/jucer_Colours.h; sourceTree = SOURCE_ROOT; }; | 9736236B5C4D6A16FC7E03AC = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_Colours.h; path = ../../Source/utility/jucer_Colours.h; sourceTree = SOURCE_ROOT; }; | ||||
| C7ADB43F83A83FFC08921A12 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = jucer_Coordinate.cpp; path = ../../Source/utility/jucer_Coordinate.cpp; sourceTree = SOURCE_ROOT; }; | |||||
| EFA0636FB8ABA3377AB6C6F4 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_Coordinate.h; path = ../../Source/utility/jucer_Coordinate.h; sourceTree = SOURCE_ROOT; }; | |||||
| CC9A3046B8B9FCDFE2092F51 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_CoordinatePropertyComponent.h; path = ../../Source/utility/jucer_CoordinatePropertyComponent.h; sourceTree = SOURCE_ROOT; }; | CC9A3046B8B9FCDFE2092F51 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_CoordinatePropertyComponent.h; path = ../../Source/utility/jucer_CoordinatePropertyComponent.h; sourceTree = SOURCE_ROOT; }; | ||||
| 5533704F0D30A9C62058FEC7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = jucer_FileHelpers.cpp; path = ../../Source/utility/jucer_FileHelpers.cpp; sourceTree = SOURCE_ROOT; }; | 5533704F0D30A9C62058FEC7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = jucer_FileHelpers.cpp; path = ../../Source/utility/jucer_FileHelpers.cpp; sourceTree = SOURCE_ROOT; }; | ||||
| 27E71DE11448E4D6721D5508 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_FileHelpers.h; path = ../../Source/utility/jucer_FileHelpers.h; sourceTree = SOURCE_ROOT; }; | 27E71DE11448E4D6721D5508 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_FileHelpers.h; path = ../../Source/utility/jucer_FileHelpers.h; sourceTree = SOURCE_ROOT; }; | ||||
| @@ -204,7 +202,8 @@ | |||||
| 7C95A5CDB1B24D227D92749E ); name = Component; sourceTree = "<group>"; }; | 7C95A5CDB1B24D227D92749E ); name = Component; sourceTree = "<group>"; }; | ||||
| E70E3BE796E91EA86CFE10FE = { isa = PBXGroup; children = ( | E70E3BE796E91EA86CFE10FE = { isa = PBXGroup; children = ( | ||||
| B1471E8698D193FBCF0DD13D, | B1471E8698D193FBCF0DD13D, | ||||
| 739F94CA6213B43D867AB0FD ); name = Drawable; sourceTree = "<group>"; }; | |||||
| 739F94CA6213B43D867AB0FD, | |||||
| BDE8CD9273E1B0D0E500D283 ); name = Drawable; sourceTree = "<group>"; }; | |||||
| ADA17383E5554BCDF567AACC = { isa = PBXGroup; children = ( | ADA17383E5554BCDF567AACC = { isa = PBXGroup; children = ( | ||||
| 9DCB32BBD7053ACCB598CE79, | 9DCB32BBD7053ACCB598CE79, | ||||
| 201DF0B7B4AA3E03B1AA5144, | 201DF0B7B4AA3E03B1AA5144, | ||||
| @@ -280,8 +279,6 @@ | |||||
| 9C58E022906C193862372BC1, | 9C58E022906C193862372BC1, | ||||
| AAF3C58696944A256CA61730, | AAF3C58696944A256CA61730, | ||||
| 9736236B5C4D6A16FC7E03AC, | 9736236B5C4D6A16FC7E03AC, | ||||
| C7ADB43F83A83FFC08921A12, | |||||
| EFA0636FB8ABA3377AB6C6F4, | |||||
| CC9A3046B8B9FCDFE2092F51, | CC9A3046B8B9FCDFE2092F51, | ||||
| 5533704F0D30A9C62058FEC7, | 5533704F0D30A9C62058FEC7, | ||||
| 27E71DE11448E4D6721D5508, | 27E71DE11448E4D6721D5508, | ||||
| @@ -438,7 +435,6 @@ | |||||
| 984444E3B2947675DC7D65DA, | 984444E3B2947675DC7D65DA, | ||||
| 58BF60E87F9A8EDCACC5D1AE, | 58BF60E87F9A8EDCACC5D1AE, | ||||
| 28B94C4BB7B572E6F5419E5D, | 28B94C4BB7B572E6F5419E5D, | ||||
| 5BF87265418D736250283182, | |||||
| 12C1D006503C664FF07F476F, | 12C1D006503C664FF07F476F, | ||||
| DDAB225ABE572196882C3524, | DDAB225ABE572196882C3524, | ||||
| 92612DD3884793248F1EC45A, | 92612DD3884793248F1EC45A, | ||||
| @@ -154,6 +154,7 @@ | |||||
| <Filter Name="Drawable"> | <Filter Name="Drawable"> | ||||
| <File RelativePath="..\..\Source\model\Drawable\jucer_DrawableDocument.cpp"/> | <File RelativePath="..\..\Source\model\Drawable\jucer_DrawableDocument.cpp"/> | ||||
| <File RelativePath="..\..\Source\model\Drawable\jucer_DrawableDocument.h"/> | <File RelativePath="..\..\Source\model\Drawable\jucer_DrawableDocument.h"/> | ||||
| <File RelativePath="..\..\Source\model\Drawable\jucer_DrawableTypeHandler.h"/> | |||||
| </Filter> | </Filter> | ||||
| <Filter Name="Project"> | <Filter Name="Project"> | ||||
| <File RelativePath="..\..\Source\model\Project\jucer_NewFileWizard.cpp"/> | <File RelativePath="..\..\Source\model\Project\jucer_NewFileWizard.cpp"/> | ||||
| @@ -229,8 +230,6 @@ | |||||
| <File RelativePath="..\..\Source\utility\jucer_CodeHelpers.h"/> | <File RelativePath="..\..\Source\utility\jucer_CodeHelpers.h"/> | ||||
| <File RelativePath="..\..\Source\utility\jucer_ColourEditorComponent.h"/> | <File RelativePath="..\..\Source\utility\jucer_ColourEditorComponent.h"/> | ||||
| <File RelativePath="..\..\Source\utility\jucer_Colours.h"/> | <File RelativePath="..\..\Source\utility\jucer_Colours.h"/> | ||||
| <File RelativePath="..\..\Source\utility\jucer_Coordinate.cpp"/> | |||||
| <File RelativePath="..\..\Source\utility\jucer_Coordinate.h"/> | |||||
| <File RelativePath="..\..\Source\utility\jucer_CoordinatePropertyComponent.h"/> | <File RelativePath="..\..\Source\utility\jucer_CoordinatePropertyComponent.h"/> | ||||
| <File RelativePath="..\..\Source\utility\jucer_FileHelpers.cpp"/> | <File RelativePath="..\..\Source\utility\jucer_FileHelpers.cpp"/> | ||||
| <File RelativePath="..\..\Source\utility\jucer_FileHelpers.h"/> | <File RelativePath="..\..\Source\utility\jucer_FileHelpers.h"/> | ||||
| @@ -154,6 +154,7 @@ | |||||
| <Filter Name="Drawable"> | <Filter Name="Drawable"> | ||||
| <File RelativePath="..\..\Source\model\Drawable\jucer_DrawableDocument.cpp"/> | <File RelativePath="..\..\Source\model\Drawable\jucer_DrawableDocument.cpp"/> | ||||
| <File RelativePath="..\..\Source\model\Drawable\jucer_DrawableDocument.h"/> | <File RelativePath="..\..\Source\model\Drawable\jucer_DrawableDocument.h"/> | ||||
| <File RelativePath="..\..\Source\model\Drawable\jucer_DrawableTypeHandler.h"/> | |||||
| </Filter> | </Filter> | ||||
| <Filter Name="Project"> | <Filter Name="Project"> | ||||
| <File RelativePath="..\..\Source\model\Project\jucer_NewFileWizard.cpp"/> | <File RelativePath="..\..\Source\model\Project\jucer_NewFileWizard.cpp"/> | ||||
| @@ -229,8 +230,6 @@ | |||||
| <File RelativePath="..\..\Source\utility\jucer_CodeHelpers.h"/> | <File RelativePath="..\..\Source\utility\jucer_CodeHelpers.h"/> | ||||
| <File RelativePath="..\..\Source\utility\jucer_ColourEditorComponent.h"/> | <File RelativePath="..\..\Source\utility\jucer_ColourEditorComponent.h"/> | ||||
| <File RelativePath="..\..\Source\utility\jucer_Colours.h"/> | <File RelativePath="..\..\Source\utility\jucer_Colours.h"/> | ||||
| <File RelativePath="..\..\Source\utility\jucer_Coordinate.cpp"/> | |||||
| <File RelativePath="..\..\Source\utility\jucer_Coordinate.h"/> | |||||
| <File RelativePath="..\..\Source\utility\jucer_CoordinatePropertyComponent.h"/> | <File RelativePath="..\..\Source\utility\jucer_CoordinatePropertyComponent.h"/> | ||||
| <File RelativePath="..\..\Source\utility\jucer_FileHelpers.cpp"/> | <File RelativePath="..\..\Source\utility\jucer_FileHelpers.cpp"/> | ||||
| <File RelativePath="..\..\Source\utility\jucer_FileHelpers.h"/> | <File RelativePath="..\..\Source\utility\jucer_FileHelpers.h"/> | ||||
| @@ -72,6 +72,8 @@ | |||||
| file="Source/model/Drawable/jucer_DrawableDocument.cpp"/> | file="Source/model/Drawable/jucer_DrawableDocument.cpp"/> | ||||
| <FILE id="qMcrWuCal" name="jucer_DrawableDocument.h" compile="0" resource="0" | <FILE id="qMcrWuCal" name="jucer_DrawableDocument.h" compile="0" resource="0" | ||||
| file="Source/model/Drawable/jucer_DrawableDocument.h"/> | file="Source/model/Drawable/jucer_DrawableDocument.h"/> | ||||
| <FILE id="tGjXOXiR9" name="jucer_DrawableTypeHandler.h" compile="0" | |||||
| resource="0" file="Source/model/Drawable/jucer_DrawableTypeHandler.h"/> | |||||
| </GROUP> | </GROUP> | ||||
| <GROUP id="na25KSPIj" name="Project"> | <GROUP id="na25KSPIj" name="Project"> | ||||
| <FILE id="jqL1mb9xp" name="jucer_NewFileWizard.cpp" compile="1" resource="0" | <FILE id="jqL1mb9xp" name="jucer_NewFileWizard.cpp" compile="1" resource="0" | ||||
| @@ -205,10 +207,6 @@ | |||||
| resource="0" file="Source/utility/jucer_ColourEditorComponent.h"/> | resource="0" file="Source/utility/jucer_ColourEditorComponent.h"/> | ||||
| <FILE id="bjibbvm3S" name="jucer_Colours.h" compile="0" resource="0" | <FILE id="bjibbvm3S" name="jucer_Colours.h" compile="0" resource="0" | ||||
| file="Source/utility/jucer_Colours.h"/> | file="Source/utility/jucer_Colours.h"/> | ||||
| <FILE id="bDebnoSX" name="jucer_Coordinate.cpp" compile="1" resource="0" | |||||
| file="Source/utility/jucer_Coordinate.cpp"/> | |||||
| <FILE id="uqXX3Ga6S" name="jucer_Coordinate.h" compile="0" resource="0" | |||||
| file="Source/utility/jucer_Coordinate.h"/> | |||||
| <FILE id="DDCunFHcy" name="jucer_CoordinatePropertyComponent.h" compile="0" | <FILE id="DDCunFHcy" name="jucer_CoordinatePropertyComponent.h" compile="0" | ||||
| resource="0" file="Source/utility/jucer_CoordinatePropertyComponent.h"/> | resource="0" file="Source/utility/jucer_CoordinatePropertyComponent.h"/> | ||||
| <FILE id="WlEYep7NN" name="jucer_FileHelpers.cpp" compile="1" resource="0" | <FILE id="WlEYep7NN" name="jucer_FileHelpers.cpp" compile="1" resource="0" | ||||
| @@ -40,7 +40,7 @@ public: | |||||
| //============================================================================== | //============================================================================== | ||||
| ComponentBoundsEditor (ComponentDocument& document_, const String& name, Type type_, | ComponentBoundsEditor (ComponentDocument& document_, const String& name, Type type_, | ||||
| const ValueTree& compState_, const Value& coordValue_) | const ValueTree& compState_, const Value& coordValue_) | ||||
| : CoordinatePropertyComponent (document_, name, | |||||
| : CoordinatePropertyComponent (&document_, name, | |||||
| Value (new CoordExtractor (coordValue_, type_)), | Value (new CoordExtractor (coordValue_, type_)), | ||||
| type_ == left || type_ == right), | type_ == left || type_ == right), | ||||
| document (document_), | document (document_), | ||||
| @@ -184,7 +184,7 @@ Component* ComponentTypeManager::createFromStoredType (ComponentDocument& docume | |||||
| ComponentTypeHandler* ComponentTypeManager::getHandlerFor (const Identifier& type) | ComponentTypeHandler* ComponentTypeManager::getHandlerFor (const Identifier& type) | ||||
| { | { | ||||
| for (int i = handlers.size(); --i >= 0;) | for (int i = handlers.size(); --i >= 0;) | ||||
| if (handlers.getUnchecked(i)->getXmlTag() == type) | |||||
| if (handlers.getUnchecked(i)->getValueTreeType() == type) | |||||
| return handlers.getUnchecked(i); | return handlers.getUnchecked(i); | ||||
| return 0; | return 0; | ||||
| @@ -205,8 +205,8 @@ juce_ImplementSingleton_SingleThreaded (ComponentTypeManager); | |||||
| //============================================================================== | //============================================================================== | ||||
| ComponentTypeHandler::ComponentTypeHandler (const String& displayName_, const String& className_, | ComponentTypeHandler::ComponentTypeHandler (const String& displayName_, const String& className_, | ||||
| const String& xmlTag_, const String& memberNameRoot_) | |||||
| : displayName (displayName_), className (className_), xmlTag (xmlTag_), | |||||
| const Identifier& valueTreeType_, const String& memberNameRoot_) | |||||
| : displayName (displayName_), className (className_), valueTreeType (valueTreeType_), | |||||
| memberNameRoot (memberNameRoot_) | memberNameRoot (memberNameRoot_) | ||||
| { | { | ||||
| } | } | ||||
| @@ -315,7 +315,7 @@ void ComponentTypeInstance::initialiseNewItemBasics() | |||||
| void ComponentTypeInstance::updateComponentBasics (Component* comp) | void ComponentTypeInstance::updateComponentBasics (Component* comp) | ||||
| { | { | ||||
| RelativeRectangle pos (state [ComponentDocument::compBoundsProperty].toString()); | RelativeRectangle pos (state [ComponentDocument::compBoundsProperty].toString()); | ||||
| comp->setBounds (pos.resolve (document).getSmallestIntegerContainer()); | |||||
| comp->setBounds (pos.resolve (&document).getSmallestIntegerContainer()); | |||||
| //comp->setName (state [ComponentDocument::compNameProperty]); | //comp->setName (state [ComponentDocument::compNameProperty]); | ||||
| @@ -86,11 +86,12 @@ class ComponentTypeHandler | |||||
| { | { | ||||
| public: | public: | ||||
| //============================================================================== | //============================================================================== | ||||
| ComponentTypeHandler (const String& displayName_, const String& className_, const String& xmlTag_, const String& memberNameRoot_); | |||||
| ComponentTypeHandler (const String& displayName_, const String& className_, | |||||
| const Identifier& valueTreeType_, const String& memberNameRoot_); | |||||
| virtual ~ComponentTypeHandler(); | virtual ~ComponentTypeHandler(); | ||||
| const String& getDisplayName() const { return displayName; } | const String& getDisplayName() const { return displayName; } | ||||
| const Identifier& getXmlTag() const { return xmlTag; } | |||||
| const Identifier& getValueTreeType() const { return valueTreeType; } | |||||
| const String& getMemberNameRoot() const { return memberNameRoot; } | const String& getMemberNameRoot() const { return memberNameRoot; } | ||||
| virtual Component* createComponent() = 0; | virtual Component* createComponent() = 0; | ||||
| @@ -106,7 +107,7 @@ public: | |||||
| protected: | protected: | ||||
| //============================================================================== | //============================================================================== | ||||
| const String displayName, className, memberNameRoot; | const String displayName, className, memberNameRoot; | ||||
| const Identifier xmlTag; | |||||
| const Identifier valueTreeType; | |||||
| private: | private: | ||||
| ComponentTypeHandler (const ComponentTypeHandler&); | ComponentTypeHandler (const ComponentTypeHandler&); | ||||
| @@ -359,7 +359,7 @@ const ValueTree ComponentDocument::performNewComponentMenuItem (int menuResultCo | |||||
| if (handler != 0) | if (handler != 0) | ||||
| { | { | ||||
| ValueTree state (handler->getXmlTag()); | |||||
| ValueTree state (handler->getValueTreeType()); | |||||
| state.setProperty (idProperty, createAlphaNumericUID(), 0); | state.setProperty (idProperty, createAlphaNumericUID(), 0); | ||||
| ComponentTypeInstance comp (*this, state); | ComponentTypeInstance comp (*this, state); | ||||
| @@ -532,7 +532,7 @@ void ComponentDocument::renameAnchor (const String& oldName, const String& newNa | |||||
| { | { | ||||
| ValueTree v (getComponent(i)); | ValueTree v (getComponent(i)); | ||||
| RelativeRectangle coords (getCoordsFor (v)); | RelativeRectangle coords (getCoordsFor (v)); | ||||
| coords.renameAnchorIfUsed (oldName, newName, *this); | |||||
| coords.renameAnchorIfUsed (oldName, newName, this); | |||||
| setCoordsFor (v, coords); | setCoordsFor (v, coords); | ||||
| } | } | ||||
| @@ -551,7 +551,7 @@ void ComponentDocument::addMarkerMenuItem (int i, const RelativeCoordinate& coor | |||||
| name << '.' << edge; | name << '.' << edge; | ||||
| menu.addItem (i, name, | menu.addItem (i, name, | ||||
| ! (name == fullCoordName || requestedCoord.references (fullCoordName, *this)), | |||||
| ! (name == fullCoordName || requestedCoord.references (fullCoordName, this)), | |||||
| name == (isAnchor1 ? coord.getAnchorName1() : coord.getAnchorName2())); | name == (isAnchor1 ? coord.getAnchorName1() : coord.getAnchorName2())); | ||||
| } | } | ||||
| @@ -780,7 +780,7 @@ bool ComponentDocument::MarkerList::createProperties (Array <PropertyComponent*> | |||||
| props.add (new TextPropertyComponent (Value (new MarkerListBase::MarkerNameValueSource (this, getNameAsValue (marker))), | props.add (new TextPropertyComponent (Value (new MarkerListBase::MarkerNameValueSource (this, getNameAsValue (marker))), | ||||
| "Marker Name", 256, false)); | "Marker Name", 256, false)); | ||||
| props.add (new MarkerListBase::PositionPropertyComponent (document, *this, "Position", marker, | |||||
| props.add (new MarkerListBase::PositionPropertyComponent (&document, *this, "Position", marker, | |||||
| marker.getPropertyAsValue (getMarkerPosProperty(), document.getUndoManager()))); | marker.getPropertyAsValue (getMarkerPosProperty(), document.getUndoManager()))); | ||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -28,7 +28,6 @@ | |||||
| #include "../../jucer_Headers.h" | #include "../../jucer_Headers.h" | ||||
| #include "../Project/jucer_Project.h" | #include "../Project/jucer_Project.h" | ||||
| #include "../../utility/jucer_Coordinate.h" | |||||
| #include "../../utility/jucer_MarkerListBase.h" | #include "../../utility/jucer_MarkerListBase.h" | ||||
| #include "jucer_CodeGenerator.h" | #include "jucer_CodeGenerator.h" | ||||
| @@ -24,6 +24,54 @@ | |||||
| */ | */ | ||||
| #include "jucer_DrawableDocument.h" | #include "jucer_DrawableDocument.h" | ||||
| #include "jucer_DrawableTypeHandler.h" | |||||
| //============================================================================== | |||||
| class DrawableTypeManager : public DeletedAtShutdown | |||||
| { | |||||
| public: | |||||
| DrawableTypeManager() | |||||
| { | |||||
| handlers.add (new DrawablePathHandler()); | |||||
| handlers.add (new DrawableImageHandler()); | |||||
| } | |||||
| ~DrawableTypeManager() | |||||
| { | |||||
| } | |||||
| juce_DeclareSingleton_SingleThreaded_Minimal (DrawableTypeManager); | |||||
| //============================================================================== | |||||
| int getNumHandlers() const { return handlers.size(); } | |||||
| DrawableTypeHandler* getHandler (const int index) const { return handlers[index]; } | |||||
| DrawableTypeHandler* getHandlerFor (const Identifier& type) | |||||
| { | |||||
| for (int i = handlers.size(); --i >= 0;) | |||||
| if (handlers.getUnchecked(i)->getValueTreeType() == type) | |||||
| return handlers.getUnchecked(i); | |||||
| jassertfalse; | |||||
| return 0; | |||||
| } | |||||
| const StringArray getDisplayNames() | |||||
| { | |||||
| StringArray s; | |||||
| for (int i = 0; i < handlers.size(); ++i) | |||||
| s.add (handlers.getUnchecked(i)->getDisplayName()); | |||||
| return s; | |||||
| } | |||||
| private: | |||||
| OwnedArray <DrawableTypeHandler> handlers; | |||||
| }; | |||||
| juce_ImplementSingleton_SingleThreaded (DrawableTypeManager); | |||||
| //============================================================================== | //============================================================================== | ||||
| @@ -55,9 +103,9 @@ DrawableDocument::~DrawableDocument() | |||||
| root.removeListener (this); | root.removeListener (this); | ||||
| } | } | ||||
| ValueTree DrawableDocument::getRootDrawableNode() const | |||||
| DrawableComposite::ValueTreeWrapper DrawableDocument::getRootDrawableNode() const | |||||
| { | { | ||||
| return root.getChild (0); | |||||
| return DrawableComposite::ValueTreeWrapper (root.getChild (0)); | |||||
| } | } | ||||
| void DrawableDocument::checkRootObject() | void DrawableDocument::checkRootObject() | ||||
| @@ -75,11 +123,6 @@ void DrawableDocument::checkRootObject() | |||||
| getCanvasHeight() = 500; | getCanvasHeight() = 500; | ||||
| } | } | ||||
| const String DrawableDocument::getIdFor (const ValueTree& object) | |||||
| { | |||||
| return object [Ids::id_]; | |||||
| } | |||||
| //============================================================================== | //============================================================================== | ||||
| void DrawableDocument::setName (const String& name) | void DrawableDocument::setName (const String& name) | ||||
| { | { | ||||
| @@ -194,59 +237,49 @@ void DrawableDocument::changed() | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| static const Colour getRandomColour() | |||||
| { | |||||
| return Colours::red.withHue (Random::getSystemRandom().nextFloat()); | |||||
| } | |||||
| const int menuItemOffset = 0x63451fa4; | |||||
| void DrawableDocument::addDrawable (Drawable& d) | |||||
| void DrawableDocument::addNewItemMenuItems (PopupMenu& menu) const | |||||
| { | { | ||||
| DrawableComposite dc; | |||||
| dc.insertDrawable (d.createCopy()); | |||||
| ValueTree dcNode (dc.createValueTree (0)); | |||||
| ValueTree subNode (dcNode.getChild(0)); | |||||
| dcNode.removeChild (subNode, 0); | |||||
| addMissingIds (subNode); | |||||
| const StringArray displayNames (DrawableTypeManager::getInstance()->getDisplayNames()); | |||||
| getRootDrawableNode().addChild (subNode, -1, getUndoManager()); | |||||
| for (int i = 0; i < displayNames.size(); ++i) | |||||
| menu.addItem (i + menuItemOffset, "New " + displayNames[i]); | |||||
| } | } | ||||
| void DrawableDocument::addRectangle() | |||||
| const ValueTree DrawableDocument::performNewItemMenuItem (int menuResultCode) | |||||
| { | { | ||||
| Path p; | |||||
| p.addRectangle ((float) Random::getSystemRandom().nextInt (500), | |||||
| (float) Random::getSystemRandom().nextInt (500), | |||||
| 100.0f, 100.0f); | |||||
| const StringArray displayNames (DrawableTypeManager::getInstance()->getDisplayNames()); | |||||
| DrawablePath d; | |||||
| d.setPath (p); | |||||
| d.setFill (FillType (getRandomColour())); | |||||
| if (menuResultCode >= menuItemOffset && menuResultCode < menuItemOffset + displayNames.size()) | |||||
| { | |||||
| DrawableTypeHandler* handler = DrawableTypeManager::getInstance()->getHandler (menuResultCode - menuItemOffset); | |||||
| jassert (handler != 0); | |||||
| addDrawable (d); | |||||
| } | |||||
| if (handler != 0) | |||||
| { | |||||
| ValueTree state (handler->createNewInstance (*this, | |||||
| Point<float> (Random::getSystemRandom().nextFloat() * 100.0f + 100.0f, | |||||
| Random::getSystemRandom().nextFloat() * 100.0f + 100.0f))); | |||||
| void DrawableDocument::addCircle() | |||||
| { | |||||
| Path p; | |||||
| p.addEllipse ((float) Random::getSystemRandom().nextInt (500), | |||||
| (float) Random::getSystemRandom().nextInt (500), | |||||
| 100.0f, 100.0f); | |||||
| getRootDrawableNode().addDrawable (state, -1, getUndoManager()); | |||||
| DrawablePath d; | |||||
| d.setPath (p); | |||||
| d.setFill (FillType (getRandomColour())); | |||||
| return state; | |||||
| } | |||||
| } | |||||
| addDrawable (d); | |||||
| return ValueTree::invalid; | |||||
| } | } | ||||
| void DrawableDocument::addImage (const File& imageFile) | |||||
| //============================================================================== | |||||
| Image* DrawableDocument::getImageForIdentifier (const var& imageIdentifier) | |||||
| { | { | ||||
| jassertfalse | |||||
| DrawableImage d; | |||||
| return ImageCache::getFromMemory (BinaryData::juce_icon_png, BinaryData::juce_icon_pngSize); | |||||
| } | |||||
| addDrawable (d); | |||||
| const var DrawableDocument::getIdentifierForImage (Image* image) | |||||
| { | |||||
| return var::null; //xxx todo | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -28,13 +28,13 @@ | |||||
| #include "../../jucer_Headers.h" | #include "../../jucer_Headers.h" | ||||
| #include "../Project/jucer_Project.h" | #include "../Project/jucer_Project.h" | ||||
| #include "../../utility/jucer_Coordinate.h" | |||||
| #include "../../utility/jucer_MarkerListBase.h" | #include "../../utility/jucer_MarkerListBase.h" | ||||
| //============================================================================== | //============================================================================== | ||||
| class DrawableDocument : public ValueTree::Listener, | class DrawableDocument : public ValueTree::Listener, | ||||
| public ChangeBroadcaster | |||||
| public ChangeBroadcaster, | |||||
| public Drawable::ImageProvider | |||||
| { | { | ||||
| public: | public: | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -51,16 +51,13 @@ public: | |||||
| void changed(); | void changed(); | ||||
| ValueTree& getRoot() { return root; } | ValueTree& getRoot() { return root; } | ||||
| ValueTree getRootDrawableNode() const; | |||||
| void addRectangle(); | |||||
| void addCircle(); | |||||
| void addImage (const File& imageFile); | |||||
| DrawableComposite::ValueTreeWrapper getRootDrawableNode() const; | |||||
| Value getCanvasWidth() const { return getRootValueNonUndoable (Ids::width); } | Value getCanvasWidth() const { return getRootValueNonUndoable (Ids::width); } | ||||
| Value getCanvasHeight() const { return getRootValueNonUndoable (Ids::height); } | Value getCanvasHeight() const { return getRootValueNonUndoable (Ids::height); } | ||||
| static const String getIdFor (const ValueTree& object); | |||||
| void addNewItemMenuItems (PopupMenu& menu) const; | |||||
| const ValueTree performNewItemMenuItem (int menuResultCode); | |||||
| //============================================================================== | //============================================================================== | ||||
| class MarkerList : public MarkerListBase | class MarkerList : public MarkerListBase | ||||
| @@ -91,6 +88,9 @@ public: | |||||
| const String getNonexistentMarkerName (const String& name); | const String getNonexistentMarkerName (const String& name); | ||||
| void renameAnchor (const String& oldName, const String& newName); | void renameAnchor (const String& oldName, const String& newName); | ||||
| Image* getImageForIdentifier (const var& imageIdentifier); | |||||
| const var getIdentifierForImage (Image* image); | |||||
| //============================================================================== | //============================================================================== | ||||
| void valueTreePropertyChanged (ValueTree& tree, const Identifier& name); | void valueTreePropertyChanged (ValueTree& tree, const Identifier& name); | ||||
| void valueTreeChildrenChanged (ValueTree& tree); | void valueTreeChildrenChanged (ValueTree& tree); | ||||
| @@ -0,0 +1,103 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||||
| Copyright 2004-10 by Raw Material Software Ltd. | |||||
| ------------------------------------------------------------------------------ | |||||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||||
| Public License (Version 2), as published by the Free Software Foundation. | |||||
| A copy of the license is included in the JUCE distribution, or can be found | |||||
| online at www.gnu.org/licenses. | |||||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
| ------------------------------------------------------------------------------ | |||||
| To release a closed-source product which uses JUCE, commercial licenses are | |||||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| #ifndef __JUCER_DRAWABLETYPEHANDLER_H_7FB02E2F__ | |||||
| #define __JUCER_DRAWABLETYPEHANDLER_H_7FB02E2F__ | |||||
| #include "jucer_DrawableDocument.h" | |||||
| //============================================================================== | |||||
| class DrawableTypeHandler | |||||
| { | |||||
| public: | |||||
| DrawableTypeHandler (const String& displayName_, const Identifier& valueTreeType_) | |||||
| : displayName (displayName_), valueTreeType (valueTreeType_) | |||||
| { | |||||
| } | |||||
| virtual ~DrawableTypeHandler() {} | |||||
| virtual const ValueTree createNewInstance (DrawableDocument& document, const Point<float>& approxPosition) = 0; | |||||
| const String& getDisplayName() const { return displayName; } | |||||
| const Identifier& getValueTreeType() const { return valueTreeType; } | |||||
| private: | |||||
| const String displayName; | |||||
| const Identifier valueTreeType; | |||||
| }; | |||||
| //============================================================================== | |||||
| class DrawablePathHandler : public DrawableTypeHandler | |||||
| { | |||||
| public: | |||||
| DrawablePathHandler() : DrawableTypeHandler ("Polygon", DrawablePath::valueTreeType) {} | |||||
| ~DrawablePathHandler() {} | |||||
| const ValueTree createNewInstance (DrawableDocument& document, const Point<float>& approxPosition) | |||||
| { | |||||
| Path p; | |||||
| p.addTriangle (approxPosition.getX(), approxPosition.getY() - 50.0f, | |||||
| approxPosition.getX() + 50.0f, approxPosition.getY() + 20.0f, | |||||
| approxPosition.getX() - 50.0f, approxPosition.getY() + 20.0f); | |||||
| DrawablePath dp; | |||||
| dp.setPath (p); | |||||
| dp.setFill (Colours::lightblue.withHue (Random::getSystemRandom().nextFloat())); | |||||
| return dp.createValueTree (0); | |||||
| } | |||||
| }; | |||||
| //============================================================================== | |||||
| class DrawableImageHandler : public DrawableTypeHandler | |||||
| { | |||||
| public: | |||||
| DrawableImageHandler() : DrawableTypeHandler ("Image", DrawableImage::valueTreeType) {} | |||||
| ~DrawableImageHandler() {} | |||||
| const ValueTree createNewInstance (DrawableDocument& document, const Point<float>& approxPosition) | |||||
| { | |||||
| Image tempImage (Image::ARGB, 100, 100, true); | |||||
| { | |||||
| Graphics g (tempImage); | |||||
| g.fillAll (Colours::grey.withAlpha (0.3f)); | |||||
| g.setColour (Colours::red); | |||||
| g.setFont (40.0f); | |||||
| g.drawText ("?", 0, 0, 100, 100, Justification::centred, false); | |||||
| } | |||||
| DrawableImage di; | |||||
| di.setTransform (RelativePoint (approxPosition), | |||||
| RelativePoint (approxPosition + Point<float> (100.0f, 0.0f)), | |||||
| RelativePoint (approxPosition + Point<float> (0.0f, 100.0f))); | |||||
| return di.createValueTree (&document); | |||||
| } | |||||
| }; | |||||
| #endif // __JUCER_DRAWABLETYPEHANDLER_H_7FB02E2F__ | |||||
| @@ -298,7 +298,7 @@ private: | |||||
| out << "$(OBJDIR)/" << escapeSpaces (getObjectFileFor (files.getReference(i))) | out << "$(OBJDIR)/" << escapeSpaces (getObjectFileFor (files.getReference(i))) | ||||
| << ": " << escapeSpaces (files.getReference(i).toUnixStyle()) << newLine | << ": " << escapeSpaces (files.getReference(i).toUnixStyle()) << newLine | ||||
| << "\t-@mkdir -p $(OBJDIR)" << newLine | << "\t-@mkdir -p $(OBJDIR)" << newLine | ||||
| << "\t@echo $(notdir $<)" << newLine | |||||
| << "\t@echo \"Compiling " << files.getReference(i).getFileName() << "\"" << newLine | |||||
| << (files.getReference(i).hasFileExtension (".c") ? "\t@$(CC) $(CFLAGS) -o \"$@\" -c \"$<\"" | << (files.getReference(i).hasFileExtension (".c") ? "\t@$(CC) $(CFLAGS) -o \"$@\" -c \"$<\"" | ||||
| : "\t@$(CXX) $(CXXFLAGS) -o \"$@\" -c \"$<\"") | : "\t@$(CXX) $(CXXFLAGS) -o \"$@\" -c \"$<\"") | ||||
| << newLine << newLine; | << newLine << newLine; | ||||
| @@ -120,7 +120,7 @@ public: | |||||
| const Rectangle<int> getObjectPosition (const ValueTree& state) | const Rectangle<int> getObjectPosition (const ValueTree& state) | ||||
| { | { | ||||
| return getDocument().getCoordsFor (state).resolve (getDocument()).getSmallestIntegerContainer(); | |||||
| return getDocument().getCoordsFor (state).resolve (&getDocument()).getSmallestIntegerContainer(); | |||||
| } | } | ||||
| RelativeRectangle getObjectCoords (const ValueTree& state) | RelativeRectangle getObjectCoords (const ValueTree& state) | ||||
| @@ -176,14 +176,14 @@ public: | |||||
| const Rectangle<float> getObjectPosition (const ValueTree& state) | const Rectangle<float> getObjectPosition (const ValueTree& state) | ||||
| { | { | ||||
| ComponentDocument& doc = getDocument(); | ComponentDocument& doc = getDocument(); | ||||
| return doc.getCoordsFor (state).resolve (doc); | |||||
| return doc.getCoordsFor (state).resolve (&doc); | |||||
| } | } | ||||
| bool setObjectPosition (ValueTree& state, const Rectangle<float>& newBounds) | bool setObjectPosition (ValueTree& state, const Rectangle<float>& newBounds) | ||||
| { | { | ||||
| ComponentDocument& doc = getDocument(); | ComponentDocument& doc = getDocument(); | ||||
| RelativeRectangle pr (doc.getCoordsFor (state)); | RelativeRectangle pr (doc.getCoordsFor (state)); | ||||
| pr.moveToAbsolute (newBounds, doc); | |||||
| pr.moveToAbsolute (newBounds, &doc); | |||||
| return doc.setCoordsFor (state, pr); | return doc.setCoordsFor (state, pr); | ||||
| } | } | ||||
| @@ -191,7 +191,7 @@ public: | |||||
| float getMarkerPosition (const ValueTree& marker, bool isX) | float getMarkerPosition (const ValueTree& marker, bool isX) | ||||
| { | { | ||||
| ComponentDocument& doc = getDocument(); | ComponentDocument& doc = getDocument(); | ||||
| return (float) doc.getMarkerList (isX).getCoordinate (marker).resolve (doc); | |||||
| return (float) doc.getMarkerList (isX).getCoordinate (marker).resolve (&doc); | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -80,7 +80,7 @@ void ComponentViewer::handleAsyncUpdate() | |||||
| background = Colour::fromString (componentDocument->getBackgroundColour().toString()); | background = Colour::fromString (componentDocument->getBackgroundColour().toString()); | ||||
| if (layoutManager == 0) | if (layoutManager == 0) | ||||
| layoutManager = new ComponentAutoLayoutManager (this); | |||||
| layoutManager = new RelativeRectangleLayoutManager (this); | |||||
| int i; | int i; | ||||
| for (i = getNumChildComponents(); --i >= 0;) | for (i = getNumChildComponents(); --i >= 0;) | ||||
| @@ -62,7 +62,7 @@ private: | |||||
| ComponentDocument* componentDocument; | ComponentDocument* componentDocument; | ||||
| ValueTree documentRoot; | ValueTree documentRoot; | ||||
| ScopedPointer<ComponentAutoLayoutManager> layoutManager; | |||||
| ScopedPointer<RelativeRectangleLayoutManager> layoutManager; | |||||
| Colour background; | Colour background; | ||||
| ComponentViewer (const ComponentViewer&); | ComponentViewer (const ComponentViewer&); | ||||
| @@ -53,7 +53,7 @@ public: | |||||
| void createCanvas() | void createCanvas() | ||||
| { | { | ||||
| initialise (new DrawableEditorCanvas (editor), toolbarFactory, | initialise (new DrawableEditorCanvas (editor), toolbarFactory, | ||||
| new DrawableTreeViewItem (editor, editor.getDocument().getRootDrawableNode())); | |||||
| new DrawableTreeViewItem (editor, editor.getDocument().getRootDrawableNode().getState())); | |||||
| } | } | ||||
| SelectedItemSet<String>& getSelection() | SelectedItemSet<String>& getSelection() | ||||
| @@ -117,17 +117,10 @@ void DrawableEditor::selectionToBack() | |||||
| void DrawableEditor::showNewShapeMenu (Component* componentToAttachTo) | void DrawableEditor::showNewShapeMenu (Component* componentToAttachTo) | ||||
| { | { | ||||
| /* | |||||
| PopupMenu m; | PopupMenu m; | ||||
| getDocument().addNewComponentMenuItems (m); | |||||
| getDocument().addNewItemMenuItems (m); | |||||
| const int r = m.showAt (componentToAttachTo); | const int r = m.showAt (componentToAttachTo); | ||||
| const ValueTree newComp (getDocument().performNewComponentMenuItem (r)); | |||||
| if (newComp.isValid()) | |||||
| getSelection().selectOnly (newComp [ComponentDocument::idProperty]); | |||||
| */ | |||||
| getDocument().performNewItemMenuItem (r); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -54,8 +54,19 @@ public: | |||||
| void updateComponents() | void updateComponents() | ||||
| { | { | ||||
| drawable = Drawable::createFromValueTree (getEditor().getDocument().getRootDrawableNode(), 0); | |||||
| getComponentHolder()->repaint(); | |||||
| DrawableDocument& doc = getEditor().getDocument(); | |||||
| if (drawable == 0) | |||||
| { | |||||
| drawable = Drawable::createFromValueTree (doc.getRootDrawableNode().getState(), &doc); | |||||
| getComponentHolder()->repaint(); | |||||
| } | |||||
| else | |||||
| { | |||||
| const Rectangle<float> damage (drawable->refreshFromValueTree (doc.getRootDrawableNode().getState(), &doc)); | |||||
| getComponentHolder()->repaint (damage.getSmallestIntegerContainer()); | |||||
| } | |||||
| startTimer (500); | startTimer (500); | ||||
| } | } | ||||
| @@ -89,9 +100,9 @@ public: | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| // getDocument().addNewComponentMenuItems (m); | |||||
| // const int r = m.show(); | |||||
| // getDocument().performNewComponentMenuItem (r); | |||||
| getDocument().addNewItemMenuItems (m); | |||||
| const int r = m.show(); | |||||
| getDocument().performNewItemMenuItem (r); | |||||
| } | } | ||||
| } | } | ||||
| @@ -38,14 +38,14 @@ public: | |||||
| DrawableTreeViewItem (DrawableEditor& editor_, const ValueTree& drawableRoot) | DrawableTreeViewItem (DrawableEditor& editor_, const ValueTree& drawableRoot) | ||||
| : editor (editor_), node (drawableRoot), typeName (drawableRoot.getType().toString()) | : editor (editor_), node (drawableRoot), typeName (drawableRoot.getType().toString()) | ||||
| { | { | ||||
| node.addListener (this); | |||||
| node.getState().addListener (this); | |||||
| editor.getSelection().addChangeListener (this); | editor.getSelection().addChangeListener (this); | ||||
| } | } | ||||
| ~DrawableTreeViewItem() | ~DrawableTreeViewItem() | ||||
| { | { | ||||
| editor.getSelection().removeChangeListener (this); | editor.getSelection().removeChangeListener (this); | ||||
| node.removeListener (this); | |||||
| node.getState().removeListener (this); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -55,7 +55,7 @@ public: | |||||
| void valueTreeChildrenChanged (ValueTree& tree) | void valueTreeChildrenChanged (ValueTree& tree) | ||||
| { | { | ||||
| if (tree == node) | |||||
| if (tree == node.getState()) | |||||
| refreshSubItems(); | refreshSubItems(); | ||||
| } | } | ||||
| @@ -67,14 +67,13 @@ public: | |||||
| // TreeViewItem stuff.. | // TreeViewItem stuff.. | ||||
| bool mightContainSubItems() | bool mightContainSubItems() | ||||
| { | { | ||||
| return node.getType() == DrawableComposite::valueTreeType | |||||
| && node.getNumChildren() > 0; | |||||
| return node.getState().getType() == DrawableComposite::valueTreeType; | |||||
| } | } | ||||
| const String getUniqueName() const | const String getUniqueName() const | ||||
| { | { | ||||
| jassert (node [Ids::id_].toString().isNotEmpty()); | |||||
| return node [Ids::id_]; | |||||
| jassert (node.getID().isNotEmpty()); | |||||
| return node.getID(); | |||||
| } | } | ||||
| void itemOpennessChanged (bool isNowOpen) | void itemOpennessChanged (bool isNowOpen) | ||||
| @@ -85,15 +84,17 @@ public: | |||||
| void refreshSubItems() | void refreshSubItems() | ||||
| { | { | ||||
| if (node.getType() == DrawableComposite::valueTreeType) | |||||
| if (node.getState().getType() == DrawableComposite::valueTreeType) | |||||
| { | { | ||||
| ScopedPointer <XmlElement> oldOpenness (getOpennessState()); | ScopedPointer <XmlElement> oldOpenness (getOpennessState()); | ||||
| clearSubItems(); | clearSubItems(); | ||||
| for (int i = 0; i < node.getNumChildren(); ++i) | |||||
| DrawableComposite::ValueTreeWrapper composite (node.getState()); | |||||
| for (int i = 0; i < composite.getNumDrawables(); ++i) | |||||
| { | { | ||||
| ValueTree subNode (node.getChild (i)); | |||||
| ValueTree subNode (composite.getDrawableState (i)); | |||||
| DrawableTreeViewItem* const item = new DrawableTreeViewItem (editor, subNode); | DrawableTreeViewItem* const item = new DrawableTreeViewItem (editor, subNode); | ||||
| addSubItem (item); | addSubItem (item); | ||||
| } | } | ||||
| @@ -114,7 +115,7 @@ public: | |||||
| const String getRenamingName() const | const String getRenamingName() const | ||||
| { | { | ||||
| return node ["name"]; | |||||
| return node.getID(); | |||||
| } | } | ||||
| void setName (const String& newName) | void setName (const String& newName) | ||||
| @@ -138,7 +139,7 @@ public: | |||||
| void itemSelectionChanged (bool isNowSelected) | void itemSelectionChanged (bool isNowSelected) | ||||
| { | { | ||||
| const String objectId (DrawableDocument::getIdFor (node)); | |||||
| const String objectId (node.getID()); | |||||
| if (isNowSelected) | if (isNowSelected) | ||||
| editor.getSelection().addToSelection (objectId); | editor.getSelection().addToSelection (objectId); | ||||
| @@ -148,7 +149,7 @@ public: | |||||
| void changeListenerCallback (void*) | void changeListenerCallback (void*) | ||||
| { | { | ||||
| setSelected (editor.getSelection().isSelected (DrawableDocument::getIdFor (node)), false); | |||||
| setSelected (editor.getSelection().isSelected (node.getID()), false); | |||||
| } | } | ||||
| const String getTooltip() | const String getTooltip() | ||||
| @@ -194,7 +195,7 @@ public: | |||||
| //============================================================================== | //============================================================================== | ||||
| DrawableEditor& editor; | DrawableEditor& editor; | ||||
| ValueTree node; | |||||
| Drawable::ValueTreeWrapperBase node; | |||||
| private: | private: | ||||
| String typeName; | String typeName; | ||||
| @@ -243,7 +243,7 @@ public: | |||||
| void updatePosition() | void updatePosition() | ||||
| { | { | ||||
| RelativeCoordinate coord (getMarkerList().getCoordinate (marker)); | RelativeCoordinate coord (getMarkerList().getCoordinate (marker)); | ||||
| const int pos = roundToInt (coord.resolve (getMarkerList())); | |||||
| const int pos = roundToInt (coord.resolve (&getMarkerList())); | |||||
| const int width = 8; | const int width = 8; | ||||
| if (isX) | if (isX) | ||||
| @@ -309,7 +309,7 @@ public: | |||||
| canvas->getUndoManager().beginNewTransaction(); | canvas->getUndoManager().beginNewTransaction(); | ||||
| RelativeCoordinate coord (getMarkerList().getCoordinate (marker)); | RelativeCoordinate coord (getMarkerList().getCoordinate (marker)); | ||||
| dragStartPos = coord.resolve (getMarkerList()); | |||||
| dragStartPos = coord.resolve (&getMarkerList()); | |||||
| } | } | ||||
| } | } | ||||
| @@ -335,7 +335,7 @@ public: | |||||
| // (can't use getDistanceFromDragStart() because it doesn't take into account auto-scrolling) | // (can't use getDistanceFromDragStart() because it doesn't take into account auto-scrolling) | ||||
| coord.moveToAbsolute (jmax (0, roundToInt (dragStartPos + (isX ? e2.x - mouseDownPos.getX() | coord.moveToAbsolute (jmax (0, roundToInt (dragStartPos + (isX ? e2.x - mouseDownPos.getX() | ||||
| : e2.y - mouseDownPos.getY()))), | : e2.y - mouseDownPos.getY()))), | ||||
| getMarkerList()); | |||||
| &getMarkerList()); | |||||
| getMarkerList().setCoordinate (marker, coord); | getMarkerList().setCoordinate (marker, coord); | ||||
| } | } | ||||
| else | else | ||||
| @@ -26,10 +26,10 @@ | |||||
| #ifndef __JUCER_EDITORCANVAS_H_EF886D17__ | #ifndef __JUCER_EDITORCANVAS_H_EF886D17__ | ||||
| #define __JUCER_EDITORCANVAS_H_EF886D17__ | #define __JUCER_EDITORCANVAS_H_EF886D17__ | ||||
| #include "../../utility/jucer_Coordinate.h" | |||||
| #include "../../utility/jucer_MarkerListBase.h" | #include "../../utility/jucer_MarkerListBase.h" | ||||
| class EditorPanelBase; | class EditorPanelBase; | ||||
| //============================================================================== | //============================================================================== | ||||
| class EditorCanvasBase : public Component, | class EditorCanvasBase : public Component, | ||||
| public ValueTree::Listener, | public ValueTree::Listener, | ||||
| @@ -1,167 +0,0 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||||
| Copyright 2004-10 by Raw Material Software Ltd. | |||||
| ------------------------------------------------------------------------------ | |||||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||||
| Public License (Version 2), as published by the Free Software Foundation. | |||||
| A copy of the license is included in the JUCE distribution, or can be found | |||||
| online at www.gnu.org/licenses. | |||||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
| ------------------------------------------------------------------------------ | |||||
| To release a closed-source product which uses JUCE, commercial licenses are | |||||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| #include "jucer_Coordinate.h" | |||||
| //============================================================================== | |||||
| ComponentAutoLayoutManager::ComponentAutoLayoutManager (Component* parentComponent) | |||||
| : parent (parentComponent) | |||||
| { | |||||
| parent->addComponentListener (this); | |||||
| } | |||||
| ComponentAutoLayoutManager::~ComponentAutoLayoutManager() | |||||
| { | |||||
| parent->removeComponentListener (this); | |||||
| for (int i = components.size(); --i >= 0;) | |||||
| components.getUnchecked(i)->component->removeComponentListener (this); | |||||
| } | |||||
| void ComponentAutoLayoutManager::setMarker (const String& name, const RelativeCoordinate& coord) | |||||
| { | |||||
| for (int i = markers.size(); --i >= 0;) | |||||
| { | |||||
| MarkerPosition* m = markers.getUnchecked(i); | |||||
| if (m->markerName == name) | |||||
| { | |||||
| m->position = coord; | |||||
| applyLayout(); | |||||
| return; | |||||
| } | |||||
| } | |||||
| markers.add (new MarkerPosition (name, coord)); | |||||
| applyLayout(); | |||||
| } | |||||
| void ComponentAutoLayoutManager::setComponentBounds (Component* comp, const String& name, const RelativeRectangle& coords) | |||||
| { | |||||
| jassert (comp != 0); | |||||
| // All the components that this layout manages must be inside the parent component.. | |||||
| jassert (parent->isParentOf (comp)); | |||||
| for (int i = components.size(); --i >= 0;) | |||||
| { | |||||
| ComponentPosition* c = components.getUnchecked(i); | |||||
| if (c->component == comp) | |||||
| { | |||||
| c->name = name; | |||||
| c->coords = coords; | |||||
| triggerAsyncUpdate(); | |||||
| return; | |||||
| } | |||||
| } | |||||
| components.add (new ComponentPosition (comp, name, coords)); | |||||
| comp->addComponentListener (this); | |||||
| triggerAsyncUpdate(); | |||||
| } | |||||
| void ComponentAutoLayoutManager::applyLayout() | |||||
| { | |||||
| for (int i = components.size(); --i >= 0;) | |||||
| { | |||||
| ComponentPosition* c = components.getUnchecked(i); | |||||
| // All the components that this layout manages must be inside the parent component.. | |||||
| jassert (parent->isParentOf (c->component)); | |||||
| c->component->setBounds (c->coords.resolve (*this).getSmallestIntegerContainer()); | |||||
| } | |||||
| } | |||||
| const RelativeCoordinate ComponentAutoLayoutManager::findNamedCoordinate (const String& objectName, const String& edge) const | |||||
| { | |||||
| if (objectName == RelativeCoordinate::Strings::parent) | |||||
| { | |||||
| if (edge == RelativeCoordinate::Strings::right) return RelativeCoordinate ((double) parent->getWidth(), true); | |||||
| if (edge == RelativeCoordinate::Strings::bottom) return RelativeCoordinate ((double) parent->getHeight(), false); | |||||
| } | |||||
| if (objectName.isNotEmpty() && edge.isNotEmpty()) | |||||
| { | |||||
| for (int i = components.size(); --i >= 0;) | |||||
| { | |||||
| ComponentPosition* c = components.getUnchecked(i); | |||||
| if (c->name == objectName) | |||||
| { | |||||
| if (edge == RelativeCoordinate::Strings::left) return c->coords.left; | |||||
| if (edge == RelativeCoordinate::Strings::right) return c->coords.right; | |||||
| if (edge == RelativeCoordinate::Strings::top) return c->coords.top; | |||||
| if (edge == RelativeCoordinate::Strings::bottom) return c->coords.bottom; | |||||
| } | |||||
| } | |||||
| } | |||||
| for (int i = markers.size(); --i >= 0;) | |||||
| { | |||||
| MarkerPosition* m = markers.getUnchecked(i); | |||||
| if (m->markerName == objectName) | |||||
| return m->position; | |||||
| } | |||||
| return RelativeCoordinate(); | |||||
| } | |||||
| void ComponentAutoLayoutManager::componentMovedOrResized (Component& component, bool wasMoved, bool wasResized) | |||||
| { | |||||
| triggerAsyncUpdate(); | |||||
| if (parent == &component) | |||||
| handleUpdateNowIfNeeded(); | |||||
| } | |||||
| void ComponentAutoLayoutManager::componentBeingDeleted (Component& component) | |||||
| { | |||||
| for (int i = components.size(); --i >= 0;) | |||||
| { | |||||
| ComponentPosition* c = components.getUnchecked(i); | |||||
| if (c->component == &component) | |||||
| { | |||||
| components.remove (i); | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| void ComponentAutoLayoutManager::handleAsyncUpdate() | |||||
| { | |||||
| applyLayout(); | |||||
| } | |||||
| ComponentAutoLayoutManager::MarkerPosition::MarkerPosition (const String& name, const RelativeCoordinate& coord) | |||||
| : markerName (name), position (coord) | |||||
| { | |||||
| } | |||||
| ComponentAutoLayoutManager::ComponentPosition::ComponentPosition (Component* component_, const String& name_, const RelativeRectangle& coords_) | |||||
| : component (component_), name (name_), coords (coords_) | |||||
| { | |||||
| } | |||||
| @@ -1,102 +0,0 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||||
| Copyright 2004-10 by Raw Material Software Ltd. | |||||
| ------------------------------------------------------------------------------ | |||||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||||
| Public License (Version 2), as published by the Free Software Foundation. | |||||
| A copy of the license is included in the JUCE distribution, or can be found | |||||
| online at www.gnu.org/licenses. | |||||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
| ------------------------------------------------------------------------------ | |||||
| To release a closed-source product which uses JUCE, commercial licenses are | |||||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| #ifndef __JUCER_COORDINATE_H_EF56ACFA__ | |||||
| #define __JUCER_COORDINATE_H_EF56ACFA__ | |||||
| #include "../jucer_Headers.h" | |||||
| //============================================================================== | |||||
| /** | |||||
| */ | |||||
| class ComponentAutoLayoutManager : public ComponentListener, | |||||
| public RelativeCoordinate::NamedCoordinateFinder, | |||||
| public AsyncUpdater | |||||
| { | |||||
| public: | |||||
| //============================================================================== | |||||
| /** | |||||
| */ | |||||
| ComponentAutoLayoutManager (Component* parentComponent); | |||||
| /** Destructor. */ | |||||
| ~ComponentAutoLayoutManager(); | |||||
| //============================================================================== | |||||
| /** | |||||
| */ | |||||
| void setMarker (const String& name, const RelativeCoordinate& coord); | |||||
| /** | |||||
| */ | |||||
| void setComponentBounds (Component* component, const String& componentName, const RelativeRectangle& bounds); | |||||
| /** | |||||
| */ | |||||
| void applyLayout(); | |||||
| //============================================================================== | |||||
| /** @internal */ | |||||
| const RelativeCoordinate findNamedCoordinate (const String& objectName, const String& edge) const; | |||||
| /** @internal */ | |||||
| void componentMovedOrResized (Component& component, bool wasMoved, bool wasResized); | |||||
| /** @internal */ | |||||
| void componentBeingDeleted (Component& component); | |||||
| /** @internal */ | |||||
| void handleAsyncUpdate(); | |||||
| juce_UseDebuggingNewOperator | |||||
| private: | |||||
| //============================================================================== | |||||
| struct ComponentPosition | |||||
| { | |||||
| ComponentPosition (Component* component, const String& name, const RelativeRectangle& coords); | |||||
| Component* component; | |||||
| String name; | |||||
| RelativeRectangle coords; | |||||
| }; | |||||
| struct MarkerPosition | |||||
| { | |||||
| MarkerPosition (const String& name, const RelativeCoordinate& coord); | |||||
| String markerName; | |||||
| RelativeCoordinate position; | |||||
| }; | |||||
| Component* parent; | |||||
| OwnedArray <ComponentPosition> components; | |||||
| OwnedArray <MarkerPosition> markers; | |||||
| ComponentAutoLayoutManager (const ComponentAutoLayoutManager&); | |||||
| ComponentAutoLayoutManager& operator= (const ComponentAutoLayoutManager&); | |||||
| }; | |||||
| #endif // __JUCER_COORDINATE_H_EF56ACFA__ | |||||
| @@ -34,7 +34,7 @@ class CoordinatePropertyComponent : public PropertyComponent, | |||||
| { | { | ||||
| public: | public: | ||||
| //============================================================================== | //============================================================================== | ||||
| CoordinatePropertyComponent (RelativeCoordinate::NamedCoordinateFinder& nameSource_, const String& name, | |||||
| CoordinatePropertyComponent (RelativeCoordinate::NamedCoordinateFinder* nameSource_, const String& name, | |||||
| const Value& coordValue_, bool isHorizontal_) | const Value& coordValue_, bool isHorizontal_) | ||||
| : PropertyComponent (name, 40), nameSource (nameSource_), | : PropertyComponent (name, 40), nameSource (nameSource_), | ||||
| coordValue (coordValue_), | coordValue (coordValue_), | ||||
| @@ -142,7 +142,7 @@ public: | |||||
| virtual const String pickMarker (TextButton* button, const String& currentMarker, bool isAnchor1) = 0; | virtual const String pickMarker (TextButton* button, const String& currentMarker, bool isAnchor1) = 0; | ||||
| protected: | protected: | ||||
| RelativeCoordinate::NamedCoordinateFinder& nameSource; | |||||
| RelativeCoordinate::NamedCoordinateFinder* nameSource; | |||||
| Value coordValue, textValue; | Value coordValue, textValue; | ||||
| Label* label; | Label* label; | ||||
| TextButton* proportionButton; | TextButton* proportionButton; | ||||
| @@ -56,7 +56,7 @@ public: | |||||
| { | { | ||||
| ValueTree v (getMarker (i)); | ValueTree v (getMarker (i)); | ||||
| RelativeCoordinate coord (getCoordinate (v)); | RelativeCoordinate coord (getCoordinate (v)); | ||||
| coord.renameAnchorIfUsed (oldName, newName, *this); | |||||
| coord.renameAnchorIfUsed (oldName, newName, this); | |||||
| setCoordinate (v, coord); | setCoordinate (v, coord); | ||||
| } | } | ||||
| } | } | ||||
| @@ -133,7 +133,7 @@ public: | |||||
| { | { | ||||
| public: | public: | ||||
| //============================================================================== | //============================================================================== | ||||
| PositionPropertyComponent (NamedCoordinateFinder& nameSource_, MarkerListBase& markerList_, | |||||
| PositionPropertyComponent (NamedCoordinateFinder* nameSource_, MarkerListBase& markerList_, | |||||
| const String& name, const ValueTree& markerState_, | const String& name, const ValueTree& markerState_, | ||||
| const Value& coordValue_) | const Value& coordValue_) | ||||
| : CoordinatePropertyComponent (nameSource_, name, coordValue_, markerList_.isHorizontal()), | : CoordinatePropertyComponent (nameSource_, name, coordValue_, markerList_.isHorizontal()), | ||||
| @@ -266,3 +266,143 @@ void FloatingLabelComponent::paint (Graphics& g) | |||||
| g.setColour (colour); | g.setColour (colour); | ||||
| glyphs.draw (g, AffineTransform::translation (1.0f, 1.0f)); | glyphs.draw (g, AffineTransform::translation (1.0f, 1.0f)); | ||||
| } | } | ||||
| //============================================================================== | |||||
| RelativeRectangleLayoutManager::RelativeRectangleLayoutManager (Component* parentComponent) | |||||
| : parent (parentComponent) | |||||
| { | |||||
| parent->addComponentListener (this); | |||||
| } | |||||
| RelativeRectangleLayoutManager::~RelativeRectangleLayoutManager() | |||||
| { | |||||
| parent->removeComponentListener (this); | |||||
| for (int i = components.size(); --i >= 0;) | |||||
| components.getUnchecked(i)->component->removeComponentListener (this); | |||||
| } | |||||
| void RelativeRectangleLayoutManager::setMarker (const String& name, const RelativeCoordinate& coord) | |||||
| { | |||||
| for (int i = markers.size(); --i >= 0;) | |||||
| { | |||||
| MarkerPosition* m = markers.getUnchecked(i); | |||||
| if (m->markerName == name) | |||||
| { | |||||
| m->position = coord; | |||||
| applyLayout(); | |||||
| return; | |||||
| } | |||||
| } | |||||
| markers.add (new MarkerPosition (name, coord)); | |||||
| applyLayout(); | |||||
| } | |||||
| void RelativeRectangleLayoutManager::setComponentBounds (Component* comp, const String& name, const RelativeRectangle& coords) | |||||
| { | |||||
| jassert (comp != 0); | |||||
| // All the components that this layout manages must be inside the parent component.. | |||||
| jassert (parent->isParentOf (comp)); | |||||
| for (int i = components.size(); --i >= 0;) | |||||
| { | |||||
| ComponentPosition* c = components.getUnchecked(i); | |||||
| if (c->component == comp) | |||||
| { | |||||
| c->name = name; | |||||
| c->coords = coords; | |||||
| triggerAsyncUpdate(); | |||||
| return; | |||||
| } | |||||
| } | |||||
| components.add (new ComponentPosition (comp, name, coords)); | |||||
| comp->addComponentListener (this); | |||||
| triggerAsyncUpdate(); | |||||
| } | |||||
| void RelativeRectangleLayoutManager::applyLayout() | |||||
| { | |||||
| for (int i = components.size(); --i >= 0;) | |||||
| { | |||||
| ComponentPosition* c = components.getUnchecked(i); | |||||
| // All the components that this layout manages must be inside the parent component.. | |||||
| jassert (parent->isParentOf (c->component)); | |||||
| c->component->setBounds (c->coords.resolve (this).getSmallestIntegerContainer()); | |||||
| } | |||||
| } | |||||
| const RelativeCoordinate RelativeRectangleLayoutManager::findNamedCoordinate (const String& objectName, const String& edge) const | |||||
| { | |||||
| if (objectName == RelativeCoordinate::Strings::parent) | |||||
| { | |||||
| if (edge == RelativeCoordinate::Strings::right) return RelativeCoordinate ((double) parent->getWidth(), true); | |||||
| if (edge == RelativeCoordinate::Strings::bottom) return RelativeCoordinate ((double) parent->getHeight(), false); | |||||
| } | |||||
| if (objectName.isNotEmpty() && edge.isNotEmpty()) | |||||
| { | |||||
| for (int i = components.size(); --i >= 0;) | |||||
| { | |||||
| ComponentPosition* c = components.getUnchecked(i); | |||||
| if (c->name == objectName) | |||||
| { | |||||
| if (edge == RelativeCoordinate::Strings::left) return c->coords.left; | |||||
| if (edge == RelativeCoordinate::Strings::right) return c->coords.right; | |||||
| if (edge == RelativeCoordinate::Strings::top) return c->coords.top; | |||||
| if (edge == RelativeCoordinate::Strings::bottom) return c->coords.bottom; | |||||
| } | |||||
| } | |||||
| } | |||||
| for (int i = markers.size(); --i >= 0;) | |||||
| { | |||||
| MarkerPosition* m = markers.getUnchecked(i); | |||||
| if (m->markerName == objectName) | |||||
| return m->position; | |||||
| } | |||||
| return RelativeCoordinate(); | |||||
| } | |||||
| void RelativeRectangleLayoutManager::componentMovedOrResized (Component& component, bool wasMoved, bool wasResized) | |||||
| { | |||||
| triggerAsyncUpdate(); | |||||
| if (parent == &component) | |||||
| handleUpdateNowIfNeeded(); | |||||
| } | |||||
| void RelativeRectangleLayoutManager::componentBeingDeleted (Component& component) | |||||
| { | |||||
| for (int i = components.size(); --i >= 0;) | |||||
| { | |||||
| ComponentPosition* c = components.getUnchecked(i); | |||||
| if (c->component == &component) | |||||
| { | |||||
| components.remove (i); | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| void RelativeRectangleLayoutManager::handleAsyncUpdate() | |||||
| { | |||||
| applyLayout(); | |||||
| } | |||||
| RelativeRectangleLayoutManager::MarkerPosition::MarkerPosition (const String& name, const RelativeCoordinate& coord) | |||||
| : markerName (name), position (coord) | |||||
| { | |||||
| } | |||||
| RelativeRectangleLayoutManager::ComponentPosition::ComponentPosition (Component* component_, const String& name_, const RelativeRectangle& coords_) | |||||
| : component (component_), name (name_), coords (coords_) | |||||
| { | |||||
| } | |||||
| @@ -136,3 +136,72 @@ private: | |||||
| JucerToolbarButton (const JucerToolbarButton&); | JucerToolbarButton (const JucerToolbarButton&); | ||||
| JucerToolbarButton& operator= (const JucerToolbarButton&); | JucerToolbarButton& operator= (const JucerToolbarButton&); | ||||
| }; | }; | ||||
| //============================================================================== | |||||
| /** | |||||
| */ | |||||
| class RelativeRectangleLayoutManager : public ComponentListener, | |||||
| public RelativeCoordinate::NamedCoordinateFinder, | |||||
| public AsyncUpdater | |||||
| { | |||||
| public: | |||||
| //============================================================================== | |||||
| /** | |||||
| */ | |||||
| RelativeRectangleLayoutManager (Component* parentComponent); | |||||
| /** Destructor. */ | |||||
| ~RelativeRectangleLayoutManager(); | |||||
| //============================================================================== | |||||
| /** | |||||
| */ | |||||
| void setMarker (const String& name, const RelativeCoordinate& coord); | |||||
| /** | |||||
| */ | |||||
| void setComponentBounds (Component* component, const String& componentName, const RelativeRectangle& bounds); | |||||
| /** | |||||
| */ | |||||
| void applyLayout(); | |||||
| //============================================================================== | |||||
| /** @internal */ | |||||
| const RelativeCoordinate findNamedCoordinate (const String& objectName, const String& edge) const; | |||||
| /** @internal */ | |||||
| void componentMovedOrResized (Component& component, bool wasMoved, bool wasResized); | |||||
| /** @internal */ | |||||
| void componentBeingDeleted (Component& component); | |||||
| /** @internal */ | |||||
| void handleAsyncUpdate(); | |||||
| juce_UseDebuggingNewOperator | |||||
| private: | |||||
| //============================================================================== | |||||
| struct ComponentPosition | |||||
| { | |||||
| ComponentPosition (Component* component, const String& name, const RelativeRectangle& coords); | |||||
| Component* component; | |||||
| String name; | |||||
| RelativeRectangle coords; | |||||
| }; | |||||
| struct MarkerPosition | |||||
| { | |||||
| MarkerPosition (const String& name, const RelativeCoordinate& coord); | |||||
| String markerName; | |||||
| RelativeCoordinate position; | |||||
| }; | |||||
| Component* parent; | |||||
| OwnedArray <ComponentPosition> components; | |||||
| OwnedArray <MarkerPosition> markers; | |||||
| RelativeRectangleLayoutManager (const RelativeRectangleLayoutManager&); | |||||
| RelativeRectangleLayoutManager& operator= (const RelativeRectangleLayoutManager&); | |||||
| }; | |||||
| @@ -63,12 +63,12 @@ clean: | |||||
| $(OBJDIR)/Main.o: ../../Source/Main.cpp | $(OBJDIR)/Main.o: ../../Source/Main.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling Main.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/JuceLibraryCode.o: ../../JuceLibraryCode/JuceLibraryCode.cpp | $(OBJDIR)/JuceLibraryCode.o: ../../JuceLibraryCode/JuceLibraryCode.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling JuceLibraryCode.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| -include $(OBJECTS:%.o=%.d) | -include $(OBJECTS:%.o=%.d) | ||||
| @@ -70,47 +70,47 @@ clean: | |||||
| $(OBJDIR)/FilterGraph.o: ../../Source/FilterGraph.cpp | $(OBJDIR)/FilterGraph.o: ../../Source/FilterGraph.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling FilterGraph.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/GraphEditorPanel.o: ../../Source/GraphEditorPanel.cpp | $(OBJDIR)/GraphEditorPanel.o: ../../Source/GraphEditorPanel.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling GraphEditorPanel.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/HostStartup.o: ../../Source/HostStartup.cpp | $(OBJDIR)/HostStartup.o: ../../Source/HostStartup.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling HostStartup.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/InternalFilters.o: ../../Source/InternalFilters.cpp | $(OBJDIR)/InternalFilters.o: ../../Source/InternalFilters.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling InternalFilters.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/MainHostWindow.o: ../../Source/MainHostWindow.cpp | $(OBJDIR)/MainHostWindow.o: ../../Source/MainHostWindow.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling MainHostWindow.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/JuceLibraryCode1.o: ../../JuceLibraryCode/JuceLibraryCode1.cpp | $(OBJDIR)/JuceLibraryCode1.o: ../../JuceLibraryCode/JuceLibraryCode1.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling JuceLibraryCode1.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/JuceLibraryCode2.o: ../../JuceLibraryCode/JuceLibraryCode2.cpp | $(OBJDIR)/JuceLibraryCode2.o: ../../JuceLibraryCode/JuceLibraryCode2.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling JuceLibraryCode2.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/JuceLibraryCode3.o: ../../JuceLibraryCode/JuceLibraryCode3.cpp | $(OBJDIR)/JuceLibraryCode3.o: ../../JuceLibraryCode/JuceLibraryCode3.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling JuceLibraryCode3.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/JuceLibraryCode4.o: ../../JuceLibraryCode/JuceLibraryCode4.cpp | $(OBJDIR)/JuceLibraryCode4.o: ../../JuceLibraryCode/JuceLibraryCode4.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling JuceLibraryCode4.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| -include $(OBJECTS:%.o=%.d) | -include $(OBJECTS:%.o=%.d) | ||||
| @@ -63,12 +63,12 @@ clean: | |||||
| $(OBJDIR)/Main.o: ../../Source/Main.cpp | $(OBJDIR)/Main.o: ../../Source/Main.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling Main.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/JuceLibraryCode.o: ../../JuceLibraryCode/JuceLibraryCode.cpp | $(OBJDIR)/JuceLibraryCode.o: ../../JuceLibraryCode/JuceLibraryCode.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling JuceLibraryCode.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| -include $(OBJECTS:%.o=%.d) | -include $(OBJECTS:%.o=%.d) | ||||
| @@ -67,32 +67,32 @@ clean: | |||||
| $(OBJDIR)/Main.o: ../../Source/Main.cpp | $(OBJDIR)/Main.o: ../../Source/Main.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling Main.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/MainComponent.o: ../../Source/MainComponent.cpp | $(OBJDIR)/MainComponent.o: ../../Source/MainComponent.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling MainComponent.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/JuceLibraryCode1.o: ../../JuceLibraryCode/JuceLibraryCode1.cpp | $(OBJDIR)/JuceLibraryCode1.o: ../../JuceLibraryCode/JuceLibraryCode1.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling JuceLibraryCode1.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/JuceLibraryCode2.o: ../../JuceLibraryCode/JuceLibraryCode2.cpp | $(OBJDIR)/JuceLibraryCode2.o: ../../JuceLibraryCode/JuceLibraryCode2.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling JuceLibraryCode2.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/JuceLibraryCode3.o: ../../JuceLibraryCode/JuceLibraryCode3.cpp | $(OBJDIR)/JuceLibraryCode3.o: ../../JuceLibraryCode/JuceLibraryCode3.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling JuceLibraryCode3.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/JuceLibraryCode4.o: ../../JuceLibraryCode/JuceLibraryCode4.cpp | $(OBJDIR)/JuceLibraryCode4.o: ../../JuceLibraryCode/JuceLibraryCode4.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling JuceLibraryCode4.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| -include $(OBJECTS:%.o=%.d) | -include $(OBJECTS:%.o=%.d) | ||||
| @@ -87,132 +87,132 @@ clean: | |||||
| $(OBJDIR)/ApplicationStartup.o: ../../Source/ApplicationStartup.cpp | $(OBJDIR)/ApplicationStartup.o: ../../Source/ApplicationStartup.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling ApplicationStartup.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/MainDemoWindow.o: ../../Source/MainDemoWindow.cpp | $(OBJDIR)/MainDemoWindow.o: ../../Source/MainDemoWindow.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling MainDemoWindow.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/AudioDemoLatencyPage.o: ../../Source/demos/AudioDemoLatencyPage.cpp | $(OBJDIR)/AudioDemoLatencyPage.o: ../../Source/demos/AudioDemoLatencyPage.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling AudioDemoLatencyPage.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/AudioDemoPlaybackPage.o: ../../Source/demos/AudioDemoPlaybackPage.cpp | $(OBJDIR)/AudioDemoPlaybackPage.o: ../../Source/demos/AudioDemoPlaybackPage.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling AudioDemoPlaybackPage.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/AudioDemoRecordPage.o: ../../Source/demos/AudioDemoRecordPage.cpp | $(OBJDIR)/AudioDemoRecordPage.o: ../../Source/demos/AudioDemoRecordPage.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling AudioDemoRecordPage.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/AudioDemoSetupPage.o: ../../Source/demos/AudioDemoSetupPage.cpp | $(OBJDIR)/AudioDemoSetupPage.o: ../../Source/demos/AudioDemoSetupPage.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling AudioDemoSetupPage.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/AudioDemoSynthPage.o: ../../Source/demos/AudioDemoSynthPage.cpp | $(OBJDIR)/AudioDemoSynthPage.o: ../../Source/demos/AudioDemoSynthPage.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling AudioDemoSynthPage.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/AudioDemoTabComponent.o: ../../Source/demos/AudioDemoTabComponent.cpp | $(OBJDIR)/AudioDemoTabComponent.o: ../../Source/demos/AudioDemoTabComponent.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling AudioDemoTabComponent.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/CameraDemo.o: ../../Source/demos/CameraDemo.cpp | $(OBJDIR)/CameraDemo.o: ../../Source/demos/CameraDemo.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling CameraDemo.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/CodeEditorDemo.o: ../../Source/demos/CodeEditorDemo.cpp | $(OBJDIR)/CodeEditorDemo.o: ../../Source/demos/CodeEditorDemo.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling CodeEditorDemo.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/DragAndDropDemo.o: ../../Source/demos/DragAndDropDemo.cpp | $(OBJDIR)/DragAndDropDemo.o: ../../Source/demos/DragAndDropDemo.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling DragAndDropDemo.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/FontsAndTextDemo.o: ../../Source/demos/FontsAndTextDemo.cpp | $(OBJDIR)/FontsAndTextDemo.o: ../../Source/demos/FontsAndTextDemo.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling FontsAndTextDemo.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/InterprocessCommsDemo.o: ../../Source/demos/InterprocessCommsDemo.cpp | $(OBJDIR)/InterprocessCommsDemo.o: ../../Source/demos/InterprocessCommsDemo.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling InterprocessCommsDemo.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/OpenGLDemo.o: ../../Source/demos/OpenGLDemo.cpp | $(OBJDIR)/OpenGLDemo.o: ../../Source/demos/OpenGLDemo.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling OpenGLDemo.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/QuickTimeDemo.o: ../../Source/demos/QuickTimeDemo.cpp | $(OBJDIR)/QuickTimeDemo.o: ../../Source/demos/QuickTimeDemo.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling QuickTimeDemo.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/RenderingTestComponent.o: ../../Source/demos/RenderingTestComponent.cpp | $(OBJDIR)/RenderingTestComponent.o: ../../Source/demos/RenderingTestComponent.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling RenderingTestComponent.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/TableDemo.o: ../../Source/demos/TableDemo.cpp | $(OBJDIR)/TableDemo.o: ../../Source/demos/TableDemo.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling TableDemo.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/ThreadingDemo.o: ../../Source/demos/ThreadingDemo.cpp | $(OBJDIR)/ThreadingDemo.o: ../../Source/demos/ThreadingDemo.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling ThreadingDemo.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/TreeViewDemo.o: ../../Source/demos/TreeViewDemo.cpp | $(OBJDIR)/TreeViewDemo.o: ../../Source/demos/TreeViewDemo.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling TreeViewDemo.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/WebBrowserDemo.o: ../../Source/demos/WebBrowserDemo.cpp | $(OBJDIR)/WebBrowserDemo.o: ../../Source/demos/WebBrowserDemo.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling WebBrowserDemo.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/WidgetsDemo.o: ../../Source/demos/WidgetsDemo.cpp | $(OBJDIR)/WidgetsDemo.o: ../../Source/demos/WidgetsDemo.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling WidgetsDemo.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/BinaryData.o: ../../JuceLibraryCode/BinaryData.cpp | $(OBJDIR)/BinaryData.o: ../../JuceLibraryCode/BinaryData.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling BinaryData.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/JuceLibraryCode1.o: ../../JuceLibraryCode/JuceLibraryCode1.cpp | $(OBJDIR)/JuceLibraryCode1.o: ../../JuceLibraryCode/JuceLibraryCode1.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling JuceLibraryCode1.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/JuceLibraryCode2.o: ../../JuceLibraryCode/JuceLibraryCode2.cpp | $(OBJDIR)/JuceLibraryCode2.o: ../../JuceLibraryCode/JuceLibraryCode2.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling JuceLibraryCode2.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/JuceLibraryCode3.o: ../../JuceLibraryCode/JuceLibraryCode3.cpp | $(OBJDIR)/JuceLibraryCode3.o: ../../JuceLibraryCode/JuceLibraryCode3.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling JuceLibraryCode3.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| $(OBJDIR)/JuceLibraryCode4.o: ../../JuceLibraryCode/JuceLibraryCode4.cpp | $(OBJDIR)/JuceLibraryCode4.o: ../../JuceLibraryCode/JuceLibraryCode4.cpp | ||||
| -@mkdir -p $(OBJDIR) | -@mkdir -p $(OBJDIR) | ||||
| @echo $(notdir $<) | |||||
| @echo "Compiling JuceLibraryCode4.cpp" | |||||
| @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" | ||||
| -include $(OBJECTS:%.o=%.d) | -include $(OBJECTS:%.o=%.d) | ||||
| @@ -150,7 +150,7 @@ public: | |||||
| return false; | return false; | ||||
| for (int i = numUsed; --i >= 0;) | for (int i = numUsed; --i >= 0;) | ||||
| if (data.elements [i] != other.data.elements [i]) | |||||
| if (! (data.elements [i] == other.data.elements [i])) | |||||
| return false; | return false; | ||||
| return true; | return true; | ||||
| @@ -40,6 +40,11 @@ inline NamedValueSet::NamedValue::NamedValue (const Identifier& name_, const var | |||||
| { | { | ||||
| } | } | ||||
| bool NamedValueSet::NamedValue::operator== (const NamedValueSet::NamedValue& other) const throw() | |||||
| { | |||||
| return name == other.name && value == other.value; | |||||
| } | |||||
| //============================================================================== | //============================================================================== | ||||
| NamedValueSet::NamedValueSet() throw() | NamedValueSet::NamedValueSet() throw() | ||||
| { | { | ||||
| @@ -60,6 +65,16 @@ NamedValueSet::~NamedValueSet() | |||||
| { | { | ||||
| } | } | ||||
| bool NamedValueSet::operator== (const NamedValueSet& other) const | |||||
| { | |||||
| return values == other.values; | |||||
| } | |||||
| bool NamedValueSet::operator!= (const NamedValueSet& other) const | |||||
| { | |||||
| return ! operator== (other); | |||||
| } | |||||
| int NamedValueSet::size() const throw() | int NamedValueSet::size() const throw() | ||||
| { | { | ||||
| return values.size(); | return values.size(); | ||||
| @@ -51,6 +51,9 @@ public: | |||||
| /** Destructor. */ | /** Destructor. */ | ||||
| ~NamedValueSet(); | ~NamedValueSet(); | ||||
| bool operator== (const NamedValueSet& other) const; | |||||
| bool operator!= (const NamedValueSet& other) const; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Returns the total number of values that the set contains. */ | /** Returns the total number of values that the set contains. */ | ||||
| int size() const throw(); | int size() const throw(); | ||||
| @@ -108,6 +111,7 @@ private: | |||||
| { | { | ||||
| NamedValue() throw(); | NamedValue() throw(); | ||||
| NamedValue (const Identifier& name, const var& value); | NamedValue (const Identifier& name, const var& value); | ||||
| bool operator== (const NamedValue& other) const throw(); | |||||
| Identifier name; | Identifier name; | ||||
| var value; | var value; | ||||
| @@ -500,6 +500,22 @@ void ValueTree::SharedObject::moveChild (int currentIndex, int newIndex, UndoMan | |||||
| } | } | ||||
| } | } | ||||
| bool ValueTree::SharedObject::isEquivalentTo (const SharedObject& other) const | |||||
| { | |||||
| if (type != other.type | |||||
| || properties.size() != other.properties.size() | |||||
| || children.size() != other.children.size() | |||||
| || properties != other.properties) | |||||
| return false; | |||||
| for (int i = 0; i < children.size(); ++i) | |||||
| if (! children.getUnchecked(i)->isEquivalentTo (*other.children.getUnchecked(i))) | |||||
| return false; | |||||
| return true; | |||||
| } | |||||
| //============================================================================== | //============================================================================== | ||||
| ValueTree::ValueTree() throw() | ValueTree::ValueTree() throw() | ||||
| : object (0) | : object (0) | ||||
| @@ -546,16 +562,22 @@ ValueTree::~ValueTree() | |||||
| object->valueTreesWithListeners.removeValue (this); | object->valueTreesWithListeners.removeValue (this); | ||||
| } | } | ||||
| bool ValueTree::operator== (const ValueTree& other) const | |||||
| bool ValueTree::operator== (const ValueTree& other) const throw() | |||||
| { | { | ||||
| return object == other.object; | return object == other.object; | ||||
| } | } | ||||
| bool ValueTree::operator!= (const ValueTree& other) const | |||||
| bool ValueTree::operator!= (const ValueTree& other) const throw() | |||||
| { | { | ||||
| return object != other.object; | return object != other.object; | ||||
| } | } | ||||
| bool ValueTree::isEquivalentTo (const ValueTree& other) const | |||||
| { | |||||
| return object == other.object | |||||
| || (object != 0 && other.object != 0 && object->isEquivalentTo (*other.object)); | |||||
| } | |||||
| ValueTree ValueTree::createCopy() const | ValueTree ValueTree::createCopy() const | ||||
| { | { | ||||
| return ValueTree (object != 0 ? new SharedObject (*object) : 0); | return ValueTree (object != 0 ? new SharedObject (*object) : 0); | ||||
| @@ -710,7 +732,7 @@ int ValueTree::indexOf (const ValueTree& child) const | |||||
| return object != 0 ? object->indexOf (child) : -1; | return object != 0 ? object->indexOf (child) : -1; | ||||
| } | } | ||||
| void ValueTree::addChild (ValueTree child, int index, UndoManager* const undoManager) | |||||
| void ValueTree::addChild (const ValueTree& child, int index, UndoManager* const undoManager) | |||||
| { | { | ||||
| if (object != 0) | if (object != 0) | ||||
| object->addChild (child.object, index, undoManager); | object->addChild (child.object, index, undoManager); | ||||
| @@ -102,13 +102,21 @@ public: | |||||
| Note that this isn't a value comparison - two independently-created trees which | Note that this isn't a value comparison - two independently-created trees which | ||||
| contain identical data are not considered equal. | contain identical data are not considered equal. | ||||
| */ | */ | ||||
| bool operator== (const ValueTree& other) const; | |||||
| bool operator== (const ValueTree& other) const throw(); | |||||
| /** Returns true if this and the other node refer to different underlying structures. | /** Returns true if this and the other node refer to different underlying structures. | ||||
| Note that this isn't a value comparison - two independently-created trees which | Note that this isn't a value comparison - two independently-created trees which | ||||
| contain identical data are not considered equal. | contain identical data are not considered equal. | ||||
| */ | */ | ||||
| bool operator!= (const ValueTree& other) const; | |||||
| bool operator!= (const ValueTree& other) const throw(); | |||||
| /** Performs a deep comparison between the properties and children of two trees. | |||||
| If all the properties and children of the two trees are the same (recursively), this | |||||
| returns true. | |||||
| The normal operator==() only checks whether two trees refer to the same shared data | |||||
| structure, so use this method if you need to do a proper value comparison. | |||||
| */ | |||||
| bool isEquivalentTo (const ValueTree& other) const; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Returns true if this node refers to some valid data. | /** Returns true if this node refers to some valid data. | ||||
| @@ -233,7 +241,7 @@ public: | |||||
| If the undoManager parameter is non-null, its UndoManager::perform() method will be used, | If the undoManager parameter is non-null, its UndoManager::perform() method will be used, | ||||
| so that this change can be undone. | so that this change can be undone. | ||||
| */ | */ | ||||
| void addChild (ValueTree child, int index, UndoManager* undoManager); | |||||
| void addChild (const ValueTree& child, int index, UndoManager* undoManager); | |||||
| /** Removes the specified child from this node's child-list. | /** Removes the specified child from this node's child-list. | ||||
| If the undoManager parameter is non-null, its UndoManager::perform() method will be used, | If the undoManager parameter is non-null, its UndoManager::perform() method will be used, | ||||
| @@ -464,6 +472,7 @@ private: | |||||
| void removeChild (int childIndex, UndoManager*); | void removeChild (int childIndex, UndoManager*); | ||||
| void removeAllChildren (UndoManager*); | void removeAllChildren (UndoManager*); | ||||
| void moveChild (int currentIndex, int newIndex, UndoManager*); | void moveChild (int currentIndex, int newIndex, UndoManager*); | ||||
| bool isEquivalentTo (const SharedObject& other) const; | |||||
| XmlElement* createXml() const; | XmlElement* createXml() const; | ||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| @@ -33,7 +33,7 @@ | |||||
| */ | */ | ||||
| #define JUCE_MAJOR_VERSION 1 | #define JUCE_MAJOR_VERSION 1 | ||||
| #define JUCE_MINOR_VERSION 52 | #define JUCE_MINOR_VERSION 52 | ||||
| #define JUCE_BUILDNUMBER 5 | |||||
| #define JUCE_BUILDNUMBER 6 | |||||
| /** Current Juce version number. | /** Current Juce version number. | ||||
| @@ -877,8 +877,7 @@ void ListBox::setHeaderComponent (Component* const newHeaderComponent) | |||||
| void ListBox::repaintRow (const int rowNumber) throw() | void ListBox::repaintRow (const int rowNumber) throw() | ||||
| { | { | ||||
| const Rectangle<int> r (getRowPosition (rowNumber, true)); | |||||
| repaint (r.getX(), r.getY(), r.getWidth(), r.getHeight()); | |||||
| repaint (getRowPosition (rowNumber, true)); | |||||
| } | } | ||||
| Image* ListBox::createSnapshotOfSelectedRows (int& imageX, int& imageY) | Image* ListBox::createSnapshotOfSelectedRows (int& imageX, int& imageY) | ||||
| @@ -1338,8 +1338,9 @@ void TreeViewItem::repaintItem() const | |||||
| { | { | ||||
| if (ownerView != 0 && areAllParentsOpen()) | if (ownerView != 0 && areAllParentsOpen()) | ||||
| { | { | ||||
| const Rectangle<int> r (getItemPosition (true)); | |||||
| ownerView->viewport->repaint (0, r.getY(), r.getRight(), r.getHeight()); | |||||
| Rectangle<int> r (getItemPosition (true)); | |||||
| r.setLeft (0); | |||||
| ownerView->viewport->repaint (r); | |||||
| } | } | ||||
| } | } | ||||
| @@ -1555,6 +1555,11 @@ void Component::repaint (const int x, const int y, | |||||
| internalRepaint (x, y, w, h); | internalRepaint (x, y, w, h); | ||||
| } | } | ||||
| void Component::repaint (const Rectangle<int>& area) | |||||
| { | |||||
| repaint (area.getX(), area.getY(), area.getWidth(), area.getHeight()); | |||||
| } | |||||
| void Component::internalRepaint (int x, int y, int w, int h) | void Component::internalRepaint (int x, int y, int w, int h) | ||||
| { | { | ||||
| // if component methods are being called from threads other than the message | // if component methods are being called from threads other than the message | ||||
| @@ -1596,7 +1601,7 @@ void Component::internalRepaint (int x, int y, int w, int h) | |||||
| ComponentPeer* const peer = getPeer(); | ComponentPeer* const peer = getPeer(); | ||||
| if (peer != 0) | if (peer != 0) | ||||
| peer->repaint (x, y, w, h); | |||||
| peer->repaint (Rectangle<int> (x, y, w, h)); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -819,6 +819,21 @@ public: | |||||
| */ | */ | ||||
| void repaint (int x, int y, int width, int height); | void repaint (int x, int y, int width, int height); | ||||
| /** Marks a subsection of this component as needing to be redrawn. | |||||
| Calling this will not do any repainting immediately, but will mark the given region | |||||
| of the component as 'dirty'. At some point in the near future the operating system | |||||
| will send a paint message, which will redraw all the dirty regions of all components. | |||||
| There's no guarantee about how soon after calling repaint() the redraw will actually | |||||
| happen, and other queued events may be delivered before a redraw is done. | |||||
| The region that is passed in will be clipped to keep it within the bounds of this | |||||
| component. | |||||
| @see repaint() | |||||
| */ | |||||
| void repaint (const Rectangle<int>& area); | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Makes the component use an internal buffer to optimise its redrawing. | /** Makes the component use an internal buffer to optimise its redrawing. | ||||
| @@ -117,14 +117,14 @@ public: | |||||
| && ((unsigned int) position.getY()) < (unsigned int) magnifierComp->getHeight(); | && ((unsigned int) position.getY()) < (unsigned int) magnifierComp->getHeight(); | ||||
| } | } | ||||
| void repaint (int x, int y, int w, int h) | |||||
| void repaint (const Rectangle<int>& area) | |||||
| { | { | ||||
| const double zoom = magnifierComp->getScaleFactor(); | const double zoom = magnifierComp->getScaleFactor(); | ||||
| magnifierComp->repaint ((int) (x * zoom), | |||||
| (int) (y * zoom), | |||||
| roundToInt (w * zoom) + 1, | |||||
| roundToInt (h * zoom) + 1); | |||||
| magnifierComp->repaint ((int) (area.getX() * zoom), | |||||
| (int) (area.getY() * zoom), | |||||
| roundToInt (area.getWidth() * zoom) + 1, | |||||
| roundToInt (area.getHeight() * zoom) + 1); | |||||
| } | } | ||||
| void performAnyPendingRepaintsNow() | void performAnyPendingRepaintsNow() | ||||
| @@ -281,7 +281,7 @@ public: | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Invalidates a region of the window to be repainted asynchronously. */ | /** Invalidates a region of the window to be repainted asynchronously. */ | ||||
| virtual void repaint (int x, int y, int w, int h) = 0; | |||||
| virtual void repaint (const Rectangle<int>& area) = 0; | |||||
| /** This can be called (from the message thread) to cause the immediate redrawing | /** This can be called (from the message thread) to cause the immediate redrawing | ||||
| of any areas of this window that need repainting. | of any areas of this window that need repainting. | ||||
| @@ -95,9 +95,7 @@ DocumentWindow::~DocumentWindow() | |||||
| //============================================================================== | //============================================================================== | ||||
| void DocumentWindow::repaintTitleBar() | void DocumentWindow::repaintTitleBar() | ||||
| { | { | ||||
| const Rectangle<int> titleBarArea (getTitleBarArea()); | |||||
| repaint (titleBarArea.getX(), titleBarArea.getY(), | |||||
| titleBarArea.getWidth(), titleBarArea.getHeight()); | |||||
| repaint (getTitleBarArea()); | |||||
| } | } | ||||
| void DocumentWindow::setName (const String& newName) | void DocumentWindow::setName (const String& newName) | ||||
| @@ -177,12 +177,13 @@ public: | |||||
| x = endX; | x = endX; | ||||
| } | } | ||||
| levelAccumulator >>= 8; | |||||
| if (levelAccumulator > 0) | if (levelAccumulator > 0) | ||||
| { | { | ||||
| x >>= 8; | x >>= 8; | ||||
| jassert (x >= bounds.getX() && x < bounds.getRight()); | jassert (x >= bounds.getX() && x < bounds.getRight()); | ||||
| levelAccumulator >>= 8; | |||||
| if (levelAccumulator >> 8) | if (levelAccumulator >> 8) | ||||
| iterationCallback.handleEdgeTablePixelFull (x); | iterationCallback.handleEdgeTablePixelFull (x); | ||||
| else | else | ||||
| @@ -76,6 +76,16 @@ FillType::~FillType() throw() | |||||
| { | { | ||||
| } | } | ||||
| bool FillType::operator== (const FillType& other) const | |||||
| { | |||||
| return colour == other.colour && gradient == other.gradient && image == other.image; | |||||
| } | |||||
| bool FillType::operator!= (const FillType& other) const | |||||
| { | |||||
| return ! operator== (other); | |||||
| } | |||||
| void FillType::setColour (const Colour& newColour) throw() | void FillType::setColour (const Colour& newColour) throw() | ||||
| { | { | ||||
| gradient = 0; | gradient = 0; | ||||
| @@ -110,4 +120,10 @@ void FillType::setOpacity (const float newOpacity) throw() | |||||
| colour = colour.withAlpha (newOpacity); | colour = colour.withAlpha (newOpacity); | ||||
| } | } | ||||
| bool FillType::isInvisible() const throw() | |||||
| { | |||||
| return colour.isTransparent() || (gradient != 0 && gradient->isInvisible()); | |||||
| } | |||||
| END_JUCE_NAMESPACE | END_JUCE_NAMESPACE | ||||
| @@ -103,6 +103,12 @@ public: | |||||
| */ | */ | ||||
| float getOpacity() const throw() { return colour.getFloatAlpha(); } | float getOpacity() const throw() { return colour.getFloatAlpha(); } | ||||
| /** Returns true if this fill type is completely transparent. */ | |||||
| bool isInvisible() const throw(); | |||||
| bool operator== (const FillType& other) const; | |||||
| bool operator!= (const FillType& other) const; | |||||
| /** The solid colour being used. | /** The solid colour being used. | ||||
| If the fill type is not a solid colour, the alpha channel of this colour indicates | If the fill type is not a solid colour, the alpha channel of this colour indicates | ||||
| @@ -1899,41 +1899,38 @@ public: | |||||
| shapeToFill = clip->applyClipTo (shapeToFill); | shapeToFill = clip->applyClipTo (shapeToFill); | ||||
| if (shapeToFill != 0) | if (shapeToFill != 0) | ||||
| fillShapeWithoutClipping (image, shapeToFill, replaceContents); | |||||
| } | |||||
| { | |||||
| Image::BitmapData destData (image, 0, 0, image.getWidth(), image.getHeight(), true); | |||||
| void fillShapeWithoutClipping (Image& image, const SoftwareRendererClasses::ClipRegionBase::Ptr& shapeToFill, const bool replaceContents) | |||||
| { | |||||
| Image::BitmapData destData (image, 0, 0, image.getWidth(), image.getHeight(), true); | |||||
| if (fillType.isGradient()) | |||||
| { | |||||
| jassert (! replaceContents); // that option is just for solid colours | |||||
| if (fillType.isGradient()) | |||||
| { | |||||
| jassert (! replaceContents); // that option is just for solid colours | |||||
| ColourGradient g2 (*(fillType.gradient)); | |||||
| g2.multiplyOpacity (fillType.getOpacity()); | |||||
| g2.point1.addXY (-0.5f, -0.5f); | |||||
| g2.point2.addXY (-0.5f, -0.5f); | |||||
| AffineTransform transform (fillType.transform.translated ((float) xOffset, (float) yOffset)); | |||||
| const bool isIdentity = transform.isOnlyTranslation(); | |||||
| ColourGradient g2 (*(fillType.gradient)); | |||||
| g2.multiplyOpacity (fillType.getOpacity()); | |||||
| g2.point1.addXY (-0.5f, -0.5f); | |||||
| g2.point2.addXY (-0.5f, -0.5f); | |||||
| AffineTransform transform (fillType.transform.translated ((float) xOffset, (float) yOffset)); | |||||
| const bool isIdentity = transform.isOnlyTranslation(); | |||||
| if (isIdentity) | |||||
| { | |||||
| // If our translation doesn't involve any distortion, we can speed it up.. | |||||
| g2.point1.applyTransform (transform); | |||||
| g2.point2.applyTransform (transform); | |||||
| transform = AffineTransform::identity; | |||||
| } | |||||
| if (isIdentity) | |||||
| shapeToFill->fillAllWithGradient (destData, g2, transform, isIdentity); | |||||
| } | |||||
| else if (fillType.isTiledImage()) | |||||
| { | { | ||||
| // If our translation doesn't involve any distortion, we can speed it up.. | |||||
| g2.point1.applyTransform (transform); | |||||
| g2.point2.applyTransform (transform); | |||||
| transform = AffineTransform::identity; | |||||
| renderImage (image, *(fillType.image), fillType.image->getBounds(), fillType.transform, shapeToFill); | |||||
| } | |||||
| else | |||||
| { | |||||
| shapeToFill->fillAllWithColour (destData, fillType.colour.getPixelARGB(), replaceContents); | |||||
| } | } | ||||
| shapeToFill->fillAllWithGradient (destData, g2, transform, isIdentity); | |||||
| } | |||||
| else if (fillType.isTiledImage()) | |||||
| { | |||||
| renderImage (image, *(fillType.image), fillType.image->getBounds(), fillType.transform, shapeToFill); | |||||
| } | |||||
| else | |||||
| { | |||||
| shapeToFill->fillAllWithColour (destData, fillType.colour.getPixelARGB(), replaceContents); | |||||
| } | } | ||||
| } | } | ||||
| @@ -36,7 +36,6 @@ BEGIN_JUCE_NAMESPACE | |||||
| #include "../../../text/juce_XmlDocument.h" | #include "../../../text/juce_XmlDocument.h" | ||||
| #include "../../../io/files/juce_FileInputStream.h" | #include "../../../io/files/juce_FileInputStream.h" | ||||
| const Identifier Drawable::idProperty ("id"); | |||||
| //============================================================================== | //============================================================================== | ||||
| Drawable::RenderingContext::RenderingContext (Graphics& g_, | Drawable::RenderingContext::RenderingContext (Graphics& g_, | ||||
| @@ -50,6 +49,7 @@ Drawable::RenderingContext::RenderingContext (Graphics& g_, | |||||
| //============================================================================== | //============================================================================== | ||||
| Drawable::Drawable() | Drawable::Drawable() | ||||
| : parent (0) | |||||
| { | { | ||||
| } | } | ||||
| @@ -57,8 +57,7 @@ Drawable::~Drawable() | |||||
| { | { | ||||
| } | } | ||||
| void Drawable::draw (Graphics& g, const float opacity, | |||||
| const AffineTransform& transform) const | |||||
| void Drawable::draw (Graphics& g, const float opacity, const AffineTransform& transform) const | |||||
| { | { | ||||
| render (RenderingContext (g, transform, opacity)); | render (RenderingContext (g, transform, opacity)); | ||||
| } | } | ||||
| @@ -156,4 +155,131 @@ Drawable* Drawable::createFromValueTree (const ValueTree& tree, ImageProvider* i | |||||
| } | } | ||||
| //============================================================================== | |||||
| const Identifier Drawable::ValueTreeWrapperBase::idProperty ("id"); | |||||
| const Identifier Drawable::ValueTreeWrapperBase::type ("type"); | |||||
| const Identifier Drawable::ValueTreeWrapperBase::x1 ("x1"); | |||||
| const Identifier Drawable::ValueTreeWrapperBase::x2 ("x2"); | |||||
| const Identifier Drawable::ValueTreeWrapperBase::y1 ("y1"); | |||||
| const Identifier Drawable::ValueTreeWrapperBase::y2 ("y2"); | |||||
| const Identifier Drawable::ValueTreeWrapperBase::colour ("colour"); | |||||
| const Identifier Drawable::ValueTreeWrapperBase::radial ("radial"); | |||||
| const Identifier Drawable::ValueTreeWrapperBase::colours ("colours"); | |||||
| Drawable::ValueTreeWrapperBase::ValueTreeWrapperBase (const ValueTree& state_) | |||||
| : state (state_) | |||||
| { | |||||
| } | |||||
| Drawable::ValueTreeWrapperBase::~ValueTreeWrapperBase() | |||||
| { | |||||
| } | |||||
| const String Drawable::ValueTreeWrapperBase::getID() const | |||||
| { | |||||
| return state [idProperty]; | |||||
| } | |||||
| void Drawable::ValueTreeWrapperBase::setID (const String& newID, UndoManager* undoManager) | |||||
| { | |||||
| if (newID.isEmpty()) | |||||
| state.removeProperty (idProperty, undoManager); | |||||
| else | |||||
| state.setProperty (idProperty, newID, undoManager); | |||||
| } | |||||
| const FillType Drawable::ValueTreeWrapperBase::readFillType (const ValueTree& v) | |||||
| { | |||||
| const String newType (v[type].toString()); | |||||
| if (newType == "solid") | |||||
| { | |||||
| const String colourString (v [colour].toString()); | |||||
| return FillType (Colour (colourString.isEmpty() ? (uint32) 0xff000000 | |||||
| : (uint32) colourString.getHexValue32())); | |||||
| } | |||||
| else if (newType == "gradient") | |||||
| { | |||||
| ColourGradient g; | |||||
| g.point1.setXY (v[x1], v[y1]); | |||||
| g.point2.setXY (v[x2], v[y2]); | |||||
| g.isRadial = v[radial]; | |||||
| StringArray colourSteps; | |||||
| colourSteps.addTokens (v[colours].toString(), false); | |||||
| for (int i = 0; i < colourSteps.size() / 2; ++i) | |||||
| g.addColour (colourSteps[i * 2].getDoubleValue(), | |||||
| Colour ((uint32) colourSteps[i * 2 + 1].getHexValue32())); | |||||
| return FillType (g); | |||||
| } | |||||
| else if (newType == "image") | |||||
| { | |||||
| jassertfalse; //xxx todo | |||||
| } | |||||
| jassertfalse; | |||||
| return FillType(); | |||||
| } | |||||
| void Drawable::ValueTreeWrapperBase::replaceFillType (const Identifier& tag, const FillType& fillType, UndoManager* undoManager) | |||||
| { | |||||
| ValueTree v (state.getChildWithName (tag)); | |||||
| if (! v.isValid()) | |||||
| { | |||||
| state.addChild (ValueTree (tag), -1, undoManager); | |||||
| v = state.getChildWithName (tag); | |||||
| } | |||||
| if (fillType.isColour()) | |||||
| { | |||||
| v.setProperty (type, "solid", undoManager); | |||||
| v.setProperty (colour, String::toHexString ((int) fillType.colour.getARGB()), undoManager); | |||||
| v.removeProperty (x1, undoManager); | |||||
| v.removeProperty (x2, undoManager); | |||||
| v.removeProperty (y1, undoManager); | |||||
| v.removeProperty (y2, undoManager); | |||||
| v.removeProperty (radial, undoManager); | |||||
| v.removeProperty (colours, undoManager); | |||||
| } | |||||
| else if (fillType.isGradient()) | |||||
| { | |||||
| v.setProperty (type, "gradient", undoManager); | |||||
| v.setProperty (x1, fillType.gradient->point1.getX(), undoManager); | |||||
| v.setProperty (y1, fillType.gradient->point1.getY(), undoManager); | |||||
| v.setProperty (x2, fillType.gradient->point2.getX(), undoManager); | |||||
| v.setProperty (y2, fillType.gradient->point2.getY(), undoManager); | |||||
| v.setProperty (radial, fillType.gradient->isRadial, undoManager); | |||||
| String s; | |||||
| for (int i = 0; i < fillType.gradient->getNumColours(); ++i) | |||||
| s << " " << fillType.gradient->getColourPosition (i) | |||||
| << " " << String::toHexString ((int) fillType.gradient->getColour(i).getARGB()); | |||||
| v.setProperty (colours, s.trimStart(), undoManager); | |||||
| v.removeProperty (colour, undoManager); | |||||
| } | |||||
| else if (fillType.isTiledImage()) | |||||
| { | |||||
| v.setProperty (type, "image", undoManager); | |||||
| jassertfalse; //xxx todo | |||||
| v.removeProperty (x1, undoManager); | |||||
| v.removeProperty (x2, undoManager); | |||||
| v.removeProperty (y1, undoManager); | |||||
| v.removeProperty (y2, undoManager); | |||||
| v.removeProperty (radial, undoManager); | |||||
| v.removeProperty (colours, undoManager); | |||||
| v.removeProperty (colour, undoManager); | |||||
| } | |||||
| else | |||||
| { | |||||
| jassertfalse; | |||||
| } | |||||
| } | |||||
| END_JUCE_NAMESPACE | END_JUCE_NAMESPACE | ||||
| @@ -27,8 +27,10 @@ | |||||
| #define __JUCE_DRAWABLE_JUCEHEADER__ | #define __JUCE_DRAWABLE_JUCEHEADER__ | ||||
| #include "../contexts/juce_Graphics.h" | #include "../contexts/juce_Graphics.h" | ||||
| #include "../geometry/juce_RelativeCoordinate.h" | |||||
| #include "../../../text/juce_XmlElement.h" | #include "../../../text/juce_XmlElement.h" | ||||
| #include "../../../containers/juce_ValueTree.h" | #include "../../../containers/juce_ValueTree.h" | ||||
| class DrawableComposite; | |||||
| //============================================================================== | //============================================================================== | ||||
| @@ -229,11 +231,34 @@ public: | |||||
| /** Returns the tag ID that is used for a ValueTree that stores this type of drawable. */ | /** Returns the tag ID that is used for a ValueTree that stores this type of drawable. */ | ||||
| virtual const Identifier getValueTreeType() const = 0; | virtual const Identifier getValueTreeType() const = 0; | ||||
| //============================================================================== | |||||
| /** Internal class used to manage ValueTrees that represent Drawables. */ | |||||
| class ValueTreeWrapperBase | |||||
| { | |||||
| public: | |||||
| ValueTreeWrapperBase (const ValueTree& state); | |||||
| ~ValueTreeWrapperBase(); | |||||
| ValueTree& getState() throw() { return state; } | |||||
| const String getID() const; | |||||
| void setID (const String& newID, UndoManager* undoManager); | |||||
| protected: | |||||
| ValueTree state; | |||||
| static const Identifier idProperty, type, x1, x2, y1, y2, colour, radial, colours; | |||||
| static const FillType readFillType (const ValueTree& v); | |||||
| void replaceFillType (const Identifier& tag, const FillType& fillType, UndoManager* undoManager); | |||||
| }; | |||||
| //============================================================================== | //============================================================================== | ||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| protected: | protected: | ||||
| static const Identifier idProperty; | |||||
| friend class DrawableComposite; | |||||
| DrawableComposite* parent; | |||||
| virtual void invalidatePoints() = 0; | |||||
| private: | private: | ||||
| String name; | String name; | ||||
| @@ -37,8 +37,21 @@ BEGIN_JUCE_NAMESPACE | |||||
| //============================================================================== | //============================================================================== | ||||
| DrawableComposite::DrawableComposite() | DrawableComposite::DrawableComposite() | ||||
| { | { | ||||
| controlPoints[1].setXY (1.0f, 0.0f); | |||||
| controlPoints[2].setXY (0.0f, 1.0f); | |||||
| controlPoints[1] = RelativePoint (Point<float> (1.0f, 0.0f)); | |||||
| controlPoints[2] = RelativePoint (Point<float> (0.0f, 1.0f)); | |||||
| } | |||||
| DrawableComposite::DrawableComposite (const DrawableComposite& other) | |||||
| { | |||||
| int i; | |||||
| for (i = 0; i < 3; ++i) | |||||
| controlPoints[i] = other.controlPoints[i]; | |||||
| for (i = 0; i < drawables.size(); ++i) | |||||
| drawables.add (other.drawables.getUnchecked(i)->createCopy()); | |||||
| for (i = 0; i < markers.size(); ++i) | |||||
| markers.add (new Marker (*other.markers.getUnchecked(i))); | |||||
| } | } | ||||
| DrawableComposite::~DrawableComposite() | DrawableComposite::~DrawableComposite() | ||||
| @@ -51,7 +64,9 @@ void DrawableComposite::insertDrawable (Drawable* drawable, const int index) | |||||
| if (drawable != 0) | if (drawable != 0) | ||||
| { | { | ||||
| jassert (! drawables.contains (drawable)); // trying to add a drawable that's already in here! | jassert (! drawables.contains (drawable)); // trying to add a drawable that's already in here! | ||||
| jassert (drawable->parent == 0); // A drawable can only live inside one parent at a time! | |||||
| drawables.insert (index, drawable); | drawables.insert (index, drawable); | ||||
| drawable->parent = this; | |||||
| } | } | ||||
| } | } | ||||
| @@ -71,9 +86,9 @@ void DrawableComposite::bringToFront (const int index) | |||||
| drawables.move (index, -1); | drawables.move (index, -1); | ||||
| } | } | ||||
| void DrawableComposite::setTransform (const Point<float>& targetPositionForOrigin, | |||||
| const Point<float>& targetPositionForX1Y0, | |||||
| const Point<float>& targetPositionForX0Y1) | |||||
| void DrawableComposite::setTransform (const RelativePoint& targetPositionForOrigin, | |||||
| const RelativePoint& targetPositionForX1Y0, | |||||
| const RelativePoint& targetPositionForX0Y1) | |||||
| { | { | ||||
| controlPoints[0] = targetPositionForOrigin; | controlPoints[0] = targetPositionForOrigin; | ||||
| controlPoints[1] = targetPositionForX1Y0; | controlPoints[1] = targetPositionForX1Y0; | ||||
| @@ -81,11 +96,70 @@ void DrawableComposite::setTransform (const Point<float>& targetPositionForOrigi | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| const AffineTransform DrawableComposite::getTransform() const | |||||
| DrawableComposite::Marker::Marker (const DrawableComposite::Marker& other) | |||||
| : name (other.name), position (other.position), isOnXAxis (other.isOnXAxis) | |||||
| { | |||||
| } | |||||
| DrawableComposite::Marker::Marker (const String& name_, const RelativeCoordinate& position_, const bool isOnXAxis_) | |||||
| : name (name_), position (position_), isOnXAxis (isOnXAxis_) | |||||
| { | |||||
| } | |||||
| bool DrawableComposite::Marker::operator!= (const DrawableComposite::Marker& other) const throw() | |||||
| { | |||||
| return name != other.name || position != other.position || isOnXAxis != other.isOnXAxis; | |||||
| } | |||||
| //============================================================================== | |||||
| int DrawableComposite::getNumMarkers (bool xAxis) const throw() | |||||
| { | |||||
| return markers.size(); | |||||
| } | |||||
| const DrawableComposite::Marker* DrawableComposite::getMarker (int index) const throw() | |||||
| { | |||||
| return markers [index]; | |||||
| } | |||||
| void DrawableComposite::setMarker (const String& name, bool xAxis, const RelativeCoordinate& position) | |||||
| { | |||||
| for (int i = 0; i < markers.size(); ++i) | |||||
| { | |||||
| Marker* const m = markers.getUnchecked(i); | |||||
| if (m->name == name) | |||||
| { | |||||
| jassert (m->isOnXAxis == xAxis); // trying to either have two markers with the same name on different axes? | |||||
| if (m->position != position) | |||||
| { | |||||
| m->position = position; | |||||
| invalidatePoints(); | |||||
| } | |||||
| return; | |||||
| } | |||||
| } | |||||
| markers.add (new Marker (name, position, xAxis)); | |||||
| invalidatePoints(); | |||||
| } | |||||
| void DrawableComposite::removeMarker (int index) | |||||
| { | { | ||||
| return AffineTransform::fromTargetPoints (controlPoints[0].getX(), controlPoints[0].getY(), | |||||
| controlPoints[1].getX(), controlPoints[1].getY(), | |||||
| controlPoints[2].getX(), controlPoints[2].getY()); | |||||
| markers.remove (index); | |||||
| } | |||||
| //============================================================================== | |||||
| const AffineTransform DrawableComposite::calculateTransform() const | |||||
| { | |||||
| Point<float> resolved[3]; | |||||
| for (int i = 0; i < 3; ++i) | |||||
| resolved[i] = controlPoints[i].resolve (parent); | |||||
| return AffineTransform::fromTargetPoints (resolved[0].getX(), resolved[0].getY(), | |||||
| resolved[1].getX(), resolved[1].getY(), | |||||
| resolved[2].getX(), resolved[2].getY()); | |||||
| } | } | ||||
| void DrawableComposite::render (const Drawable::RenderingContext& context) const | void DrawableComposite::render (const Drawable::RenderingContext& context) const | ||||
| @@ -95,7 +169,7 @@ void DrawableComposite::render (const Drawable::RenderingContext& context) const | |||||
| if (context.opacity >= 1.0f || drawables.size() == 1) | if (context.opacity >= 1.0f || drawables.size() == 1) | ||||
| { | { | ||||
| Drawable::RenderingContext contextCopy (context); | Drawable::RenderingContext contextCopy (context); | ||||
| contextCopy.transform = getTransform().followedBy (context.transform); | |||||
| contextCopy.transform = calculateTransform().followedBy (context.transform); | |||||
| for (int i = 0; i < drawables.size(); ++i) | for (int i = 0; i < drawables.size(); ++i) | ||||
| drawables.getUnchecked(i)->render (contextCopy); | drawables.getUnchecked(i)->render (contextCopy); | ||||
| @@ -121,6 +195,33 @@ void DrawableComposite::render (const Drawable::RenderingContext& context) const | |||||
| } | } | ||||
| } | } | ||||
| const RelativeCoordinate DrawableComposite::findNamedCoordinate (const String& objectName, const String& edge) const | |||||
| { | |||||
| if (objectName == RelativeCoordinate::Strings::parent) | |||||
| { | |||||
| if (edge == RelativeCoordinate::Strings::right) | |||||
| { | |||||
| jassertfalse; // a Drawable doesn't have a fixed right-hand edge - use a marker instead if you need a point of reference. | |||||
| return RelativeCoordinate (100.0, true); | |||||
| } | |||||
| if (edge == RelativeCoordinate::Strings::bottom) | |||||
| { | |||||
| jassertfalse; // a Drawable doesn't have a fixed bottom edge - use a marker instead if you need a point of reference. | |||||
| return RelativeCoordinate (100.0, false); | |||||
| } | |||||
| } | |||||
| for (int i = 0; i < markers.size(); ++i) | |||||
| { | |||||
| Marker* const m = markers.getUnchecked(i); | |||||
| if (m->name == objectName) | |||||
| return m->position; | |||||
| } | |||||
| return RelativeCoordinate(); | |||||
| } | |||||
| const Rectangle<float> DrawableComposite::getUntransformedBounds() const | const Rectangle<float> DrawableComposite::getUntransformedBounds() const | ||||
| { | { | ||||
| Rectangle<float> bounds; | Rectangle<float> bounds; | ||||
| @@ -133,12 +234,12 @@ const Rectangle<float> DrawableComposite::getUntransformedBounds() const | |||||
| const Rectangle<float> DrawableComposite::getBounds() const | const Rectangle<float> DrawableComposite::getBounds() const | ||||
| { | { | ||||
| return getUntransformedBounds().transformed (getTransform()); | |||||
| return getUntransformedBounds().transformed (calculateTransform()); | |||||
| } | } | ||||
| bool DrawableComposite::hitTest (float x, float y) const | bool DrawableComposite::hitTest (float x, float y) const | ||||
| { | { | ||||
| getTransform().inverted().transformPoint (x, y); | |||||
| calculateTransform().inverted().transformPoint (x, y); | |||||
| for (int i = 0; i < drawables.size(); ++i) | for (int i = 0; i < drawables.size(); ++i) | ||||
| if (drawables.getUnchecked(i)->hitTest (x, y)) | if (drawables.getUnchecked(i)->hitTest (x, y)) | ||||
| @@ -149,125 +250,282 @@ bool DrawableComposite::hitTest (float x, float y) const | |||||
| Drawable* DrawableComposite::createCopy() const | Drawable* DrawableComposite::createCopy() const | ||||
| { | { | ||||
| DrawableComposite* const dc = new DrawableComposite(); | |||||
| for (int i = 0; i < 3; ++i) | |||||
| dc->controlPoints[i] = controlPoints[i]; | |||||
| return new DrawableComposite (*this); | |||||
| } | |||||
| void DrawableComposite::invalidatePoints() | |||||
| { | |||||
| for (int i = 0; i < drawables.size(); ++i) | for (int i = 0; i < drawables.size(); ++i) | ||||
| dc->drawables.add (drawables.getUnchecked(i)->createCopy()); | |||||
| return dc; | |||||
| drawables.getUnchecked(i)->invalidatePoints(); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| const Identifier DrawableComposite::valueTreeType ("Group"); | const Identifier DrawableComposite::valueTreeType ("Group"); | ||||
| namespace DrawableCompositeHelpers | |||||
| const Identifier DrawableComposite::ValueTreeWrapper::topLeft ("topLeft"); | |||||
| const Identifier DrawableComposite::ValueTreeWrapper::topRight ("topRight"); | |||||
| const Identifier DrawableComposite::ValueTreeWrapper::bottomLeft ("bottomLeft"); | |||||
| const Identifier DrawableComposite::ValueTreeWrapper::childGroupTag ("Drawables"); | |||||
| const Identifier DrawableComposite::ValueTreeWrapper::markerGroupTag ("Markers"); | |||||
| const Identifier DrawableComposite::ValueTreeWrapper::markerTag ("Marker"); | |||||
| const Identifier DrawableComposite::ValueTreeWrapper::nameProperty ("name"); | |||||
| const Identifier DrawableComposite::ValueTreeWrapper::xAxisProperty ("xAxis"); | |||||
| const Identifier DrawableComposite::ValueTreeWrapper::posProperty ("position"); | |||||
| //============================================================================== | |||||
| DrawableComposite::ValueTreeWrapper::ValueTreeWrapper (const ValueTree& state_) | |||||
| : ValueTreeWrapperBase (state_) | |||||
| { | |||||
| jassert (state.hasType (valueTreeType)); | |||||
| } | |||||
| ValueTree DrawableComposite::ValueTreeWrapper::getChildList() const | |||||
| { | |||||
| return state.getChildWithName (childGroupTag); | |||||
| } | |||||
| ValueTree DrawableComposite::ValueTreeWrapper::getChildListCreating (UndoManager* undoManager) | |||||
| { | |||||
| const ValueTree childList (getChildList()); | |||||
| if (childList.isValid()) | |||||
| return childList; | |||||
| state.addChild (ValueTree (childGroupTag), 0, undoManager); | |||||
| return getChildList(); | |||||
| } | |||||
| ValueTree DrawableComposite::ValueTreeWrapper::getMarkerList() const | |||||
| { | { | ||||
| static const Identifier topLeft ("topLeft"); | |||||
| static const Identifier topRight ("topRight"); | |||||
| static const Identifier bottomLeft ("bottomLeft"); | |||||
| return state.getChildWithName (markerGroupTag); | |||||
| } | |||||
| ValueTree DrawableComposite::ValueTreeWrapper::getMarkerListCreating (UndoManager* undoManager) | |||||
| { | |||||
| const ValueTree markerList (getMarkerList()); | |||||
| if (markerList.isValid()) | |||||
| return markerList; | |||||
| state.addChild (ValueTree (markerGroupTag), -1, undoManager); | |||||
| return getMarkerList(); | |||||
| } | |||||
| int DrawableComposite::ValueTreeWrapper::getNumDrawables() const | |||||
| { | |||||
| return getChildList().getNumChildren(); | |||||
| } | |||||
| const ValueTree DrawableComposite::ValueTreeWrapper::getDrawableState (int index) const | |||||
| { | |||||
| return getChildList().getChild (index); | |||||
| } | |||||
| void DrawableComposite::ValueTreeWrapper::addDrawable (const ValueTree& newDrawableState, int index, UndoManager* undoManager) | |||||
| { | |||||
| getChildListCreating (undoManager).addChild (newDrawableState, index, undoManager); | |||||
| } | |||||
| void DrawableComposite::ValueTreeWrapper::moveDrawableOrder (int currentIndex, int newIndex, UndoManager* undoManager) | |||||
| { | |||||
| getChildListCreating (undoManager).moveChild (currentIndex, newIndex, undoManager); | |||||
| } | |||||
| void DrawableComposite::ValueTreeWrapper::removeDrawable (int index, UndoManager* undoManager) | |||||
| { | |||||
| getChildList().removeChild (index, undoManager); | |||||
| } | |||||
| const RelativePoint DrawableComposite::ValueTreeWrapper::getTargetPositionForOrigin() const | |||||
| { | |||||
| const String pos (state [topLeft].toString()); | |||||
| return pos.isNotEmpty() ? RelativePoint (pos) : RelativePoint (); | |||||
| } | |||||
| void DrawableComposite::ValueTreeWrapper::setTargetPositionForOrigin (const RelativePoint& newPoint, UndoManager* undoManager) | |||||
| { | |||||
| state.setProperty (topLeft, newPoint.toString(), undoManager); | |||||
| } | |||||
| const RelativePoint DrawableComposite::ValueTreeWrapper::getTargetPositionForX1Y0() const | |||||
| { | |||||
| const String pos (state [topRight].toString()); | |||||
| return pos.isNotEmpty() ? RelativePoint (pos) : RelativePoint (Point<float> (1.0f, 0.0f)); | |||||
| } | |||||
| void DrawableComposite::ValueTreeWrapper::setTargetPositionForX1Y0 (const RelativePoint& newPoint, UndoManager* undoManager) | |||||
| { | |||||
| state.setProperty (topRight, newPoint.toString(), undoManager); | |||||
| } | |||||
| static void stringToPoint (const String& coords, Point<float>& point) | |||||
| const RelativePoint DrawableComposite::ValueTreeWrapper::getTargetPositionForX0Y1() const | |||||
| { | |||||
| const String pos (state [bottomLeft].toString()); | |||||
| return pos.isNotEmpty() ? RelativePoint (pos) : RelativePoint (Point<float> (0.0f, 1.0f)); | |||||
| } | |||||
| void DrawableComposite::ValueTreeWrapper::setTargetPositionForX0Y1 (const RelativePoint& newPoint, UndoManager* undoManager) | |||||
| { | |||||
| state.setProperty (bottomLeft, newPoint.toString(), undoManager); | |||||
| } | |||||
| int DrawableComposite::ValueTreeWrapper::getNumMarkers() const | |||||
| { | |||||
| return getMarkerList().getNumChildren(); | |||||
| } | |||||
| const DrawableComposite::Marker DrawableComposite::ValueTreeWrapper::getMarker (int index) const | |||||
| { | |||||
| const ValueTree marker (getMarkerList().getChild (index)); | |||||
| const bool isXAxis = marker [xAxisProperty]; | |||||
| return Marker (marker [nameProperty], | |||||
| RelativeCoordinate (marker [posProperty].toString(), isXAxis), | |||||
| isXAxis); | |||||
| } | |||||
| void DrawableComposite::ValueTreeWrapper::setMarker (const String& name, bool xAxis, const RelativeCoordinate& position, UndoManager* undoManager) | |||||
| { | |||||
| ValueTree markerList (getMarkerListCreating (undoManager)); | |||||
| ValueTree marker (markerList.getChildWithProperty (nameProperty, name)); | |||||
| if (marker.isValid()) | |||||
| { | { | ||||
| if (coords.isNotEmpty()) | |||||
| { | |||||
| const int comma = coords.indexOfChar (','); | |||||
| point.setXY (coords.substring (0, comma).getFloatValue(), | |||||
| coords.substring (comma + 1).getFloatValue()); | |||||
| } | |||||
| jassert ((bool) marker [xAxisProperty] == xAxis); // shouldn't change the axis of a marker after it has been created! | |||||
| marker.setProperty (posProperty, position.toString(), undoManager); | |||||
| } | } | ||||
| static const var pointToString (const Point<float>& point) | |||||
| else | |||||
| { | { | ||||
| return String (point.getX()) + ", " + String (point.getY()); | |||||
| marker = ValueTree (markerTag); | |||||
| marker.setProperty (nameProperty, name, 0); | |||||
| marker.setProperty (xAxisProperty, xAxis, 0); | |||||
| marker.setProperty (posProperty, position.toString(), 0); | |||||
| markerList.addChild (marker, -1, undoManager); | |||||
| } | } | ||||
| } | } | ||||
| const Rectangle<float> DrawableComposite::refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider) | |||||
| void DrawableComposite::ValueTreeWrapper::removeMarker (int index, UndoManager* undoManager) | |||||
| { | { | ||||
| jassert (tree.hasType (valueTreeType)); | |||||
| return getMarkerList().removeChild (index, undoManager); | |||||
| } | |||||
| //============================================================================== | |||||
| const Rectangle<float> DrawableComposite::refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider) | |||||
| { | |||||
| Rectangle<float> damageRect; | Rectangle<float> damageRect; | ||||
| const ValueTreeWrapper controller (tree); | |||||
| setName (controller.getID()); | |||||
| setName (tree [idProperty]); | |||||
| RelativePoint newControlPoint[3] = { controller.getTargetPositionForOrigin(), | |||||
| controller.getTargetPositionForX1Y0(), | |||||
| controller.getTargetPositionForX0Y1() }; | |||||
| Point<float> newControlPoint[3]; | |||||
| DrawableCompositeHelpers::stringToPoint (tree [DrawableCompositeHelpers::topLeft].toString(), newControlPoint[0]); | |||||
| DrawableCompositeHelpers::stringToPoint (tree [DrawableCompositeHelpers::topRight].toString(), newControlPoint[1]); | |||||
| DrawableCompositeHelpers::stringToPoint (tree [DrawableCompositeHelpers::bottomLeft].toString(), newControlPoint[2]); | |||||
| bool controlPointsChanged = false; | |||||
| bool redrawAll = false; | |||||
| if (controlPoints[0] != newControlPoint[0] | if (controlPoints[0] != newControlPoint[0] | ||||
| || controlPoints[1] != newControlPoint[1] | || controlPoints[1] != newControlPoint[1] | ||||
| || controlPoints[2] != newControlPoint[2]) | || controlPoints[2] != newControlPoint[2]) | ||||
| { | { | ||||
| controlPointsChanged = true; | |||||
| redrawAll = true; | |||||
| damageRect = getUntransformedBounds(); | damageRect = getUntransformedBounds(); | ||||
| controlPoints[0] = newControlPoint[0]; | controlPoints[0] = newControlPoint[0]; | ||||
| controlPoints[1] = newControlPoint[1]; | controlPoints[1] = newControlPoint[1]; | ||||
| controlPoints[2] = newControlPoint[2]; | controlPoints[2] = newControlPoint[2]; | ||||
| } | } | ||||
| // Remove deleted markers... | |||||
| int i; | int i; | ||||
| for (i = drawables.size(); --i >= tree.getNumChildren();) | |||||
| for (i = markers.size(); --i >= controller.getNumMarkers();) | |||||
| { | |||||
| if (damageRect.isEmpty()) | |||||
| damageRect = getUntransformedBounds(); | |||||
| removeMarker (i); | |||||
| } | |||||
| // Update markers and add new ones.. | |||||
| for (i = 0; i < controller.getNumMarkers(); ++i) | |||||
| { | { | ||||
| damageRect = damageRect.getUnion (drawables.getUnchecked(i)->getBounds()); | |||||
| const Marker newMarker (controller.getMarker (i)); | |||||
| Marker* m = markers[i]; | |||||
| if (m == 0 || newMarker != *m) | |||||
| { | |||||
| redrawAll = true; | |||||
| if (damageRect.isEmpty()) | |||||
| damageRect = getUntransformedBounds(); | |||||
| if (m == 0) | |||||
| markers.add (new Marker (newMarker)); | |||||
| else | |||||
| *m = newMarker; | |||||
| } | |||||
| } | |||||
| // Remove deleted drawables.. | |||||
| for (i = drawables.size(); --i >= controller.getNumDrawables();) | |||||
| { | |||||
| Drawable* const d = drawables.getUnchecked(i); | |||||
| damageRect = damageRect.getUnion (d->getBounds()); | |||||
| d->parent = 0; | |||||
| drawables.remove (i); | drawables.remove (i); | ||||
| } | } | ||||
| for (int i = 0; i < tree.getNumChildren(); ++i) | |||||
| // Update drawables and add new ones.. | |||||
| for (i = 0; i < controller.getNumDrawables(); ++i) | |||||
| { | { | ||||
| const ValueTree childTree (tree.getChild (i)); | |||||
| const ValueTree newDrawable (controller.getDrawableState (i)); | |||||
| Drawable* d = drawables[i]; | Drawable* d = drawables[i]; | ||||
| if (d != 0) | if (d != 0) | ||||
| { | { | ||||
| if (childTree.hasType (d->getValueTreeType())) | |||||
| if (newDrawable.hasType (d->getValueTreeType())) | |||||
| { | { | ||||
| damageRect = damageRect.getUnion (d->refreshFromValueTree (childTree, imageProvider)); | |||||
| damageRect = damageRect.getUnion (d->refreshFromValueTree (newDrawable, imageProvider)); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| damageRect = damageRect.getUnion (d->getBounds()); | damageRect = damageRect.getUnion (d->getBounds()); | ||||
| d = createFromValueTree (childTree, imageProvider); | |||||
| d = createFromValueTree (newDrawable, imageProvider); | |||||
| d->parent = this; | |||||
| drawables.set (i, d); | drawables.set (i, d); | ||||
| damageRect = damageRect.getUnion (d->getBounds()); | damageRect = damageRect.getUnion (d->getBounds()); | ||||
| } | } | ||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| d = createFromValueTree (childTree, imageProvider); | |||||
| d = createFromValueTree (newDrawable, imageProvider); | |||||
| d->parent = this; | |||||
| drawables.set (i, d); | drawables.set (i, d); | ||||
| damageRect = damageRect.getUnion (d->getBounds()); | damageRect = damageRect.getUnion (d->getBounds()); | ||||
| } | } | ||||
| } | } | ||||
| if (controlPointsChanged) | |||||
| if (redrawAll) | |||||
| damageRect = damageRect.getUnion (getUntransformedBounds()); | damageRect = damageRect.getUnion (getUntransformedBounds()); | ||||
| return damageRect.transformed (getTransform()); | |||||
| return damageRect.transformed (calculateTransform()); | |||||
| } | } | ||||
| const ValueTree DrawableComposite::createValueTree (ImageProvider* imageProvider) const | const ValueTree DrawableComposite::createValueTree (ImageProvider* imageProvider) const | ||||
| { | { | ||||
| ValueTree v (valueTreeType); | |||||
| ValueTree tree (valueTreeType); | |||||
| ValueTreeWrapper v (tree); | |||||
| if (getName().isNotEmpty()) | |||||
| v.setProperty (idProperty, getName(), 0); | |||||
| v.setID (getName(), 0); | |||||
| v.setTargetPositionForOrigin (controlPoints[0], 0); | |||||
| v.setTargetPositionForX1Y0 (controlPoints[1], 0); | |||||
| v.setTargetPositionForX0Y1 (controlPoints[2], 0); | |||||
| if (! getTransform().isIdentity()) | |||||
| int i; | |||||
| for (i = 0; i < drawables.size(); ++i) | |||||
| v.addDrawable (drawables.getUnchecked(i)->createValueTree (imageProvider), -1, 0); | |||||
| for (i = 0; i < markers.size(); ++i) | |||||
| { | { | ||||
| v.setProperty (DrawableCompositeHelpers::topLeft, DrawableCompositeHelpers::pointToString (controlPoints[0]), 0); | |||||
| v.setProperty (DrawableCompositeHelpers::topRight, DrawableCompositeHelpers::pointToString (controlPoints[1]), 0); | |||||
| v.setProperty (DrawableCompositeHelpers::bottomLeft, DrawableCompositeHelpers::pointToString (controlPoints[2]), 0); | |||||
| const Marker* m = markers.getUnchecked(i); | |||||
| v.setMarker (m->name, m->isOnXAxis, m->position, 0); | |||||
| } | } | ||||
| for (int i = 0; i < drawables.size(); ++i) | |||||
| v.addChild (drawables.getUnchecked(i)->createValueTree (imageProvider), -1, 0); | |||||
| return v; | |||||
| return tree; | |||||
| } | } | ||||
| @@ -35,14 +35,17 @@ | |||||
| @see Drawable | @see Drawable | ||||
| */ | */ | ||||
| class JUCE_API DrawableComposite : public Drawable | |||||
| class JUCE_API DrawableComposite : public Drawable, | |||||
| public RelativeCoordinate::NamedCoordinateFinder | |||||
| { | { | ||||
| public: | public: | ||||
| //============================================================================== | //============================================================================== | ||||
| /** Creates a composite Drawable. | |||||
| */ | |||||
| /** Creates a composite Drawable. */ | |||||
| DrawableComposite(); | DrawableComposite(); | ||||
| /** Creates a copy of a DrawableComposite. */ | |||||
| DrawableComposite (const DrawableComposite& other); | |||||
| /** Destructor. */ | /** Destructor. */ | ||||
| virtual ~DrawableComposite(); | virtual ~DrawableComposite(); | ||||
| @@ -122,27 +125,44 @@ public: | |||||
| @param targetPositionForX0Y1 the position that the local coordinate (0, 1) should be | @param targetPositionForX0Y1 the position that the local coordinate (0, 1) should be | ||||
| mapped onto when rendering this object. | mapped onto when rendering this object. | ||||
| */ | */ | ||||
| void setTransform (const Point<float>& targetPositionForOrigin, | |||||
| const Point<float>& targetPositionForX1Y0, | |||||
| const Point<float>& targetPositionForX0Y1); | |||||
| void setTransform (const RelativePoint& targetPositionForOrigin, | |||||
| const RelativePoint& targetPositionForX1Y0, | |||||
| const RelativePoint& targetPositionForX0Y1); | |||||
| /** Returns the position to which the local coordinate (0, 0) should be remapped in the target | /** Returns the position to which the local coordinate (0, 0) should be remapped in the target | ||||
| coordinate space when rendering this object. | coordinate space when rendering this object. | ||||
| @see setTransform | @see setTransform | ||||
| */ | */ | ||||
| const Point<float>& getTargetPositionForOrigin() const throw() { return controlPoints[0]; } | |||||
| const RelativePoint& getTargetPositionForOrigin() const throw() { return controlPoints[0]; } | |||||
| /** Returns the position to which the local coordinate (1, 0) should be remapped in the target | /** Returns the position to which the local coordinate (1, 0) should be remapped in the target | ||||
| coordinate space when rendering this object. | coordinate space when rendering this object. | ||||
| @see setTransform | @see setTransform | ||||
| */ | */ | ||||
| const Point<float>& getTargetPositionForX1Y0() const throw() { return controlPoints[1]; } | |||||
| const RelativePoint& getTargetPositionForX1Y0() const throw() { return controlPoints[1]; } | |||||
| /** Returns the position to which the local coordinate (0, 1) should be remapped in the target | /** Returns the position to which the local coordinate (0, 1) should be remapped in the target | ||||
| coordinate space when rendering this object. | coordinate space when rendering this object. | ||||
| @see setTransform | @see setTransform | ||||
| */ | */ | ||||
| const Point<float>& getTargetPositionForX0Y1() const throw() { return controlPoints[2]; } | |||||
| const RelativePoint& getTargetPositionForX0Y1() const throw() { return controlPoints[2]; } | |||||
| //============================================================================== | |||||
| struct Marker | |||||
| { | |||||
| Marker (const Marker&); | |||||
| Marker (const String& name, const RelativeCoordinate& position, bool isOnXAxis); | |||||
| bool operator!= (const Marker&) const throw(); | |||||
| String name; | |||||
| RelativeCoordinate position; | |||||
| bool isOnXAxis; | |||||
| }; | |||||
| int getNumMarkers (bool xAxis) const throw(); | |||||
| const Marker* getMarker (int index) const throw(); | |||||
| void setMarker (const String& name, bool xAxis, const RelativeCoordinate& position); | |||||
| void removeMarker (int index); | |||||
| //============================================================================== | //============================================================================== | ||||
| /** @internal */ | /** @internal */ | ||||
| @@ -152,12 +172,10 @@ public: | |||||
| /** @internal */ | /** @internal */ | ||||
| bool hitTest (float x, float y) const; | bool hitTest (float x, float y) const; | ||||
| /** @internal */ | /** @internal */ | ||||
| int getNumControlPoints() const; | |||||
| /** @internal */ | |||||
| const Point<float> getControlPoint (int index) const; | |||||
| /** @internal */ | |||||
| Drawable* createCopy() const; | Drawable* createCopy() const; | ||||
| /** @internal */ | /** @internal */ | ||||
| void invalidatePoints(); | |||||
| /** @internal */ | |||||
| const Rectangle<float> refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider); | const Rectangle<float> refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider); | ||||
| /** @internal */ | /** @internal */ | ||||
| const ValueTree createValueTree (ImageProvider* imageProvider) const; | const ValueTree createValueTree (ImageProvider* imageProvider) const; | ||||
| @@ -165,18 +183,57 @@ public: | |||||
| static const Identifier valueTreeType; | static const Identifier valueTreeType; | ||||
| /** @internal */ | /** @internal */ | ||||
| const Identifier getValueTreeType() const { return valueTreeType; } | const Identifier getValueTreeType() const { return valueTreeType; } | ||||
| /** @internal */ | |||||
| const RelativeCoordinate findNamedCoordinate (const String& objectName, const String& edge) const; | |||||
| //============================================================================== | |||||
| /** Internally-used class for wrapping a DrawableComposite's state into a ValueTree. */ | |||||
| class ValueTreeWrapper : public ValueTreeWrapperBase | |||||
| { | |||||
| public: | |||||
| ValueTreeWrapper (const ValueTree& state); | |||||
| int getNumDrawables() const; | |||||
| const ValueTree getDrawableState (int index) const; | |||||
| void addDrawable (const ValueTree& newDrawableState, int index, UndoManager* undoManager); | |||||
| void moveDrawableOrder (int currentIndex, int newIndex, UndoManager* undoManager); | |||||
| void removeDrawable (int index, UndoManager* undoManager); | |||||
| const RelativePoint getTargetPositionForOrigin() const; | |||||
| void setTargetPositionForOrigin (const RelativePoint& newPoint, UndoManager* undoManager); | |||||
| const RelativePoint getTargetPositionForX1Y0() const; | |||||
| void setTargetPositionForX1Y0 (const RelativePoint& newPoint, UndoManager* undoManager); | |||||
| const RelativePoint getTargetPositionForX0Y1() const; | |||||
| void setTargetPositionForX0Y1 (const RelativePoint& newPoint, UndoManager* undoManager); | |||||
| int getNumMarkers() const; | |||||
| const Marker getMarker (int index) const; | |||||
| void setMarker (const String& name, bool xAxis, const RelativeCoordinate& position, UndoManager* undoManager); | |||||
| void removeMarker (int index, UndoManager* undoManager); | |||||
| private: | |||||
| static const Identifier topLeft, topRight, bottomLeft, childGroupTag, markerGroupTag, | |||||
| markerTag, nameProperty, xAxisProperty, posProperty; | |||||
| ValueTree getChildList() const; | |||||
| ValueTree getChildListCreating (UndoManager* undoManager); | |||||
| ValueTree getMarkerList() const; | |||||
| ValueTree getMarkerListCreating (UndoManager* undoManager); | |||||
| }; | |||||
| //============================================================================== | //============================================================================== | ||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| private: | private: | ||||
| OwnedArray <Drawable> drawables; | OwnedArray <Drawable> drawables; | ||||
| Point<float> controlPoints[3]; | |||||
| RelativePoint controlPoints[3]; | |||||
| OwnedArray <Marker> markers; | |||||
| const Rectangle<float> getUntransformedBounds() const; | const Rectangle<float> getUntransformedBounds() const; | ||||
| const AffineTransform getTransform() const; | |||||
| const AffineTransform calculateTransform() const; | |||||
| DrawableComposite (const DrawableComposite&); | |||||
| DrawableComposite& operator= (const DrawableComposite&); | DrawableComposite& operator= (const DrawableComposite&); | ||||
| }; | }; | ||||
| @@ -27,8 +27,8 @@ | |||||
| BEGIN_JUCE_NAMESPACE | BEGIN_JUCE_NAMESPACE | ||||
| #include "juce_DrawableImage.h" | #include "juce_DrawableImage.h" | ||||
| #include "juce_DrawableComposite.h" | |||||
| #include "../imaging/juce_ImageCache.h" | #include "../imaging/juce_ImageCache.h" | ||||
| @@ -39,47 +39,58 @@ DrawableImage::DrawableImage() | |||||
| opacity (1.0f), | opacity (1.0f), | ||||
| overlayColour (0x00000000) | overlayColour (0x00000000) | ||||
| { | { | ||||
| controlPoints[1].setXY (1.0f, 0.0f); | |||||
| controlPoints[2].setXY (0.0f, 1.0f); | |||||
| controlPoints[1] = RelativePoint (Point<float> (1.0f, 0.0f)); | |||||
| controlPoints[2] = RelativePoint (Point<float> (0.0f, 1.0f)); | |||||
| } | } | ||||
| DrawableImage::~DrawableImage() | |||||
| DrawableImage::DrawableImage (const DrawableImage& other) | |||||
| : image (0), | |||||
| canDeleteImage (false), | |||||
| opacity (other.opacity), | |||||
| overlayColour (other.overlayColour) | |||||
| { | { | ||||
| clearImage(); | |||||
| for (int i = 0; i < numElementsInArray (controlPoints); ++i) | |||||
| controlPoints[i] = other.controlPoints[i]; | |||||
| if (other.image != 0) | |||||
| { | |||||
| if ((! other.canDeleteImage) || ! ImageCache::isImageInCache (other.image)) | |||||
| { | |||||
| setImage (*other.image); | |||||
| } | |||||
| else | |||||
| { | |||||
| ImageCache::incReferenceCount (other.image); | |||||
| setImage (other.image, true); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| //============================================================================== | |||||
| void DrawableImage::clearImage() | |||||
| DrawableImage::~DrawableImage() | |||||
| { | { | ||||
| if (canDeleteImage && image != 0) | |||||
| ImageCache::releaseOrDelete (image); | |||||
| image = 0; | |||||
| setImage (0, false); | |||||
| } | } | ||||
| //============================================================================== | |||||
| void DrawableImage::setImage (const Image& imageToCopy) | void DrawableImage::setImage (const Image& imageToCopy) | ||||
| { | { | ||||
| clearImage(); | |||||
| image = new Image (imageToCopy); | |||||
| canDeleteImage = true; | |||||
| controlPoints[0].setXY (0.0f, 0.0f); | |||||
| controlPoints[1].setXY ((float) image->getWidth(), 0.0f); | |||||
| controlPoints[2].setXY (0.0f, (float) image->getHeight()); | |||||
| setImage (new Image (imageToCopy), true); | |||||
| } | } | ||||
| void DrawableImage::setImage (Image* imageToUse, | void DrawableImage::setImage (Image* imageToUse, | ||||
| const bool releaseWhenNotNeeded) | const bool releaseWhenNotNeeded) | ||||
| { | { | ||||
| clearImage(); | |||||
| if (canDeleteImage) | |||||
| ImageCache::releaseOrDelete (image); | |||||
| image = imageToUse; | image = imageToUse; | ||||
| canDeleteImage = releaseWhenNotNeeded; | canDeleteImage = releaseWhenNotNeeded; | ||||
| if (image != 0) | if (image != 0) | ||||
| { | { | ||||
| controlPoints[0].setXY (0.0f, 0.0f); | |||||
| controlPoints[1].setXY ((float) image->getWidth(), 0.0f); | |||||
| controlPoints[2].setXY (0.0f, (float) image->getHeight()); | |||||
| controlPoints[0] = RelativePoint (Point<float> (0.0f, 0.0f)); | |||||
| controlPoints[1] = RelativePoint (Point<float> ((float) image->getWidth(), 0.0f)); | |||||
| controlPoints[2] = RelativePoint (Point<float> (0.0f, (float) image->getHeight())); | |||||
| } | } | ||||
| } | } | ||||
| @@ -93,9 +104,9 @@ void DrawableImage::setOverlayColour (const Colour& newOverlayColour) | |||||
| overlayColour = newOverlayColour; | overlayColour = newOverlayColour; | ||||
| } | } | ||||
| void DrawableImage::setTransform (const Point<float>& imageTopLeftPosition, | |||||
| const Point<float>& imageTopRightPosition, | |||||
| const Point<float>& imageBottomLeftPosition) | |||||
| void DrawableImage::setTransform (const RelativePoint& imageTopLeftPosition, | |||||
| const RelativePoint& imageTopRightPosition, | |||||
| const RelativePoint& imageBottomLeftPosition) | |||||
| { | { | ||||
| controlPoints[0] = imageTopLeftPosition; | controlPoints[0] = imageTopLeftPosition; | ||||
| controlPoints[1] = imageTopRightPosition; | controlPoints[1] = imageTopRightPosition; | ||||
| @@ -103,15 +114,19 @@ void DrawableImage::setTransform (const Point<float>& imageTopLeftPosition, | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| const AffineTransform DrawableImage::getTransform() const | |||||
| const AffineTransform DrawableImage::calculateTransform() const | |||||
| { | { | ||||
| if (image == 0) | if (image == 0) | ||||
| return AffineTransform::identity; | return AffineTransform::identity; | ||||
| const Point<float> tr (controlPoints[0] + (controlPoints[1] - controlPoints[0]) / (float) image->getWidth()); | |||||
| const Point<float> bl (controlPoints[0] + (controlPoints[2] - controlPoints[0]) / (float) image->getHeight()); | |||||
| Point<float> resolved[3]; | |||||
| for (int i = 0; i < 3; ++i) | |||||
| resolved[i] = controlPoints[i].resolve (parent); | |||||
| return AffineTransform::fromTargetPoints (controlPoints[0].getX(), controlPoints[0].getY(), | |||||
| const Point<float> tr (resolved[0] + (resolved[1] - resolved[0]) / (float) image->getWidth()); | |||||
| const Point<float> bl (resolved[0] + (resolved[2] - resolved[0]) / (float) image->getHeight()); | |||||
| return AffineTransform::fromTargetPoints (resolved[0].getX(), resolved[0].getY(), | |||||
| tr.getX(), tr.getY(), | tr.getX(), tr.getY(), | ||||
| bl.getX(), bl.getY()); | bl.getX(), bl.getY()); | ||||
| } | } | ||||
| @@ -120,7 +135,7 @@ void DrawableImage::render (const Drawable::RenderingContext& context) const | |||||
| { | { | ||||
| if (image != 0) | if (image != 0) | ||||
| { | { | ||||
| const AffineTransform t (getTransform().followedBy (context.transform)); | |||||
| const AffineTransform t (calculateTransform().followedBy (context.transform)); | |||||
| if (opacity > 0.0f && ! overlayColour.isOpaque()) | if (opacity > 0.0f && ! overlayColour.isOpaque()) | ||||
| { | { | ||||
| @@ -141,7 +156,11 @@ const Rectangle<float> DrawableImage::getBounds() const | |||||
| if (image == 0) | if (image == 0) | ||||
| return Rectangle<float>(); | return Rectangle<float>(); | ||||
| const Point<float> bottomRight (controlPoints[1] + (controlPoints[2] - controlPoints[0])); | |||||
| Point<float> resolved[3]; | |||||
| for (int i = 0; i < 3; ++i) | |||||
| resolved[i] = controlPoints[i].resolve (parent); | |||||
| const Point<float> bottomRight (resolved[1] + (resolved[2] - resolved[0])); | |||||
| float minX = bottomRight.getX(); | float minX = bottomRight.getX(); | ||||
| float maxX = minX; | float maxX = minX; | ||||
| float minY = bottomRight.getY(); | float minY = bottomRight.getY(); | ||||
| @@ -149,10 +168,10 @@ const Rectangle<float> DrawableImage::getBounds() const | |||||
| for (int i = 0; i < 3; ++i) | for (int i = 0; i < 3; ++i) | ||||
| { | { | ||||
| minX = jmin (minX, controlPoints[i].getX()); | |||||
| maxX = jmax (maxX, controlPoints[i].getX()); | |||||
| minY = jmin (minY, controlPoints[i].getY()); | |||||
| maxY = jmax (maxY, controlPoints[i].getY()); | |||||
| minX = jmin (minX, resolved[i].getX()); | |||||
| maxX = jmax (maxX, resolved[i].getX()); | |||||
| minY = jmin (minY, resolved[i].getY()); | |||||
| maxY = jmax (maxY, resolved[i].getY()); | |||||
| } | } | ||||
| return Rectangle<float> (minX, minY, maxX - minX, maxY - minY); | return Rectangle<float> (minX, minY, maxX - minX, maxY - minY); | ||||
| @@ -163,7 +182,7 @@ bool DrawableImage::hitTest (float x, float y) const | |||||
| if (image == 0) | if (image == 0) | ||||
| return false; | return false; | ||||
| getTransform().inverted().transformPoint (x, y); | |||||
| calculateTransform().inverted().transformPoint (x, y); | |||||
| const int ix = roundToInt (x); | const int ix = roundToInt (x); | ||||
| const int iy = roundToInt (y); | const int iy = roundToInt (y); | ||||
| @@ -177,81 +196,117 @@ bool DrawableImage::hitTest (float x, float y) const | |||||
| Drawable* DrawableImage::createCopy() const | Drawable* DrawableImage::createCopy() const | ||||
| { | { | ||||
| DrawableImage* const di = new DrawableImage(); | |||||
| return new DrawableImage (*this); | |||||
| } | |||||
| di->opacity = opacity; | |||||
| di->overlayColour = overlayColour; | |||||
| void DrawableImage::invalidatePoints() | |||||
| { | |||||
| } | |||||
| for (int i = 0; i < 4; ++i) | |||||
| di->controlPoints[i] = controlPoints[i]; | |||||
| //============================================================================== | |||||
| const Identifier DrawableImage::valueTreeType ("Image"); | |||||
| if (image != 0) | |||||
| { | |||||
| if ((! canDeleteImage) || ! ImageCache::isImageInCache (image)) | |||||
| { | |||||
| di->setImage (*image); | |||||
| } | |||||
| else | |||||
| { | |||||
| ImageCache::incReferenceCount (image); | |||||
| di->setImage (image, true); | |||||
| } | |||||
| } | |||||
| const Identifier DrawableImage::ValueTreeWrapper::opacity ("opacity"); | |||||
| const Identifier DrawableImage::ValueTreeWrapper::overlay ("overlay"); | |||||
| const Identifier DrawableImage::ValueTreeWrapper::image ("image"); | |||||
| const Identifier DrawableImage::ValueTreeWrapper::topLeft ("topLeft"); | |||||
| const Identifier DrawableImage::ValueTreeWrapper::topRight ("topRight"); | |||||
| const Identifier DrawableImage::ValueTreeWrapper::bottomLeft ("bottomLeft"); | |||||
| return di; | |||||
| //============================================================================== | |||||
| DrawableImage::ValueTreeWrapper::ValueTreeWrapper (const ValueTree& state_) | |||||
| : ValueTreeWrapperBase (state_) | |||||
| { | |||||
| jassert (state.hasType (valueTreeType)); | |||||
| } | } | ||||
| //============================================================================== | |||||
| const Identifier DrawableImage::valueTreeType ("Image"); | |||||
| const var DrawableImage::ValueTreeWrapper::getImageIdentifier() const | |||||
| { | |||||
| return state [image]; | |||||
| } | |||||
| namespace DrawableImageHelpers | |||||
| void DrawableImage::ValueTreeWrapper::setImageIdentifier (const var& newIdentifier, UndoManager* undoManager) | |||||
| { | { | ||||
| static const Identifier opacity ("opacity"); | |||||
| static const Identifier overlay ("overlay"); | |||||
| static const Identifier image ("image"); | |||||
| static const Identifier topLeft ("topLeft"); | |||||
| static const Identifier topRight ("topRight"); | |||||
| static const Identifier bottomLeft ("bottomLeft"); | |||||
| static void stringToPoint (const String& coords, Point<float>& point) | |||||
| { | |||||
| if (coords.isNotEmpty()) | |||||
| { | |||||
| const int comma = coords.indexOfChar (','); | |||||
| point.setXY (coords.substring (0, comma).getFloatValue(), | |||||
| coords.substring (comma + 1).getFloatValue()); | |||||
| } | |||||
| } | |||||
| state.setProperty (image, newIdentifier, undoManager); | |||||
| } | |||||
| static const var pointToString (const Point<float>& point) | |||||
| { | |||||
| return String (point.getX()) + ", " + String (point.getY()); | |||||
| } | |||||
| float DrawableImage::ValueTreeWrapper::getOpacity() const | |||||
| { | |||||
| return (float) state.getProperty (opacity, 1.0); | |||||
| } | } | ||||
| const Rectangle<float> DrawableImage::refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider) | |||||
| void DrawableImage::ValueTreeWrapper::setOpacity (float newOpacity, UndoManager* undoManager) | |||||
| { | |||||
| state.setProperty (opacity, newOpacity, undoManager); | |||||
| } | |||||
| const Colour DrawableImage::ValueTreeWrapper::getOverlayColour() const | |||||
| { | |||||
| return Colour (state [overlay].toString().getHexValue32()); | |||||
| } | |||||
| void DrawableImage::ValueTreeWrapper::setOverlayColour (const Colour& newColour, UndoManager* undoManager) | |||||
| { | |||||
| if (newColour.isTransparent()) | |||||
| state.removeProperty (overlay, undoManager); | |||||
| else | |||||
| state.setProperty (overlay, String::toHexString ((int) newColour.getARGB()), undoManager); | |||||
| } | |||||
| const RelativePoint DrawableImage::ValueTreeWrapper::getTargetPositionForTopLeft() const | |||||
| { | |||||
| const String pos (state [topLeft].toString()); | |||||
| return pos.isNotEmpty() ? RelativePoint (pos) : RelativePoint(); | |||||
| } | |||||
| void DrawableImage::ValueTreeWrapper::setTargetPositionForTopLeft (const RelativePoint& newPoint, UndoManager* undoManager) | |||||
| { | |||||
| state.setProperty (topLeft, newPoint.toString(), undoManager); | |||||
| } | |||||
| const RelativePoint DrawableImage::ValueTreeWrapper::getTargetPositionForTopRight() const | |||||
| { | |||||
| const String pos (state [topRight].toString()); | |||||
| return pos.isNotEmpty() ? RelativePoint (pos) : RelativePoint (Point<float> (100.0f, 0.0f)); | |||||
| } | |||||
| void DrawableImage::ValueTreeWrapper::setTargetPositionForTopRight (const RelativePoint& newPoint, UndoManager* undoManager) | |||||
| { | |||||
| state.setProperty (topRight, newPoint.toString(), undoManager); | |||||
| } | |||||
| const RelativePoint DrawableImage::ValueTreeWrapper::getTargetPositionForBottomLeft() const | |||||
| { | |||||
| const String pos (state [bottomLeft].toString()); | |||||
| return pos.isNotEmpty() ? RelativePoint (pos) : RelativePoint (Point<float> (0.0f, 100.0f)); | |||||
| } | |||||
| void DrawableImage::ValueTreeWrapper::setTargetPositionForBottomLeft (const RelativePoint& newPoint, UndoManager* undoManager) | |||||
| { | { | ||||
| jassert (tree.hasType (valueTreeType)); | |||||
| state.setProperty (bottomLeft, newPoint.toString(), undoManager); | |||||
| } | |||||
| setName (tree [idProperty]); | |||||
| //============================================================================== | |||||
| const Rectangle<float> DrawableImage::refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider) | |||||
| { | |||||
| const ValueTreeWrapper controller (tree); | |||||
| setName (controller.getID()); | |||||
| const float newOpacity = tree.getProperty (DrawableImageHelpers::opacity, 1.0); | |||||
| const Colour newOverlayColour (tree [DrawableImageHelpers::overlay].toString().getHexValue32()); | |||||
| const float newOpacity = controller.getOpacity(); | |||||
| const Colour newOverlayColour (controller.getOverlayColour()); | |||||
| Image* newImage = 0; | Image* newImage = 0; | ||||
| const String imageIdentifier (tree [DrawableImageHelpers::image].toString()); | |||||
| if (imageIdentifier.isNotEmpty()) | |||||
| { | |||||
| jassert (imageProvider != 0); // if you're using images, you need to provide something that can load and save them! | |||||
| const var imageIdentifier (controller.getImageIdentifier()); | |||||
| if (imageProvider != 0) | |||||
| newImage = imageProvider->getImageForIdentifier (imageIdentifier); | |||||
| } | |||||
| jassert (imageProvider != 0 || imageIdentifier.isVoid()); // if you're using images, you need to provide something that can load and save them! | |||||
| if (imageProvider != 0) | |||||
| newImage = imageProvider->getImageForIdentifier (imageIdentifier); | |||||
| Point<float> newControlPoint[3]; | |||||
| DrawableImageHelpers::stringToPoint (tree [DrawableImageHelpers::topLeft].toString(), newControlPoint[0]); | |||||
| DrawableImageHelpers::stringToPoint (tree [DrawableImageHelpers::topRight].toString(), newControlPoint[1]); | |||||
| DrawableImageHelpers::stringToPoint (tree [DrawableImageHelpers::bottomLeft].toString(), newControlPoint[2]); | |||||
| RelativePoint newControlPoint[3] = { controller.getTargetPositionForTopLeft(), | |||||
| controller.getTargetPositionForTopRight(), | |||||
| controller.getTargetPositionForBottomLeft() }; | |||||
| if (newOpacity != opacity || overlayColour != newOverlayColour || image != newImage | if (newOpacity != opacity || overlayColour != newOverlayColour || image != newImage | ||||
| || controlPoints[0] != newControlPoint[0] | || controlPoints[0] != newControlPoint[0] | ||||
| @@ -266,7 +321,10 @@ const Rectangle<float> DrawableImage::refreshFromValueTree (const ValueTree& tre | |||||
| if (image != newImage) | if (image != newImage) | ||||
| { | { | ||||
| ImageCache::release (image); | |||||
| if (canDeleteImage) | |||||
| ImageCache::releaseOrDelete (image); | |||||
| canDeleteImage = true; | |||||
| image = newImage; | image = newImage; | ||||
| } | } | ||||
| @@ -279,33 +337,25 @@ const Rectangle<float> DrawableImage::refreshFromValueTree (const ValueTree& tre | |||||
| const ValueTree DrawableImage::createValueTree (ImageProvider* imageProvider) const | const ValueTree DrawableImage::createValueTree (ImageProvider* imageProvider) const | ||||
| { | { | ||||
| ValueTree v (valueTreeType); | |||||
| ValueTree tree (valueTreeType); | |||||
| ValueTreeWrapper v (tree); | |||||
| if (getName().isNotEmpty()) | |||||
| v.setProperty (idProperty, getName(), 0); | |||||
| if (opacity < 1.0f) | |||||
| v.setProperty (DrawableImageHelpers::opacity, (double) opacity, 0); | |||||
| if (! overlayColour.isTransparent()) | |||||
| v.setProperty (DrawableImageHelpers::overlay, String::toHexString ((int) overlayColour.getARGB()), 0); | |||||
| if (! getTransform().isIdentity()) | |||||
| { | |||||
| v.setProperty (DrawableImageHelpers::topLeft, DrawableImageHelpers::pointToString (controlPoints[0]), 0); | |||||
| v.setProperty (DrawableImageHelpers::topRight, DrawableImageHelpers::pointToString (controlPoints[1]), 0); | |||||
| v.setProperty (DrawableImageHelpers::bottomLeft, DrawableImageHelpers::pointToString (controlPoints[2]), 0); | |||||
| } | |||||
| v.setID (getName(), 0); | |||||
| v.setOpacity (opacity, 0); | |||||
| v.setOverlayColour (overlayColour, 0); | |||||
| v.setTargetPositionForTopLeft (controlPoints[0], 0); | |||||
| v.setTargetPositionForTopRight (controlPoints[1], 0); | |||||
| v.setTargetPositionForBottomLeft (controlPoints[2], 0); | |||||
| if (image != 0) | if (image != 0) | ||||
| { | { | ||||
| jassert (imageProvider != 0); // if you're using images, you need to provide something that can load and save them! | jassert (imageProvider != 0); // if you're using images, you need to provide something that can load and save them! | ||||
| if (imageProvider != 0) | if (imageProvider != 0) | ||||
| v.setProperty (DrawableImageHelpers::image, imageProvider->getIdentifierForImage (image), 0); | |||||
| v.setImageIdentifier (imageProvider->getIdentifierForImage (image), 0); | |||||
| } | } | ||||
| return v; | |||||
| return tree; | |||||
| } | } | ||||
| @@ -40,6 +40,7 @@ class JUCE_API DrawableImage : public Drawable | |||||
| public: | public: | ||||
| //============================================================================== | //============================================================================== | ||||
| DrawableImage(); | DrawableImage(); | ||||
| DrawableImage (const DrawableImage& other); | |||||
| /** Destructor. */ | /** Destructor. */ | ||||
| virtual ~DrawableImage(); | virtual ~DrawableImage(); | ||||
| @@ -59,7 +60,7 @@ public: | |||||
| with ImageCache and pass it in here with releaseWhenNotNeeded = true, then | with ImageCache and pass it in here with releaseWhenNotNeeded = true, then | ||||
| it'll be released neatly with its reference count being decreased. | it'll be released neatly with its reference count being decreased. | ||||
| @param imageToUse the image to render | |||||
| @param imageToUse the image to render (may be a null pointer) | |||||
| @param releaseWhenNotNeeded if false, a simple pointer is kept to the image; if true, | @param releaseWhenNotNeeded if false, a simple pointer is kept to the image; if true, | ||||
| then the image will be deleted when this object no longer | then the image will be deleted when this object no longer | ||||
| needs it - unless the image was created by the ImageCache, | needs it - unless the image was created by the ImageCache, | ||||
| @@ -70,9 +71,6 @@ public: | |||||
| /** Returns the current image. */ | /** Returns the current image. */ | ||||
| Image* getImage() const throw() { return image; } | Image* getImage() const throw() { return image; } | ||||
| /** Clears (and possibly deletes) the currently set image. */ | |||||
| void clearImage(); | |||||
| /** Sets the opacity to use when drawing the image. */ | /** Sets the opacity to use when drawing the image. */ | ||||
| void setOpacity (float newOpacity); | void setOpacity (float newOpacity); | ||||
| @@ -103,27 +101,27 @@ public: | |||||
| @param imageBottomLeftPosition the position that the image's bottom-left corner should be mapped to | @param imageBottomLeftPosition the position that the image's bottom-left corner should be mapped to | ||||
| in the target coordinate space. | in the target coordinate space. | ||||
| */ | */ | ||||
| void setTransform (const Point<float>& imageTopLeftPosition, | |||||
| const Point<float>& imageTopRightPosition, | |||||
| const Point<float>& imageBottomLeftPosition); | |||||
| void setTransform (const RelativePoint& imageTopLeftPosition, | |||||
| const RelativePoint& imageTopRightPosition, | |||||
| const RelativePoint& imageBottomLeftPosition); | |||||
| /** Returns the position to which the image's top-left corner should be remapped in the target | /** Returns the position to which the image's top-left corner should be remapped in the target | ||||
| coordinate space when rendering this object. | coordinate space when rendering this object. | ||||
| @see setTransform | @see setTransform | ||||
| */ | */ | ||||
| const Point<float>& getTargetPositionForTopLeft() const throw() { return controlPoints[0]; } | |||||
| const RelativePoint& getTargetPositionForTopLeft() const throw() { return controlPoints[0]; } | |||||
| /** Returns the position to which the image's top-right corner should be remapped in the target | /** Returns the position to which the image's top-right corner should be remapped in the target | ||||
| coordinate space when rendering this object. | coordinate space when rendering this object. | ||||
| @see setTransform | @see setTransform | ||||
| */ | */ | ||||
| const Point<float>& getTargetPositionForTopRight() const throw() { return controlPoints[1]; } | |||||
| const RelativePoint& getTargetPositionForTopRight() const throw() { return controlPoints[1]; } | |||||
| /** Returns the position to which the image's bottom-left corner should be remapped in the target | /** Returns the position to which the image's bottom-left corner should be remapped in the target | ||||
| coordinate space when rendering this object. | coordinate space when rendering this object. | ||||
| @see setTransform | @see setTransform | ||||
| */ | */ | ||||
| const Point<float>& getTargetPositionForBottomLeft() const throw() { return controlPoints[2]; } | |||||
| const RelativePoint& getTargetPositionForBottomLeft() const throw() { return controlPoints[2]; } | |||||
| //============================================================================== | //============================================================================== | ||||
| /** @internal */ | /** @internal */ | ||||
| @@ -135,6 +133,8 @@ public: | |||||
| /** @internal */ | /** @internal */ | ||||
| Drawable* createCopy() const; | Drawable* createCopy() const; | ||||
| /** @internal */ | /** @internal */ | ||||
| void invalidatePoints(); | |||||
| /** @internal */ | |||||
| const Rectangle<float> refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider); | const Rectangle<float> refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider); | ||||
| /** @internal */ | /** @internal */ | ||||
| const ValueTree createValueTree (ImageProvider* imageProvider) const; | const ValueTree createValueTree (ImageProvider* imageProvider) const; | ||||
| @@ -143,6 +143,35 @@ public: | |||||
| /** @internal */ | /** @internal */ | ||||
| const Identifier getValueTreeType() const { return valueTreeType; } | const Identifier getValueTreeType() const { return valueTreeType; } | ||||
| //============================================================================== | |||||
| /** Internally-used class for wrapping a DrawableImage's state into a ValueTree. */ | |||||
| class ValueTreeWrapper : public ValueTreeWrapperBase | |||||
| { | |||||
| public: | |||||
| ValueTreeWrapper (const ValueTree& state); | |||||
| const var getImageIdentifier() const; | |||||
| void setImageIdentifier (const var& newIdentifier, UndoManager* undoManager); | |||||
| float getOpacity() const; | |||||
| void setOpacity (float newOpacity, UndoManager* undoManager); | |||||
| const Colour getOverlayColour() const; | |||||
| void setOverlayColour (const Colour& newColour, UndoManager* undoManager); | |||||
| const RelativePoint getTargetPositionForTopLeft() const; | |||||
| void setTargetPositionForTopLeft (const RelativePoint& newPoint, UndoManager* undoManager); | |||||
| const RelativePoint getTargetPositionForTopRight() const; | |||||
| void setTargetPositionForTopRight (const RelativePoint& newPoint, UndoManager* undoManager); | |||||
| const RelativePoint getTargetPositionForBottomLeft() const; | |||||
| void setTargetPositionForBottomLeft (const RelativePoint& newPoint, UndoManager* undoManager); | |||||
| private: | |||||
| static const Identifier opacity, overlay, image, topLeft, topRight, bottomLeft; | |||||
| }; | |||||
| //============================================================================== | //============================================================================== | ||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| @@ -151,11 +180,10 @@ private: | |||||
| bool canDeleteImage; | bool canDeleteImage; | ||||
| float opacity; | float opacity; | ||||
| Colour overlayColour; | Colour overlayColour; | ||||
| Point<float> controlPoints[3]; | |||||
| RelativePoint controlPoints[3]; | |||||
| const AffineTransform getTransform() const; | |||||
| const AffineTransform calculateTransform() const; | |||||
| DrawableImage (const DrawableImage&); | |||||
| DrawableImage& operator= (const DrawableImage&); | DrawableImage& operator= (const DrawableImage&); | ||||
| }; | }; | ||||
| @@ -28,6 +28,7 @@ | |||||
| BEGIN_JUCE_NAMESPACE | BEGIN_JUCE_NAMESPACE | ||||
| #include "juce_DrawablePath.h" | #include "juce_DrawablePath.h" | ||||
| #include "juce_DrawableComposite.h" | |||||
| #include "../../../io/streams/juce_MemoryOutputStream.h" | #include "../../../io/streams/juce_MemoryOutputStream.h" | ||||
| @@ -35,10 +36,25 @@ BEGIN_JUCE_NAMESPACE | |||||
| DrawablePath::DrawablePath() | DrawablePath::DrawablePath() | ||||
| : mainFill (Colours::black), | : mainFill (Colours::black), | ||||
| strokeFill (Colours::transparentBlack), | strokeFill (Colours::transparentBlack), | ||||
| strokeType (0.0f) | |||||
| strokeType (0.0f), | |||||
| pathNeedsUpdating (true), | |||||
| strokeNeedsUpdating (true) | |||||
| { | { | ||||
| } | } | ||||
| DrawablePath::DrawablePath (const DrawablePath& other) | |||||
| : mainFill (other.mainFill), | |||||
| strokeFill (other.strokeFill), | |||||
| strokeType (other.strokeType), | |||||
| pathNeedsUpdating (true), | |||||
| strokeNeedsUpdating (true) | |||||
| { | |||||
| if (other.relativePath != 0) | |||||
| relativePath = new RelativePointPath (*other.relativePath); | |||||
| else | |||||
| path = other.path; | |||||
| } | |||||
| DrawablePath::~DrawablePath() | DrawablePath::~DrawablePath() | ||||
| { | { | ||||
| } | } | ||||
| @@ -47,7 +63,7 @@ DrawablePath::~DrawablePath() | |||||
| void DrawablePath::setPath (const Path& newPath) | void DrawablePath::setPath (const Path& newPath) | ||||
| { | { | ||||
| path = newPath; | path = newPath; | ||||
| updateOutline(); | |||||
| strokeNeedsUpdating = true; | |||||
| } | } | ||||
| void DrawablePath::setFill (const FillType& newFill) | void DrawablePath::setFill (const FillType& newFill) | ||||
| @@ -63,7 +79,7 @@ void DrawablePath::setStrokeFill (const FillType& newFill) | |||||
| void DrawablePath::setStrokeType (const PathStrokeType& newStrokeType) | void DrawablePath::setStrokeType (const PathStrokeType& newStrokeType) | ||||
| { | { | ||||
| strokeType = newStrokeType; | strokeType = newStrokeType; | ||||
| updateOutline(); | |||||
| strokeNeedsUpdating = true; | |||||
| } | } | ||||
| void DrawablePath::setStrokeThickness (const float newThickness) | void DrawablePath::setStrokeThickness (const float newThickness) | ||||
| @@ -71,6 +87,55 @@ void DrawablePath::setStrokeThickness (const float newThickness) | |||||
| setStrokeType (PathStrokeType (newThickness, strokeType.getJointStyle(), strokeType.getEndStyle())); | setStrokeType (PathStrokeType (newThickness, strokeType.getJointStyle(), strokeType.getEndStyle())); | ||||
| } | } | ||||
| void DrawablePath::updatePath() const | |||||
| { | |||||
| if (pathNeedsUpdating) | |||||
| { | |||||
| pathNeedsUpdating = false; | |||||
| if (relativePath != 0) | |||||
| { | |||||
| path.clear(); | |||||
| relativePath->createPath (path, parent); | |||||
| strokeNeedsUpdating = true; | |||||
| } | |||||
| } | |||||
| } | |||||
| void DrawablePath::updateStroke() const | |||||
| { | |||||
| if (strokeNeedsUpdating) | |||||
| { | |||||
| strokeNeedsUpdating = false; | |||||
| updatePath(); | |||||
| stroke.clear(); | |||||
| strokeType.createStrokedPath (stroke, path, AffineTransform::identity, 4.0f); | |||||
| } | |||||
| } | |||||
| const Path& DrawablePath::getPath() const | |||||
| { | |||||
| updatePath(); | |||||
| return path; | |||||
| } | |||||
| const Path& DrawablePath::getStrokePath() const | |||||
| { | |||||
| updateStroke(); | |||||
| return stroke; | |||||
| } | |||||
| bool DrawablePath::isStrokeVisible() const throw() | |||||
| { | |||||
| return strokeType.getStrokeThickness() > 0.0f && ! strokeFill.isInvisible(); | |||||
| } | |||||
| void DrawablePath::invalidatePoints() | |||||
| { | |||||
| pathNeedsUpdating = true; | |||||
| strokeNeedsUpdating = true; | |||||
| } | |||||
| //============================================================================== | //============================================================================== | ||||
| void DrawablePath::render (const Drawable::RenderingContext& context) const | void DrawablePath::render (const Drawable::RenderingContext& context) const | ||||
| { | { | ||||
| @@ -81,10 +146,10 @@ void DrawablePath::render (const Drawable::RenderingContext& context) const | |||||
| f.transform = f.transform.followedBy (context.transform); | f.transform = f.transform.followedBy (context.transform); | ||||
| context.g.setFillType (f); | context.g.setFillType (f); | ||||
| context.g.fillPath (path, context.transform); | |||||
| context.g.fillPath (getPath(), context.transform); | |||||
| } | } | ||||
| if (strokeType.getStrokeThickness() > 0.0f) | |||||
| if (isStrokeVisible()) | |||||
| { | { | ||||
| FillType f (strokeFill); | FillType f (strokeFill); | ||||
| if (f.isGradient()) | if (f.isGradient()) | ||||
| @@ -92,162 +157,133 @@ void DrawablePath::render (const Drawable::RenderingContext& context) const | |||||
| f.transform = f.transform.followedBy (context.transform); | f.transform = f.transform.followedBy (context.transform); | ||||
| context.g.setFillType (f); | context.g.setFillType (f); | ||||
| context.g.fillPath (stroke, context.transform); | |||||
| context.g.fillPath (getStrokePath(), context.transform); | |||||
| } | } | ||||
| } | } | ||||
| void DrawablePath::updateOutline() | |||||
| { | |||||
| stroke.clear(); | |||||
| strokeType.createStrokedPath (stroke, path, AffineTransform::identity, 4.0f); | |||||
| } | |||||
| const Rectangle<float> DrawablePath::getBounds() const | const Rectangle<float> DrawablePath::getBounds() const | ||||
| { | { | ||||
| if (strokeType.getStrokeThickness() > 0.0f) | |||||
| return stroke.getBounds(); | |||||
| if (isStrokeVisible()) | |||||
| return getStrokePath().getBounds(); | |||||
| else | else | ||||
| return path.getBounds(); | |||||
| return getPath().getBounds(); | |||||
| } | } | ||||
| bool DrawablePath::hitTest (float x, float y) const | bool DrawablePath::hitTest (float x, float y) const | ||||
| { | { | ||||
| return path.contains (x, y) | |||||
| || stroke.contains (x, y); | |||||
| return getPath().contains (x, y) | |||||
| || (isStrokeVisible() && getStrokePath().contains (x, y)); | |||||
| } | } | ||||
| Drawable* DrawablePath::createCopy() const | Drawable* DrawablePath::createCopy() const | ||||
| { | { | ||||
| DrawablePath* const dp = new DrawablePath(); | |||||
| dp->path = path; | |||||
| dp->stroke = stroke; | |||||
| dp->mainFill = mainFill; | |||||
| dp->strokeFill = strokeFill; | |||||
| dp->strokeType = strokeType; | |||||
| return dp; | |||||
| return new DrawablePath (*this); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| const Identifier DrawablePath::valueTreeType ("Path"); | const Identifier DrawablePath::valueTreeType ("Path"); | ||||
| namespace DrawablePathHelpers | |||||
| { | |||||
| static const Identifier type ("type"); | |||||
| static const Identifier solid ("solid"); | |||||
| static const Identifier colour ("colour"); | |||||
| static const Identifier gradient ("gradient"); | |||||
| static const Identifier x1 ("x1"); | |||||
| static const Identifier x2 ("x2"); | |||||
| static const Identifier y1 ("y1"); | |||||
| static const Identifier y2 ("y2"); | |||||
| static const Identifier radial ("radial"); | |||||
| static const Identifier colours ("colours"); | |||||
| static const Identifier fill ("fill"); | |||||
| static const Identifier stroke ("stroke"); | |||||
| static const Identifier jointStyle ("jointStyle"); | |||||
| static const Identifier capStyle ("capStyle"); | |||||
| static const Identifier strokeWidth ("strokeWidth"); | |||||
| static const Identifier path ("path"); | |||||
| static bool updateFillType (const ValueTree& v, FillType& fillType) | |||||
| { | |||||
| const String type (v[type].toString()); | |||||
| if (type.equalsIgnoreCase (solid)) | |||||
| { | |||||
| const String colourString (v [colour].toString()); | |||||
| const Colour newColour (colourString.isEmpty() ? (uint32) 0xff000000 | |||||
| : (uint32) colourString.getHexValue32()); | |||||
| if (fillType.isColour() && fillType.colour == newColour) | |||||
| return false; | |||||
| const Identifier DrawablePath::ValueTreeWrapper::fill ("fill"); | |||||
| const Identifier DrawablePath::ValueTreeWrapper::stroke ("stroke"); | |||||
| const Identifier DrawablePath::ValueTreeWrapper::jointStyle ("jointStyle"); | |||||
| const Identifier DrawablePath::ValueTreeWrapper::capStyle ("capStyle"); | |||||
| const Identifier DrawablePath::ValueTreeWrapper::strokeWidth ("strokeWidth"); | |||||
| const Identifier DrawablePath::ValueTreeWrapper::path ("path"); | |||||
| fillType.setColour (newColour); | |||||
| return true; | |||||
| } | |||||
| else if (type.equalsIgnoreCase (gradient)) | |||||
| { | |||||
| ColourGradient g; | |||||
| g.point1.setXY (v[x1], v[y1]); | |||||
| g.point2.setXY (v[x2], v[y2]); | |||||
| g.isRadial = v[radial]; | |||||
| //============================================================================== | |||||
| DrawablePath::ValueTreeWrapper::ValueTreeWrapper (const ValueTree& state_) | |||||
| : ValueTreeWrapperBase (state_) | |||||
| { | |||||
| jassert (state.hasType (valueTreeType)); | |||||
| } | |||||
| StringArray colourSteps; | |||||
| colourSteps.addTokens (v[colours].toString(), false); | |||||
| const FillType DrawablePath::ValueTreeWrapper::getMainFill() const | |||||
| { | |||||
| return readFillType (state.getChildWithName (fill)); | |||||
| } | |||||
| for (int i = 0; i < colourSteps.size() / 2; ++i) | |||||
| g.addColour (colourSteps[i * 2].getDoubleValue(), | |||||
| Colour ((uint32) colourSteps[i * 2 + 1].getHexValue32())); | |||||
| void DrawablePath::ValueTreeWrapper::setMainFill (const FillType& newFill, UndoManager* undoManager) | |||||
| { | |||||
| replaceFillType (fill, newFill, undoManager); | |||||
| } | |||||
| if (fillType.isGradient() && *fillType.gradient == g) | |||||
| return false; | |||||
| const FillType DrawablePath::ValueTreeWrapper::getStrokeFill() const | |||||
| { | |||||
| return readFillType (state.getChildWithName (stroke)); | |||||
| } | |||||
| fillType.setGradient (g); | |||||
| return true; | |||||
| } | |||||
| void DrawablePath::ValueTreeWrapper::setStrokeFill (const FillType& newFill, UndoManager* undoManager) | |||||
| { | |||||
| replaceFillType (stroke, newFill, undoManager); | |||||
| } | |||||
| jassertfalse; | |||||
| return false; | |||||
| } | |||||
| const PathStrokeType DrawablePath::ValueTreeWrapper::getStrokeType() const | |||||
| { | |||||
| const String jointStyleString (state [jointStyle].toString()); | |||||
| const String capStyleString (state [capStyle].toString()); | |||||
| return PathStrokeType (state [strokeWidth], | |||||
| jointStyleString == "curved" ? PathStrokeType::curved | |||||
| : (jointStyleString == "bevel" ? PathStrokeType::beveled | |||||
| : PathStrokeType::mitered), | |||||
| capStyleString == "square" ? PathStrokeType::square | |||||
| : (capStyleString == "round" ? PathStrokeType::rounded | |||||
| : PathStrokeType::butt)); | |||||
| } | |||||
| static ValueTree createFillType (const Identifier& tagName, const FillType& fillType) | |||||
| { | |||||
| ValueTree v (tagName); | |||||
| void DrawablePath::ValueTreeWrapper::setStrokeType (const PathStrokeType& newStrokeType, UndoManager* undoManager) | |||||
| { | |||||
| state.setProperty (strokeWidth, (double) newStrokeType.getStrokeThickness(), undoManager); | |||||
| state.setProperty (jointStyle, newStrokeType.getJointStyle() == PathStrokeType::mitered | |||||
| ? "miter" : (newStrokeType.getJointStyle() == PathStrokeType::curved ? "curved" : "bevel"), undoManager); | |||||
| state.setProperty (capStyle, newStrokeType.getEndStyle() == PathStrokeType::butt | |||||
| ? "butt" : (newStrokeType.getEndStyle() == PathStrokeType::square ? "square" : "round"), undoManager); | |||||
| } | |||||
| if (fillType.isColour()) | |||||
| { | |||||
| v.setProperty (type, "solid", 0); | |||||
| v.setProperty (colour, String::toHexString ((int) fillType.colour.getARGB()), 0); | |||||
| } | |||||
| else if (fillType.isGradient()) | |||||
| { | |||||
| v.setProperty (type, "gradient", 0); | |||||
| v.setProperty (x1, fillType.gradient->point1.getX(), 0); | |||||
| v.setProperty (y1, fillType.gradient->point1.getY(), 0); | |||||
| v.setProperty (x2, fillType.gradient->point2.getX(), 0); | |||||
| v.setProperty (y2, fillType.gradient->point2.getY(), 0); | |||||
| v.setProperty (radial, fillType.gradient->isRadial, 0); | |||||
| String s; | |||||
| for (int i = 0; i < fillType.gradient->getNumColours(); ++i) | |||||
| s << " " << fillType.gradient->getColourPosition (i) | |||||
| << " " << String::toHexString ((int) fillType.gradient->getColour(i).getARGB()); | |||||
| v.setProperty (colours, s.trimStart(), 0); | |||||
| } | |||||
| else | |||||
| { | |||||
| jassertfalse; //xxx | |||||
| } | |||||
| void DrawablePath::ValueTreeWrapper::getPath (RelativePointPath& p) const | |||||
| { | |||||
| RelativePointPath newPath (state [path]); | |||||
| p.swapWith (newPath); | |||||
| } | |||||
| return v; | |||||
| } | |||||
| void DrawablePath::ValueTreeWrapper::setPath (const String& newPath, UndoManager* undoManager) | |||||
| { | |||||
| state.setProperty (path, newPath, undoManager); | |||||
| } | } | ||||
| const Rectangle<float> DrawablePath::refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider) | const Rectangle<float> DrawablePath::refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider) | ||||
| { | { | ||||
| jassert (tree.hasType (valueTreeType)); | |||||
| Rectangle<float> damageRect; | Rectangle<float> damageRect; | ||||
| setName (tree [idProperty]); | |||||
| ValueTreeWrapper v (tree); | |||||
| setName (v.getID()); | |||||
| bool needsRedraw = false; | |||||
| const FillType newFill (v.getMainFill()); | |||||
| if (mainFill != newFill) | |||||
| { | |||||
| needsRedraw = true; | |||||
| mainFill = newFill; | |||||
| } | |||||
| const FillType newStrokeFill (v.getStrokeFill()); | |||||
| bool needsRedraw = DrawablePathHelpers::updateFillType (tree.getChildWithName (DrawablePathHelpers::fill), mainFill); | |||||
| needsRedraw = DrawablePathHelpers::updateFillType (tree.getChildWithName (DrawablePathHelpers::stroke), strokeFill) || needsRedraw; | |||||
| if (strokeFill != newStrokeFill) | |||||
| { | |||||
| needsRedraw = true; | |||||
| strokeFill = newStrokeFill; | |||||
| } | |||||
| const String jointStyle (tree [DrawablePathHelpers::jointStyle].toString()); | |||||
| const String endStyle (tree [DrawablePathHelpers::capStyle].toString()); | |||||
| const PathStrokeType newStroke (v.getStrokeType()); | |||||
| PathStrokeType newStroke (tree [DrawablePathHelpers::strokeWidth], | |||||
| jointStyle == "curved" ? PathStrokeType::curved | |||||
| : (jointStyle == "bevel" ? PathStrokeType::beveled | |||||
| : PathStrokeType::mitered), | |||||
| endStyle == "square" ? PathStrokeType::square | |||||
| : (endStyle == "round" ? PathStrokeType::rounded | |||||
| : PathStrokeType::butt)); | |||||
| ScopedPointer<RelativePointPath> newRelativePath (new RelativePointPath()); | |||||
| v.getPath (*newRelativePath); | |||||
| Path newPath; | Path newPath; | ||||
| newPath.restoreFromString (tree [DrawablePathHelpers::path]); | |||||
| newRelativePath->createPath (newPath, parent); | |||||
| if (! newRelativePath->containsAnyDynamicPoints()) | |||||
| newRelativePath = 0; | |||||
| if (strokeType != newStroke || path != newPath) | if (strokeType != newStroke || path != newPath) | ||||
| { | { | ||||
| @@ -257,6 +293,8 @@ const Rectangle<float> DrawablePath::refreshFromValueTree (const ValueTree& tree | |||||
| needsRedraw = true; | needsRedraw = true; | ||||
| } | } | ||||
| relativePath = newRelativePath.release(); | |||||
| if (needsRedraw) | if (needsRedraw) | ||||
| damageRect = damageRect.getUnion (getBounds()); | damageRect = damageRect.getUnion (getBounds()); | ||||
| @@ -265,22 +303,20 @@ const Rectangle<float> DrawablePath::refreshFromValueTree (const ValueTree& tree | |||||
| const ValueTree DrawablePath::createValueTree (ImageProvider* imageProvider) const | const ValueTree DrawablePath::createValueTree (ImageProvider* imageProvider) const | ||||
| { | { | ||||
| ValueTree v (valueTreeType); | |||||
| ValueTree tree (valueTreeType); | |||||
| ValueTreeWrapper v (tree); | |||||
| v.addChild (DrawablePathHelpers::createFillType (DrawablePathHelpers::fill, mainFill), -1, 0); | |||||
| v.addChild (DrawablePathHelpers::createFillType (DrawablePathHelpers::stroke, strokeFill), -1, 0); | |||||
| v.setID (getName(), 0); | |||||
| v.setMainFill (mainFill, 0); | |||||
| v.setStrokeFill (strokeFill, 0); | |||||
| v.setStrokeType (strokeType, 0); | |||||
| if (getName().isNotEmpty()) | |||||
| v.setProperty (idProperty, getName(), 0); | |||||
| v.setProperty (DrawablePathHelpers::strokeWidth, (double) strokeType.getStrokeThickness(), 0); | |||||
| v.setProperty (DrawablePathHelpers::jointStyle, strokeType.getJointStyle() == PathStrokeType::mitered | |||||
| ? "miter" : (strokeType.getJointStyle() == PathStrokeType::curved ? "curved" : "bevel"), 0); | |||||
| v.setProperty (DrawablePathHelpers::capStyle, strokeType.getEndStyle() == PathStrokeType::butt | |||||
| ? "butt" : (strokeType.getEndStyle() == PathStrokeType::square ? "square" : "round"), 0); | |||||
| v.setProperty (DrawablePathHelpers::path, path.toString(), 0); | |||||
| if (relativePath != 0) | |||||
| v.setPath (relativePath->toString(), 0); | |||||
| else | |||||
| v.setPath (path.toString(), 0); | |||||
| return v; | |||||
| return tree; | |||||
| } | } | ||||
| @@ -40,9 +40,9 @@ class JUCE_API DrawablePath : public Drawable | |||||
| { | { | ||||
| public: | public: | ||||
| //============================================================================== | //============================================================================== | ||||
| /** Creates a DrawablePath. | |||||
| */ | |||||
| /** Creates a DrawablePath. */ | |||||
| DrawablePath(); | DrawablePath(); | ||||
| DrawablePath (const DrawablePath& other); | |||||
| /** Destructor. */ | /** Destructor. */ | ||||
| virtual ~DrawablePath(); | virtual ~DrawablePath(); | ||||
| @@ -54,9 +54,6 @@ public: | |||||
| */ | */ | ||||
| void setPath (const Path& newPath); | void setPath (const Path& newPath); | ||||
| /** Returns the current path. */ | |||||
| const Path& getPath() const throw() { return path; } | |||||
| /** Sets a fill type for the path. | /** Sets a fill type for the path. | ||||
| This colour is used to fill the path - if you don't want the path to be | This colour is used to fill the path - if you don't want the path to be | ||||
| @@ -97,6 +94,13 @@ public: | |||||
| const PathStrokeType& getStrokeType() const throw() { return strokeType; } | const PathStrokeType& getStrokeType() const throw() { return strokeType; } | ||||
| //============================================================================== | |||||
| /** Returns the current path. */ | |||||
| const Path& getPath() const; | |||||
| /** Returns the current path for the outline. */ | |||||
| const Path& getStrokePath() const; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** @internal */ | /** @internal */ | ||||
| void render (const Drawable::RenderingContext& context) const; | void render (const Drawable::RenderingContext& context) const; | ||||
| @@ -107,6 +111,8 @@ public: | |||||
| /** @internal */ | /** @internal */ | ||||
| Drawable* createCopy() const; | Drawable* createCopy() const; | ||||
| /** @internal */ | /** @internal */ | ||||
| void invalidatePoints(); | |||||
| /** @internal */ | |||||
| const Rectangle<float> refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider); | const Rectangle<float> refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider); | ||||
| /** @internal */ | /** @internal */ | ||||
| const ValueTree createValueTree (ImageProvider* imageProvider) const; | const ValueTree createValueTree (ImageProvider* imageProvider) const; | ||||
| @@ -115,17 +121,43 @@ public: | |||||
| /** @internal */ | /** @internal */ | ||||
| const Identifier getValueTreeType() const { return valueTreeType; } | const Identifier getValueTreeType() const { return valueTreeType; } | ||||
| //============================================================================== | |||||
| /** Internally-used class for wrapping a DrawablePath's state into a ValueTree. */ | |||||
| class ValueTreeWrapper : public ValueTreeWrapperBase | |||||
| { | |||||
| public: | |||||
| ValueTreeWrapper (const ValueTree& state); | |||||
| const FillType getMainFill() const; | |||||
| void setMainFill (const FillType& newFill, UndoManager* undoManager); | |||||
| const FillType getStrokeFill() const; | |||||
| void setStrokeFill (const FillType& newFill, UndoManager* undoManager); | |||||
| const PathStrokeType getStrokeType() const; | |||||
| void setStrokeType (const PathStrokeType& newStrokeType, UndoManager* undoManager); | |||||
| void getPath (RelativePointPath& path) const; | |||||
| void setPath (const String& newPath, UndoManager* undoManager); | |||||
| private: | |||||
| static const Identifier fill, stroke, jointStyle, capStyle, strokeWidth, path; | |||||
| }; | |||||
| //============================================================================== | //============================================================================== | ||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| private: | private: | ||||
| Path path, stroke; | |||||
| FillType mainFill, strokeFill; | FillType mainFill, strokeFill; | ||||
| PathStrokeType strokeType; | PathStrokeType strokeType; | ||||
| ScopedPointer<RelativePointPath> relativePath; | |||||
| mutable Path path, stroke; | |||||
| mutable bool pathNeedsUpdating, strokeNeedsUpdating; | |||||
| void updateOutline(); | |||||
| void updatePath() const; | |||||
| void updateStroke() const; | |||||
| bool isStrokeVisible() const throw(); | |||||
| DrawablePath (const DrawablePath&); | |||||
| DrawablePath& operator= (const DrawablePath&); | DrawablePath& operator= (const DrawablePath&); | ||||
| }; | }; | ||||
| @@ -36,6 +36,12 @@ DrawableText::DrawableText() | |||||
| { | { | ||||
| } | } | ||||
| DrawableText::DrawableText (const DrawableText& other) | |||||
| : text (other.text), | |||||
| colour (other.colour) | |||||
| { | |||||
| } | |||||
| DrawableText::~DrawableText() | DrawableText::~DrawableText() | ||||
| { | { | ||||
| } | } | ||||
| @@ -76,21 +82,28 @@ bool DrawableText::hitTest (float x, float y) const | |||||
| Drawable* DrawableText::createCopy() const | Drawable* DrawableText::createCopy() const | ||||
| { | { | ||||
| DrawableText* const dt = new DrawableText(); | |||||
| dt->text = text; | |||||
| dt->colour = colour; | |||||
| return new DrawableText (*this); | |||||
| } | |||||
| return dt; | |||||
| void DrawableText::invalidatePoints() | |||||
| { | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| const Identifier DrawableText::valueTreeType ("Text"); | const Identifier DrawableText::valueTreeType ("Text"); | ||||
| const Identifier DrawableText::ValueTreeWrapper::text ("text"); | |||||
| DrawableText::ValueTreeWrapper::ValueTreeWrapper (const ValueTree& state_) | |||||
| : ValueTreeWrapperBase (state_) | |||||
| { | |||||
| jassert (state.hasType (valueTreeType)); | |||||
| } | |||||
| const Rectangle<float> DrawableText::refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider) | const Rectangle<float> DrawableText::refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider) | ||||
| { | { | ||||
| jassert (tree.hasType (valueTreeType)); | |||||
| setName (tree [idProperty]); | |||||
| ValueTreeWrapper v (tree); | |||||
| setName (v.getID()); | |||||
| jassertfalse; // xxx not finished! | jassertfalse; // xxx not finished! | ||||
| @@ -99,13 +112,14 @@ const Rectangle<float> DrawableText::refreshFromValueTree (const ValueTree& tree | |||||
| const ValueTree DrawableText::createValueTree (ImageProvider* imageProvider) const | const ValueTree DrawableText::createValueTree (ImageProvider* imageProvider) const | ||||
| { | { | ||||
| ValueTree v (valueTreeType); | |||||
| ValueTree tree (valueTreeType); | |||||
| ValueTreeWrapper v (tree); | |||||
| if (getName().isNotEmpty()) | |||||
| v.setProperty (idProperty, getName(), 0); | |||||
| v.setID (getName(), 0); | |||||
| jassertfalse; // xxx not finished! | jassertfalse; // xxx not finished! | ||||
| return v; | |||||
| return tree; | |||||
| } | } | ||||
| @@ -42,6 +42,7 @@ public: | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Creates a DrawableText object. */ | /** Creates a DrawableText object. */ | ||||
| DrawableText(); | DrawableText(); | ||||
| DrawableText (const DrawableText& other); | |||||
| /** Destructor. */ | /** Destructor. */ | ||||
| virtual ~DrawableText(); | virtual ~DrawableText(); | ||||
| @@ -78,6 +79,8 @@ public: | |||||
| /** @internal */ | /** @internal */ | ||||
| Drawable* createCopy() const; | Drawable* createCopy() const; | ||||
| /** @internal */ | /** @internal */ | ||||
| void invalidatePoints(); | |||||
| /** @internal */ | |||||
| const Rectangle<float> refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider); | const Rectangle<float> refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider); | ||||
| /** @internal */ | /** @internal */ | ||||
| const ValueTree createValueTree (ImageProvider* imageProvider) const; | const ValueTree createValueTree (ImageProvider* imageProvider) const; | ||||
| @@ -86,6 +89,19 @@ public: | |||||
| /** @internal */ | /** @internal */ | ||||
| const Identifier getValueTreeType() const { return valueTreeType; } | const Identifier getValueTreeType() const { return valueTreeType; } | ||||
| //============================================================================== | |||||
| /** Internally-used class for wrapping a DrawableText's state into a ValueTree. */ | |||||
| class ValueTreeWrapper : public ValueTreeWrapperBase | |||||
| { | |||||
| public: | |||||
| ValueTreeWrapper (const ValueTree& state); | |||||
| //xxx todo | |||||
| private: | |||||
| static const Identifier text; | |||||
| }; | |||||
| //============================================================================== | //============================================================================== | ||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| @@ -93,7 +109,6 @@ private: | |||||
| GlyphArrangement text; | GlyphArrangement text; | ||||
| Colour colour; | Colour colour; | ||||
| DrawableText (const DrawableText&); | |||||
| DrawableText& operator= (const DrawableText&); | DrawableText& operator= (const DrawableText&); | ||||
| }; | }; | ||||
| @@ -74,12 +74,7 @@ namespace PathHelpers | |||||
| while (*t != 0 && ! CharacterFunctions::isWhitespace (*t)) | while (*t != 0 && ! CharacterFunctions::isWhitespace (*t)) | ||||
| ++t; | ++t; | ||||
| const int length = (int) (t - start); | |||||
| while (CharacterFunctions::isWhitespace (*t)) | |||||
| ++t; | |||||
| return String (start, length); | |||||
| return String (start, (int) (t - start)); | |||||
| } | } | ||||
| } | } | ||||
| @@ -1479,12 +1474,15 @@ void Path::restoreFromString (const String& stringVersion) | |||||
| int numValues = 2; | int numValues = 2; | ||||
| float values [6]; | float values [6]; | ||||
| while (*t != 0) | |||||
| for (;;) | |||||
| { | { | ||||
| const String token (PathHelpers::nextToken (t)); | const String token (PathHelpers::nextToken (t)); | ||||
| const juce_wchar firstChar = token[0]; | const juce_wchar firstChar = token[0]; | ||||
| int startNum = 0; | int startNum = 0; | ||||
| if (firstChar == 0) | |||||
| break; | |||||
| if (firstChar == 'm' || firstChar == 'l') | if (firstChar == 'm' || firstChar == 'l') | ||||
| { | { | ||||
| marker = firstChar; | marker = firstChar; | ||||
| @@ -28,6 +28,8 @@ | |||||
| BEGIN_JUCE_NAMESPACE | BEGIN_JUCE_NAMESPACE | ||||
| #include "juce_RelativeCoordinate.h" | #include "juce_RelativeCoordinate.h" | ||||
| #include "../../../io/streams/juce_MemoryOutputStream.h" | |||||
| //============================================================================== | //============================================================================== | ||||
| namespace RelativeCoordinateHelpers | namespace RelativeCoordinateHelpers | ||||
| @@ -61,9 +63,10 @@ namespace RelativeCoordinateHelpers | |||||
| return fullName.fromFirstOccurrenceOf (".", false, false); | return fullName.fromFirstOccurrenceOf (".", false, false); | ||||
| } | } | ||||
| static const RelativeCoordinate findCoordinate (const String& name, const RelativeCoordinate::NamedCoordinateFinder& nameFinder) | |||||
| static const RelativeCoordinate findCoordinate (const String& name, const RelativeCoordinate::NamedCoordinateFinder* nameFinder) | |||||
| { | { | ||||
| return nameFinder.findNamedCoordinate (getObjectName (name), getEdgeName (name)); | |||||
| return nameFinder != 0 ? nameFinder->findNamedCoordinate (getObjectName (name), getEdgeName (name)) | |||||
| : RelativeCoordinate(); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -81,6 +84,13 @@ namespace RelativeCoordinateHelpers | |||||
| ++i; | ++i; | ||||
| } | } | ||||
| static void skipComma (const String& s, int& i) | |||||
| { | |||||
| skipWhitespace (s, i); | |||||
| if (s[i] == ',') | |||||
| ++i; | |||||
| } | |||||
| static const String readAnchorName (const String& s, int& i) | static const String readAnchorName (const String& s, int& i) | ||||
| { | { | ||||
| skipWhitespace (s, i); | skipWhitespace (s, i); | ||||
| @@ -126,10 +136,89 @@ namespace RelativeCoordinateHelpers | |||||
| return value; | return value; | ||||
| } | } | ||||
| static const RelativeCoordinate readNextCoordinate (const String& s, int& i, const bool isHorizontal) | |||||
| { | |||||
| String anchor1 (readAnchorName (s, i)); | |||||
| double value = 0; | |||||
| if (anchor1.isNotEmpty()) | |||||
| { | |||||
| skipWhitespace (s, i); | |||||
| if (s[i] == '+') | |||||
| value = readNumber (s, ++i); | |||||
| else if (s[i] == '-') | |||||
| value = -readNumber (s, ++i); | |||||
| return RelativeCoordinate (value, anchor1); | |||||
| } | |||||
| else | |||||
| { | |||||
| value = readNumber (s, i); | |||||
| skipWhitespace (s, i); | |||||
| if (s[i] == '%') | |||||
| { | |||||
| value /= 100.0; | |||||
| skipWhitespace (s, ++i); | |||||
| String anchor2; | |||||
| if (s[i] == '*') | |||||
| { | |||||
| anchor1 = readAnchorName (s, ++i); | |||||
| if (anchor1.isEmpty()) | |||||
| anchor1 = getOriginAnchorName (isHorizontal); | |||||
| skipWhitespace (s, i); | |||||
| if (s[i] == '-' && s[i + 1] == '>') | |||||
| { | |||||
| i += 2; | |||||
| anchor2 = readAnchorName (s, i); | |||||
| } | |||||
| else | |||||
| { | |||||
| anchor2 = anchor1; | |||||
| anchor1 = getOriginAnchorName (isHorizontal); | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| anchor1 = getOriginAnchorName (isHorizontal); | |||||
| anchor2 = getExtentAnchorName (isHorizontal); | |||||
| } | |||||
| return RelativeCoordinate (value, anchor1, anchor2); | |||||
| } | |||||
| return RelativeCoordinate (value, isHorizontal); | |||||
| } | |||||
| } | |||||
| static const String limitedAccuracyString (const double n) | static const String limitedAccuracyString (const double n) | ||||
| { | { | ||||
| return String (n, 3).trimCharactersAtEnd ("0").trimCharactersAtEnd ("."); | return String (n, 3).trimCharactersAtEnd ("0").trimCharactersAtEnd ("."); | ||||
| } | } | ||||
| static bool couldBeMistakenForPathCommand (const String& s) | |||||
| { | |||||
| switch (s[0]) | |||||
| { | |||||
| case 'a': | |||||
| case 'm': | |||||
| case 'l': | |||||
| case 'z': | |||||
| case 'q': | |||||
| case 'c': | |||||
| return s[1] == 0 || CharacterFunctions::isWhitespace (s[1]); | |||||
| default: | |||||
| break; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -171,10 +260,27 @@ RelativeCoordinate::RelativeCoordinate (const double relativeProportion, const S | |||||
| jassert (anchor2.isNotEmpty()); | jassert (anchor2.isNotEmpty()); | ||||
| } | } | ||||
| RelativeCoordinate::RelativeCoordinate (const String& s, const bool isHorizontal) | |||||
| : value (0) | |||||
| { | |||||
| int i = 0; | |||||
| *this = RelativeCoordinateHelpers::readNextCoordinate (s, i, isHorizontal); | |||||
| } | |||||
| RelativeCoordinate::~RelativeCoordinate() | RelativeCoordinate::~RelativeCoordinate() | ||||
| { | { | ||||
| } | } | ||||
| bool RelativeCoordinate::operator== (const RelativeCoordinate& other) const throw() | |||||
| { | |||||
| return value == other.value && anchor1 == other.anchor1 && anchor2 == other.anchor2; | |||||
| } | |||||
| bool RelativeCoordinate::operator!= (const RelativeCoordinate& other) const throw() | |||||
| { | |||||
| return ! operator== (other); | |||||
| } | |||||
| //============================================================================== | //============================================================================== | ||||
| const RelativeCoordinate RelativeCoordinate::getAnchorCoordinate1() const | const RelativeCoordinate RelativeCoordinate::getAnchorCoordinate1() const | ||||
| { | { | ||||
| @@ -186,7 +292,7 @@ const RelativeCoordinate RelativeCoordinate::getAnchorCoordinate2() const | |||||
| return RelativeCoordinate (0.0, anchor2); | return RelativeCoordinate (0.0, anchor2); | ||||
| } | } | ||||
| double RelativeCoordinate::resolveAnchor (const String& anchorName, const NamedCoordinateFinder& nameFinder, int recursionCounter) | |||||
| double RelativeCoordinate::resolveAnchor (const String& anchorName, const NamedCoordinateFinder* nameFinder, int recursionCounter) | |||||
| { | { | ||||
| if (RelativeCoordinateHelpers::isOrigin (anchorName)) | if (RelativeCoordinateHelpers::isOrigin (anchorName)) | ||||
| return 0.0; | return 0.0; | ||||
| @@ -194,7 +300,7 @@ double RelativeCoordinate::resolveAnchor (const String& anchorName, const NamedC | |||||
| return RelativeCoordinateHelpers::findCoordinate (anchorName, nameFinder).resolve (nameFinder, recursionCounter + 1); | return RelativeCoordinateHelpers::findCoordinate (anchorName, nameFinder).resolve (nameFinder, recursionCounter + 1); | ||||
| } | } | ||||
| double RelativeCoordinate::resolve (const NamedCoordinateFinder& nameFinder, int recursionCounter) const | |||||
| double RelativeCoordinate::resolve (const NamedCoordinateFinder* nameFinder, int recursionCounter) const | |||||
| { | { | ||||
| if (recursionCounter > 150) | if (recursionCounter > 150) | ||||
| { | { | ||||
| @@ -208,7 +314,7 @@ double RelativeCoordinate::resolve (const NamedCoordinateFinder& nameFinder, int | |||||
| : pos1 + value; | : pos1 + value; | ||||
| } | } | ||||
| double RelativeCoordinate::resolve (const NamedCoordinateFinder& nameFinder) const | |||||
| double RelativeCoordinate::resolve (const NamedCoordinateFinder* nameFinder) const | |||||
| { | { | ||||
| try | try | ||||
| { | { | ||||
| @@ -220,7 +326,7 @@ double RelativeCoordinate::resolve (const NamedCoordinateFinder& nameFinder) con | |||||
| return 0.0; | return 0.0; | ||||
| } | } | ||||
| bool RelativeCoordinate::isRecursive (const NamedCoordinateFinder& nameFinder) const | |||||
| bool RelativeCoordinate::isRecursive (const NamedCoordinateFinder* nameFinder) const | |||||
| { | { | ||||
| try | try | ||||
| { | { | ||||
| @@ -234,7 +340,7 @@ bool RelativeCoordinate::isRecursive (const NamedCoordinateFinder& nameFinder) c | |||||
| return false; | return false; | ||||
| } | } | ||||
| void RelativeCoordinate::moveToAbsolute (double newPos, const NamedCoordinateFinder& nameFinder) | |||||
| void RelativeCoordinate::moveToAbsolute (double newPos, const NamedCoordinateFinder* nameFinder) | |||||
| { | { | ||||
| try | try | ||||
| { | { | ||||
| @@ -256,7 +362,7 @@ void RelativeCoordinate::moveToAbsolute (double newPos, const NamedCoordinateFin | |||||
| {} | {} | ||||
| } | } | ||||
| void RelativeCoordinate::toggleProportionality (const NamedCoordinateFinder& nameFinder, bool isHorizontal) | |||||
| void RelativeCoordinate::toggleProportionality (const NamedCoordinateFinder* nameFinder, bool isHorizontal) | |||||
| { | { | ||||
| const double oldValue = resolve (nameFinder); | const double oldValue = resolve (nameFinder); | ||||
| @@ -267,8 +373,7 @@ void RelativeCoordinate::toggleProportionality (const NamedCoordinateFinder& nam | |||||
| moveToAbsolute (oldValue, nameFinder); | moveToAbsolute (oldValue, nameFinder); | ||||
| } | } | ||||
| //============================================================================== | |||||
| bool RelativeCoordinate::references (const String& coordName, const NamedCoordinateFinder& nameFinder) const | |||||
| bool RelativeCoordinate::references (const String& coordName, const NamedCoordinateFinder* nameFinder) const | |||||
| { | { | ||||
| using namespace RelativeCoordinateHelpers; | using namespace RelativeCoordinateHelpers; | ||||
| @@ -281,65 +386,12 @@ bool RelativeCoordinate::references (const String& coordName, const NamedCoordin | |||||
| || (isProportional() && findCoordinate (anchor2, nameFinder).references (coordName, nameFinder)); | || (isProportional() && findCoordinate (anchor2, nameFinder).references (coordName, nameFinder)); | ||||
| } | } | ||||
| //============================================================================== | |||||
| RelativeCoordinate::RelativeCoordinate (const String& s, bool isHorizontal) | |||||
| : value (0) | |||||
| bool RelativeCoordinate::isDynamic() const | |||||
| { | { | ||||
| using namespace RelativeCoordinateHelpers; | |||||
| int i = 0; | |||||
| anchor1 = readAnchorName (s, i); | |||||
| if (anchor1.isNotEmpty()) | |||||
| { | |||||
| skipWhitespace (s, i); | |||||
| if (s[i] == '+') | |||||
| value = readNumber (s, ++i); | |||||
| else if (s[i] == '-') | |||||
| value = -readNumber (s, ++i); | |||||
| } | |||||
| else | |||||
| { | |||||
| anchor1 = getOriginAnchorName (isHorizontal); | |||||
| value = readNumber (s, i); | |||||
| skipWhitespace (s, i); | |||||
| if (s[i] == '%') | |||||
| { | |||||
| value /= 100.0; | |||||
| skipWhitespace (s, ++i); | |||||
| if (s[i] == '*') | |||||
| { | |||||
| anchor1 = readAnchorName (s, ++i); | |||||
| if (anchor1.isEmpty()) | |||||
| anchor1 = getOriginAnchorName (isHorizontal); | |||||
| skipWhitespace (s, i); | |||||
| if (s[i] == '-' && s[i + 1] == '>') | |||||
| { | |||||
| i += 2; | |||||
| anchor2 = readAnchorName (s, i); | |||||
| } | |||||
| else | |||||
| { | |||||
| anchor2 = anchor1; | |||||
| anchor1 = getOriginAnchorName (isHorizontal); | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| anchor1 = getOriginAnchorName (isHorizontal); | |||||
| anchor2 = getExtentAnchorName (isHorizontal); | |||||
| } | |||||
| } | |||||
| } | |||||
| return anchor2.isNotEmpty() || ! RelativeCoordinateHelpers::isOrigin (anchor1); | |||||
| } | } | ||||
| //============================================================================== | |||||
| const String RelativeCoordinate::toString() const | const String RelativeCoordinate::toString() const | ||||
| { | { | ||||
| using namespace RelativeCoordinateHelpers; | using namespace RelativeCoordinateHelpers; | ||||
| @@ -383,7 +435,7 @@ void RelativeCoordinate::setEditableNumber (const double newValue) | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| void RelativeCoordinate::changeAnchor1 (const String& newAnchorName, const NamedCoordinateFinder& nameFinder) | |||||
| void RelativeCoordinate::changeAnchor1 (const String& newAnchorName, const NamedCoordinateFinder* nameFinder) | |||||
| { | { | ||||
| jassert (newAnchorName.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_.")); | jassert (newAnchorName.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_.")); | ||||
| @@ -392,7 +444,7 @@ void RelativeCoordinate::changeAnchor1 (const String& newAnchorName, const Named | |||||
| moveToAbsolute (oldValue, nameFinder); | moveToAbsolute (oldValue, nameFinder); | ||||
| } | } | ||||
| void RelativeCoordinate::changeAnchor2 (const String& newAnchorName, const NamedCoordinateFinder& nameFinder) | |||||
| void RelativeCoordinate::changeAnchor2 (const String& newAnchorName, const NamedCoordinateFinder* nameFinder) | |||||
| { | { | ||||
| jassert (isProportional()); | jassert (isProportional()); | ||||
| jassert (newAnchorName.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_.")); | jassert (newAnchorName.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_.")); | ||||
| @@ -402,7 +454,7 @@ void RelativeCoordinate::changeAnchor2 (const String& newAnchorName, const Named | |||||
| moveToAbsolute (oldValue, nameFinder); | moveToAbsolute (oldValue, nameFinder); | ||||
| } | } | ||||
| void RelativeCoordinate::renameAnchorIfUsed (const String& oldName, const String& newName, const NamedCoordinateFinder& nameFinder) | |||||
| void RelativeCoordinate::renameAnchorIfUsed (const String& oldName, const String& newName, const NamedCoordinateFinder* nameFinder) | |||||
| { | { | ||||
| using namespace RelativeCoordinateHelpers; | using namespace RelativeCoordinateHelpers; | ||||
| jassert (oldName.isNotEmpty()); | jassert (oldName.isNotEmpty()); | ||||
| @@ -439,21 +491,36 @@ RelativePoint::RelativePoint (const Point<float>& absolutePoint) | |||||
| { | { | ||||
| } | } | ||||
| RelativePoint::RelativePoint (const String& stringVersion) | |||||
| RelativePoint::RelativePoint (const RelativeCoordinate& x_, const RelativeCoordinate& y_) | |||||
| : x (x_), y (y_) | |||||
| { | { | ||||
| const int separator = stringVersion.indexOfChar (','); | |||||
| } | |||||
| x = RelativeCoordinate (stringVersion.substring (0, separator), true); | |||||
| y = RelativeCoordinate (stringVersion.substring (separator + 1), false); | |||||
| RelativePoint::RelativePoint (const String& s) | |||||
| { | |||||
| int i = 0; | |||||
| x = RelativeCoordinateHelpers::readNextCoordinate (s, i, true); | |||||
| RelativeCoordinateHelpers::skipComma (s, i); | |||||
| y = RelativeCoordinateHelpers::readNextCoordinate (s, i, false); | |||||
| } | } | ||||
| const Point<float> RelativePoint::resolve (const RelativeCoordinate::NamedCoordinateFinder& nameFinder) const | |||||
| bool RelativePoint::operator== (const RelativePoint& other) const throw() | |||||
| { | |||||
| return x == other.x && y == other.y; | |||||
| } | |||||
| bool RelativePoint::operator!= (const RelativePoint& other) const throw() | |||||
| { | |||||
| return ! operator== (other); | |||||
| } | |||||
| const Point<float> RelativePoint::resolve (const RelativeCoordinate::NamedCoordinateFinder* nameFinder) const | |||||
| { | { | ||||
| return Point<float> ((float) x.resolve (nameFinder), | return Point<float> ((float) x.resolve (nameFinder), | ||||
| (float) y.resolve (nameFinder)); | (float) y.resolve (nameFinder)); | ||||
| } | } | ||||
| void RelativePoint::moveToAbsolute (const Point<float>& newPos, const RelativeCoordinate::NamedCoordinateFinder& nameFinder) | |||||
| void RelativePoint::moveToAbsolute (const Point<float>& newPos, const RelativeCoordinate::NamedCoordinateFinder* nameFinder) | |||||
| { | { | ||||
| x.moveToAbsolute (newPos.getX(), nameFinder); | x.moveToAbsolute (newPos.getX(), nameFinder); | ||||
| y.moveToAbsolute (newPos.getY(), nameFinder); | y.moveToAbsolute (newPos.getY(), nameFinder); | ||||
| @@ -464,12 +531,17 @@ const String RelativePoint::toString() const | |||||
| return x.toString() + ", " + y.toString(); | return x.toString() + ", " + y.toString(); | ||||
| } | } | ||||
| void RelativePoint::renameAnchorIfUsed (const String& oldName, const String& newName, const RelativeCoordinate::NamedCoordinateFinder& nameFinder) | |||||
| void RelativePoint::renameAnchorIfUsed (const String& oldName, const String& newName, const RelativeCoordinate::NamedCoordinateFinder* nameFinder) | |||||
| { | { | ||||
| x.renameAnchorIfUsed (oldName, newName, nameFinder); | x.renameAnchorIfUsed (oldName, newName, nameFinder); | ||||
| y.renameAnchorIfUsed (oldName, newName, nameFinder); | y.renameAnchorIfUsed (oldName, newName, nameFinder); | ||||
| } | } | ||||
| bool RelativePoint::isDynamic() const | |||||
| { | |||||
| return x.isDynamic() || y.isDynamic(); | |||||
| } | |||||
| //============================================================================== | //============================================================================== | ||||
| RelativeRectangle::RelativeRectangle() | RelativeRectangle::RelativeRectangle() | ||||
| @@ -484,18 +556,29 @@ RelativeRectangle::RelativeRectangle (const Rectangle<float>& rect, const String | |||||
| { | { | ||||
| } | } | ||||
| RelativeRectangle::RelativeRectangle (const String& stringVersion) | |||||
| RelativeRectangle::RelativeRectangle (const String& s) | |||||
| { | { | ||||
| StringArray tokens; | |||||
| tokens.addTokens (stringVersion, ",", String::empty); | |||||
| int i = 0; | |||||
| left = RelativeCoordinateHelpers::readNextCoordinate (s, i, true); | |||||
| RelativeCoordinateHelpers::skipComma (s, i); | |||||
| top = RelativeCoordinateHelpers::readNextCoordinate (s, i, false); | |||||
| RelativeCoordinateHelpers::skipComma (s, i); | |||||
| right = RelativeCoordinateHelpers::readNextCoordinate (s, i, true); | |||||
| RelativeCoordinateHelpers::skipComma (s, i); | |||||
| bottom = RelativeCoordinateHelpers::readNextCoordinate (s, i, false); | |||||
| } | |||||
| left = RelativeCoordinate (tokens [0], true); | |||||
| top = RelativeCoordinate (tokens [1], false); | |||||
| right = RelativeCoordinate (tokens [2], true); | |||||
| bottom = RelativeCoordinate (tokens [3], false); | |||||
| bool RelativeRectangle::operator== (const RelativeRectangle& other) const throw() | |||||
| { | |||||
| return left == other.left && top == other.top && right == other.right && bottom == other.bottom; | |||||
| } | } | ||||
| const Rectangle<float> RelativeRectangle::resolve (const RelativeCoordinate::NamedCoordinateFinder& nameFinder) const | |||||
| bool RelativeRectangle::operator!= (const RelativeRectangle& other) const throw() | |||||
| { | |||||
| return ! operator== (other); | |||||
| } | |||||
| const Rectangle<float> RelativeRectangle::resolve (const RelativeCoordinate::NamedCoordinateFinder* nameFinder) const | |||||
| { | { | ||||
| const double l = left.resolve (nameFinder); | const double l = left.resolve (nameFinder); | ||||
| const double r = right.resolve (nameFinder); | const double r = right.resolve (nameFinder); | ||||
| @@ -505,7 +588,7 @@ const Rectangle<float> RelativeRectangle::resolve (const RelativeCoordinate::Nam | |||||
| return Rectangle<float> ((float) l, (float) t, (float) (r - l), (float) (b - t)); | return Rectangle<float> ((float) l, (float) t, (float) (r - l), (float) (b - t)); | ||||
| } | } | ||||
| void RelativeRectangle::moveToAbsolute (const Rectangle<float>& newPos, const RelativeCoordinate::NamedCoordinateFinder& nameFinder) | |||||
| void RelativeRectangle::moveToAbsolute (const Rectangle<float>& newPos, const RelativeCoordinate::NamedCoordinateFinder* nameFinder) | |||||
| { | { | ||||
| left.moveToAbsolute (newPos.getX(), nameFinder); | left.moveToAbsolute (newPos.getX(), nameFinder); | ||||
| right.moveToAbsolute (newPos.getRight(), nameFinder); | right.moveToAbsolute (newPos.getRight(), nameFinder); | ||||
| @@ -519,7 +602,7 @@ const String RelativeRectangle::toString() const | |||||
| } | } | ||||
| void RelativeRectangle::renameAnchorIfUsed (const String& oldName, const String& newName, | void RelativeRectangle::renameAnchorIfUsed (const String& oldName, const String& newName, | ||||
| const RelativeCoordinate::NamedCoordinateFinder& nameFinder) | |||||
| const RelativeCoordinate::NamedCoordinateFinder* nameFinder) | |||||
| { | { | ||||
| left.renameAnchorIfUsed (oldName, newName, nameFinder); | left.renameAnchorIfUsed (oldName, newName, nameFinder); | ||||
| right.renameAnchorIfUsed (oldName, newName, nameFinder); | right.renameAnchorIfUsed (oldName, newName, nameFinder); | ||||
| @@ -528,4 +611,264 @@ void RelativeRectangle::renameAnchorIfUsed (const String& oldName, const String& | |||||
| } | } | ||||
| //============================================================================== | |||||
| RelativePointPath::RelativePointPath() | |||||
| : usesNonZeroWinding (true), | |||||
| containsDynamicPoints (false) | |||||
| { | |||||
| } | |||||
| RelativePointPath::RelativePointPath (const RelativePointPath& other) | |||||
| : usesNonZeroWinding (true), | |||||
| containsDynamicPoints (false) | |||||
| { | |||||
| parseString (other.toString()); | |||||
| } | |||||
| RelativePointPath::RelativePointPath (const String& s) | |||||
| : usesNonZeroWinding (true), | |||||
| containsDynamicPoints (false) | |||||
| { | |||||
| parseString (s); | |||||
| } | |||||
| void RelativePointPath::parseString (const String& s) | |||||
| { | |||||
| int i = 0; | |||||
| juce_wchar marker = 'm'; | |||||
| int numValues = 2; | |||||
| RelativePoint points [3]; | |||||
| for (;;) | |||||
| { | |||||
| RelativeCoordinateHelpers::skipWhitespace (s, i); | |||||
| const juce_wchar firstChar = s[i]; | |||||
| if (firstChar == 0) | |||||
| break; | |||||
| const juce_wchar secondChar = s[i + 1]; | |||||
| if (secondChar == 0 || CharacterFunctions::isWhitespace (secondChar)) | |||||
| { | |||||
| if (firstChar == 'm' || firstChar == 'l') | |||||
| { | |||||
| ++i; | |||||
| marker = firstChar; | |||||
| numValues = 1; | |||||
| } | |||||
| else if (firstChar == 'q') | |||||
| { | |||||
| ++i; | |||||
| marker = firstChar; | |||||
| numValues = 2; | |||||
| } | |||||
| else if (firstChar == 'c') | |||||
| { | |||||
| ++i; | |||||
| marker = firstChar; | |||||
| numValues = 3; | |||||
| } | |||||
| else if (firstChar == 'z') | |||||
| { | |||||
| ++i; | |||||
| marker = 'm'; | |||||
| numValues = 2; | |||||
| elements.add (new CloseSubPath()); | |||||
| continue; | |||||
| } | |||||
| else if (firstChar == 'a') | |||||
| { | |||||
| ++i; | |||||
| usesNonZeroWinding = false; | |||||
| continue; | |||||
| } | |||||
| } | |||||
| if (firstChar == '#') | |||||
| ++i; | |||||
| for (int j = 0; j < numValues; ++j) | |||||
| { | |||||
| const RelativeCoordinate x (RelativeCoordinateHelpers::readNextCoordinate (s, i, true)); | |||||
| const RelativeCoordinate y (RelativeCoordinateHelpers::readNextCoordinate (s, i, false)); | |||||
| points[j] = RelativePoint (x, y); | |||||
| containsDynamicPoints = containsDynamicPoints || points[j].isDynamic(); | |||||
| } | |||||
| switch (marker) | |||||
| { | |||||
| case 'm': elements.add (new StartSubPath (points[0])); break; | |||||
| case 'l': elements.add (new LineTo (points[0])); break; | |||||
| case 'q': elements.add (new QuadraticTo (points[0], points[1])); break; | |||||
| case 'c': elements.add (new CubicTo (points[0], points[1], points[2])); break; | |||||
| default: jassertfalse; break; // illegal string format? | |||||
| } | |||||
| } | |||||
| } | |||||
| RelativePointPath::~RelativePointPath() | |||||
| { | |||||
| } | |||||
| void RelativePointPath::swapWith (RelativePointPath& other) throw() | |||||
| { | |||||
| elements.swapWithArray (other.elements); | |||||
| swapVariables (usesNonZeroWinding, other.usesNonZeroWinding); | |||||
| } | |||||
| void RelativePointPath::createPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) | |||||
| { | |||||
| for (int i = 0; i < elements.size(); ++i) | |||||
| elements.getUnchecked(i)->addToPath (path, coordFinder); | |||||
| } | |||||
| bool RelativePointPath::containsAnyDynamicPoints() const | |||||
| { | |||||
| return containsDynamicPoints; | |||||
| } | |||||
| const String RelativePointPath::toString() const | |||||
| { | |||||
| ElementType lastType = nullElement; | |||||
| MemoryOutputStream out; | |||||
| if (! usesNonZeroWinding) | |||||
| out << 'a'; | |||||
| for (int i = 0; i < elements.size(); ++i) | |||||
| { | |||||
| if (out.getDataSize() > 0) | |||||
| out << ' '; | |||||
| const ElementBase* const e = elements.getUnchecked(i); | |||||
| e->write (out, lastType); | |||||
| lastType = e->type; | |||||
| } | |||||
| return out.toUTF8(); | |||||
| } | |||||
| //============================================================================== | |||||
| RelativePointPath::ElementBase::ElementBase (const ElementType type_) : type (type_) | |||||
| { | |||||
| } | |||||
| //============================================================================== | |||||
| RelativePointPath::StartSubPath::StartSubPath (const RelativePoint& pos) | |||||
| : ElementBase (startSubPathElement), startPos (pos) | |||||
| { | |||||
| } | |||||
| void RelativePointPath::StartSubPath::write (OutputStream& out, ElementType lastTypeWritten) const | |||||
| { | |||||
| const String p (startPos.toString()); | |||||
| if (lastTypeWritten != startSubPathElement) | |||||
| out << "m "; | |||||
| else if (RelativeCoordinateHelpers::couldBeMistakenForPathCommand (p)) | |||||
| out << '#'; | |||||
| out << p; | |||||
| } | |||||
| void RelativePointPath::StartSubPath::addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const | |||||
| { | |||||
| const Point<float> p (startPos.resolve (coordFinder)); | |||||
| path.startNewSubPath (p.getX(), p.getY()); | |||||
| } | |||||
| //============================================================================== | |||||
| RelativePointPath::CloseSubPath::CloseSubPath() | |||||
| : ElementBase (closeSubPathElement) | |||||
| { | |||||
| } | |||||
| void RelativePointPath::CloseSubPath::write (OutputStream& out, ElementType lastTypeWritten) const | |||||
| { | |||||
| if (lastTypeWritten != closeSubPathElement) | |||||
| out << 'z'; | |||||
| } | |||||
| void RelativePointPath::CloseSubPath::addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder*) const | |||||
| { | |||||
| path.closeSubPath(); | |||||
| } | |||||
| //============================================================================== | |||||
| RelativePointPath::LineTo::LineTo (const RelativePoint& endPoint_) | |||||
| : ElementBase (lineToElement), endPoint (endPoint_) | |||||
| { | |||||
| } | |||||
| void RelativePointPath::LineTo::write (OutputStream& out, ElementType lastTypeWritten) const | |||||
| { | |||||
| const String p (endPoint.toString()); | |||||
| if (lastTypeWritten != lineToElement) | |||||
| out << "l "; | |||||
| else if (RelativeCoordinateHelpers::couldBeMistakenForPathCommand (p)) | |||||
| out << '#'; | |||||
| out << p; | |||||
| } | |||||
| void RelativePointPath::LineTo::addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const | |||||
| { | |||||
| const Point<float> p (endPoint.resolve (coordFinder)); | |||||
| path.lineTo (p.getX(), p.getY()); | |||||
| } | |||||
| //============================================================================== | |||||
| RelativePointPath::QuadraticTo::QuadraticTo (const RelativePoint& controlPoint_, const RelativePoint& endPoint_) | |||||
| : ElementBase (quadraticToElement), controlPoint (controlPoint_), endPoint (endPoint_) | |||||
| { | |||||
| } | |||||
| void RelativePointPath::QuadraticTo::write (OutputStream& out, ElementType lastTypeWritten) const | |||||
| { | |||||
| const String p1 (controlPoint.toString()); | |||||
| if (lastTypeWritten != quadraticToElement) | |||||
| out << "q "; | |||||
| else if (RelativeCoordinateHelpers::couldBeMistakenForPathCommand (p1)) | |||||
| out << '#'; | |||||
| out << p1 << ' ' << endPoint.toString(); | |||||
| } | |||||
| void RelativePointPath::QuadraticTo::addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const | |||||
| { | |||||
| const Point<float> p1 (controlPoint.resolve (coordFinder)); | |||||
| const Point<float> p2 (endPoint.resolve (coordFinder)); | |||||
| path.quadraticTo (p1.getX(), p1.getY(), p2.getX(), p2.getY()); | |||||
| } | |||||
| //============================================================================== | |||||
| RelativePointPath::CubicTo::CubicTo (const RelativePoint& controlPoint1_, const RelativePoint& controlPoint2_, const RelativePoint& endPoint_) | |||||
| : ElementBase (cubicToElement), controlPoint1 (controlPoint1_), controlPoint2 (controlPoint2_), endPoint (endPoint_) | |||||
| { | |||||
| } | |||||
| void RelativePointPath::CubicTo::write (OutputStream& out, ElementType lastTypeWritten) const | |||||
| { | |||||
| const String p1 (controlPoint1.toString()); | |||||
| if (lastTypeWritten != cubicToElement) | |||||
| out << "c "; | |||||
| else if (RelativeCoordinateHelpers::couldBeMistakenForPathCommand (p1)) | |||||
| out << '#'; | |||||
| out << p1 << ' ' << controlPoint2.toString() << ' ' << endPoint.toString(); | |||||
| } | |||||
| void RelativePointPath::CubicTo::addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const | |||||
| { | |||||
| const Point<float> p1 (controlPoint1.resolve (coordFinder)); | |||||
| const Point<float> p2 (controlPoint2.resolve (coordFinder)); | |||||
| const Point<float> p3 (endPoint.resolve (coordFinder)); | |||||
| path.cubicTo (p1.getX(), p1.getY(), p2.getX(), p2.getY(), p3.getX(), p3.getY()); | |||||
| } | |||||
| END_JUCE_NAMESPACE | END_JUCE_NAMESPACE | ||||
| @@ -26,7 +26,9 @@ | |||||
| #ifndef __JUCE_RELATIVECOORDINATE_JUCEHEADER__ | #ifndef __JUCE_RELATIVECOORDINATE_JUCEHEADER__ | ||||
| #define __JUCE_RELATIVECOORDINATE_JUCEHEADER__ | #define __JUCE_RELATIVECOORDINATE_JUCEHEADER__ | ||||
| #include "juce_Path.h" | |||||
| #include "juce_Rectangle.h" | #include "juce_Rectangle.h" | ||||
| #include "../../../containers/juce_OwnedArray.h" | |||||
| //============================================================================== | //============================================================================== | ||||
| @@ -101,8 +103,8 @@ public: | |||||
| e.g. "marker1", or it can be a two-part name in the form "objectName.edge". For example "parent.left" is | e.g. "marker1", or it can be a two-part name in the form "objectName.edge". For example "parent.left" is | ||||
| the origin, or "myComponent.top" is the top edge of a component called "myComponent". The exact names that | the origin, or "myComponent.top" is the top edge of a component called "myComponent". The exact names that | ||||
| will be recognised are dependent on the NamedCoordinateFinder that you provide for looking them up, but | will be recognised are dependent on the NamedCoordinateFinder that you provide for looking them up, but | ||||
| "parent.left", "parent.top", "parent.right" and "parent.bottom" are always available, representing the | |||||
| extents of the target coordinate space. | |||||
| "parent.left" and "parent.top" are always available, meaning the origin. "parent.right" and "parent.bottom" | |||||
| may also be available if the coordinate space has a fixed size. | |||||
| @param stringVersion the string to parse | @param stringVersion the string to parse | ||||
| @param isHorizontal this must be true if this is an X coordinate, or false if it's on the Y axis. | @param isHorizontal this must be true if this is an X coordinate, or false if it's on the Y axis. | ||||
| @@ -114,6 +116,9 @@ public: | |||||
| /** Destructor. */ | /** Destructor. */ | ||||
| ~RelativeCoordinate(); | ~RelativeCoordinate(); | ||||
| bool operator== (const RelativeCoordinate& other) const throw(); | |||||
| bool operator!= (const RelativeCoordinate& other) const throw(); | |||||
| //============================================================================== | //============================================================================== | ||||
| /** | /** | ||||
| Provides an interface for looking up the position of a named anchor when resolving a RelativeCoordinate. | Provides an interface for looking up the position of a named anchor when resolving a RelativeCoordinate. | ||||
| @@ -145,15 +150,18 @@ public: | |||||
| You'll need to provide a suitable NamedCoordinateFinder for looking up any coordinates that may | You'll need to provide a suitable NamedCoordinateFinder for looking up any coordinates that may | ||||
| be needed to calculate the result. | be needed to calculate the result. | ||||
| */ | */ | ||||
| double resolve (const NamedCoordinateFinder& nameFinder) const; | |||||
| double resolve (const NamedCoordinateFinder* nameFinder) const; | |||||
| /** Returns true if this coordinate uses the specified coord name at any level in its evaluation. | /** Returns true if this coordinate uses the specified coord name at any level in its evaluation. | ||||
| This will recursively check any coordinates upon which this one depends. | This will recursively check any coordinates upon which this one depends. | ||||
| */ | */ | ||||
| bool references (const String& coordName, const NamedCoordinateFinder& nameFinder) const; | |||||
| bool references (const String& coordName, const NamedCoordinateFinder* nameFinder) const; | |||||
| /** Returns true if there's a recursive loop when trying to resolve this coordinate's position. */ | /** Returns true if there's a recursive loop when trying to resolve this coordinate's position. */ | ||||
| bool isRecursive (const NamedCoordinateFinder& nameFinder) const; | |||||
| bool isRecursive (const NamedCoordinateFinder* nameFinder) const; | |||||
| /** Returns true if this coordinate depends on any other coordinates for its position. */ | |||||
| bool isDynamic() const; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Changes the value of this coord to make it resolve to the specified position. | /** Changes the value of this coord to make it resolve to the specified position. | ||||
| @@ -162,7 +170,7 @@ public: | |||||
| or relative position to whatever value is necessary to make its resultant position | or relative position to whatever value is necessary to make its resultant position | ||||
| match the position that is provided. | match the position that is provided. | ||||
| */ | */ | ||||
| void moveToAbsolute (double absoluteTargetPosition, const NamedCoordinateFinder& nameFinder); | |||||
| void moveToAbsolute (double absoluteTargetPosition, const NamedCoordinateFinder* nameFinder); | |||||
| /** Returns true if the coordinate is calculated as a proportion of the distance between two other points. | /** Returns true if the coordinate is calculated as a proportion of the distance between two other points. | ||||
| @see toggleProportionality | @see toggleProportionality | ||||
| @@ -173,7 +181,7 @@ public: | |||||
| Note that calling this will reset the names of any anchor points, and just make the | Note that calling this will reset the names of any anchor points, and just make the | ||||
| coordinate relative to the parent origin and parent size. | coordinate relative to the parent origin and parent size. | ||||
| */ | */ | ||||
| void toggleProportionality (const NamedCoordinateFinder& nameFinder, bool isHorizontal); | |||||
| void toggleProportionality (const NamedCoordinateFinder* nameFinder, bool isHorizontal); | |||||
| /** Returns a value that can be edited to set this coordinate's position. | /** Returns a value that can be edited to set this coordinate's position. | ||||
| The meaning of this number depends on the coordinate's mode. If the coordinate is | The meaning of this number depends on the coordinate's mode. If the coordinate is | ||||
| @@ -212,12 +220,12 @@ public: | |||||
| /** Changes the first anchor point, keeping the resultant position of this coordinate in | /** Changes the first anchor point, keeping the resultant position of this coordinate in | ||||
| the same place it was previously. | the same place it was previously. | ||||
| */ | */ | ||||
| void changeAnchor1 (const String& newAnchor, const NamedCoordinateFinder& nameFinder); | |||||
| void changeAnchor1 (const String& newAnchor, const NamedCoordinateFinder* nameFinder); | |||||
| /** Changes the second anchor point, keeping the resultant position of this coordinate in | /** Changes the second anchor point, keeping the resultant position of this coordinate in | ||||
| the same place it was previously. | the same place it was previously. | ||||
| */ | */ | ||||
| void changeAnchor2 (const String& newAnchor, const NamedCoordinateFinder& nameFinder); | |||||
| void changeAnchor2 (const String& newAnchor, const NamedCoordinateFinder* nameFinder); | |||||
| /** Tells the coordinate that an object is changing its name or being deleted. | /** Tells the coordinate that an object is changing its name or being deleted. | ||||
| @@ -227,7 +235,7 @@ public: | |||||
| instead. | instead. | ||||
| */ | */ | ||||
| void renameAnchorIfUsed (const String& oldName, const String& newName, | void renameAnchorIfUsed (const String& oldName, const String& newName, | ||||
| const NamedCoordinateFinder& nameFinder); | |||||
| const NamedCoordinateFinder* nameFinder); | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Returns a string which represents this coordinate. | /** Returns a string which represents this coordinate. | ||||
| @@ -261,8 +269,8 @@ private: | |||||
| String anchor1, anchor2; | String anchor1, anchor2; | ||||
| double value; | double value; | ||||
| double resolve (const NamedCoordinateFinder& nameFinder, int recursionCounter) const; | |||||
| static double resolveAnchor (const String& anchorName, const NamedCoordinateFinder& nameFinder, int recursionCounter); | |||||
| double resolve (const NamedCoordinateFinder* nameFinder, int recursionCounter) const; | |||||
| static double resolveAnchor (const String& anchorName, const NamedCoordinateFinder* nameFinder, int recursionCounter); | |||||
| }; | }; | ||||
| @@ -281,19 +289,25 @@ public: | |||||
| /** Creates an absolute point, relative to the origin. */ | /** Creates an absolute point, relative to the origin. */ | ||||
| RelativePoint (const Point<float>& absolutePoint); | RelativePoint (const Point<float>& absolutePoint); | ||||
| /** Creates an absolute point from two coordinates. */ | |||||
| RelativePoint (const RelativeCoordinate& x, const RelativeCoordinate& y); | |||||
| /** Creates a point from a stringified representation. | /** Creates a point from a stringified representation. | ||||
| The string must contain a pair of coordinates, separated by a comma. The syntax for the coordinate | |||||
| The string must contain a pair of coordinates, separated by space or a comma. The syntax for the coordinate | |||||
| strings is explained in the RelativeCoordinate class. | strings is explained in the RelativeCoordinate class. | ||||
| @see toString | @see toString | ||||
| */ | */ | ||||
| RelativePoint (const String& stringVersion); | RelativePoint (const String& stringVersion); | ||||
| bool operator== (const RelativePoint& other) const throw(); | |||||
| bool operator!= (const RelativePoint& other) const throw(); | |||||
| /** Calculates the absolute position of this point. | /** Calculates the absolute position of this point. | ||||
| You'll need to provide a suitable NamedCoordinateFinder for looking up any coordinates that may | You'll need to provide a suitable NamedCoordinateFinder for looking up any coordinates that may | ||||
| be needed to calculate the result. | be needed to calculate the result. | ||||
| */ | */ | ||||
| const Point<float> resolve (const RelativeCoordinate::NamedCoordinateFinder& nameFinder) const; | |||||
| const Point<float> resolve (const RelativeCoordinate::NamedCoordinateFinder* nameFinder) const; | |||||
| /** Changes the values of this point's coordinates to make it resolve to the specified position. | /** Changes the values of this point's coordinates to make it resolve to the specified position. | ||||
| @@ -301,7 +315,7 @@ public: | |||||
| or relative positions to whatever values are necessary to make the resultant position | or relative positions to whatever values are necessary to make the resultant position | ||||
| match the position that is provided. | match the position that is provided. | ||||
| */ | */ | ||||
| void moveToAbsolute (const Point<float>& newPos, const RelativeCoordinate::NamedCoordinateFinder& nameFinder); | |||||
| void moveToAbsolute (const Point<float>& newPos, const RelativeCoordinate::NamedCoordinateFinder* nameFinder); | |||||
| /** Returns a string which represents this point. | /** Returns a string which represents this point. | ||||
| This returns a comma-separated pair of coordinates. For details of the string syntax used by the | This returns a comma-separated pair of coordinates. For details of the string syntax used by the | ||||
| @@ -314,7 +328,10 @@ public: | |||||
| This calls RelativeCoordinate::renameAnchorIfUsed() on its X and Y coordinates. | This calls RelativeCoordinate::renameAnchorIfUsed() on its X and Y coordinates. | ||||
| */ | */ | ||||
| void renameAnchorIfUsed (const String& oldName, const String& newName, | void renameAnchorIfUsed (const String& oldName, const String& newName, | ||||
| const RelativeCoordinate::NamedCoordinateFinder& nameFinder); | |||||
| const RelativeCoordinate::NamedCoordinateFinder* nameFinder); | |||||
| /** Returns true if this point depends on any other coordinates for its position. */ | |||||
| bool isDynamic() const; | |||||
| // The actual X and Y coords... | // The actual X and Y coords... | ||||
| RelativeCoordinate x, y; | RelativeCoordinate x, y; | ||||
| @@ -347,13 +364,16 @@ public: | |||||
| */ | */ | ||||
| explicit RelativeRectangle (const String& stringVersion); | explicit RelativeRectangle (const String& stringVersion); | ||||
| bool operator== (const RelativeRectangle& other) const throw(); | |||||
| bool operator!= (const RelativeRectangle& other) const throw(); | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Calculates the absolute position of this rectangle. | /** Calculates the absolute position of this rectangle. | ||||
| You'll need to provide a suitable NamedCoordinateFinder for looking up any coordinates that may | You'll need to provide a suitable NamedCoordinateFinder for looking up any coordinates that may | ||||
| be needed to calculate the result. | be needed to calculate the result. | ||||
| */ | */ | ||||
| const Rectangle<float> resolve (const RelativeCoordinate::NamedCoordinateFinder& nameFinder) const; | |||||
| const Rectangle<float> resolve (const RelativeCoordinate::NamedCoordinateFinder* nameFinder) const; | |||||
| /** Changes the values of this rectangle's coordinates to make it resolve to the specified position. | /** Changes the values of this rectangle's coordinates to make it resolve to the specified position. | ||||
| @@ -361,7 +381,7 @@ public: | |||||
| or relative positions to whatever values are necessary to make the resultant position | or relative positions to whatever values are necessary to make the resultant position | ||||
| match the position that is provided. | match the position that is provided. | ||||
| */ | */ | ||||
| void moveToAbsolute (const Rectangle<float>& newPos, const RelativeCoordinate::NamedCoordinateFinder& nameFinder); | |||||
| void moveToAbsolute (const Rectangle<float>& newPos, const RelativeCoordinate::NamedCoordinateFinder* nameFinder); | |||||
| /** Returns a string which represents this point. | /** Returns a string which represents this point. | ||||
| This returns a comma-separated list of coordinates, in the order left, top, right, bottom. For details of | This returns a comma-separated list of coordinates, in the order left, top, right, bottom. For details of | ||||
| @@ -374,11 +394,139 @@ public: | |||||
| This calls RelativeCoordinate::renameAnchorIfUsed() on the rectangle's coordinates. | This calls RelativeCoordinate::renameAnchorIfUsed() on the rectangle's coordinates. | ||||
| */ | */ | ||||
| void renameAnchorIfUsed (const String& oldName, const String& newName, | void renameAnchorIfUsed (const String& oldName, const String& newName, | ||||
| const RelativeCoordinate::NamedCoordinateFinder& nameFinder); | |||||
| const RelativeCoordinate::NamedCoordinateFinder* nameFinder); | |||||
| // The actual rectangle coords... | // The actual rectangle coords... | ||||
| RelativeCoordinate left, right, top, bottom; | RelativeCoordinate left, right, top, bottom; | ||||
| }; | }; | ||||
| //============================================================================== | |||||
| /** | |||||
| A path object that consists of RelativePoint coordinates rather than the normal fixed ones. | |||||
| One of these paths can be converted into a Path object for drawing and manipulation, but | |||||
| unlike a Path, its points can be dynamic instead of just fixed. | |||||
| @see RelativePoint, RelativeCoordinate | |||||
| */ | |||||
| class JUCE_API RelativePointPath | |||||
| { | |||||
| public: | |||||
| //============================================================================== | |||||
| RelativePointPath(); | |||||
| RelativePointPath (const RelativePointPath& other); | |||||
| RelativePointPath (const String& stringVersion); | |||||
| ~RelativePointPath(); | |||||
| //============================================================================== | |||||
| /** Resolves this points in this path and adds them to a normal Path object. */ | |||||
| void createPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder); | |||||
| /** Returns true if the path contains any non-fixed points. */ | |||||
| bool containsAnyDynamicPoints() const; | |||||
| /** Returns a string version of the path. | |||||
| This has the same format as Path::toString(), but since it can contain RelativeCoordinate | |||||
| positions, it can't be parsed by the Path class if any of the points are dynamic. | |||||
| */ | |||||
| const String toString() const; | |||||
| /** Quickly swaps the contents of this path with another. */ | |||||
| void swapWith (RelativePointPath& other) throw(); | |||||
| //============================================================================== | |||||
| /** The types of element that may be contained in this path. | |||||
| @see RelativePointPath::ElementBase | |||||
| */ | |||||
| enum ElementType | |||||
| { | |||||
| nullElement, | |||||
| startSubPathElement, | |||||
| closeSubPathElement, | |||||
| lineToElement, | |||||
| quadraticToElement, | |||||
| cubicToElement | |||||
| }; | |||||
| //============================================================================== | |||||
| /** Base class for the elements that make up a RelativePointPath. | |||||
| */ | |||||
| class JUCE_API ElementBase | |||||
| { | |||||
| public: | |||||
| ElementBase (ElementType type); | |||||
| virtual ~ElementBase() {} | |||||
| virtual void write (OutputStream& out, ElementType lastTypeWritten) const = 0; | |||||
| virtual void addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const = 0; | |||||
| const ElementType type; | |||||
| }; | |||||
| class JUCE_API StartSubPath : public ElementBase | |||||
| { | |||||
| public: | |||||
| StartSubPath (const RelativePoint& pos); | |||||
| ~StartSubPath() {} | |||||
| void write (OutputStream& out, ElementType lastTypeWritten) const; | |||||
| void addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const; | |||||
| RelativePoint startPos; | |||||
| }; | |||||
| class JUCE_API CloseSubPath : public ElementBase | |||||
| { | |||||
| public: | |||||
| CloseSubPath(); | |||||
| ~CloseSubPath() {} | |||||
| void write (OutputStream& out, ElementType lastTypeWritten) const; | |||||
| void addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const; | |||||
| }; | |||||
| class JUCE_API LineTo : public ElementBase | |||||
| { | |||||
| public: | |||||
| LineTo (const RelativePoint& endPoint); | |||||
| ~LineTo() {} | |||||
| void write (OutputStream& out, ElementType lastTypeWritten) const; | |||||
| void addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const; | |||||
| RelativePoint endPoint; | |||||
| }; | |||||
| class JUCE_API QuadraticTo : public ElementBase | |||||
| { | |||||
| public: | |||||
| QuadraticTo (const RelativePoint& controlPoint, const RelativePoint& endPoint); | |||||
| ~QuadraticTo() {} | |||||
| void write (OutputStream& out, ElementType lastTypeWritten) const; | |||||
| void addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const; | |||||
| RelativePoint controlPoint, endPoint; | |||||
| }; | |||||
| class JUCE_API CubicTo : public ElementBase | |||||
| { | |||||
| public: | |||||
| CubicTo (const RelativePoint& controlPoint1, const RelativePoint& controlPoint2, const RelativePoint& endPoint); | |||||
| ~CubicTo() {} | |||||
| void write (OutputStream& out, ElementType lastTypeWritten) const; | |||||
| void addToPath (Path& path, RelativeCoordinate::NamedCoordinateFinder* coordFinder) const; | |||||
| RelativePoint controlPoint1, controlPoint2, endPoint; | |||||
| }; | |||||
| //============================================================================== | |||||
| OwnedArray <ElementBase> elements; | |||||
| bool usesNonZeroWinding; | |||||
| private: | |||||
| bool containsDynamicPoints; | |||||
| void parseString (const String& s); | |||||
| RelativePointPath& operator= (const RelativePointPath&); | |||||
| }; | |||||
| #endif // __JUCE_RELATIVECOORDINATE_JUCEHEADER__ | #endif // __JUCE_RELATIVECOORDINATE_JUCEHEADER__ | ||||
| @@ -131,6 +131,9 @@ void ImageCache::releaseOrDelete (Image* const imageToRelease) | |||||
| bool ImageCache::isImageInCache (Image* const imageToLookFor) | bool ImageCache::isImageInCache (Image* const imageToLookFor) | ||||
| { | { | ||||
| if (imageToLookFor == 0) | |||||
| return false; | |||||
| if (instance != 0) | if (instance != 0) | ||||
| { | { | ||||
| const ScopedLock sl (instance->lock); | const ScopedLock sl (instance->lock); | ||||
| @@ -35,7 +35,7 @@ DirectoryIterator::DirectoryIterator (const File& directory, | |||||
| bool isRecursive_, | bool isRecursive_, | ||||
| const String& wildCard_, | const String& wildCard_, | ||||
| const int whatToLookFor_) | const int whatToLookFor_) | ||||
| : fileFinder (directory, isRecursive ? "*" : wildCard_), | |||||
| : fileFinder (directory, isRecursive_ ? "*" : wildCard_), | |||||
| wildCard (wildCard_), | wildCard (wildCard_), | ||||
| path (File::addTrailingSeparator (directory.getFullPathName())), | path (File::addTrailingSeparator (directory.getFullPathName())), | ||||
| index (-1), | index (-1), | ||||
| @@ -1091,15 +1091,9 @@ public: | |||||
| { | { | ||||
| } | } | ||||
| void repaint (int x, int y, int w, int h) | |||||
| void repaint (const Rectangle<int>& area) | |||||
| { | { | ||||
| if (Rectangle<int>::intersectRectangles (x, y, w, h, | |||||
| 0, 0, | |||||
| getComponent()->getWidth(), | |||||
| getComponent()->getHeight())) | |||||
| { | |||||
| repainter->repaint (x, y, w, h); | |||||
| } | |||||
| repainter->repaint (area.getIntersection (getComponent()->getLocalBounds())); | |||||
| } | } | ||||
| void performAnyPendingRepaintsNow() | void performAnyPendingRepaintsNow() | ||||
| @@ -1526,8 +1520,8 @@ public: | |||||
| &child); | &child); | ||||
| } | } | ||||
| repaint (exposeEvent->x, exposeEvent->y, | |||||
| exposeEvent->width, exposeEvent->height); | |||||
| repaint (Rectangle<int> (exposeEvent->x, exposeEvent->y, | |||||
| exposeEvent->width, exposeEvent->height)); | |||||
| while (XEventsQueued (display, QueuedAfterFlush) > 0) | while (XEventsQueued (display, QueuedAfterFlush) > 0) | ||||
| { | { | ||||
| @@ -1537,8 +1531,8 @@ public: | |||||
| XNextEvent (display, (XEvent*) &nextEvent); | XNextEvent (display, (XEvent*) &nextEvent); | ||||
| XExposeEvent* nextExposeEvent = (XExposeEvent*) &nextEvent.xexpose; | XExposeEvent* nextExposeEvent = (XExposeEvent*) &nextEvent.xexpose; | ||||
| repaint (nextExposeEvent->x, nextExposeEvent->y, | |||||
| nextExposeEvent->width, nextExposeEvent->height); | |||||
| repaint (Rectangle<int> (nextExposeEvent->x, nextExposeEvent->y, | |||||
| nextExposeEvent->width, nextExposeEvent->height)); | |||||
| } | } | ||||
| break; | break; | ||||
| @@ -1838,12 +1832,12 @@ private: | |||||
| } | } | ||||
| } | } | ||||
| void repaint (int x, int y, int w, int h) | |||||
| void repaint (const Rectangle<int>& area) | |||||
| { | { | ||||
| if (! isTimerRunning()) | if (! isTimerRunning()) | ||||
| startTimer (repaintTimerPeriod); | startTimer (repaintTimerPeriod); | ||||
| regionsNeedingRepaint.add (x, y, w, h); | |||||
| regionsNeedingRepaint.add (area); | |||||
| } | } | ||||
| void performAnyPendingRepaintsNow() | void performAnyPendingRepaintsNow() | ||||
| @@ -138,7 +138,7 @@ public: | |||||
| void handleTouches (UIEvent* e, bool isDown, bool isUp, bool isCancel); | void handleTouches (UIEvent* e, bool isDown, bool isUp, bool isCancel); | ||||
| //============================================================================== | //============================================================================== | ||||
| void repaint (int x, int y, int w, int h); | |||||
| void repaint (const Rectangle<int>& area); | |||||
| void performAnyPendingRepaintsNow(); | void performAnyPendingRepaintsNow(); | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -849,19 +849,20 @@ public: | |||||
| void messageCallback() | void messageCallback() | ||||
| { | { | ||||
| if (ComponentPeer::isValidPeer (peer)) | if (ComponentPeer::isValidPeer (peer)) | ||||
| peer->repaint (rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight()); | |||||
| peer->repaint (rect); | |||||
| } | } | ||||
| }; | }; | ||||
| void UIViewComponentPeer::repaint (int x, int y, int w, int h) | |||||
| void UIViewComponentPeer::repaint (const Rectangle<int>& area) | |||||
| { | { | ||||
| if (insideDrawRect || ! MessageManager::getInstance()->isThisTheMessageThread()) | if (insideDrawRect || ! MessageManager::getInstance()->isThisTheMessageThread()) | ||||
| { | { | ||||
| (new AsyncRepaintMessage (this, Rectangle<int> (x, y, w, h)))->post(); | |||||
| (new AsyncRepaintMessage (this, area))->post(); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| [view setNeedsDisplayInRect: CGRectMake ((float) x, (float) y, (float) w, (float) h)]; | |||||
| [view setNeedsDisplayInRect: CGRectMake ((float) area.getX(), (float) area.getY(), | |||||
| (float) area.getWidth(), (float) area.getHeight())]; | |||||
| } | } | ||||
| } | } | ||||
| @@ -253,7 +253,7 @@ public: | |||||
| void textInputRequired (const Point<int>& position); | void textInputRequired (const Point<int>& position); | ||||
| //============================================================================== | //============================================================================== | ||||
| void repaint (int x, int y, int w, int h); | |||||
| void repaint (const Rectangle<int>& area); | |||||
| void performAnyPendingRepaintsNow(); | void performAnyPendingRepaintsNow(); | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -1631,20 +1631,20 @@ public: | |||||
| void messageCallback() | void messageCallback() | ||||
| { | { | ||||
| if (ComponentPeer::isValidPeer (peer)) | if (ComponentPeer::isValidPeer (peer)) | ||||
| peer->repaint (rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight()); | |||||
| peer->repaint (rect); | |||||
| } | } | ||||
| }; | }; | ||||
| void NSViewComponentPeer::repaint (int x, int y, int w, int h) | |||||
| void NSViewComponentPeer::repaint (const Rectangle<int>& area) | |||||
| { | { | ||||
| if (insideDrawRect) | if (insideDrawRect) | ||||
| { | { | ||||
| (new AsyncRepaintMessage (this, Rectangle<int> (x, y, w, h)))->post(); | |||||
| (new AsyncRepaintMessage (this, area))->post(); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| [view setNeedsDisplayInRect: NSMakeRect ((float) x, (float) ([view frame].size.height - (y + h)), | |||||
| (float) w, (float) h)]; | |||||
| [view setNeedsDisplayInRect: NSMakeRect ((float) area.getX(), [view frame].size.height - (float) area.getBottom(), | |||||
| (float) area.getWidth(), (float) area.getHeight())]; | |||||
| } | } | ||||
| } | } | ||||
| @@ -597,7 +597,10 @@ public: | |||||
| Thread::sleep (20); | Thread::sleep (20); | ||||
| isStarted = false; | isStarted = false; | ||||
| isOpen_ = false; | isOpen_ = false; | ||||
| close(); | |||||
| const String errorCopy (error); | |||||
| close(); // (this resets the error string) | |||||
| error = errorCopy; | |||||
| } | } | ||||
| needToReset = false; | needToReset = false; | ||||
| @@ -288,8 +288,7 @@ public: | |||||
| void repaint() | void repaint() | ||||
| { | { | ||||
| const Rectangle<int> bounds (nativeWindow->getBounds()); | |||||
| nativeWindow->repaint (0, 0, bounds.getWidth(), bounds.getHeight()); | |||||
| nativeWindow->repaint (nativeWindow->getBounds().withPosition (Point<int>())); | |||||
| } | } | ||||
| void swapBuffers() | void swapBuffers() | ||||
| @@ -685,7 +685,7 @@ public: | |||||
| int getInputLatencyInSamples() { return latencyIn; } | int getInputLatencyInSamples() { return latencyIn; } | ||||
| const BigInteger getActiveOutputChannels() const { return outputDevice != 0 ? outputDevice->channels : BigInteger(); } | const BigInteger getActiveOutputChannels() const { return outputDevice != 0 ? outputDevice->channels : BigInteger(); } | ||||
| const BigInteger getActiveInputChannels() const { return inputDevice != 0 ? inputDevice->channels : BigInteger(); } | const BigInteger getActiveInputChannels() const { return inputDevice != 0 ? inputDevice->channels : BigInteger(); } | ||||
| const String getLastError() { return lastError; } | |||||
| const String getLastError() { return lastError; } | |||||
| const String open (const BigInteger& inputChannels, const BigInteger& outputChannels, | const String open (const BigInteger& inputChannels, const BigInteger& outputChannels, | ||||
| @@ -705,9 +705,9 @@ public: | |||||
| SetCaretPos (0, 0); | SetCaretPos (0, 0); | ||||
| } | } | ||||
| void repaint (int x, int y, int w, int h) | |||||
| void repaint (const Rectangle<int>& area) | |||||
| { | { | ||||
| const RECT r = { x, y, x + w, y + h }; | |||||
| const RECT r = { area.getX(), area.getY(), area.getRight(), area.getBottom() }; | |||||
| InvalidateRect (hwnd, &r, FALSE); | InvalidateRect (hwnd, &r, FALSE); | ||||
| } | } | ||||
| @@ -1055,9 +1055,7 @@ static int indexOfMatch (const juce_wchar* const wildcard, | |||||
| else | else | ||||
| { | { | ||||
| if (wc == '*' && (wildcard [i + 1] == 0 | if (wc == '*' && (wildcard [i + 1] == 0 | ||||
| || indexOfMatch (wildcard + i + 1, | |||||
| test + start + i, | |||||
| ignoreCase) >= 0)) | |||||
| || indexOfMatch (wildcard + i + 1, test + start + i, ignoreCase) >= 0)) | |||||
| { | { | ||||
| return start; | return start; | ||||
| } | } | ||||
| @@ -1093,9 +1091,7 @@ bool String::matchesWildcard (const String& wildcard, const bool ignoreCase) con | |||||
| else | else | ||||
| { | { | ||||
| return wc == '*' && (wildcard [i + 1] == 0 | return wc == '*' && (wildcard [i + 1] == 0 | ||||
| || indexOfMatch (wildcard.text + i + 1, | |||||
| text + i, | |||||
| ignoreCase) >= 0); | |||||
| || indexOfMatch (wildcard.text + i + 1, text + i, ignoreCase) >= 0); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||