mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Major changes to the way Drawables are converted to ValueTrees (with more changes still to come in this area). Important fix to DirectoryIterator. Minor fix for ASIO. Jucer development.
This commit is contained in:
parent
97982bcfdc
commit
8ff6737261
75 changed files with 4704 additions and 2247 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -68,7 +68,6 @@ OBJECTS := \
|
|||
$(OBJDIR)/jucer_ProjectTreeViewBase.o \
|
||||
$(OBJDIR)/jucer_TreeViewTypes.o \
|
||||
$(OBJDIR)/jucer_CodeHelpers.o \
|
||||
$(OBJDIR)/jucer_Coordinate.o \
|
||||
$(OBJDIR)/jucer_FileHelpers.o \
|
||||
$(OBJDIR)/jucer_StoredSettings.o \
|
||||
$(OBJDIR)/jucer_MiscUtilities.o \
|
||||
|
|
@ -96,177 +95,172 @@ clean:
|
|||
|
||||
$(OBJDIR)/jucer_CodeGenerator.o: ../../Source/model/Component/jucer_CodeGenerator.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_CodeGenerator.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_ComponentDocument.o: ../../Source/model/Component/jucer_ComponentDocument.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_ComponentDocument.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_ComponentTypeManager.o: ../../Source/model/Component/Types/jucer_ComponentTypeManager.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_ComponentTypeManager.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_DrawableDocument.o: ../../Source/model/Drawable/jucer_DrawableDocument.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_DrawableDocument.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_NewFileWizard.o: ../../Source/model/Project/jucer_NewFileWizard.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_NewFileWizard.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_Project.o: ../../Source/model/Project/jucer_Project.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_Project.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_ProjectExporter.o: ../../Source/model/Project/jucer_ProjectExporter.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_ProjectExporter.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_ProjectWizard.o: ../../Source/model/Project/jucer_ProjectWizard.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_ProjectWizard.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_ResourceFile.o: ../../Source/model/Project/jucer_ResourceFile.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_ResourceFile.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_SourceCodeEditor.o: ../../Source/ui/Code\ Editor/jucer_SourceCodeEditor.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_SourceCodeEditor.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_ComponentEditor.o: ../../Source/ui/Component\ Editor/jucer_ComponentEditor.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_ComponentEditor.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_ComponentViewer.o: ../../Source/ui/Component\ Editor/jucer_ComponentViewer.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_ComponentViewer.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_DrawableEditor.o: ../../Source/ui/Drawable\ Editor/jucer_DrawableEditor.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_DrawableEditor.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_EditorCanvas.o: ../../Source/ui/Editor\ Base/jucer_EditorCanvas.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_EditorCanvas.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_DocumentEditorComponent.o: ../../Source/ui/jucer_DocumentEditorComponent.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_DocumentEditorComponent.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_JucerTreeViewBase.o: ../../Source/ui/jucer_JucerTreeViewBase.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_JucerTreeViewBase.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_MainWindow.o: ../../Source/ui/jucer_MainWindow.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_MainWindow.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_OpenDocumentManager.o: ../../Source/ui/jucer_OpenDocumentManager.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_OpenDocumentManager.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_GroupInformationComponent.o: ../../Source/ui/Project\ Editor/jucer_GroupInformationComponent.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_GroupInformationComponent.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_ItemPreviewComponent.o: ../../Source/ui/Project\ Editor/jucer_ItemPreviewComponent.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_ItemPreviewComponent.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_ProjectContentComponent.o: ../../Source/ui/Project\ Editor/jucer_ProjectContentComponent.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_ProjectContentComponent.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_ProjectInformationComponent.o: ../../Source/ui/Project\ Editor/jucer_ProjectInformationComponent.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_ProjectInformationComponent.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_ProjectTreeViewBase.o: ../../Source/ui/Project\ Editor/jucer_ProjectTreeViewBase.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_ProjectTreeViewBase.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_TreeViewTypes.o: ../../Source/ui/Project\ Editor/jucer_TreeViewTypes.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_TreeViewTypes.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_CodeHelpers.o: ../../Source/utility/jucer_CodeHelpers.cpp
|
||||
-@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 "$<"
|
||||
|
||||
$(OBJDIR)/jucer_FileHelpers.o: ../../Source/utility/jucer_FileHelpers.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_FileHelpers.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_StoredSettings.o: ../../Source/utility/jucer_StoredSettings.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_StoredSettings.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_MiscUtilities.o: ../../Source/utility/jucer_MiscUtilities.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_MiscUtilities.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/jucer_Main.o: ../../Source/jucer_Main.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling jucer_Main.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/BinaryData.o: ../../JuceLibraryCode/BinaryData.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling BinaryData.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/JuceLibraryCode1.o: ../../JuceLibraryCode/JuceLibraryCode1.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling JuceLibraryCode1.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/JuceLibraryCode2.o: ../../JuceLibraryCode/JuceLibraryCode2.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling JuceLibraryCode2.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/JuceLibraryCode3.o: ../../JuceLibraryCode/JuceLibraryCode3.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling JuceLibraryCode3.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/JuceLibraryCode4.o: ../../JuceLibraryCode/JuceLibraryCode4.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling JuceLibraryCode4.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
-include $(OBJECTS:%.o=%.d)
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@
|
|||
984444E3B2947675DC7D65DA = { isa = PBXBuildFile; fileRef = 1FDE55685608689765ADC578; };
|
||||
58BF60E87F9A8EDCACC5D1AE = { isa = PBXBuildFile; fileRef = 939E2A7946081DB4D21B89B6; };
|
||||
28B94C4BB7B572E6F5419E5D = { isa = PBXBuildFile; fileRef = 78E0309CB6D5E7E80B5BED7D; };
|
||||
5BF87265418D736250283182 = { isa = PBXBuildFile; fileRef = C7ADB43F83A83FFC08921A12; };
|
||||
12C1D006503C664FF07F476F = { isa = PBXBuildFile; fileRef = 5533704F0D30A9C62058FEC7; };
|
||||
DDAB225ABE572196882C3524 = { isa = PBXBuildFile; fileRef = 7A1CD936BD306A6E0BEFB046; };
|
||||
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; };
|
||||
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; };
|
||||
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; };
|
||||
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; };
|
||||
|
|
@ -143,8 +143,6 @@
|
|||
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; };
|
||||
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; };
|
||||
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; };
|
||||
|
|
@ -204,7 +202,8 @@
|
|||
7C95A5CDB1B24D227D92749E ); name = Component; sourceTree = "<group>"; };
|
||||
E70E3BE796E91EA86CFE10FE = { isa = PBXGroup; children = (
|
||||
B1471E8698D193FBCF0DD13D,
|
||||
739F94CA6213B43D867AB0FD ); name = Drawable; sourceTree = "<group>"; };
|
||||
739F94CA6213B43D867AB0FD,
|
||||
BDE8CD9273E1B0D0E500D283 ); name = Drawable; sourceTree = "<group>"; };
|
||||
ADA17383E5554BCDF567AACC = { isa = PBXGroup; children = (
|
||||
9DCB32BBD7053ACCB598CE79,
|
||||
201DF0B7B4AA3E03B1AA5144,
|
||||
|
|
@ -280,8 +279,6 @@
|
|||
9C58E022906C193862372BC1,
|
||||
AAF3C58696944A256CA61730,
|
||||
9736236B5C4D6A16FC7E03AC,
|
||||
C7ADB43F83A83FFC08921A12,
|
||||
EFA0636FB8ABA3377AB6C6F4,
|
||||
CC9A3046B8B9FCDFE2092F51,
|
||||
5533704F0D30A9C62058FEC7,
|
||||
27E71DE11448E4D6721D5508,
|
||||
|
|
@ -438,7 +435,6 @@
|
|||
984444E3B2947675DC7D65DA,
|
||||
58BF60E87F9A8EDCACC5D1AE,
|
||||
28B94C4BB7B572E6F5419E5D,
|
||||
5BF87265418D736250283182,
|
||||
12C1D006503C664FF07F476F,
|
||||
DDAB225ABE572196882C3524,
|
||||
92612DD3884793248F1EC45A,
|
||||
|
|
|
|||
|
|
@ -154,6 +154,7 @@
|
|||
<Filter Name="Drawable">
|
||||
<File RelativePath="..\..\Source\model\Drawable\jucer_DrawableDocument.cpp"/>
|
||||
<File RelativePath="..\..\Source\model\Drawable\jucer_DrawableDocument.h"/>
|
||||
<File RelativePath="..\..\Source\model\Drawable\jucer_DrawableTypeHandler.h"/>
|
||||
</Filter>
|
||||
<Filter Name="Project">
|
||||
<File RelativePath="..\..\Source\model\Project\jucer_NewFileWizard.cpp"/>
|
||||
|
|
@ -229,8 +230,6 @@
|
|||
<File RelativePath="..\..\Source\utility\jucer_CodeHelpers.h"/>
|
||||
<File RelativePath="..\..\Source\utility\jucer_ColourEditorComponent.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_FileHelpers.cpp"/>
|
||||
<File RelativePath="..\..\Source\utility\jucer_FileHelpers.h"/>
|
||||
|
|
|
|||
|
|
@ -154,6 +154,7 @@
|
|||
<Filter Name="Drawable">
|
||||
<File RelativePath="..\..\Source\model\Drawable\jucer_DrawableDocument.cpp"/>
|
||||
<File RelativePath="..\..\Source\model\Drawable\jucer_DrawableDocument.h"/>
|
||||
<File RelativePath="..\..\Source\model\Drawable\jucer_DrawableTypeHandler.h"/>
|
||||
</Filter>
|
||||
<Filter Name="Project">
|
||||
<File RelativePath="..\..\Source\model\Project\jucer_NewFileWizard.cpp"/>
|
||||
|
|
@ -229,8 +230,6 @@
|
|||
<File RelativePath="..\..\Source\utility\jucer_CodeHelpers.h"/>
|
||||
<File RelativePath="..\..\Source\utility\jucer_ColourEditorComponent.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_FileHelpers.cpp"/>
|
||||
<File RelativePath="..\..\Source\utility\jucer_FileHelpers.h"/>
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@
|
|||
file="Source/model/Drawable/jucer_DrawableDocument.cpp"/>
|
||||
<FILE id="qMcrWuCal" name="jucer_DrawableDocument.h" compile="0" resource="0"
|
||||
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 id="na25KSPIj" name="Project">
|
||||
<FILE id="jqL1mb9xp" name="jucer_NewFileWizard.cpp" compile="1" resource="0"
|
||||
|
|
@ -205,10 +207,6 @@
|
|||
resource="0" file="Source/utility/jucer_ColourEditorComponent.h"/>
|
||||
<FILE id="bjibbvm3S" name="jucer_Colours.h" compile="0" resource="0"
|
||||
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"
|
||||
resource="0" file="Source/utility/jucer_CoordinatePropertyComponent.h"/>
|
||||
<FILE id="WlEYep7NN" name="jucer_FileHelpers.cpp" compile="1" resource="0"
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ public:
|
|||
//==============================================================================
|
||||
ComponentBoundsEditor (ComponentDocument& document_, const String& name, Type type_,
|
||||
const ValueTree& compState_, const Value& coordValue_)
|
||||
: CoordinatePropertyComponent (document_, name,
|
||||
: CoordinatePropertyComponent (&document_, name,
|
||||
Value (new CoordExtractor (coordValue_, type_)),
|
||||
type_ == left || type_ == right),
|
||||
document (document_),
|
||||
|
|
@ -184,7 +184,7 @@ Component* ComponentTypeManager::createFromStoredType (ComponentDocument& docume
|
|||
ComponentTypeHandler* ComponentTypeManager::getHandlerFor (const Identifier& type)
|
||||
{
|
||||
for (int i = handlers.size(); --i >= 0;)
|
||||
if (handlers.getUnchecked(i)->getXmlTag() == type)
|
||||
if (handlers.getUnchecked(i)->getValueTreeType() == type)
|
||||
return handlers.getUnchecked(i);
|
||||
|
||||
return 0;
|
||||
|
|
@ -205,8 +205,8 @@ juce_ImplementSingleton_SingleThreaded (ComponentTypeManager);
|
|||
|
||||
//==============================================================================
|
||||
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_)
|
||||
{
|
||||
}
|
||||
|
|
@ -315,7 +315,7 @@ void ComponentTypeInstance::initialiseNewItemBasics()
|
|||
void ComponentTypeInstance::updateComponentBasics (Component* comp)
|
||||
{
|
||||
RelativeRectangle pos (state [ComponentDocument::compBoundsProperty].toString());
|
||||
comp->setBounds (pos.resolve (document).getSmallestIntegerContainer());
|
||||
comp->setBounds (pos.resolve (&document).getSmallestIntegerContainer());
|
||||
|
||||
//comp->setName (state [ComponentDocument::compNameProperty]);
|
||||
|
||||
|
|
|
|||
|
|
@ -86,11 +86,12 @@ class ComponentTypeHandler
|
|||
{
|
||||
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();
|
||||
|
||||
const String& getDisplayName() const { return displayName; }
|
||||
const Identifier& getXmlTag() const { return xmlTag; }
|
||||
const Identifier& getValueTreeType() const { return valueTreeType; }
|
||||
const String& getMemberNameRoot() const { return memberNameRoot; }
|
||||
|
||||
virtual Component* createComponent() = 0;
|
||||
|
|
@ -106,7 +107,7 @@ public:
|
|||
protected:
|
||||
//==============================================================================
|
||||
const String displayName, className, memberNameRoot;
|
||||
const Identifier xmlTag;
|
||||
const Identifier valueTreeType;
|
||||
|
||||
private:
|
||||
ComponentTypeHandler (const ComponentTypeHandler&);
|
||||
|
|
|
|||
|
|
@ -359,7 +359,7 @@ const ValueTree ComponentDocument::performNewComponentMenuItem (int menuResultCo
|
|||
|
||||
if (handler != 0)
|
||||
{
|
||||
ValueTree state (handler->getXmlTag());
|
||||
ValueTree state (handler->getValueTreeType());
|
||||
state.setProperty (idProperty, createAlphaNumericUID(), 0);
|
||||
|
||||
ComponentTypeInstance comp (*this, state);
|
||||
|
|
@ -532,7 +532,7 @@ void ComponentDocument::renameAnchor (const String& oldName, const String& newNa
|
|||
{
|
||||
ValueTree v (getComponent(i));
|
||||
RelativeRectangle coords (getCoordsFor (v));
|
||||
coords.renameAnchorIfUsed (oldName, newName, *this);
|
||||
coords.renameAnchorIfUsed (oldName, newName, this);
|
||||
setCoordsFor (v, coords);
|
||||
}
|
||||
|
||||
|
|
@ -551,7 +551,7 @@ void ComponentDocument::addMarkerMenuItem (int i, const RelativeCoordinate& coor
|
|||
name << '.' << edge;
|
||||
|
||||
menu.addItem (i, name,
|
||||
! (name == fullCoordName || requestedCoord.references (fullCoordName, *this)),
|
||||
! (name == fullCoordName || requestedCoord.references (fullCoordName, this)),
|
||||
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))),
|
||||
"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())));
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
#include "../../jucer_Headers.h"
|
||||
#include "../Project/jucer_Project.h"
|
||||
#include "../../utility/jucer_Coordinate.h"
|
||||
#include "../../utility/jucer_MarkerListBase.h"
|
||||
#include "jucer_CodeGenerator.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,54 @@
|
|||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
ValueTree DrawableDocument::getRootDrawableNode() const
|
||||
DrawableComposite::ValueTreeWrapper DrawableDocument::getRootDrawableNode() const
|
||||
{
|
||||
return root.getChild (0);
|
||||
return DrawableComposite::ValueTreeWrapper (root.getChild (0));
|
||||
}
|
||||
|
||||
void DrawableDocument::checkRootObject()
|
||||
|
|
@ -75,11 +123,6 @@ void DrawableDocument::checkRootObject()
|
|||
getCanvasHeight() = 500;
|
||||
}
|
||||
|
||||
const String DrawableDocument::getIdFor (const ValueTree& object)
|
||||
{
|
||||
return object [Ids::id_];
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void DrawableDocument::setName (const String& name)
|
||||
{
|
||||
|
|
@ -194,59 +237,49 @@ void DrawableDocument::changed()
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
static const Colour getRandomColour()
|
||||
const int menuItemOffset = 0x63451fa4;
|
||||
|
||||
void DrawableDocument::addNewItemMenuItems (PopupMenu& menu) const
|
||||
{
|
||||
return Colours::red.withHue (Random::getSystemRandom().nextFloat());
|
||||
const StringArray displayNames (DrawableTypeManager::getInstance()->getDisplayNames());
|
||||
|
||||
for (int i = 0; i < displayNames.size(); ++i)
|
||||
menu.addItem (i + menuItemOffset, "New " + displayNames[i]);
|
||||
}
|
||||
|
||||
void DrawableDocument::addDrawable (Drawable& d)
|
||||
const ValueTree DrawableDocument::performNewItemMenuItem (int menuResultCode)
|
||||
{
|
||||
DrawableComposite dc;
|
||||
dc.insertDrawable (d.createCopy());
|
||||
const StringArray displayNames (DrawableTypeManager::getInstance()->getDisplayNames());
|
||||
|
||||
ValueTree dcNode (dc.createValueTree (0));
|
||||
ValueTree subNode (dcNode.getChild(0));
|
||||
dcNode.removeChild (subNode, 0);
|
||||
addMissingIds (subNode);
|
||||
if (menuResultCode >= menuItemOffset && menuResultCode < menuItemOffset + displayNames.size())
|
||||
{
|
||||
DrawableTypeHandler* handler = DrawableTypeManager::getInstance()->getHandler (menuResultCode - menuItemOffset);
|
||||
jassert (handler != 0);
|
||||
|
||||
getRootDrawableNode().addChild (subNode, -1, getUndoManager());
|
||||
if (handler != 0)
|
||||
{
|
||||
ValueTree state (handler->createNewInstance (*this,
|
||||
Point<float> (Random::getSystemRandom().nextFloat() * 100.0f + 100.0f,
|
||||
Random::getSystemRandom().nextFloat() * 100.0f + 100.0f)));
|
||||
|
||||
getRootDrawableNode().addDrawable (state, -1, getUndoManager());
|
||||
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
return ValueTree::invalid;
|
||||
}
|
||||
|
||||
void DrawableDocument::addRectangle()
|
||||
//==============================================================================
|
||||
Image* DrawableDocument::getImageForIdentifier (const var& imageIdentifier)
|
||||
{
|
||||
Path p;
|
||||
p.addRectangle ((float) Random::getSystemRandom().nextInt (500),
|
||||
(float) Random::getSystemRandom().nextInt (500),
|
||||
100.0f, 100.0f);
|
||||
|
||||
DrawablePath d;
|
||||
d.setPath (p);
|
||||
d.setFill (FillType (getRandomColour()));
|
||||
|
||||
addDrawable (d);
|
||||
return ImageCache::getFromMemory (BinaryData::juce_icon_png, BinaryData::juce_icon_pngSize);
|
||||
}
|
||||
|
||||
void DrawableDocument::addCircle()
|
||||
const var DrawableDocument::getIdentifierForImage (Image* image)
|
||||
{
|
||||
Path p;
|
||||
p.addEllipse ((float) Random::getSystemRandom().nextInt (500),
|
||||
(float) Random::getSystemRandom().nextInt (500),
|
||||
100.0f, 100.0f);
|
||||
|
||||
DrawablePath d;
|
||||
d.setPath (p);
|
||||
d.setFill (FillType (getRandomColour()));
|
||||
|
||||
addDrawable (d);
|
||||
}
|
||||
|
||||
void DrawableDocument::addImage (const File& imageFile)
|
||||
{
|
||||
jassertfalse
|
||||
|
||||
DrawableImage d;
|
||||
|
||||
addDrawable (d);
|
||||
return var::null; //xxx todo
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -28,13 +28,13 @@
|
|||
|
||||
#include "../../jucer_Headers.h"
|
||||
#include "../Project/jucer_Project.h"
|
||||
#include "../../utility/jucer_Coordinate.h"
|
||||
#include "../../utility/jucer_MarkerListBase.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class DrawableDocument : public ValueTree::Listener,
|
||||
public ChangeBroadcaster
|
||||
public ChangeBroadcaster,
|
||||
public Drawable::ImageProvider
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
|
|
@ -51,16 +51,13 @@ public:
|
|||
void changed();
|
||||
|
||||
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 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
|
||||
|
|
@ -91,6 +88,9 @@ public:
|
|||
const String getNonexistentMarkerName (const String& name);
|
||||
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 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)))
|
||||
<< ": " << escapeSpaces (files.getReference(i).toUnixStyle()) << 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 \"$<\""
|
||||
: "\t@$(CXX) $(CXXFLAGS) -o \"$@\" -c \"$<\"")
|
||||
<< newLine << newLine;
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ public:
|
|||
|
||||
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)
|
||||
|
|
@ -176,14 +176,14 @@ public:
|
|||
const Rectangle<float> getObjectPosition (const ValueTree& state)
|
||||
{
|
||||
ComponentDocument& doc = getDocument();
|
||||
return doc.getCoordsFor (state).resolve (doc);
|
||||
return doc.getCoordsFor (state).resolve (&doc);
|
||||
}
|
||||
|
||||
bool setObjectPosition (ValueTree& state, const Rectangle<float>& newBounds)
|
||||
{
|
||||
ComponentDocument& doc = getDocument();
|
||||
RelativeRectangle pr (doc.getCoordsFor (state));
|
||||
pr.moveToAbsolute (newBounds, doc);
|
||||
pr.moveToAbsolute (newBounds, &doc);
|
||||
|
||||
return doc.setCoordsFor (state, pr);
|
||||
}
|
||||
|
|
@ -191,7 +191,7 @@ public:
|
|||
float getMarkerPosition (const ValueTree& marker, bool isX)
|
||||
{
|
||||
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());
|
||||
|
||||
if (layoutManager == 0)
|
||||
layoutManager = new ComponentAutoLayoutManager (this);
|
||||
layoutManager = new RelativeRectangleLayoutManager (this);
|
||||
|
||||
int i;
|
||||
for (i = getNumChildComponents(); --i >= 0;)
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ private:
|
|||
ComponentDocument* componentDocument;
|
||||
ValueTree documentRoot;
|
||||
|
||||
ScopedPointer<ComponentAutoLayoutManager> layoutManager;
|
||||
ScopedPointer<RelativeRectangleLayoutManager> layoutManager;
|
||||
Colour background;
|
||||
|
||||
ComponentViewer (const ComponentViewer&);
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ public:
|
|||
void createCanvas()
|
||||
{
|
||||
initialise (new DrawableEditorCanvas (editor), toolbarFactory,
|
||||
new DrawableTreeViewItem (editor, editor.getDocument().getRootDrawableNode()));
|
||||
new DrawableTreeViewItem (editor, editor.getDocument().getRootDrawableNode().getState()));
|
||||
}
|
||||
|
||||
SelectedItemSet<String>& getSelection()
|
||||
|
|
@ -117,17 +117,10 @@ void DrawableEditor::selectionToBack()
|
|||
|
||||
void DrawableEditor::showNewShapeMenu (Component* componentToAttachTo)
|
||||
{
|
||||
/*
|
||||
PopupMenu m;
|
||||
getDocument().addNewComponentMenuItems (m);
|
||||
|
||||
getDocument().addNewItemMenuItems (m);
|
||||
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()
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -89,9 +100,9 @@ public:
|
|||
}
|
||||
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)
|
||||
: editor (editor_), node (drawableRoot), typeName (drawableRoot.getType().toString())
|
||||
{
|
||||
node.addListener (this);
|
||||
node.getState().addListener (this);
|
||||
editor.getSelection().addChangeListener (this);
|
||||
}
|
||||
|
||||
~DrawableTreeViewItem()
|
||||
{
|
||||
editor.getSelection().removeChangeListener (this);
|
||||
node.removeListener (this);
|
||||
node.getState().removeListener (this);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -55,7 +55,7 @@ public:
|
|||
|
||||
void valueTreeChildrenChanged (ValueTree& tree)
|
||||
{
|
||||
if (tree == node)
|
||||
if (tree == node.getState())
|
||||
refreshSubItems();
|
||||
}
|
||||
|
||||
|
|
@ -67,14 +67,13 @@ public:
|
|||
// TreeViewItem stuff..
|
||||
bool mightContainSubItems()
|
||||
{
|
||||
return node.getType() == DrawableComposite::valueTreeType
|
||||
&& node.getNumChildren() > 0;
|
||||
return node.getState().getType() == DrawableComposite::valueTreeType;
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
@ -85,15 +84,17 @@ public:
|
|||
|
||||
void refreshSubItems()
|
||||
{
|
||||
if (node.getType() == DrawableComposite::valueTreeType)
|
||||
if (node.getState().getType() == DrawableComposite::valueTreeType)
|
||||
{
|
||||
ScopedPointer <XmlElement> oldOpenness (getOpennessState());
|
||||
|
||||
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);
|
||||
addSubItem (item);
|
||||
}
|
||||
|
|
@ -114,7 +115,7 @@ public:
|
|||
|
||||
const String getRenamingName() const
|
||||
{
|
||||
return node ["name"];
|
||||
return node.getID();
|
||||
}
|
||||
|
||||
void setName (const String& newName)
|
||||
|
|
@ -138,7 +139,7 @@ public:
|
|||
|
||||
void itemSelectionChanged (bool isNowSelected)
|
||||
{
|
||||
const String objectId (DrawableDocument::getIdFor (node));
|
||||
const String objectId (node.getID());
|
||||
|
||||
if (isNowSelected)
|
||||
editor.getSelection().addToSelection (objectId);
|
||||
|
|
@ -148,7 +149,7 @@ public:
|
|||
|
||||
void changeListenerCallback (void*)
|
||||
{
|
||||
setSelected (editor.getSelection().isSelected (DrawableDocument::getIdFor (node)), false);
|
||||
setSelected (editor.getSelection().isSelected (node.getID()), false);
|
||||
}
|
||||
|
||||
const String getTooltip()
|
||||
|
|
@ -194,7 +195,7 @@ public:
|
|||
|
||||
//==============================================================================
|
||||
DrawableEditor& editor;
|
||||
ValueTree node;
|
||||
Drawable::ValueTreeWrapperBase node;
|
||||
|
||||
private:
|
||||
String typeName;
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@ public:
|
|||
void updatePosition()
|
||||
{
|
||||
RelativeCoordinate coord (getMarkerList().getCoordinate (marker));
|
||||
const int pos = roundToInt (coord.resolve (getMarkerList()));
|
||||
const int pos = roundToInt (coord.resolve (&getMarkerList()));
|
||||
const int width = 8;
|
||||
|
||||
if (isX)
|
||||
|
|
@ -309,7 +309,7 @@ public:
|
|||
canvas->getUndoManager().beginNewTransaction();
|
||||
|
||||
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)
|
||||
coord.moveToAbsolute (jmax (0, roundToInt (dragStartPos + (isX ? e2.x - mouseDownPos.getX()
|
||||
: e2.y - mouseDownPos.getY()))),
|
||||
getMarkerList());
|
||||
&getMarkerList());
|
||||
getMarkerList().setCoordinate (marker, coord);
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -26,10 +26,10 @@
|
|||
#ifndef __JUCER_EDITORCANVAS_H_EF886D17__
|
||||
#define __JUCER_EDITORCANVAS_H_EF886D17__
|
||||
|
||||
#include "../../utility/jucer_Coordinate.h"
|
||||
#include "../../utility/jucer_MarkerListBase.h"
|
||||
class EditorPanelBase;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class EditorCanvasBase : public Component,
|
||||
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:
|
||||
//==============================================================================
|
||||
CoordinatePropertyComponent (RelativeCoordinate::NamedCoordinateFinder& nameSource_, const String& name,
|
||||
CoordinatePropertyComponent (RelativeCoordinate::NamedCoordinateFinder* nameSource_, const String& name,
|
||||
const Value& coordValue_, bool isHorizontal_)
|
||||
: PropertyComponent (name, 40), nameSource (nameSource_),
|
||||
coordValue (coordValue_),
|
||||
|
|
@ -142,7 +142,7 @@ public:
|
|||
virtual const String pickMarker (TextButton* button, const String& currentMarker, bool isAnchor1) = 0;
|
||||
|
||||
protected:
|
||||
RelativeCoordinate::NamedCoordinateFinder& nameSource;
|
||||
RelativeCoordinate::NamedCoordinateFinder* nameSource;
|
||||
Value coordValue, textValue;
|
||||
Label* label;
|
||||
TextButton* proportionButton;
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ public:
|
|||
{
|
||||
ValueTree v (getMarker (i));
|
||||
RelativeCoordinate coord (getCoordinate (v));
|
||||
coord.renameAnchorIfUsed (oldName, newName, *this);
|
||||
coord.renameAnchorIfUsed (oldName, newName, this);
|
||||
setCoordinate (v, coord);
|
||||
}
|
||||
}
|
||||
|
|
@ -133,7 +133,7 @@ public:
|
|||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
PositionPropertyComponent (NamedCoordinateFinder& nameSource_, MarkerListBase& markerList_,
|
||||
PositionPropertyComponent (NamedCoordinateFinder* nameSource_, MarkerListBase& markerList_,
|
||||
const String& name, const ValueTree& markerState_,
|
||||
const Value& coordValue_)
|
||||
: CoordinatePropertyComponent (nameSource_, name, coordValue_, markerList_.isHorizontal()),
|
||||
|
|
|
|||
|
|
@ -266,3 +266,143 @@ void FloatingLabelComponent::paint (Graphics& g)
|
|||
g.setColour (colour);
|
||||
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& 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
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling Main.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/JuceLibraryCode.o: ../../JuceLibraryCode/JuceLibraryCode.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling JuceLibraryCode.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
-include $(OBJECTS:%.o=%.d)
|
||||
|
|
|
|||
|
|
@ -70,47 +70,47 @@ clean:
|
|||
|
||||
$(OBJDIR)/FilterGraph.o: ../../Source/FilterGraph.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling FilterGraph.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/GraphEditorPanel.o: ../../Source/GraphEditorPanel.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling GraphEditorPanel.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/HostStartup.o: ../../Source/HostStartup.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling HostStartup.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/InternalFilters.o: ../../Source/InternalFilters.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling InternalFilters.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/MainHostWindow.o: ../../Source/MainHostWindow.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling MainHostWindow.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/JuceLibraryCode1.o: ../../JuceLibraryCode/JuceLibraryCode1.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling JuceLibraryCode1.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/JuceLibraryCode2.o: ../../JuceLibraryCode/JuceLibraryCode2.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling JuceLibraryCode2.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/JuceLibraryCode3.o: ../../JuceLibraryCode/JuceLibraryCode3.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling JuceLibraryCode3.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/JuceLibraryCode4.o: ../../JuceLibraryCode/JuceLibraryCode4.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling JuceLibraryCode4.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
-include $(OBJECTS:%.o=%.d)
|
||||
|
|
|
|||
|
|
@ -63,12 +63,12 @@ clean:
|
|||
|
||||
$(OBJDIR)/Main.o: ../../Source/Main.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling Main.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/JuceLibraryCode.o: ../../JuceLibraryCode/JuceLibraryCode.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling JuceLibraryCode.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
-include $(OBJECTS:%.o=%.d)
|
||||
|
|
|
|||
|
|
@ -67,32 +67,32 @@ clean:
|
|||
|
||||
$(OBJDIR)/Main.o: ../../Source/Main.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling Main.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/MainComponent.o: ../../Source/MainComponent.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling MainComponent.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/JuceLibraryCode1.o: ../../JuceLibraryCode/JuceLibraryCode1.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling JuceLibraryCode1.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/JuceLibraryCode2.o: ../../JuceLibraryCode/JuceLibraryCode2.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling JuceLibraryCode2.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/JuceLibraryCode3.o: ../../JuceLibraryCode/JuceLibraryCode3.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling JuceLibraryCode3.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/JuceLibraryCode4.o: ../../JuceLibraryCode/JuceLibraryCode4.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling JuceLibraryCode4.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
-include $(OBJECTS:%.o=%.d)
|
||||
|
|
|
|||
|
|
@ -87,132 +87,132 @@ clean:
|
|||
|
||||
$(OBJDIR)/ApplicationStartup.o: ../../Source/ApplicationStartup.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling ApplicationStartup.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/MainDemoWindow.o: ../../Source/MainDemoWindow.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling MainDemoWindow.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/AudioDemoLatencyPage.o: ../../Source/demos/AudioDemoLatencyPage.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling AudioDemoLatencyPage.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/AudioDemoPlaybackPage.o: ../../Source/demos/AudioDemoPlaybackPage.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling AudioDemoPlaybackPage.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/AudioDemoRecordPage.o: ../../Source/demos/AudioDemoRecordPage.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling AudioDemoRecordPage.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/AudioDemoSetupPage.o: ../../Source/demos/AudioDemoSetupPage.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling AudioDemoSetupPage.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/AudioDemoSynthPage.o: ../../Source/demos/AudioDemoSynthPage.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling AudioDemoSynthPage.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/AudioDemoTabComponent.o: ../../Source/demos/AudioDemoTabComponent.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling AudioDemoTabComponent.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/CameraDemo.o: ../../Source/demos/CameraDemo.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling CameraDemo.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/CodeEditorDemo.o: ../../Source/demos/CodeEditorDemo.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling CodeEditorDemo.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/DragAndDropDemo.o: ../../Source/demos/DragAndDropDemo.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling DragAndDropDemo.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/FontsAndTextDemo.o: ../../Source/demos/FontsAndTextDemo.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling FontsAndTextDemo.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/InterprocessCommsDemo.o: ../../Source/demos/InterprocessCommsDemo.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling InterprocessCommsDemo.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/OpenGLDemo.o: ../../Source/demos/OpenGLDemo.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling OpenGLDemo.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/QuickTimeDemo.o: ../../Source/demos/QuickTimeDemo.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling QuickTimeDemo.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/RenderingTestComponent.o: ../../Source/demos/RenderingTestComponent.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling RenderingTestComponent.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/TableDemo.o: ../../Source/demos/TableDemo.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling TableDemo.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/ThreadingDemo.o: ../../Source/demos/ThreadingDemo.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling ThreadingDemo.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/TreeViewDemo.o: ../../Source/demos/TreeViewDemo.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling TreeViewDemo.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/WebBrowserDemo.o: ../../Source/demos/WebBrowserDemo.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling WebBrowserDemo.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/WidgetsDemo.o: ../../Source/demos/WidgetsDemo.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling WidgetsDemo.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/BinaryData.o: ../../JuceLibraryCode/BinaryData.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling BinaryData.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/JuceLibraryCode1.o: ../../JuceLibraryCode/JuceLibraryCode1.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling JuceLibraryCode1.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/JuceLibraryCode2.o: ../../JuceLibraryCode/JuceLibraryCode2.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling JuceLibraryCode2.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/JuceLibraryCode3.o: ../../JuceLibraryCode/JuceLibraryCode3.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling JuceLibraryCode3.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/JuceLibraryCode4.o: ../../JuceLibraryCode/JuceLibraryCode4.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@echo "Compiling JuceLibraryCode4.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
-include $(OBJECTS:%.o=%.d)
|
||||
|
|
|
|||
1859
juce_amalgamated.cpp
1859
juce_amalgamated.cpp
File diff suppressed because it is too large
Load diff
1109
juce_amalgamated.h
1109
juce_amalgamated.h
File diff suppressed because it is too large
Load diff
|
|
@ -150,7 +150,7 @@ public:
|
|||
return false;
|
||||
|
||||
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 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()
|
||||
{
|
||||
|
|
@ -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()
|
||||
{
|
||||
return values.size();
|
||||
|
|
|
|||
|
|
@ -51,6 +51,9 @@ public:
|
|||
/** Destructor. */
|
||||
~NamedValueSet();
|
||||
|
||||
bool operator== (const NamedValueSet& other) const;
|
||||
bool operator!= (const NamedValueSet& other) const;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the total number of values that the set contains. */
|
||||
int size() const throw();
|
||||
|
|
@ -108,6 +111,7 @@ private:
|
|||
{
|
||||
NamedValue() throw();
|
||||
NamedValue (const Identifier& name, const var& value);
|
||||
bool operator== (const NamedValue& other) const throw();
|
||||
|
||||
Identifier name;
|
||||
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()
|
||||
: object (0)
|
||||
|
|
@ -546,16 +562,22 @@ ValueTree::~ValueTree()
|
|||
object->valueTreesWithListeners.removeValue (this);
|
||||
}
|
||||
|
||||
bool ValueTree::operator== (const ValueTree& other) const
|
||||
bool ValueTree::operator== (const ValueTree& other) const throw()
|
||||
{
|
||||
return object == other.object;
|
||||
}
|
||||
|
||||
bool ValueTree::operator!= (const ValueTree& other) const
|
||||
bool ValueTree::operator!= (const ValueTree& other) const throw()
|
||||
{
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void ValueTree::addChild (ValueTree child, int index, UndoManager* const undoManager)
|
||||
void ValueTree::addChild (const ValueTree& child, int index, UndoManager* const undoManager)
|
||||
{
|
||||
if (object != 0)
|
||||
object->addChild (child.object, index, undoManager);
|
||||
|
|
|
|||
|
|
@ -102,13 +102,21 @@ public:
|
|||
Note that this isn't a value comparison - two independently-created trees which
|
||||
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.
|
||||
Note that this isn't a value comparison - two independently-created trees which
|
||||
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.
|
||||
|
|
@ -233,7 +241,7 @@ public:
|
|||
If the undoManager parameter is non-null, its UndoManager::perform() method will be used,
|
||||
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.
|
||||
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 removeAllChildren (UndoManager*);
|
||||
void moveChild (int currentIndex, int newIndex, UndoManager*);
|
||||
bool isEquivalentTo (const SharedObject& other) const;
|
||||
XmlElement* createXml() const;
|
||||
|
||||
juce_UseDebuggingNewOperator
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
*/
|
||||
#define JUCE_MAJOR_VERSION 1
|
||||
#define JUCE_MINOR_VERSION 52
|
||||
#define JUCE_BUILDNUMBER 5
|
||||
#define JUCE_BUILDNUMBER 6
|
||||
|
||||
/** Current Juce version number.
|
||||
|
||||
|
|
|
|||
|
|
@ -877,8 +877,7 @@ void ListBox::setHeaderComponent (Component* const newHeaderComponent)
|
|||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -1338,8 +1338,9 @@ void TreeViewItem::repaintItem() const
|
|||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// 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();
|
||||
|
||||
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);
|
||||
|
||||
/** 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.
|
||||
|
||||
|
|
|
|||
|
|
@ -117,14 +117,14 @@ public:
|
|||
&& ((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();
|
||||
|
||||
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()
|
||||
|
|
|
|||
|
|
@ -281,7 +281,7 @@ public:
|
|||
|
||||
//==============================================================================
|
||||
/** 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
|
||||
of any areas of this window that need repainting.
|
||||
|
|
|
|||
|
|
@ -95,9 +95,7 @@ DocumentWindow::~DocumentWindow()
|
|||
//==============================================================================
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -177,12 +177,13 @@ public:
|
|||
x = endX;
|
||||
}
|
||||
|
||||
levelAccumulator >>= 8;
|
||||
|
||||
if (levelAccumulator > 0)
|
||||
{
|
||||
x >>= 8;
|
||||
jassert (x >= bounds.getX() && x < bounds.getRight());
|
||||
|
||||
levelAccumulator >>= 8;
|
||||
if (levelAccumulator >> 8)
|
||||
iterationCallback.handleEdgeTablePixelFull (x);
|
||||
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()
|
||||
{
|
||||
gradient = 0;
|
||||
|
|
@ -110,4 +120,10 @@ void FillType::setOpacity (const float newOpacity) throw()
|
|||
colour = colour.withAlpha (newOpacity);
|
||||
}
|
||||
|
||||
bool FillType::isInvisible() const throw()
|
||||
{
|
||||
return colour.isTransparent() || (gradient != 0 && gradient->isInvisible());
|
||||
}
|
||||
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -103,6 +103,12 @@ public:
|
|||
*/
|
||||
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.
|
||||
|
||||
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);
|
||||
|
||||
if (shapeToFill != 0)
|
||||
fillShapeWithoutClipping (image, shapeToFill, replaceContents);
|
||||
}
|
||||
|
||||
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
|
||||
Image::BitmapData destData (image, 0, 0, image.getWidth(), image.getHeight(), true);
|
||||
|
||||
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 (fillType.isGradient())
|
||||
{
|
||||
// If our translation doesn't involve any distortion, we can speed it up..
|
||||
g2.point1.applyTransform (transform);
|
||||
g2.point2.applyTransform (transform);
|
||||
transform = AffineTransform::identity;
|
||||
}
|
||||
jassert (! replaceContents); // that option is just for solid colours
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
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 "../../../io/files/juce_FileInputStream.h"
|
||||
|
||||
const Identifier Drawable::idProperty ("id");
|
||||
|
||||
//==============================================================================
|
||||
Drawable::RenderingContext::RenderingContext (Graphics& g_,
|
||||
|
|
@ -50,6 +49,7 @@ Drawable::RenderingContext::RenderingContext (Graphics& g_,
|
|||
|
||||
//==============================================================================
|
||||
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));
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -27,8 +27,10 @@
|
|||
#define __JUCE_DRAWABLE_JUCEHEADER__
|
||||
|
||||
#include "../contexts/juce_Graphics.h"
|
||||
#include "../geometry/juce_RelativeCoordinate.h"
|
||||
#include "../../../text/juce_XmlElement.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. */
|
||||
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
|
||||
|
||||
protected:
|
||||
static const Identifier idProperty;
|
||||
friend class DrawableComposite;
|
||||
DrawableComposite* parent;
|
||||
virtual void invalidatePoints() = 0;
|
||||
|
||||
private:
|
||||
String name;
|
||||
|
|
|
|||
|
|
@ -37,8 +37,21 @@ BEGIN_JUCE_NAMESPACE
|
|||
//==============================================================================
|
||||
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()
|
||||
|
|
@ -51,7 +64,9 @@ void DrawableComposite::insertDrawable (Drawable* drawable, const int index)
|
|||
if (drawable != 0)
|
||||
{
|
||||
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);
|
||||
drawable->parent = this;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -71,9 +86,9 @@ void DrawableComposite::bringToFront (const int index)
|
|||
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[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)
|
||||
{
|
||||
return AffineTransform::fromTargetPoints (controlPoints[0].getX(), controlPoints[0].getY(),
|
||||
controlPoints[1].getX(), controlPoints[1].getY(),
|
||||
controlPoints[2].getX(), controlPoints[2].getY());
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
|
|
@ -95,7 +169,7 @@ void DrawableComposite::render (const Drawable::RenderingContext& context) const
|
|||
if (context.opacity >= 1.0f || drawables.size() == 1)
|
||||
{
|
||||
Drawable::RenderingContext contextCopy (context);
|
||||
contextCopy.transform = getTransform().followedBy (context.transform);
|
||||
contextCopy.transform = calculateTransform().followedBy (context.transform);
|
||||
|
||||
for (int i = 0; i < drawables.size(); ++i)
|
||||
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
|
||||
{
|
||||
Rectangle<float> bounds;
|
||||
|
|
@ -133,12 +234,12 @@ const Rectangle<float> DrawableComposite::getUntransformedBounds() const
|
|||
|
||||
const Rectangle<float> DrawableComposite::getBounds() const
|
||||
{
|
||||
return getUntransformedBounds().transformed (getTransform());
|
||||
return getUntransformedBounds().transformed (calculateTransform());
|
||||
}
|
||||
|
||||
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)
|
||||
if (drawables.getUnchecked(i)->hitTest (x, y))
|
||||
|
|
@ -149,125 +250,282 @@ bool DrawableComposite::hitTest (float x, float y) 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)
|
||||
dc->drawables.add (drawables.getUnchecked(i)->createCopy());
|
||||
|
||||
return dc;
|
||||
drawables.getUnchecked(i)->invalidatePoints();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
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_)
|
||||
{
|
||||
static const Identifier topLeft ("topLeft");
|
||||
static const Identifier topRight ("topRight");
|
||||
static const Identifier bottomLeft ("bottomLeft");
|
||||
jassert (state.hasType (valueTreeType));
|
||||
}
|
||||
|
||||
static void stringToPoint (const String& coords, Point<float>& point)
|
||||
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
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawableComposite::ValueTreeWrapper::removeMarker (int index, UndoManager* undoManager)
|
||||
{
|
||||
return getMarkerList().removeChild (index, undoManager);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const Rectangle<float> DrawableComposite::refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider)
|
||||
{
|
||||
jassert (tree.hasType (valueTreeType));
|
||||
|
||||
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]
|
||||
|| controlPoints[1] != newControlPoint[1]
|
||||
|| controlPoints[2] != newControlPoint[2])
|
||||
{
|
||||
controlPointsChanged = true;
|
||||
redrawAll = true;
|
||||
damageRect = getUntransformedBounds();
|
||||
controlPoints[0] = newControlPoint[0];
|
||||
controlPoints[1] = newControlPoint[1];
|
||||
controlPoints[2] = newControlPoint[2];
|
||||
}
|
||||
|
||||
// Remove deleted markers...
|
||||
int i;
|
||||
for (i = drawables.size(); --i >= tree.getNumChildren();)
|
||||
for (i = markers.size(); --i >= controller.getNumMarkers();)
|
||||
{
|
||||
damageRect = damageRect.getUnion (drawables.getUnchecked(i)->getBounds());
|
||||
if (damageRect.isEmpty())
|
||||
damageRect = getUntransformedBounds();
|
||||
|
||||
removeMarker (i);
|
||||
}
|
||||
|
||||
// Update markers and add new ones..
|
||||
for (i = 0; i < controller.getNumMarkers(); ++i)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
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
|
||||
{
|
||||
damageRect = damageRect.getUnion (d->getBounds());
|
||||
d = createFromValueTree (childTree, imageProvider);
|
||||
d = createFromValueTree (newDrawable, imageProvider);
|
||||
d->parent = this;
|
||||
drawables.set (i, d);
|
||||
damageRect = damageRect.getUnion (d->getBounds());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
d = createFromValueTree (childTree, imageProvider);
|
||||
d = createFromValueTree (newDrawable, imageProvider);
|
||||
d->parent = this;
|
||||
drawables.set (i, d);
|
||||
damageRect = damageRect.getUnion (d->getBounds());
|
||||
}
|
||||
}
|
||||
|
||||
if (controlPointsChanged)
|
||||
if (redrawAll)
|
||||
damageRect = damageRect.getUnion (getUntransformedBounds());
|
||||
|
||||
return damageRect.transformed (getTransform());
|
||||
return damageRect.transformed (calculateTransform());
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
class JUCE_API DrawableComposite : public Drawable
|
||||
class JUCE_API DrawableComposite : public Drawable,
|
||||
public RelativeCoordinate::NamedCoordinateFinder
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a composite Drawable.
|
||||
*/
|
||||
/** Creates a composite Drawable. */
|
||||
DrawableComposite();
|
||||
|
||||
/** Creates a copy of a DrawableComposite. */
|
||||
DrawableComposite (const DrawableComposite& other);
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~DrawableComposite();
|
||||
|
||||
|
|
@ -122,27 +125,44 @@ public:
|
|||
@param targetPositionForX0Y1 the position that the local coordinate (0, 1) should be
|
||||
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
|
||||
coordinate space when rendering this object.
|
||||
@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
|
||||
coordinate space when rendering this object.
|
||||
@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
|
||||
coordinate space when rendering this object.
|
||||
@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 */
|
||||
|
|
@ -152,12 +172,10 @@ public:
|
|||
/** @internal */
|
||||
bool hitTest (float x, float y) const;
|
||||
/** @internal */
|
||||
int getNumControlPoints() const;
|
||||
/** @internal */
|
||||
const Point<float> getControlPoint (int index) const;
|
||||
/** @internal */
|
||||
Drawable* createCopy() const;
|
||||
/** @internal */
|
||||
void invalidatePoints();
|
||||
/** @internal */
|
||||
const Rectangle<float> refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider);
|
||||
/** @internal */
|
||||
const ValueTree createValueTree (ImageProvider* imageProvider) const;
|
||||
|
|
@ -165,18 +183,57 @@ public:
|
|||
static const Identifier valueTreeType;
|
||||
/** @internal */
|
||||
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
|
||||
|
||||
private:
|
||||
OwnedArray <Drawable> drawables;
|
||||
Point<float> controlPoints[3];
|
||||
RelativePoint controlPoints[3];
|
||||
OwnedArray <Marker> markers;
|
||||
|
||||
const Rectangle<float> getUntransformedBounds() const;
|
||||
const AffineTransform getTransform() const;
|
||||
const AffineTransform calculateTransform() const;
|
||||
|
||||
DrawableComposite (const DrawableComposite&);
|
||||
DrawableComposite& operator= (const DrawableComposite&);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@
|
|||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
|
||||
#include "juce_DrawableImage.h"
|
||||
#include "juce_DrawableComposite.h"
|
||||
#include "../imaging/juce_ImageCache.h"
|
||||
|
||||
|
||||
|
|
@ -39,47 +39,58 @@ DrawableImage::DrawableImage()
|
|||
opacity (1.0f),
|
||||
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 (const DrawableImage& other)
|
||||
: image (0),
|
||||
canDeleteImage (false),
|
||||
opacity (other.opacity),
|
||||
overlayColour (other.overlayColour)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DrawableImage::~DrawableImage()
|
||||
{
|
||||
clearImage();
|
||||
setImage (0, false);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void DrawableImage::clearImage()
|
||||
{
|
||||
if (canDeleteImage && image != 0)
|
||||
ImageCache::releaseOrDelete (image);
|
||||
|
||||
image = 0;
|
||||
}
|
||||
|
||||
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,
|
||||
const bool releaseWhenNotNeeded)
|
||||
{
|
||||
clearImage();
|
||||
if (canDeleteImage)
|
||||
ImageCache::releaseOrDelete (image);
|
||||
|
||||
image = imageToUse;
|
||||
canDeleteImage = releaseWhenNotNeeded;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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[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)
|
||||
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(),
|
||||
bl.getX(), bl.getY());
|
||||
}
|
||||
|
|
@ -120,7 +135,7 @@ void DrawableImage::render (const Drawable::RenderingContext& context) const
|
|||
{
|
||||
if (image != 0)
|
||||
{
|
||||
const AffineTransform t (getTransform().followedBy (context.transform));
|
||||
const AffineTransform t (calculateTransform().followedBy (context.transform));
|
||||
|
||||
if (opacity > 0.0f && ! overlayColour.isOpaque())
|
||||
{
|
||||
|
|
@ -141,7 +156,11 @@ const Rectangle<float> DrawableImage::getBounds() const
|
|||
if (image == 0)
|
||||
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 maxX = minX;
|
||||
float minY = bottomRight.getY();
|
||||
|
|
@ -149,10 +168,10 @@ const Rectangle<float> DrawableImage::getBounds() const
|
|||
|
||||
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);
|
||||
|
|
@ -163,7 +182,7 @@ bool DrawableImage::hitTest (float x, float y) const
|
|||
if (image == 0)
|
||||
return false;
|
||||
|
||||
getTransform().inverted().transformPoint (x, y);
|
||||
calculateTransform().inverted().transformPoint (x, y);
|
||||
|
||||
const int ix = roundToInt (x);
|
||||
const int iy = roundToInt (y);
|
||||
|
|
@ -177,81 +196,117 @@ bool DrawableImage::hitTest (float x, float y) const
|
|||
|
||||
Drawable* DrawableImage::createCopy() const
|
||||
{
|
||||
DrawableImage* const di = new DrawableImage();
|
||||
return new DrawableImage (*this);
|
||||
}
|
||||
|
||||
di->opacity = opacity;
|
||||
di->overlayColour = overlayColour;
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
di->controlPoints[i] = controlPoints[i];
|
||||
|
||||
if (image != 0)
|
||||
{
|
||||
if ((! canDeleteImage) || ! ImageCache::isImageInCache (image))
|
||||
{
|
||||
di->setImage (*image);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImageCache::incReferenceCount (image);
|
||||
di->setImage (image, true);
|
||||
}
|
||||
}
|
||||
|
||||
return di;
|
||||
void DrawableImage::invalidatePoints()
|
||||
{
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const Identifier DrawableImage::valueTreeType ("Image");
|
||||
|
||||
namespace DrawableImageHelpers
|
||||
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");
|
||||
|
||||
//==============================================================================
|
||||
DrawableImage::ValueTreeWrapper::ValueTreeWrapper (const ValueTree& state_)
|
||||
: ValueTreeWrapperBase (state_)
|
||||
{
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
static const var pointToString (const Point<float>& point)
|
||||
{
|
||||
return String (point.getX()) + ", " + String (point.getY());
|
||||
}
|
||||
jassert (state.hasType (valueTreeType));
|
||||
}
|
||||
|
||||
const var DrawableImage::ValueTreeWrapper::getImageIdentifier() const
|
||||
{
|
||||
return state [image];
|
||||
}
|
||||
|
||||
void DrawableImage::ValueTreeWrapper::setImageIdentifier (const var& newIdentifier, UndoManager* undoManager)
|
||||
{
|
||||
state.setProperty (image, newIdentifier, undoManager);
|
||||
}
|
||||
|
||||
float DrawableImage::ValueTreeWrapper::getOpacity() const
|
||||
{
|
||||
return (float) state.getProperty (opacity, 1.0);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
state.setProperty (bottomLeft, newPoint.toString(), undoManager);
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
const Rectangle<float> DrawableImage::refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider)
|
||||
{
|
||||
jassert (tree.hasType (valueTreeType));
|
||||
const ValueTreeWrapper controller (tree);
|
||||
setName (controller.getID());
|
||||
|
||||
setName (tree [idProperty]);
|
||||
|
||||
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;
|
||||
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!
|
||||
|
||||
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]);
|
||||
if (imageProvider != 0)
|
||||
newImage = imageProvider->getImageForIdentifier (imageIdentifier);
|
||||
|
||||
RelativePoint newControlPoint[3] = { controller.getTargetPositionForTopLeft(),
|
||||
controller.getTargetPositionForTopRight(),
|
||||
controller.getTargetPositionForBottomLeft() };
|
||||
|
||||
if (newOpacity != opacity || overlayColour != newOverlayColour || image != newImage
|
||||
|| controlPoints[0] != newControlPoint[0]
|
||||
|
|
@ -266,7 +321,10 @@ const Rectangle<float> DrawableImage::refreshFromValueTree (const ValueTree& tre
|
|||
|
||||
if (image != newImage)
|
||||
{
|
||||
ImageCache::release (image);
|
||||
if (canDeleteImage)
|
||||
ImageCache::releaseOrDelete (image);
|
||||
|
||||
canDeleteImage = true;
|
||||
image = newImage;
|
||||
}
|
||||
|
||||
|
|
@ -279,33 +337,25 @@ const Rectangle<float> DrawableImage::refreshFromValueTree (const ValueTree& tre
|
|||
|
||||
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)
|
||||
{
|
||||
jassert (imageProvider != 0); // if you're using images, you need to provide something that can load and save them!
|
||||
|
||||
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:
|
||||
//==============================================================================
|
||||
DrawableImage();
|
||||
DrawableImage (const DrawableImage& other);
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~DrawableImage();
|
||||
|
|
@ -59,7 +60,7 @@ public:
|
|||
with ImageCache and pass it in here with releaseWhenNotNeeded = true, then
|
||||
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,
|
||||
then the image will be deleted when this object no longer
|
||||
needs it - unless the image was created by the ImageCache,
|
||||
|
|
@ -70,9 +71,6 @@ public:
|
|||
/** Returns the current 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. */
|
||||
void setOpacity (float newOpacity);
|
||||
|
||||
|
|
@ -103,27 +101,27 @@ public:
|
|||
@param imageBottomLeftPosition the position that the image's bottom-left corner should be mapped to
|
||||
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
|
||||
coordinate space when rendering this object.
|
||||
@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
|
||||
coordinate space when rendering this object.
|
||||
@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
|
||||
coordinate space when rendering this object.
|
||||
@see setTransform
|
||||
*/
|
||||
const Point<float>& getTargetPositionForBottomLeft() const throw() { return controlPoints[2]; }
|
||||
const RelativePoint& getTargetPositionForBottomLeft() const throw() { return controlPoints[2]; }
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
|
|
@ -135,6 +133,8 @@ public:
|
|||
/** @internal */
|
||||
Drawable* createCopy() const;
|
||||
/** @internal */
|
||||
void invalidatePoints();
|
||||
/** @internal */
|
||||
const Rectangle<float> refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider);
|
||||
/** @internal */
|
||||
const ValueTree createValueTree (ImageProvider* imageProvider) const;
|
||||
|
|
@ -143,6 +143,35 @@ public:
|
|||
/** @internal */
|
||||
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
|
||||
|
||||
|
|
@ -151,11 +180,10 @@ private:
|
|||
bool canDeleteImage;
|
||||
float opacity;
|
||||
Colour overlayColour;
|
||||
Point<float> controlPoints[3];
|
||||
RelativePoint controlPoints[3];
|
||||
|
||||
const AffineTransform getTransform() const;
|
||||
const AffineTransform calculateTransform() const;
|
||||
|
||||
DrawableImage (const DrawableImage&);
|
||||
DrawableImage& operator= (const DrawableImage&);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
#include "juce_DrawablePath.h"
|
||||
#include "juce_DrawableComposite.h"
|
||||
#include "../../../io/streams/juce_MemoryOutputStream.h"
|
||||
|
||||
|
||||
|
|
@ -35,10 +36,25 @@ BEGIN_JUCE_NAMESPACE
|
|||
DrawablePath::DrawablePath()
|
||||
: mainFill (Colours::black),
|
||||
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()
|
||||
{
|
||||
}
|
||||
|
|
@ -47,7 +63,7 @@ DrawablePath::~DrawablePath()
|
|||
void DrawablePath::setPath (const Path& newPath)
|
||||
{
|
||||
path = newPath;
|
||||
updateOutline();
|
||||
strokeNeedsUpdating = true;
|
||||
}
|
||||
|
||||
void DrawablePath::setFill (const FillType& newFill)
|
||||
|
|
@ -63,7 +79,7 @@ void DrawablePath::setStrokeFill (const FillType& newFill)
|
|||
void DrawablePath::setStrokeType (const PathStrokeType& newStrokeType)
|
||||
{
|
||||
strokeType = newStrokeType;
|
||||
updateOutline();
|
||||
strokeNeedsUpdating = true;
|
||||
}
|
||||
|
||||
void DrawablePath::setStrokeThickness (const float newThickness)
|
||||
|
|
@ -71,6 +87,55 @@ void DrawablePath::setStrokeThickness (const float newThickness)
|
|||
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
|
||||
{
|
||||
|
|
@ -81,10 +146,10 @@ void DrawablePath::render (const Drawable::RenderingContext& context) const
|
|||
|
||||
f.transform = f.transform.followedBy (context.transform);
|
||||
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);
|
||||
if (f.isGradient())
|
||||
|
|
@ -92,162 +157,133 @@ void DrawablePath::render (const Drawable::RenderingContext& context) const
|
|||
|
||||
f.transform = f.transform.followedBy (context.transform);
|
||||
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
|
||||
{
|
||||
if (strokeType.getStrokeThickness() > 0.0f)
|
||||
return stroke.getBounds();
|
||||
if (isStrokeVisible())
|
||||
return getStrokePath().getBounds();
|
||||
else
|
||||
return path.getBounds();
|
||||
return getPath().getBounds();
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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");
|
||||
|
||||
namespace DrawablePathHelpers
|
||||
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");
|
||||
|
||||
//==============================================================================
|
||||
DrawablePath::ValueTreeWrapper::ValueTreeWrapper (const ValueTree& state_)
|
||||
: ValueTreeWrapperBase (state_)
|
||||
{
|
||||
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");
|
||||
jassert (state.hasType (valueTreeType));
|
||||
}
|
||||
|
||||
static bool updateFillType (const ValueTree& v, FillType& fillType)
|
||||
{
|
||||
const String type (v[type].toString());
|
||||
const FillType DrawablePath::ValueTreeWrapper::getMainFill() const
|
||||
{
|
||||
return readFillType (state.getChildWithName (fill));
|
||||
}
|
||||
|
||||
if (type.equalsIgnoreCase (solid))
|
||||
{
|
||||
const String colourString (v [colour].toString());
|
||||
const Colour newColour (colourString.isEmpty() ? (uint32) 0xff000000
|
||||
: (uint32) colourString.getHexValue32());
|
||||
void DrawablePath::ValueTreeWrapper::setMainFill (const FillType& newFill, UndoManager* undoManager)
|
||||
{
|
||||
replaceFillType (fill, newFill, undoManager);
|
||||
}
|
||||
|
||||
if (fillType.isColour() && fillType.colour == newColour)
|
||||
return false;
|
||||
const FillType DrawablePath::ValueTreeWrapper::getStrokeFill() const
|
||||
{
|
||||
return readFillType (state.getChildWithName (stroke));
|
||||
}
|
||||
|
||||
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];
|
||||
void DrawablePath::ValueTreeWrapper::setStrokeFill (const FillType& newFill, UndoManager* undoManager)
|
||||
{
|
||||
replaceFillType (stroke, newFill, undoManager);
|
||||
}
|
||||
|
||||
StringArray colourSteps;
|
||||
colourSteps.addTokens (v[colours].toString(), false);
|
||||
const PathStrokeType DrawablePath::ValueTreeWrapper::getStrokeType() const
|
||||
{
|
||||
const String jointStyleString (state [jointStyle].toString());
|
||||
const String capStyleString (state [capStyle].toString());
|
||||
|
||||
for (int i = 0; i < colourSteps.size() / 2; ++i)
|
||||
g.addColour (colourSteps[i * 2].getDoubleValue(),
|
||||
Colour ((uint32) colourSteps[i * 2 + 1].getHexValue32()));
|
||||
return PathStrokeType (state [strokeWidth],
|
||||
jointStyleString == "curved" ? PathStrokeType::curved
|
||||
: (jointStyleString == "bevel" ? PathStrokeType::beveled
|
||||
: PathStrokeType::mitered),
|
||||
capStyleString == "square" ? PathStrokeType::square
|
||||
: (capStyleString == "round" ? PathStrokeType::rounded
|
||||
: PathStrokeType::butt));
|
||||
}
|
||||
|
||||
if (fillType.isGradient() && *fillType.gradient == g)
|
||||
return false;
|
||||
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);
|
||||
}
|
||||
|
||||
fillType.setGradient (g);
|
||||
return true;
|
||||
}
|
||||
void DrawablePath::ValueTreeWrapper::getPath (RelativePointPath& p) const
|
||||
{
|
||||
RelativePointPath newPath (state [path]);
|
||||
p.swapWith (newPath);
|
||||
}
|
||||
|
||||
jassertfalse;
|
||||
return false;
|
||||
}
|
||||
|
||||
static ValueTree createFillType (const Identifier& tagName, const FillType& fillType)
|
||||
{
|
||||
ValueTree v (tagName);
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
jassert (tree.hasType (valueTreeType));
|
||||
|
||||
Rectangle<float> damageRect;
|
||||
setName (tree [idProperty]);
|
||||
ValueTreeWrapper v (tree);
|
||||
setName (v.getID());
|
||||
|
||||
bool needsRedraw = DrawablePathHelpers::updateFillType (tree.getChildWithName (DrawablePathHelpers::fill), mainFill);
|
||||
needsRedraw = DrawablePathHelpers::updateFillType (tree.getChildWithName (DrawablePathHelpers::stroke), strokeFill) || needsRedraw;
|
||||
bool needsRedraw = false;
|
||||
const FillType newFill (v.getMainFill());
|
||||
|
||||
const String jointStyle (tree [DrawablePathHelpers::jointStyle].toString());
|
||||
const String endStyle (tree [DrawablePathHelpers::capStyle].toString());
|
||||
if (mainFill != newFill)
|
||||
{
|
||||
needsRedraw = true;
|
||||
mainFill = newFill;
|
||||
}
|
||||
|
||||
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));
|
||||
const FillType newStrokeFill (v.getStrokeFill());
|
||||
|
||||
if (strokeFill != newStrokeFill)
|
||||
{
|
||||
needsRedraw = true;
|
||||
strokeFill = newStrokeFill;
|
||||
}
|
||||
|
||||
const PathStrokeType newStroke (v.getStrokeType());
|
||||
|
||||
ScopedPointer<RelativePointPath> newRelativePath (new RelativePointPath());
|
||||
v.getPath (*newRelativePath);
|
||||
|
||||
Path newPath;
|
||||
newPath.restoreFromString (tree [DrawablePathHelpers::path]);
|
||||
newRelativePath->createPath (newPath, parent);
|
||||
|
||||
if (! newRelativePath->containsAnyDynamicPoints())
|
||||
newRelativePath = 0;
|
||||
|
||||
if (strokeType != newStroke || path != newPath)
|
||||
{
|
||||
|
|
@ -257,6 +293,8 @@ const Rectangle<float> DrawablePath::refreshFromValueTree (const ValueTree& tree
|
|||
needsRedraw = true;
|
||||
}
|
||||
|
||||
relativePath = newRelativePath.release();
|
||||
|
||||
if (needsRedraw)
|
||||
damageRect = damageRect.getUnion (getBounds());
|
||||
|
||||
|
|
@ -265,22 +303,20 @@ const Rectangle<float> DrawablePath::refreshFromValueTree (const ValueTree& tree
|
|||
|
||||
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);
|
||||
if (relativePath != 0)
|
||||
v.setPath (relativePath->toString(), 0);
|
||||
else
|
||||
v.setPath (path.toString(), 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);
|
||||
|
||||
return v;
|
||||
return tree;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -40,9 +40,9 @@ class JUCE_API DrawablePath : public Drawable
|
|||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a DrawablePath.
|
||||
*/
|
||||
/** Creates a DrawablePath. */
|
||||
DrawablePath();
|
||||
DrawablePath (const DrawablePath& other);
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~DrawablePath();
|
||||
|
|
@ -54,9 +54,6 @@ public:
|
|||
*/
|
||||
void setPath (const Path& newPath);
|
||||
|
||||
/** Returns the current path. */
|
||||
const Path& getPath() const throw() { return 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
|
||||
|
|
@ -97,6 +94,13 @@ public:
|
|||
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 */
|
||||
void render (const Drawable::RenderingContext& context) const;
|
||||
|
|
@ -107,6 +111,8 @@ public:
|
|||
/** @internal */
|
||||
Drawable* createCopy() const;
|
||||
/** @internal */
|
||||
void invalidatePoints();
|
||||
/** @internal */
|
||||
const Rectangle<float> refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider);
|
||||
/** @internal */
|
||||
const ValueTree createValueTree (ImageProvider* imageProvider) const;
|
||||
|
|
@ -115,17 +121,43 @@ public:
|
|||
/** @internal */
|
||||
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
|
||||
|
||||
private:
|
||||
Path path, stroke;
|
||||
FillType mainFill, strokeFill;
|
||||
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&);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,12 @@ DrawableText::DrawableText()
|
|||
{
|
||||
}
|
||||
|
||||
DrawableText::DrawableText (const DrawableText& other)
|
||||
: text (other.text),
|
||||
colour (other.colour)
|
||||
{
|
||||
}
|
||||
|
||||
DrawableText::~DrawableText()
|
||||
{
|
||||
}
|
||||
|
|
@ -76,21 +82,28 @@ bool DrawableText::hitTest (float x, float y) const
|
|||
|
||||
Drawable* DrawableText::createCopy() const
|
||||
{
|
||||
DrawableText* const dt = new DrawableText();
|
||||
return new DrawableText (*this);
|
||||
}
|
||||
|
||||
dt->text = text;
|
||||
dt->colour = colour;
|
||||
|
||||
return dt;
|
||||
void DrawableText::invalidatePoints()
|
||||
{
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
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)
|
||||
{
|
||||
jassert (tree.hasType (valueTreeType));
|
||||
setName (tree [idProperty]);
|
||||
ValueTreeWrapper v (tree);
|
||||
setName (v.getID());
|
||||
|
||||
jassertfalse; // xxx not finished!
|
||||
|
||||
|
|
@ -99,13 +112,14 @@ const Rectangle<float> DrawableText::refreshFromValueTree (const ValueTree& tree
|
|||
|
||||
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!
|
||||
return v;
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ public:
|
|||
//==============================================================================
|
||||
/** Creates a DrawableText object. */
|
||||
DrawableText();
|
||||
DrawableText (const DrawableText& other);
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~DrawableText();
|
||||
|
|
@ -78,6 +79,8 @@ public:
|
|||
/** @internal */
|
||||
Drawable* createCopy() const;
|
||||
/** @internal */
|
||||
void invalidatePoints();
|
||||
/** @internal */
|
||||
const Rectangle<float> refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider);
|
||||
/** @internal */
|
||||
const ValueTree createValueTree (ImageProvider* imageProvider) const;
|
||||
|
|
@ -86,6 +89,19 @@ public:
|
|||
/** @internal */
|
||||
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
|
||||
|
||||
|
|
@ -93,7 +109,6 @@ private:
|
|||
GlyphArrangement text;
|
||||
Colour colour;
|
||||
|
||||
DrawableText (const DrawableText&);
|
||||
DrawableText& operator= (const DrawableText&);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -74,12 +74,7 @@ namespace PathHelpers
|
|||
while (*t != 0 && ! CharacterFunctions::isWhitespace (*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;
|
||||
float values [6];
|
||||
|
||||
while (*t != 0)
|
||||
for (;;)
|
||||
{
|
||||
const String token (PathHelpers::nextToken (t));
|
||||
const juce_wchar firstChar = token[0];
|
||||
int startNum = 0;
|
||||
|
||||
if (firstChar == 0)
|
||||
break;
|
||||
|
||||
if (firstChar == 'm' || firstChar == 'l')
|
||||
{
|
||||
marker = firstChar;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
#include "juce_RelativeCoordinate.h"
|
||||
#include "../../../io/streams/juce_MemoryOutputStream.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
namespace RelativeCoordinateHelpers
|
||||
|
|
@ -61,9 +63,10 @@ namespace RelativeCoordinateHelpers
|
|||
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;
|
||||
}
|
||||
|
||||
static void skipComma (const String& s, int& i)
|
||||
{
|
||||
skipWhitespace (s, i);
|
||||
if (s[i] == ',')
|
||||
++i;
|
||||
}
|
||||
|
||||
static const String readAnchorName (const String& s, int& i)
|
||||
{
|
||||
skipWhitespace (s, i);
|
||||
|
|
@ -126,10 +136,89 @@ namespace RelativeCoordinateHelpers
|
|||
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)
|
||||
{
|
||||
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());
|
||||
}
|
||||
|
||||
RelativeCoordinate::RelativeCoordinate (const String& s, const bool isHorizontal)
|
||||
: value (0)
|
||||
{
|
||||
int i = 0;
|
||||
*this = RelativeCoordinateHelpers::readNextCoordinate (s, i, isHorizontal);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
|
|
@ -186,7 +292,7 @@ const RelativeCoordinate RelativeCoordinate::getAnchorCoordinate2() const
|
|||
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))
|
||||
return 0.0;
|
||||
|
|
@ -194,7 +300,7 @@ double RelativeCoordinate::resolveAnchor (const String& anchorName, const NamedC
|
|||
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)
|
||||
{
|
||||
|
|
@ -208,7 +314,7 @@ double RelativeCoordinate::resolve (const NamedCoordinateFinder& nameFinder, int
|
|||
: pos1 + value;
|
||||
}
|
||||
|
||||
double RelativeCoordinate::resolve (const NamedCoordinateFinder& nameFinder) const
|
||||
double RelativeCoordinate::resolve (const NamedCoordinateFinder* nameFinder) const
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -220,7 +326,7 @@ double RelativeCoordinate::resolve (const NamedCoordinateFinder& nameFinder) con
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
bool RelativeCoordinate::isRecursive (const NamedCoordinateFinder& nameFinder) const
|
||||
bool RelativeCoordinate::isRecursive (const NamedCoordinateFinder* nameFinder) const
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -234,7 +340,7 @@ bool RelativeCoordinate::isRecursive (const NamedCoordinateFinder& nameFinder) c
|
|||
return false;
|
||||
}
|
||||
|
||||
void RelativeCoordinate::moveToAbsolute (double newPos, const NamedCoordinateFinder& nameFinder)
|
||||
void RelativeCoordinate::moveToAbsolute (double newPos, const NamedCoordinateFinder* nameFinder)
|
||||
{
|
||||
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);
|
||||
|
||||
|
|
@ -267,8 +373,7 @@ void RelativeCoordinate::toggleProportionality (const NamedCoordinateFinder& nam
|
|||
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;
|
||||
|
||||
|
|
@ -281,65 +386,12 @@ bool RelativeCoordinate::references (const String& coordName, const NamedCoordin
|
|||
|| (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
|
||||
{
|
||||
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_."));
|
||||
|
||||
|
|
@ -392,7 +444,7 @@ void RelativeCoordinate::changeAnchor1 (const String& newAnchorName, const Named
|
|||
moveToAbsolute (oldValue, nameFinder);
|
||||
}
|
||||
|
||||
void RelativeCoordinate::changeAnchor2 (const String& newAnchorName, const NamedCoordinateFinder& nameFinder)
|
||||
void RelativeCoordinate::changeAnchor2 (const String& newAnchorName, const NamedCoordinateFinder* nameFinder)
|
||||
{
|
||||
jassert (isProportional());
|
||||
jassert (newAnchorName.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_."));
|
||||
|
|
@ -402,7 +454,7 @@ void RelativeCoordinate::changeAnchor2 (const String& newAnchorName, const Named
|
|||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
const Point<float> RelativePoint::resolve (const RelativeCoordinate::NamedCoordinateFinder& nameFinder) const
|
||||
RelativePoint::RelativePoint (const String& s)
|
||||
{
|
||||
int i = 0;
|
||||
x = RelativeCoordinateHelpers::readNextCoordinate (s, i, true);
|
||||
RelativeCoordinateHelpers::skipComma (s, i);
|
||||
y = RelativeCoordinateHelpers::readNextCoordinate (s, i, false);
|
||||
}
|
||||
|
||||
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),
|
||||
(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);
|
||||
y.moveToAbsolute (newPos.getY(), nameFinder);
|
||||
|
|
@ -464,12 +531,17 @@ const String RelativePoint::toString() const
|
|||
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);
|
||||
y.renameAnchorIfUsed (oldName, newName, nameFinder);
|
||||
}
|
||||
|
||||
bool RelativePoint::isDynamic() const
|
||||
{
|
||||
return x.isDynamic() || y.isDynamic();
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
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);
|
||||
|
||||
left = RelativeCoordinate (tokens [0], true);
|
||||
top = RelativeCoordinate (tokens [1], false);
|
||||
right = RelativeCoordinate (tokens [2], true);
|
||||
bottom = RelativeCoordinate (tokens [3], false);
|
||||
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);
|
||||
}
|
||||
|
||||
const Rectangle<float> RelativeRectangle::resolve (const RelativeCoordinate::NamedCoordinateFinder& nameFinder) const
|
||||
bool RelativeRectangle::operator== (const RelativeRectangle& other) const throw()
|
||||
{
|
||||
return left == other.left && top == other.top && right == other.right && bottom == other.bottom;
|
||||
}
|
||||
|
||||
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 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));
|
||||
}
|
||||
|
||||
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);
|
||||
right.moveToAbsolute (newPos.getRight(), nameFinder);
|
||||
|
|
@ -519,7 +602,7 @@ const String RelativeRectangle::toString() const
|
|||
}
|
||||
|
||||
void RelativeRectangle::renameAnchorIfUsed (const String& oldName, const String& newName,
|
||||
const RelativeCoordinate::NamedCoordinateFinder& nameFinder)
|
||||
const RelativeCoordinate::NamedCoordinateFinder* nameFinder)
|
||||
{
|
||||
left.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
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@
|
|||
#ifndef __JUCE_RELATIVECOORDINATE_JUCEHEADER__
|
||||
#define __JUCE_RELATIVECOORDINATE_JUCEHEADER__
|
||||
|
||||
#include "juce_Path.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
|
||||
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
|
||||
"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 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. */
|
||||
~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.
|
||||
|
|
@ -145,15 +150,18 @@ public:
|
|||
You'll need to provide a suitable NamedCoordinateFinder for looking up any coordinates that may
|
||||
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.
|
||||
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. */
|
||||
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.
|
||||
|
|
@ -162,7 +170,7 @@ public:
|
|||
or relative position to whatever value is necessary to make its resultant position
|
||||
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.
|
||||
@see toggleProportionality
|
||||
|
|
@ -173,7 +181,7 @@ public:
|
|||
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.
|
||||
*/
|
||||
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.
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
|
|
@ -227,7 +235,7 @@ public:
|
|||
instead.
|
||||
*/
|
||||
void renameAnchorIfUsed (const String& oldName, const String& newName,
|
||||
const NamedCoordinateFinder& nameFinder);
|
||||
const NamedCoordinateFinder* nameFinder);
|
||||
|
||||
//==============================================================================
|
||||
/** Returns a string which represents this coordinate.
|
||||
|
|
@ -261,8 +269,8 @@ private:
|
|||
String anchor1, anchor2;
|
||||
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. */
|
||||
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.
|
||||
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.
|
||||
@see toString
|
||||
*/
|
||||
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.
|
||||
|
||||
You'll need to provide a suitable NamedCoordinateFinder for looking up any coordinates that may
|
||||
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.
|
||||
|
||||
|
|
@ -301,7 +315,7 @@ public:
|
|||
or relative positions to whatever values are necessary to make the resultant position
|
||||
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.
|
||||
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.
|
||||
*/
|
||||
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...
|
||||
RelativeCoordinate x, y;
|
||||
|
|
@ -347,13 +364,16 @@ public:
|
|||
*/
|
||||
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.
|
||||
|
||||
You'll need to provide a suitable NamedCoordinateFinder for looking up any coordinates that may
|
||||
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.
|
||||
|
||||
|
|
@ -361,7 +381,7 @@ public:
|
|||
or relative positions to whatever values are necessary to make the resultant position
|
||||
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.
|
||||
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.
|
||||
*/
|
||||
void renameAnchorIfUsed (const String& oldName, const String& newName,
|
||||
const RelativeCoordinate::NamedCoordinateFinder& nameFinder);
|
||||
const RelativeCoordinate::NamedCoordinateFinder* nameFinder);
|
||||
|
||||
// The actual rectangle coords...
|
||||
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__
|
||||
|
|
|
|||
|
|
@ -131,6 +131,9 @@ void ImageCache::releaseOrDelete (Image* const imageToRelease)
|
|||
|
||||
bool ImageCache::isImageInCache (Image* const imageToLookFor)
|
||||
{
|
||||
if (imageToLookFor == 0)
|
||||
return false;
|
||||
|
||||
if (instance != 0)
|
||||
{
|
||||
const ScopedLock sl (instance->lock);
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ DirectoryIterator::DirectoryIterator (const File& directory,
|
|||
bool isRecursive_,
|
||||
const String& wildCard_,
|
||||
const int whatToLookFor_)
|
||||
: fileFinder (directory, isRecursive ? "*" : wildCard_),
|
||||
: fileFinder (directory, isRecursive_ ? "*" : wildCard_),
|
||||
wildCard (wildCard_),
|
||||
path (File::addTrailingSeparator (directory.getFullPathName())),
|
||||
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()
|
||||
|
|
@ -1526,8 +1520,8 @@ public:
|
|||
&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)
|
||||
{
|
||||
|
|
@ -1537,8 +1531,8 @@ public:
|
|||
|
||||
XNextEvent (display, (XEvent*) &nextEvent);
|
||||
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;
|
||||
|
|
@ -1838,12 +1832,12 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
void repaint (int x, int y, int w, int h)
|
||||
void repaint (const Rectangle<int>& area)
|
||||
{
|
||||
if (! isTimerRunning())
|
||||
startTimer (repaintTimerPeriod);
|
||||
|
||||
regionsNeedingRepaint.add (x, y, w, h);
|
||||
regionsNeedingRepaint.add (area);
|
||||
}
|
||||
|
||||
void performAnyPendingRepaintsNow()
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ public:
|
|||
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();
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -849,19 +849,20 @@ public:
|
|||
void messageCallback()
|
||||
{
|
||||
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())
|
||||
{
|
||||
(new AsyncRepaintMessage (this, Rectangle<int> (x, y, w, h)))->post();
|
||||
(new AsyncRepaintMessage (this, area))->post();
|
||||
}
|
||||
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 repaint (int x, int y, int w, int h);
|
||||
void repaint (const Rectangle<int>& area);
|
||||
void performAnyPendingRepaintsNow();
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -1631,20 +1631,20 @@ public:
|
|||
void messageCallback()
|
||||
{
|
||||
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)
|
||||
{
|
||||
(new AsyncRepaintMessage (this, Rectangle<int> (x, y, w, h)))->post();
|
||||
(new AsyncRepaintMessage (this, area))->post();
|
||||
}
|
||||
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);
|
||||
isStarted = false;
|
||||
isOpen_ = false;
|
||||
close();
|
||||
|
||||
const String errorCopy (error);
|
||||
close(); // (this resets the error string)
|
||||
error = errorCopy;
|
||||
}
|
||||
|
||||
needToReset = false;
|
||||
|
|
|
|||
|
|
@ -288,8 +288,7 @@ public:
|
|||
|
||||
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()
|
||||
|
|
|
|||
|
|
@ -685,7 +685,7 @@ public:
|
|||
int getInputLatencyInSamples() { return latencyIn; }
|
||||
const BigInteger getActiveOutputChannels() const { return outputDevice != 0 ? outputDevice->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,
|
||||
|
|
|
|||
|
|
@ -705,9 +705,9 @@ public:
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1055,9 +1055,7 @@ static int indexOfMatch (const juce_wchar* const wildcard,
|
|||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
|
@ -1093,9 +1091,7 @@ bool String::matchesWildcard (const String& wildcard, const bool ignoreCase) con
|
|||
else
|
||||
{
|
||||
return wc == '*' && (wildcard [i + 1] == 0
|
||||
|| indexOfMatch (wildcard.text + i + 1,
|
||||
text + i,
|
||||
ignoreCase) >= 0);
|
||||
|| indexOfMatch (wildcard.text + i + 1, text + i, ignoreCase) >= 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue